Documentation ¶
Overview ¶
Package httptun implements the client and server for the TCP over HTTP tunnel.
Index ¶
- Constants
- Variables
- type Buffer
- func (b *Buffer) Close()
- func (b *Buffer) CloseWithErr(err error)
- func (b *Buffer) Read(flowID uuid.UUID, p []byte) (n int, err error)
- func (b *Buffer) SetReaderPos(pos int64) error
- func (b *Buffer) TakeReader(flowID uuid.UUID) *BufferReader
- func (b *Buffer) Write(p []byte) (n int, err error)
- func (b *Buffer) WriterPos() int64
- type BufferReader
- type Client
- type ErrorCode
- type Flow
- type Handshake
- type Server
- type Stream
- func (s *Stream) Close() error
- func (s *Stream) IsClosed() bool
- func (s *Stream) LocalAddr() net.Addr
- func (s *Stream) NewFlow() (*Flow, int64, error)
- func (s *Stream) OnClose(f func(startTime time.Time, bytesRead, bytesWritten int64))
- func (s *Stream) Read(p []byte) (n int, err error)
- func (s *Stream) RemoteAddr() net.Addr
- func (s *Stream) SetDeadline(t time.Time) error
- func (s *Stream) SetReadDeadline(t time.Time) error
- func (s *Stream) SetWriteDeadline(t time.Time) error
- func (s *Stream) Write(p []byte) (n int, err error)
- type WebsocketConn
- func (c *WebsocketConn) Close() error
- func (c *WebsocketConn) LocalAddr() net.Addr
- func (c *WebsocketConn) Read(b []byte) (int, error)
- func (c *WebsocketConn) RemoteAddr() net.Addr
- func (c *WebsocketConn) SetDeadline(t time.Time) error
- func (c *WebsocketConn) SetReadDeadline(t time.Time) error
- func (c *WebsocketConn) SetWriteDeadline(t time.Time) error
- func (c *WebsocketConn) Write(b []byte) (int, error)
Constants ¶
const ( CodeNoError = ErrorCode(iota) CodeSessionNotFound CodeCannotResume CodeDialError )
List of error codes.
Variables ¶
var ErrPreempted = errors.New("buffer: preempted")
ErrPreempted (preemption) is a mechanism that makes Read calls of buffers return immediately, and notify the caller they have been preempted. The caller should immediately exit as it indicates that their flow is no longer valid.
Functions ¶
This section is empty.
Types ¶
type Buffer ¶
type Buffer struct {
// contains filtered or unexported fields
}
Buffer provides the flexibility to recover from an interrupted connection. Each part of a working connection is referred to as a "flow". When a flow is resumed with (*Flow).Resume, a handshake is performed that adjusts the (*Buffer).readerPos on the other side to the appropriate position to continue the TCP connection based on the number of bytes last successfully received. Thus the job of the buffer is to provide enough backwards space for the readerPos to jump back to. This is represented by (*Buffer).minBehindBuffer. The forward space of the buffer isn't technically necessary, it's there to improve throughput and to keep connections from stalling when a connection is interrupted.
The journey of a "packet" looks like this:
1. The underlying connection is read by the caller, or inside server.go 2. (*Buffer).Write() is called, which appends the data to the buffer. 3. (*Buffer).Read() is called, which reads from the buffer from (*Buffer).readerPos. 4. (net.Conn).Write() is called on the "unreliable" connection. --- You're now on the other side --- 5. (net.Conn).Read() is called on the "unreliable" connection from within (*Flow).Resume. 6. Inside (*Flow).Resume, the read data is written to a small, simple buffer (*Stream).writeBuffer. 7. (*Stream).Read() is called, which reads from (*Stream).writeBuffer and provides the "reliable" connection.
The steady state of the Buffer looks like this:
maxTotalBuffer (combined buffer) <-----------------------------------------------> minBehindBuffer (buffer for recovering a lost connection) <-----------------> bufferHead readerPos (position in buffer consumer is reading from) v v
(*Buffer).buffer = []byte{.................................................}
func NewBuffer ¶
func NewBuffer(maxTotal, minBehind int64, logger *zap.SugaredLogger) *Buffer
NewBuffer constructs a new buffer with the given size and logger. See Buffer for more information.
func (*Buffer) Close ¶
func (b *Buffer) Close()
Close closes the buffer. It will cause all readers and writers to return with an error.
func (*Buffer) CloseWithErr ¶
CloseWithErr closes the buffer with a specific error. It will cause all readers and writers to return with the specified error.
func (*Buffer) Read ¶
Read reads from the buffer. It will block until there is data to read. ErrPreempted is returned if the flow is preempted by another flow.
func (*Buffer) SetReaderPos ¶
SetReaderPos sets the reader position of the buffer, it used during the handshake of httptun to resume a TCP connection.
func (*Buffer) TakeReader ¶
func (b *Buffer) TakeReader(flowID uuid.UUID) *BufferReader
TakeReader returns a wrapped io.Reader from the *Buffer that is tied to a specific flow ID.
type BufferReader ¶
type BufferReader struct { *Buffer // contains filtered or unexported fields }
BufferReader is a reader that reads from a Buffer. It wraps Buffer with a flow ID that is used to manage the flows being read from the buffer.
type Client ¶
type Client struct { *websocket.Dialer Addr string RequestHeaders func() http.Header Logger *zap.SugaredLogger // KeepAlive sets the interval and timeout (2*KeepAlive) of WebSocket keep alive messages. // If unset, defaults to 5 seconds. KeepAlive time.Duration }
Client opens Websocket connections, returning them as a net.Conn. A zero Client is ready for use without initialization. If Dialer is nil, websocket.DefaultDialer is used.
type Flow ¶
type Flow struct { *Stream // contains filtered or unexported fields }
Flow is an active "instance" of a stream, which represents an unreliable connection such as a WebSocket connection.
func (*Flow) Close ¶
func (f *Flow) Close()
Close causes a panic to prevent misuse. Closing the flow is prohibited but *Flow wraps a *Stream, so the Close method is implemented to prevent accidental misuse of the (*Stream).Close method.
func (*Flow) IsValid ¶
IsValid returns true if the flow is still valid (i.e. the stream's current flow ID is this flow's, and there is no underlying error reported.
func (*Flow) Resume ¶
Resume attempts to resume the flow's stream with the given "unreliable" connection (typically a WebSocket connection) and resumeFrom value from the handshake. Once the flow is successfully resumed, Resume returns. Call Wait to wait for the flow to finish. unreliable is automatically closed.
type Handshake ¶
Handshake is the handshake message sent by both the client and server to negotiate connection resumption.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server implements http.Handler for the server (termination point) of a TCP over HTTP tunnel.
func NewServer ¶
NewServer creates a new server that can be used to serve HTTP requests over a websocket connection. timeout specifies the maximum time that a stream can be idle with no active flows before it is closed.
func (*Server) Close ¶
func (s *Server) Close()
Close shuts down the server, closing existing streams and rejects new connections.
type Stream ¶
type Stream struct {
// contains filtered or unexported fields
}
Stream is a resumable stream, it represents a logical, persistent (extra-reliable) connection.
func NewStream ¶
func NewStream(maxTotal, minBehind int64, logger *zap.SugaredLogger) *Stream
NewStream creates a new stream.
func (*Stream) Close ¶
Close closes the stream, immediately preempting all Read, Write calls and flows. It is safe to call Close multiple times.
func (*Stream) LocalAddr ¶
LocalAddr implements net.Conn. It returns a dummy but valid net.Addr value.
func (*Stream) NewFlow ¶
NewFlow prepares the stream for resumption with a new flow. It preempts any existing flows and returns the ResumeFrom value of the stream that should be given to the other side in a handshake.
func (*Stream) OnClose ¶
OnClose sets a callback function that is called when a stream closes. It provides the start time of the connection, and the total number of bytes read from and written to the stream.
func (*Stream) Read ¶
Read implements io.Reader. Stream's Read method is behind a buffer and is interruption-free when flows are interrupted.
func (*Stream) RemoteAddr ¶
RemoteAddr implements net.Conn. It returns a dummy but valid net.Addr value.
func (*Stream) SetDeadline ¶
SetDeadline implements net.Conn. It is an unimplemented no-op.
func (*Stream) SetReadDeadline ¶
SetReadDeadline implements net.Conn. It is an unimplemented no-op.
func (*Stream) SetWriteDeadline ¶
SetWriteDeadline implements net.Conn. It is an unimplemented no-op.
type WebsocketConn ¶
type WebsocketConn struct {
// contains filtered or unexported fields
}
WebsocketConn wraps *websocket.Conn into implementing net.Conn
func NewWebsocketConn ¶
func NewWebsocketConn(conn *websocket.Conn, writeMu *sync.Mutex, waitClose func()) *WebsocketConn
NewWebsocketConn creates a new WebsocketConn from an open websocket connection which implements net.Conn
func (*WebsocketConn) LocalAddr ¶
func (c *WebsocketConn) LocalAddr() net.Addr
LocalAddr implements net.Conn
func (*WebsocketConn) Read ¶
func (c *WebsocketConn) Read(b []byte) (int, error)
Read implements net.Conn
func (*WebsocketConn) RemoteAddr ¶
func (c *WebsocketConn) RemoteAddr() net.Addr
RemoteAddr implements net.Conn
func (*WebsocketConn) SetDeadline ¶
func (c *WebsocketConn) SetDeadline(t time.Time) error
SetDeadline implements net.Conn
func (*WebsocketConn) SetReadDeadline ¶
func (c *WebsocketConn) SetReadDeadline(t time.Time) error
SetReadDeadline implements net.Conn
func (*WebsocketConn) SetWriteDeadline ¶
func (c *WebsocketConn) SetWriteDeadline(t time.Time) error
SetWriteDeadline implements net.Conn