Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit d11dc9f

Browse files
committed
Test sending data
1 parent 63fbaa3 commit d11dc9f

File tree

5 files changed

+175
-40
lines changed

5 files changed

+175
-40
lines changed

wsnet/conn.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package wsnet
2+
3+
import (
4+
"net"
5+
"time"
6+
7+
"github.com/pion/datachannel"
8+
)
9+
10+
type conn struct {
11+
addr *net.UnixAddr
12+
rw datachannel.ReadWriteCloser
13+
}
14+
15+
func (c *conn) Read(b []byte) (n int, err error) {
16+
return c.rw.Read(b)
17+
}
18+
19+
func (c *conn) Write(b []byte) (n int, err error) {
20+
return c.rw.Write(b)
21+
}
22+
23+
func (c *conn) Close() error {
24+
return c.rw.Close()
25+
}
26+
27+
func (c *conn) LocalAddr() net.Addr {
28+
return c.addr
29+
}
30+
31+
func (c *conn) RemoteAddr() net.Addr {
32+
return c.addr
33+
}
34+
35+
func (c *conn) SetDeadline(t time.Time) error {
36+
return nil
37+
}
38+
39+
func (c *conn) SetReadDeadline(t time.Time) error {
40+
return nil
41+
}
42+
43+
func (c *conn) SetWriteDeadline(t time.Time) error {
44+
return nil
45+
}

wsnet/dial.go

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net"
1010

1111
"cdr.dev/coder-cli/coder-sdk"
12+
"github.com/pion/datachannel"
1213
"github.com/pion/webrtc/v3"
1314
"nhooyr.io/websocket"
1415
)
@@ -22,7 +23,9 @@ type DialConfig struct {
2223
//
2324
func Dial(ctx context.Context, broker string, config *DialConfig) (*Dialer, error) {
2425
if config == nil {
25-
config = &DialConfig{}
26+
config = &DialConfig{
27+
ICEServers: []webrtc.ICEServer{},
28+
}
2629
}
2730

2831
conn, resp, err := websocket.Dial(ctx, broker, nil)
@@ -92,15 +95,17 @@ func Dial(ctx context.Context, broker string, config *DialConfig) (*Dialer, erro
9295
_ = conn.Close(websocket.StatusAbnormalClosure, "timeout")
9396
return
9497
}
98+
dialer.ctrlrw, _ = ctrl.Detach()
9599
_ = conn.Close(websocket.StatusNormalClosure, "connected")
96100
}()
97101

98102
return dialer, dialer.negotiate(nconn)
99103
}
100104

101105
type Dialer struct {
102-
ctrl *webrtc.DataChannel
103-
rtc *webrtc.PeerConnection
106+
ctrl *webrtc.DataChannel
107+
ctrlrw datachannel.ReadWriteCloser
108+
rtc *webrtc.PeerConnection
104109
}
105110

106111
func (d *Dialer) negotiate(nconn net.Conn) (err error) {
@@ -142,14 +147,45 @@ func (d *Dialer) negotiate(nconn net.Conn) (err error) {
142147
return nil
143148
}
144149

150+
// Close closes the RTC connection.
151+
// All data channels dialed will be closed.
145152
func (d *Dialer) Close() error {
146-
return nil
153+
return d.rtc.Close()
147154
}
148155

156+
// Ping sends a ping through the control channel.
149157
func (d *Dialer) Ping(ctx context.Context) error {
150-
return nil
158+
_, err := d.ctrlrw.Write([]byte{'a'})
159+
if err != nil {
160+
return fmt.Errorf("write: %w", err)
161+
}
162+
b := make([]byte, 4)
163+
_, err = d.ctrlrw.Read(b)
164+
return err
151165
}
152166

167+
// DialContext dials the network and address on the remote listener.
153168
func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
154-
return nil, nil
169+
dc, err := d.rtc.CreateDataChannel("proxy", &webrtc.DataChannelInit{
170+
Ordered: boolPtr(network != "udp"),
171+
Protocol: stringPtr(fmt.Sprintf("%s:%s", network, address)),
172+
})
173+
if err != nil {
174+
return nil, fmt.Errorf("create data channel: %w", err)
175+
}
176+
err = waitForDataChannelOpen(ctx, dc)
177+
if err != nil {
178+
return nil, fmt.Errorf("wait for open: %w", err)
179+
}
180+
rw, err := dc.Detach()
181+
if err != nil {
182+
return nil, fmt.Errorf("detach: %w", err)
183+
}
184+
return &conn{
185+
addr: &net.UnixAddr{
186+
Name: address,
187+
Net: network,
188+
},
189+
rw: rw,
190+
}, nil
155191
}

wsnet/dial_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package wsnet
33
import (
44
"context"
55
"errors"
6+
"fmt"
7+
"testing"
68

79
"github.com/pion/webrtc/v3"
810
)
@@ -39,3 +41,48 @@ func ExampleDial_basic() {
3941
defer conn.Close()
4042
// You now have access to the proxied remote port in `conn`.
4143
}
44+
45+
func TestDial(t *testing.T) {
46+
t.Run("Ping", func(t *testing.T) {
47+
connectAddr, listenAddr := createDumbBroker(t)
48+
_, err := Listen(context.Background(), listenAddr)
49+
if err != nil {
50+
t.Error(err)
51+
}
52+
dialer, err := Dial(context.Background(), connectAddr, nil)
53+
if err != nil {
54+
t.Error(err)
55+
}
56+
err = dialer.Ping(context.Background())
57+
if err != nil {
58+
t.Error(err)
59+
}
60+
61+
})
62+
63+
t.Run("Pipe", func(t *testing.T) {
64+
connectAddr, listenAddr := createDumbBroker(t)
65+
listener, err := Listen(context.Background(), listenAddr)
66+
if err != nil {
67+
t.Error(err)
68+
}
69+
dialer, err := Dial(context.Background(), connectAddr, nil)
70+
if err != nil {
71+
t.Error(err)
72+
}
73+
go func() {
74+
conn, err := dialer.DialContext(context.Background(), "tcp", "localhost:40000")
75+
if err != nil {
76+
t.Error(err)
77+
}
78+
conn.Write([]byte("hello"))
79+
}()
80+
conn, err := listener.Accept()
81+
if err != nil {
82+
t.Error(err)
83+
}
84+
b := make([]byte, 5)
85+
_, _ = conn.Read(b)
86+
fmt.Printf("WE LEGIT GOT IT! %s\n", b)
87+
})
88+
}

wsnet/listen.go

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import (
55
"encoding/json"
66
"fmt"
77
"net"
8+
"strings"
89

910
"cdr.dev/coder-cli/coder-sdk"
1011
"github.com/hashicorp/yamux"
11-
"github.com/pion/datachannel"
1212
"github.com/pion/webrtc/v3"
1313
"nhooyr.io/websocket"
1414
)
@@ -149,15 +149,43 @@ func (l *listener) negotiate(conn net.Conn) {
149149
}
150150

151151
func (l *listener) handle(dc *webrtc.DataChannel) {
152-
// if dc.Protocol() == controlChannel {
153-
// return
154-
// }
155-
156-
fmt.Printf("GOT CHANNEL %s\n", dc.Protocol())
152+
if dc.Protocol() == controlChannel {
153+
// The control channel handles pings.
154+
dc.OnOpen(func() {
155+
rw, err := dc.Detach()
156+
if err != nil {
157+
return
158+
}
159+
// We'll read and write back a single byte for ping/pongin'.
160+
d := make([]byte, 1)
161+
for {
162+
_, err = rw.Read(d)
163+
if err != nil {
164+
continue
165+
}
166+
_, _ = rw.Write(d)
167+
}
168+
})
169+
return
170+
}
157171

158-
// dc.OnOpen(func() {
159-
// rw, err := dc.Detach()
160-
// })
172+
dc.OnOpen(func() {
173+
rw, err := dc.Detach()
174+
if err != nil {
175+
return
176+
}
177+
parts := strings.SplitN(dc.Protocol(), ":", 2)
178+
network := parts[0]
179+
addr := parts[1]
180+
181+
l.conns <- &conn{
182+
addr: &net.UnixAddr{
183+
Name: addr,
184+
Net: network,
185+
},
186+
rw: rw,
187+
}
188+
})
161189
}
162190

163191
// Accept accepts a new connection.
@@ -176,28 +204,3 @@ func (l *listener) Close() error {
176204
func (l *listener) Addr() net.Addr {
177205
return nil
178206
}
179-
180-
type dataChannelConn struct {
181-
rw datachannel.ReadWriteCloser
182-
localAddr net.Addr
183-
}
184-
185-
func (d *dataChannelConn) Read(b []byte) (n int, err error) {
186-
return d.rw.Read(b)
187-
}
188-
189-
func (d *dataChannelConn) Write(b []byte) (n int, err error) {
190-
return d.rw.Write(b)
191-
}
192-
193-
func (d *dataChannelConn) Close() error {
194-
return d.Close()
195-
}
196-
197-
func (d *dataChannelConn) LocalAddr() net.Addr {
198-
return d.localAddr
199-
}
200-
201-
func (d *dataChannelConn) RemoteAddr() net.Addr {
202-
return nil
203-
}

wsnet/rtc.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ import (
2020
var (
2121
ErrMismatchedProtocol = errors.New("mismatched protocols")
2222
ErrInvalidCredentials = errors.New("invalid credentials")
23+
24+
DefaultPublicSTUN = webrtc.ICEServer{
25+
URLs: []string{"stun:stun.l.google.com:19302"},
26+
}
2327
)
2428

2529
const (

0 commit comments

Comments
 (0)