p2p

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Apr 24, 2025 License: MIT Imports: 21 Imported by: 0

README

go-p2p

go-p2p is an easy-to-use game-dev datagram-based P2P networking library focused on reducing boilerplate while remaining robust and flexible which allows you to communicate without external servers, and without worrying about NAT and port forwarding on routers. It was primarily designed as a game development library, implementing a lightweight version of TCP over UDP, enabling fast and reliable communication.

⚠ You should be aware of the limitations of this approach, which doesn't rely on external servers. Some routers may have stricter rules that prevent you from establishing a connection.

Features

  • Reliability and Order: (Optional) It ensures that the packets reaches their destination in the order they were sent.
  • Fully Asynchronous: The API allows you to send packets without blocking and receive packets by registering handlers for specific packet types.
  • Auto-generated Packets: You can auto-generate utilities (at pre-compile time) for building and parsing packets by just declaring their payload with structs.

Installation

Import
import "github.com/MarcosTypeAP/go-p2p"
Download
$ go mod tidy
# Or
$ go get github.com/MarcosTypeAP/go-p2p

# Install the packet generator (optional)
$ go install github.com/MarcosTypeAP/go-p2p/cmd/genpackets@latest

Usage

API Example

This is just an example of the API, there is a working example below :)

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/MarcosTypeAP/go-p2p"
)

// Auto-generate utilities
//go:generate genpackets -prefix=Payload -payload-flags=-fields=all

// Group level
//
//p2p:packet -need-ack
const (
	PacketMessage = p2p.PacketCustom + iota

	// Packet level
	PacketPing //p2p:packet -need-ack -exclude=parser
	PacketPong //p2p:packet -need-ack -exclude=parser

	PacketSomething //p2p:packet
	// ...
)

type PayloadPacketMessage struct {
	msg string
}

type Thing struct {
	nested string
}

//p2p:payload PacketSomething -fields=unexported -ref=parser
type PayloadPacketSomething struct {
	ptr    *float32
	random struct {
		a       int
		b       Thing
		mapList []map[int]string
	}
	Exported int
}

func client() {
    // Imagine this is useful
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// Connect to 100.100.100.100 (both peers are using the default port)
	conn, err := p2p.Dial(ctx, "100.100.100.100")
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// Listen for PacketPing and reply with PacketPong
	conn.OnReceive(PacketPing, func(packet p2p.Packet) {
		buf := make([]byte, p2p.HeaderSize)
		conn.Send(BuildPacketPong(buf))
	})

	thing := PayloadPacketSomething{}
	thing.random.mapList = make([]map[int]string, 2)
	for i := range len(thing.random.mapList) {
		thing.random.mapList[i] = make(map[int]string, 4)
	}

	// Listen for PacketSomething and parse it without allocating new memory
	conn.OnReceive(PacketSomething, func(packet p2p.Packet) {
		err = ParsePacketSomething(packet, &thing)
		if err != nil {
			log.Fatal(err)
		}
		for _, m := range thing.random.mapList {
			for k, v := range m {
				log.Println("Some random thing:", k, v)
			}
		}
	})

	msg := PayloadPacketMessage{"some message"}
	buf := make([]byte, 32)

	// Send a PacketMessage and wait for it to arrive
	err = <-conn.Send(BuildPacketMessage(buf, msg))
	if err != nil {
		log.Fatal(err)
	}

	// Wait to receive a PacketMessage
	res := <-conn.Receive(PacketMessage, buf)
	if res.Err != nil {
		log.Fatal(res.Err)
	}
	// And then parse it
	msg, err = ParsePacketMessage(res.Packet)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Received message:", msg.msg)

	// Wait for the connection to end
	<-conn.Done()

	// Check the cause why it ended
	err = conn.Err()
	if err != nil {
		if errors.Is(err, p2p.ErrPeerClosed) {
			log.Println("Peer disconnected")
			return
		}
		log.Fatal(err)
	}
}

func server() {
    // Imagine this is useful
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// Wait for 200.200.200.200 to connect (both peers are using the default port)
	conn, err := p2p.Listen(ctx, "200.200.200.200", p2p.WithReceiveBufferSize(8), p2p.WithReuseAddress()) // Some random options
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// Listen to unexpected packets and exit
	conn.OnReceiveUnexpected(func(packet p2p.Packet) {
		log.Fatalf("Received unexpected packet: kind=%v, payload=%d", packet.Kind(), packet.Payload())
	})

	thing := PayloadPacketSomething{
		random: struct {
			a       int
			b       Thing
			mapList []map[int]string
		}{
			mapList: []map[int]string{
				{},
				{
					69:   "420",
					1337: "leet",
				},
			},
		},
	}
	buf := make([]byte, 128)

	// Send a PacketSomething 3 times because it doesn't have the -need-ack flag (hope at least one arrives)
	thingPacket := BuildPacketSomething(buf, thing)
	for range 3 {
		conn.Send(thingPacket)
	}

	// Wait to receive a PacketMessage
	res := <-conn.Receive(PacketMessage, buf)
	if res.Err != nil {
		log.Fatal(res.Err)
	}
	// And then parse it
	msg, err := ParsePacketMessage(res.Packet)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Received message:", msg.msg)

	// Wait for the connection to end
	<-conn.Done()

	// Check the cause why it ended
	err = conn.Err()
	if err != nil {
		if errors.Is(err, p2p.ErrPeerClosed) {
			log.Println("Peer disconnected")
			return
		}
		log.Fatal(err)
	}
}

func main() {
    // client()
    // or
    // server()
}
// Generate utilities before compiling
$ go generate [<package>]
Genpackets Usage

⚠ This may be outdated, if you are using it, see it running genpackets -help.

Genpackets generates builders and parsers for the specified packet kinds.
It looks for comment directives to generate packet utilities.

Usage:

    genpackets [flags]

Flags:
    -path string
        Indicates the file path of the generated code, it will be suffixed with '_gen.go'.
        (absolute or relative to the file where //go:generate was placed) (default "packets")
    -payload-flags flags
        Comma-separated list of payload directive flags passed to structs matched by prefix.
    -prefix string
        Generate utilities for structs that have the prefix followed by packet kind.
        eg: prefix=Payload and kind=PacketPing matches: type PayloadPacketPing struct { ... }
    -register-names
        Indicates that names should be generated for the registered packet kinds. (default true)

Directives:

//p2p:packet [flags]

    Must be placed above or next to a packet kind declaration of type p2p.PacketKind.
    It registers a single variable (or group) as a packet kind and specifies their behavior.
    If it is placed on a declaration group, it applies to all declarations in the group.
    If it is placed on a single declaration, it overwrites the group directive.

    Flags:
        -exclude scope
            This indicates that no utility should be generated for this packet kind and the given scope.
        -need-ack
            This indicates that the receiver needs to send an acknowledgment that it received the packet.
        -register-name
            Indicates that names should be generated for the registered packet kinds. (default true)

    Example:
        //p2p:packet -need-ack
        const (
          PacketA = p2p.PacketCustom + iota
          PacketB //p2p:packet -exclude=builder
          ...
        )

        const PacketC p2p.PacketKind = 69

    Final flags:
        PacketA has -need-ack (from group directive)
        PacketB has -exclude=builder (overwrites group directive)
        PacketC has none (It is not recognized as a valid kind because it does not have the directive)

//p2p:payload PACKET_KIND [flags]

    Must be placed above a struct. It indicates that the struct below represents the payload format of the specified packet kind.
    By default, only a builder is generated for packets without this directive.

    Flags:
        -alloc
            This indicates that memory should be allocated for slices and maps.
            It only affects parsers and it is always 'on' when -ref is not used.
        -exclude scope
            This indicates that no utility should be generated for this packet kind and the given scope. 
        -fields export-type
            This filters which fields are used to generate the utilities given the export-type.
        -ref scope
            This indicates that the struct should be passed by reference to the generated utilities on the given scope. 

    Example:
        //p2p:packet
        const (
          PacketPing = p2p.PacketCustom + iota
          ...
        )

        //p2p:payload PacketPing -ref=parser
        type packetPingPayload struct {
          a int
          b bool
        }

    Generates:
        func BuildPacketPing(buf []byte, payload packetPingPayload) p2p.Packet { ... }
        func ParsePacketPing(packet p2p.Packet, payload *packetPingPayload) (err error) { ... }

    Types:
        Scope = none | builder | parser | all
        Export-type = exported | unexported | all
Chat App Example

The example code can be found here.

Steps
$ mkdir chatapp && cd chatapp
$ go mod init chatapp

// Download the chat code example
$ wget https://raw.githubusercontent.com/MarcosTypeAP/go-p2p/refs/heads/main/cmd/example/chat/chat.go

// Download `go-p2p` and `genpackets`
$ go mod tidy
$ go install github.com/MarcosTypeAP/go-p2p/cmd/genpackets@latest

// Generate packet utilities
$ go generate

Try it on localhost:

  • Type something and hit enter to send a message.
  • You can change your name with /name <name>
Shell 1

Run go run . -laddr=127.0.0.1:61000 -peer=127.0.0.1:62000 -peer=127.0.0.1:63000

Peers: 127.0.0.1:62000, 127.0.0.1:63000
Connected: 127.0.0.1:62000
Connected: 127.0.0.1:63000
/name juanceto01
bar
Message from 127.0.0.1:62000: foo
Disconnected: 127.0.0.1:63000
Connected: 127.0.0.1:63000
Message from 127.0.0.1:63000: baz
Shell 2

Run go run . -laddr=127.0.0.1:62000 -peer=127.0.0.1:61000 -peer=127.0.0.1:63000

Peers: 127.0.0.1:61000, 127.0.0.1:63000
Connected: 127.0.0.1:61000
Connected: 127.0.0.1:63000
Message from juanceto01: bar
foo
Disconnected: 127.0.0.1:63000
Connected: 127.0.0.1:63000
Message from 127.0.0.1:63000: baz
Shell 3

Run go run . -laddr=127.0.0.1:63000 -peer=127.0.0.1:61000 -peer=127.0.0.1:62000

Peers: 127.0.0.1:61000, 127.0.0.1:62000
Connected: 127.0.0.1:61000
Connected: 127.0.0.1:62000
Message from juanceto01: bar
Message from 127.0.0.1:62000: foo
^C                                                                                                                                                                           

$ go run . -laddr=127.0.0.1:63000 -peer=127.0.0.1:61000 -peer=127.0.0.1:62000
Peers: 127.0.0.1:61000, 127.0.0.1:62000
Connected: 127.0.0.1:61000
Connected: 127.0.0.1:62000
baz

Documentation

Index

Constants

View Source
const (
	Version = 0

	MaxPacketSize = 4096
)
View Source
const DefaultPort = 42069
View Source
const HeaderSize = sVersion + sKind + sFlags + sID

Variables

View Source
var DefaultOptions = connOptions{
	LocalAddr:                   fmt.Sprintf("%s:%d", getPrivateIP(), DefaultPort),
	SendQueueSize:               64,
	SendQueueFullBehavior:       queueBlock,
	ResendTries:                 5,
	PendingAckQueueSize:         64 * 5,
	PendingAckQueueFullBehavior: queuePanic,
	ReceiveAckTimeout:           100 * time.Millisecond,
	ReceiveBufferSize:           64,
	ConnectionRefusedCooldown:   1 * time.Second,
	ReuseAddress:                false,
}
View Source
var ErrPeerClosed = errors.New("connection closed by peer")
View Source
var ErrPendingAckQueueFull = errors.New("pending acknowledgment queue full")
View Source
var ErrSendQueueFull = errors.New("send queue full")

Functions

func RegisterPacketKindName

func RegisterPacketKindName(kind PacketKind, name string)

RegisterPacketKindName sets the name for a packet kind to be retrieved with PacketKind.String().

This function should only be used for packets without the //p2p:packet directive. Panics if the packet kind was already registered.

Types

type Conn

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

Conn is a peer to peer network connection. Multiple goroutines may invoke methods on a Conn simultaneously.

func Dial

func Dial(ctx context.Context, raddr string, options ...OptFunc) (*Conn, error)

Dial connects to the given address.

It waits for the connection to be established. The connection is established after sending packets and receiving an acknowledgment from the other peer. If the address does not have a port, DefaultPort will be used.

You can see the default options in DefaultOptions.

func (*Conn) Close

func (c *Conn) Close()

Close signals the connection to end. Before closing the connection it tries to signal the other peer that its closing the connection. There is no guarantee that the other peer will receive the closing signal, especially if it is due to an error.

Panics if called when the connection is not established yet. It is safe to call it from multiple goroutines.

func (*Conn) Done

func (c *Conn) Done() <-chan struct{}

Done returns a channel that is closed when the connection has finished closing and cleaning.

It is safe to call it from multiple goroutines.

func (*Conn) Err

func (c *Conn) Err() error

Err returns the reason why the connection ended.

If the other peer sends a closing signal, the error will be ErrPeerClosed.

It is safe to call it from multiple goroutines.

func (*Conn) LocalAddr

func (c *Conn) LocalAddr() net.Addr

LocalAddr returns the local network address, if known.

func (*Conn) OnReceive

func (c *Conn) OnReceive(kind PacketKind, handler func(packet Packet))

OnReceive registers a packet handler.

The given handler will be called with the received packet matching the packet kind. The passed packet should only live within the scope of the handler function; if you want to use it outside, you should allocate a copy.

Packets are processed serially, and the receiving process is paused in the meantime, so the handlers should return as soon as possible. It is safe to call it from multiple goroutines.

func (*Conn) OnReceiveUnexpected

func (c *Conn) OnReceiveUnexpected(handler func(packet Packet))

OnReceiveUnexpected registers a packet handler for received packets that do not have a registered handler.

The given handler will be called with the received packet that does not match any registered packet kind. The passed packet should only live within the scope of the handler function; if you want to use it outside, you should allocate a copy.

Packets are processed serially, and the receiving process is paused in the meantime, so the handlers should return as soon as possible. It is safe to call it from multiple goroutines.

func (*Conn) Receive

func (c *Conn) Receive(kind PacketKind, buf []byte) <-chan struct {
	Packet Packet
	Err    error
}

Receive waits to receive a packet that matches the given packet kind.

The received packet is written to buf and delivered over the returned channel.

It is safe to call it from multiple goroutines.

func (*Conn) RemoteAddr

func (c *Conn) RemoteAddr() net.Addr

RemoteAddr returns the remote network address, if known.

func (*Conn) Send

func (c *Conn) Send(packet Packet) <-chan error

Send sends a packet to the other peer.

This method is asyncronous and simpy places the packet in the send queue. If the packet requires any acknowledgment, it will be signaled by the returned channel, otherwise it will be nil.

It is safe to call it from multiple goroutines.

func (*Conn) SendContext

func (c *Conn) SendContext(ctx context.Context, packet Packet) <-chan error

SendContext is the same as Conn.Send but it receives a context.

Useful when the "full send queue" behavior is to block.

type OptFunc

type OptFunc func(*connOptions)

func WithConnectionRefusedCooldown

func WithConnectionRefusedCooldown(cooldown time.Duration) OptFunc

Time between failed connection attempts.

func WithLocalAddr

func WithLocalAddr(localAddr string) OptFunc

Change local address. If IP is missing, the machine's private IP is used If port is missing, DefaultPort is used.

func WithPendingAckQueueFullBehavior

func WithPendingAckQueueFullBehavior(behavior string) OptFunc

What should happen when the pending ack queue is full.

Possible values are:

"error": return an error.
"panic": well... panic.

func WithPendingAckQueueSize

func WithPendingAckQueueSize(size int) OptFunc

The number of packets that can be queued waiting for an acknowledgment before it becomes full.

func WithReceiveAckTimeout

func WithReceiveAckTimeout(timeout time.Duration) OptFunc

Time to wait for an acknowledgment before attempting to resend the packet.

func WithReceiveBufferSize

func WithReceiveBufferSize(size int) OptFunc

Buffer size to store packets received to early (to maintain order).

func WithResendTries

func WithResendTries(tries int32) OptFunc

Number of attempts to receive acknowledgment before disconnecting. Use -1 to disable retries.

func WithReuseAddress

func WithReuseAddress() OptFunc

Sets syscall.SO_REUSEADDR on the connection socket.

func WithSendQueueFullBehavior

func WithSendQueueFullBehavior(behavior string) OptFunc

What should happen when the send queue is full.

Possible values are:

"block": block until it is not full.
"discard": discard the packet.
"error": return an error.
"panic": well... panic.

func WithSendQueueSize

func WithSendQueueSize(size int) OptFunc

The number of packets that can be queued for sending before it becomes full.

type Packet

type Packet []byte

| version | kind | flags | id | payload |

func (Packet) Flags

func (p Packet) Flags() PacketFlag

func (Packet) HasFlags

func (p Packet) HasFlags(flags PacketFlag) bool

func (Packet) ID

func (p Packet) ID() uint32

func (Packet) Kind

func (p Packet) Kind() PacketKind

func (Packet) Payload

func (p Packet) Payload() []byte

func (Packet) String

func (p Packet) String() string

func (Packet) Validate

func (p Packet) Validate() error

func (Packet) Version

func (p Packet) Version() int

type PacketBuilder

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

A PacketBuilder helps to build a packet payload by keeping track of the write offset.

func NewPacketBuilder

func NewPacketBuilder(buf []byte, kind PacketKind, flags PacketFlag) PacketBuilder

NewPacketBuilder creates a new PacketBuilder and initializes the packet header.

func (PacketBuilder) Build

func (p PacketBuilder) Build() Packet

Build returns the built packet.

Panics if the written payload is larger than MaxPacketSize.

func (*PacketBuilder) Reset

func (p *PacketBuilder) Reset()

Reset deletes the payload. The header is left untouched.

func (*PacketBuilder) WriteAngle

func (p *PacketBuilder) WriteAngle(v float32)

WriteAngle writes an angle value to the payload.

An angle is 2 bytes long and has 3 decimal places of precision. Allowed angle range:

[-PI*2, PI*2]

func (*PacketBuilder) WriteBool

func (p *PacketBuilder) WriteBool(v bool)

WriteBool writes a bool value to the payload.

func (*PacketBuilder) WriteBytes

func (p *PacketBuilder) WriteBytes(b []byte)

WriteBytes writes a []byte value to the payload.

func (*PacketBuilder) WriteFloat

func (p *PacketBuilder) WriteFloat(v float64)

WriteFloat writes a float value to the payload.

func (*PacketBuilder) WriteFloat32

func (p *PacketBuilder) WriteFloat32(v float32)

WriteFloat32 writes a float32 value to the payload.

func (*PacketBuilder) WriteFloat64

func (p *PacketBuilder) WriteFloat64(v float64)

WriteFloat64 writes a float64 value to the payload.

func (*PacketBuilder) WriteInt

func (p *PacketBuilder) WriteInt(v int)

WriteInt writes a int value to the payload.

func (*PacketBuilder) WriteInt16

func (p *PacketBuilder) WriteInt16(v int16)

WriteInt16 writes a int16 value to the payload.

func (*PacketBuilder) WriteInt32

func (p *PacketBuilder) WriteInt32(v int32)

WriteInt32 writes a int32 value to the payload.

func (*PacketBuilder) WriteInt64

func (p *PacketBuilder) WriteInt64(v int64)

WriteInt64 writes a int64 value to the payload.

func (*PacketBuilder) WriteInt8

func (p *PacketBuilder) WriteInt8(v int8)

WriteInt8 writes a int8 value to the payload.

func (*PacketBuilder) WriteRune

func (p *PacketBuilder) WriteRune(v rune)

WriteRune writes a rune value to the payload.

func (*PacketBuilder) WriteString

func (p *PacketBuilder) WriteString(s string)

WriteString writes a string value to the payload.

func (*PacketBuilder) WriteUint

func (p *PacketBuilder) WriteUint(v uint)

WriteUint writes a uint value to the payload.

func (*PacketBuilder) WriteUint16

func (p *PacketBuilder) WriteUint16(v uint16)

WriteUint16 writes a uint16 value to the payload.

func (*PacketBuilder) WriteUint32

func (p *PacketBuilder) WriteUint32(v uint32)

WriteUint32 writes a uint32 value to the payload.

func (*PacketBuilder) WriteUint64

func (p *PacketBuilder) WriteUint64(v uint64)

WriteUint64 writes a uint64 value to the payload.

func (*PacketBuilder) WriteUint8

func (p *PacketBuilder) WriteUint8(v uint8)

WriteUint8 writes a uint8 value to the payload.

type PacketFlag

type PacketFlag byte
const (
	FlagNone PacketFlag = 1 << iota >> 1
	// Indicates that the receiver needs to send an acknowledgment.
	FlagNeedAck
)

type PacketID

type PacketID = uint32

type PacketKind

type PacketKind uint16
const (
	PacketInvalid PacketKind = iota

	// Represents and acknowledgment.
	PacketAck
	// Tells the receiving peer to close the connection.
	PacketReset
	PacketPing
	// Used to keep a "hole" open in the peer's NAT.
	PacketKeepAlive

	// Used to register new packet kinds with iota.
	// It is not a valid packet kind in itself.
	//
	//Usage:
	//
	//    const (
	//        PacketA = p2p.PacketCustom + iota
	//        PacketB
	//        PacketC
	//        ...
	//    )
	PacketCustom
)

func (PacketKind) String

func (k PacketKind) String() string

type PacketParser

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

A PacketParser helps parse a packet by keeping track of the read offset and delaying any errors until the end.

func NewPacketParser

func NewPacketParser(packet Packet) PacketParser

NewPacketParser creates a new PacketParser and performs some validations.

func (*PacketParser) Err

func (p *PacketParser) Err() error

Err returns the first error set.

func (*PacketParser) GetBytes

func (p *PacketParser) GetBytes(n int) []byte

GetBytes returns the next n bytes from payload.

func (*PacketParser) ParseAngle

func (p *PacketParser) ParseAngle() float32

ParseAngle parses an angle value from the payload.

An angle is 2 bytes long and has 3 decimal places of precision. Allowed angle range:

[-PI*2, PI*2]

func (*PacketParser) ParseBool

func (p *PacketParser) ParseBool() bool

ParseBool parses a bool value from the payload.

func (*PacketParser) ParseBytes

func (p *PacketParser) ParseBytes() []byte

ParseBytes parses a []byte value from the payload.

This does not make a copy. Sounds goofy ngl

func (*PacketParser) ParseFloat

func (p *PacketParser) ParseFloat() float64

ParseFloat parses a float value from the payload.

func (*PacketParser) ParseFloat32

func (p *PacketParser) ParseFloat32() float32

ParseFloat32 parses a float32 value from the payload.

func (*PacketParser) ParseFloat64

func (p *PacketParser) ParseFloat64() float64

ParseFloat64 parses a float64 value from the payload.

func (*PacketParser) ParseInt

func (p *PacketParser) ParseInt() int

ParseInt parses a int value from the payload.

func (*PacketParser) ParseInt16

func (p *PacketParser) ParseInt16() int16

ParseInt16 parses a int16 value from the payload.

func (*PacketParser) ParseInt32

func (p *PacketParser) ParseInt32() int32

ParseInt32 parses a int32 value from the payload.

func (*PacketParser) ParseInt64

func (p *PacketParser) ParseInt64() int64

ParseInt64 parses a int64 value from the payload.

func (*PacketParser) ParseInt8

func (p *PacketParser) ParseInt8() int8

ParseInt8 parses a int8 value from the payload.

func (*PacketParser) ParseRune

func (p *PacketParser) ParseRune() rune

ParseRune parses a rune value from the payload.

func (*PacketParser) ParseString

func (p *PacketParser) ParseString() string

ParseString parses a string value from the payload.

func (*PacketParser) ParseUint

func (p *PacketParser) ParseUint() uint

ParseUint parses a uint value from the payload.

func (*PacketParser) ParseUint16

func (p *PacketParser) ParseUint16() uint16

ParseUint16 parses a uint16 value from the payload.

func (*PacketParser) ParseUint32

func (p *PacketParser) ParseUint32() uint32

ParseUint32 parses a uint32 value from the payload.

func (*PacketParser) ParseUint64

func (p *PacketParser) ParseUint64() uint64

ParseUint64 parses a uint64 value from the payload.

func (*PacketParser) ParseUint8

func (p *PacketParser) ParseUint8() uint8

ParseUint8 parses a uint8 value from the payload.

func (*PacketParser) SetErr

func (p *PacketParser) SetErr(err error)

SetErr sets an error in the parser.

Only the first call will set an error.

type PacketPool

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

A PacketPool is a thread-safe pool of Packet.

func (*PacketPool) Clone

func (p *PacketPool) Clone(packet Packet) Packet

Clone returns a packet from the pool with the content of the given packet.

func (*PacketPool) Get

func (p *PacketPool) Get(size int) Packet

Get returns a packet from the pool with at least the given size. If it does not find one, it allocates it.

Panics if size > MaxPacketSize.

func (*PacketPool) Put

func (p *PacketPool) Put(packets ...Packet)

Put returns packets to the pool.

type PendingAck

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

Directories

Path Synopsis
cmd
example/chat command
genpackets command
internal

Jump to

Keyboard shortcuts

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