@@ -9,12 +9,14 @@ package turn
9
9
import (
10
10
"fmt"
11
11
"net"
12
+ "syscall"
12
13
"testing"
13
14
"time"
14
15
15
16
"github.com/pion/logging"
16
17
"github.com/pion/transport/v3/test"
17
18
"github.com/pion/transport/v3/vnet"
19
+ "github.com/pion/turn/v3/internal/allocation"
18
20
"github.com/pion/turn/v3/internal/proto"
19
21
"github.com/stretchr/testify/assert"
20
22
)
@@ -119,6 +121,93 @@ func TestServer(t *testing.T) {
119
121
assert .NoError (t , server .Close ())
120
122
})
121
123
124
+ t .Run ("Delete allocation on spontaneous TCP close" , func (t * testing.T ) {
125
+ // Test whether allocation is properly deleted when client spontaneously closes the
126
+ // TCP connection underlying it
127
+ tcpListener , err := net .Listen ("tcp4" , "127.0.0.1:3478" )
128
+ assert .NoError (t , err )
129
+
130
+ server , err := NewServer (ServerConfig {
131
+ AuthHandler : func (username , realm string , srcAddr net.Addr ) (key []byte , ok bool ) {
132
+ if pw , ok := credMap [username ]; ok {
133
+ return pw , true
134
+ }
135
+ return nil , false
136
+ },
137
+ ListenerConfigs : []ListenerConfig {
138
+ {
139
+ Listener : tcpListener ,
140
+ RelayAddressGenerator : & RelayAddressGeneratorStatic {
141
+ RelayAddress : net .ParseIP ("127.0.0.1" ),
142
+ Address : "127.0.0.1" ,
143
+ },
144
+ },
145
+ },
146
+ Realm : "pion.ly" ,
147
+ LoggerFactory : loggerFactory ,
148
+ })
149
+ assert .NoError (t , err )
150
+
151
+ // make sure we can reuse the client port
152
+ dialer := & net.Dialer {
153
+ Control : func (network , address string , conn syscall.RawConn ) error {
154
+ return conn .Control (func (descriptor uintptr ) {
155
+ _ = syscall .SetsockoptInt (int (descriptor ), syscall .SOL_SOCKET , syscall .SO_REUSEADDR , 1 )
156
+ })
157
+ },
158
+ }
159
+ conn , err := dialer .Dial ("tcp" , "127.0.0.1:3478" )
160
+ assert .NoError (t , err )
161
+
162
+ clientAddr := conn .LocalAddr ()
163
+
164
+ serverAddr , err := net .ResolveTCPAddr ("tcp4" , "127.0.0.1:3478" )
165
+ assert .NoError (t , err )
166
+
167
+ client , err := NewClient (& ClientConfig {
168
+ STUNServerAddr : serverAddr .String (),
169
+ TURNServerAddr : serverAddr .String (),
170
+ Conn : NewSTUNConn (conn ),
171
+ Username : "user" ,
172
+ Password : "pass" ,
173
+ Realm : "pion.ly" ,
174
+ LoggerFactory : loggerFactory ,
175
+ })
176
+ assert .NoError (t , err )
177
+ assert .NoError (t , client .Listen ())
178
+
179
+ _ , err = client .SendBindingRequestTo (& net.UDPAddr {IP : net .IPv4 (127 , 0 , 0 , 1 ), Port : 3478 })
180
+ assert .NoError (t , err , "should succeed" )
181
+
182
+ relayConn , err := client .Allocate ()
183
+ assert .NoError (t , err )
184
+ assert .NotNil (t , relayConn )
185
+
186
+ fiveTuple := & allocation.FiveTuple {
187
+ Protocol : allocation .UDP , // Fixed UDP
188
+ SrcAddr : clientAddr ,
189
+ DstAddr : serverAddr ,
190
+ }
191
+ // Allocation exists
192
+ assert .Len (t , server .allocationManagers , 1 )
193
+ assert .NotNil (t , server .allocationManagers [0 ].GetAllocation (fiveTuple ))
194
+
195
+ // client.Close()
196
+ // This should properly close the client and delete the allocation on the server
197
+ assert .NoError (t , conn .Close ())
198
+
199
+ // Let connection to properly close
200
+ time .Sleep (100 * time .Millisecond )
201
+ // to we still have the allocation on the server?
202
+ assert .Nil (t , server .allocationManagers [0 ].GetAllocation (fiveTuple ))
203
+
204
+ client .Close ()
205
+ // This should err: client connection has gone so we cannot send the Refresh(0)
206
+ // message
207
+ assert .Error (t , relayConn .Close ())
208
+ assert .NoError (t , server .Close ())
209
+ })
210
+
122
211
t .Run ("Filter on client address and peer IP" , func (t * testing.T ) {
123
212
udpListener , err := net .ListenPacket ("udp4" , "0.0.0.0:3478" )
124
213
assert .NoError (t , err )
0 commit comments