udt

package
v0.0.0-...-23397e3 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2023 License: MIT Imports: 14 Imported by: 0

README

UDT: UDP-based Data Transfer Protocol

UDT (UDP-based Data Transfer Protocol) is a transfer protocol on top of UDP. See https://udt.sourceforge.io/ for the original spec and the reference implementation.

This code is a fork from https://github.com/odysseus654/go-udt which itself is a fork.

Stream vs Datagram

// TypeSTREAM describes a reliable streaming protocol (e.g. TCP)
TypeSTREAM SocketType = 1

// TypeDGRAM describes a partially-reliable messaging protocol
TypeDGRAM SocketType = 2

UDT supports both reliable data streaming and partial reliable 
messaging. The data streaming semantics is similar to that of TCP, 
while the messaging semantics can be regarded as a subset of SCTP 
[RFC4960]. 

From udtSocket.Read:

// for datagram sockets, block until we have a message to return and then return it
// if the buffer isn't big enough, return a truncated message (discarding the rest) and return an error

// for streaming sockets, block until we have at least something to return, then
// fill up the passed buffer as far as we can without blocking again

According to DataPacket.SetMessageData, datagram messages do not set the order flag (bit 29).

Deviations

MTU negotiation is disabled. Peernet uses a hardcoded max packet size (see protocol package). Packets may be routed through any network adapter, therefore pinning a MTU specific to a network adapter would not make much sense.

The "rendezvous" functionality has been removed since Peernet supports native Traverse messages for UDP hole punching.

Multiplexing multiple UDT sockets to a single UDT connection is removed. It added complexity without benefits in this case. Peernet uses a single UDP port and UDP connection between two peers. Multiplexing has no effect other than breaking the concept and the security of Peernet message sequences.

The order flag (bit 29) set for datagram messages is ignored for security reasons; the behavior whether incoming packets must be ordered or not is hardcoded to whether it is in streaming or datagram mode.

Documentation

Index

Constants

View Source
const (
	TerminateReasonListenerClosed     = 1000 // Listener: The listener.Close function was called.
	TerminateReasonLingerTimerExpired = 1001 // Socket: The linger timer expired. Use CloseLinger to know the actual closing reason.
	TerminateReasonConnectTimeout     = 1002 // Socket: The connection timed out when sending the initial handshake.
	TerminateReasonRemoteSentShutdown = 1003 // Remote peer sent a shutdown message.
	TerminateReasonSocketClosed       = 1004 // Send: Socket closed. Called UDTSocket.Close().
	TerminateReasonInvalidPacketIDAck = 1005 // Send: Invalid packet ID received in ACK message.
	TerminateReasonInvalidPacketIDNak = 1006 // Send: Invalid packet ID received in NAK message.
	TerminateReasonCorruptPacketNak   = 1007 // Send: Invalid NAK packet received.
	TerminateReasonSignal             = 1008 // Send: Terminate signal. Called UDTSocket.Terminate().
)

The termination reason is passed on to the close function

Variables

This section is empty.

Functions

func FloydRivestBuckets

func FloydRivestBuckets(slice sort.Interface, bucketSize int)

FloydRivestBuckets. Sort a slice into buckets of given size. All elements from one bucket are smaller than any element from the next one. elements at position i * bucketSize are guaranteed to be the (i * bucketSize) th smallest elements s := // some slice FloydRivest.Buckets(sort.Interface(s), 5) s is now sorted into buckets of size 5 max(s[0:5]) < min(s[5:10]) max(s[10: 15]) < min(s[15:20]) ...

func FloydRivestSelect

func FloydRivestSelect(array sort.Interface, k, left, right int)

left is the left index for the interval right is the right index for the interval k is the desired index value, where array[k] is the k+1 smallest element when left = 0

func ListenUDT

func ListenUDT(config *Config, closer Closer, incomingData <-chan []byte, outgoingData chan<- []byte, terminationSignal <-chan struct{}) *listener

ListenUDT listens for incoming UDT connections using the existing provided packet connection. It creates a UDT server.

Types

type Closer

type Closer interface {
	Close(reason int) error       // Close is called when the socket is actually closed.
	CloseLinger(reason int) error // CloseLinger is called when the socket indicates to be closed soon, after the linger time.
}

Closer provides a status code indicating why the closing happens.

type Config

type Config struct {
	CanAcceptDgram     bool          // can this listener accept datagrams?
	CanAcceptStream    bool          // can this listener accept streams?
	ListenReplayWindow time.Duration // length of time to wait for repeated incoming connections
	MaxPacketSize      uint          // Upper limit on maximum packet size (0 = unlimited)
	MaxBandwidth       uint64        // Maximum bandwidth to take with this connection (in bytes/sec, 0 = unlimited)
	LingerTime         time.Duration // time to wait for retransmit requests after connection shutdown
	MaxFlowWinSize     uint          // maximum number of unacknowledged packets to permit (minimum 32)
	SynTime            time.Duration // SynTime

	CanAccept           func(hsPacket *packet.HandshakePacket) error // can this listener accept this connection?
	CongestionForSocket func(sock *UDTSocket) CongestionControl      // create or otherwise return the CongestionControl for this socket
}

Config controls behavior of sockets created with it

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig constructs a Config with default values

type CongestionControl

type CongestionControl interface {
	// Init to be called (only) at the start of a UDT connection.
	Init(CongestionControlParms, time.Duration)

	// Close to be called when a UDT connection is closed.
	Close(CongestionControlParms)

	// OnACK to be called when an ACK packet is received
	OnACK(CongestionControlParms, packet.PacketID)

	// OnNAK to be called when a loss report is received
	OnNAK(CongestionControlParms, []packet.PacketID)

	// OnTimeout to be called when a timeout event occurs
	OnTimeout(CongestionControlParms)

	// OnPktSent to be called when data is sent
	OnPktSent(CongestionControlParms, packet.Packet)

	// OnPktRecv to be called when data is received
	OnPktRecv(CongestionControlParms, packet.DataPacket)

	// OnCustomMsg to process a user-defined packet
	OnCustomMsg(CongestionControlParms, packet.UserDefControlPacket)
}

CongestionControl controls how timing is handled and UDT connections tuned

type CongestionControlParms

type CongestionControlParms interface {
	// GetSndCurrSeqNo is the most recently sent packet ID
	GetSndCurrSeqNo() packet.PacketID

	// SetCongestionWindowSize sets the size of the congestion window (in packets)
	SetCongestionWindowSize(uint)

	// GetCongestionWindowSize gets the size of the congestion window (in packets)
	GetCongestionWindowSize() uint

	// GetPacketSendPeriod gets the current delay between sending packets
	GetPacketSendPeriod() time.Duration

	// SetPacketSendPeriod sets the current delay between sending packets
	SetPacketSendPeriod(time.Duration)

	// GetMaxFlowWindow is the largest number of unacknowledged packets we can receive (in packets)
	GetMaxFlowWindow() uint

	// GetReceiveRates is the current calculated receive rate and bandwidth (in packets/sec)
	GetReceiveRates() (recvSpeed, bandwidth uint)

	// GetRTT is the current calculated roundtrip time between peers
	GetRTT() time.Duration

	// GetMSS is the largest packet size we can currently send (in bytes)
	GetMSS() uint

	// SetACKPeriod sets the time between ACKs sent to the peer
	SetACKPeriod(time.Duration)

	// SetACKInterval sets the number of packets sent to the peer before sending an ACK
	SetACKInterval(uint)
}

CongestionControlParms permits a CongestionControl implementation to interface with the UDT socket

type Metrics

type Metrics struct {
	PktSentData        uint64  // number of sent data packets, including retransmissions
	PktSendHandShake   uint64  // number of Handshake packets sent
	PktRecvHandShake   uint64  // number of Handshake packets received
	PktSendKeepAlive   uint64  // number of Keep-alive packets sent
	PktRecvKeepAlive   uint64  // number of Keep-alive packets received
	PktRecvData        uint64  // number of received packets
	PktSentCongestion  uint64  // number of Congestion Packets sent
	PktRecvCongestion  uint64  // number of Congestion Packets received
	PktSentShutdown    uint64  // number of Shutdown Packets sent
	PktRecvShutdown    uint64  // number of Shutdown Packets received
	PktSendMessageDrop uint64  // number of Message Drop Packets sent
	PktRecvMessageDrop uint64  // number of Message Drop Packets received
	PktSendError       uint64  // number of Error Packets sent
	PktRecvError       uint64  // number of Error Packets received
	PktSendUserDefined uint64  // number of User Defined Packets sent
	PktRecvUserDefined uint64  // number of User Defined Packets received
	PktSndLoss         uint64  // number of lost packets (sender side)
	PktRcvLoss         uint64  // number of lost packets (receiver side)
	PktRetrans         uint64  // number of retransmitted packets
	PktSentACK         uint64  // number of sent ACK packets
	PktSentACK2        uint64  // number of sent ACK2 packets
	PktRecvACK2        uint64  // number of received ACK2 packets
	PktRecvACK         uint64  // number of received ACK packets
	PktSentNAK         uint64  // number of sent NAK packets
	PktRecvNAK         uint64  // number of received NAK packets
	PktSentOther       uint64  // number of sent Other packets
	PktRecvOther       uint64  // number of received Other packets
	DataSent           uint64  // Payload data sent in bytes
	DataReceived       uint64  // Payload data received in bytes
	SpeedSend          float64 // Incoming data transfer speed in bytes/second
	SpeedReceive       float64 // Outgoing data transfer speed in bytes/second

	Started time.Time // Started
	// contains filtered or unexported fields
}

type NativeCongestionControl

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

NativeCongestionControl implements the default congestion control logic for UDP

func (*NativeCongestionControl) Close

Close to be called when a UDT connection is closed.

func (*NativeCongestionControl) Init

func (ncc *NativeCongestionControl) Init(parms CongestionControlParms, synTime time.Duration)

Init to be called (only) at the start of a UDT connection.

func (*NativeCongestionControl) OnACK

OnACK to be called when an ACK packet is received

func (*NativeCongestionControl) OnCustomMsg

OnCustomMsg to process a user-defined packet

func (*NativeCongestionControl) OnNAK

func (ncc *NativeCongestionControl) OnNAK(parms CongestionControlParms, losslist []packet.PacketID)

OnNAK to be called when a loss report is received

func (*NativeCongestionControl) OnPktRecv

OnPktRecv to be called when a data is received

func (*NativeCongestionControl) OnPktSent

func (ncc *NativeCongestionControl) OnPktSent(parms CongestionControlParms, pkt packet.Packet)

OnPktSent to be called when data is sent

func (*NativeCongestionControl) OnTimeout

func (ncc *NativeCongestionControl) OnTimeout(parms CongestionControlParms)

OnTimeout to be called when a timeout event occurs

type UDTSocket

type UDTSocket struct {
	Config *Config // configuration parameters for this socket

	// performance metrics
	Metrics *Metrics
	// contains filtered or unexported fields
}

UDTSocket encapsulates a UDT socket between a local and remote address pair, as defined by the UDT specification. UDTSocket implements the net.Conn interface so that it can be used anywhere that a stream-oriented network connection (like TCP) would be used.

func DialUDT

func DialUDT(config *Config, closer Closer, incomingData <-chan []byte, outgoingData chan<- []byte, terminationSignal <-chan struct{}, isStream bool) (*UDTSocket, error)

DialUDT establishes an outbound UDT connection using the existing provided packet connection. It creates a UDT client.

func (*UDTSocket) Close

func (s *UDTSocket) Close() error

Close closes the connection. Any blocked Read or Write operations will be unblocked. Write operations will be permitted to send (initial packets) Read operations will return an error // (required for net.Conn implementation). Note: Do not simultaneously call Close() and Write(). To close while the socket is still in use, use Terminate().

func (*UDTSocket) LocalAddr

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

LocalAddr returns the local network address. (required for net.Conn implementation)

func (*UDTSocket) Read

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

Read reads data from the connection. Read can be made to time out and return an Error with Timeout() == true after a fixed time limit; see SetDeadline and SetReadDeadline. (required for net.Conn implementation)

func (*UDTSocket) RemoteAddr

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

RemoteAddr returns the remote network address. (required for net.Conn implementation)

func (*UDTSocket) SetDeadline

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

SetDeadline sets the read and write deadlines associated with the connection. It is equivalent to calling both SetReadDeadline and SetWriteDeadline.

A deadline is an absolute time after which I/O operations fail with a timeout (see type Error) instead of blocking. The deadline applies to all future and pending I/O, not just the immediately following call to Read or Write. After a deadline has been exceeded, the connection can be refreshed by setting a deadline in the future.

An idle timeout can be implemented by repeatedly extending the deadline after successful Read or Write calls.

A zero value for t means I/O operations will not time out.

Note that if a TCP connection has keep-alive turned on, which is the default unless overridden by Dialer.KeepAlive or ListenConfig.KeepAlive, then a keep-alive failure may also return a timeout error. On Unix systems a keep-alive failure on I/O can be detected using errors.Is(err, syscall.ETIMEDOUT). (required for net.Conn implementation)

func (*UDTSocket) SetReadDeadline

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

SetReadDeadline sets the deadline for future Read calls and any currently-blocked Read call. A zero value for t means Read will not time out. (required for net.Conn implementation)

func (*UDTSocket) SetWriteDeadline

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

SetWriteDeadline sets the deadline for future Write calls and any currently-blocked Write call. Even if write times out, it may return n > 0, indicating that some of the data was successfully written. A zero value for t means Write will not time out. (required for net.Conn implementation)

func (*UDTSocket) Terminate

func (s *UDTSocket) Terminate() error

Terminate terminates the connection immediately. Unlike Close, it does not permit any reading/writing. If the connection should be ordinarily closed (after reading/writing) use Close().

func (*UDTSocket) Write

func (s *UDTSocket) Write(p []byte) (n int, err error)

Write writes data to the connection. Write can be made to time out and return an Error with Timeout() == true after a fixed time limit; see SetDeadline and SetWriteDeadline. (required for net.Conn implementation)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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