123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- package trojan
- import (
- std_bufio "bufio"
- "context"
- "net"
- "os"
- "github.com/sagernet/sing/common/buf"
- "github.com/sagernet/sing/common/bufio"
- E "github.com/sagernet/sing/common/exceptions"
- "github.com/sagernet/sing/common/logger"
- M "github.com/sagernet/sing/common/metadata"
- N "github.com/sagernet/sing/common/network"
- "github.com/sagernet/sing/common/task"
- "github.com/sagernet/smux"
- )
- func HandleMuxConnection(ctx context.Context, conn net.Conn, source M.Socksaddr, handler Handler, logger logger.ContextLogger, onClose N.CloseHandlerFunc) error {
- session, err := smux.Server(conn, smuxConfig())
- if err != nil {
- return err
- }
- var group task.Group
- group.Append0(func(_ context.Context) error {
- var stream net.Conn
- for {
- stream, err = session.AcceptStream()
- if err != nil {
- return err
- }
- go newMuxConnection(ctx, stream, source, handler, logger)
- }
- })
- group.Cleanup(func() {
- session.Close()
- if onClose != nil {
- onClose(os.ErrClosed)
- }
- })
- return group.Run(ctx)
- }
- func newMuxConnection(ctx context.Context, conn net.Conn, source M.Socksaddr, handler Handler, logger logger.ContextLogger) {
- err := newMuxConnection0(ctx, conn, source, handler)
- if err != nil {
- logger.ErrorContext(ctx, E.Cause(err, "process trojan-go multiplex connection"))
- }
- }
- func newMuxConnection0(ctx context.Context, conn net.Conn, source M.Socksaddr, handler Handler) error {
- reader := std_bufio.NewReader(conn)
- command, err := reader.ReadByte()
- if err != nil {
- return E.Cause(err, "read command")
- }
- destination, err := M.SocksaddrSerializer.ReadAddrPort(reader)
- if err != nil {
- return E.Cause(err, "read destination")
- }
- if reader.Buffered() > 0 {
- buffer := buf.NewSize(reader.Buffered())
- _, err = buffer.ReadFullFrom(reader, buffer.Len())
- if err != nil {
- return err
- }
- conn = bufio.NewCachedConn(conn, buffer)
- }
- switch command {
- case CommandTCP:
- handler.NewConnectionEx(ctx, conn, source, destination, nil)
- case CommandUDP:
- handler.NewPacketConnectionEx(ctx, &PacketConn{Conn: conn}, source, destination, nil)
- default:
- return E.New("unknown command ", command)
- }
- return nil
- }
- func smuxConfig() *smux.Config {
- config := smux.DefaultConfig()
- config.KeepAliveDisabled = true
- return config
- }
|