minq

package module
v0.0.0-...-a99b583 Latest Latest
Warning

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

Go to latest
Published: Jul 15, 2017 License: MIT Imports: 17 Imported by: 0

README

A mink forming a Q

minq -- A minimal QUIC stack

Minq is a minimal implementation of QUIC, as documented at https://quicwg.github.io/. Minq partly implements draft-05 (it advertises -04 but it's actually more like the editor's copy) with TLS 1.3 draft-20 or draft-21.

Currently it will do:

  • A 1-RTT handshake (with self-generated and unverified certificates)
  • Some ACK processing
  • Primitive retransmission (manual, no timers)
  • 1-RTT application data
  • Exchange of stream close (though this doesn't really have much impact)

Important missing pieces for the first implementation draft include:

  • Handling ACK ranges
  • Real timeout and retransmission support

Other defects include:

  • Doesn't properly clean up state, so things will just grow without bound
  • TLS configuration and verification
  • A huge other pile of unknown and known defects.

WARNING

Minq is absolutely not ready for any kind of production use and should only be used for testing.

Quick Start (untested but should be rightish)

cd ${GOPATH}/src
# The following line will produce a complaint about mint.CipherSuiteParams. Ignore it.
go get github.com/ekr/minq
cd github.com/bifurcation/mint
git remote add ekr https://www.github.com/ekr/mint
git fetch ekr
git checkout minq_draft_21
cd ../../ekr/minq
go test

This should produce something like this:

Result =  010002616263
Result2 =  010002616263
Result =  0102616263
Result2 =  0102616263
{1 2 [97 98 99]}
{1 1 [8 16]}
{3 2 [8 16 24 32]}
Checking client state
Checking server state
Encoded frame  ab00deadbeef0000000000000001
Encoded frame  bb0100deadbeef00000000000000010e00000001
Result =  820123456789abcdefdeadbeefff000001
Result2 =  820123456789abcdefdeadbeefff000001
PASS
ok  	github.com/ekr/minq	1.285s

It's the "ok" at the end that's important.

There are two test programs that live in minq/bin/client and minq/bin/server. The server is an echo server that upcases the returned data. The client is just a passthrough.

In ${GOPATH}/src/github.com/ekr, doing

go run minq/bin/server/main.go
go run minq/bin/client/main.go

In separate windows should have the desired result.

Logging

To enable logging, set the MINQ_LOG environment variable, as in MINQ_LOG=connection go test. Valid values are:

// Pre-defined log types
const (
	logTypeAead       = "aead"
	logTypeCodec      = "codec"
	logTypeConnBuffer = "connbuffer"
	logTypeConnection = "connection"
	logTypeAck        = "ack"
	logTypeFrame      = "frame"
	logTypeHandshake  = "handshake"
	logTypeTls        = "tls"
	logTypeTrace      = "trace"
	logTypeServer     = "server"
	logTypeUdp        = "udp"
)

Multiple log levels can be separated by commas.

Mint

Minq depends on Mint (https://www.github.com/bifurcation/mint) for TLS. There are some changes to Mint to support QUIC that haven't been merged yet, so in the meantime you will want the following branch: https://github.com/ekr/mint/tree/minq_draft_21 (or https://github.com/ekr/mint/tree/minq_draft_20 for draft-20).

Documentation

Overview

Package minq is a minimal implementation of QUIC, as documented at https://quicwg.github.io/. Minq partly implements draft-04.

Index

Constants

View Source
const (
	RoleClient = 1
	RoleServer = 2
)
View Source
const (
	StateInit                   = State(1)
	StateWaitClientInitial      = State(2)
	StateWaitServerFirstFlight  = State(3)
	StateWaitClientSecondFlight = State(4)
	StateEstablished            = State(5)
	StateClosed                 = State(6)
)

Variables

View Source
var ErrorDestroyConnection = fmt.Errorf("Terminate connection")
View Source
var ErrorReceivedVersionNegotiation = fmt.Errorf("Received a version negotiation packet advertising a different version than ours")
View Source
var ErrorWouldBlock = fmt.Errorf("Would have blocked")

Return codes.

Functions

This section is empty.

Types

type Connection

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

Connection represents a QUIC connection. Clients can make connections directly but servers should create a minq.Server object which creates Connections as a side effect.

The control discipline is entirely operated by the consuming application. It has two major responsibilities:

  1. Deliver any incoming datagrams using Input()
  2. Periodically call CheckTimer(). In future there will be some way to know how often to call it, but right now it treats every call to CheckTimer() as timer expiry.

The application provides a handler object which the Connection calls to notify it of various events.

func NewConnection

func NewConnection(trans Transport, role uint8, tls TlsConfig, handler ConnectionHandler) *Connection

Create a new QUIC connection. Should only be used with role=RoleClient, though we use it with RoleServer internally.

func (*Connection) CheckTimer

func (c *Connection) CheckTimer() (int, error)

Check the connection's timer and process any events whose time has expired in the meantime. This includes sending retransmits, etc.

func (*Connection) Close

func (c *Connection) Close()

Close a connection.

func (*Connection) CreateStream

func (c *Connection) CreateStream() *Stream

Create a stream on a given connection. Returns the created stream.

func (*Connection) GetState

func (c *Connection) GetState() State

Get the current state of a connection.

func (*Connection) GetStream

func (c *Connection) GetStream(id uint32) *Stream

Get the stream with stream id |id|. Returns nil if no such stream exists.

func (*Connection) Id

func (c *Connection) Id() ConnectionId

Get the connection ID for a connection. Returns 0 if you are a client and the first server packet hasn't been received.

func (*Connection) Input

func (c *Connection) Input(p []byte) error

Provide a packet to the connection.

TODO(ekr@rtfm.com): when is error returned?

func (*Connection) SetHandler

func (c *Connection) SetHandler(h ConnectionHandler)

Set the handler class for a given connection.

type ConnectionHandler

type ConnectionHandler interface {
	// The connection has changed state to state |s|
	StateChanged(s State)

	// A new stream has been created (by receiving a frame
	// from the other side. |s| contains the stream.
	NewStream(s *Stream)

	// Stream |s| is now readable.
	StreamReadable(s *Stream)
}

Interface for the handler object which the Connection will call to notify of events on the connection.

type ConnectionId

type ConnectionId uint64

type ErrorCode

type ErrorCode uint32

Protocol errors

type Server

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

Server represents a QUIC server. A server can be fed an arbitrary number of packets and will create Connections as needed, passing each packet to the right connection.

func NewServer

func NewServer(factory TransportFactory, tls TlsConfig, handler ServerHandler) *Server

Create a new QUIC server with the provide TLS config.

func (*Server) Input

func (s *Server) Input(addr *net.UDPAddr, data []byte) (*Connection, error)

Pass an incoming packet to the Server.

type ServerHandler

type ServerHandler interface {
	// A new connection has been created and can be found in |c|.
	NewConnection(c *Connection)
}

Interface for the handler object which the Server will call to notify of events.

type State

type State uint8

The state of a QUIC connection.

type Stream

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

A single QUIC stream.

func (*Stream) Id

func (s *Stream) Id() uint32

Get the ID of a stream.

func (*Stream) Read

func (s *Stream) Read(b []byte) (int, error)

Read from a stream into a buffer. Up to |len(b)| bytes will be read, and the number of bytes returned is in |n|.

func (*Stream) Write

func (s *Stream) Write(b []byte)

Write bytes to a stream. This function always succeeds, though the bytes may end up being buffered.

type TlsConfig

type TlsConfig struct {
}

type Transport

type Transport interface {
	Send(p []byte) error
}

Interface for an object to send packets. Each Transport is bound to some particular remote address (or in testing we just use a mock which sends the packet into a queue).

type TransportFactory

type TransportFactory interface {
	// contains filtered or unexported methods
}

TransportFactory makes transports bound to a specific remote address.

type UdpTransport

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

func NewUdpTransport

func NewUdpTransport(u *net.UDPConn, r *net.UDPAddr) *UdpTransport

func (*UdpTransport) Send

func (t *UdpTransport) Send(p []byte) error

type UdpTransportFactory

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

func NewUdpTransportFactory

func NewUdpTransportFactory(sock *net.UDPConn) *UdpTransportFactory

type VersionNumber

type VersionNumber uint32

The protocol version number.

Directories

Path Synopsis
bin
client command
server command

Jump to

Keyboard shortcuts

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