func ipToSocksAddr(family int, ip net.IP, port int, zone string) (unix.Sockaddr, error) { switch family { case unix.AF_INET: if len(ip) == 0 { ip = net.IPv4zero } if ip = ip.To4(); ip == nil { return nil, net.InvalidAddrError("non-IPv4 address") } sa := new(unix.SockaddrInet4) for i := 0; i < net.IPv4len; i++ { sa.Addr[i] = ip[i] } sa.Port = port return sa, nil case unix.AF_INET6: if len(ip) == 0 { ip = net.IPv6zero } // IPv4 callers use 0.0.0.0 to mean "announce on any available address". // In IPv6 mode, Linux treats that as meaning "announce on 0.0.0.0", // which it refuses to do. Rewrite to the IPv6 unspecified address. if ip.Equal(net.IPv4zero) { ip = net.IPv6zero } if ip = ip.To16(); ip == nil { return nil, net.InvalidAddrError("non-IPv6 address") } sa := new(unix.SockaddrInet6) for i := 0; i < net.IPv6len; i++ { sa.Addr[i] = ip[i] } sa.Port = port sa.ZoneId = uint32(zoneToInt(zone)) return sa, nil } return nil, net.InvalidAddrError("unexpected socket family") }
func tcpAddrToSockaddr(addr string) (sa unix.Sockaddr, err error) { if len(addr) > 0 && addr[0] == ':' { addr = "0.0.0.0" + addr } tcpAddr, err := net.ResolveTCPAddr("tcp", addr) if err != nil { return } if ip := tcpAddr.IP.To4(); ip != nil { sa := new(unix.SockaddrInet4) sa.Port = tcpAddr.Port copy(sa.Addr[:], ip) return sa, nil } else if ip := tcpAddr.IP.To16(); ip != nil { sa := new(unix.SockaddrInet6) sa.Port = tcpAddr.Port copy(sa.Addr[:], ip) sa.ZoneId = uint32(zoneToInt(tcpAddr.Zone)) return sa, nil } return nil, net.InvalidAddrError("unknown address") }
func main() { fmt.Println("Listening on port :", port) counter := new(connCounter) // create socket fd, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, 0) if err != nil { log.Fatal("socket-error: ", err) } // sa struct sa := new(unix.SockaddrInet4) sa.Port = 9090 // bind err = unix.Bind(fd, sa) if err != nil { log.Fatal("bind: ", err) } // listen err = unix.Listen(fd, 3) if err != nil { log.Fatal("listen: ", err) } for { connInfo := new(connection) // accept connection, discard SA struct newFd, _, err := unix.Accept(fd) connInfo.fd = newFd if err != nil { log.Fatal("accept: ", err) } // client reads until closes, adding // a gorutine allows dealing with more // requests. counter.mu.Lock() counter.num += 1 counter.mu.Unlock() fmt.Println("Number of connections: ", counter.num) go func(c *connection, counter *connCounter) { fmt.Printf("Conn.fd=%d\n", c.fd) for { // read c.buf = make([]byte, 50) n, err := unix.Read(c.fd, c.buf) if err != nil { log.Fatal("read: ", err) } fmt.Printf("Read: %d Value: %s\n", n, string(c.buf[0:n])) // close if string(c.buf[0:5]) == "close" { _, err = unix.Write(c.fd, []byte(`Bye bye buddy`)) if err != nil { log.Fatal("close: ", err) } err = unix.Close(c.fd) if err != nil { log.Fatal("close: ", err) } counter.mu.Lock() counter.num = counter.num - 1 counter.mu.Unlock() return } } }(connInfo, counter) } }