@@ -2,8 +2,10 @@ package vpn
2
2
3
3
import (
4
4
"context"
5
+ "encoding/json"
5
6
"maps"
6
7
"net"
8
+ "net/http"
7
9
"net/netip"
8
10
"net/url"
9
11
"slices"
@@ -22,32 +24,51 @@ import (
22
24
"github.com/coder/quartz"
23
25
24
26
maputil "github.com/coder/coder/v2/coderd/util/maps"
27
+ "github.com/coder/coder/v2/codersdk"
25
28
"github.com/coder/coder/v2/tailnet"
26
29
"github.com/coder/coder/v2/tailnet/proto"
27
30
"github.com/coder/coder/v2/testutil"
28
31
)
29
32
30
33
func newFakeClient (ctx context.Context , t * testing.T ) * fakeClient {
31
34
return & fakeClient {
32
- t : t ,
33
- ctx : ctx ,
34
- ch : make (chan * fakeConn , 1 ),
35
+ t : t ,
36
+ ctx : ctx ,
37
+ connCh : make (chan * fakeConn , 1 ),
38
+ }
39
+ }
40
+
41
+ func newFakeClientWithOptsCh (ctx context.Context , t * testing.T ) * fakeClient {
42
+ return & fakeClient {
43
+ t : t ,
44
+ ctx : ctx ,
45
+ connCh : make (chan * fakeConn , 1 ),
46
+ optsCh : make (chan * Options , 1 ),
35
47
}
36
48
}
37
49
38
50
type fakeClient struct {
39
- t * testing.T
40
- ctx context.Context
41
- ch chan * fakeConn
51
+ t * testing.T
52
+ ctx context.Context
53
+ connCh chan * fakeConn
54
+ optsCh chan * Options // options will be written to this channel if it's not nil
42
55
}
43
56
44
57
var _ Client = (* fakeClient )(nil )
45
58
46
- func (f * fakeClient ) NewConn (context.Context , * url.URL , string , * Options ) (Conn , error ) {
59
+ func (f * fakeClient ) NewConn (_ context.Context , _ * url.URL , _ string , opts * Options ) (Conn , error ) {
60
+ if f .optsCh != nil {
61
+ select {
62
+ case <- f .ctx .Done ():
63
+ return nil , f .ctx .Err ()
64
+ case f .optsCh <- opts :
65
+ }
66
+ }
67
+
47
68
select {
48
69
case <- f .ctx .Done ():
49
70
return nil , f .ctx .Err ()
50
- case conn := <- f .ch :
71
+ case conn := <- f .connCh :
51
72
return conn , nil
52
73
}
53
74
}
@@ -134,37 +155,53 @@ func TestTunnel_StartStop(t *testing.T) {
134
155
t .Parallel ()
135
156
136
157
ctx := testutil .Context (t , testutil .WaitShort )
137
- client := newFakeClient (ctx , t )
158
+ client := newFakeClientWithOptsCh (ctx , t )
138
159
conn := newFakeConn (tailnet.WorkspaceUpdate {}, time.Time {})
139
160
140
161
_ , mgr := setupTunnel (t , ctx , client , quartz .NewMock (t ))
141
162
142
163
errCh := make (chan error , 1 )
143
164
var resp * TunnelMessage
144
165
// When: we start the tunnel
166
+ telemetry := codersdk.CoderDesktopTelemetry {
167
+ DeviceID : "device001" ,
168
+ DeviceOS : "macOS" ,
169
+ CoderDesktopVersion : "0.24.8" ,
170
+ }
171
+ telemetryJSON , err := json .Marshal (telemetry )
172
+ require .NoError (t , err )
145
173
go func () {
146
174
r , err := mgr .unaryRPC (ctx , & ManagerMessage {
147
175
Msg : & ManagerMessage_Start {
148
176
Start : & StartRequest {
149
177
TunnelFileDescriptor : 2 ,
150
- CoderUrl : "https://coder.example.com" ,
151
- ApiToken : "fakeToken" ,
178
+ // Use default value for TunnelUseSoftNetIsolation
179
+ CoderUrl : "https://coder.example.com" ,
180
+ ApiToken : "fakeToken" ,
152
181
Headers : []* StartRequest_Header {
153
182
{Name : "X-Test-Header" , Value : "test" },
154
183
},
155
- DeviceOs : "macOS" ,
156
- DeviceId : "device001" ,
157
- CoderDesktopVersion : "0.24.8" ,
184
+ DeviceOs : telemetry . DeviceOS ,
185
+ DeviceId : telemetry . DeviceID ,
186
+ CoderDesktopVersion : telemetry . CoderDesktopVersion ,
158
187
},
159
188
},
160
189
})
161
190
resp = r
162
191
errCh <- err
163
192
}()
164
- // Then: `NewConn` is called,
165
- testutil .RequireSend (ctx , t , client .ch , conn )
193
+
194
+ // Then: `NewConn` is called
195
+ opts := testutil .RequireReceive (ctx , t , client .optsCh )
196
+ require .Equal (t , http.Header {
197
+ "X-Test-Header" : {"test" },
198
+ codersdk .CoderDesktopTelemetryHeader : {string (telemetryJSON )},
199
+ }, opts .Headers )
200
+ require .False (t , opts .UseSoftNetIsolation ) // the default is false
201
+ testutil .RequireSend (ctx , t , client .connCh , conn )
202
+
166
203
// And: a response is received
167
- err : = testutil .TryReceive (ctx , t , errCh )
204
+ err = testutil .TryReceive (ctx , t , errCh )
168
205
require .NoError (t , err )
169
206
_ , ok := resp .Msg .(* TunnelMessage_Start )
170
207
require .True (t , ok )
@@ -197,7 +234,7 @@ func TestTunnel_PeerUpdate(t *testing.T) {
197
234
wsID1 := uuid.UUID {1 }
198
235
wsID2 := uuid.UUID {2 }
199
236
200
- client := newFakeClient (ctx , t )
237
+ client := newFakeClientWithOptsCh (ctx , t )
201
238
conn := newFakeConn (tailnet.WorkspaceUpdate {
202
239
UpsertedWorkspaces : []* tailnet.Workspace {
203
240
{
@@ -211,22 +248,28 @@ func TestTunnel_PeerUpdate(t *testing.T) {
211
248
212
249
tun , mgr := setupTunnel (t , ctx , client , quartz .NewMock (t ))
213
250
251
+ // When: we start the tunnel
214
252
errCh := make (chan error , 1 )
215
253
var resp * TunnelMessage
216
254
go func () {
217
255
r , err := mgr .unaryRPC (ctx , & ManagerMessage {
218
256
Msg : & ManagerMessage_Start {
219
257
Start : & StartRequest {
220
- TunnelFileDescriptor : 2 ,
221
- CoderUrl : "https://coder.example.com" ,
222
- ApiToken : "fakeToken" ,
258
+ TunnelFileDescriptor : 2 ,
259
+ TunnelUseSoftNetIsolation : true ,
260
+ CoderUrl : "https://coder.example.com" ,
261
+ ApiToken : "fakeToken" ,
223
262
},
224
263
},
225
264
})
226
265
resp = r
227
266
errCh <- err
228
267
}()
229
- testutil .RequireSend (ctx , t , client .ch , conn )
268
+
269
+ // Then: `NewConn` is called
270
+ opts := testutil .RequireReceive (ctx , t , client .optsCh )
271
+ require .True (t , opts .UseSoftNetIsolation )
272
+ testutil .RequireSend (ctx , t , client .connCh , conn )
230
273
err := testutil .TryReceive (ctx , t , errCh )
231
274
require .NoError (t , err )
232
275
_ , ok := resp .Msg .(* TunnelMessage_Start )
@@ -291,7 +334,7 @@ func TestTunnel_NetworkSettings(t *testing.T) {
291
334
resp = r
292
335
errCh <- err
293
336
}()
294
- testutil .RequireSend (ctx , t , client .ch , conn )
337
+ testutil .RequireSend (ctx , t , client .connCh , conn )
295
338
err := testutil .TryReceive (ctx , t , errCh )
296
339
require .NoError (t , err )
297
340
_ , ok := resp .Msg .(* TunnelMessage_Start )
@@ -432,7 +475,7 @@ func TestTunnel_sendAgentUpdate(t *testing.T) {
432
475
resp = r
433
476
errCh <- err
434
477
}()
435
- testutil .RequireSend (ctx , t , client .ch , conn )
478
+ testutil .RequireSend (ctx , t , client .connCh , conn )
436
479
err := testutil .TryReceive (ctx , t , errCh )
437
480
require .NoError (t , err )
438
481
_ , ok := resp .Msg .(* TunnelMessage_Start )
@@ -603,7 +646,7 @@ func TestTunnel_sendAgentUpdateReconnect(t *testing.T) {
603
646
resp = r
604
647
errCh <- err
605
648
}()
606
- testutil .RequireSend (ctx , t , client .ch , conn )
649
+ testutil .RequireSend (ctx , t , client .connCh , conn )
607
650
err := testutil .TryReceive (ctx , t , errCh )
608
651
require .NoError (t , err )
609
652
_ , ok := resp .Msg .(* TunnelMessage_Start )
@@ -703,7 +746,7 @@ func TestTunnel_sendAgentUpdateWorkspaceReconnect(t *testing.T) {
703
746
resp = r
704
747
errCh <- err
705
748
}()
706
- testutil .RequireSend (ctx , t , client .ch , conn )
749
+ testutil .RequireSend (ctx , t , client .connCh , conn )
707
750
err := testutil .TryReceive (ctx , t , errCh )
708
751
require .NoError (t , err )
709
752
_ , ok := resp .Msg .(* TunnelMessage_Start )
@@ -806,7 +849,7 @@ func TestTunnel_slowPing(t *testing.T) {
806
849
resp = r
807
850
errCh <- err
808
851
}()
809
- testutil .RequireSend (ctx , t , client .ch , conn )
852
+ testutil .RequireSend (ctx , t , client .connCh , conn )
810
853
err := testutil .TryReceive (ctx , t , errCh )
811
854
require .NoError (t , err )
812
855
_ , ok := resp .Msg .(* TunnelMessage_Start )
@@ -895,7 +938,7 @@ func TestTunnel_stopMidPing(t *testing.T) {
895
938
resp = r
896
939
errCh <- err
897
940
}()
898
- testutil .RequireSend (ctx , t , client .ch , conn )
941
+ testutil .RequireSend (ctx , t , client .connCh , conn )
899
942
err := testutil .TryReceive (ctx , t , errCh )
900
943
require .NoError (t , err )
901
944
_ , ok := resp .Msg .(* TunnelMessage_Start )
0 commit comments