github.com/MerlinKodo/sing-tun@v0.1.15/stack_lwip.go (about) 1 //go:build with_lwip 2 3 package tun 4 5 import ( 6 "context" 7 "net" 8 "net/netip" 9 "os" 10 11 lwip "github.com/sagernet/go-tun2socks/core" 12 "github.com/sagernet/sing/common" 13 "github.com/sagernet/sing/common/buf" 14 M "github.com/sagernet/sing/common/metadata" 15 N "github.com/sagernet/sing/common/network" 16 "github.com/sagernet/sing/common/udpnat" 17 ) 18 19 type LWIP struct { 20 ctx context.Context 21 tun Tun 22 tunMtu uint32 23 udpTimeout int64 24 handler Handler 25 stack lwip.LWIPStack 26 udpNat *udpnat.Service[netip.AddrPort] 27 } 28 29 func NewLWIP( 30 options StackOptions, 31 ) (Stack, error) { 32 return &LWIP{ 33 ctx: options.Context, 34 tun: options.Tun, 35 tunMtu: options.MTU, 36 handler: options.Handler, 37 stack: lwip.NewLWIPStack(), 38 udpNat: udpnat.New[netip.AddrPort](options.UDPTimeout, options.Handler), 39 }, nil 40 } 41 42 func (l *LWIP) Start() error { 43 lwip.RegisterTCPConnHandler(l) 44 lwip.RegisterUDPConnHandler(l) 45 lwip.RegisterOutputFn(l.tun.Write) 46 go l.loopIn() 47 return nil 48 } 49 50 func (l *LWIP) loopIn() { 51 if winTun, isWintun := l.tun.(WinTun); isWintun { 52 l.loopInWintun(winTun) 53 return 54 } 55 buffer := make([]byte, int(l.tunMtu)+PacketOffset) 56 for { 57 n, err := l.tun.Read(buffer) 58 if err != nil { 59 return 60 } 61 _, err = l.stack.Write(buffer[PacketOffset:n]) 62 if err != nil { 63 if err.Error() == "stack closed" { 64 return 65 } 66 l.handler.NewError(context.Background(), err) 67 } 68 } 69 } 70 71 func (l *LWIP) loopInWintun(tun WinTun) { 72 for { 73 packet, release, err := tun.ReadPacket() 74 if err != nil { 75 return 76 } 77 _, err = l.stack.Write(packet) 78 release() 79 if err != nil { 80 if err.Error() == "stack closed" { 81 return 82 } 83 l.handler.NewError(context.Background(), err) 84 } 85 } 86 } 87 88 func (l *LWIP) Close() error { 89 lwip.RegisterTCPConnHandler(nil) 90 lwip.RegisterUDPConnHandler(nil) 91 lwip.RegisterOutputFn(func(bytes []byte) (int, error) { 92 return 0, os.ErrClosed 93 }) 94 return l.stack.Close() 95 } 96 97 func (l *LWIP) Handle(conn net.Conn) error { 98 lAddr := conn.LocalAddr() 99 rAddr := conn.RemoteAddr() 100 if lAddr == nil || rAddr == nil { 101 conn.Close() 102 return nil 103 } 104 go func() { 105 var metadata M.Metadata 106 metadata.Source = M.SocksaddrFromNet(lAddr) 107 metadata.Destination = M.SocksaddrFromNet(rAddr) 108 hErr := l.handler.NewConnection(l.ctx, conn, metadata) 109 if hErr != nil { 110 conn.(lwip.TCPConn).Abort() 111 } 112 }() 113 return nil 114 } 115 116 func (l *LWIP) ReceiveTo(conn lwip.UDPConn, data []byte, addr M.Socksaddr) error { 117 var upstreamMetadata M.Metadata 118 upstreamMetadata.Source = conn.LocalAddr() 119 upstreamMetadata.Destination = addr 120 121 l.udpNat.NewPacket( 122 l.ctx, 123 upstreamMetadata.Source.AddrPort(), 124 buf.As(data).ToOwned(), 125 upstreamMetadata, 126 func(natConn N.PacketConn) N.PacketWriter { 127 return &LWIPUDPBackWriter{conn} 128 }, 129 ) 130 return nil 131 } 132 133 type LWIPUDPBackWriter struct { 134 conn lwip.UDPConn 135 } 136 137 func (w *LWIPUDPBackWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { 138 defer buffer.Release() 139 return common.Error(w.conn.WriteFrom(buffer.Bytes(), destination)) 140 } 141 142 func (w *LWIPUDPBackWriter) Close() error { 143 return w.conn.Close() 144 }