diff options
Diffstat (limited to 'sockets.go')
-rw-r--r-- | sockets.go | 90 |
1 files changed, 26 insertions, 64 deletions
@@ -1,79 +1,41 @@ | |||
1 | package main | 1 | package main |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "context" | 4 | "fmt" |
5 | "io" | 5 | "io" |
6 | "log" | ||
7 | "net" | ||
8 | 6 | ||
9 | "github.com/gorilla/websocket" | 7 | "github.com/gorilla/websocket" |
10 | ) | 8 | ) |
11 | 9 | ||
12 | func wsReader(wsconn *websocket.Conn, out chan []byte, ctx context.Context) { | 10 | type WebsocketReadWriter struct { |
13 | for { | 11 | W *websocket.Conn |
14 | messageType, p, err := wsconn.ReadMessage() | ||
15 | if err != nil { | ||
16 | log.Printf("error: wsReader: %s", err) | ||
17 | return | ||
18 | } | ||
19 | if messageType != websocket.BinaryMessage { | ||
20 | log.Println("error: wsReader: only binary messages are supported") | ||
21 | continue | ||
22 | } | ||
23 | select { | ||
24 | case out <- p: | ||
25 | continue | ||
26 | case <-ctx.Done(): | ||
27 | return | ||
28 | } | ||
29 | } | ||
30 | } | 12 | } |
31 | 13 | ||
32 | func socketReader(proxyconn net.Conn, out chan []byte, ctx context.Context) { | 14 | func (w *WebsocketReadWriter) Read(p []byte) (int, error) { |
33 | for { | 15 | t, m, err := w.W.ReadMessage() |
34 | readBuffer := make([]byte, 2048) | 16 | if err != nil { |
35 | 17 | return 0, fmt.Errorf("error reading websocket: %w", err) | |
36 | i, err := proxyconn.Read(readBuffer) | 18 | } |
37 | if err != nil { | 19 | if t != websocket.BinaryMessage { |
38 | if err == io.EOF { | 20 | return 0, fmt.Errorf("error reading websocket: only binary messages are supported") |
39 | log.Println("info: socketReader: Disconnected") | 21 | } |
40 | } else { | 22 | if cap(p) < len(m) { |
41 | log.Printf("error: socketReader: %s", err) | 23 | return 0, fmt.Errorf("error reading websocket: outputbuffer too short for input") |
42 | } | 24 | } |
43 | return | 25 | if i := copy(p, m); i != len(m) { |
44 | } | 26 | return 0, fmt.Errorf("error reading websocket: copy failed %d of %d", i, len(m)) |
45 | |||
46 | select { | ||
47 | case out <- readBuffer[:i]: | ||
48 | continue | ||
49 | case <-ctx.Done(): | ||
50 | return | ||
51 | } | ||
52 | } | 27 | } |
28 | return len(m), nil | ||
53 | } | 29 | } |
54 | 30 | ||
55 | func serviceBoth(wsconn *websocket.Conn, proxyconn net.Conn, ctx context.Context) { | 31 | func (w *WebsocketReadWriter) Write(p []byte) (int, error) { |
56 | sc := make(chan []byte) | 32 | if err := w.W.WriteMessage(websocket.BinaryMessage, p); err != nil { |
57 | wsc := make(chan []byte) | 33 | return 0, fmt.Errorf("error writing websocket: %w", err) |
58 | |||
59 | go socketReader(proxyconn, sc, ctx) | ||
60 | go wsReader(wsconn, wsc, ctx) | ||
61 | |||
62 | for { | ||
63 | select { | ||
64 | case sd := <-sc: | ||
65 | if err := wsconn.WriteMessage(websocket.BinaryMessage, sd); err != nil { | ||
66 | log.Printf("error: serviceBoth: %s", err) | ||
67 | return | ||
68 | } | ||
69 | |||
70 | case wsd := <-wsc: | ||
71 | if _, err := proxyconn.Write(wsd); err != nil { | ||
72 | log.Printf("error: serviceBoth: %s", err) | ||
73 | return | ||
74 | } | ||
75 | case <-ctx.Done(): | ||
76 | return | ||
77 | } | ||
78 | } | 34 | } |
35 | return len(p), nil | ||
36 | } | ||
37 | |||
38 | func serviceBoth(dst io.Writer, src io.Reader, errc chan<- error) { | ||
39 | _, err := io.Copy(dst, src) | ||
40 | errc <- err | ||
79 | } | 41 | } |