@@ -13,13 +13,20 @@ import (
13
13
)
14
14
15
15
var (
16
- reservedHost = "coder"
17
- credential = "coder"
16
+ // reservedAddress is a magic address that's used exclusively
17
+ // for proxying via Coder. We don't proxy all TURN connections,
18
+ // because that'd exclude the possibility of a customer using
19
+ // their own TURN server.
20
+ reservedAddress = "127.0.0.1:12345"
21
+ credential = "coder"
22
+ localhost = & net.TCPAddr {
23
+ IP : net .IPv4 (127 , 0 , 0 , 1 ),
24
+ }
18
25
19
26
// Proxy is a an ICE Server that uses a special hostname
20
27
// to indicate traffic should be proxied.
21
28
Proxy = webrtc.ICEServer {
22
- URLs : []string {"turns:" + reservedHost },
29
+ URLs : []string {"turns:" + reservedAddress },
23
30
Username : "coder" ,
24
31
Credential : credential ,
25
32
}
@@ -29,14 +36,35 @@ var (
29
36
// The relay address is used to broadcast the location of an accepted connection.
30
37
func New (relayAddress * turn.RelayAddressGeneratorStatic ) (* Server , error ) {
31
38
if relayAddress == nil {
32
- // Default to localhost.
39
+ ip := ""
40
+ addrs , err := net .InterfaceAddrs ()
41
+ if err != nil {
42
+ return nil , xerrors .Errorf ("find interface addrs: %w" , err )
43
+ }
44
+ // Try to find the localhost IP address.
45
+ // It will generally be 127.0.0.1, but
46
+ // search to be sure!
47
+ for _ , address := range addrs {
48
+ ipNet , ok := address .(* net.IPNet )
49
+ if ! ok {
50
+ continue
51
+ }
52
+ if ! ipNet .IP .IsLoopback () {
53
+ continue
54
+ }
55
+ ip = ipNet .IP .String ()
56
+ break
57
+ }
58
+ if ip == "" {
59
+ ip = "127.0.0.1"
60
+ }
33
61
relayAddress = & turn.RelayAddressGeneratorStatic {
34
- RelayAddress : net.IP { 127 , 0 , 0 , 1 } ,
35
- Address : "127.0.0.1" ,
62
+ RelayAddress : net .ParseIP ( ip ) ,
63
+ Address : ip ,
36
64
}
37
65
}
38
66
logger := logging .NewDefaultLoggerFactory ()
39
- logger .DefaultLogLevel = logging .LogLevelDisabled
67
+ logger .DefaultLogLevel = logging .LogLevelDebug
40
68
server := & Server {
41
69
conns : make (chan net.Conn , 1 ),
42
70
closed : make (chan struct {}),
@@ -47,6 +75,8 @@ func New(relayAddress *turn.RelayAddressGeneratorStatic) (*Server, error) {
47
75
var err error
48
76
server .turn , err = turn .NewServer (turn.ServerConfig {
49
77
AuthHandler : func (username , realm string , srcAddr net.Addr ) (key []byte , ok bool ) {
78
+ // TURN connections require credentials. It's not important
79
+ // for our use-case, because our listener is entirely in-memory.
50
80
return turn .GenerateAuthKey (Proxy .Username , "" , credential ), true
51
81
},
52
82
ListenerConfigs : []turn.ListenerConfig {{
@@ -62,33 +92,6 @@ func New(relayAddress *turn.RelayAddressGeneratorStatic) (*Server, error) {
62
92
return server , nil
63
93
}
64
94
65
- // ProxyDialer accepts a proxy function that's called when the connection
66
- // address matches the reserved host in the "Proxy" ICE server.
67
- //
68
- // This should be passed to WebRTC connections as an ICE dialer.
69
- func ProxyDialer (proxyFunc func () (c net.Conn , err error )) proxy.Dialer {
70
- return dialer (func (network , addr string ) (net.Conn , error ) {
71
- host , _ , err := net .SplitHostPort (addr )
72
- if err != nil {
73
- return nil , err
74
- }
75
- if host != reservedHost {
76
- return proxy .Direct .Dial (network , addr )
77
- }
78
- netConn , err := proxyFunc ()
79
- if err != nil {
80
- return nil , err
81
- }
82
- return & Conn {
83
- localAddress : & net.TCPAddr {
84
- IP : net .IPv4 (127 , 0 , 0 , 1 ),
85
- },
86
- closed : make (chan struct {}),
87
- Conn : netConn ,
88
- }, nil
89
- })
90
- }
91
-
92
95
// Server accepts and connects TURN allocations.
93
96
//
94
97
// This is a thin wrapper around pion/turn that pipes
@@ -105,10 +108,14 @@ type Server struct {
105
108
// Accept consumes a new connection into the TURN server.
106
109
// A unique remote address must exist per-connection.
107
110
// pion/turn indexes allocations based on the address.
108
- func (s * Server ) Accept (nc net.Conn , remoteAddress * net.TCPAddr ) * Conn {
111
+ func (s * Server ) Accept (nc net.Conn , remoteAddress , localAddress * net.TCPAddr ) * Conn {
112
+ if localAddress == nil {
113
+ localAddress = localhost
114
+ }
109
115
conn := & Conn {
110
116
Conn : nc ,
111
117
remoteAddress : remoteAddress ,
118
+ localAddress : localAddress ,
112
119
closed : make (chan struct {}),
113
120
}
114
121
s .conns <- conn
@@ -181,16 +188,38 @@ func (c *Conn) Closed() <-chan struct{} {
181
188
}
182
189
183
190
func (c * Conn ) Close () error {
191
+ err := c .Conn .Close ()
184
192
select {
185
193
case <- c .closed :
186
194
default :
187
195
close (c .closed )
188
196
}
189
- return c . Conn . Close ()
197
+ return err
190
198
}
191
199
192
200
type dialer func (network , addr string ) (c net.Conn , err error )
193
201
194
202
func (d dialer ) Dial (network , addr string ) (c net.Conn , err error ) {
195
203
return d (network , addr )
196
204
}
205
+
206
+ // ProxyDialer accepts a proxy function that's called when the connection
207
+ // address matches the reserved host in the "Proxy" ICE server.
208
+ //
209
+ // This should be passed to WebRTC connections as an ICE dialer.
210
+ func ProxyDialer (proxyFunc func () (c net.Conn , err error )) proxy.Dialer {
211
+ return dialer (func (network , addr string ) (net.Conn , error ) {
212
+ if addr != reservedAddress {
213
+ return proxy .Direct .Dial (network , addr )
214
+ }
215
+ netConn , err := proxyFunc ()
216
+ if err != nil {
217
+ return nil , err
218
+ }
219
+ return & Conn {
220
+ localAddress : localhost ,
221
+ closed : make (chan struct {}),
222
+ Conn : netConn ,
223
+ }, nil
224
+ })
225
+ }
0 commit comments