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 ( 141316Smax.romanov@nginx.com "net" 151316Smax.romanov@nginx.com "os" 161316Smax.romanov@nginx.com "sync" 171316Smax.romanov@nginx.com "unsafe" 181316Smax.romanov@nginx.com) 191316Smax.romanov@nginx.com 201316Smax.romanov@nginx.comtype port_key struct { 211316Smax.romanov@nginx.com pid int 221316Smax.romanov@nginx.com id int 231316Smax.romanov@nginx.com} 241316Smax.romanov@nginx.com 251316Smax.romanov@nginx.comtype port struct { 261316Smax.romanov@nginx.com key port_key 271316Smax.romanov@nginx.com rcv *net.UnixConn 281316Smax.romanov@nginx.com snd *net.UnixConn 291316Smax.romanov@nginx.com} 301316Smax.romanov@nginx.com 311316Smax.romanov@nginx.comtype port_registry struct { 321316Smax.romanov@nginx.com sync.RWMutex 331316Smax.romanov@nginx.com m map[port_key]*port 341316Smax.romanov@nginx.com} 351316Smax.romanov@nginx.com 361316Smax.romanov@nginx.comvar port_registry_ port_registry 371316Smax.romanov@nginx.com 381316Smax.romanov@nginx.comfunc find_port(key port_key) *port { 391316Smax.romanov@nginx.com port_registry_.RLock() 401316Smax.romanov@nginx.com res := port_registry_.m[key] 411316Smax.romanov@nginx.com port_registry_.RUnlock() 421316Smax.romanov@nginx.com 431316Smax.romanov@nginx.com return res 441316Smax.romanov@nginx.com} 451316Smax.romanov@nginx.com 461316Smax.romanov@nginx.comfunc add_port(p *port) { 471316Smax.romanov@nginx.com 481316Smax.romanov@nginx.com port_registry_.Lock() 491316Smax.romanov@nginx.com if port_registry_.m == nil { 501316Smax.romanov@nginx.com port_registry_.m = make(map[port_key]*port) 511316Smax.romanov@nginx.com } 521316Smax.romanov@nginx.com 531452Smax.romanov@nginx.com old := port_registry_.m[p.key] 541452Smax.romanov@nginx.com 551452Smax.romanov@nginx.com if old == nil { 561452Smax.romanov@nginx.com port_registry_.m[p.key] = p 571452Smax.romanov@nginx.com } 581316Smax.romanov@nginx.com 591316Smax.romanov@nginx.com port_registry_.Unlock() 601316Smax.romanov@nginx.com} 611316Smax.romanov@nginx.com 621316Smax.romanov@nginx.comfunc (p *port) Close() { 631316Smax.romanov@nginx.com if p.rcv != nil { 641316Smax.romanov@nginx.com p.rcv.Close() 651316Smax.romanov@nginx.com } 661316Smax.romanov@nginx.com 671316Smax.romanov@nginx.com if p.snd != nil { 681316Smax.romanov@nginx.com p.snd.Close() 691316Smax.romanov@nginx.com } 701316Smax.romanov@nginx.com} 711316Smax.romanov@nginx.com 721316Smax.romanov@nginx.comfunc getUnixConn(fd int) *net.UnixConn { 731316Smax.romanov@nginx.com if fd < 0 { 741316Smax.romanov@nginx.com return nil 751316Smax.romanov@nginx.com } 761316Smax.romanov@nginx.com 771316Smax.romanov@nginx.com f := os.NewFile(uintptr(fd), "sock") 781316Smax.romanov@nginx.com defer f.Close() 791316Smax.romanov@nginx.com 801316Smax.romanov@nginx.com c, err := net.FileConn(f) 811316Smax.romanov@nginx.com if err != nil { 821316Smax.romanov@nginx.com nxt_go_warn("FileConn error %s", err) 831316Smax.romanov@nginx.com return nil 841316Smax.romanov@nginx.com } 851316Smax.romanov@nginx.com 861316Smax.romanov@nginx.com uc, ok := c.(*net.UnixConn) 871316Smax.romanov@nginx.com if !ok { 881316Smax.romanov@nginx.com nxt_go_warn("Not a Unix-domain socket %d", fd) 891316Smax.romanov@nginx.com return nil 901316Smax.romanov@nginx.com } 911316Smax.romanov@nginx.com 921316Smax.romanov@nginx.com return uc 931316Smax.romanov@nginx.com} 941316Smax.romanov@nginx.com 951316Smax.romanov@nginx.com//export nxt_go_add_port 96*1547Smax.romanov@nginx.comfunc nxt_go_add_port(ctx C.uintptr_t, pid C.int, id C.int, rcv C.int, snd C.int) { 971316Smax.romanov@nginx.com p := &port{ 981316Smax.romanov@nginx.com key: port_key{ 991316Smax.romanov@nginx.com pid: int(pid), 1001316Smax.romanov@nginx.com id: int(id), 1011316Smax.romanov@nginx.com }, 1021316Smax.romanov@nginx.com rcv: getUnixConn(int(rcv)), 1031316Smax.romanov@nginx.com snd: getUnixConn(int(snd)), 1041316Smax.romanov@nginx.com } 1051316Smax.romanov@nginx.com 1061316Smax.romanov@nginx.com add_port(p) 107*1547Smax.romanov@nginx.com 108*1547Smax.romanov@nginx.com if id == 65535 { 109*1547Smax.romanov@nginx.com go func(ctx C.uintptr_t) { 110*1547Smax.romanov@nginx.com C.nxt_cgo_unit_run_shared(ctx); 111*1547Smax.romanov@nginx.com }(ctx) 112*1547Smax.romanov@nginx.com } 1131316Smax.romanov@nginx.com} 1141316Smax.romanov@nginx.com 1151316Smax.romanov@nginx.com//export nxt_go_remove_port 1161316Smax.romanov@nginx.comfunc nxt_go_remove_port(pid C.int, id C.int) { 1171316Smax.romanov@nginx.com key := port_key{ 1181316Smax.romanov@nginx.com pid: int(pid), 1191316Smax.romanov@nginx.com id: int(id), 1201316Smax.romanov@nginx.com } 1211316Smax.romanov@nginx.com 1221316Smax.romanov@nginx.com port_registry_.Lock() 1231316Smax.romanov@nginx.com if port_registry_.m != nil { 1241316Smax.romanov@nginx.com delete(port_registry_.m, key) 1251316Smax.romanov@nginx.com } 1261316Smax.romanov@nginx.com 1271316Smax.romanov@nginx.com port_registry_.Unlock() 1281316Smax.romanov@nginx.com} 1291316Smax.romanov@nginx.com 1301316Smax.romanov@nginx.com//export nxt_go_port_send 1311316Smax.romanov@nginx.comfunc nxt_go_port_send(pid C.int, id C.int, buf unsafe.Pointer, buf_size C.int, 1321316Smax.romanov@nginx.com oob unsafe.Pointer, oob_size C.int) C.ssize_t { 1331316Smax.romanov@nginx.com 1341316Smax.romanov@nginx.com key := port_key{ 1351316Smax.romanov@nginx.com pid: int(pid), 1361316Smax.romanov@nginx.com id: int(id), 1371316Smax.romanov@nginx.com } 1381316Smax.romanov@nginx.com 1391316Smax.romanov@nginx.com p := find_port(key) 1401316Smax.romanov@nginx.com 1411316Smax.romanov@nginx.com if p == nil { 1421316Smax.romanov@nginx.com nxt_go_warn("port %d:%d not found", pid, id) 1431316Smax.romanov@nginx.com return 0 1441316Smax.romanov@nginx.com } 1451316Smax.romanov@nginx.com 1461316Smax.romanov@nginx.com n, oobn, err := p.snd.WriteMsgUnix(GoBytes(buf, buf_size), 1471316Smax.romanov@nginx.com GoBytes(oob, oob_size), nil) 1481316Smax.romanov@nginx.com 1491316Smax.romanov@nginx.com if err != nil { 1501316Smax.romanov@nginx.com nxt_go_warn("write result %d (%d), %s", n, oobn, err) 1511438Smax.romanov@nginx.com 1521438Smax.romanov@nginx.com n = -1 1531316Smax.romanov@nginx.com } 1541316Smax.romanov@nginx.com 1551316Smax.romanov@nginx.com return C.ssize_t(n) 1561316Smax.romanov@nginx.com} 1571316Smax.romanov@nginx.com 1581316Smax.romanov@nginx.com//export nxt_go_port_recv 1591316Smax.romanov@nginx.comfunc nxt_go_port_recv(pid C.int, id C.int, buf unsafe.Pointer, buf_size C.int, 1601316Smax.romanov@nginx.com oob unsafe.Pointer, oob_size C.int) C.ssize_t { 1611316Smax.romanov@nginx.com 1621316Smax.romanov@nginx.com key := port_key{ 1631316Smax.romanov@nginx.com pid: int(pid), 1641316Smax.romanov@nginx.com id: int(id), 1651316Smax.romanov@nginx.com } 1661316Smax.romanov@nginx.com 1671316Smax.romanov@nginx.com p := find_port(key) 1681316Smax.romanov@nginx.com 1691316Smax.romanov@nginx.com if p == nil { 1701316Smax.romanov@nginx.com nxt_go_warn("port %d:%d not found", pid, id) 1711316Smax.romanov@nginx.com return 0 1721316Smax.romanov@nginx.com } 1731316Smax.romanov@nginx.com 1741316Smax.romanov@nginx.com n, oobn, _, _, err := p.rcv.ReadMsgUnix(GoBytes(buf, buf_size), 1751316Smax.romanov@nginx.com GoBytes(oob, oob_size)) 1761316Smax.romanov@nginx.com 1771316Smax.romanov@nginx.com if err != nil { 1781316Smax.romanov@nginx.com nxt_go_warn("read result %d (%d), %s", n, oobn, err) 1791438Smax.romanov@nginx.com 1801438Smax.romanov@nginx.com n = -1 1811316Smax.romanov@nginx.com } 1821316Smax.romanov@nginx.com 1831316Smax.romanov@nginx.com return C.ssize_t(n) 1841316Smax.romanov@nginx.com} 185