@@ -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,32 @@ 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 := "127.0.0.1"
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
+ }
33
58
relayAddress = & turn.RelayAddressGeneratorStatic {
34
- RelayAddress : net.IP { 127 , 0 , 0 , 1 } ,
35
- Address : "127.0.0.1" ,
59
+ RelayAddress : net .ParseIP ( ip ) ,
60
+ Address : ip ,
36
61
}
37
62
}
38
63
logger := logging .NewDefaultLoggerFactory ()
39
- logger .DefaultLogLevel = logging .LogLevelDisabled
64
+ logger .DefaultLogLevel = logging .LogLevelDebug
40
65
server := & Server {
41
66
conns : make (chan net.Conn , 1 ),
42
67
closed : make (chan struct {}),
@@ -47,6 +72,8 @@ func New(relayAddress *turn.RelayAddressGeneratorStatic) (*Server, error) {
47
72
var err error
48
73
server .turn , err = turn .NewServer (turn.ServerConfig {
49
74
AuthHandler : func (username , realm string , srcAddr net.Addr ) (key []byte , ok bool ) {
75
+ // TURN connections require credentials. It's not important
76
+ // for our use-case, because our listener is entirely in-memory.
50
77
return turn .GenerateAuthKey (Proxy .Username , "" , credential ), true
51
78
},
52
79
ListenerConfigs : []turn.ListenerConfig {{
@@ -62,33 +89,6 @@ func New(relayAddress *turn.RelayAddressGeneratorStatic) (*Server, error) {
62
89
return server , nil
63
90
}
64
91
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
92
// Server accepts and connects TURN allocations.
93
93
//
94
94
// This is a thin wrapper around pion/turn that pipes
@@ -105,10 +105,14 @@ type Server struct {
105
105
// Accept consumes a new connection into the TURN server.
106
106
// A unique remote address must exist per-connection.
107
107
// pion/turn indexes allocations based on the address.
108
- func (s * Server ) Accept (nc net.Conn , remoteAddress * net.TCPAddr ) * Conn {
108
+ func (s * Server ) Accept (nc net.Conn , remoteAddress , localAddress * net.TCPAddr ) * Conn {
109
+ if localAddress == nil {
110
+ localAddress = localhost
111
+ }
109
112
conn := & Conn {
110
113
Conn : nc ,
111
114
remoteAddress : remoteAddress ,
115
+ localAddress : localAddress ,
112
116
closed : make (chan struct {}),
113
117
}
114
118
s .conns <- conn
@@ -181,16 +185,38 @@ func (c *Conn) Closed() <-chan struct{} {
181
185
}
182
186
183
187
func (c * Conn ) Close () error {
188
+ err := c .Conn .Close ()
184
189
select {
185
190
case <- c .closed :
186
191
default :
187
192
close (c .closed )
188
193
}
189
- return c . Conn . Close ()
194
+ return err
190
195
}
191
196
192
197
type dialer func (network , addr string ) (c net.Conn , err error )
193
198
194
199
func (d dialer ) Dial (network , addr string ) (c net.Conn , err error ) {
195
200
return d (network , addr )
196
201
}
202
+
203
+ // ProxyDialer accepts a proxy function that's called when the connection
204
+ // address matches the reserved host in the "Proxy" ICE server.
205
+ //
206
+ // This should be passed to WebRTC connections as an ICE dialer.
207
+ func ProxyDialer (proxyFunc func () (c net.Conn , err error )) proxy.Dialer {
208
+ return dialer (func (network , addr string ) (net.Conn , error ) {
209
+ if addr != reservedAddress {
210
+ return proxy .Direct .Dial (network , addr )
211
+ }
212
+ netConn , err := proxyFunc ()
213
+ if err != nil {
214
+ return nil , err
215
+ }
216
+ return & Conn {
217
+ localAddress : localhost ,
218
+ closed : make (chan struct {}),
219
+ Conn : netConn ,
220
+ }, nil
221
+ })
222
+ }
0 commit comments