h2

package
v0.0.0-...-19b1976 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 5, 2024 License: Apache-2.0 Imports: 24 Imported by: 3

README

Fork of grpc transport, for use with HBone.

Rationale

The golang H2 stack is optimized for the http use case - 'ease of use', consistency with the golang IO and http model. It is not optimized for performance or uses of H2 as a generic transport or tunneling.

This is the reason gRPC has its own stack - optimized for gRPC use case and performance.

There are few options:

  • fork and modify the golang h2 stack
  • fork and modify the gRPC h2 transport - this module
  • fork the FastHTTP H2 implementation - initial evaluation is that gRPC stack has far more usage/maturity, but it may change, FastHTTP is pretty perf-oriented.

The changes made to gRPC are around few goals:

  • remove gRPC specific functionality, which shouldn't be in the h2 transport
  • remove mTLS related code - it should be handled in the L4 layer and generic
  • explore options for further optimizations and reuse.

Ideally the framer can also be optimized and an event based, non-blocking low level can be added.

TODO

  • test with 1M frame size instead of default 16k
  • remove the use of the pipe for http request
  • use Stream as net.Conn
  • P0 implement deadlines properly, use an idle timer for streams too
  • Read() seems to return one frame at a time - despite having more info. Should also report buffered in/iot

Internals of gRPC stack

API

  • ServerTransport is an interface - gRPC allows plugging different implemenation, so hbone could be one.

  • HandleStreams() callbacks on stream received - returns after handshake !

  • WriteHeader(s), Write(...), WriteStatus(), Close(), Drain(), IncrMsgSend/Recv

  • 'channelzData' has stats for the stream.

  • Context includes the Stream ( with interface exposing the Method, SetHeader, SendHeader, SetTrailer)

Client:

  • Close/GracefulClose for the connection
  • Write(stream, 2 byte[], last)
  • NewStrem() - sends headers, doesn't wait
  • CloseStream() - must be called when stream is finished.
  • Error() ch -> closed on connection error
  • GoAway() ch for graceful connection close

Removed / fixed

  • grpc specific headers
  • auth - using http layer
  • the h in data frames
  • context, MD - since exposing the Stream directly.
  • Write - was not blocking on write, since byte[] was result of marshal. Also no reuse
  • Read - io semantics, partial reads instead of readfull.

Code

  • bpdEstimator - evaluate bandwidth ( Bandwidth * Delay product), for dynamicWindow (unless InitialConnWindowSize is set), updates the window and sends SettingsInitialWindowSize dynamically.
  • controlbuf - loopyWriter, buffer logic for sending
  • flowcontrol - in and out flow control handling. When app reads data it sends window updates.
  • handler_server - used for adapting the H2 handler to gRPC. Not used, removed. Handles grpc-timeout, content-type, meta, decodes binary headers.
  • http_util - deal with grpc headers, newFramer using a bufWriter - wraps http2.NewFramer.
  • proxy - authenticate with basicAuth with proxies, implement CONNECT 1.1. Not used.
  • transport - bufferPool, recvMsg, recvBuffer and reader. Interfaces - Stream, transportReader.

Other changes:

  • Removed channelz, statsHandler
  • removed TLS/auth related code.

Client code:

  1. Initialization - replacing dial with a net.Conn from L4

The http2 core implementation:

  • has a databuffer - pool of chunks of different sizes
  • client conn pool handling for http
  • supports priorities - not used in hbone

H2 notes - from H3 perspective

  • At start, 64K flow window for both stream and connection.
  • receiver can increase both using WINDOW_UPDATE, cleaner than SETTINGS
  • adjusting frame size doesn't seem very useful, increases bench but may be more harmful default is 16k

H2 frame header is 9B, QUIC is varint tag,len

QUIC

  • stream ID second bit is 2Way or 1Way
  • Sender: STREAM, STREAM_DATA_BLOCKED, RESET_STREAM
  • Receiver: MAX_STREAM_DATA, STOP_SENDING
  • Also MAX_DATA for connection

Packets include a set of frames Connections may migrate or use multiple paths - based on connection ID.

Documentation

Overview

Package transport defines and implements message oriented communication channel to complete various transactions (e.g., an RPC). It is meant for grpc-internal usage and is not intended to be imported directly by users.

Index

Constants

View Source
const SettingH2R = 0xF051

Variables

View Source
var (
	// ErrIllegalHeaderWrite indicates that setting header is illegal because of
	// the stream's streamDone.
	ErrIllegalHeaderWrite = errors.New("transport: SendHeader called multiple times")
	// ErrHeaderListSizeLimitViolation indicates that the header list size is larger
	// than the limit set by peer.
	ErrHeaderListSizeLimitViolation = errors.New("transport: trying to send header list size larger than the limit set by peer")
)
View Source
var (
	// ErrConnClosing indicates that the transport is closing.
	ErrConnClosing = connectionErrorf(true, nil, "transport is closing")
)

Functions

func ContextErr

func ContextErr(err error) error

ContextErr converts the error from context package into a status error.

Types

type CallHdr

type CallHdr struct {
	Req *http.Request

	DoneFunc func() // called when the stream is finished
}

CallHdr carries the information of a particular RPC.

type ClientParameters

type ClientParameters struct {
	// After a duration of this time if the client doesn't see any activity it
	// pings the server to see if the transport is still alive.
	// If set below 10s, a minimum value of 10s will be used instead.
	Time time.Duration // The current default value is infinity.
	// After having pinged for keepalive check, the client waits for a duration
	// of Timeout and if no activity is seen even after that the connection is
	// closed.
	Timeout time.Duration // The current default value is 20 seconds.
	// If true, client sends keepalive pings even with no active RPCs. If false,
	// when there are no active RPCs, Time and Timeout will be ignored and no
	// keepalive pings will be sent.
	PermitWithoutStream bool // false by default.
}

ClientParameters is used to set keepalive parameters on the client-side. These configure how the client will actively probe to notice when a connection is broken and send pings so intermediaries will be aware of the liveness of the connection. Make sure these parameters are set in coordination with the keepalive policy on the server, as incompatible settings can result in closing of connection.

type ClientServerTransport

type ClientServerTransport struct {
	Listener net.Listener

	ServerTransport *H2Transport

	// All received H2 streams will be added here.
	AcceptedStreams chan *H2Stream

	ClientTransport *H2ClientTransport
}

ClientServerTransport creates a piped H2 client and server.

func NewClientServerTransport

func NewClientServerTransport() *ClientServerTransport

func (*ClientServerTransport) InitPair

func (p *ClientServerTransport) InitPair() error

func (*ClientServerTransport) TcpPair

func (p *ClientServerTransport) TcpPair() (net.Conn, net.Conn, error)

type Code

type Code uint32

A Code is an unsigned 32-bit error code as defined in the gRPC spec.

const (
	// OK is returned on success.
	OK Code = 0

	// Canceled indicates the operation was canceled (typically by the caller).
	//
	// The gRPC framework will generate this error code when cancellation
	// is requested.
	Canceled Code = 1

	// Unknown error. An example of where this error may be returned is
	// if a Status value received from another address space belongs to
	// an error-space that is not known in this address space. Also
	// errors raised by APIs that do not return enough error information
	// may be converted to this error.
	//
	// The gRPC framework will generate this error code in the above two
	// mentioned cases.
	Unknown Code = 2

	// InvalidArgument indicates client specified an invalid argument.
	// Note that this differs from FailedPrecondition. It indicates arguments
	// that are problematic regardless of the streamDone of the system
	// (e.g., a malformed file name).
	//
	// This error code will not be generated by the gRPC framework.
	InvalidArgument Code = 3

	// DeadlineExceeded means operation expired before completion.
	// For operations that change the streamDone of the system, this error may be
	// returned even if the operation has completed successfully. For
	// example, a successful response from a server could have been delayed
	// long enough for the deadline to expire.
	//
	// The gRPC framework will generate this error code when the deadline is
	// exceeded.
	DeadlineExceeded Code = 4

	// NotFound means some requested entity (e.g., file or directory) was
	// not found.
	//
	// This error code will not be generated by the gRPC framework.
	NotFound Code = 5

	// AlreadyExists means an attempt to create an entity failed because one
	// already exists.
	//
	// This error code will not be generated by the gRPC framework.
	AlreadyExists Code = 6

	// PermissionDenied indicates the caller does not have permission to
	// execute the specified operation. It must not be used for rejections
	// caused by exhausting some resource (use ResourceExhausted
	// instead for those errors). It must not be
	// used if the caller cannot be identified (use Unauthenticated
	// instead for those errors).
	//
	// This error code will not be generated by the gRPC core framework,
	// but expect authentication middleware to use it.
	PermissionDenied Code = 7

	// ResourceExhausted indicates some resource has been exhausted, perhaps
	// a per-user quota, or perhaps the entire file system is out of space.
	//
	// This error code will be generated by the gRPC framework in
	// out-of-memory and server overload situations, or when a message is
	// larger than the configured maximum size.
	ResourceExhausted Code = 8

	// FailedPrecondition indicates operation was rejected because the
	// system is not in a streamDone required for the operation's execution.
	// For example, directory to be deleted may be non-empty, an rmdir
	// operation is applied to a non-directory, etc.
	//
	// A litmus test that may help a service implementor in deciding
	// between FailedPrecondition, Aborted, and Unavailable:
	//  (a) Use Unavailable if the client can retry just the failing call.
	//  (b) Use Aborted if the client should retry at a higher-level
	//      (e.g., restarting a readBlocking-modify-write sequence).
	//  (c) Use FailedPrecondition if the client should not retry until
	//      the system streamDone has been explicitly fixed. E.g., if an "rmdir"
	//      fails because the directory is non-empty, FailedPrecondition
	//      should be returned since the client should not retry unless
	//      they have first fixed up the directory by deleting files from it.
	//  (d) Use FailedPrecondition if the client performs conditional
	//      REST Get/Record/Delete on a resource and the resource on the
	//      server does not match the condition. E.g., conflicting
	//      readBlocking-modify-write on the same resource.
	//
	// This error code will not be generated by the gRPC framework.
	FailedPrecondition Code = 9

	// Aborted indicates the operation was aborted, typically due to a
	// concurrency issue like sequencer check failures, transaction aborts,
	// etc.
	//
	// See litmus test above for deciding between FailedPrecondition,
	// Aborted, and Unavailable.
	//
	// This error code will not be generated by the gRPC framework.
	Aborted Code = 10

	// OutOfRange means operation was attempted past the valid range.
	// E.g., seeking or reading past end of file.
	//
	// Unlike InvalidArgument, this error indicates a problem that may
	// be fixed if the system streamDone changes. For example, a 32-bit file
	// system will generate InvalidArgument if asked to readBlocking at an
	// offset that is not in the range [0,2^32-1], but it will generate
	// OutOfRange if asked to readBlocking from an offset past the current
	// file size.
	//
	// There is a fair bit of overlap between FailedPrecondition and
	// OutOfRange. We recommend using OutOfRange (the more specific
	// error) when it applies so that callers who are iterating through
	// a space can easily look for an OutOfRange error to detect when
	// they are done.
	//
	// This error code will not be generated by the gRPC framework.
	OutOfRange Code = 11

	// Unimplemented indicates operation is not implemented or not
	// supported/enabled in this service.
	//
	// This error code will be generated by the gRPC framework. Most
	// commonly, you will see this error code when a method implementation
	// is missing on the server. It can also be generated for unknown
	// compression algorithms or a disagreement as to whether an RPC should
	// be streaming.
	Unimplemented Code = 12

	// Internal errors. Means some invariants expected by underlying
	// system has been broken. If you see one of these errors,
	// something is very broken.
	//
	// This error code will be generated by the gRPC framework in several
	// internal error conditions.
	Internal Code = 13

	// Unavailable indicates the service is currently unavailable.
	// This is a most likely a transient condition and may be corrected
	// by retrying with a backoff. Note that it is not always safe to retry
	// non-idempotent operations.
	//
	// See litmus test above for deciding between FailedPrecondition,
	// Aborted, and Unavailable.
	//
	// This error code will be generated by the gRPC framework during
	// abrupt shutdown of a server process or network connection.
	Unavailable Code = 14

	// DataLoss indicates unrecoverable data loss or corruption.
	//
	// This error code will not be generated by the gRPC framework.
	DataLoss Code = 15

	// Unauthenticated indicates the request does not have valid
	// authentication credentials for the operation.
	//
	// The gRPC framework will generate this error code when the
	// authentication metadata is invalid or a Credentials callback fails,
	// but also expect authentication middleware to generate it.
	Unauthenticated Code = 16
)

type ConnectionError

type ConnectionError struct {
	Desc string
	// contains filtered or unexported fields
}

ConnectionError is an error that results in the termination of the entire connection and the retry of all the active streams.

func (ConnectionError) Error

func (e ConnectionError) Error() string

func (ConnectionError) Origin

func (e ConnectionError) Origin() error

Origin returns the original error of this connection error.

func (ConnectionError) Temporary

func (e ConnectionError) Temporary() bool

Temporary indicates if this connection error is temporary or fatal.

func (ConnectionError) Unwrap

func (e ConnectionError) Unwrap() error

Unwrap returns the original error of this connection error or nil when the origin is nil.

type EnforcementPolicy

type EnforcementPolicy struct {
	// MinTime is the minimum amount of time a client should wait before sending
	// a keepalive ping.
	MinTime time.Duration // The current default value is 5 minutes.
	// If true, server allows keepalive pings even when there are no active
	// streams(RPCs). If false, and client sends ping when there are no active
	// streams, server will send GOAWAY and close the connection.
	PermitWithoutStream bool // false by default.
}

EnforcementPolicy is used to set keepalive enforcement policy on the server-side. Server will close connection with a client that violates this policy.

type Event

type Event struct {
	H2Mux    *H2Transport
	H2Stream *H2Stream
	Frame    *nio.Buffer
}

Event includes information about H2.

In the core library, httptrace package provides a subset.

type EventHandler

type EventHandler interface {
	HandleEvent(evtype EventType, t *H2Transport, s *H2Stream, f *nio.Buffer)
}

type EventHandlerFunc

type EventHandlerFunc func(evt EventType, t *H2Transport, s *H2Stream, f *nio.Buffer)

func (EventHandlerFunc) HandleEvent

func (f EventHandlerFunc) HandleEvent(evt EventType, t *H2Transport, s *H2Stream, d *nio.Buffer)

type EventType

type EventType int
const (
	Event_Unknown EventType = iota

	// Client TCP connection starting, called before dialing the endpoint TCP conn
	Event_Connect_Start

	// Server/client: Connect portion done, including handshake for settings.
	// TLS alpn and conn info available.
	Event_Connect_Done

	// Settings received from the other side.
	Event_Settings

	// Server: sent go away, start draining. Client: received go away, draining.
	Event_GoAway

	// Connection closed.
	Event_ConnClose

	// H2Stream-level
	Event_Response

	// Generated before sending headers for requests only. May add headers.
	EventStreamRequestStart

	EventStreamStart

	Event_WroteHeaders

	// For net.http, this is called on the first byte of response header.
	// For hbone and h2, on the receipt of the full header frame.
	EventGotFirstResponseByte

	// In http interceptor: WroteRequest(err)
	EventSendDone
	EventReceiveDone

	EventStreamClosed

	// Data events
	Event_FrameReceived
	Event_FrameSent

	EventLAST
)

type Events

type Events struct {
	// contains filtered or unexported fields
}

func (*Events) Add

func (e *Events) Add(events Events)

func (*Events) GetHandler

func (e *Events) GetHandler(t EventType) EventHandler

func (*Events) OnEvent

func (s *Events) OnEvent(t EventType, eh EventHandler)

type GoAwayReason

type GoAwayReason uint8

GoAwayReason contains the reason for the GoAway frame received.

const (
	// GoAwayInvalid indicates that no GoAway frame is received.
	GoAwayInvalid GoAwayReason = 0
	// GoAwayNoReason is the default value when GoAway frame is received.
	GoAwayNoReason GoAwayReason = 1
	// GoAwayTooManyPings indicates that a GoAway frame with
	// ErrCodeEnhanceYourCalm was received and that the debug data said
	// "too_many_pings".
	GoAwayTooManyPings GoAwayReason = 2
)

type H2ClientTransport

type H2ClientTransport struct {
	H2Transport

	KeepaliveParams ClientParameters
	// contains filtered or unexported fields
}

H2ClientTransport implements the ClientTransport interface with HTTP2.

func NewConnection

func NewConnection(ctx context.Context, opts H2Config) (_ *H2ClientTransport, err error)

newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2 and starts to receive messages on it. Non-nil error returns if construction fails.

func (*H2ClientTransport) CanTakeNewRequest

func (t *H2ClientTransport) CanTakeNewRequest() bool

func (*H2ClientTransport) Error

func (t *H2ClientTransport) Error() <-chan struct{}

func (*H2ClientTransport) GetGoAwayReason

func (t *H2ClientTransport) GetGoAwayReason() (GoAwayReason, string)

func (*H2ClientTransport) GoAway

func (t *H2ClientTransport) GoAway() <-chan struct{}

func (*H2ClientTransport) StartConn

func (t *H2ClientTransport) StartConn(conn net.Conn) (err error)

type H2Config

type H2Config struct {
	// InitialConnWindowSize sets the initial window size for a connection.
	InitialConnWindowSize int32

	// InitialWindowSize sets the initial window size for a stream.
	InitialWindowSize int32

	MaxFrameSize uint32

	// MaxHeaderListSize sets the max (uncompressed) size of header list that is prepared to be received.
	MaxHeaderListSize *uint32

	// WriteBufferSize sets the size of write buffer which in turn determines how
	// much data can be batched before it's written on the wire.
	WriteBufferSize int

	// ReadBufferSize sets the size of readBlocking buffer, which in turn determines how much data can
	// be readBlocking at most for one readBlocking syscall.
	ReadBufferSize int

	// ====== Client specific =========
	// UserAgent is the application user agent.
	UserAgent string

	// FailOnNonTempDialError specifies if gRPC fails on non-temporary dial errors.
	FailOnNonTempDialError bool

	// KeepaliveParams stores the keepalive parameters.
	KeepaliveParams ClientParameters
}

type H2Stream

type H2Stream struct {
	nio.StreamState

	// If set, all data frames will be sent to this method and bypass the reader queue.
	// User is required to call s.Transport().UpdateWindow(s, uint32(n)) explicitly to receive
	// more data. This may happen later, when space is available.
	OnData func(*frame.DataFrame)

	Request  *http.Request
	Response *http.Response

	// Error causing the close of the stream - stream reset, connection errors, etc
	// trReader.Err contains any read error - including io.EOF, which indicates successful read close.
	Error error
	// contains filtered or unexported fields
}

H2Stream represents an H2 stream.

H2Stream implements the net.Conn, context.Context interfaces It exposes read and write quota and other low-level H2 concepts.

func NewGRPCStream

func NewGRPCStream(ctx context.Context, host, path string) *H2Stream

NewGRPCStream creates a HTTPConn with a request set using gRPC framing and headers, capable of sending a stream of GRPC messages.

https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md

No protobuf processed or used - this is a low-level network interface. Caller or generated code can handle marshalling. It only provides gRPC encapsulation, i.e. 1 byte TAG, 4 byte len, msg[len] It can be used for both unary and streaming requests - unary gRPC just sends or receives a single request.

Caller should set Req.Headers, including: - Set content-type to a specific subtype ( default is set to application/grpc ) - add extra headers

For response, the caller must handle headers like:

  • trailer grpc-status, grpc-message, grpc-status-details-bin, grpc-encoding
  • http status codes other than 200 (which is expected for gRPC)

func NewStreamReq

func NewStreamReq(req *http.Request) *H2Stream

func (*H2Stream) AdjustWindow

func (s *H2Stream) AdjustWindow(n uint32)

AdjustWindow sends out extra window update over the initial window size of stream if the application is requesting data larger in size than the window. For example if Read([]buf) is called with a large buffer, we notify the other side that we have buffer space. This is a temporary adjustment.

func (*H2Stream) Close

func (s *H2Stream) Close() error

Close() is one of the most complicated methods for H2 and TCP.

Recommended close:

  • CloseWrite will send a FIN (data frame or trailer headers). Read continues until it receives FIN, at which point stream is closed. Close() is called internally.
  • CloseError will send a RST explicitly, with the given code. Read is closed as well, and Close() is called internally.

Repeated calls to Close() have no effects.

Unfortunately many net.Conn users treat Close() as CloseWrite() - since there is no explicit method. TLS Conn does send closeNotify, and TCP Conn appears to also send FIN. RST in TCP is only sent if data is received after close().

The expectation is that Read() will also be unblocked by Close, if EOF not already received - but it should not return EOF since it's not the real cause. Like os close, there is no lingering by default.

net.Close doc: Close closes the connection. Any blocked Read or Write operations will be unblocked and return errors.

func (*H2Stream) CloseError

func (s *H2Stream) CloseError(code uint32)

CloseError will close the stream with an error code. This will result in a RST sent, reader will be closed as well.

Will unblock Read and Write and cancel the stream context.

func (*H2Stream) CloseWrite

func (s *H2Stream) CloseWrite() error

Send EOS/FIN.

Client: send FIN Server: send trailers and FIN

func (*H2Stream) Conn

func (s *H2Stream) Conn() net.Conn

Return the underlying connection ( typically tcp ), for remote addr or other things.

func (*H2Stream) Context

func (s *H2Stream) Context() context.Context

Context returns the context of the stream.

func (*H2Stream) Deadline

func (ctx *H2Stream) Deadline() (deadline time.Time, ok bool)

Deadline returns the time when work done on behalf of this context should be canceled. Deadline returns ok==false when no deadline is set. Successive calls to Deadline return the same results.

This method always returns 0, false and is only present to make RequestCtx implement the context interface.

func (*H2Stream) Do

func (s *H2Stream) Do() error

Send the request headers. Does not wait for status.

func (*H2Stream) Done

func (ctx *H2Stream) Done() <-chan struct{}

Done returns a channel which is closed when it receives the final status from the server.

Context: Done returns a channel that's closed when work done on behalf of this context should be canceled. Done may return nil if this context can never be canceled. Successive calls to Done return the same value.

func (*H2Stream) Err

func (ctx *H2Stream) Err() error

Err returns a non-nil error value after Done is closed, successive calls to Err return the same error. If Done is not yet closed, Err returns nil. If Done is closed, Err returns a non-nil error explaining why: Canceled if the context was canceled (via server Shutdown) or DeadlineExceeded if the context's deadline passed.

func (*H2Stream) GetWriteFrame

func (hc *H2Stream) GetWriteFrame(sz int) *nio.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 (*H2Stream) GoString

func (s *H2Stream) GoString() string

GoString is implemented by H2Stream so context.String() won't race when printing %#v.

func (*H2Stream) Header

func (s *H2Stream) Header() http.Header

Response headers.

func (*H2Stream) LocalAddr

func (s *H2Stream) LocalAddr() net.Addr

func (*H2Stream) Read

func (s *H2Stream) Read(p []byte) (n int, err error)

Read reads all p bytes from the wire for this stream.

func (*H2Stream) RecvRaw

func (s *H2Stream) RecvRaw() (bb *bytes.Buffer, err error)

Recv returns the next data frame buffer and updates the window. The buffer should be recycled when done, or written to a different stream. Post write the buffers are recycled automatically.

func (*H2Stream) RecycleDataFrame

func (s *H2Stream) RecycleDataFrame(bb *bytes.Buffer)

Recycle a buffer for data frames.

func (*H2Stream) RemoteAddr

func (s *H2Stream) RemoteAddr() net.Addr

func (*H2Stream) RequestHeader

func (s *H2Stream) RequestHeader() http.Header

func (*H2Stream) Send

func (hc *H2Stream) Send(b *nio.Buffer) error

Framed sending/receiving.

func (*H2Stream) SendRaw

func (hc *H2Stream) SendRaw(b []byte, start, end int, last bool) error

Send is an alternative to Write(), where the buffer ownership is passed to the stream and the method does not wait for the buffer to be sent.

func (*H2Stream) SetDeadline

func (s *H2Stream) SetDeadline(t time.Time) error

func (*H2Stream) SetReadDeadline

func (s *H2Stream) SetReadDeadline(t time.Time) error

func (*H2Stream) SetTransport

func (s *H2Stream) SetTransport(tr *H2Transport, client bool)

func (*H2Stream) SetValue

func (ctx *H2Stream) SetValue(key string, val interface{}) interface{}

func (*H2Stream) SetWriteDeadline

func (s *H2Stream) SetWriteDeadline(t time.Time) error

func (*H2Stream) State

func (s *H2Stream) State() *nio.StreamState

func (*H2Stream) TLSConnectionState

func (s *H2Stream) TLSConnectionState() *tls.ConnectionState

func (*H2Stream) Transport

func (hc *H2Stream) Transport() *H2Transport

func (*H2Stream) TransportConn

func (s *H2Stream) TransportConn() net.Conn

func (*H2Stream) Value

func (ctx *H2Stream) Value(key interface{}) interface{}

Value returns the value associated with this context for key, or nil if no value is associated with key. Successive calls to Value with the same key returns the same result.

This method is present to make RequestCtx implement the context interface. This method is the same as calling ctx.UserValue(key)

func (*H2Stream) WaitHeaders

func (s *H2Stream) WaitHeaders()

func (*H2Stream) Write

func (s *H2Stream) Write(d []byte) (int, error)

func (*H2Stream) WriteHeader

func (s *H2Stream) WriteHeader(statusCode int)

WriteHeader implements the ResponseWriter interface. Used to send a response back to the initiator.

type H2Transport

type H2Transport struct {
	// Time when last frame was received.
	LastRead int64 // Keep this field 64-bit aligned. Accessed atomically.

	// lastStreamCreatedTime stores the timestamp that the last stream gets created. It is of int64 type
	// instead of time.Time since it's more costly to atomically update time.Time variable than int64
	// variable. The same goes for lastMsgSentTime and lastMsgRecvTime.
	LastStreamCreatedTime int64

	FrameSize    uint32
	PeerSettings *frame.SettingsFrame

	Events

	Handle   func(*H2Stream)
	TraceCtx func(context.Context, string) context.Context

	// Error causing the close of the transport
	Error error

	// Time of the accept() or dial
	StartTime time.Time
	// contains filtered or unexported fields
}

H2Transport handles one TCP/TLS connection with a peer, implementing client and server H2Streams. The goal is to support the full HTTPTransport.

func NewServerConnection

func NewServerConnection(conn net.Conn, config *ServerConfig, ev *Events) (_ *H2Transport, err error)

NewServerConnection creates a http2 transport with conn and configuration options from config.

It returns a non-nil transport and a nil error on success. On failure, it returns a nil transport and a non-nil error. For a special case where the underlying conn gets closed before the client preface could be readBlocking, it returns a nil transport and a nil error.

func (*H2Transport) Close

func (t *H2Transport) Close(err error)

Close starts shutting down the H2Transport transport. After it is called, the transport should not be accessed any more, in future may be recycled.

func (*H2Transport) Conn

func (t *H2Transport) Conn() net.Conn

func (*H2Transport) CreateHeader

func (t *H2Transport) CreateHeader(ctx context.Context, r *http.Request) ([]hpack.HeaderField, error)

Create the header frame for a request.

func (*H2Transport) Dial

func (t *H2Transport) Dial(request *http.Request) (*http.Response, error)

Dial sends a request (headers). Does not block waiting for response, but waits for available stream.

func (*H2Transport) DialStream

func (t *H2Transport) DialStream(s *H2Stream) error

dial associates a H2Stream with a mux and sends the request. Will send headers, but not wait for res headers.

func (*H2Transport) Drain

func (t *H2Transport) Drain()

func (*H2Transport) HandleStreams

func (t *H2Transport) HandleStreams()

HandleStreams receives incoming streams using the given handler. This is typically run in a separate goroutine. traceCtx attaches trace to ctx and returns the new context.

func (*H2Transport) IsServer

func (t *H2Transport) IsServer() bool

func (*H2Transport) MuxEvent

func (s *H2Transport) MuxEvent(t EventType)

func (*H2Transport) RoundTrip

func (t *H2Transport) RoundTrip(request *http.Request) (*http.Response, error)

func (*H2Transport) Send

func (t *H2Transport) Send(s *H2Stream, b []byte, start, end int, last bool) error

Send will add the buffer to the send queue, waiting for quota if needed. The buffer ownership is passed to the transport - after write the buffer will be recycled and reused for input or output. Write may fail later - the last call to Send or CloseWrite will return an error if any write failed.

func (*H2Transport) UpdateWindow

func (t *H2Transport) UpdateWindow(s *H2Stream, n uint32)

updateWindow adjusts the inbound quota for the stream. Window updates will be sent out when the cumulative quota exceeds the corresponding threshold.

func (*H2Transport) Write

func (t *H2Transport) Write(s *H2Stream, hdr []byte, data []byte, last bool) error

Write converts the data into HTTP2 data frame and sends it out. Non-nil error is returns if it fails (e.g., framing error, transport error).

func (*H2Transport) WriteHeader

func (t *H2Transport) WriteHeader(s *H2Stream) error

WriteHeader sends the header metadata md back to the client.

type NewStreamError

type NewStreamError struct {
	Err error

	AllowTransparentRetry bool
}

NewStreamError wraps an error and reports additional information. Typically NewStream errors result in transparent retry, as they mean nothing went onto the wire. However, there are two notable exceptions:

  1. If the stream headers violate the max header list size allowed by the server. It's possible this could succeed on another transport, even if it's unlikely, but do not transparently retry.
  2. If the credentials errored when requesting their headers. In this case, it's possible a retry can fix the problem, but indefinitely transparently retrying is not appropriate as it is likely the credentials, if they can eventually succeed, would need I/O to do so.

func (NewStreamError) Error

func (e NewStreamError) Error() string

type Options

type Options struct {
	// Last indicates whether this write is the last piece for
	// this stream.
	Last bool
}

Options provides additional hints and information for message transmission.

type ServerConfig

type ServerConfig struct {
	H2Config

	MaxStreams      uint32
	HeaderTableSize *uint32
	KeepaliveParams ServerParameters
	KeepalivePolicy EnforcementPolicy
}

ServerConfig consists of all the configurations to establish a server transport.

type ServerParameters

type ServerParameters struct {
	// MaxConnectionIdle is a duration for the amount of time after which an
	// idle connection would be closed by sending a GoAway. Idleness duration is
	// defined since the most recent time the number of outstanding RPCs became
	// zero or the connection establishment.
	MaxConnectionIdle time.Duration // The current default value is infinity.
	// MaxConnectionAge is a duration for the maximum amount of time a
	// connection may exist before it will be closed by sending a GoAway. A
	// random jitter of +/-10% will be added to MaxConnectionAge to spread out
	// connection storms.
	MaxConnectionAge time.Duration // The current default value is infinity.
	// MaxConnectionAgeGrace is an additive period after MaxConnectionAge after
	// which the connection will be forcibly closed.
	MaxConnectionAgeGrace time.Duration // The current default value is infinity.
	// After a duration of this time if the server doesn't see any activity it
	// pings the client to see if the transport is still alive.
	// If set below 1s, a minimum value of 1s will be used instead.
	Time time.Duration // The current default value is 2 hours.
	// After having pinged for keepalive check, the server waits for a duration
	// of Timeout and if no activity is seen even after that the connection is
	// closed.
	Timeout time.Duration // The current default value is 20 seconds.
}

ServerParameters is used to set keepalive and max-age parameters on the server-side.

type Status

type Status struct {

	// The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
	Code int
	// A developer-facing error message, which should be in English. Any
	// user-facing error message should be localized and sent in the
	// [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
	Message string
	// A list of messages that carry the error details.  There is a common set of
	// message types for APIs to use.
	Details [][]byte

	Err error
}

Status is the gRPC trailer. It can also be used in regular H2 (despite the grpc keys) instead of inventing new names. It implements error interface.

func (*Status) Error

func (s *Status) Error() string

type WebTransport

type WebTransport struct {
}

Directories

Path Synopsis
Package http2 implements the HTTP/2 protocol.
Package http2 implements the HTTP/2 protocol.
Package hpack implements HPACK, a compression format for efficiently representing HTTP header fields in the context of HTTP/2.
Package hpack implements HPACK, a compression format for efficiently representing HTTP header fields in the context of HTTP/2.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL