11316Smax.romanov@nginx.com/* 21316Smax.romanov@nginx.com * Copyright (C) Max Romanov 31316Smax.romanov@nginx.com * Copyright (C) NGINX, Inc. 41316Smax.romanov@nginx.com */ 51316Smax.romanov@nginx.com 61316Smax.romanov@nginx.compackage unit 71316Smax.romanov@nginx.com 81316Smax.romanov@nginx.com/* 91316Smax.romanov@nginx.com#include "nxt_cgo_lib.h" 101316Smax.romanov@nginx.com*/ 111316Smax.romanov@nginx.comimport "C" 121316Smax.romanov@nginx.com 131316Smax.romanov@nginx.comimport ( 141713Smax.romanov@nginx.com "io" 151316Smax.romanov@nginx.com "net" 161316Smax.romanov@nginx.com "os" 171316Smax.romanov@nginx.com "sync" 181316Smax.romanov@nginx.com "unsafe" 191316Smax.romanov@nginx.com) 201316Smax.romanov@nginx.com 211316Smax.romanov@nginx.comtype port_key struct { 221316Smax.romanov@nginx.com pid int 231316Smax.romanov@nginx.com id int 241316Smax.romanov@nginx.com} 251316Smax.romanov@nginx.com 261316Smax.romanov@nginx.comtype port struct { 271316Smax.romanov@nginx.com key port_key 281316Smax.romanov@nginx.com rcv *net.UnixConn 291316Smax.romanov@nginx.com snd *net.UnixConn 301316Smax.romanov@nginx.com} 311316Smax.romanov@nginx.com 321316Smax.romanov@nginx.comtype port_registry struct { 331316Smax.romanov@nginx.com sync.RWMutex 341316Smax.romanov@nginx.com m map[port_key]*port 351316Smax.romanov@nginx.com} 361316Smax.romanov@nginx.com 371316Smax.romanov@nginx.comvar port_registry_ port_registry 381316Smax.romanov@nginx.com 391316Smax.romanov@nginx.comfunc find_port(key port_key) *port { 401316Smax.romanov@nginx.com port_registry_.RLock() 411316Smax.romanov@nginx.com res := port_registry_.m[key] 421316Smax.romanov@nginx.com port_registry_.RUnlock() 431316Smax.romanov@nginx.com 441316Smax.romanov@nginx.com return res 451316Smax.romanov@nginx.com} 461316Smax.romanov@nginx.com 471316Smax.romanov@nginx.comfunc add_port(p *port) { 481316Smax.romanov@nginx.com 491316Smax.romanov@nginx.com port_registry_.Lock() 501316Smax.romanov@nginx.com if port_registry_.m == nil { 511316Smax.romanov@nginx.com port_registry_.m = make(map[port_key]*port) 521316Smax.romanov@nginx.com } 531316Smax.romanov@nginx.com 541452Smax.romanov@nginx.com old := port_registry_.m[p.key] 551452Smax.romanov@nginx.com 561452Smax.romanov@nginx.com if old == nil { 571452Smax.romanov@nginx.com port_registry_.m[p.key] = p 581452Smax.romanov@nginx.com } 591316Smax.romanov@nginx.com 601316Smax.romanov@nginx.com port_registry_.Unlock() 611316Smax.romanov@nginx.com} 621316Smax.romanov@nginx.com 631316Smax.romanov@nginx.comfunc (p *port) Close() { 641316Smax.romanov@nginx.com if p.rcv != nil { 651316Smax.romanov@nginx.com p.rcv.Close() 661316Smax.romanov@nginx.com } 671316Smax.romanov@nginx.com 681316Smax.romanov@nginx.com if p.snd != nil { 691316Smax.romanov@nginx.com p.snd.Close() 701316Smax.romanov@nginx.com } 711316Smax.romanov@nginx.com} 721316Smax.romanov@nginx.com 731316Smax.romanov@nginx.comfunc getUnixConn(fd int) *net.UnixConn { 741316Smax.romanov@nginx.com if fd < 0 { 751316Smax.romanov@nginx.com return nil 761316Smax.romanov@nginx.com } 771316Smax.romanov@nginx.com 781316Smax.romanov@nginx.com f := os.NewFile(uintptr(fd), "sock") 791316Smax.romanov@nginx.com defer f.Close() 801316Smax.romanov@nginx.com 811316Smax.romanov@nginx.com c, err := net.FileConn(f) 821316Smax.romanov@nginx.com if err != nil { 831713Smax.romanov@nginx.com nxt_go_alert("FileConn error %s", err) 841316Smax.romanov@nginx.com return nil 851316Smax.romanov@nginx.com } 861316Smax.romanov@nginx.com 871316Smax.romanov@nginx.com uc, ok := c.(*net.UnixConn) 881316Smax.romanov@nginx.com if !ok { 891713Smax.romanov@nginx.com nxt_go_alert("Not a Unix-domain socket %d", fd) 901316Smax.romanov@nginx.com return nil 911316Smax.romanov@nginx.com } 921316Smax.romanov@nginx.com 931316Smax.romanov@nginx.com return uc 941316Smax.romanov@nginx.com} 951316Smax.romanov@nginx.com 961316Smax.romanov@nginx.com//export nxt_go_add_port 971713Smax.romanov@nginx.comfunc nxt_go_add_port(ctx *C.nxt_unit_ctx_t, p *C.nxt_unit_port_t) C.int { 981713Smax.romanov@nginx.com 991713Smax.romanov@nginx.com new_port := &port{ 1001316Smax.romanov@nginx.com key: port_key{ 1011713Smax.romanov@nginx.com pid: int(p.id.pid), 1021713Smax.romanov@nginx.com id: int(p.id.id), 1031316Smax.romanov@nginx.com }, 1041713Smax.romanov@nginx.com rcv: getUnixConn(int(p.in_fd)), 1051713Smax.romanov@nginx.com snd: getUnixConn(int(p.out_fd)), 1061316Smax.romanov@nginx.com } 1071316Smax.romanov@nginx.com 1081713Smax.romanov@nginx.com add_port(new_port) 1091547Smax.romanov@nginx.com 1101713Smax.romanov@nginx.com p.in_fd = -1 1111713Smax.romanov@nginx.com p.out_fd = -1 1121713Smax.romanov@nginx.com 1131993Smax.romanov@nginx.com return C.NXT_UNIT_OK 1141993Smax.romanov@nginx.com} 1151993Smax.romanov@nginx.com 1161993Smax.romanov@nginx.com//export nxt_go_ready 1171993Smax.romanov@nginx.comfunc nxt_go_ready(ctx *C.nxt_unit_ctx_t) C.int { 1181993Smax.romanov@nginx.com go func(ctx *C.nxt_unit_ctx_t) { 1191993Smax.romanov@nginx.com C.nxt_unit_run_shared(ctx) 1201993Smax.romanov@nginx.com }(ctx) 1211713Smax.romanov@nginx.com 1221713Smax.romanov@nginx.com return C.NXT_UNIT_OK 1231316Smax.romanov@nginx.com} 1241316Smax.romanov@nginx.com 1251316Smax.romanov@nginx.com//export nxt_go_remove_port 1261980Smax.romanov@nginx.comfunc nxt_go_remove_port(unit *C.nxt_unit_t, ctx *C.nxt_unit_ctx_t, 1271980Smax.romanov@nginx.com p *C.nxt_unit_port_t) { 1281713Smax.romanov@nginx.com 1291316Smax.romanov@nginx.com key := port_key{ 1301713Smax.romanov@nginx.com pid: int(p.id.pid), 1311713Smax.romanov@nginx.com id: int(p.id.id), 1321316Smax.romanov@nginx.com } 1331316Smax.romanov@nginx.com 1341316Smax.romanov@nginx.com port_registry_.Lock() 1351316Smax.romanov@nginx.com if port_registry_.m != nil { 1361316Smax.romanov@nginx.com delete(port_registry_.m, key) 1371316Smax.romanov@nginx.com } 1381316Smax.romanov@nginx.com 1391316Smax.romanov@nginx.com port_registry_.Unlock() 1401316Smax.romanov@nginx.com} 1411316Smax.romanov@nginx.com 1421316Smax.romanov@nginx.com//export nxt_go_port_send 1431316Smax.romanov@nginx.comfunc nxt_go_port_send(pid C.int, id C.int, buf unsafe.Pointer, buf_size C.int, 1441316Smax.romanov@nginx.com oob unsafe.Pointer, oob_size C.int) C.ssize_t { 1451316Smax.romanov@nginx.com 1461316Smax.romanov@nginx.com key := port_key{ 1471316Smax.romanov@nginx.com pid: int(pid), 1481316Smax.romanov@nginx.com id: int(id), 1491316Smax.romanov@nginx.com } 1501316Smax.romanov@nginx.com 1511316Smax.romanov@nginx.com p := find_port(key) 1521316Smax.romanov@nginx.com 1531316Smax.romanov@nginx.com if p == nil { 1541713Smax.romanov@nginx.com nxt_go_alert("port %d:%d not found", pid, id) 1551316Smax.romanov@nginx.com return 0 1561316Smax.romanov@nginx.com } 1571316Smax.romanov@nginx.com 1581316Smax.romanov@nginx.com n, oobn, err := p.snd.WriteMsgUnix(GoBytes(buf, buf_size), 1591316Smax.romanov@nginx.com GoBytes(oob, oob_size), nil) 1601316Smax.romanov@nginx.com 1611316Smax.romanov@nginx.com if err != nil { 1621316Smax.romanov@nginx.com nxt_go_warn("write result %d (%d), %s", n, oobn, err) 1631438Smax.romanov@nginx.com 1641438Smax.romanov@nginx.com n = -1 1651316Smax.romanov@nginx.com } 1661316Smax.romanov@nginx.com 1671316Smax.romanov@nginx.com return C.ssize_t(n) 1681316Smax.romanov@nginx.com} 1691316Smax.romanov@nginx.com 1701316Smax.romanov@nginx.com//export nxt_go_port_recv 1711316Smax.romanov@nginx.comfunc nxt_go_port_recv(pid C.int, id C.int, buf unsafe.Pointer, buf_size C.int, 172*1996St.nateldemoura@f5.com oob unsafe.Pointer, oob_size *C.size_t) C.ssize_t { 1731316Smax.romanov@nginx.com 1741316Smax.romanov@nginx.com key := port_key{ 1751316Smax.romanov@nginx.com pid: int(pid), 1761316Smax.romanov@nginx.com id: int(id), 1771316Smax.romanov@nginx.com } 1781316Smax.romanov@nginx.com 1791316Smax.romanov@nginx.com p := find_port(key) 1801316Smax.romanov@nginx.com 1811316Smax.romanov@nginx.com if p == nil { 1821713Smax.romanov@nginx.com nxt_go_alert("port %d:%d not found", pid, id) 1831316Smax.romanov@nginx.com return 0 1841316Smax.romanov@nginx.com } 1851316Smax.romanov@nginx.com 1861316Smax.romanov@nginx.com n, oobn, _, _, err := p.rcv.ReadMsgUnix(GoBytes(buf, buf_size), 187*1996St.nateldemoura@f5.com GoBytes(oob, C.int(*oob_size))) 1881316Smax.romanov@nginx.com 1891316Smax.romanov@nginx.com if err != nil { 1901713Smax.romanov@nginx.com if nerr, ok := err.(*net.OpError); ok { 1911713Smax.romanov@nginx.com if nerr.Err == io.EOF { 1921713Smax.romanov@nginx.com return 0 1931713Smax.romanov@nginx.com } 1941713Smax.romanov@nginx.com } 1951713Smax.romanov@nginx.com 1961316Smax.romanov@nginx.com nxt_go_warn("read result %d (%d), %s", n, oobn, err) 1971438Smax.romanov@nginx.com 1981438Smax.romanov@nginx.com n = -1 199*1996St.nateldemoura@f5.com 200*1996St.nateldemoura@f5.com } else { 201*1996St.nateldemoura@f5.com *oob_size = C.size_t(oobn) 2021316Smax.romanov@nginx.com } 2031316Smax.romanov@nginx.com 2041316Smax.romanov@nginx.com return C.ssize_t(n) 2051316Smax.romanov@nginx.com} 206