seqs

package module
v0.0.0-...-1201bab Latest Latest
Warning

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

Go to latest
Published: May 27, 2024 License: BSD-3-Clause Imports: 11 Imported by: 6

README

seqs

go.dev reference Go Report Card codecov Go sourcegraph

seqs is what is commonly referred to as a userspace IP implementation. It handles:

  • Ethernet protocol
  • IP packet marshalling to sub-protocols:
    • ARP requests and responses
    • UDP packet handling
    • DHCP client requests and DHCP server
    • TCP connections over IP with support for multiple listeners on same port. These implement net.Conn and net.Listener interfaces. See stacks/tcpconn.go
    • HTTP: Algorithm to reuse heap memory between requests and avoid allocations. See httpx package
    • NTP client for resolving time offset to a NTP server
Example of use
// stack works by having access to Ethernet packet sending
// and processing. NIC is our physical link to the internet.
var NIC NetworkInterfaceCard = getNIC()

stack := stacks.NewPortStack(stacks.PortStackConfig{
    MAC:             MAC,
    MaxOpenPortsTCP: 1,
    MaxOpenPortsUDP: 1,
    MTU:             2048,
})
// stack.RecvEth should be called on receiving an ethernet packet. It should NOT block.
NIC.SetRecvEthHandle(stack.RecvEth)

// Static IP setting.
ip := netip.AddrFrom4([4]byte{192, 168, 1, 45}) 
stack.SetAddr(ip)

// Or can request an address via DHCP.
dhcpClient := stacks.NewDHCPClient(stack, dhcp.DefaultClientPort)
err = dhcpClient.BeginRequest(stacks.DHCPRequestConfig{
    RequestedAddr: netip.AddrFrom4([4]byte{192, 168, 1, 69}),
    Xid:           0x12345678,
    Hostname:      "tinygo-pico",
})
if err != nil {
    panic(err)
}

fmt.Println("Start DHCP...")
for !dhcpClient.Done() {
    doNICPoll(NIC)
    time.Sleep(time.Second / 10)
}

offeredIP := dhcpClient.Offer()
fmt.Println("got offer:", offeredIP)
stack.SetAddr(offeredIP)

How to use seqs

go mod download github.com/soypat/seqs@latest
History - Precursors to seqs

Before seqs there was:

  • ether-swtch - First known instance of a (barely) working TCP/IP stack in Go working on embedded systems, circa June 2021. Could blink an Arduino UNO's LED via HTTP (!). Famously bad design, code, performance, readability.
  • dgrams - Library prepared for Pico W's wifi chip. Already shows similarities with seqs. Circa May 2023.

Documentation

Overview

package seqs implements TCP control flow.

Transmission Control Block

The Transmission Control Block (TCB) is the core data structure of TCP. It stores core state of the TCP connection such as the send and receive sequence number spaces, the current state of the connection, and the pending control segment flags.

Values and Sizes

All arithmetic dealing with sequence numbers must be performed modulo 2**32 which brings with it subtleties to computer modulo arithmetic.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func InRange

func InRange(v, a, b Value) bool

InRange checks if v is in the range [a,b) (modulo 32), i.e., a <= v < b.

func InWindow

func InWindow(v, first Value, size Size) bool

InWindow checks if v is in the window that starts at 'first' and spans 'size' sequence numbers (modulo 32).

func LessThan

func LessThan(v, w Value) bool

LessThan checks if v is before w (modulo 32) i.e., v < w.

func LessThanEq

func LessThanEq(v, w Value) bool

LessThanEq returns true if v==w or v is before (modulo 32) i.e., v < w.

func StringExchange

func StringExchange(seg Segment, A, B State, invertDir bool) string

StringExchange returns a string representation of a segment exchange over a network in RFC9293 styled visualization. invertDir inverts the arrow directions. i.e:

SynSent --> <SEQ=300><ACK=91>[SYN,ACK]  --> SynRcvd

Types

type ControlBlock

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

ControlBlock is a partial Transmission Control Block (TCB) implementation as per RFC 9293 in section 3.3.1. In contrast with the description in RFC9293, this implementation is limited to receiving only sequential segments. This means buffer management is left up entirely to the user of the ControlBlock. Use ControlBlock as the building block that solves Sequence Number calculation and validation in a full TCP implementation.

A ControlBlock's internal state is modified by the available "System Calls" as defined in RFC9293, such as Close, Listen/Open, Send, and Receive. Sent and received data is represented with the Segment struct type.

func (*ControlBlock) Close

func (tcb *ControlBlock) Close() (err error)

Close implements a passive/active closing of a connection. It does not immediately delete the TCB but initiates the process so that pending outgoing segments initiate the closing process. After a call to Close users should not send more data. Close returns an error if the connection is already closed or closing.

func (*ControlBlock) HasPending

func (tcb *ControlBlock) HasPending() bool

HasPending returns true if there is a pending control segment to send. Calls to Send will advance the pending queue.

func (*ControlBlock) ISS

func (tcb *ControlBlock) ISS() Value

ISS returns the initial sequence number of the connection that was defined on a call to Open by user.

func (*ControlBlock) IncomingIsKeepalive

func (tcb *ControlBlock) IncomingIsKeepalive(incomingSegment Segment) bool

IncomingIsKeepalive checks if an incoming segment is a keepalive segment. Segments which are keepalives should not be passed into Recv or Send methods.

func (*ControlBlock) MakeKeepalive

func (tcb *ControlBlock) MakeKeepalive() Segment

MakeKeepalive creates a TCP keepalive segment. This segment should not be passed into Recv or Send methods.

func (*ControlBlock) MaxInFlightData

func (tcb *ControlBlock) MaxInFlightData() Size

MaxInFlightData returns the maximum size of a segment that can be sent by taking into account the send window size and the unacked data. Returns 0 before StateSynRcvd.

func (*ControlBlock) Open

func (tcb *ControlBlock) Open(iss Value, wnd Size, state State) (err error)

Open implements a passive/active opening of a connection. state must be StateListen or StateSynSent.

func (*ControlBlock) PendingSegment

func (tcb *ControlBlock) PendingSegment(payloadLen int) (_ Segment, ok bool)

PendingSegment calculates a suitable next segment to send from a payload length. It does not modify the ControlBlock state or pending segment queue.

func (*ControlBlock) Recv

func (tcb *ControlBlock) Recv(seg Segment) (err error)

Recv processes a segment that is being received from the network. It updates the TCB if there is no error. The ControlBlock can only receive segments that are the next expected sequence number which means the caller must handle the out-of-order case and buffering that comes with it.

func (*ControlBlock) RecvNext

func (tcb *ControlBlock) RecvNext() Value

RecvNext returns the next sequence number expected to be received from remote. This implementation will reject segments that are not the next expected sequence. RecvNext returns 0 before StateSynRcvd.

func (*ControlBlock) RecvWindow

func (tcb *ControlBlock) RecvWindow() Size

RecvWindow returns the receive window size. If connection is closed will return 0.

func (*ControlBlock) Send

func (tcb *ControlBlock) Send(seg Segment) error

Send processes a segment that is being sent to the network. It updates the TCB if there is no error.

func (*ControlBlock) SetLogger

func (tcb *ControlBlock) SetLogger(log *slog.Logger)

SetLogger sets the logger to be used by the ControlBlock.

func (*ControlBlock) SetRecvWindow

func (tcb *ControlBlock) SetRecvWindow(wnd Size)

SetWindow sets the local receive window size. This represents the maximum amount of data that is permitted to be in flight.

func (*ControlBlock) State

func (tcb *ControlBlock) State() State

State returns the current state of the connection.

type Flags

type Flags uint16

Flags is a TCP flags masked implementation i.e: SYN, FIN, ACK.

const (
	FlagFIN Flags = 1 << iota // FlagFIN - No more data from sender.
	FlagSYN                   // FlagSYN - Synchronize sequence numbers.
	FlagRST                   // FlagRST - Reset the connection.
	FlagPSH                   // FlagPSH - Push function.
	FlagACK                   // FlagACK - Acknowledgment field significant.
	FlagURG                   // FlagURG - Urgent pointer field significant.
	FlagECE                   // FlagECE - ECN-Echo has a nonce-sum in the SYN/ACK.
	FlagCWR                   // FlagCWR - Congestion Window Reduced.
	FlagNS                    // FlagNS  - Nonce Sum flag (see RFC 3540).
)

func (Flags) AppendFormat

func (flags Flags) AppendFormat(b []byte) []byte

AppendFormat appends a human readable flag string to b returning the extended buffer.

func (Flags) HasAll

func (flags Flags) HasAll(mask Flags) bool

HasAll checks if mask bits are all set in the receiver flags.

func (Flags) HasAny

func (flags Flags) HasAny(mask Flags) bool

HasAny checks if one or more mask bits are set in receiver flags.

func (Flags) String

func (flags Flags) String() string

StringFlags returns human readable flag string. i.e:

"[SYN,ACK]"

Flags are printed in order from LSB (FIN) to MSB (NS). All flags are printed with length of 3, so a NS flag will end with a space i.e. [ACK,NS ]

type RejectError

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

RejectError represents an error that arises during admission of a segment into the Transmission Control Block logic in which the packet cannot be processed by the TCB.

func (*RejectError) Error

func (e *RejectError) Error() string

type Segment

type Segment struct {
	SEQ     Value // sequence number of first octet of segment. If SYN is set it is the initial sequence number (ISN) and the first data octet is ISN+1.
	ACK     Value // acknowledgment number. If ACK is set it is sequence number of first octet the sender of the segment is expecting to receive next.
	DATALEN Size  // The number of octets occupied by the data (payload) not counting SYN and FIN.
	WND     Size  // segment window
	Flags   Flags // TCP flags.
}

Segment represents an incoming/outgoing TCP segment in the sequence space.

func (*Segment) LEN

func (seg *Segment) LEN() Size

LEN returns the length of the segment in octets including SYN and FIN flags.

func (*Segment) Last

func (seg *Segment) Last() Value

End returns the sequence number of the last octet of the segment.

type Size

type Size uint32

Size represents the size (length) of a sequence number window.

func Sizeof

func Sizeof(v, w Value) Size

Size calculates the size of the window defined by [v, w).

type State

type State uint8

State enumerates states a TCP connection progresses through during its lifetime.

const (
	// CLOSED - represents no connection state at all. Is not a valid state of the TCP state machine but rather a pseudo-state pre-initialization.
	StateClosed State = iota
	// LISTEN - represents waiting for a connection request from any remote TCP and port.
	StateListen
	// SYN-RECEIVED - represents waiting for a confirming connection request acknowledgment
	// after having both received and sent a connection request.
	StateSynRcvd
	// SYN-SENT - represents waiting for a matching connection request after having sent a connection request.
	StateSynSent
	// ESTABLISHED - represents an open connection, data received can be delivered
	// to the user.  The normal state for the data transfer phase of the connection.
	StateEstablished
	// FIN-WAIT-1 - represents waiting for a connection termination request
	// from the remote TCP, or an acknowledgment of the connection
	// termination request previously sent.
	StateFinWait1
	// FIN-WAIT-2 - represents waiting for a connection termination request
	// from the remote TCP.
	StateFinWait2
	// CLOSING - represents waiting for a connection termination request
	// acknowledgment from the remote TCP.
	StateClosing
	// TIME-WAIT - represents waiting for enough time to pass to be sure the remote
	// TCP received the acknowledgment of its connection termination request.
	StateTimeWait
	// CLOSE-WAIT - represents waiting for a connection termination request
	// from the local user.
	StateCloseWait
	// LAST-ACK - represents waiting for an acknowledgment of the
	// connection termination request previously sent to the remote TCP
	// (which includes an acknowledgment of its connection termination request).
	StateLastAck
)

func (State) IsClosed

func (s State) IsClosed() bool

IsClosed returns true if the connection closed and can possibly relieved of all state related to the remote connection. It returns true if Closed or in TimeWait.

func (State) IsClosing

func (s State) IsClosing() bool

IsClosing returns true if the connection is in a closing state but not yet terminated (relieved of remote connection state). Returns false for Closed pseudo state.

func (State) IsPreestablished

func (s State) IsPreestablished() bool

IsPreestablished returns true if the connection is in a state preceding the established state. Returns false for Closed pseudo state.

func (State) IsSynchronized

func (s State) IsSynchronized() bool

IsSynchronized returns true if the connection has gone through the Established state.

func (State) String

func (i State) String() string

type Value

type Value uint32

Value represents the value of a sequence number.

func Add

func Add(v Value, s Size) Value

Add calculates the sequence number following the [v, v+s) window.

func DefaultNewISS

func DefaultNewISS(t time.Time) Value

DefaultNewISS returns a new initial send sequence number. It's implementation is suggested by RFC9293.

func (*Value) UpdateForward

func (v *Value) UpdateForward(s Size)

UpdateForward updates v such that it becomes v + s.

Directories

Path Synopsis
eth
package eth implements Ethernet, ARP, IP, TCP among other datagram and protocol frame processing and manipulation tools.
package eth implements Ethernet, ARP, IP, TCP among other datagram and protocol frame processing and manipulation tools.
dns
Code generated by "stringer" command for the types within this file; DO NOT EDIT.
Code generated by "stringer" command for the types within this file; DO NOT EDIT.
ntp
package ntp implements the NTP protocol as described in RFC 5905.
package ntp implements the NTP protocol as described in RFC 5905.

Jump to

Keyboard shortcuts

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