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