mirror of
https://github.com/amnezia-vpn/amneziawg-go.git
synced 2025-04-20 07:56:54 +02:00
85 lines
1.9 KiB
Go
85 lines
1.9 KiB
Go
package pipe
|
|
|
|
import (
|
|
"io"
|
|
"net"
|
|
|
|
"github.com/gobwas/ws"
|
|
"github.com/gobwas/ws/wsutil"
|
|
)
|
|
|
|
// wsConn represents a WebSocket connection that's been already initialized.
|
|
type wsConn struct {
|
|
rwc io.ReadWriteCloser
|
|
remoteAddr net.Addr
|
|
r *wsutil.Reader
|
|
w *wsutil.Writer
|
|
}
|
|
|
|
// newWsConn creates a wrapper over the existing network connection that is
|
|
// able to send/read messages using WebSocket protocol.
|
|
func newWsConn(rwc io.ReadWriteCloser, remoteAddr net.Addr, state ws.State) (c *wsConn) {
|
|
r := wsutil.NewReader(rwc, state)
|
|
w := wsutil.NewWriter(rwc, state, ws.OpBinary)
|
|
|
|
return &wsConn{
|
|
rwc: rwc,
|
|
remoteAddr: remoteAddr,
|
|
r: r,
|
|
w: w,
|
|
}
|
|
}
|
|
|
|
// type check
|
|
var _ io.ReadWriteCloser = (*wsConn)(nil)
|
|
|
|
// Read implements the io.ReadWriteCloser interface for *wsConn.
|
|
func (w *wsConn) Read(b []byte) (n int, err error) {
|
|
n, err = w.r.Read(b)
|
|
if err == wsutil.ErrNoFrameAdvance {
|
|
log.Debug("Reading the next WebSocket frame from %v", w.remoteAddr)
|
|
|
|
hdr, fErr := w.r.NextFrame()
|
|
if fErr != nil {
|
|
return 0, io.EOF
|
|
}
|
|
|
|
log.Debug(
|
|
"Received WebSocket frame with opcode=%d len=%d fin=%v from %v",
|
|
hdr.OpCode,
|
|
hdr.Length,
|
|
hdr.Fin,
|
|
w.remoteAddr,
|
|
)
|
|
|
|
// Reading again after the frame has been read.
|
|
n, err = w.r.Read(b)
|
|
|
|
// EOF in the case of wsutil.Reader does not mean that the connection is
|
|
// closed, it only means that the current frame is finished.
|
|
if err == io.EOF {
|
|
err = nil
|
|
}
|
|
}
|
|
|
|
return n, err
|
|
}
|
|
|
|
// Write implements the io.ReadWriteCloser interface for *wsConn.
|
|
func (w *wsConn) Write(b []byte) (n int, err error) {
|
|
log.Debug("Writing data len=%d to the WebSocket %v", len(b), w.remoteAddr)
|
|
|
|
n, err = w.w.Write(b)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
err = w.w.Flush()
|
|
|
|
return n, err
|
|
}
|
|
|
|
// Close implements the io.ReadWriteCloser interface for *wsConn.
|
|
func (w *wsConn) Close() (err error) {
|
|
return w.rwc.Close()
|
|
}
|