-
Notifications
You must be signed in to change notification settings - Fork 7
/
bidirConnection.go
96 lines (84 loc) · 2.26 KB
/
bidirConnection.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package main
import (
"io"
"log"
"net"
"os"
"time"
"github.com/gorilla/websocket"
)
////////////////////////////////////////////////////////////////////////////////
// bidirConnection
////////////////////////////////////////////////////////////////////////////////
// bidirConnection implements the Runner interface
type bidirConnection struct {
tcpConn net.Conn
wsConn *websocket.Conn
tcpReadTimeout time.Duration
}
// NewBidirConnection to create an object to transfer data between the TCP socket and web connection in bidirectional way
func NewBidirConnection(tcpConn net.Conn, wsConn *websocket.Conn, tcpReadTimeout time.Duration) Runner {
return &bidirConnection{
tcpConn: tcpConn,
wsConn: wsConn,
tcpReadTimeout: tcpReadTimeout,
}
}
func (b *bidirConnection) sendTCPToWS() {
defer b.close()
data := make([]byte, BufferSize)
for {
if b.tcpReadTimeout > 0 {
b.tcpConn.SetReadDeadline(time.Now().Add(b.tcpReadTimeout))
}
readSize, err := b.tcpConn.Read(data)
if err != nil && !os.IsTimeout(err) {
if err != io.EOF {
log.Printf("TCPToWS - Error while reading from TCP: %s", err)
}
return
}
if err := b.wsConn.WriteMessage(websocket.BinaryMessage, data[:readSize]); err != nil {
log.Printf("TCPToWS - Error while writing to WS: %s", err)
return
}
}
}
func (b *bidirConnection) sendWSToTCP() {
defer b.close()
data := make([]byte, BufferSize)
for {
messageType, wsReader, err := b.wsConn.NextReader()
if err != nil {
log.Printf("WSToTCP - Error while reading from WS: %s", err)
return
}
if messageType != websocket.BinaryMessage {
log.Printf("WSToTCP - Got wrong message type from WS: %d", messageType)
return
}
for {
readSize, err := wsReader.Read(data)
if err != nil {
if err != io.EOF {
log.Printf("WSToTCP - Error while reading from WS: %s", err)
}
break
}
if _, err := b.tcpConn.Write(data[:readSize]); err != nil {
log.Printf("WSToTCP - Error while writing to TCP: %s", err)
return
}
}
}
}
func (b *bidirConnection) Run() error {
go b.sendTCPToWS()
b.sendWSToTCP()
return nil
}
func (b *bidirConnection) close() {
b.wsConn.WriteControl(websocket.CloseMessage, []byte{}, time.Now().Add(time.Second))
b.wsConn.Close()
b.tcpConn.Close()
}