server

package
v0.0.0-...-804a7a4 Latest Latest
Warning

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

Go to latest
Published: Feb 4, 2019 License: GPL-3.0 Imports: 9 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// Maximum MTU size is the maximum packet size.
	// Any MTU size above this will get limited to the maximum.
	MaximumMTUSize = 1492
	// MinimumMTUSize is the minimum packet size.
	// Any MTU size below this will get set to the minimum.
	MinimumMTUSize = 400
)

Variables

View Source
var NotStarted = errors.New("udp server has not started")

NotStarted is an error returned for the Read and Write functions if the server has not yet been started.

Functions

func HandleUnconnectedMessage

func HandleUnconnectedMessage(packetInterface protocol.IPacket, addr *net.UDPAddr, manager *Manager)

HandleUnconnectedMessage handles an incoming unconnected message from a UDPAddr. A response will be made for every packet, which gets sent back to the sender. A session gets created for the sender once the OpenConnectionRequest2 gets sent.

Types

type Indexes

type Indexes struct {
	sync.Mutex
	// contains filtered or unexported fields
}

Indexes is used for the collection of indexes related to datagrams and encapsulated packets. It uses several maps and is therefore protected by a mutex.

type Manager

type Manager struct {
	Server   *UDPServer
	Sessions SessionManager

	// PongData is the data returned when the server gets an unconnected ping.
	PongData string
	// Security ensures a secure connection between a pair of systems.
	// Setting this to false is often the best idea for mobile devices.
	Security bool
	// Encryption encrypts all packets sent over RakNet.
	// Encryption should be disabled if used for Minecraft.
	Encryption bool
	// ServerId is a random ID to identify servers. It is randomly generated for each manager.
	ServerId int64
	// Running specifies the running state of the manager.
	// The manager will automatically stop working if the running state is false.
	Running bool
	// CurrentTick is the current tick of the manager. This current Tick increments for every
	// time the manager ticks.
	CurrentTick int64
	// TimeoutDuration is the duration after which a session gets timed out.
	// Timed out sessions get closed and removed immediately.
	// The default timeout duration is 6 seconds.
	TimeoutDuration time.Duration

	// RawPacketFunction gets called when a raw packet is processed.
	// The address given is the address of the sender, and the byte array the buffer of the packet.
	RawPacketFunction func(packet []byte, addr *net.UDPAddr)
	// PacketFunction gets called once an encapsulated packet is fully processed.
	// This function only gets called for encapsulated packets not recognized as RakNet internal packets.
	// A byte array argument gets passed, which is the buffer of the buffer in the encapsulated packet.
	PacketFunction func(packet []byte, session *Session)
	// ConnectFunction gets called once a session is fully connected to the server,
	// and packets of the game protocol start to get sent.
	ConnectFunction func(session *Session)
	// DisconnectFunction gets called with the associated session on a disconnect.
	// This disconnect may be either client initiated or server initiated.
	DisconnectFunction func(session *Session)

	*sync.RWMutex
	// contains filtered or unexported fields
}

Manager manages a UDP server and its components.

func NewManager

func NewManager() *Manager

NewManager returns a new Manager for a UDP Server. A random server ID gets generated.

func (*Manager) BlockIP

func (manager *Manager) BlockIP(addr *net.UDPAddr, duration time.Duration)

BlockIP blocks the IP of the given UDP address, ignoring any further packets until the duration runs out.

func (*Manager) IsIPBlocked

func (manager *Manager) IsIPBlocked(addr *net.UDPAddr) bool

IsIPBlocked checks if the IP of a UDP address is blocked. If true, packets are not processed of the address.

func (*Manager) Start

func (manager *Manager) Start(address string, port int) error

Start starts the UDP server on the given address and port. Start returns an error if any might have occurred during starting. The manager will keep processing incoming packets until it has been Stop()ed.

func (*Manager) Stop

func (manager *Manager) Stop()

Stop makes the manager stop processing incoming packets.

func (*Manager) UnblockIP

func (manager *Manager) UnblockIP(addr *net.UDPAddr)

UnblockIP unblocks the IP of the address and allows packets from the address once again.

type Priority

type Priority byte

Priority is the priority at which packets will be sent out when queued. PriorityImmediate will make packets get sent out immediately.

const (
	// PriorityImmediate is the highest possible priority.
	// Packets with this priority get sent out immediately.
	PriorityImmediate Priority = iota
	// PriorityHigh is the highest possible priority that gets buffered.
	// High priority packets get sent out every tick.
	PriorityHigh
	// PriorityMedium is the priority most used.
	// Medium priority packets get sent out every other tick.
	PriorityMedium
	// PriorityLow is the lowest possible priority.
	// Low priority packets get sent out every fourth tick.
	PriorityLow
)

type PriorityQueue

type PriorityQueue chan *protocol.EncapsulatedPacket

A PriorityQueue is used to send packets with a certain priority. Encapsulated packets can be queued in these queues.

func NewPriorityQueue

func NewPriorityQueue(bufferingSize int) *PriorityQueue

NewPriorityQueue returns a new priority queue with buffering size. The buffering size specifies the maximum amount of packets in the queue, and the queue becomes blocking once the amount of packets exceeds the buffering size.

func (*PriorityQueue) AddEncapsulated

func (queue *PriorityQueue) AddEncapsulated(packet *protocol.EncapsulatedPacket, session *Session)

AddEncapsulated adds an encapsulated packet to a priority queue. The packet will first be split into smaller sub packets if needed, after which all packets will be added to the queue.

func (*PriorityQueue) Flush

func (queue *PriorityQueue) Flush(session *Session)

Flush flushes all encapsulated packets in the priority queue, and sends them to a session. All encapsulated packets will first be fetched from the channel, after which they will be put into datagrams. A new datagram is made once an encapsulated packet makes the size of a datagram exceed the MTU size of the session.

func (*PriorityQueue) Split

func (queue *PriorityQueue) Split(packet *protocol.EncapsulatedPacket, session *Session) []*protocol.EncapsulatedPacket

Split splits an encapsulated packet into smaller sub packets. Every encapsulated packet that exceeds the MTUSize of the session will be split into sub packets, and returned into a slice.

type Queues

type Queues struct {
	Immediate *PriorityQueue
	High      *PriorityQueue
	Medium    *PriorityQueue
	Low       *PriorityQueue
}

Queues is a container of four priority queues. Immediate priority, high priority, medium priority and low priority queues.

func (Queues) AddEncapsulated

func (queues Queues) AddEncapsulated(packet *protocol.EncapsulatedPacket, priority Priority, session *Session)

AddEncapsulated adds an encapsulated packet at the given priority. The queue gets flushed immediately if the priority is immediate priority.

type RawPacket

type RawPacket struct {
	*binutils.Stream
}

A RawPacket is used to identify packets that do not follow the RakNet protocol. Raw packets may be of different protocols, query protocols as an example. They are simply ignored and forwarded to the managing program. Raw packets serve no purpose other than simply forwarding data.

func NewRawPacket

func NewRawPacket() RawPacket

NewRawPacket returns a new raw packet.

func (RawPacket) Decode

func (pk RawPacket) Decode()

func (RawPacket) Encode

func (pk RawPacket) Encode()

func (RawPacket) GetId

func (pk RawPacket) GetId() int

func (RawPacket) HasMagic

func (pk RawPacket) HasMagic() bool

type ReceiveWindow

type ReceiveWindow struct {
	// DatagramHandleFunction is a function that gets called once a datagram gets released from the receive window.
	// A timestamped datagram gets returned with the timestamp of the time the datagram entered the receive window.
	DatagramHandleFunction func(datagram TimestampedDatagram)
	// contains filtered or unexported fields
}

ReceiveWindow is a window used to hold datagrams until they're read to be released. ReceiveWindow restores the order of datagrams that arrived out of order, and sends NAKs where needed.

func NewReceiveWindow

func NewReceiveWindow() *ReceiveWindow

NewReceiveWindow returns a new receive window.

func (*ReceiveWindow) AddDatagram

func (window *ReceiveWindow) AddDatagram(datagram *protocol.Datagram)

AddDatagram adds a datagram to the receive window. The datagram is first encapsulated with a timestamp, and is added to a channel in order to await the next tick for further processing.

func (*ReceiveWindow) Tick

func (window *ReceiveWindow) Tick()

Tick ticks the ReceiveWindow and releases any datagrams when possible. Tick also fetches all datagrams that are currently in the channel.

type RecoveryQueue

type RecoveryQueue struct {
	sync.Mutex
	// contains filtered or unexported fields
}

A RecoveryQueue manages the recovery of lost datagrams over the connection. Datagrams get restored by the client sending a NAK. The recovery queue holds every datagram sent and releases them, once an ACK is received with the datagram's sequence number.

func NewRecoveryQueue

func NewRecoveryQueue() *RecoveryQueue

NewRecoveryQueue returns a new recovery queue.

func (*RecoveryQueue) AddRecovery

func (queue *RecoveryQueue) AddRecovery(datagram *protocol.Datagram)

AddRecovery adds recovery for the given datagram. The recovery will consist until an ACK gets sent by the client, and the datagram is safe to be removed.

func (*RecoveryQueue) IsRecoverable

func (queue *RecoveryQueue) IsRecoverable(sequenceNumber uint32) bool

IsRecoverable checks if the datagram with the given sequence number is recoverable.

func (*RecoveryQueue) Recover

func (queue *RecoveryQueue) Recover(sequenceNumbers []uint32) ([]*protocol.Datagram, []uint32)

Recover recovers all datagrams associated with the sequence numbers in the array given. Every recoverable datagram with sequence number in the array will be returned, along with an array containing all recovered sequence numbers.

func (*RecoveryQueue) RemoveRecovery

func (queue *RecoveryQueue) RemoveRecovery(sequenceNumbers []uint32)

RemoveRecovery removes recovery for all sequence numbers given. Removed datagrams can not be retrieved in any way, therefore this function should only be used once the client sends an ACK to ensure arrival.

type Session

type Session struct {
	*net.UDPAddr
	Manager       *Manager
	ReceiveWindow *ReceiveWindow
	RecoveryQueue *RecoveryQueue

	// MTUSize is the maximum size of packets sent and received to and from this sessoin.
	MTUSize int16
	// Indexes holds all datagram and encapsulated packet indexes.
	Indexes Indexes
	// Queues holds all send queues of the session.
	Queues Queues
	// ClientId is the unique client ID of the session.
	ClientId uint64
	// CurrentPing is the current latency of the session.
	CurrentPing int64
	// LastUpdate is the last update time of the session.
	LastUpdate time.Time
	// FlaggedForClose indicates if this session has been flagged to close.
	// Sessions flagged for close will be closed next tick safely.
	FlaggedForClose bool
}

Session is a manager of a connection between the client and the server. Sessions manage everything related to packet ordering and processing.

func NewSession

func NewSession(addr *net.UDPAddr, mtuSize int16, manager *Manager) *Session

NewSession returns a new session with UDP address. The MTUSize provided is the maximum packet size of the session.

func (*Session) Close

func (session *Session) Close()

Close removes all references of the session, and removes the capability to send and handle packets. Sessions can not be opened once closed. It is strongly unrecommended to use this function directly. Use FlagForClose instead.

func (*Session) FlagForClose

func (session *Session) FlagForClose()

FlagForClose flags the session for close. It is always recommended to use this function over direct Close. Sessions flagged for close will be closed the next tick.

func (*Session) HandleACK

func (session *Session) HandleACK(ack *protocol.ACK)

HandleACK handles an incoming ACK packet. Recovery gets removed for every datagram with a sequence number in the ACK.

func (*Session) HandleConnectedPing

func (session *Session) HandleConnectedPing(packet *protocol.EncapsulatedPacket, timestamp int64)

HandleConnectedPing handles a connected ping from the client. A pong is sent back at low priority.

func (*Session) HandleConnectedPong

func (session *Session) HandleConnectedPong(packet *protocol.EncapsulatedPacket, timestamp int64)

HandleConnectedPong handles a pong reply of our own sent ping.

func (*Session) HandleConnectionRequest

func (session *Session) HandleConnectionRequest(packet *protocol.EncapsulatedPacket)

HandleConnectionRequest handles a connection request from the session. A connection accept gets sent back to the client.

func (*Session) HandleDatagram

func (session *Session) HandleDatagram(datagram TimestampedDatagram)

HandleDatagram handles an incoming datagram encapsulated by a timestamp. The actual receive time of the datagram can be checked.

func (*Session) HandleEncapsulated

func (session *Session) HandleEncapsulated(packet *protocol.EncapsulatedPacket, timestamp int64)

HandleEncapsulated handles an encapsulated packet from a datagram. A timestamp is passed, which is the timestamp of which the datagram received in the receive window.

func (*Session) HandleNACK

func (session *Session) HandleNACK(nack *protocol.NAK)

HandleNACK handles an incoming NACK packet. All packets requested in the NACK get resent to the client.

func (*Session) HandleSplitEncapsulated

func (session *Session) HandleSplitEncapsulated(packet *protocol.EncapsulatedPacket, timestamp int64)

HandleSplitEncapsulated handles a split encapsulated packet. Split encapsulated packets are first collected into an array, and are merged once all fragments of the encapsulated packets have arrived.

func (*Session) IsClosed

func (session *Session) IsClosed() bool

IsClosed checks if the session is closed. Sending and handling packets for a session is impossible once the session is closed.

func (*Session) Send

func (session *Session) Send(buffer []byte) (int, error)

Send sends the given buffer to the session over UDP. Returns an int describing the amount of bytes written, and an error if unsuccessful.

func (*Session) SendACK

func (session *Session) SendACK(sequenceNumber uint32)

SendACK sends an ACK packet to the session for the given sequence number. ACKs should only be sent once a datagram is received.

func (*Session) SendPacket

func (session *Session) SendPacket(packet protocol.IConnectedPacket, reliability byte, priority Priority)

SendPacket sends an external packet to a session. The reliability given will be added to the encapsulated packet. The packet will be added with the given priority. Immediate priority packets are sent out immediately.

func (*Session) Tick

func (session *Session) Tick(currentTick int64)

Tick ticks the session and processes the receive window and priority queues. currentTick is the current tick of the server, which increments every time this function is ran.

type SessionManager

type SessionManager map[string]*Session

SessionManager is a manager of all sessions in the Manager.

func NewSessionManager

func NewSessionManager() SessionManager

NewSessionManager returns a new session manager.

func (SessionManager) GetSession

func (manager SessionManager) GetSession(addr *net.UDPAddr) (*Session, bool)

GetSession returns a session by a UDP address. GetSession also returns a bool indicating success of the call.

func (SessionManager) SessionExists

func (manager SessionManager) SessionExists(addr *net.UDPAddr) bool

SessionExists checks if the session manager has a session with a UDPAddr.

type TimestampedDatagram

type TimestampedDatagram struct {
	*protocol.Datagram
	Timestamp int64
}

TimestampedDatagram is a datagram encapsulated by a timestamp. Every datagram added to the receive window gets its timestamp recorded immediately.

type UDPServer

type UDPServer struct {
	*net.UDPConn
}

UDPServer is a wrapper around a UDPConn. It can be started on a given address and port, and provides functions to read and write packets to the connection.

func NewUDPServer

func NewUDPServer() *UDPServer

NewUDPServer returns a new UDP server. The UDPServer will not have a default connection, and all actions executed on it before starting will fail.

func (*UDPServer) HasStarted

func (server *UDPServer) HasStarted() bool

HasStarted checks if a UDPServer has been started. No actions can be executed on the UDPServer while not started.

func (*UDPServer) Read

func (server *UDPServer) Read(buffer []byte) (bytesRead int, addr *net.UDPAddr, err error)

Read reads any data from the UDP connection into the given byte array. The IP address and port of the client that sent the data will be returned, along with an error that might have occurred during reading.

func (*UDPServer) Start

func (server *UDPServer) Start(address string, port int) error

Start starts the UDP server on the given address and port. An error is returned if ListenUDP is not successful. Actions can be used on the UDP server once started.

func (*UDPServer) Write

func (server *UDPServer) Write(buffer []byte, addr *net.UDPAddr) (int, error)

Write writes a byte array to a UDP connection. Write returns the amount of bytes written and an error that might have occurred.

Jump to

Keyboard shortcuts

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