mirror of https://github.com/elisescu/tty-share
Add support for TCP tunneling
Tunnel a TCP connection from the local client side to the remote server side. This, of course, works only for the command line client, and not the web browser client.pull/62/head
parent
2663a880de
commit
e09a0c802e
@ -0,0 +1,64 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type TunInitMsg struct {
|
||||
Address string
|
||||
}
|
||||
|
||||
type WSConnReadWriteCloser struct {
|
||||
WsConn *websocket.Conn
|
||||
reader io.Reader
|
||||
}
|
||||
|
||||
func (conn *WSConnReadWriteCloser) Read(p []byte) (n int, err error) {
|
||||
// Weird method here, as we need to do a few things:
|
||||
// - re-use the WS reader between different calls of this function. If the existing reader
|
||||
// has no more data, then get another reader (NextReader())
|
||||
// - if we get a CloseAbnormalClosure, or CloseGoingAway error message from WS, we need to
|
||||
// transform that into a io.EOF, otherwise yamux will complain. We use yamux on top of this
|
||||
// reader interface, in order to multiplex multiple streams
|
||||
// More here:
|
||||
// https://github.com/hashicorp/yamux/blob/574fd304fd659b0dfdd79e221f4e34f6b7cd9ed2/session.go#L554
|
||||
// https://github.com/gorilla/websocket/blob/b65e62901fc1c0d968042419e74789f6af455eb9/examples/chat/client.go#L67
|
||||
// https://stackoverflow.com/questions/61108552/go-websocket-error-close-1006-abnormal-closure-unexpected-eof
|
||||
|
||||
filterErr := func() {
|
||||
|
||||
if err != nil && !websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
|
||||
// if we have an error != nil, and it's one of the two, then return EOF
|
||||
err = io.EOF
|
||||
}
|
||||
}
|
||||
|
||||
defer filterErr()
|
||||
|
||||
if conn.reader != nil {
|
||||
n, err = conn.reader.Read(p)
|
||||
|
||||
if err == io.EOF {
|
||||
// if this reader has no more data, get the next reader
|
||||
_, conn.reader, err = conn.WsConn.NextReader()
|
||||
|
||||
if err == nil {
|
||||
// and read in this same call as well
|
||||
return conn.reader.Read(p)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, conn.reader, err = conn.WsConn.NextReader()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (conn *WSConnReadWriteCloser) Write(p []byte) (n int, err error) {
|
||||
return len(p), conn.WsConn.WriteMessage(websocket.BinaryMessage, p)
|
||||
}
|
||||
|
||||
func (conn *WSConnReadWriteCloser) Close() error {
|
||||
return conn.WsConn.Close()
|
||||
}
|
Loading…
Reference in New Issue