mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 11:11:30 -04:00
Turbo Tunnel client and server.
The client opts into turbotunnel mode by sending a magic token at the beginning of each WebSocket connection (before sending even the ClientID). The token is just a random byte string I generated. The server peeks at the token and, if it matches, uses turbotunnel mode. Otherwise, it unreads the token and continues in the old one-session-per-WebSocket mode.
This commit is contained in:
parent
222ab3d85a
commit
70126177fb
6 changed files with 399 additions and 29 deletions
68
client/lib/turbotunnel.go
Normal file
68
client/lib/turbotunnel.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"git.torproject.org/pluggable-transports/snowflake.git/common/encapsulation"
|
||||
)
|
||||
|
||||
var errNotImplemented = errors.New("not implemented")
|
||||
|
||||
// EncapsulationPacketConn implements the net.PacketConn interface over an
|
||||
// io.ReadWriteCloser stream, using the encapsulation package to represent
|
||||
// packets in a stream.
|
||||
type EncapsulationPacketConn struct {
|
||||
io.ReadWriteCloser
|
||||
localAddr net.Addr
|
||||
remoteAddr net.Addr
|
||||
bw *bufio.Writer
|
||||
}
|
||||
|
||||
// NewEncapsulationPacketConn makes
|
||||
func NewEncapsulationPacketConn(
|
||||
localAddr, remoteAddr net.Addr,
|
||||
conn io.ReadWriteCloser,
|
||||
) *EncapsulationPacketConn {
|
||||
return &EncapsulationPacketConn{
|
||||
ReadWriteCloser: conn,
|
||||
localAddr: localAddr,
|
||||
remoteAddr: remoteAddr,
|
||||
bw: bufio.NewWriter(conn),
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFrom reads an encapsulated packet from the stream.
|
||||
func (c *EncapsulationPacketConn) ReadFrom(p []byte) (int, net.Addr, error) {
|
||||
data, err := encapsulation.ReadData(c.ReadWriteCloser)
|
||||
if err != nil {
|
||||
return 0, c.remoteAddr, err
|
||||
}
|
||||
return copy(p, data), c.remoteAddr, nil
|
||||
}
|
||||
|
||||
// WriteTo writes an encapsulated packet to the stream.
|
||||
func (c *EncapsulationPacketConn) WriteTo(p []byte, addr net.Addr) (int, error) {
|
||||
// addr is ignored.
|
||||
_, err := encapsulation.WriteData(c.bw, p)
|
||||
if err == nil {
|
||||
err = c.bw.Flush()
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// LocalAddr returns the localAddr value that was passed to
|
||||
// NewEncapsulationPacketConn.
|
||||
func (c *EncapsulationPacketConn) LocalAddr() net.Addr {
|
||||
return c.localAddr
|
||||
}
|
||||
|
||||
func (c *EncapsulationPacketConn) SetDeadline(t time.Time) error { return errNotImplemented }
|
||||
func (c *EncapsulationPacketConn) SetReadDeadline(t time.Time) error { return errNotImplemented }
|
||||
func (c *EncapsulationPacketConn) SetWriteDeadline(t time.Time) error { return errNotImplemented }
|
Loading…
Add table
Add a link
Reference in a new issue