photon

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: May 17, 2026 License: MIT Imports: 8 Imported by: 0

README

photon-parser

Download

As a Go dependency (recommended when you only need the library in your module):

go get github.com/AutoDruid/photon-parser@latest

Clone the repository (for contributing, running examples, or local development):

git clone https://github.com/AutoDruid/photon-parser.git
cd photon-parser

Introduction

photon-parser is a Go library that decodes Photon session envelopes and command payloads from raw bytes—useful for inspecting captures, learning how the wire format is structured, and building tools around Photon traffic. This project is explanatory and educational: it documents and parses protocol data for understanding; it does not endorse any particular use, and maintainers are not responsible for how you apply it (including compliance, game or service terms, or any risk you take when handling real traffic). The library supports protocol version 16 and protocol version 18 (distinct parameter layouts and reliable-header parameter counting). For more information look at the documentation.

How it works

Parsing is sequential: an internal Reader holds the input buffer and a cursor that advances as fields are read—there is no upfront full decode into a giant tree. Lazy access shows up in how you read values after parse: scalars are read when you call accessor methods; arrays, dictionaries, and other composite parameters are exposed as Go iter sequences (or similar pull-based access) so underlying bytes are processed as you iterate, instead of allocating everything up front.

Local development

This repo pins Go and tooling in .mise/config.toml. With mise installed:

  1. Clone the repository and cd into it.
  2. Run mise install in the project root so the pinned Go and golangci-lint versions are available.
  3. Use the defined tasks (run mise tasks to list them)

From any subdirectory, mise resolves config upward; staying under the repo root ensures these tasks use the pinned toolchain.

Contributing

Contributions are welcome. Open an issue to describe a bug, a protocol gap, or a feature you have in mind so maintainers can discuss scope and approach. When you are ready to implement a fix or enhancement, resolve it with a pull request that references the issue and keeps the change focused and easy to review.

Documentation

Overview

Package photon decodes Photon session envelopes and reliable payloads from raw bytes. It supports protocol versions 16 and 18, which differ in parameter layout and how reliable headers declare parameter counts.

Basic usage

parser := photon.NewParserV18()
var sess photon.SessionV18
if err := parser.ParsePacketInto(payload, &sess); err != nil {
    log.Fatal(err)
}
for _, cmd := range sess.Commands {
    fmt.Println(cmd.Type)
}

Performance

ParsePacketInto is the zero-allocation hot path: it reuses internal pools and writes into the caller-supplied Session. The Session and its Commands slice are valid only until the next call to ParsePacketInto on the same Parser.

Hooks (sync and async) are a convenience layer and carry additional cost:

  • Sync hooks run inline during parsing; a slow callback blocks the parser.
  • Async hooks copy the Commands slice before sending to avoid use-after-pool corruption; prefer the direct Session() approach for high-throughput paths.

Public type aliases and wire-level constants for Photon decoding.

Index

Constants

View Source
const (
	AcknowledgeCommand          = types.AcknowledgeCommand
	ConnectCommand              = types.ConnectCommand
	VerifyConnectCommand        = types.VerifyConnectCommand
	DisconnectCommand           = types.DisconnectCommand
	PingCommand                 = types.PingCommand
	SendReliableCommand         = types.SendReliableCommand
	SendUnreliableCommand       = types.SendUnreliableCommand
	SendReliableFragmentCommand = types.SendReliableFragmentCommand
)

Photon command type bytes (CommandHeader.Type).

View Source
const (
	OperationRequest       = types.OperationRequest
	OperationResponse      = types.OperationResponse
	OtherOperationResponse = types.OtherOperationResponse
	EventDataType          = types.EventDataType
	ExchangeKeys           = types.ExchangeKeys
)

Reliable payload message kinds (ReliableHeader.Type).

Variables

This section is empty.

Functions

This section is empty.

Types

type Command

type Command[P types.ParameterView] = types.Command[P]

type CommandType added in v1.0.0

type CommandType = types.CommandType

type CommandV16 added in v1.0.0

type CommandV16 = types.Command[v16.Parameter]

CommandV16 is a single parsed Photon command with v16 parameter payloads.

type CommandV18 added in v1.0.0

type CommandV18 = types.Command[v18.Parameter]

CommandV18 is a single parsed Photon command with v18 parameter payloads.

type HookOptions

type HookOptions = types.HookOptions

HookOptions configures asynchronous hooks; Size is the channel buffer capacity.

type MessageType added in v1.0.0

type MessageType = types.MessageType

type Option added in v1.0.0

type Option func(*types.Config)

Option is a functional option that configures a Parser at construction time. Pass Options to NewParserV16 or NewParserV18.

func SkipCommands added in v1.0.0

func SkipCommands(commands ...types.CommandType) Option

SkipCommands registers one or more command types that the parser should skip entirely. The payload bytes of a skipped command are consumed but not decoded, and no hooks are fired for it.

This is useful when a capture contains high-frequency commands (such as AcknowledgeCommand or PingCommand) that are irrelevant to your analysis.

parser := photon.NewParserV18(
    photon.SkipCommands(photon.AcknowledgeCommand, photon.PingCommand),
)

func SkipParameterParsing added in v1.0.0

func SkipParameterParsing(skip bool) Option

SkipParameterParsing controls whether the parser skips decoding parameters inside reliable and unreliable payloads.

Enable this option when you only need command-level metadata (type, sequence number, event code) and do not need to inspect individual parameters. It avoids all per-parameter allocations on the hot path.

parser := photon.NewParserV18(photon.SkipParameterParsing(true))

func SkipTargetEventCodes added in v1.0.0

func SkipTargetEventCodes(codes ...types.MessageType) Option

SkipTargetEventCodes registers one or more message types whose parameters the parser should skip. The reliable header is still decoded (giving you the event code and parameter count) but the parameter bytes are consumed without being parsed, and no parameter hooks are fired.

Use this option to ignore high-volume event types that are not relevant to your workload, reducing CPU and allocation overhead.

parser := photon.NewParserV18(
    photon.SkipTargetEventCodes(photon.OperationRequest, photon.OperationResponse),
)

func SkipUnknownPayloads added in v1.0.0

func SkipUnknownPayloads(skip bool) Option

SkipUnknownPayloads controls whether the parser silently skips command payloads it does not recognise (for example encrypted or future command types) instead of storing their raw bytes.

Enabling this option reduces allocations when unknown payloads are frequent and their raw content is not needed.

parser := photon.NewParserV18(photon.SkipUnknownPayloads(true))

type ParameterV16

type ParameterV16 = v16.Parameter

ParameterV16 is the decoded v16 parameter value type used with Parser v16 APIs.

type ParameterV16Type added in v1.0.0

type ParameterV16Type = v16.ParameterType

ParameterV16Type is the v16 on-wire type discriminator for one parameter slot.

type ParameterV18

type ParameterV18 = v18.Parameter

ParameterV18 is the decoded v18 parameter value type used with Parser v18 APIs.

type ParameterV18Type

type ParameterV18Type = v18.ParameterType

ParameterV18Type is the v18 on-wire type discriminator for one parameter slot.

type Parser

type Parser[P types.ParameterView] struct {
	// contains filtered or unexported fields
}

Parser decodes Photon UDP payloads for a fixed protocol version. Create one with NewParserV16 or NewParserV18.

A Parser is not safe for concurrent use. For parallel workloads, create one Parser per goroutine.

func NewParserV16 added in v1.0.0

func NewParserV16(options ...Option) *Parser[v16.Parameter]

NewParserV16 returns a Parser that decodes parameters and reliable headers using Photon protocol version 16 rules.

Pass functional Option values to override the default configuration, for example to skip unknown payloads or filter specific command types.

func NewParserV18 added in v1.0.0

func NewParserV18(options ...Option) *Parser[v18.Parameter]

NewParserV18 returns a Parser that decodes parameters and reliable headers using Photon protocol version 18 rules.

Pass functional Option values to override the default configuration, for example to skip unknown payloads or filter specific command types.

func (*Parser[P]) Close

func (p *Parser[P]) Close()

Close closes all async hook channels registered via [OnSessionAsync], [OnCommandAsync], and [OnParameterAsync], signalling consumers that no further values will be sent.

After Close, new async hooks can be registered by calling the On*Async methods again.

func (*Parser[P]) OnCommandAsync

func (p *Parser[P]) OnCommandAsync(options types.HookOptions) <-chan Command[P]

OnCommandAsync returns a receive-only channel that receives each decoded Command during [ParsePacketInto].

If the channel buffer is full the command is dropped silently. Call [Close] when you are done.

func (*Parser[P]) OnCommandSync

func (p *Parser[P]) OnCommandSync(fn func(Command[P]))

OnCommandSync registers a sync callback invoked once per decoded command during [ParsePacketInto].

The Command passed to fn is valid only for the duration of the call; copy any fields you need to retain.

func (*Parser[P]) OnEventData added in v1.0.0

func (p *Parser[P]) OnEventData(fn func(Reliable[P]))

OnEventData registers a sync callback invoked for each reliable EventData message (server-raised events) decoded during [ParsePacketInto].

The callback runs on the parser goroutine; a slow implementation will reduce parsing throughput. For non-blocking processing use [OnSessionAsync] or decouple work with your own channel.

func (*Parser[P]) OnOperationRequest added in v1.0.0

func (p *Parser[P]) OnOperationRequest(fn func(Reliable[P]))

OnOperationRequest registers a sync callback invoked for each reliable OperationRequest message decoded during [ParsePacketInto].

func (*Parser[P]) OnOperationResponse added in v1.0.0

func (p *Parser[P]) OnOperationResponse(fn func(Reliable[P]))

OnOperationResponse registers a sync callback invoked for each reliable OperationResponse message decoded during [ParsePacketInto].

func (*Parser[P]) OnOtherOperationResponse added in v1.0.0

func (p *Parser[P]) OnOtherOperationResponse(fn func(Reliable[P]))

OnOtherOperationResponse registers a sync callback invoked for each reliable OtherOperationResponse message decoded during [ParsePacketInto].

func (*Parser[P]) OnParameterAsync

func (p *Parser[P]) OnParameterAsync(options types.HookOptions) <-chan P

OnParameterAsync returns a receive-only channel that receives each decoded parameter during [ParsePacketInto].

If the channel buffer is full the parameter is dropped silently. Call [Close] when you are done.

func (*Parser[P]) OnParameterSync

func (p *Parser[P]) OnParameterSync(fn func(P))

OnParameterSync registers a sync callback invoked once per decoded parameter during [ParsePacketInto].

func (*Parser[P]) OnSessionAsync

func (p *Parser[P]) OnSessionAsync(options types.HookOptions) <-chan Session[P]

OnSessionAsync returns a receive-only channel that receives a copy of each decoded Session after [ParsePacketInto] completes.

The Commands slice is copied before sending to guarantee safe access after the parser has moved on; this allocation is the trade-off for non-blocking delivery. If the channel buffer is full the session is dropped silently — size the buffer (via HookOptions.Size) to match your consumer throughput.

Call [Close] when you are done to drain and close the underlying channel.

func (*Parser[P]) OnSessionSync

func (p *Parser[P]) OnSessionSync(fn func(Session[P]))

OnSessionSync registers a sync callback invoked once per [ParsePacketInto] call, after the full session (header + all commands) has been decoded.

The Session passed to fn is valid only for the duration of the call; copy any fields you need to retain.

func (*Parser[P]) ParsePacketInto added in v1.0.0

func (p *Parser[P]) ParsePacketInto(data []byte, sess *Session[P]) error

ParsePacketInto resets the internal reader to data and decodes one Photon session into sess.

This is the zero-allocation hot path. The parsed Session and its Commands slice are valid only until the next call to ParsePacketInto on the same Parser; do not retain references across calls unless you copy the data you need.

Any sync or async hooks registered on the Parser are invoked during this call.

type Reliable added in v1.0.0

type Reliable[P types.ParameterView] = types.Reliable[P]

Reliable is a parsed reliable/unreliable message body: header plus a parameter list. It appears inside Command payloads (for example SendReliable / SendUnreliable).

type ReliableV16 added in v1.0.0

type ReliableV16 = Reliable[ParameterV16]

ReliableV16 is Reliable[ParameterV16], the shape of reliable payloads for NewV16 parsers.

type ReliableV18 added in v1.0.0

type ReliableV18 = Reliable[ParameterV18]

ReliableV18 is Reliable[ParameterV18], the shape of reliable payloads for NewV18 parsers.

type Session

type Session[P types.ParameterView] = types.Session[P]

type SessionV16 added in v1.0.0

type SessionV16 = types.Session[v16.Parameter]

SessionV16 is a decoded Photon session using protocol 16 parameters (see NewV16).

func ParsePacketV16 added in v1.0.0

func ParsePacketV16(data []byte, options ...Option) (*SessionV16, error)

ParsePacketV16 is a convenience wrapper that allocates a one-shot protocol 16 Parser, parses data, and returns the resulting Session.

For repeated parsing of multiple packets, prefer NewParserV16 and reuse the Parser to avoid per-call allocation overhead.

type SessionV18 added in v1.0.0

type SessionV18 = types.Session[v18.Parameter]

SessionV18 is a decoded Photon session using protocol 18 parameters (see NewV18).

func ParsePacketV18 added in v1.0.0

func ParsePacketV18(data []byte, options ...Option) (*SessionV18, error)

ParsePacketV18 is a convenience wrapper that allocates a one-shot protocol 18 Parser, parses data, and returns the resulting Session.

For repeated parsing of multiple packets, prefer NewParserV18 and reuse the Parser to avoid per-call allocation overhead.

Directories

Path Synopsis
internal
session
Package session provides parsing for Photon Protocol session layer packets.
Package session provides parsing for Photon Protocol session layer packets.

Jump to

Keyboard shortcuts

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