11package tun
22
33import (
4+ "context"
45 "io"
56 "sync"
7+ "time"
68
79 "github.com/xtls/xray-core/common/buf"
10+ "github.com/xtls/xray-core/common/errors"
811 "github.com/xtls/xray-core/common/net"
912)
1013
14+ type packet struct {
15+ data []byte
16+ dest * net.Destination
17+ }
18+
1119// sub-handler specifically for udp connections under main handler
1220type udpConnectionHandler struct {
13- sync.Mutex
21+ sync.RWMutex
1422
1523 udpConns map [net.Destination ]* udpConn
1624
@@ -30,25 +38,44 @@ func newUdpConnectionHandler(handleConnection func(conn net.Conn, dest net.Desti
3038
3139// HandlePacket handles UDP packets coming from tun, to forward to the dispatcher
3240// this custom handler support FullCone NAT of returning packets, binding connection only by the source addr:port
33- func (u * udpConnectionHandler ) HandlePacket (src net.Destination , dst net.Destination , data []byte ) bool {
34- u .Lock ()
41+ func (u * udpConnectionHandler ) HandlePacket (src net.Destination , dst net.Destination , data []byte ) {
42+ u .RLock ()
3543 conn , found := u .udpConns [src ]
44+ if found {
45+ select {
46+ case conn .egress <- & packet {
47+ data : data ,
48+ dest : & dst ,
49+ }:
50+ default :
51+ errors .LogDebug (context .Background (), "drop udp with size " , len (data ), " to " , dst .NetAddr (), " original " , conn .dst .NetAddr (), " > queue full" )
52+ }
53+ u .RUnlock ()
54+ return
55+ }
56+ u .RUnlock ()
57+
58+ u .Lock ()
59+ defer u .Unlock ()
60+
61+ conn , found = u .udpConns [src ]
3662 if ! found {
37- egress := make (chan [] byte , 16 )
63+ egress := make (chan * packet , 1024 )
3864 conn = & udpConn {handler : u , egress : egress , src : src , dst : dst }
3965 u .udpConns [src ] = conn
4066
4167 go u .handleConnection (conn , dst )
4268 }
43- u .Unlock ()
4469
4570 // send packet data to the egress channel, if it has buffer, or discard
4671 select {
47- case conn .egress <- data :
72+ case conn .egress <- & packet {
73+ data : data ,
74+ dest : & dst ,
75+ }:
4876 default :
77+ errors .LogDebug (context .Background (), "drop udp with size " , len (data ), " to " , dst .NetAddr (), " original " , conn .dst .NetAddr (), " > queue full" )
4978 }
50-
51- return true
5279}
5380
5481func (u * udpConnectionHandler ) connectionFinished (src net.Destination ) {
@@ -63,27 +90,64 @@ func (u *udpConnectionHandler) connectionFinished(src net.Destination) {
6390
6491// udp connection abstraction
6592type udpConn struct {
66- net.Conn
67- buf.Writer
68-
6993 handler * udpConnectionHandler
7094
71- egress chan [] byte
95+ egress chan * packet
7296 src net.Destination
7397 dst net.Destination
7498}
7599
100+ func (c * udpConn ) ReadMultiBuffer () (buf.MultiBuffer , error ) {
101+ for {
102+ e , ok := <- c .egress
103+ if ! ok {
104+ return nil , io .EOF
105+ }
106+
107+ b := buf .New ()
108+
109+ _ , err := b .Write (e .data )
110+ if err != nil {
111+ errors .LogDebugInner (context .Background (), err , "drop udp with size " , len (e .data ), " to " , e .dest .NetAddr (), " original " , c .dst .NetAddr ())
112+ b .Release ()
113+ continue
114+ }
115+
116+ b .UDP = e .dest
117+
118+ return buf.MultiBuffer {b }, nil
119+ }
120+ }
121+
76122// Read packets from the connection
77123func (c * udpConn ) Read (p []byte ) (int , error ) {
78- data , ok := <- c .egress
124+ e , ok := <- c .egress
79125 if ! ok {
80126 return 0 , io .EOF
81127 }
82-
83- n := copy (p , data )
128+ n := copy (p , e .data )
129+ if n != len (e .data ) {
130+ return 0 , io .ErrShortBuffer
131+ }
84132 return n , nil
85133}
86134
135+ func (c * udpConn ) WriteMultiBuffer (mb buf.MultiBuffer ) error {
136+ for i , b := range mb {
137+ dst := c .dst
138+ if b .UDP != nil {
139+ dst = * b .UDP
140+ }
141+ err := c .handler .writePacket (b .Bytes (), dst , c .src )
142+ if err != nil {
143+ buf .ReleaseMulti (mb [i :])
144+ return err
145+ }
146+ b .Release ()
147+ }
148+ return nil
149+ }
150+
87151// Write returning packets back
88152func (c * udpConn ) Write (p []byte ) (int , error ) {
89153 // sending packets back mean sending payload with source/destination reversed
@@ -102,33 +166,21 @@ func (c *udpConn) Close() error {
102166}
103167
104168func (c * udpConn ) LocalAddr () net.Addr {
105- return & net. UDPAddr { IP : c .dst .Address . IP (), Port : int ( c . dst . Port . Value ())}
169+ return c .dst .RawNetAddr ()
106170}
107171
108172func (c * udpConn ) RemoteAddr () net.Addr {
109- return & net. UDPAddr { IP : c .src .Address . IP (), Port : int ( c . src . Port . Value ())}
173+ return c .src .RawNetAddr ()
110174}
111175
112- // Write returning packets back
113- func (c * udpConn ) WriteMultiBuffer (mb buf.MultiBuffer ) error {
114- for _ , b := range mb {
115- dst := c .dst
116- if b .UDP != nil {
117- dst = * b .UDP
118- }
119-
120- // validate address family matches between buffer packet and the connection
121- if dst .Address .Family () != c .dst .Address .Family () {
122- continue
123- }
176+ func (c * udpConn ) SetDeadline (t time.Time ) error {
177+ return nil
178+ }
124179
125- // sending packets back mean sending payload with source/destination reversed
126- err := c .handler .writePacket (b .Bytes (), dst , c .src )
127- if err != nil {
128- // udp doesn't guarantee delivery, so in any failure we just continue to the next packet
129- continue
130- }
131- }
180+ func (c * udpConn ) SetReadDeadline (t time.Time ) error {
181+ return nil
182+ }
132183
184+ func (c * udpConn ) SetWriteDeadline (t time.Time ) error {
133185 return nil
134186}
0 commit comments