Documentation ¶
Overview ¶
Package zanarkand provides TCP packet reassembly for FFXIV network streams and some simple interfaces to access them. The main use is for capturing FFXIV IPC Messages for parsing or analysis of game events. In FFXIV, communication between the client and server is done via RPC. Each IPC message is identified by a Segment ID to identify it's payload type, and some Segment-specific fields such as opcodes to identify IPC types.. One or more Messages are then wrapped into a Frame, optionally compressed with ZLIB, and transmitted over TCP.
Index ¶
Constants ¶
const ( SessionInit = 1 SessionRecv = 2 GameEvent = 3 ServerPing = 7 ServerPong = 8 EncryptInit = 9 EncryptRecv = 10 )
Segment types separate messages into their relevant field maps. Session/Encryption types are not implemented due to them largely only containing the player ID, or information that should be kept hidden due to privacy concerns. While this may inconvenience debugging, this project will not facilitate capturing player login details.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ErrDecodingFailure ¶
type ErrDecodingFailure struct {
Err error
}
ErrDecodingFailure indicates an error during decoding a specific message type.
func (ErrDecodingFailure) Error ¶
func (e ErrDecodingFailure) Error() string
func (*ErrDecodingFailure) Unwrap ¶
func (e *ErrDecodingFailure) Unwrap() error
type ErrNotEnoughData ¶
ErrNotEnoughData occurs when the Length field is longer than the payload.
func (ErrNotEnoughData) Error ¶
func (e ErrNotEnoughData) Error() string
func (*ErrNotEnoughData) Unwrap ¶
func (e *ErrNotEnoughData) Unwrap() error
type ErrUnknownInput ¶
type ErrUnknownInput struct {
Err error
}
ErrUnknownInput indicates the provided mode for a sniffer is not a known type.
func (*ErrUnknownInput) Unwrap ¶
func (e *ErrUnknownInput) Unwrap() error
type FlowDirection ¶
type FlowDirection int
FlowDirection indicates the flow being inbound or outbound.
const ( FrameIngress FlowDirection = 1 FrameEgress FlowDirection = 2 )
FrameIngress is an inbound Frame. FrameEgress is an outbound Frame.
type Frame ¶
type Frame struct { Magic uint64 `json:"-"` // [0:8] - mainly to verify magic bytes Timestamp time.Time `json:"-"` // [16:24] - timestamp in milliseconds since epoch Length uint32 `json:"size"` // [24:28] Connection uint16 `json:"connectionType"` // [28:30] - 0 lobby, 1 zone, 2 chat Count uint16 `json:"count"` // [30:32] Compressed bool `json:"compressed"` // [33] UINT8 bool tho Body []byte `json:"-"` // contains filtered or unexported fields }
Frame is an FFXIV bundled message encapsulation layer. Currently, bytes 4:7, 8:15, 32, and 34:39 are unknown.
func (*Frame) Direction ¶
func (f *Frame) Direction() FlowDirection
Direction outputs if the Frame is inbound or outbound.
func (*Frame) MarshalJSON ¶
MarshalJSON provides an override for timestamp handling for encoding/JSON
type GameEventMessage ¶
type GameEventMessage struct { GenericHeader Opcode uint16 `json:"opcode"` // [18:20] - message context identifier, the "opcode" ServerID uint16 `json:"serverID"` // [22:24] Timestamp time.Time `json:"-"` // [24:28] Body []byte `json:"-"` // contains filtered or unexported fields }
GameEventMessage is a pre-type casted GameEventHeader and body.
func (*GameEventMessage) Decode ¶
func (m *GameEventMessage) Decode(r *bufio.Reader) error
Decode turns a byte payload into a real GameEventMessage.
func (GameEventMessage) IsMessage ¶
func (GameEventMessage) IsMessage()
IsMessage confirms a GameEventMessage is a Message.
func (*GameEventMessage) MarshalJSON ¶
func (m *GameEventMessage) MarshalJSON() ([]byte, error)
MarshalJSON provides an override for timestamp handling for encoding/JSON
func (*GameEventMessage) String ¶
func (m *GameEventMessage) String() string
String prints a Segment and IPC Message specific headers.
type GameEventSubscriber ¶
type GameEventSubscriber struct { IngressEvents chan *GameEventMessage EgressEvents chan *GameEventMessage }
GameEventSubscriber is a Subscriber for GameEvent segments.
func NewGameEventSubscriber ¶
func NewGameEventSubscriber() *GameEventSubscriber
NewGameEventSubscriber returns a Subscriber handle with channels for inbound and outbound GameEventMessages.
func (*GameEventSubscriber) Close ¶
func (g *GameEventSubscriber) Close(s *Sniffer)
Close will stop a sniffer, drain the channels, then close the channels.
func (*GameEventSubscriber) Subscribe ¶
func (g *GameEventSubscriber) Subscribe(s *Sniffer) error
Subscribe starts the GameEventSubscriber.
type GenericHeader ¶
type GenericHeader struct { Length uint32 `json:"size"` // [0:4] SourceActor uint32 `json:"sourceActorID"` // [4:8] TargetActor uint32 `json:"targetActorID"` // [8:12] Segment uint16 `json:"segmentType"` // [12:14] // contains filtered or unexported fields }
GenericHeader provides the metadata for an FFXIV IPC. 0:16 provide the generic header, other types have additional header fields. Data pulled from Sapphire's `Network/CommonNetwork.h`
func (*GenericHeader) Decode ¶
func (m *GenericHeader) Decode(r *bufio.Reader) error
Decode a GenericHeader from a byte array.
func (*GenericHeader) String ¶
func (m *GenericHeader) String() string
String is a stringer for the GenericHeader of a Message.
type GenericMessage ¶
type GenericMessage interface { Decode(*bufio.Reader) error IsMessage() MarshalJSON() ([]byte, error) String() string }
GenericMessage is an interface for other Message types to make the Framer generic.
type KeepaliveMessage ¶
type KeepaliveMessage struct { GenericHeader ID uint32 `json:"ID"` // [16:20] Timestamp time.Time `json:"-"` // [20:24] }
KeepaliveMessage is a representation of ping/pong requests.
func (*KeepaliveMessage) Decode ¶
func (m *KeepaliveMessage) Decode(r *bufio.Reader) error
Decode turns a byte payload into a real KeepaliveMessage.
func (KeepaliveMessage) IsMessage ¶
func (KeepaliveMessage) IsMessage()
IsMessage confirms a KeepaliveMessage is a Message.
func (*KeepaliveMessage) MarshalJSON ¶
func (m *KeepaliveMessage) MarshalJSON() ([]byte, error)
MarshalJSON provides an override for timestamp handling for encoding/JSON
func (*KeepaliveMessage) String ¶
func (m *KeepaliveMessage) String() string
String prints the Segment header and Keepalive Message.
type KeepaliveSubscriber ¶
type KeepaliveSubscriber struct {
Events chan *KeepaliveMessage
}
KeepaliveSubscriber is a Subscriber for Keepalive segments.
func NewKeepaliveSubscriber ¶
func NewKeepaliveSubscriber() *KeepaliveSubscriber
NewKeepaliveSubscriber returns a Subscriber handle. As the traffic is minimal, this subscriber uses a single Event channel.
func (*KeepaliveSubscriber) Close ¶
func (k *KeepaliveSubscriber) Close(s *Sniffer)
Close will stop a sniffer, drain the channel, then close the channel.
func (*KeepaliveSubscriber) Subscribe ¶
func (k *KeepaliveSubscriber) Subscribe(s *Sniffer) error
Subscribe starts the KeepaliveSubscriber.
type Sniffer ¶
type Sniffer struct { // Sniffer State Active bool Status string Source *gopacket.PacketSource // contains filtered or unexported fields }
Sniffer is a representation of a packet source, filter, and destination.
func NewSniffer ¶
NewSniffer creates a Sniffer instance.
type Subscriber ¶
type Subscriber interface { Subscribe(*Sniffer) Close() }
Subscriber describes the interface for individual Frame segment subscribers.