@@ -16,18 +16,23 @@ import (
16
16
"github.com/sagernet/sing/common/pipe"
17
17
)
18
18
19
+ // Deprecated: Use N.UDPConnectionHandler instead.
20
+ //
21
+ //nolint:staticcheck
19
22
type Handler interface {
20
23
N.UDPConnectionHandler
21
24
E.Handler
22
25
}
23
26
24
27
type Service [K comparable ] struct {
25
- nat * cache.LruCache [K , * conn ]
26
- handler Handler
28
+ nat * cache.LruCache [K , * conn ]
29
+ handler Handler
30
+ handlerEx N.UDPConnectionHandlerEx
27
31
}
28
32
33
+ // Deprecated: Use NewEx instead.
29
34
func New [K comparable ](maxAge int64 , handler Handler ) * Service [K ] {
30
- return & Service [K ]{
35
+ service := & Service [K ]{
31
36
nat : cache .New (
32
37
cache.WithAge [K , * conn ](maxAge ),
33
38
cache .WithUpdateAgeOnGet [K , * conn ](),
@@ -37,11 +42,27 @@ func New[K comparable](maxAge int64, handler Handler) *Service[K] {
37
42
),
38
43
handler : handler ,
39
44
}
45
+ return service
46
+ }
47
+
48
+ func NewEx [K comparable ](maxAge int64 , handler N.UDPConnectionHandlerEx ) * Service [K ] {
49
+ service := & Service [K ]{
50
+ nat : cache .New (
51
+ cache.WithAge [K , * conn ](maxAge ),
52
+ cache .WithUpdateAgeOnGet [K , * conn ](),
53
+ cache.WithEvict [K , * conn ](func (key K , conn * conn ) {
54
+ conn .Close ()
55
+ }),
56
+ ),
57
+ handlerEx : handler ,
58
+ }
59
+ return service
40
60
}
41
61
42
62
func (s * Service [T ]) WriteIsThreadUnsafe () {
43
63
}
44
64
65
+ // Deprecated: don't use
45
66
func (s * Service [T ]) NewPacketDirect (ctx context.Context , key T , conn N.PacketConn , buffer * buf.Buffer , metadata M.Metadata ) {
46
67
s .NewContextPacket (ctx , key , buffer , metadata , func (natConn N.PacketConn ) (context.Context , N.PacketWriter ) {
47
68
return ctx , & DirectBackWriter {conn , natConn }
@@ -61,18 +82,30 @@ func (w *DirectBackWriter) Upstream() any {
61
82
return w .Source
62
83
}
63
84
85
+ // Deprecated: use NewPacketEx instead.
64
86
func (s * Service [T ]) NewPacket (ctx context.Context , key T , buffer * buf.Buffer , metadata M.Metadata , init func (natConn N.PacketConn ) N.PacketWriter ) {
65
87
s .NewContextPacket (ctx , key , buffer , metadata , func (natConn N.PacketConn ) (context.Context , N.PacketWriter ) {
66
88
return ctx , init (natConn )
67
89
})
68
90
}
69
91
92
+ func (s * Service [T ]) NewPacketEx (ctx context.Context , key T , buffer * buf.Buffer , source M.Socksaddr , destination M.Socksaddr , init func (natConn N.PacketConn ) N.PacketWriter ) {
93
+ s .NewContextPacketEx (ctx , key , buffer , source , destination , func (natConn N.PacketConn ) (context.Context , N.PacketWriter ) {
94
+ return ctx , init (natConn )
95
+ })
96
+ }
97
+
98
+ // Deprecated: Use NewPacketConnectionEx instead.
70
99
func (s * Service [T ]) NewContextPacket (ctx context.Context , key T , buffer * buf.Buffer , metadata M.Metadata , init func (natConn N.PacketConn ) (context.Context , N.PacketWriter )) {
100
+ s .NewContextPacketEx (ctx , key , buffer , metadata .Source , metadata .Destination , init )
101
+ }
102
+
103
+ func (s * Service [T ]) NewContextPacketEx (ctx context.Context , key T , buffer * buf.Buffer , source M.Socksaddr , destination M.Socksaddr , init func (natConn N.PacketConn ) (context.Context , N.PacketWriter )) {
71
104
c , loaded := s .nat .LoadOrStore (key , func () * conn {
72
105
c := & conn {
73
106
data : make (chan packet , 64 ),
74
- localAddr : metadata . Source ,
75
- remoteAddr : metadata . Destination ,
107
+ localAddr : source ,
108
+ remoteAddr : destination ,
76
109
readDeadline : pipe .MakeDeadline (),
77
110
}
78
111
c .ctx , c .cancel = common .ContextWithCancelCause (ctx )
@@ -81,26 +114,36 @@ func (s *Service[T]) NewContextPacket(ctx context.Context, key T, buffer *buf.Bu
81
114
if ! loaded {
82
115
ctx , c .source = init (c )
83
116
go func () {
84
- err := s .handler .NewPacketConnection (ctx , c , metadata )
85
- if err != nil {
86
- s .handler .NewError (ctx , err )
117
+ if s .handlerEx != nil {
118
+ s .handlerEx .NewPacketConnectionEx (ctx , c , source , destination , func (err error ) {
119
+ s .nat .Delete (key )
120
+ })
121
+ } else {
122
+ //nolint:staticcheck
123
+ err := s .handler .NewPacketConnection (ctx , c , M.Metadata {
124
+ Source : source ,
125
+ Destination : destination ,
126
+ })
127
+ if err != nil {
128
+ s .handler .NewError (ctx , err )
129
+ }
130
+ c .Close ()
131
+ s .nat .Delete (key )
87
132
}
88
- c .Close ()
89
- s .nat .Delete (key )
90
133
}()
91
134
} else {
92
- c .localAddr = metadata . Source
135
+ c .localAddr = source
93
136
}
94
137
if common .Done (c .ctx ) {
95
138
s .nat .Delete (key )
96
139
if ! common .Done (ctx ) {
97
- s .NewContextPacket (ctx , key , buffer , metadata , init )
140
+ s .NewContextPacketEx (ctx , key , buffer , source , destination , init )
98
141
}
99
142
return
100
143
}
101
144
c .data <- packet {
102
145
data : buffer ,
103
- destination : metadata . Destination ,
146
+ destination : destination ,
104
147
}
105
148
}
106
149
0 commit comments