// ListenAX25 announces on the local port axPort using mycall as the local address. func ListenAX25(axPort, mycall string) (net.Listener, error) { if _, err := loadPorts(); err != nil { return nil, err } // Setup local address (via callsign of supplied axPort) localAddr := newAX25Addr(mycall) if err := localAddr.setPort(axPort); err != nil { return nil, err } // Create file descriptor var socket fd if f, err := syscall.Socket(syscall.AF_AX25, syscall.SOCK_SEQPACKET, 0); err != nil { return nil, err } else { socket = fd(f) } if err := socket.bind(localAddr); err != nil { return nil, err } if err := syscall.Listen(int(socket), syscall.SOMAXCONN); err != nil { return nil, err } return ax25Listener{ sock: fd(socket), localAddr: AX25Addr{localAddr}, }, nil }
func listenStream(netw, addr string) (l net.Listener, err error) { var ( file *os.File ) fd, err := listen(netw, addr) if err != nil { return nil, err } // Set backlog size to the maximum if err = syscall.Listen(fd, syscall.SOMAXCONN); err != nil { syscall.Close(fd) return nil, err } file = os.NewFile(uintptr(fd), filePrefix+strconv.Itoa(os.Getpid())) if l, err = net.FileListener(file); err != nil { syscall.Close(fd) return nil, err } if err = file.Close(); err != nil { syscall.Close(fd) l.Close() return nil, err } return l, err }
// Listen wraps syscall.Listen. func (sw *Switch) Listen(s syscall.Handle, backlog int) (err error) { so := sw.sockso(s) if so == nil { return syscall.Listen(s, backlog) } sw.fmu.RLock() f, _ := sw.fltab[FilterListen] sw.fmu.RUnlock() af, err := f.apply(so) if err != nil { return err } so.Err = syscall.Listen(s, backlog) if err = af.apply(so); err != nil { return err } sw.smu.Lock() defer sw.smu.Unlock() if so.Err != nil { sw.stats.getLocked(so.Cookie).ListenFailed++ return so.Err } sw.stats.getLocked(so.Cookie).Listened++ return nil }
func so_listen(fd int, queue int) error { if queue < 1 { return os.NewSyscallError("so_listen", syscall.Listen(fd, syscall.SOMAXCONN)) } return os.NewSyscallError("so_listen", syscall.Listen(fd, queue)) }
// Create a tcp socket, setting the TCP_FASTOPEN socket option. func (s *TFOServer) Bind() (err error) { s.fd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) if err != nil { if err == syscall.ENOPROTOOPT { err = errors.New("TCP Fast Open server support is unavailable (unsupported kernel).") } return } err = syscall.SetsockoptInt(s.fd, syscall.SOL_TCP, TCP_FASTOPEN, 1) if err != nil { err = errors.New(fmt.Sprintf("Failed to set necessary TCP_FASTOPEN socket option: %s", err)) return } sa := &syscall.SockaddrInet4{Addr: s.ServerAddr, Port: s.ServerPort} err = syscall.Bind(s.fd, sa) if err != nil { err = errors.New(fmt.Sprintf("Failed to bind to Addr: %v, Port: %d, Reason: %s", s.ServerAddr, s.ServerPort, err)) return } log.Printf("Server: Bound to addr: %v, port: %d\n", s.ServerAddr, s.ServerPort) err = syscall.Listen(s.fd, LISTEN_BACKLOG) if err != nil { err = errors.New(fmt.Sprintf("Failed to listen: %s", err)) return } return }
func main() { acceptingFd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) check(err) addr := &syscall.SockaddrInet4{Port: 3000, Addr: [4]byte{0, 0, 0, 0}} err = syscall.Bind(acceptingFd, addr) check(err) err = syscall.Listen(acceptingFd, 100) check(err) for { connectionFd, _, err := syscall.Accept(acceptingFd) check(err) fmt.Println("Accepted new connectrion") data := make([]byte, 1024) _, err = syscall.Read(connectionFd, data) check(err) fmt.Printf("Received: %s\n", string(data)) _, err = syscall.Write(connectionFd, data) check(err) err = syscall.Close(connectionFd) check(err) } }
func (io *NetIOManager) ProxyNetListen(sa syscall.Sockaddr) error { serverfd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if err != nil { goto Error } err = syscall.Bind(serverfd, sa) if err != nil { goto Cleanup } err = syscall.Listen(serverfd, io.max_backlog) if err != nil { goto Cleanup } err = syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_ADD, serverfd, &syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(serverfd)}) if err != nil { goto Cleanup } io.proxy_server_fd = serverfd return nil Cleanup: syscall.Close(serverfd) Error: return err }
func CreateTCPSocket(proto, addr string) (net.Listener, error) { var err error var laddr *net.TCPAddr laddr, err = net.ResolveTCPAddr(proto, addr) if err != nil { return nil, err } family, ipv6only := favoriteTCPAddrFamily(proto, laddr, "listen") var socketAddr syscall.Sockaddr if socketAddr, err = ipToSockaddr(family, laddr.IP, laddr.Port, laddr.Zone); err != nil { panic(err) return nil, err } var s int if s, err = sysSocket(family, syscall.SOCK_STREAM, 0); err != nil { return nil, err } if err = setDefaultSockopts(s, family, syscall.SOCK_STREAM, ipv6only); err != nil { closesocket(s) return nil, err } if err = setDefaultListenerSockopts(s); err != nil { closesocket(s) return nil, err } if err = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, SO_REUSEPORT, 1); err != nil { closesocket(s) panic(err) return nil, err } if err = syscall.Bind(s, socketAddr); err != nil { closesocket(s) return nil, err } if err = syscall.Listen(s, maxListenerBacklog()); err != nil { closesocket(s) return nil, err } file := os.NewFile(uintptr(s), "listener-"+laddr.String()) defer file.Close() var socketListener net.Listener if socketListener, err = net.FileListener(file); err != nil { return nil, err } return socketListener, nil }
// Listen returns TCP listener with SO_REUSEPORT option set. // // Only tcp4 network is supported. // // ErrNoReusePort error is returned if the system doesn't support SO_REUSEPORT. func Listen(network, addr string) (l net.Listener, err error) { var ( soType, fd int file *os.File sockaddr syscall.Sockaddr ) if sockaddr, soType, err = getSockaddr(network, addr); err != nil { return nil, err } syscall.ForkLock.RLock() fd, err = syscall.Socket(soType, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if err == nil { syscall.CloseOnExec(fd) } syscall.ForkLock.RUnlock() if err != nil { return nil, err } if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { syscall.Close(fd) return nil, err } if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, soReusePort, 1); err != nil { syscall.Close(fd) return nil, &ErrNoReusePort{err} } if err = syscall.Bind(fd, sockaddr); err != nil { syscall.Close(fd) return nil, err } if err = syscall.Listen(fd, syscall.SOMAXCONN); err != nil { syscall.Close(fd) return nil, err } name := fmt.Sprintf("reuseport.%d.%s.%s", os.Getpid(), network, addr) file = os.NewFile(uintptr(fd), name) if l, err = net.FileListener(file); err != nil { file.Close() return nil, err } if err = file.Close(); err != nil { l.Close() return nil, err } return l, err }
func listen2(path string) int { _, err := os.Stat(path) if err == nil { os.Remove(path) } fd, _ := syscall.Socket(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0) addr := &syscall.SockaddrUnix{Name: path} syscall.Bind(fd, addr) syscall.Listen(fd, 1) return fd }
// NewReusablePortListener returns net.FileListener that created from // a file discriptor for a socket with SO_REUSEPORT option. func NewReusablePortListener(proto, addr string) (l net.Listener, err error) { var ( soType, fd int file *os.File sockaddr syscall.Sockaddr ) if sockaddr, soType, err = getSockaddr(proto, addr); err != nil { return nil, err } syscall.ForkLock.RLock() if fd, err = syscall.Socket(soType, syscall.SOCK_STREAM, syscall.IPPROTO_TCP); err != nil { return nil, err } syscall.ForkLock.RUnlock() if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { syscall.Close(fd) return nil, err } if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, reusePort, 1); err != nil { syscall.Close(fd) return nil, err } if err = syscall.Bind(fd, sockaddr); err != nil { syscall.Close(fd) return nil, err } // Set backlog size to the maximum if err = syscall.Listen(fd, listenerBacklogMaxSize); err != nil { syscall.Close(fd) return nil, err } file = os.NewFile(uintptr(fd), getSocketFileName(proto, addr)) if l, err = net.FileListener(file); err != nil { syscall.Close(fd) return nil, err } if err = file.Close(); err != nil { syscall.Close(fd) return nil, err } return l, err }
// TuneAndListenTCP announces on the TCP address laddr and returns a TCP // listener. The configuration config indicates additional socket options // set on the listener socket. func TuneAndListenTCP(net string, laddr *TCPAddr, tuners ...Tuner) (Listener, error) { var err error family, ipv6only := favoriteTCPAddrFamily(net, laddr, "listen") var socketAddr syscall.Sockaddr if socketAddr, err = ipToSockaddr(family, laddr.IP, laddr.Port, laddr.Zone); err != nil { return nil, err } var s int if s, err = sysSocket(family, syscall.SOCK_STREAM, 0); err != nil { return nil, err } if err = setDefaultSockopts(s, family, syscall.SOCK_STREAM, ipv6only); err != nil { closesocket(s) return nil, err } if err = setDefaultListenerSockopts(s); err != nil { closesocket(s) return nil, err } for _, tuner := range tuners { if err := tuner(s); err != nil { return nil, err } } if err = syscall.Bind(s, socketAddr); err != nil { closesocket(s) return nil, err } if err = syscall.Listen(s, maxListenerBacklog()); err != nil { closesocket(s) return nil, err } file := os.NewFile(uintptr(s), "listener-"+laddr.String()) defer file.Close() var socketListener Listener if socketListener, err = FileListener(file); err != nil { return nil, err } return socketListener, nil }
// NewReusablePortListener returns net.FileListener that created from a file discriptor for a socket with SO_REUSEPORT option. func NewReusablePortListener(proto, addr string) (l net.Listener, err error) { var ( soType, fd int file *os.File sockaddr syscall.Sockaddr ) if sockaddr, soType, err = getSockaddr(proto, addr); err != nil { return nil, err } if fd, err = syscall.Socket(soType, syscall.SOCK_STREAM, syscall.IPPROTO_TCP); err != nil { return nil, err } defer func() { if err != nil { syscall.Close(fd) } }() if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { return nil, err } if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, reusePort, 1); err != nil { return nil, err } if err = syscall.Bind(fd, sockaddr); err != nil { return nil, err } // Set backlog size to the maximum if err = syscall.Listen(fd, listenerBacklog); err != nil { return nil, err } // File Name get be nil file = os.NewFile(uintptr(fd), filePrefix+strconv.Itoa(os.Getpid())) if l, err = net.FileListener(file); err != nil { return nil, err } if err = file.Close(); err != nil { return nil, err } return l, err }
// ListenTCP announces on the TCP address laddr and returns a TCP listener. // Net must be "tcp", "tcp4", or "tcp6". // If laddr has a port of 0, it means to listen on some available port. // The caller can use l.Addr() to retrieve the chosen address. func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) { fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP) if err != nil { return nil, err } err = syscall.Listen(fd.sysfd, listenerBacklog) if err != nil { closesocket(fd.sysfd) return nil, &OpError{"listen", net, laddr, err} } l := new(TCPListener) l.fd = fd return l, nil }
// ListenTCP announces on the TCP address laddr and returns a TCP listener. // Net must be "tcp", "tcp4", or "tcp6". // If laddr has a port of 0, it means to listen on some available port. // The caller can use l.Addr() to retrieve the chosen address. func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error) { fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_STREAM, "listen", sockaddrToTCP) if err != nil { return nil, err } errno := syscall.Listen(fd.sysfd, listenBacklog()) if errno != 0 { syscall.Close(fd.sysfd) return nil, &OpError{"listen", "tcp", laddr, os.Errno(errno)} } l = new(TCPListener) l.fd = fd return l, nil }
/*----------------------------------------------------------------------------- -- FUNCTION: manageConnections -- -- DATE: February 7, 2016 -- -- REVISIONS: February 11, 2016 Modified for EPoll -- -- -- DESIGNER: Marc Vouve -- -- PROGRAMMER: Marc Vouve -- -- INTERFACE: func manageConnections(srvInfo serverInfo, osSignals chan os.Signal) -- srvInfo: information about the server (IPC and listening port) -- osSignals: listens for signals from the OS that should stop the server from running -- -- RETURNS: void -- -- NOTES: This server will loop until inturupted by an OS Signal on soSignals. ------------------------------------------------------------------------------*/ func newServerInfo() serverInfo { srvInfo := serverInfo{serverConnection: make(chan int, 100), connectInfo: make(chan connectionInfo, 100)} fd, err := syscall.Socket(syscall.AF_INET, syscall.O_NONBLOCK|syscall.SOCK_STREAM, 0) if err != nil { log.Println(err) } syscall.SetNonblock(fd, true) // TODO: make port vairable addr := getAddr() syscall.Bind(fd, &addr) syscall.Listen(fd, backlog) srvInfo.listener = fd return srvInfo }
// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener. // Net must be "unix" (stream sockets). func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err error) { if net != "unix" && net != "unixgram" && net != "unixpacket" { return nil, UnknownNetworkError(net) } if laddr != nil { laddr = &UnixAddr{laddr.Name, net} // make our own copy } fd, err := unixSocket(net, laddr, nil, "listen") if err != nil { return nil, err } e1 := syscall.Listen(fd.sysfd, 8) // listenBacklog()); if e1 != 0 { closesocket(fd.sysfd) return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Err: os.Errno(e1)} } return &UnixListener{fd, laddr.Name}, nil }
// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener. // Net must be "unix" (stream sockets). func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) { if net != "unix" && net != "unixgram" && net != "unixpacket" { return nil, UnknownNetworkError(net) } if laddr != nil { laddr = &UnixAddr{laddr.Name, net} // make our own copy } fd, err := unixSocket(net, laddr, nil, "listen") if err != nil { return nil, err } err = syscall.Listen(fd.sysfd, listenerBacklog) if err != nil { closesocket(fd.sysfd) return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err} } return &UnixListener{fd, laddr.Name}, nil }
func main() { fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC|syscall.SOCK_NONBLOCK, syscall.IPPROTO_TCP) if err != nil { log.Fatalln("Cannot create socket:", err) } err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) if err != nil { log.Fatalln("Cannot setsockopt:", err) } sa := &syscall.SockaddrInet4{ Port: 12345, // Listen on this port number Addr: [4]byte{}, // Listen to all IPs } err = syscall.Bind(fd, sa) if err != nil { log.Fatalln("Cannot bind to socket:", err) } err = syscall.Listen(fd, 10) if err != nil { log.Fatalln("Cannot listen to socket:", err) } // TODO select /* go func() { x, raddr, err := syscall.Accept(fd) if err != nil { log.Fatalln("Cannot listen to socket:", err) } log.Printf("received:") log.Printf("%#v", raddr) log.Printf("%#v", x) }() */ }
// ListenUnix announces on the Unix domain socket laddr and returns a // Unix listener. The network net must be "unix", "unixgram" or // "unixpacket". func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) { switch net { case "unix", "unixgram", "unixpacket": default: return nil, UnknownNetworkError(net) } if laddr == nil { return nil, &OpError{"listen", net, nil, errMissingAddress} } fd, err := unixSocket(net, laddr, nil, "listen", noDeadline) if err != nil { return nil, err } err = syscall.Listen(fd.sysfd, listenerBacklog) if err != nil { closesocket(fd.sysfd) return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err} } return &UnixListener{fd, laddr.Name}, nil }
// ListenTCP announces on the TCP address laddr and returns a TCP listener. // Net must be "tcp", "tcp4", or "tcp6". // If laddr has a port of 0, it means to listen on some available port. // The caller can use l.Addr() to retrieve the chosen address. func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) { switch net { case "tcp", "tcp4", "tcp6": default: return nil, UnknownNetworkError(net) } if laddr == nil { laddr = &TCPAddr{} } fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP) if err != nil { return nil, err } err = syscall.Listen(fd.sysfd, listenerBacklog) if err != nil { closesocket(fd.sysfd) return nil, &OpError{"listen", net, laddr, err} } return &TCPListener{fd}, nil }
func main() { check(os.MkdirAll(FOLDER, 0777)) // Initialisation des variables serveur lastUpdate = time.Date(1994, time.April, 2, 2, 0, 0, 0, time.UTC) dat, err := ioutil.ReadFile(LASTUPFOLDER) if err == nil { err = json.Unmarshal(dat, &lastUpdate) check(err) } envoi = &sync.Mutex{} err = util.ScanDir(FOLDER, &mainFolder) check(err) // création du socket d'écoute fd, err := s.Socket(s.AF_INET, s.SOCK_STREAM, 0) if err != nil { check(err) } defer s.Close(fd) if err := s.Bind(fd, &s.SockaddrInet4{Port: PORT, Addr: [4]byte{0, 0, 0, 0}}); err != nil { check(err) } if err := s.Listen(fd, 5); err != nil { check(err) } // Lancement de l'écoute du serveur fmt.Println("Serveur lancé !") for { nfd, sa, err := s.Accept(fd) if err != nil { check(err) } envoi.Lock() go app(nfd, sa) envoi.Unlock() } }
func (fd *netFD) listenStream(laddr sockaddr, backlog int, toAddr func(syscall.Sockaddr) Addr) error { if err := setDefaultListenerSockopts(fd.sysfd); err != nil { return err } if lsa, err := laddr.sockaddr(fd.family); err != nil { return err } else if lsa != nil { if err := syscall.Bind(fd.sysfd, lsa); err != nil { return os.NewSyscallError("bind", err) } } if err := syscall.Listen(fd.sysfd, backlog); err != nil { return os.NewSyscallError("listen", err) } if err := fd.init(); err != nil { return err } lsa, _ := syscall.Getsockname(fd.sysfd) fd.setAddr(toAddr(lsa), nil) return nil }
// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener. // Net must be "unix" (stream sockets). func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) { if net != "unix" && net != "unixgram" { return nil, UnknownNetworkError(net) } if laddr != nil { laddr = &UnixAddr{laddr.Name, net == "unixgram"} // make our own copy } fd, e := unixSocket(net, laddr, nil, "listen") if e != nil { if pe, ok := e.(*os.PathError); ok { e = pe.Error } return nil, e } e1 := syscall.Listen(fd.sysfd, 8) // listenBacklog()); if e1 != 0 { syscall.Close(fd.sysfd) return nil, &OpError{"listen", "unix", laddr, os.Errno(e1)} } return &UnixListener{fd, laddr.Name}, nil }
// ReusableListen returns a TCP listener with SO_REUSEPORT and keepalives // enabled. func ReusableListen(proto, addr string) (net.Listener, error) { backlogOnce.Do(func() { backlog = maxListenerBacklog() }) saddr, typ, err := sockaddr(proto, addr) if err != nil { return nil, err } fd, err := syscall.Socket(typ, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if err != nil { return nil, err } if err := setSockopt(fd); err != nil { return nil, err } if err := syscall.Bind(fd, saddr); err != nil { return nil, err } if err := syscall.Listen(fd, backlog); err != nil { return nil, err } f := os.NewFile(uintptr(fd), proto+":"+addr) l, err := net.FileListener(f) if err != nil { return nil, err } if err := f.Close(); err != nil { l.Close() return nil, err } return l, nil }
// NewReusablePortListener returns net.FileListener that created from a file discriptor for a socket with SO_REUSEPORT option. func newSocket(proto, addr string) (file *os.File, err error) { var ( soType, fd int sockaddr syscall.Sockaddr ) if sockaddr, soType, err = getSockaddr(proto, addr); err != nil { return nil, err } if proto == "tcp" || proto == "tcp4" || proto == "tcp6" { if fd, err = syscall.Socket(soType, syscall.SOCK_STREAM, syscall.IPPROTO_TCP); err != nil { return nil, err } } else { if fd, err = syscall.Socket(soType, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP); err != nil { return nil, err } } if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, reusePort, 1); err != nil { return nil, err } if err = syscall.Bind(fd, sockaddr); err != nil { return nil, err } if proto == "tcp" || proto == "tcp4" || proto == "tcp6" { // Set backlog size to the maximum if err = syscall.Listen(fd, syscall.SOMAXCONN); err != nil { return nil, err } } // File Name get be nil file = os.NewFile(uintptr(fd), filePrefix+strconv.Itoa(os.Getpid())) return file, err }
// dialExec will ForkExec a new process, and returns a wsConn that connects to its stdin func dialExec(binpath string) (rwc io.ReadWriteCloser, err os.Error) { listenBacklog := 1024 dir, file := path.Split(binpath) socketPath := "/tmp/" + file + ".sock" socketIndex := 0 // if the first socket is really in use (we are launching this same process more than once) // then the socketIndex will start incrementing so we assign .sock-1 to the second process, etc for { err := os.Remove(socketPath) // if the socket file is stale, but not in use, the Remove succeeds with no error if err == nil { goto haveSocket // success, found a stale socket we can re-use } // otherwise we have to check what the error was switch err.String() { case "remove " + socketPath + ": no such file or directory": goto haveSocket // success, we have found an unused socket. default: // if its really in use, we start incrementing socketIndex socketIndex += 1 socketPath = "/tmp/" + file + ".sock-" + strconv.Itoa(socketIndex) Log("Socket was in use, trying:", socketPath) } } haveSocket: var fd, cfd, errno int var sa syscall.Sockaddr // we can almost use UnixListener to do this except it doesn't expose the fd it's listening on // create a new socket if fd, errno = syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0); errno != 0 { Log("Creating first new socket failed:", syscall.Errstr(errno)) return nil, os.NewError(fmt.Sprint("Creating first new socket failed:", syscall.Errstr(errno))) } // bind the new socket to socketPath if errno = syscall.Bind(fd, &syscall.SockaddrUnix{Name: socketPath}); errno != 0 { Log("Bind failed:", syscall.Errstr(errno)) return nil, os.NewError(fmt.Sprint("Bind failed:", syscall.Errstr(errno))) } // start to listen on that socket if errno = syscall.Listen(fd, listenBacklog); errno != 0 { Log("Listen failed:", syscall.Errstr(errno)) return nil, os.NewError(fmt.Sprint("Listen failed:", syscall.Errstr(errno))) } // then ForkExec a new process, and give this listening socket to them as stdin // DEBUG: for now, give the new process our stdout, and stderr, but the spec says these should be closed // in reality, we should redirect, capture, and possibly log separately if _, errno = syscall.ForkExec(file, []string{}, []string{}, dir, []int{fd, 1, 2}); errno != 0 { Log("ForkExec failed:", syscall.Errstr(errno)) return nil, os.NewError(fmt.Sprint("ForkExec failed:", syscall.Errstr(errno))) } // now create a socket for the client-side of the connection if cfd, errno = syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0); errno != 0 { Log("Creating new socket on webserver failed:", syscall.Errstr(errno)) return nil, os.NewError(fmt.Sprint("Creating new socket on webserver failed:", syscall.Errstr(errno))) } // find the address of the socket we gave the new process if sa, errno = syscall.Getsockname(fd); errno != 0 { Log("Getsockname failed:", syscall.Errstr(errno)) return nil, os.NewError(fmt.Sprint("Getsockname failed:", syscall.Errstr(errno))) } // connect our client side to the remote address if errno = syscall.Connect(cfd, sa); errno != 0 { Log("Connect failed:", syscall.Errstr(errno)) return nil, os.NewError(fmt.Sprint("Connect failed:", syscall.Errstr(errno))) } // return a wrapper around the client side of this connection rwc = os.NewFile(cfd, "exec://"+binpath) return rwc, nil }
// dialExec will ForkExec a new process, and returns a wsConn that connects to its // stdin func dialExec(binpath string) (io.ReadWriteCloser, os.Error) { listenBacklog := 1024 dir, file := path.Split(binpath) socketPath := "/tmp/" + file + ".sock" // if the first socket is really in use (we are launching this same process more // than once) then the socketIndex will start incrementing so we assign .sock-1 // to the second process, etc socketIndex := 0 err := os.Remove(socketPath) // if the socket file is stale but not in use, // Remove succeeds with no error for err != nil { pe, ok := err.(*os.PathError) if ok && pe.Error == os.ENOENT { // success, found a stale socket we can re-use break } // if it's really in use, we start incrementing socketIndex socketIndex++ socketPath = "/tmp/" + file + ".sock-" + strconv.Itoa(socketIndex) Log("Socket was in use, trying:", socketPath) err = os.Remove(socketPath) } var fd, cfd, errno int var sa syscall.Sockaddr // we can almost use UnixListener to do this except it doesn't expose the fd // it's listening on // create a new socket if fd, errno = syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0); errno != 0 { msg := "Creating first new socket failed: " + syscall.Errstr(errno) Log(msg) return nil, os.NewError(msg) } // bind the new socket to socketPath if errno = syscall.Bind(fd, &syscall.SockaddrUnix{Name: socketPath}); errno != 0 { msg := "Bind failed: " + syscall.Errstr(errno) Log(msg) return nil, os.NewError(msg) } // start to listen on that socket if errno = syscall.Listen(fd, listenBacklog); errno != 0 { msg := "Listen failed: " + syscall.Errstr(errno) Log(msg) return nil, os.NewError(msg) } // then ForkExec a new process, and give this listening socket to them as stdin // DEBUG: for now, give the new process our stdout, and stderr, but the spec // says these should be closed // in reality, we should redirect, capture, and possibly log separately if _, errno = syscall.ForkExec(file, []string{}, []string{}, dir, []int{fd, 1, 2}); errno != 0 { msg := "ForkExec failed: " + syscall.Errstr(errno) Log(msg) return nil, os.NewError(msg) } // now create a socket for the client-side of the connection if cfd, errno = syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0); errno != 0 { msg := "Creating new socket on webserved failed: " + syscall.Errstr(errno) Log(msg) return nil, os.NewError(msg) } // find the address of the socket we gave the new process if sa, errno = syscall.Getsockname(fd); errno != 0 { msg := "Getsockname failed: " + syscall.Errstr(errno) Log(msg) return nil, os.NewError(msg) } // connect our client side to the remote address if errno = syscall.Connect(cfd, sa); errno != 0 { msg := "Connected failed: " + syscall.Errstr(errno) Log(msg) return nil, os.NewError(msg) } // return a wrapper around the client side of this connection rwc := os.NewFile(cfd, "exec://"+binpath) return rwc, nil }
func Listen(rendezvousAddr string, key string) (net.Listener, error) { raddr, err := net.ResolveTCPAddr("tcp", rendezvousAddr) if err != nil { return nil, err } rsockaddr, domain, err := tcpaddrToSockaddr(raddr) if err != nil { return nil, err } sendSock, err := syscall.Socket(domain, syscall.SOCK_STREAM, 0) if err != nil { return nil, err } if err := syscall.SetsockoptInt( sendSock, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1, ); err != nil { return nil, err } if err := syscall.Connect(sendSock, rsockaddr); err != nil { return nil, err } lsockaddr, err := syscall.Getsockname(sendSock) if err != nil { return nil, err } listenSock, err := syscall.Socket(domain, syscall.SOCK_STREAM, 0) if err != nil { return nil, err } if err := syscall.SetsockoptInt( listenSock, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1, ); err != nil { return nil, err } if err := syscall.Bind(listenSock, lsockaddr); err != nil { return nil, err } if err := syscall.Listen(listenSock, 1000); err != nil { return nil, err } sendFile := os.NewFile(uintptr(sendSock), "rendezvous-send") listenFile := os.NewFile(uintptr(listenSock), "rendezvous-listen") rendezvousConn, err := net.FileConn(sendFile) if err != nil { return nil, err } encoder := json.NewEncoder(rendezvousConn) message := map[string]string{ "action": "listen", "key": key, } if err := encoder.Encode(&message); err != nil { return nil, err } return net.FileListener(listenFile) }
var initStep = [...]InitStep{ { ErrFmt: "Create epoll fd error [%s]\n", Action: func(t *Tunnel) (err error) { t.LFd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) return err }}, { ErrFmt: "Bind epoll fd error [%s]\n", Action: func(t *Tunnel) error { return syscall.Bind(t.LFd, &syscall.SockaddrInet4{Port: int(t.EPort), Addr: [4]byte{0, 0, 0, 0}}) }}, { ErrFmt: "Listen fd error [%s]\n", Action: func(t *Tunnel) error { return syscall.Listen(t.LFd, 10) }}, { ErrFmt: "Add fd to epoll error [%s]\n", Action: func(t *Tunnel) error { return syscall.EpollCtl(epollFd, syscall.EPOLL_CTL_ADD, t.LFd, &syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(t.LFd)}) }}, } var pathAddStep = [...]TunnelStep{ { ErrFmt: "Port [%d] accept error [%s]", Action: func(tc *TunnelConn) (err error) { tc.EFd, _, err = syscall.Accept(tc.RelTunnel.LFd) return }},