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  }