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