http2

package module
v0.0.0-...-74df219 Latest Latest
Warning

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

Go to latest
Published: Mar 14, 2024 License: MIT Imports: 18 Imported by: 0

README

tinygrpc

A tiny implementation of HTTP2 and gRPC server, written for study purposes, not for practical use at this moment.

This implementation supports:

  • HTTP/1.1 protocol upgrade or prior-knowledge (h2c handshake)
  • minimal implementation for HTTP2 flow including multiplexing, WINDOW_UPDATE and PING frames
  • gRPC unary calls
  • gRPC streaming implementation with minimal support for google.golang.org/grpc.ServiceDesc

This implementation does NOT support for now:

  • ALPN TLS h2 handshake
  • client settings accounting (HTTP2-Settings header, SETTINGS and WINDOW_UPDATE frames)
  • GOAWAY, RST_STREAM frames
  • splitting responses into parts (multiple DATA and HEADER frames)
  • assembling multiplexed requests from parts for incoming gRPC calls
  • correct return of non-fatal errors as statuses
  • initial HTTP/1 request greater than RecvBufferSize (16KB)

The main functionality tests are in the file conn_test.go.

Feel free to run $ go test -count 1 -v ./... ;-)

Documentation

Index

Constants

View Source
const (
	ErrorCodeNoError            = ErrorCode(0x0)
	ErrorCodeProtocolError      = ErrorCode(0x1)
	ErrorCodeInternalError      = ErrorCode(0x2)
	ErrorCodeFlowControlError   = ErrorCode(0x3)
	ErrorCodeSettingsTimeout    = ErrorCode(0x4)
	ErrorCodeStreamClosed       = ErrorCode(0x5)
	ErrorCodeFrameSizeError     = ErrorCode(0x6)
	ErrorCodeRefusedStream      = ErrorCode(0x7)
	ErrorCodeCancel             = ErrorCode(0x8)
	ErrorCodeCompressionError   = ErrorCode(0x9)
	ErrorCodeConnectError       = ErrorCode(0xa)
	ErrorCodeEnhanceYourCalm    = ErrorCode(0xb)
	ErrorCodeInadequateSecurity = ErrorCode(0xc)
	ErrorCodeHTTP11Required     = ErrorCode(0xd)
)
View Source
const (
	FlagAck = FrameFlags(0x1)

	FlagEndStream  = FrameFlags(0x1)
	FlagEndHeaders = FrameFlags(0x4)
	FlagPadded     = FrameFlags(0x8)
	FlagPriority   = FrameFlags(0x20)
)
View Source
const (
	FrameTypeData         = FrameType(0)
	FrameTypeHeaders      = FrameType(1)
	FrameTypePriority     = FrameType(2)
	FrameTypeRstStream    = FrameType(3)
	FrameTypeSettings     = FrameType(4)
	FrameTypePushPromise  = FrameType(5)
	FrameTypePing         = FrameType(6)
	FrameTypeGoaway       = FrameType(7)
	FrameTypeWindowUpdate = FrameType(8)
	FrameTypeContinuation = FrameType(9)
)
View Source
const (
	SettingsHeaderTableSize      = SettingsType(0x1)
	SettingsEnablePush           = SettingsType(0x2)
	SettingsMaxConcurrentStreams = SettingsType(0x3)
	SettingsInitialWindowSize    = SettingsType(0x4)
	SettingsMaxFrameSize         = SettingsType(0x5)
	SettingsMaxHeaderListSize    = SettingsType(0x6)
)
View Source
const (
	RecvBufferSize = 16 * 1024
)

Variables

View Source
var (
	ErrWrongRequestLine   = fmt.Errorf("wrong request line")
	ErrTooLongRequest     = fmt.Errorf("request is too long")
	ErrWrongUpgradeHeader = fmt.Errorf("wrong Upgrade header value")
)

Functions

This section is empty.

Types

type BufReader

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

BufReader is a wrapper around net.Conn which for reading first reads from the internal buffer (prepend), and then from the connection (src)

func NewBufReader

func NewBufReader(src net.Conn, prepend []byte) *BufReader

func (*BufReader) Close

func (b *BufReader) Close() error

func (*BufReader) LocalAddr

func (b *BufReader) LocalAddr() net.Addr

func (*BufReader) Read

func (b *BufReader) Read(p []byte) (n int, err error)

func (*BufReader) RemoteAddr

func (b *BufReader) RemoteAddr() net.Addr

func (*BufReader) SetDeadline

func (b *BufReader) SetDeadline(t time.Time) error

func (*BufReader) SetReadDeadline

func (b *BufReader) SetReadDeadline(t time.Time) error

func (*BufReader) SetWriteDeadline

func (b *BufReader) SetWriteDeadline(t time.Time) error

func (*BufReader) Write

func (b *BufReader) Write(p []byte) (n int, err error)

type Conn

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

Conn implements HTTP/2 connection

func (*Conn) Close

func (c *Conn) Close() error

func (*Conn) RecvFrame

func (c *Conn) RecvFrame(ctx context.Context) (Frame, error)

func (*Conn) RecvRequestBody

func (c *Conn) RecvRequestBody(ctx context.Context, request *Request) error

RecvRequestBody receives only DATA frames until gets FlagEndStream

func (*Conn) RecvRequestHeaders

func (c *Conn) RecvRequestHeaders(ctx context.Context) (*Request, error)

RecvRequestHeaders receives only HEADER frames until gets FlagEndHeaders

func (*Conn) SendData

func (c *Conn) SendData(streamId uint32, flags FrameFlags, body []byte) error

func (*Conn) SendHeaders

func (c *Conn) SendHeaders(streamId uint32, flags FrameFlags, headers []hpack.HeaderField) error

func (*Conn) SendTrailerFrame

func (c *Conn) SendTrailerFrame(streamId uint32, headers []hpack.HeaderField) error

func (*Conn) ServerHandshake

func (c *Conn) ServerHandshake(ctx context.Context) (*Request, error)

type DataFrame

type DataFrame struct {
	FrameHdr
	Data []byte
}

func (*DataFrame) ReadPayload

func (f *DataFrame) ReadPayload(frameHdr *FrameHdr, payload []byte) error

func (*DataFrame) WritePayload

func (f *DataFrame) WritePayload(dst []byte) []byte

type ErrProtocolError

type ErrProtocolError struct {
	Descr string
}

func (*ErrProtocolError) Error

func (e *ErrProtocolError) Error() string

func (*ErrProtocolError) Http2Error

func (e *ErrProtocolError) Http2Error() string

type ErrWrongHTTPRequest

type ErrWrongHTTPRequest struct {
	Cause error
}

func NewErrWrongHTTPRequest

func NewErrWrongHTTPRequest(cause error) *ErrWrongHTTPRequest

func (*ErrWrongHTTPRequest) Error

func (e *ErrWrongHTTPRequest) Error() string

type ErrorCode

type ErrorCode uint32

func (ErrorCode) String

func (e ErrorCode) String() string

type Frame

type Frame interface {
	Hdr() *FrameHdr

	// ReadPayload fills a frame from payload.
	//
	// payload MUST not be used after method call
	ReadPayload(frameHdr *FrameHdr, payload []byte) error
}

type FrameFlags

type FrameFlags uint8

func (FrameFlags) String

func (f FrameFlags) String() string

type FrameHdr

type FrameHdr struct {
	Length   uint32
	Type     FrameType
	Flags    FrameFlags
	StreamId uint32
}

func (*FrameHdr) Hdr

func (fh *FrameHdr) Hdr() *FrameHdr

type FrameType

type FrameType uint8

func (FrameType) String

func (f FrameType) String() string

type GoawayFrame

type GoawayFrame struct {
	FrameHdr
	LastStreamId uint32
	ErrorCode    ErrorCode
	DebugData    []byte
}

func (*GoawayFrame) ReadPayload

func (f *GoawayFrame) ReadPayload(frameHdr *FrameHdr, payload []byte) error

func (*GoawayFrame) WritePayload

func (f *GoawayFrame) WritePayload(dst []byte) []byte

type Handler

type Handler func(ctx context.Context, request *Request, response *Response) error

type HeadersFrame

type HeadersFrame struct {
	FrameHdr
	Exclusive           bool   // A single bit flag indicating that the stream dependency is exclusive. This field is only present if the PRIORITY flag is set.
	StreamIdDepend      uint32 // This field is only present if the PRIORITY flag is set.
	Weight              uint8  // This field is only present if the PRIORITY flag is set.
	HeaderBlockFragment []hpack.HeaderField
	// contains filtered or unexported fields
}

func (*HeadersFrame) ReadPayload

func (f *HeadersFrame) ReadPayload(frameHdr *FrameHdr, payload []byte) error

func (*HeadersFrame) WritePayload

func (f *HeadersFrame) WritePayload(dst []byte, encoder *hpack.Encoder, encoderBuf *bytes.Buffer) []byte

type PingFrame

type PingFrame struct {
	FrameHdr
	Data uint64
}

func (*PingFrame) ReadPayload

func (f *PingFrame) ReadPayload(frameHdr *FrameHdr, payload []byte) error

func (*PingFrame) WritePayload

func (f *PingFrame) WritePayload(dst []byte) []byte

type Request

type Request struct {
	Method      string
	URI         string
	HTTPVersion string

	StreamId uint32

	Headers map[string]string

	Body []byte
	// contains filtered or unexported fields
}

func NewHTTPRequest

func NewHTTPRequest(streamId uint32) *Request

type Response

type Response struct {
	Status  uint64
	Headers map[string]string
	Body    []byte
}

type RstStreamFrame

type RstStreamFrame struct {
	FrameHdr
	ErrorCode int32
}

func (*RstStreamFrame) ReadPayload

func (f *RstStreamFrame) ReadPayload(frameHdr *FrameHdr, payload []byte) error

func (*RstStreamFrame) WritePayload

func (f *RstStreamFrame) WritePayload(dst []byte) []byte

type Server

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

func NewServer

func NewServer() *Server

func (*Server) Listen

func (s *Server) Listen(l net.Listener)

Listen adds listener for future Serve()

You can initialize a listener:

l, _ := net.Listen("tcp", ":80")
NewServer().Listen(l)

func (*Server) ListenTCP

func (s *Server) ListenTCP(addr string) error

func (*Server) ListenTLS

func (s *Server) ListenTLS(l net.Listener, certs ...tls.Certificate)

ListenTLS wraps listener to TLS with certs

You can load a cert from pair:

l, _ := net.Listen("tcp", ":443")
cert, _ := tls.X509KeyPair([]byte(certPEMBlock), []byte(keyPEMBlock))
NewServer().ListenTLS(l, cert)

func (*Server) Serve

func (s *Server) Serve(ctx context.Context) error

func (*Server) SetGRPPCHandler

func (s *Server) SetGRPPCHandler(desc grpc.ServiceDesc, h Handler)

func (*Server) SetGRPPCStreamHandler

func (s *Server) SetGRPPCStreamHandler(desc grpc.ServiceDesc, h StreamHandler)

func (*Server) SetHTTPHandler

func (s *Server) SetHTTPHandler(h Handler)

type Settings

type Settings struct {
	HeaderTableSize      uint32
	EnablePush           bool
	MaxConcurrentStreams uint32
	InitialWindowSize    uint32
	MaxFrameSize         uint32
	MaxHeaderListSize    uint32
}

func GetDefaultSettings

func GetDefaultSettings() Settings

func (*Settings) ToSettingsFrame

func (s *Settings) ToSettingsFrame() *SettingsFrame

func (*Settings) UpdateFromSettingsFrame

func (s *Settings) UpdateFromSettingsFrame(frame *SettingsFrame)

type SettingsFrame

type SettingsFrame struct {
	FrameHdr
	Params []SettingsFrameParam
}

func (*SettingsFrame) ReadPayload

func (f *SettingsFrame) ReadPayload(frameHdr *FrameHdr, payload []byte) error

func (*SettingsFrame) WritePayload

func (f *SettingsFrame) WritePayload(dst []byte) []byte

type SettingsFrameParam

type SettingsFrameParam struct {
	Id    SettingsType
	Value uint32
}

type SettingsType

type SettingsType uint8

func (SettingsType) String

func (s SettingsType) String() string

type StreamHandler

type StreamHandler func(ctx context.Context, request *Request, conn *Conn) error

type WindowUpdateFrame

type WindowUpdateFrame struct {
	FrameHdr
	WindowSizeIncrement uint32
}

func (*WindowUpdateFrame) ReadPayload

func (f *WindowUpdateFrame) ReadPayload(frameHdr *FrameHdr, payload []byte) error

func (*WindowUpdateFrame) WritePayload

func (f *WindowUpdateFrame) WritePayload(dst []byte) []byte

Jump to

Keyboard shortcuts

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