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 ( 14*1713Smax.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 { 83*1713Smax.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 { 89*1713Smax.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 97*1713Smax.romanov@nginx.comfunc nxt_go_add_port(ctx *C.nxt_unit_ctx_t, p *C.nxt_unit_port_t) C.int { 98*1713Smax.romanov@nginx.com 99*1713Smax.romanov@nginx.com new_port := &port{ 1001316Smax.romanov@nginx.com key: port_key{ 101*1713Smax.romanov@nginx.com pid: int(p.id.pid), 102*1713Smax.romanov@nginx.com id: int(p.id.id), 1031316Smax.romanov@nginx.com }, 104*1713Smax.romanov@nginx.com rcv: getUnixConn(int(p.in_fd)), 105*1713Smax.romanov@nginx.com snd: getUnixConn(int(p.out_fd)), 1061316Smax.romanov@nginx.com } 1071316Smax.romanov@nginx.com 108*1713Smax.romanov@nginx.com add_port(new_port) 1091547Smax.romanov@nginx.com 110*1713Smax.romanov@nginx.com p.in_fd = -1 111*1713Smax.romanov@nginx.com p.out_fd = -1 112*1713Smax.romanov@nginx.com 113*1713Smax.romanov@nginx.com if new_port.key.id == 65535 { 114*1713Smax.romanov@nginx.com go func(ctx *C.nxt_unit_ctx_t) { 115*1713Smax.romanov@nginx.com C.nxt_unit_run_shared(ctx); 1161547Smax.romanov@nginx.com }(ctx) 1171547Smax.romanov@nginx.com } 118*1713Smax.romanov@nginx.com 119*1713Smax.romanov@nginx.com return C.NXT_UNIT_OK 1201316Smax.romanov@nginx.com} 1211316Smax.romanov@nginx.com 1221316Smax.romanov@nginx.com//export nxt_go_remove_port 123*1713Smax.romanov@nginx.comfunc nxt_go_remove_port(unit *C.nxt_unit_t, p *C.nxt_unit_port_t) { 124*1713Smax.romanov@nginx.com 1251316Smax.romanov@nginx.com key := port_key{ 126*1713Smax.romanov@nginx.com pid: int(p.id.pid), 127*1713Smax.romanov@nginx.com id: int(p.id.id), 1281316Smax.romanov@nginx.com } 1291316Smax.romanov@nginx.com 1301316Smax.romanov@nginx.com port_registry_.Lock() 1311316Smax.romanov@nginx.com if port_registry_.m != nil { 1321316Smax.romanov@nginx.com delete(port_registry_.m, key) 1331316Smax.romanov@nginx.com } 1341316Smax.romanov@nginx.com 1351316Smax.romanov@nginx.com port_registry_.Unlock() 1361316Smax.romanov@nginx.com} 1371316Smax.romanov@nginx.com 1381316Smax.romanov@nginx.com//export nxt_go_port_send 1391316Smax.romanov@nginx.comfunc nxt_go_port_send(pid C.int, id C.int, buf unsafe.Pointer, buf_size C.int, 1401316Smax.romanov@nginx.com oob unsafe.Pointer, oob_size C.int) C.ssize_t { 1411316Smax.romanov@nginx.com 1421316Smax.romanov@nginx.com key := port_key{ 1431316Smax.romanov@nginx.com pid: int(pid), 1441316Smax.romanov@nginx.com id: int(id), 1451316Smax.romanov@nginx.com } 1461316Smax.romanov@nginx.com 1471316Smax.romanov@nginx.com p := find_port(key) 1481316Smax.romanov@nginx.com 1491316Smax.romanov@nginx.com if p == nil { 150*1713Smax.romanov@nginx.com nxt_go_alert("port %d:%d not found", pid, id) 1511316Smax.romanov@nginx.com return 0 1521316Smax.romanov@nginx.com } 1531316Smax.romanov@nginx.com 1541316Smax.romanov@nginx.com n, oobn, err := p.snd.WriteMsgUnix(GoBytes(buf, buf_size), 1551316Smax.romanov@nginx.com GoBytes(oob, oob_size), nil) 1561316Smax.romanov@nginx.com 1571316Smax.romanov@nginx.com if err != nil { 1581316Smax.romanov@nginx.com nxt_go_warn("write result %d (%d), %s", n, oobn, err) 1591438Smax.romanov@nginx.com 1601438Smax.romanov@nginx.com n = -1 1611316Smax.romanov@nginx.com } 1621316Smax.romanov@nginx.com 1631316Smax.romanov@nginx.com return C.ssize_t(n) 1641316Smax.romanov@nginx.com} 1651316Smax.romanov@nginx.com 1661316Smax.romanov@nginx.com//export nxt_go_port_recv 1671316Smax.romanov@nginx.comfunc nxt_go_port_recv(pid C.int, id C.int, buf unsafe.Pointer, buf_size C.int, 1681316Smax.romanov@nginx.com oob unsafe.Pointer, oob_size C.int) C.ssize_t { 1691316Smax.romanov@nginx.com 1701316Smax.romanov@nginx.com key := port_key{ 1711316Smax.romanov@nginx.com pid: int(pid), 1721316Smax.romanov@nginx.com id: int(id), 1731316Smax.romanov@nginx.com } 1741316Smax.romanov@nginx.com 1751316Smax.romanov@nginx.com p := find_port(key) 1761316Smax.romanov@nginx.com 1771316Smax.romanov@nginx.com if p == nil { 178*1713Smax.romanov@nginx.com nxt_go_alert("port %d:%d not found", pid, id) 1791316Smax.romanov@nginx.com return 0 1801316Smax.romanov@nginx.com } 1811316Smax.romanov@nginx.com 1821316Smax.romanov@nginx.com n, oobn, _, _, err := p.rcv.ReadMsgUnix(GoBytes(buf, buf_size), 1831316Smax.romanov@nginx.com GoBytes(oob, oob_size)) 1841316Smax.romanov@nginx.com 1851316Smax.romanov@nginx.com if err != nil { 186*1713Smax.romanov@nginx.com if nerr, ok := err.(*net.OpError); ok { 187*1713Smax.romanov@nginx.com if nerr.Err == io.EOF { 188*1713Smax.romanov@nginx.com return 0 189*1713Smax.romanov@nginx.com } 190*1713Smax.romanov@nginx.com } 191*1713Smax.romanov@nginx.com 1921316Smax.romanov@nginx.com nxt_go_warn("read result %d (%d), %s", n, oobn, err) 1931438Smax.romanov@nginx.com 1941438Smax.romanov@nginx.com n = -1 1951316Smax.romanov@nginx.com } 1961316Smax.romanov@nginx.com 1971316Smax.romanov@nginx.com return C.ssize_t(n) 1981316Smax.romanov@nginx.com} 199