github.com/sagernet/sing-box@v1.9.0-rc.20/transport/trojan/mux.go (about) 1 package trojan 2 3 import ( 4 "context" 5 "net" 6 7 E "github.com/sagernet/sing/common/exceptions" 8 M "github.com/sagernet/sing/common/metadata" 9 "github.com/sagernet/sing/common/rw" 10 "github.com/sagernet/sing/common/task" 11 "github.com/sagernet/smux" 12 ) 13 14 func HandleMuxConnection(ctx context.Context, conn net.Conn, metadata M.Metadata, handler Handler) error { 15 session, err := smux.Server(conn, smuxConfig()) 16 if err != nil { 17 return err 18 } 19 var group task.Group 20 group.Append0(func(_ context.Context) error { 21 var stream net.Conn 22 for { 23 stream, err = session.AcceptStream() 24 if err != nil { 25 return err 26 } 27 go newMuxConnection(ctx, stream, metadata, handler) 28 } 29 }) 30 group.Cleanup(func() { 31 session.Close() 32 }) 33 return group.Run(ctx) 34 } 35 36 func newMuxConnection(ctx context.Context, stream net.Conn, metadata M.Metadata, handler Handler) { 37 err := newMuxConnection0(ctx, stream, metadata, handler) 38 if err != nil { 39 handler.NewError(ctx, E.Cause(err, "process trojan-go multiplex connection")) 40 } 41 } 42 43 func newMuxConnection0(ctx context.Context, stream net.Conn, metadata M.Metadata, handler Handler) error { 44 command, err := rw.ReadByte(stream) 45 if err != nil { 46 return E.Cause(err, "read command") 47 } 48 metadata.Destination, err = M.SocksaddrSerializer.ReadAddrPort(stream) 49 if err != nil { 50 return E.Cause(err, "read destination") 51 } 52 switch command { 53 case CommandTCP: 54 return handler.NewConnection(ctx, stream, metadata) 55 case CommandUDP: 56 return handler.NewPacketConnection(ctx, &PacketConn{Conn: stream}, metadata) 57 default: 58 return E.New("unknown command ", command) 59 } 60 } 61 62 func smuxConfig() *smux.Config { 63 config := smux.DefaultConfig() 64 config.KeepAliveDisabled = true 65 return config 66 }