package socket import ( "errors" "fmt" "log" "net" "strings" "tunnel/pkg/server/env" "tunnel/pkg/server/opts" ) type listenSocket struct { proto, addr string listen net.Listener redirect bool } func newListenSocket(proto, addr string, opts opts.Opts) (S, error) { redirect := opts.Bool("redirect") if proto == "tcp" { if !strings.Contains(addr, ":") { addr = ":" + addr } } if redirect && proto != "tcp" { return nil, errors.New("redirect not supported") } listen, err := net.Listen(proto, addr) if err != nil { return nil, err } s := &listenSocket{ proto: proto, addr: addr, listen: listen, redirect: redirect, } return s, nil } func (s *listenSocket) Open(env env.Env) (Conn, error) { var original string conn, err := s.listen.Accept() if err != nil { return nil, err } la, ra := conn.LocalAddr(), conn.RemoteAddr() desc := fmt.Sprintf("%s/%s->%s", la.Network(), ra, la) info := fmt.Sprintf("<%s/%s", ra.Network(), ra) if s.redirect { if err := getConnOriginalAddr(conn, &original); err != nil { log.Println("accept", desc, "failed") conn.Close() return nil, err } else { env.Set("original.addr", original) } } if original == "" { log.Println("accept", desc) } else { log.Println("accept", desc, "original", original) } return newConn(conn, desc, info), nil } func (s *listenSocket) String() string { return fmt.Sprintf("%s/%s,listen", s.proto, s.addr) } func (s *listenSocket) Close() { s.listen.Close() }