sourcenet

package module
v0.0.0-...-298beda Latest Latest
Warning

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

Go to latest
Published: Nov 21, 2023 License: Unlicense Imports: 9 Imported by: 0

README

GoDoc Go report card GolangCI Build Status CircleCI

SourceNet

A Source Engine multiplayer client netcode implementation in Golang. This is very incomplete, and is based primarily on reverse engineering cs:source packet data, with a little help from the Source Engine code leaks (also see credits).

Getting started
Prerequisites
  • Steam must be running, or steamworks will have issues.
  • steam_api64.dll must be obtained from Steamworks SDK, and placed in this directory.
  • Create a file named steam_appid.txt. Contents should be only the Source Engine game appid you are acting as (e.g. Counterstrike: Source has appid 240).
Examples

There are 2 examples currently.

  • Query public info from servers. This is the same information that you see on the Steam server browser listing.
  • Initial client authentication and handshake. This example will progress to the point where the server begins to send packets to the client of its own accord.
Credits

A lot of this wouldn't have been possible without the work of leystryku: https://github.com/Leystryku/leysourceengineclient

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Channel

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

Channel is is responsible for processing received packets into appropriate formats.

func NewChannel

func NewChannel() *Channel

NewChannel return a new channel struct

func (*Channel) GetMessages

func (channel *Channel) GetMessages() []IMessage

GetMessages returns all received complete messages (ie packets that are not waiting for fragments)

func (*Channel) HandleSplitPacket

func (channel *Channel) HandleSplitPacket(recvdata *bitbuf.Reader) int

HandleSplitPacket process a packet that contains multiple entries @TODO Implement me

func (*Channel) ProcessPacket

func (channel *Channel) ProcessPacket(msg IMessage) bool

ProcessPacket Reads received packet header and determines if the packet is ready to be inspected outside on the netcode. Any packet not deemed ready (e.g. split packet) will be queued until it is ready

func (*Channel) ReadHeader

func (channel *Channel) ReadHeader(msg IMessage) (flags int32, headerSize int32)

ReadHeader parses the received packet header. Returned data is header flags value.

func (*Channel) WaitingOnFragments

func (channel *Channel) WaitingOnFragments() bool

WaitingOnFragments tests if the channel is expecting more fragments for a packet

func (*Channel) WriteHeader

func (channel *Channel) WriteHeader(msg IMessage, subchans bool) IMessage

WriteHeader writes header bytes to a message, then returns the modified message. Returns nil if there is 0 bytes to generate checksum against (ie empty body)

type Client

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

Client is a Source Engine multiplayer client

func NewClient

func NewClient() *Client

NewClient returns a new client object

func (*Client) AddListener

func (client *Client) AddListener(target IListener)

AddListener adds a callback handler for packet data

func (*Client) Connect

func (client *Client) Connect(host string, port string) error

Connect Connects to a Source Engine Server

func (*Client) Disconnect

func (client *Client) Disconnect(msg IMessage)

Disconnect ends the socket connection. This must not be confused with sending the disconnect packet to a server. Failure to send a disconnect packet before calling Disconnect() will result in the server waiting for client packets until it times out.

func (*Client) SendMessage

func (client *Client) SendMessage(msg IMessage, hasSubChannels bool) bool

SendMessage send a message to connected server

type Connection

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

Connection is A UDP Connection for sending and receiving messages to a Source Engine server

func Connect

func Connect(host string, port string) (*Connection, error)

Connect Establishes a connection with a server. Only ensures target ip:port is reachable.

func (*Connection) Receive

func (conn *Connection) Receive() IMessage

Receive waits for a message from connected server

func (*Connection) Send

func (conn *Connection) Send(msg IMessage) (length int, err error)

Send Sends a passed message to connected server

type DataFragment

type DataFragment struct {
	Filename              string
	Buffer                []byte
	SizeInBytes           uint32
	SizeInBits            uint32
	TransferID            uint32 // Used only for files
	IsCompressed          bool   // Is bzip compressed
	SizeUncompressed      uint32
	AsTCP                 bool // Send as TCP stream
	NumFragments          int32
	AcknowledgedFragments int32 // Fragments sent and acknowledges
	PendingFragments      int32 // Fragments sent, but not (yet) acknowledged
	FragmentOffsets       []int32
}

DataFragment is used for receiving files from the server. Since files are almost certainly

type IListener

type IListener interface {
	Register(*Client)
	Receive(msg IMessage, msgType int)
}

IListener Listener interface for receive packets

type IMessage

type IMessage interface {
	Connectionless() bool // Is this message a connectionless message
	Data() []byte         // Get message contents
}

IMessage interface for any message type we should either send or receive

type SplitPacket

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

SplitPacket is a case when a message can contain multiple packet types

type SubChannel

type SubChannel struct {
	// FirstFragment is the first fragments
	FirstFragment [maxStreams]int32
	// NumFragments is the number of fragments that make up
	NumFragments [maxStreams]int32
	// SendSequenceCounter
	SendSequenceCounter int32
	// State 0=free, 1=scheduled to read, 2=send & waiting, 3=dirty
	State int32
	// Index into containing channels subchannel array
	Index int32
}

SubChannel is primarily used for splitting packet types up in the primary channel

func (*SubChannel) Free

func (channel *SubChannel) Free()

Free clears up the SubChannel

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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