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