Documentation ¶
Index ¶
- Constants
- Variables
- func CanSplice(in io.Reader, out io.Writer) bool
- func CopyRequestHeaders(dst, src http.Header)
- func CopyResponseHeaders(dst, src http.Header)
- func CreateUpstreamRequest(rw http.ResponseWriter, r *http.Request) *http.Request
- func GetDataBufferChunk(size int64) []byte
- func Listen(addr string) (net.Listener, error)
- func ListenAndServe(addr string, f func(conn net.Conn)) (net.Listener, error)
- func NoEOF(err error) error
- func Proxy(nc net.Conn, in io.Reader, w io.Writer, dest string) error
- func PutDataBufferChunk(p []byte)
- func SendBackResponse(w http.ResponseWriter, r *http.Request, res *http.Response, err error)
- func ServeListener(l net.Listener, f func(conn net.Conn)) error
- type Buffer
- func (b *Buffer) Buffer() []byte
- func (b *Buffer) Bytes() []byte
- func (b *Buffer) BytesAppend() []byte
- func (b *Buffer) Clear()
- func (b *Buffer) Compact()
- func (b *Buffer) Discard(n int)
- func (b *Buffer) End() int
- func (s *Buffer) Fill(r io.Reader, i int) ([]byte, error)
- func (b *Buffer) Frame(start, end int) *Buffer
- func (b *Buffer) Grow(n int)
- func (b *Buffer) IsEmpty() bool
- func (b *Buffer) Len() int
- func (b *Buffer) Out() []byte
- func (s *Buffer) ReadBlocking(r io.Reader, d []byte) (int, error)
- func (s *Buffer) ReadByte(ior io.Reader) (byte, error)
- func (s *Buffer) ReadData(d []byte) (int, error)
- func (b *Buffer) Recycle()
- func (b *Buffer) SetByte(pos int, i byte)
- func (b *Buffer) SetUnint32(pos int, i uint32)
- func (b *Buffer) SetUnint32BE(pos int, i uint32)
- func (b *Buffer) Size() int
- func (b *Buffer) Skip(count int) int
- func (b *Buffer) Start() int
- func (b *Buffer) UpdateAppend(bout []byte)
- func (b *Buffer) Write(p []byte) (n int, err error)
- func (b *Buffer) WriteByte(d byte)
- func (b *Buffer) WriteUnint32(i uint32)
- func (b *Buffer) WriteVarint(i int64)
- type BufferPool
- type BufferReader
- type ChannelListener
- type ClientHelloMsg
- type CloseWriter
- type ContextGetter
- type DeadlineExceededError
- type H2Dialer
- type InOutStream
- func (s *InOutStream) Close() error
- func (s *InOutStream) CloseWrite() error
- func (s *InOutStream) Context() context.Context
- func (s *InOutStream) CopyBuffered(dst io.Writer, src io.Reader, srcIsRemote bool) (written int64, err error)
- func (s *InOutStream) Fill(nb int) ([]byte, error)
- func (s *InOutStream) Flush()
- func (hc *InOutStream) GetWriteFrame(sz int) *Buffer
- func (s *InOutStream) Header() http.Header
- func (s *InOutStream) LocalAddr() net.Addr
- func (b *InOutStream) PostDial(nc net.Conn, err error)
- func (s *InOutStream) ProxyTo(nc net.Conn) error
- func (s *InOutStream) RBuffer() *Buffer
- func (s *InOutStream) Read(out []byte) (int, error)
- func (s *InOutStream) ReadByte() (byte, error)
- func (s *InOutStream) ReadFrom(cin io.Reader) (n int64, err error)
- func (s *InOutStream) ReadHeader(in io.Reader) error
- func (hc *InOutStream) Recv(last bool) (*Buffer, error)
- func (s *InOutStream) RemoteAddr() net.Addr
- func (s *InOutStream) RequestHeader() http.Header
- func (hc *InOutStream) Send(b *Buffer) error
- func (s *InOutStream) SendHeader(w io.WriteCloser, h http.Header) error
- func (s *InOutStream) SetDeadline(t time.Time) error
- func (s *InOutStream) SetReadDeadline(t time.Time) error
- func (s *InOutStream) SetWriteDeadline(t time.Time) error
- func (s *InOutStream) Skip(n int)
- func (s *InOutStream) State() *StreamState
- func (s *InOutStream) TLSConnectionState() *tls.ConnectionState
- func (s *InOutStream) TransportConn() net.Conn
- func (s *InOutStream) WBuffer() *Buffer
- func (s *InOutStream) Write(b []byte) (n int, err error)
- func (s *InOutStream) WriteHeader(statusCode int)
- func (s *InOutStream) WriteTo(w io.Writer) (n int64, err error)
- type ReaderCopier
- type RecvBufferReader
- type RecvMsg
- type Stats
- type Stream
- type StreamConn
- func (s *StreamConn) Close() error
- func (s *StreamConn) Context() context.Context
- func (s *StreamConn) Header() http.Header
- func (s *StreamConn) LocalAddr() net.Addr
- func (s *StreamConn) Read(b []byte) (n int, err error)
- func (s *StreamConn) RemoteAddr() net.Addr
- func (s *StreamConn) RequestHeader() http.Header
- func (s *StreamConn) SetDeadline(t time.Time) error
- func (s *StreamConn) SetReadDeadline(t time.Time) error
- func (s *StreamConn) SetWriteDeadline(t time.Time) error
- func (s *StreamConn) State() *StreamState
- func (s *StreamConn) TLSConnectionState() *tls.ConnectionState
- func (s *StreamConn) Write(b []byte) (n int, err error)
- type StreamHttpClient
- func (s *StreamHttpClient) Close() error
- func (s *StreamHttpClient) CloseWrite() error
- func (s *StreamHttpClient) Context() context.Context
- func (s *StreamHttpClient) Header() http.Header
- func (s *StreamHttpClient) LocalAddr() net.Addr
- func (s *StreamHttpClient) Read(b []byte) (n int, err error)
- func (s *StreamHttpClient) RemoteAddr() net.Addr
- func (s *StreamHttpClient) RequestHeader() http.Header
- func (s *StreamHttpClient) SetDeadline(t time.Time) error
- func (s *StreamHttpClient) SetReadDeadline(t time.Time) error
- func (s *StreamHttpClient) SetWriteDeadline(t time.Time) error
- func (s *StreamHttpClient) State() *StreamState
- func (s *StreamHttpClient) TLSConnectionState() *tls.ConnectionState
- func (s *StreamHttpClient) Write(b []byte) (n int, err error)
- type StreamHttpServer
- func (s *StreamHttpServer) Close() error
- func (s *StreamHttpServer) CloseWrite() error
- func (s *StreamHttpServer) Context() context.Context
- func (s *StreamHttpServer) Header() http.Header
- func (s *StreamHttpServer) LocalAddr() net.Addr
- func (s *StreamHttpServer) Read(b []byte) (n int, err error)
- func (s *StreamHttpServer) RemoteAddr() net.Addr
- func (s *StreamHttpServer) RequestHeader() http.Header
- func (s *StreamHttpServer) SetDeadline(t time.Time) error
- func (s *StreamHttpServer) SetReadDeadline(t time.Time) error
- func (s *StreamHttpServer) SetWriteDeadline(t time.Time) error
- func (s *StreamHttpServer) State() *StreamState
- func (s *StreamHttpServer) TLSConnectionState() *tls.ConnectionState
- func (s *StreamHttpServer) Write(b []byte) (n int, err error)
- type StreamMeta
- type StreamState
- type StreamType
- type Streams
- type TokenSource
Constants ¶
const ConnectOverrideHeader = "x-host"
const ContextKey = "ugate.stream"
const DebugClose = true
If true, will debug or close operations. Close is one of the hardest problems, due to FIN/RST multiple interfaces.
Variables ¶
var ( CountGetBuffer atomic.Int32 CountPutBuffer atomic.Int32 )
Buffer chunks are allocated from a pool to reduce pressure on GC. The maximum wasted space per dataBuffer is 2x the largest size class, which happens when the dataBuffer has multiple chunks and there is one unread byte in both the first and last chunks. We use a few size classes to minimize overheads for servers that typically receive very small request bodies.
var ( VarzSErrRead = expvar.NewInt("ugate_srv_err_read_total") VarzSErrWrite = expvar.NewInt("ugate_srv_err_write_total") VarzCErrRead = expvar.NewInt("ugate_client_err_read_total") VarzCErrWrite = expvar.NewInt("ugate_client_err_write_total") VarzMaxRead = expvar.NewInt("ugate_max_read_bytes") // Managed by 'NewTCPProxy' - before dial. TcpConTotal = expvar.NewInt("gate_tcp_total") // Managed by updateStatsOnClose - including error cases. TcpConActive = expvar.NewInt("gate_tcp_active") )
var Debug = false
TODO: benchmark different sizes.
var DebugRW = false
var ErrDeadlineExceeded error = &DeadlineExceededError{}
ErrDeadlineExceeded is returned for an expired deadline. This is exported by the os package as os.ErrDeadlineExceeded.
var ProxyCnt atomic.Int32
var StreamId uint32
Functions ¶
func CanSplice ¶
Verify if in and out can be spliced. Used by proxy code to determine best method to copy.
Tcp connections implement ReadFrom, not WriteTo ReadFrom is only spliced in few cases
func CopyRequestHeaders ¶
used in createUpstreamRequetst to copy the headers to the new req.
func CopyResponseHeaders ¶
Also used in httpproxy_capture, for forward http proxy
func CreateUpstreamRequest ¶
CreateUpstremRequest shallow-copies r into a new request that can be sent upstream.
Derived from reverseproxy.go in the standard Go httputil package.
Use with a roundtripper - HTTP1.1 or H2C or HTTPS, followed by SendBackResponse
func GetDataBufferChunk ¶
Get a raw buffer with approximate size. Used by framer.
func PutDataBufferChunk ¶
func PutDataBufferChunk(p []byte)
Return a chunk to the pool. Called after write is completed or the buffer is no longer needed.
func SendBackResponse ¶
Used by both ForwardHTTP and ForwardMesh, after RoundTrip is done. Will copy response headers and body
Types ¶
type Buffer ¶
type Buffer struct {
// contains filtered or unexported fields
}
Buffer is a buffer associated with a stream that can be used to sniff data and to reuse the read buffers and frames.
The Fill method will populate the buffer by doing one or more Read() operations, up to buffer size. Read will first return data from the buffer, and if buffer is empty will read directly from the source reader. The buffer can be used for parsing.
func (*Buffer) BytesAppend ¶
func (*Buffer) SetUnint32 ¶
func (*Buffer) SetUnint32BE ¶
func (*Buffer) UpdateAppend ¶
UpdateAppend should be called if any append operation may resize and replace the buffer - for example protobuf case.
func (*Buffer) WriteUnint32 ¶
WriteUint32 adds a little endian uint32 to the buffer.
func (*Buffer) WriteVarint ¶
type BufferPool ¶
type BufferPool struct {
// contains filtered or unexported fields
}
func (*BufferPool) GetBuffer ¶
func (bp *BufferPool) GetBuffer() *Buffer
type BufferReader ¶
A Reader with an associated read buffer for sniffing or copy.
func NewBufferReader ¶
func NewBufferReader(in io.Reader) *BufferReader
NewBufferReader adds a buffer associated with a reader. Read will first consume the buffer. The BufferReader can peek and parse the input. Once the bufer is read, Read() will directly use the stream unless Peek methods are used.
func (*BufferReader) Close ¶
func (s *BufferReader) Close() error
func (*BufferReader) Discard ¶
func (br *BufferReader) Discard(n int)
Discard will move the start with n bytes. TODO: if n > buffer, blocking read. Currently not used in the code. Same interface as bufio.Reader
func (*BufferReader) Peek ¶
func (s *BufferReader) Peek(i int) ([]byte, error)
Peek returns the next n bytes without advancing the reader. The bytes stop being valid at the next read call. If Peek returns fewer than n bytes, it also returns an error explaining why the read is short.
Same interface as bufio.Reader Unlike bufio.Reader, if n is larger than buffer size the buffer is resized.
Peek ensures at least i bytes are read. Blocking.
Returns the buffer with all readable data, may be more than i If i==0, does one Read.
type ChannelListener ¶
ChannelListener implements Listener interface over a chan It allows apps expecting a net.Listener to accept virtual streams tunneled and multiplexed.
func NewChannelListener ¶
func NewChannelListener() *ChannelListener
func (*ChannelListener) Addr ¶
func (l *ChannelListener) Addr() net.Addr
func (*ChannelListener) Close ¶
func (l *ChannelListener) Close() error
func (*ChannelListener) OnConnection ¶
func (l *ChannelListener) OnConnection(c net.Conn) error
type ClientHelloMsg ¶
type ClientHelloMsg struct { Raw []byte //random []byte SessionID []byte CipherSuites []uint16 //compressionMethods []uint8 ServerName string // contains filtered or unexported fields }
ClientHelloMsg is a subset of the TLS ClientHello
func SniffClientHello ¶
func SniffClientHello(acc *BufferReader) (*ClientHelloMsg, string, error)
SniffClientHello will peek into acc and read enough for parsing a TLS ClientHello. All read data will be left in the stream, including bytes after ClientHello.
If ClientHello is not detected or is invalid - nil will be returned.
TODO: if a session WorkloadID is provided, use it as a cookie and attempt to find the corresponding host. On server side generate session IDs !
TODO: in mesh, use one cypher suite (TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) maybe 2 ( since keys are ECDSA )
type CloseWriter ¶
type CloseWriter interface {
CloseWrite() error
}
CloseWriter is one of possible interfaces implemented by RequestInPipe to send a FIN, without closing the input. Some writers only do this when Close is called.
type ContextGetter ¶
ContextGetter allows getting a Context associated with a stream or request or other high-level object. Based on http.Request
type DeadlineExceededError ¶
type DeadlineExceededError struct{}
DeadlineExceededError is returned for an expired deadline.
func (*DeadlineExceededError) Error ¶
func (e *DeadlineExceededError) Error() string
Implement the net.Error interface. The string is "i/o timeout" because that is what was returned by earlier Go versions. Changing it may break programs that match on error strings.
func (*DeadlineExceededError) Temporary ¶
func (e *DeadlineExceededError) Temporary() bool
func (*DeadlineExceededError) Timeout ¶
func (e *DeadlineExceededError) Timeout() bool
type H2Dialer ¶
type H2Dialer struct { MDS TokenSource H2TunURL string HttpClient *http.Client }
func NewH2Dialer ¶
type InOutStream ¶
type InOutStream struct { StreamState // In - data from remote. // // - TCP or TLS net.Conn, // - a http request Body (stream mapped to a http accepted connection in a Handler) // - http response Body (stream mapped to a client http connection) // - a QUIC stream - accepted or dialed // - some other ReadCloser. // // Closing In without fully reading all data may result in RST. // // Normal process for close is to call CloseWrite (sending a FIN), read In fully // ( i.e. until remote FIN is received ) and call In.Close. // If In.Close is called before FIN was received the TCP stack may send a RST if more // data is received from the other end. In io.ReadCloser `json:"-"` // Out - send to remote. // // - an instance of net.Conn or tls.Conn - both implementing CloseWrite for FIN // - http.ResponseWriter - for accepted HTTP connections, implements CloseWrite // - a Pipe - for dialed HTTP connections, emulating DialContext behavior ( no body sent before connection is // completed) // - nil, if the remote side is read only ( GET ) or if the creation of the // stream passed a Reader object which is automatically piped to the RequestInPipe, for example // when a HTTP request body is used. // Out io.Writer `json:"-"` // Request associated with the stream. Will be set if the stream is // received over HTTP (real or over another virtual connection), // or if the stream is originated locally and sent to a HTTP dest. // // For streams associated with HTTP server handlers, Out is the ResponseWriter. // Request *http.Request `json:"-"` // --------------------------------------------------- // Used for gRPC and other similar framing protocols // Response holds the response, for client mode Response *http.Response // Metadata to send. InOutStream implements http.ResponseWriter. // For streams without metadata - will be ignored. // Incoming metadata is set in Request. // TODO: without a request, use a buffer, append headers in serialized format directly, flush on first Write // @Deprecated - use a buf. OutHeader http.Header `json:"-"` // Header received from the remote. // For egress it is the response headers. // For ingress it is the request headers. // TODO: map[int][]byte, use read buffer to parse to avoid alloc. // Use equivalent of QPACK with uncompressed headers, custom dict. // @Deprecated - use a buf, packed format, id-based headers. InHeader http.Header `json:"-"` // Set if the connection finished a TLS handshake. // A 'dummy' value may be set if a sidecar terminated the connection. TLS *tls.ConnectionState `json:"-"` // Remote mesh ID, if authenticated. Base32(SHA256(PUB)) or Base32(PUB) (for ED) // This can be used in DNS names, URLs, etc. RemoteID string // Remote mesh ID, in byte form. Remote [32]byte // VIP is the internal ID used in dmesh, based on the SHA of address or public key. RemoteVIP uint64 // Original dest - hostname or IP, including port. Parameter of the original RoundTripStart from the captured egress stream. // May be a mesh IP6, host, etc. If original address was captured by IP, destIP will also be set. // Host is extracted from metadata (SOCKS, iptables, etc) // Typically a DNS or IP address // For example in CONNECT it will be hostname:port or IP:port // For HTTP PROXY the path is a full URL. Dest string LocalA net.Addr // Resolved destination IP. May be nil if SOCKS or forwarding is done. Final Gateway will have it set. // If capture is based on IP, it'll be set in all hops. // If set, this is the authoritiative destination. DestAddr *net.TCPAddr // Real remote address form the socket. May be different from DestAddr (DestAddr can be VIP) RemoteA net.Addr // Client type - original capture and all transport hops. // SOCKS, CONNECT, PROXY, SOCKSIP, PROXYIP, // EPROXY = TCP-over-HTTP in, direct host out // MUX- - for streams associated with a mux. // TODO: use int Type string // Methods to call when the stream is closed on the read side, i.e. received a FIN or RST or // the context was canceled. ReadCloser func() `json:"-"` // Set if CloseWrite() was called, which should result in a FIN sent. // This should happen if a EOF was received when proxying. ServerClose bool `json:"-"` // Set if the client has sent the FIN, and gateway sent the FIN to server ClientClose bool `json:"-"` // Set if Close() was called. Closed bool `json:"-"` // Only for 'accepted' streams (server side), in proxy mode: keep track // of the client side. The server is driving the proxying. ProxyReadErr error `json:"-"` ProxyWriteErr error `json:"-"` // Optional function to call after dial (proxied streams) or after a stream handling has started for local handlers. // Used to send back metadata or finish the handshake. // // For example in SOCKS it sends back the IP/port of the remote. // net.Conn may be a InOutStream or a regular TCP/TLS connection. PostDialHandler func(net.Conn, error) `json:"-"` // // // Direction StreamType Listener net.Listener // Will receive a 'nil' or error on connect. // Will receive a nil or error on receive error (clean close or RST) ErrChan chan error // contains filtered or unexported fields }
InOutStream implements net.Conn using a tunneled, multi-layer protocol with metadata.
The 'raw' connection is typically: - an accepted connection - In/RequestInPipe are the raw net.Conn - with sniffing and processing of SNI/TLS-SNI, SOCKS - a TLSConn, wrapping the accepted connection - HTTP2 RequestBody+ResponseWriter
Metadata is extracted from the headers, SNI, SOCKS, Iptables. Example: - raw TCP connection - SOCKS - extracted dest host:port or IP:port - IPTables - extracted original DST IP:port - SNI - extracted 'Server Name' - port based on the listener port - TLS - peer certificates, SNI, ALPN
Metrics and security info are also maintained.
Implements net.Conn - but does not implement ConnectionState(), so the stream can be used with H2 library to create multiplexed H2 connections over the stream.
func GetStream ¶
func GetStream(out io.Writer, in io.ReadCloser) *InOutStream
GetStream should be used to get a (recycled) stream. Streams will be tracked, and must be closed and recycled.
func NewStream ¶
func NewStream() *InOutStream
NewStream create a new stream. This stream is not tracked.
func (*InOutStream) Close ¶
func (s *InOutStream) Close() error
Must be called at the end. It is expected CloseWrite has been called, for graceful FIN.
func (*InOutStream) CloseWrite ¶
func (s *InOutStream) CloseWrite() error
func (*InOutStream) Context ¶
func (s *InOutStream) Context() context.Context
Context of the stream. It has a value 'ugate.stream' that points back to the stream, so it can be passed in various methods that only take context.
This is NOT associated with the context of the original H2 request, there is a lot of complexity and strange behaviors in the stack.
func (*InOutStream) CopyBuffered ¶
func (s *InOutStream) CopyBuffered(dst io.Writer, src io.Reader, srcIsRemote bool) (written int64, err error)
Copy src to dst, using a pooled intermediary buffer.
Will update stats about activity and data. Does not close dst when src is closed
Blocking, returns when src returned an error or EOF/graceful close. May also return with error if src or dst return errors.
srcIsRemote indicates that the connection is from the server to client. (remote to local) If false, the connection is from client to server ( local to remote )
func (*InOutStream) Fill ¶
func (s *InOutStream) Fill(nb int) ([]byte, error)
Fill the buffer by doing one Read() from the underlying reader.
Future calls to Read() will use the remaining data in the buffer. @Deprecated - use BufferReader.Peek()
func (*InOutStream) Flush ¶
func (s *InOutStream) Flush()
func (*InOutStream) GetWriteFrame ¶
func (hc *InOutStream) GetWriteFrame(sz int) *Buffer
Return a buffer with reserved front space to be used for appending. If using functions like proto.Marshal, b.UpdateForAppend should be called with the new []byte. App should not touch the prefix.
func (*InOutStream) Header ¶
func (s *InOutStream) Header() http.Header
func (*InOutStream) LocalAddr ¶
func (s *InOutStream) LocalAddr() net.Addr
func (*InOutStream) ProxyTo ¶
func (s *InOutStream) ProxyTo(nc net.Conn) error
Proxy the accepted connection to a dialed connection. Blocking, will wait for both sides to FIN or RST.
func (*InOutStream) RBuffer ¶
func (s *InOutStream) RBuffer() *Buffer
RBuffer method will return or create a buffer. It can be used for parsing headers or sniffing. The 'Read' and 'WriteTo' methods are aware of the buffer, and will use the first consume buffered data, but if the buffer is IsEmpty will use directly In.
func (*InOutStream) ReadByte ¶
func (s *InOutStream) ReadByte() (byte, error)
func (*InOutStream) ReadFrom ¶
func (s *InOutStream) ReadFrom(cin io.Reader) (n int64, err error)
Reads data from cin (the client/dialed con) until EOF or error TCP Connections typically implement this, using io.Copy().
func (*InOutStream) ReadHeader ¶
func (s *InOutStream) ReadHeader(in io.Reader) error
func (*InOutStream) RemoteAddr ¶
func (s *InOutStream) RemoteAddr() net.Addr
RemoteAddr is the client (for accepted) or server (for originated). It should be the real IP, extracted from connection or metadata. RemoteID returns the authenticated ID.
func (*InOutStream) RequestHeader ¶
func (s *InOutStream) RequestHeader() http.Header
func (*InOutStream) SendHeader ¶
func (s *InOutStream) SendHeader(w io.WriteCloser, h http.Header) error
Send will marshall the metadata (headers) and start sending the body to w.
func (*InOutStream) SetDeadline ¶
func (s *InOutStream) SetDeadline(t time.Time) error
func (*InOutStream) SetReadDeadline ¶
func (s *InOutStream) SetReadDeadline(t time.Time) error
func (*InOutStream) SetWriteDeadline ¶
func (s *InOutStream) SetWriteDeadline(t time.Time) error
func (*InOutStream) Skip ¶
func (s *InOutStream) Skip(n int)
Skip only implemented for buffer Deprecated: use BufferReader.Discard()
func (*InOutStream) State ¶
func (s *InOutStream) State() *StreamState
func (*InOutStream) TLSConnectionState ¶
func (s *InOutStream) TLSConnectionState() *tls.ConnectionState
func (*InOutStream) TransportConn ¶
func (s *InOutStream) TransportConn() net.Conn
func (*InOutStream) WBuffer ¶
func (s *InOutStream) WBuffer() *Buffer
WBuffer returns the write buffer associated with the stream. Used to encode headers or for buffering - to avoid the pattern of allocating small non-pooled buffers. TODO: also to use for bucket passing instead of copy.
func (*InOutStream) Write ¶
func (s *InOutStream) Write(b []byte) (n int, err error)
Write implements the io.Writer. The Write() is flushed if possible.
TODO: incorporate the wbuffer, optimize based on size.
func (*InOutStream) WriteHeader ¶
func (s *InOutStream) WriteHeader(statusCode int)
type ReaderCopier ¶
type ReaderCopier struct { // Number of bytes copied. Written int64 MaxRead int ReadCnt int // First error - may be on reading from In (InError=true) or writing to Out. Err error InError bool In io.Reader // For tunneled connections, this can be a tls.Writer. Close will write an TOS close. Out io.Writer // An ID of the copier, for debug purpose. ID string // Set if out doesn't implement Flusher and a separate function is needed. // Example: tunneled mTLS over http, Out is a tls.Conn which writes to a http Body. Flusher http.Flusher }
ReaderCopier copies from In to Out, keeping track of copied bytes and errors.
func (*ReaderCopier) Close ¶
func (rc *ReaderCopier) Close()
func (*ReaderCopier) Copy ¶
func (s *ReaderCopier) Copy(ch chan int, close bool)
Copy will copy src to dst, using a pooled intermediary buffer.
Blocking, returns when src returned an error or EOF/graceful close.
May also return with error if src or dst return errors.
Copy may be called in a go routine, for one of the streams in the connection - the stats and error are returned on a channel.
type RecvBufferReader ¶
type RecvBufferReader struct { // Err is set when a buffer with that error is Put. backlog may have additional data, // but no new data will be received. // May be io.EOF Err error ReadDeadline time.Time // contains filtered or unexported fields }
RecvBufferReader implements io.Reader interface to readBlocking the frame data. Frames are added to the backlog or sent (non-blocking) to the channel from the reader thread.
The blocking readBlocking is pretty complicated, attempts to consume all availalbe data first and returns it - before doing a blocking receive on the channel.
TODO: WIP to pass data frames and avoid one copy.
Orig RecvBuffer is an unbounded channel of RecvMsg structs. It can grow up to window size - flow control protects it.
Note: RecvBuffer differs from buffer.Unbounded only in the fact that it holds a channel of RecvMsg structs instead of objects implementing "item" interface. RecvBuffer is written to much more often and using strict RecvMsg structs helps avoid allocation in "RecvBuffer.Put"
func NewRecvBuffer ¶
func NewRecvBuffer(ctxDone <-chan struct{}, recycleBuffer func(*bytes.Buffer), closeStream func(err error)) *RecvBufferReader
NewRecvBuffer creates a receive buffer.
Will hold frames, represented as bytes.Buffer, added with Put ¶
The Read() method will first return existing data, then block.
recycleBuffer, if set, will be called after the buffer has been copied and can be reused. closeStream is called if there is any error except io.EOF or deadline exceeded.
func (*RecvBufferReader) Put ¶
func (b *RecvBufferReader) Put(r RecvMsg)
Put adds the buffer to either the chan or backlog. Reads on chan most be followed by reloadChannel.
func (*RecvBufferReader) Read ¶
func (r *RecvBufferReader) Read(p []byte) (n int, err error)
Read reads the next len(p) bytes from last. If last is drained, it tries to readBlocking additional data from recv. It blocks if there no additional data available in recv. If Read returns any non-nil error, it will continue to return that error.
type RecvMsg ¶
type RecvMsg struct { Buffer *bytes.Buffer // nil: received some data // io.EOF: stream is completed. data is nil. // other non-nil error: transport failure. data is nil. Err error }
RecvMsg represents the received msg from the transport. All transport protocol specific info has been removed.
type Stats ¶
type Stats struct { Open time.Time // last receive from local (and send to remote) LastWrite time.Time // last receive from remote (and send to local) LastRead time.Time // Sent from client to server ( client is initiator of the proxy ) SentBytes int SentPackets int // Received from server to client RcvdBytes int RcvdPackets int }
Stats holds telemetry for a stream or peer.
type Stream ¶
type Stream interface { net.Conn //context.Context StreamMeta ContextGetter }
Stream interface extends net.Conn with a context and metadata.
func NewStreamRequest ¶
NewStreamRequest creates a Stream based on the result of a RoundTrip. out is typically the pipe used by request to send bytes. TODO: abstract the pipe and the roundtrip call.
type StreamConn ¶
type StreamConn struct { StreamState Conn net.Conn // may be a *tls.Conn // TLS info - if the connection is direct TLS. TLS *tls.ConnectionState // May be populated from Istio metadata or PROXY protocol, etc. ResponseHeader http.Header RequestHeaders http.Header // contains filtered or unexported fields }
StreamConn wraps a net.Conn or a tls connection
func NewStreamConn ¶
func NewStreamConn(r net.Conn) *StreamConn
NewStreamConn creates the Stream wrapper around a net.Conn If tls.Conn, will also set the TLS field (which can also be set for other streams ).
func (*StreamConn) Close ¶
func (s *StreamConn) Close() error
func (*StreamConn) Context ¶
func (s *StreamConn) Context() context.Context
func (*StreamConn) Header ¶
func (s *StreamConn) Header() http.Header
func (*StreamConn) LocalAddr ¶
func (s *StreamConn) LocalAddr() net.Addr
func (*StreamConn) RemoteAddr ¶
func (s *StreamConn) RemoteAddr() net.Addr
func (*StreamConn) RequestHeader ¶
func (s *StreamConn) RequestHeader() http.Header
func (*StreamConn) SetDeadline ¶
func (s *StreamConn) SetDeadline(t time.Time) error
func (*StreamConn) SetReadDeadline ¶
func (s *StreamConn) SetReadDeadline(t time.Time) error
func (*StreamConn) SetWriteDeadline ¶
func (s *StreamConn) SetWriteDeadline(t time.Time) error
func (*StreamConn) State ¶
func (s *StreamConn) State() *StreamState
func (*StreamConn) TLSConnectionState ¶
func (s *StreamConn) TLSConnectionState() *tls.ConnectionState
type StreamHttpClient ¶
type StreamHttpClient struct { StreamState Request *http.Request Response *http.Response ReadCloser func() // Writer side of the request pipe TLS *tls.ConnectionState RequestInPipe io.WriteCloser }
func NewStreamH2 ¶
func NewStreamH2(ctx context.Context, hc *http.Client, addr string, tcpaddr string, mds TokenSource) (*StreamHttpClient, error)
NewStreamH2 creates a H2 stream using POST.
Will use the token provider if not nil.
func (*StreamHttpClient) Close ¶
func (s *StreamHttpClient) Close() error
func (*StreamHttpClient) CloseWrite ¶
func (s *StreamHttpClient) CloseWrite() error
func (*StreamHttpClient) Context ¶
func (s *StreamHttpClient) Context() context.Context
func (*StreamHttpClient) Header ¶
func (s *StreamHttpClient) Header() http.Header
func (*StreamHttpClient) LocalAddr ¶
func (s *StreamHttpClient) LocalAddr() net.Addr
func (*StreamHttpClient) RemoteAddr ¶
func (s *StreamHttpClient) RemoteAddr() net.Addr
func (*StreamHttpClient) RequestHeader ¶
func (s *StreamHttpClient) RequestHeader() http.Header
func (*StreamHttpClient) SetDeadline ¶
func (s *StreamHttpClient) SetDeadline(t time.Time) error
func (*StreamHttpClient) SetReadDeadline ¶
func (s *StreamHttpClient) SetReadDeadline(t time.Time) error
func (*StreamHttpClient) SetWriteDeadline ¶
func (s *StreamHttpClient) SetWriteDeadline(t time.Time) error
func (*StreamHttpClient) State ¶
func (s *StreamHttpClient) State() *StreamState
func (*StreamHttpClient) TLSConnectionState ¶
func (s *StreamHttpClient) TLSConnectionState() *tls.ConnectionState
type StreamHttpServer ¶
type StreamHttpServer struct { StreamState Request *http.Request TLS *tls.ConnectionState ResponseWriter http.ResponseWriter // If set, the function will be called when Close() is called. ReadCloser func() }
func NewStreamServerRequest ¶
func NewStreamServerRequest(r *http.Request, w http.ResponseWriter) *StreamHttpServer
Create a new stream from a HTTP request/response.
For accepted requests, http2/server.go newWriterAndRequests populates the request based on the headers. Server validates method, path and scheme=http|https. Req.Body is a pipe - similar with what we use for egress. Request context is based on stream context, which is a 'with cancel' based on the serverConn baseCtx.
func (*StreamHttpServer) Close ¶
func (s *StreamHttpServer) Close() error
func (*StreamHttpServer) CloseWrite ¶
func (s *StreamHttpServer) CloseWrite() error
func (*StreamHttpServer) Context ¶
func (s *StreamHttpServer) Context() context.Context
func (*StreamHttpServer) Header ¶
func (s *StreamHttpServer) Header() http.Header
func (*StreamHttpServer) LocalAddr ¶
func (s *StreamHttpServer) LocalAddr() net.Addr
func (*StreamHttpServer) RemoteAddr ¶
func (s *StreamHttpServer) RemoteAddr() net.Addr
func (*StreamHttpServer) RequestHeader ¶
func (s *StreamHttpServer) RequestHeader() http.Header
func (*StreamHttpServer) SetDeadline ¶
func (s *StreamHttpServer) SetDeadline(t time.Time) error
func (*StreamHttpServer) SetReadDeadline ¶
func (s *StreamHttpServer) SetReadDeadline(t time.Time) error
func (*StreamHttpServer) SetWriteDeadline ¶
func (s *StreamHttpServer) SetWriteDeadline(t time.Time) error
func (*StreamHttpServer) State ¶
func (s *StreamHttpServer) State() *StreamState
func (*StreamHttpServer) TLSConnectionState ¶
func (s *StreamHttpServer) TLSConnectionState() *tls.ConnectionState
type StreamMeta ¶
type StreamMeta interface { State() *StreamState // Also part of ResponseWriter - it is the response header. Header() http.Header RequestHeader() http.Header TLSConnectionState() *tls.ConnectionState }
type StreamState ¶
type StreamState struct { // It is the key in the Active table. // Streams may also have local ids associated with the transport. StreamId string // WritErr indicates that Write failed - timeout or a RST closing the stream. WriteErr error `json:"-"` // ReadErr, if not nil, indicates that Read() failed - connection was closed with RST // or timedout instead of FIN ReadErr error `json:"-"` Stats // Original or infered destination. Dest string }
StreamState provides metadata about a stream.
It includes errors, stats, other metadata. The Stream interface wraps a net.Conn with context and state.
type StreamType ¶
type StreamType int
const ( StreamTypeUnknown StreamType = iota // Ingress - received on the HBONE mux for the local process, on // a 'sidecar'. StreamTypeIn // Egress - indicates if is originated from local machine, i.e. // SOCKS/iptables/TUN capture or dialed from local process StreamTypeOut // Forward - received on HBONE mux to forward to a workload StreamTypeForward )
type Streams ¶
type Streams struct {
// contains filtered or unexported fields
}
Streams tracks active streams. Some streams are long-lived and used to mux other streams.
func (*Streams) OnStreamDone ¶
Called at the end of the connection handling. After this point nothing should use or refer to the connection, both proxy directions should already be closed for write or fully closed.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package bufferv2 provides the implementation of a non-contiguous buffer that is reference counted, pooled, and copy-on-write.
|
Package bufferv2 provides the implementation of a non-contiguous buffer that is reference counted, pooled, and copy-on-write. |
bits
Package bits includes all bit related types and operations.
|
Package bits includes all bit related types and operations. |
Package syscall provides functionalities that grpc uses to get low-level operating system stats/info.
|
Package syscall provides functionalities that grpc uses to get low-level operating system stats/info. |