Documentation
¶
Overview ¶
Package vtcp implements a full, RFC-compliant TCP protocol engine operating on raw TCP segments. It is IP-agnostic and Ethernet-agnostic — callers provide a SegmentWriter callback for sending and feed incoming segments via HandleSegment.
Supported RFCs:
Index ¶
- Constants
- func BuildOptions(opts []Option) []byte
- func GetMSS(opts []Option) uint16
- func GetTimestamp(opts []Option) (tsVal, tsEcr uint32, ok bool)
- func GetWScale(opts []Option) int
- func HasSACKPerm(opts []Option) bool
- func RandUint32Exported() uint32
- func SeqAfter(a, b uint32) bool
- func SeqAfterEq(a, b uint32) bool
- func SeqBefore(a, b uint32) bool
- func SeqBeforeEq(a, b uint32) bool
- func SeqInRange(seq, lo, hi uint32) bool
- func SeqInRangeInclusive(seq, lo, hi uint32) bool
- type CongestionController
- type Conn
- func (c *Conn) Abort() [][]byte
- func (c *Conn) AcceptCookie(remoteSeq, ourISS uint32, mss uint16, initialData []byte) [][]byte
- func (c *Conn) AcceptSYN(syn Segment) [][]byte
- func (c *Conn) Close() error
- func (c *Conn) Connect(ctx context.Context) error
- func (c *Conn) Established() <-chan struct{}
- func (c *Conn) Flush(pkts [][]byte)
- func (c *Conn) HandleSegment(seg Segment) [][]byte
- func (c *Conn) LocalAddr() net.Addr
- func (c *Conn) Read(b []byte) (int, error)
- func (c *Conn) RemoteAddr() net.Addr
- func (c *Conn) SetDeadline(t time.Time) error
- func (c *Conn) SetReadDeadline(t time.Time) error
- func (c *Conn) SetWriteDeadline(t time.Time) error
- func (c *Conn) SetupForHandshake(iss uint32)
- func (c *Conn) State() State
- func (c *Conn) Write(b []byte) (int, error)
- func (c *Conn) Writer() SegmentWriter
- type ConnConfig
- type HighSpeed
- func (hs *HighSpeed) ExitRecovery()
- func (hs *HighSpeed) InRecovery() bool
- func (hs *HighSpeed) OnACK(bytesAcked uint32)
- func (hs *HighSpeed) OnDupACK() bool
- func (hs *HighSpeed) OnFastRetransmit(flightSize uint32, sndNxt uint32)
- func (hs *HighSpeed) OnTimeout()
- func (hs *HighSpeed) RecoverySeq() uint32
- func (hs *HighSpeed) SSThresh() uint32
- func (hs *HighSpeed) SendWindow() uint32
- type NewReno
- func (nr *NewReno) ExitRecovery()
- func (nr *NewReno) InRecovery() bool
- func (nr *NewReno) OnACK(bytesAcked uint32)
- func (nr *NewReno) OnDupACK() bool
- func (nr *NewReno) OnFastRetransmit(flightSize uint32, sndNxt uint32)
- func (nr *NewReno) OnTimeout()
- func (nr *NewReno) RecoverySeq() uint32
- func (nr *NewReno) SSThresh() uint32
- func (nr *NewReno) SendWindow() uint32
- type Option
- type RTOCalculator
- func (r *RTOCalculator) AckReceived(ack uint32) bool
- func (r *RTOCalculator) Backoff()
- func (r *RTOCalculator) InvalidateTiming()
- func (r *RTOCalculator) RTO() time.Duration
- func (r *RTOCalculator) SRTT() time.Duration
- func (r *RTOCalculator) Sample(rtt time.Duration)
- func (r *RTOCalculator) StartTiming(seq uint32)
- type RecvBuf
- type SACKBlock
- type SYNCookies
- type Segment
- type SegmentWriter
- type SendBuf
- func (s *SendBuf) Acknowledge(ack uint32) uint32
- func (s *SendBuf) AdvanceSent(n int)
- func (s *SendBuf) Available() int
- func (s *SendBuf) IsEmpty() bool
- func (s *SendBuf) IsSACKed(seq uint32) bool
- func (s *SendBuf) MarkSACKed(blocks []SACKBlock)
- func (s *SendBuf) NXT() uint32
- func (s *SendBuf) PeekUnsent(n int) []byte
- func (s *SendBuf) Pending() int
- func (s *SendBuf) RetransmitData(n int) []byte
- func (s *SendBuf) UNA() uint32
- func (s *SendBuf) Unacked() int
- func (s *SendBuf) Write(p []byte) int
- type State
Constants ¶
const ( FlagFIN = 0x01 FlagSYN = 0x02 FlagRST = 0x04 FlagPSH = 0x08 FlagACK = 0x10 FlagURG = 0x20 )
TCP header flag bits.
const ( DefaultMSS = 1460 DefaultWindowSize = 65535 DefaultSendBuf = 1 << 20 // 1 MB DefaultRecvBuf = 1 << 20 // 1 MB DefaultRTO = time.Second MinRTO = 200 * time.Millisecond MaxRTO = 60 * time.Second MaxRetries = 8 TimeWaitDuration = 2 * time.Second // shortened for virtual environments DefaultKeepaliveIdle = 300 * time.Second DefaultKeepaliveInterval = 15 * time.Second DefaultKeepaliveCount = 3 )
Default values.
const ( OptEnd byte = 0 OptNOP byte = 1 OptMSS byte = 2 OptWScale byte = 3 OptSACKPerm byte = 4 OptSACK byte = 5 OptTimestamp byte = 8 )
TCP option kinds.
Variables ¶
This section is empty.
Functions ¶
func BuildOptions ¶
BuildOptions serializes options into wire format, NOP-padded to 4-byte boundary.
func GetTimestamp ¶
GetTimestamp extracts TSval and TSecr from options. Returns ok=false if not present.
func GetWScale ¶
GetWScale extracts the window scale shift from options, returning -1 if not present.
func HasSACKPerm ¶
HasSACKPerm checks if SACK-Permitted is in the options.
func RandUint32Exported ¶
func RandUint32Exported() uint32
RandUint32Exported returns a cryptographically random uint32.
func SeqAfterEq ¶
SeqAfterEq reports whether a is after or equal to b.
func SeqBeforeEq ¶
SeqBeforeEq reports whether a is before or equal to b.
func SeqInRange ¶
SeqInRange reports whether seq is in [lo, hi) in sequence space.
func SeqInRangeInclusive ¶
SeqInRangeInclusive reports whether seq is in [lo, hi] in sequence space.
Types ¶
type CongestionController ¶
type CongestionController interface {
// OnACK is called when new bytes are acknowledged.
OnACK(bytesAcked uint32)
// OnDupACK is called on each duplicate ACK.
// Returns true if fast retransmit should be triggered (3rd dup ACK).
OnDupACK() bool
// OnTimeout is called on RTO timeout (loss detected via timeout).
OnTimeout()
// OnFastRetransmit is called when entering fast retransmit/recovery.
// sndNxt is the current SND.NXT, used as the recovery point.
OnFastRetransmit(flightSize uint32, sndNxt uint32)
// ExitRecovery is called when recovery is complete (all data acked past recovery point).
ExitRecovery()
// SendWindow returns the current congestion window in bytes.
SendWindow() uint32
// InRecovery reports whether the sender is in fast recovery.
InRecovery() bool
// RecoverySeq returns the sequence number that must be fully acknowledged
// to exit fast recovery (SND.NXT at the time recovery was entered).
RecoverySeq() uint32
}
CongestionController defines the interface for TCP congestion control algorithms.
type Conn ¶
type Conn struct {
// contains filtered or unexported fields
}
Conn is a single TCP connection implementing net.Conn. It runs the full TCP state machine (RFC 793) with congestion control (RFC 5681), retransmission (RFC 6298), and optional modern extensions.
Callers interact with Conn from two sides:
- Network side: HandleSegment (inbound), returned packets (outbound)
- Application side: Read, Write, Close (net.Conn interface)
All outgoing packets are returned from methods (never sent while holding the internal mutex), making Conn safe for synchronous delivery patterns.
func NewConn ¶
func NewConn(cfg ConnConfig) *Conn
NewConn creates a new TCP connection in the CLOSED state.
func (*Conn) AcceptCookie ¶
AcceptCookie initializes a Conn directly into StateEstablished from a validated SYN cookie handshake. Unlike AcceptSYN, this skips the SYN-RECEIVED state since the three-way handshake already completed (the SYN-ACK was sent statelessly via the cookie engine).
Parameters:
- remoteSeq: the remote's current sequence number (their ISN + 1)
- ourISS: our initial sequence number (the cookie value)
- mss: the negotiated MSS from the cookie
- initialData: any data carried in the completing ACK (may be nil)
func (*Conn) AcceptSYN ¶
AcceptSYN processes an incoming SYN for passive open. Sets up connection state, queues a SYN-ACK, and returns packets to send.
func (*Conn) Connect ¶
Connect initiates a TCP handshake (active open). Sends SYN and blocks until the handshake completes or ctx is cancelled.
func (*Conn) Established ¶
func (c *Conn) Established() <-chan struct{}
Established returns a channel that is closed when the connection reaches the ESTABLISHED state (three-way handshake complete).
func (*Conn) Flush ¶
Flush sends outgoing packets via the Writer, with a trampoline to prevent stack overflow from synchronous mutual recursion (e.g. two vclients on the same L2Hub). Callers should use this instead of iterating Writer() directly.
func (*Conn) HandleSegment ¶
HandleSegment processes an incoming TCP segment following RFC 9293 §3.10.7.4. Returns packets to send in response. The caller MUST send these.
func (*Conn) RemoteAddr ¶
func (*Conn) SetupForHandshake ¶
SetupForHandshake puts the connection into SYN-SENT state with the given ISN, allowing HandleSegment to process a SYN-ACK. This is used for manual handshake in tests where Connect() can't be used (synchronous delivery).
func (*Conn) Writer ¶
func (c *Conn) Writer() SegmentWriter
type ConnConfig ¶
type ConnConfig struct {
LocalAddr net.Addr
RemoteAddr net.Addr
LocalPort uint16
RemotePort uint16
Writer SegmentWriter
MSS int
// RFC 7323
NoWindowScaling bool // set true to disable window scaling (enabled by default)
EnableTimestamps bool
// RFC 2018
EnableSACK bool
// Congestion control: "newreno" or "highspeed" (default: "highspeed")
CongestionControl string
// RFC 1122 keepalive
Keepalive bool
KeepaliveIdle time.Duration
KeepaliveInterval time.Duration
KeepaliveCount int
SendBufSize int
RecvBufSize int
}
ConnConfig holds configuration for a new Conn.
type HighSpeed ¶
type HighSpeed struct {
// contains filtered or unexported fields
}
HighSpeed implements RFC 3649 HighSpeed TCP for large congestion windows. When cwnd <= Low_Window (38 segments), it behaves identically to NewReno. Above that threshold, it uses more aggressive increase/decrease functions that scale better on high-BDP networks.
func NewHighSpeed ¶
NewHighSpeed creates a HighSpeed TCP congestion controller (RFC 3649).
func (*HighSpeed) ExitRecovery ¶
func (hs *HighSpeed) ExitRecovery()
func (*HighSpeed) InRecovery ¶
func (*HighSpeed) OnFastRetransmit ¶
func (*HighSpeed) RecoverySeq ¶
func (*HighSpeed) SendWindow ¶
type NewReno ¶
type NewReno struct {
// contains filtered or unexported fields
}
NewReno implements RFC 5681 TCP congestion control: slow start, congestion avoidance, fast retransmit, fast recovery.
func NewNewReno ¶
NewNewReno creates a NewReno congestion controller. Initial cwnd is set to min(10*MSS, max(2*MSS, 14600)) per RFC 6928.
func (*NewReno) ExitRecovery ¶
func (nr *NewReno) ExitRecovery()
ExitRecovery leaves fast recovery, deflating cwnd. RFC 5681 Section 3.2.
func (*NewReno) InRecovery ¶
InRecovery reports whether we are in fast recovery.
func (*NewReno) OnACK ¶
OnACK processes a new ACK. RFC 5681 Section 3.1.
func (*NewReno) OnDupACK ¶
OnDupACK processes a duplicate ACK. Returns true if this is the 3rd dup ACK (triggering fast retransmit). RFC 5681 Section 3.2.
func (*NewReno) OnFastRetransmit ¶
OnFastRetransmit enters fast recovery. RFC 5681 Section 3.2.
func (*NewReno) OnTimeout ¶
func (nr *NewReno) OnTimeout()
OnTimeout handles RTO timeout. RFC 5681 Section 3.1.
func (*NewReno) RecoverySeq ¶
RecoverySeq returns the recovery point (SND.NXT at time of entering recovery).
func (*NewReno) SendWindow ¶
SendWindow returns the current congestion window.
type Option ¶
Option represents a parsed TCP option.
func ParseOptions ¶
ParseOptions parses the options portion of a TCP header.
func SACKOption ¶
SACKOption creates a SACK option with the given blocks.
func TimestampOption ¶
TimestampOption creates a timestamps option.
func WScaleOption ¶
WScaleOption creates a window scale option.
type RTOCalculator ¶
type RTOCalculator struct {
// contains filtered or unexported fields
}
RTOCalculator implements RFC 6298 RTO computation.
func NewRTOCalculator ¶
func NewRTOCalculator() *RTOCalculator
NewRTOCalculator creates an RTO calculator with the default initial RTO.
func (*RTOCalculator) AckReceived ¶
func (r *RTOCalculator) AckReceived(ack uint32) bool
AckReceived checks if the ACK covers the timed segment. If so, records the sample and stops timing. Returns true if a sample was taken.
func (*RTOCalculator) Backoff ¶
func (r *RTOCalculator) Backoff()
Backoff doubles the current RTO (exponential backoff on timeout).
func (*RTOCalculator) InvalidateTiming ¶
func (r *RTOCalculator) InvalidateTiming()
InvalidateTiming implements Karn's algorithm: discard the current timing on retransmission (don't sample retransmitted segments).
func (*RTOCalculator) RTO ¶
func (r *RTOCalculator) RTO() time.Duration
RTO returns the current retransmission timeout.
func (*RTOCalculator) SRTT ¶
func (r *RTOCalculator) SRTT() time.Duration
SRTT returns the smoothed RTT. Returns 0 if no measurement yet.
func (*RTOCalculator) Sample ¶
func (r *RTOCalculator) Sample(rtt time.Duration)
Sample records an RTT measurement and recalculates RTO per RFC 6298.
func (*RTOCalculator) StartTiming ¶
func (r *RTOCalculator) StartTiming(seq uint32)
StartTiming begins timing a segment for RTT measurement.
type RecvBuf ¶
type RecvBuf struct {
// contains filtered or unexported fields
}
RecvBuf reassembles an incoming TCP byte stream, handling both in-order and out-of-order segments. It maintains a SACK scoreboard for reporting non-contiguous received blocks.
func NewRecvBuf ¶
NewRecvBuf creates a receive buffer with the given initial sequence number and maximum window size. Data beyond nxt+windowSize is rejected.
func (*RecvBuf) Insert ¶
Insert adds a segment's payload at the given sequence number. Returns the number of new contiguous bytes added (available for Read). Out-of-order segments are buffered for later reassembly. Data beyond the receive window (nxt + windowSize) is trimmed.
func (*RecvBuf) SACKBlocks ¶
SACKBlocks returns up to 3 SACK blocks describing out-of-order data held.
type SACKBlock ¶
SACKBlock represents a SACK block (left edge inclusive, right edge exclusive).
func GetSACKBlocks ¶
GetSACKBlocks extracts SACK blocks from options.
type SYNCookies ¶
type SYNCookies struct {
// contains filtered or unexported fields
}
SYNCookies generates and validates SYN cookies for TCP SYN flood protection. When a listener's accept queue is full, SYN cookies allow handshakes to complete without allocating any per-connection state until the final ACK.
The tradeoff is that SYN-cookie-established connections do not negotiate window scaling, SACK, or timestamps (there aren't enough bits in the 32-bit ISS to encode these options). This matches Linux's behavior.
func NewSYNCookies ¶
func NewSYNCookies() *SYNCookies
NewSYNCookies creates a new SYN cookie engine with a random secret.
func (*SYNCookies) GenerateSYNACK ¶
func (sc *SYNCookies) GenerateSYNACK(syn Segment, localPort, mss uint16) Segment
GenerateSYNACK builds a SYN-ACK segment using a SYN cookie as the ISS. No connection state is allocated. The caller is responsible for wrapping the returned segment in an IP packet and sending it.
func (*SYNCookies) ValidateACK ¶
func (sc *SYNCookies) ValidateACK(seg Segment, localPort uint16) (mss uint16, remoteISN uint32, ok bool)
ValidateACK checks whether an incoming ACK segment completes a SYN-cookie handshake. If valid, returns the negotiated MSS and the remote's initial sequence number (seg.Seq - 1). The caller should then create a Conn via AcceptCookie.
type Segment ¶
type Segment struct {
SrcPort uint16
DstPort uint16
Seq uint32
Ack uint32
Flags uint8
Window uint16
Checksum uint16
Urgent uint16
Options []Option
Payload []byte
}
Segment represents a parsed TCP segment (header + payload).
func ParseSegment ¶
ParseSegment parses a raw TCP segment (no IP header).
type SegmentWriter ¶
SegmentWriter is the callback for sending outgoing TCP segments. The data is a raw TCP segment (header + payload, no IP header). The caller is responsible for wrapping it in an IP packet and Ethernet frame and computing the TCP checksum (which requires the IP pseudo-header). The checksum field in the segment is left at zero.
type SendBuf ¶
type SendBuf struct {
// contains filtered or unexported fields
}
SendBuf tracks application data through the TCP send pipeline:
[acknowledged] [sent but unacked] [unsent / queued] [free space]
^ ^ ^
una nxt tail
The buffer is a simple slice-based implementation. Data is appended at the tail and removed from the front as it is acknowledged.
func NewSendBuf ¶
NewSendBuf creates a send buffer with the given capacity and initial sequence number.
func (*SendBuf) Acknowledge ¶
Acknowledge advances una to ack, freeing buffer space. Returns the number of bytes newly acknowledged.
func (*SendBuf) AdvanceSent ¶
AdvanceSent marks n bytes as sent (moves nxt forward).
func (*SendBuf) IsSACKed ¶
IsSACKed reports whether the given sequence number has been selectively acknowledged by the receiver.
func (*SendBuf) MarkSACKed ¶
MarkSACKed records SACK blocks from the receiver. These indicate out-of-order data the receiver holds. Used to avoid retransmitting already-received segments.
func (*SendBuf) PeekUnsent ¶
PeekUnsent returns up to n bytes of unsent data without consuming them.
func (*SendBuf) RetransmitData ¶
RetransmitData returns the first n bytes of unacknowledged data (from una), skipping any SACK'd ranges to avoid redundant retransmissions.
type State ¶
type State uint8
State represents a TCP connection state per RFC 793.
const ( StateClosed State = iota StateListen // passive open, waiting for SYN StateSynSent // active open, SYN sent StateSynReceived // SYN received, SYN-ACK sent StateEstablished // data transfer StateFinWait1 // FIN sent, waiting for ACK or FIN StateFinWait2 // our FIN ACKed, waiting for remote FIN StateCloseWait // remote FIN received, app hasn't closed yet StateClosing // simultaneous close (both FINs sent, waiting for ACK) StateLastAck // close from CloseWait, FIN sent, waiting for ACK StateTimeWait // both FINs ACKed, waiting before final close )