raknet

package
v0.0.0-...-d1826b6 Latest Latest
Warning

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

Go to latest
Published: Feb 23, 2022 License: AGPL-3.0, MIT Imports: 16 Imported by: 0

README

go-raknet

go-raknet is a library that implements a basic version of the RakNet protocol, which is used for Minecraft (Bedrock Edition). It implements Unreliable, Reliable and ReliableOrdered packets and sends user packets as ReliableOrdered.

go-raknet attempts to abstract away direct interaction with RakNet, and provides simple to use, idiomatic Go API used to listen for connections or connect to servers.

Getting started

Prerequisites

To use this library, Go must be installed. go-raknet does not depend on any other libraries than the standard Go library.

Usage

go-raknet can be used for both clients and servers, (and proxies, when combined) in a way very similar to the standard net.TCP* functions.

Basic RakNet server:

package main

import (
	"github.com/CMA2401PT/PhoenixBuilderHeadless/go_raknet_1_9_1"
)

func main() {
    listener, _ := raknet.Listen("0.0.0.0:19132")
    defer listener.Close()
    for {
        conn, _ := listener.Accept()
        
        b := make([]byte, 1024*1024*4)
        _, _ = conn.Read(b)
        _, _ = conn.Write([]byte{1, 2, 3})
        
        conn.Close()
    }
}

Basic RakNet client:

package main

import (
	"github.com/CMA2401PT/PhoenixBuilderHeadless/go_raknet_1_9_1"
)

func main() {
    conn, _ := raknet.Dial("mco.mineplex.com:19132")
    defer conn.Close()
    
    b := make([]byte, 1024*1024*4)
    _, _ = conn.Write([]byte{1, 2, 3})
    _, _ = conn.Read(b)
}

For an example on how to apply these and other methods in order to create a proxy, see the examples/proxy folder.

Documentation

PkgGoDev

Contact

Chat on Discord

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ErrConnectionClosed

func ErrConnectionClosed(err error) bool

ErrConnectionClosed checks if the error passed was an error caused by reading from a Conn of which the connection was closed.

func Ping

func Ping(address string) (response []byte, err error)

Ping sends a ping to an address and returns the response obtained. If successful, a non-nil response byte slice containing the data is returned. If the ping failed, an error is returned describing the failure. Note that the packet sent to the server may be lost due to the nature of UDP. If this is the case, an error is returned which implies a timeout occurred. Ping will timeout after 5 seconds.

Example
package main

import (
	raknet "github.com/CMA2401PT/PhoenixBuilderHeadless/go_raknet_1_9_1"
	bridge_fmt "github.com/CMA2401PT/PhoenixBuilderHeadless/session/bridge/fmt"
)

func main() {
	const address = "mco.mineplex.com:19132"

	// Ping the target address. This will ping with a timeout of 5 seconds. raknet.PingContext and
	// raknet.PingTimeout may be used to cancel at any other time.
	data, err := raknet.Ping(address)
	if err != nil {
		panic("error pinging " + address + ": " + err.Error())
	}
	str := string(data)

	bridge_fmt.Println(str[:4])
}
Output:

MCPE

func PingContext

func PingContext(ctx context.Context, address string) (response []byte, err error)

PingContext sends a ping to an address and returns the response obtained. If successful, a non-nil response byte slice containing the data is returned. If the ping failed, an error is returned describing the failure. Note that the packet sent to the server may be lost due to the nature of UDP. If this is the case, PingContext could last indefinitely, hence a timeout should always be attached to the context passed. PingContext cancels as soon as the deadline expires.

func PingTimeout

func PingTimeout(address string, timeout time.Duration) ([]byte, error)

PingTimeout sends a ping to an address and returns the response obtained. If successful, a non-nil response byte slice containing the data is returned. If the ping failed, an error is returned describing the failure. Note that the packet sent to the server may be lost due to the nature of UDP. If this is the case, an error is returned which implies a timeout occurred. PingTimeout will time out after the duration passed.

Types

type Conn

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

Conn represents a connection to a specific client. It is not a real connection, as UDP is connectionless, but rather a connection emulated using RakNet. Methods may be called on Conn from multiple goroutines simultaneously.

func Dial

func Dial(address string) (*Conn, error)

Dial attempts to dial a RakNet connection to the address passed. The address may be either an IP address or a hostname, combined with a port that is separated with ':'. Dial will attempt to dial a connection within 10 seconds. If not all packets are received after that, the connection will timeout and an error will be returned. Dial fills out a Dialer struct with a default error logger.

Example
package main

import (
	raknet "github.com/CMA2401PT/PhoenixBuilderHeadless/go_raknet_1_9_1"
)

func main() {
	const address = "mco.mineplex.com:19132"

	// Dial a connection to the target address. This will time out after up to 10 seconds. raknet.DialTimeout
	// and raknet.DialContext may be used to cancel at any other time.
	conn, err := raknet.Dial(address)
	if err != nil {
		panic("error connecting to " + address + ": " + err.Error())
	}

	// Read a packet from the connection dialed.
	p := make([]byte, 1500)
	n, err := conn.Read(p)
	if err != nil {
		panic("error reading packet from " + address + ": " + err.Error())
	}
	p = p[:n]

	// Write a packet to the connection.
	data := []byte("Hello World!")
	if _, err := conn.Write(data); err != nil {
		panic("error writing packet to " + address + ": " + err.Error())
	}

	// Close the connection after you're done with it.
	if err := conn.Close(); err != nil {
		panic("error closing connection: " + err.Error())
	}
}
Output:

func DialContext

func DialContext(ctx context.Context, address string) (*Conn, error)

DialContext attempts to dial a RakNet connection to the address passed. The address may be either an IP address or a hostname, combined with a port that is separated with ':'. DialContext will use the deadline (ctx.Deadline) of the context.Context passed for the maximum amount of time that the dialing can take. DialContext will terminate as soon as possible when the context.Context is closed.

func DialTimeout

func DialTimeout(address string, timeout time.Duration) (*Conn, error)

DialTimeout attempts to dial a RakNet connection to the address passed. The address may be either an IP address or a hostname, combined with a port that is separated with ':'. DialTimeout will attempt to dial a connection within the timeout duration passed. If not all packets are received after that, the connection will timeout and an error will be returned.

func (*Conn) Close

func (conn *Conn) Close() error

Close closes the connection. All blocking Read or Write actions are cancelled and will return an error.

func (*Conn) Latency

func (conn *Conn) Latency() time.Duration

Latency returns a rolling average of latency between the sending and the receiving end of the connection. The latency returned is updated continuously and is half the round trip time (RTT).

func (*Conn) LocalAddr

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

LocalAddr returns the local address of the connection, which is always the same as the listener's.

func (*Conn) Read

func (conn *Conn) Read(b []byte) (n int, err error)

Read reads from the connection into the byte slice passed. If successful, the amount of bytes read n is returned, and the error returned will be nil. Read blocks until a packet is received over the connection, or until the session is closed or the read times out, in which case an error is returned.

func (*Conn) ReadPacket

func (conn *Conn) ReadPacket() (b []byte, err error)

ReadPacket attempts to read the next packet as a byte slice. ReadPacket blocks until a packet is received over the connection, or until the session is closed or the read times out, in which case an error is returned.

func (*Conn) RemoteAddr

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

RemoteAddr returns the remote address of the connection, meaning the address this connection leads to.

func (*Conn) SetDeadline

func (conn *Conn) SetDeadline(t time.Time) error

SetDeadline sets the deadline of the connection for both Read and Write. SetDeadline is equivalent to calling both SetReadDeadline and SetWriteDeadline.

func (*Conn) SetReadDeadline

func (conn *Conn) SetReadDeadline(t time.Time) error

SetReadDeadline sets the read deadline of the connection. An error is returned only if the time passed is before time.Now(). Calling SetReadDeadline means the next Read call that exceeds the deadline will fail and return an error. Setting the read deadline to the default value of time.Time removes the deadline.

func (*Conn) SetWriteDeadline

func (conn *Conn) SetWriteDeadline(time.Time) error

SetWriteDeadline has no behaviour. It is merely there to satisfy the net.Conn interface.

func (*Conn) Write

func (conn *Conn) Write(b []byte) (n int, err error)

Write writes a buffer b over the RakNet connection. The amount of bytes written n is always equal to the length of the bytes written if the write was successful. If not, an error is returned and n is 0. Write may be called simultaneously from multiple goroutines, but will write one by one.

type Dialer

type Dialer struct {
	// ErrorLog is a logger that errors from packet decoding are logged to. It may be set to a logger that
	// simply discards the messages.
	ErrorLog *log.Logger

	// UpstreamDialer is a dialer that is used for opening udp connections.
	UpstreamDialer net.Dialer
}

Dialer allows dialing a RakNet connection with specific configuration, such as the protocol version of the connection and the logger used.

func (Dialer) Dial

func (dialer Dialer) Dial(address string) (*Conn, error)

Dial attempts to dial a RakNet connection to the address passed. The address may be either an IP address or a hostname, combined with a port that is separated with ':'. Dial will attempt to dial a connection within 10 seconds. If not all packets are received after that, the connection will timeout and an error will be returned.

func (Dialer) DialContext

func (dialer Dialer) DialContext(ctx context.Context, address string) (*Conn, error)

DialContext attempts to dial a RakNet connection to the address passed. The address may be either an IP address or a hostname, combined with a port that is separated with ':'. DialContext will use the deadline (ctx.Deadline) of the context.Context passed for the maximum amount of time that the dialing can take. DialContext will terminate as soon as possible when the context.Context is closed.

func (Dialer) DialTimeout

func (dialer Dialer) DialTimeout(address string, timeout time.Duration) (*Conn, error)

DialTimeout attempts to dial a RakNet connection to the address passed. The address may be either an IP address or a hostname, combined with a port that is separated with ':'. DialTimeout will attempt to dial a connection within the timeout duration passed. If not all packets are received after that, the connection will timeout and an error will be returned.

func (Dialer) Ping

func (dialer Dialer) Ping(address string) ([]byte, error)

Ping sends a ping to an address and returns the response obtained. If successful, a non-nil response byte slice containing the data is returned. If the ping failed, an error is returned describing the failure. Note that the packet sent to the server may be lost due to the nature of UDP. If this is the case, an error is returned which implies a timeout occurred. Ping will timeout after 5 seconds.

func (Dialer) PingContext

func (dialer Dialer) PingContext(ctx context.Context, address string) (response []byte, err error)

PingContext sends a ping to an address and returns the response obtained. If successful, a non-nil response byte slice containing the data is returned. If the ping failed, an error is returned describing the failure. Note that the packet sent to the server may be lost due to the nature of UDP. If this is the case, PingContext could last indefinitely, hence a timeout should always be attached to the context passed. PingContext cancels as soon as the deadline expires.

func (Dialer) PingTimeout

func (dialer Dialer) PingTimeout(address string, timeout time.Duration) ([]byte, error)

PingTimeout sends a ping to an address and returns the response obtained. If successful, a non-nil response byte slice containing the data is returned. If the ping failed, an error is returned describing the failure. Note that the packet sent to the server may be lost due to the nature of UDP. If this is the case, an error is returned which implies a timeout occurred. PingTimeout will time out after the duration passed.

type ListenConfig

type ListenConfig struct {
	// ErrorLog is a logger that errors from packet decoding are logged to. It may be set to a logger that
	// simply discards the messages.
	ErrorLog *log.Logger
}

ListenConfig may be used to pass additional configuration to a Listener.

func (ListenConfig) Listen

func (l ListenConfig) Listen(address string) (*Listener, error)

Listen listens on the address passed and returns a listener that may be used to accept connections. If not successful, an error is returned. The address follows the same rules as those defined in the net.TCPListen() function. Specific features of the listener may be modified once it is returned, such as the used log and/or the accepted protocol.

type Listener

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

Listener implements a RakNet connection listener. It follows the same methods as those implemented by the TCPListener in the net package. Listener implements the net.Listener interface.

func Listen

func Listen(address string) (*Listener, error)

Listen listens on the address passed and returns a listener that may be used to accept connections. If not successful, an error is returned. The address follows the same rules as those defined in the net.TCPListen() function. Specific features of the listener may be modified once it is returned, such as the used log and/or the accepted protocol.

Example
package main

import (
	raknet "github.com/CMA2401PT/PhoenixBuilderHeadless/go_raknet_1_9_1"
)

func main() {
	const address = ":19132"

	// Start listening on an address.
	l, err := raknet.Listen(address)
	if err != nil {
		panic(err)
	}

	for {
		// Accept a new connection from the Listener. Accept will only return an error if the Listener is
		// closed. (So only after a call to Listener.Close.)
		conn, err := l.Accept()
		if err != nil {
			return
		}

		// Read a packet from the connection accepted.
		p := make([]byte, 1500)
		n, err := conn.Read(p)
		if err != nil {
			panic("error reading packet from " + conn.RemoteAddr().String() + ": " + err.Error())
		}
		p = p[:n]

		// Write a packet to the connection.
		data := []byte("Hello World!")
		if _, err := conn.Write(data); err != nil {
			panic("error writing packet to " + conn.RemoteAddr().String() + ": " + err.Error())
		}

		// Close the connection after you're done with it.
		if err := conn.Close(); err != nil {
			panic("error closing connection: " + err.Error())
		}
	}
}
Output:

func (*Listener) Accept

func (listener *Listener) Accept() (net.Conn, error)

Accept blocks until a connection can be accepted by the listener. If successful, Accept returns a connection that is ready to send and receive data. If not successful, a nil listener is returned and an error describing the problem.

func (*Listener) Addr

func (listener *Listener) Addr() net.Addr

Addr returns the address the Listener is bound to and listening for connections on.

func (*Listener) Close

func (listener *Listener) Close() error

Close closes the listener so that it may be cleaned up. It makes sure the goroutine handling incoming packets is able to be freed.

func (*Listener) ID

func (listener *Listener) ID() int64

ID returns the unique ID of the listener. This ID is usually used by a client to identify a specific server during a single session.

func (*Listener) PongData

func (listener *Listener) PongData(data []byte)

PongData sets the pong data that is used to respond with when a client sends a ping. It usually holds game specific data that is used to display in a server list. If a data slice is set with a size bigger than math.MaxInt16, the function panics.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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