xref: /unit/go/port.go (revision 1547)
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