sfs

package module
v0.0.0-...-6482224 Latest Latest
Warning

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

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

README

gosfs

Go Report Card Go Reference

A Go library and CLI for decoding and encoding SmartFoxServer 2X binary protocol packets.

gosfs provides a robust, zero-dependency implementation of the SFS2X binary wire format, optimized for performance and round-trip safety.

Table of Contents

Features

  • Zero dependencies — standard library only.
  • Round-trip safe — decode → encode produces identical payloads.
  • Ordered ObjectsSFSObject preserves insertion order to match the wire format.
  • Decode SFS binary frames from hex, base64, or raw bytes.
  • Encode Go data structures back to SFS binary format.
  • Pretty-print decoded packets in a human-readable trace format.
  • JSON output for integration with other tools like jq.

Installation

From source (local clone)

If you already have the repo cloned:

cd gosfs
go install ./cmd/sfs
From GitHub
go install github.com/lucasbalestero/gosfs/cmd/sfs@latest
As a library dependency
go get github.com/lucasbalestero/gosfs

Quick Start

Decode a hex-encoded SFS frame:

echo '800043120003000163020100016103000d00017012000300016308000332323200017204ffffffff000170120003000131040000c35200013204000001e90001370400000003' | sfs decode

CLI Usage

Reading input
# Pipe hex directly
echo '80004312...' | sfs decode

# Pipe from a file
sfs decode < frame.hex

# Read from a file path
sfs decode frame.hex
sfs decode -in base64 capture.b64
Output formats
# Human-readable text (default)
sfs decode frame.hex

# JSON (for scripting or piping to jq)
sfs decode -fmt json frame.hex | jq '.p.p'
Encoding & Type Inference

The encode command converts JSON to SFS binary.

echo '{"c":"1","p":{}}' | sfs encode

️ Important Limitation: Type Inference

JSON does not distinguish between numeric types (e.g., 10 could be a byte, short, int, or long). When encoding JSON, sfs attempts to guess the most appropriate SFS type:

  • Integers: Defaults to Int (32-bit). If the value exceeds 32-bit range, it uses Long (64-bit).
  • Floats: Defaults to Double (64-bit).
  • Booleans/Strings: Map directly.

SFS is strict. If a server expects a Short (2 bytes) and receives an Int (4 bytes), it may reject the packet. For precise control over types, use gosfs as a library where you can explicitly set the TypeID.

Library Usage

See examples/basic_usage/main.go for a complete example.

import sfs "github.com/lucasbalestero/gosfs"

// Decode a frame
frame, err := sfs.DecodeFrame(rawBytes)

// Build and encode
obj := sfs.NewObject()
obj.PutUtfString("name", "hello")
obj.PutInt("level", 42) // Explicitly set as Int (int32)
bytes, err := sfs.Encode(obj)

Project Structure

gosfs/
├── cmd/sfs/          CLI tool
├── examples/         Runnable usage examples
├── types.go          Value, Object, Array data types
├── decode.go         Binary → Go structs
├── encode.go         Go structs → Binary
├── frame.go          WebSocket frame envelope (flags + zlib)
├── format.go         Human-readable pretty-printer
├── FORMAT.md         SFS binary wire format specification
└── LICENSE           MIT License

Running Tests

go test ./... -v

Include fuzz tests (Go 1.18+):

go test -fuzz=FuzzDecode -fuzztime=10s

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-change)
  3. Write tests for your changes
  4. Ensure all tests pass (go test ./...)
  5. Open a pull request

License

MIT

Documentation

Overview

Package sfs implements encoding and decoding of SmartFoxServer 2X binary protocol data.

The package handles SFSObject and SFSArray structures, which are the primary serialization format used by SmartFoxServer for data exchange between clients and servers over WebSocket connections.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrKeyNotFound is returned when a requested key is not present in the object.
	ErrKeyNotFound = errors.New("sfs: key not found")
	// ErrTypeMismatch is returned when a value is not of the expected type.
	ErrTypeMismatch = errors.New("sfs: type mismatch")
	// ErrIndexOutOfBounds is returned when an index is outside the range of the array.
	ErrIndexOutOfBounds = errors.New("sfs: index out of bounds")
)
View Source
var ErrShortData = errors.New("sfs: short data")

ErrShortData indicates the input data is shorter than expected.

Functions

func Encode

func Encode(obj *Object) ([]byte, error)

Encode serializes an Object into SFS binary format.

func EncodeArray

func EncodeArray(arr *Array) ([]byte, error)

EncodeArray serializes an Array into SFS binary format.

func EncodeFrame

func EncodeFrame(f *Frame) ([]byte, error)

EncodeFrame serializes a Frame into wire bytes. If f.Compressed is true, the payload is zlib-compressed.

func Format

func Format(v Value) string

Format renders a Value as a human-readable indented string, similar to the decoded WebSocket traces used in protocol analysis.

func FormatObject

func FormatObject(obj *Object) string

FormatObject renders an Object as a human-readable indented string.

Types

type Array

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

Array is an ordered list of Values.

func DecodeArray

func DecodeArray(data []byte) (*Array, error)

DecodeArray reads an SFSArray from binary data.

func NewArray

func NewArray() *Array

NewArray creates an empty Array.

func (*Array) Add

func (a *Array) Add(v Value)

Add appends a value to the array.

func (*Array) AddBool

func (a *Array) AddBool(v bool)

AddBool appends a boolean value to the array.

func (*Array) AddBoolArray

func (a *Array) AddBoolArray(v []bool)

AddBoolArray appends a boolean array to the array.

func (*Array) AddByte

func (a *Array) AddByte(v int8)

AddByte appends a byte (int8) value to the array.

func (*Array) AddByteArray

func (a *Array) AddByteArray(v []byte)

AddByteArray appends a byte array to the array.

func (*Array) AddDouble

func (a *Array) AddDouble(v float64)

AddDouble appends a double (float64) value to the array.

func (*Array) AddDoubleArray

func (a *Array) AddDoubleArray(v []float64)

AddDoubleArray appends a double array to the array.

func (*Array) AddFloat

func (a *Array) AddFloat(v float32)

AddFloat appends a float (float32) value to the array.

func (*Array) AddFloatArray

func (a *Array) AddFloatArray(v []float32)

AddFloatArray appends a float array to the array.

func (*Array) AddInt

func (a *Array) AddInt(v int32)

AddInt appends an int (int32) value to the array.

func (*Array) AddIntArray

func (a *Array) AddIntArray(v []int32)

AddIntArray appends an int array to the array.

func (*Array) AddLong

func (a *Array) AddLong(v int64)

AddLong appends a long (int64) value to the array.

func (*Array) AddLongArray

func (a *Array) AddLongArray(v []int64)

AddLongArray appends a long array to the array.

func (*Array) AddNull

func (a *Array) AddNull()

AddNull appends a null value to the array.

func (*Array) AddSFSArray

func (a *Array) AddSFSArray(v *Array)

AddSFSArray appends a nested SFSArray to the array.

func (*Array) AddSFSObject

func (a *Array) AddSFSObject(v *Object)

AddSFSObject appends a nested SFSObject to the array.

func (*Array) AddShort

func (a *Array) AddShort(v int16)

AddShort appends a short (int16) value to the array.

func (*Array) AddShortArray

func (a *Array) AddShortArray(v []int16)

AddShortArray appends a short array to the array.

func (*Array) AddText

func (a *Array) AddText(v string)

AddText appends a text string value to the array.

func (*Array) AddUtfString

func (a *Array) AddUtfString(v string)

AddUtfString appends a UTF-8 string value to the array.

func (*Array) AddUtfStringArray

func (a *Array) AddUtfStringArray(v []string)

AddUtfStringArray appends a string array to the array.

func (*Array) ForEach

func (a *Array) ForEach(fn func(i int, val Value) bool)

ForEach calls fn for each element. If fn returns false, iteration stops.

func (*Array) Get

func (a *Array) Get(i int) Value

Get returns the value at index i. Panics if out of bounds.

func (*Array) GetBool

func (a *Array) GetBool(i int) (bool, error)

GetBool retrieves a boolean value at the given index.

func (*Array) GetBoolArray

func (a *Array) GetBoolArray(i int) ([]bool, error)

GetBoolArray retrieves a boolean array at the given index.

func (*Array) GetByte

func (a *Array) GetByte(i int) (int8, error)

GetByte retrieves a byte (int8) value at the given index.

func (*Array) GetByteArray

func (a *Array) GetByteArray(i int) ([]byte, error)

GetByteArray retrieves a byte array at the given index.

func (*Array) GetDouble

func (a *Array) GetDouble(i int) (float64, error)

GetDouble retrieves a double (float64) value at the given index.

func (*Array) GetDoubleArray

func (a *Array) GetDoubleArray(i int) ([]float64, error)

GetDoubleArray retrieves a double array at the given index.

func (*Array) GetFloat

func (a *Array) GetFloat(i int) (float32, error)

GetFloat retrieves a float (float32) value at the given index.

func (*Array) GetFloatArray

func (a *Array) GetFloatArray(i int) ([]float32, error)

GetFloatArray retrieves a float array at the given index.

func (*Array) GetInt

func (a *Array) GetInt(i int) (int32, error)

GetInt retrieves an int (int32) value at the given index.

func (*Array) GetIntArray

func (a *Array) GetIntArray(i int) ([]int32, error)

GetIntArray retrieves an int array at the given index.

func (*Array) GetLong

func (a *Array) GetLong(i int) (int64, error)

GetLong retrieves a long (int64) value at the given index.

func (*Array) GetLongArray

func (a *Array) GetLongArray(i int) ([]int64, error)

GetLongArray retrieves a long array at the given index.

func (*Array) GetSFSArray

func (a *Array) GetSFSArray(i int) (*Array, error)

GetSFSArray retrieves a nested SFSArray at the given index.

func (*Array) GetSFSObject

func (a *Array) GetSFSObject(i int) (*Object, error)

GetSFSObject retrieves a nested SFSObject at the given index.

func (*Array) GetShort

func (a *Array) GetShort(i int) (int16, error)

GetShort retrieves a short (int16) value at the given index.

func (*Array) GetShortArray

func (a *Array) GetShortArray(i int) ([]int16, error)

GetShortArray retrieves a short array at the given index.

func (*Array) GetText

func (a *Array) GetText(i int) (string, error)

GetText retrieves a text string value at the given index.

func (*Array) GetUtfString

func (a *Array) GetUtfString(i int) (string, error)

GetUtfString retrieves a UTF-8 string value at the given index.

func (*Array) GetUtfStringArray

func (a *Array) GetUtfStringArray(i int) ([]string, error)

GetUtfStringArray retrieves a string array at the given index.

func (*Array) IsNull

func (a *Array) IsNull(i int) bool

IsNull returns true if the element at index i is TypeNull.

func (*Array) Len

func (a *Array) Len() int

Len returns the number of elements.

func (*Array) RemoveAt

func (a *Array) RemoveAt(i int) error

RemoveAt removes the element at the given index.

func (*Array) Size

func (a *Array) Size() int

Size returns the number of elements in the array.

type Frame

type Frame struct {
	Flags      byte
	Compressed bool
	Payload    *Object
}

Frame represents a SmartFoxServer WebSocket frame. The wire format is:

[1 byte:  flags]
[2 bytes: payload length (big-endian)]
[N bytes: payload (optionally zlib-compressed SFSObject)]

func DecodeFrame

func DecodeFrame(data []byte) (*Frame, error)

DecodeFrame reads a full SFS WebSocket frame from raw bytes.

type Object

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

Object is an ordered map of string keys to Values. It preserves insertion order, matching the SFS wire format.

func Decode

func Decode(data []byte) (*Object, error)

Decode reads an SFSObject from binary data. The data must start at the beginning of an SFSObject encoding (i.e., the 2-byte entry count).

func NewObject

func NewObject() *Object

NewObject creates an empty Object.

func (*Object) ContainsKey

func (o *Object) ContainsKey(key string) bool

ContainsKey returns true if the key exists in the object.

func (*Object) ForEach

func (o *Object) ForEach(fn func(key string, val Value) bool)

ForEach calls fn for each key-value pair in insertion order. If fn returns false, iteration stops.

func (*Object) Get

func (o *Object) Get(key string) (Value, bool)

Get returns the value for the given key and whether it exists.

func (*Object) GetBool

func (o *Object) GetBool(key string) (bool, error)

GetBool retrieves a boolean value for the given key.

func (*Object) GetBoolArray

func (o *Object) GetBoolArray(key string) ([]bool, error)

GetBoolArray retrieves a boolean array for the given key.

func (*Object) GetByte

func (o *Object) GetByte(key string) (int8, error)

GetByte retrieves a byte (int8) value for the given key.

func (*Object) GetByteArray

func (o *Object) GetByteArray(key string) ([]byte, error)

GetByteArray retrieves a byte array for the given key.

func (*Object) GetDouble

func (o *Object) GetDouble(key string) (float64, error)

GetDouble retrieves a double (float64) value for the given key.

func (*Object) GetDoubleArray

func (o *Object) GetDoubleArray(key string) ([]float64, error)

GetDoubleArray retrieves a double array for the given key.

func (*Object) GetFloat

func (o *Object) GetFloat(key string) (float32, error)

GetFloat retrieves a float (float32) value for the given key.

func (*Object) GetFloatArray

func (o *Object) GetFloatArray(key string) ([]float32, error)

GetFloatArray retrieves a float array for the given key.

func (*Object) GetInt

func (o *Object) GetInt(key string) (int32, error)

GetInt retrieves an int (int32) value for the given key.

func (*Object) GetIntArray

func (o *Object) GetIntArray(key string) ([]int32, error)

GetIntArray retrieves an int array for the given key.

func (*Object) GetLong

func (o *Object) GetLong(key string) (int64, error)

GetLong retrieves a long (int64) value for the given key.

func (*Object) GetLongArray

func (o *Object) GetLongArray(key string) ([]int64, error)

GetLongArray retrieves a long array for the given key.

func (*Object) GetSFSArray

func (o *Object) GetSFSArray(key string) (*Array, error)

GetSFSArray retrieves a nested SFSArray for the given key.

func (*Object) GetSFSObject

func (o *Object) GetSFSObject(key string) (*Object, error)

GetSFSObject retrieves a nested SFSObject for the given key.

func (*Object) GetShort

func (o *Object) GetShort(key string) (int16, error)

GetShort retrieves a short (int16) value for the given key.

func (*Object) GetShortArray

func (o *Object) GetShortArray(key string) ([]int16, error)

GetShortArray retrieves a short array for the given key.

func (*Object) GetText

func (o *Object) GetText(key string) (string, error)

GetText retrieves a text string value for the given key.

func (*Object) GetUtfString

func (o *Object) GetUtfString(key string) (string, error)

GetUtfString retrieves a UTF-8 string value for the given key.

func (*Object) GetUtfStringArray

func (o *Object) GetUtfStringArray(key string) ([]string, error)

GetUtfStringArray retrieves a string array for the given key.

func (*Object) IsNull

func (o *Object) IsNull(key string) bool

IsNull returns true if the key exists and its value is TypeNull.

func (*Object) Keys

func (o *Object) Keys() []string

Keys returns the keys in insertion order.

func (*Object) Len

func (o *Object) Len() int

Len returns the number of entries.

func (*Object) Put

func (o *Object) Put(key string, v Value)

Put inserts or replaces a value for the given key.

func (*Object) PutBool

func (o *Object) PutBool(key string, v bool)

PutBool inserts a boolean value for the given key.

func (*Object) PutBoolArray

func (o *Object) PutBoolArray(key string, v []bool)

PutBoolArray inserts a boolean array for the given key.

func (*Object) PutByte

func (o *Object) PutByte(key string, v int8)

PutByte inserts a byte (int8) value for the given key.

func (*Object) PutByteArray

func (o *Object) PutByteArray(key string, v []byte)

PutByteArray inserts a byte array for the given key.

func (*Object) PutDouble

func (o *Object) PutDouble(key string, v float64)

PutDouble inserts a double (float64) value for the given key.

func (*Object) PutDoubleArray

func (o *Object) PutDoubleArray(key string, v []float64)

PutDoubleArray inserts a double array for the given key.

func (*Object) PutFloat

func (o *Object) PutFloat(key string, v float32)

PutFloat inserts a float (float32) value for the given key.

func (*Object) PutFloatArray

func (o *Object) PutFloatArray(key string, v []float32)

PutFloatArray inserts a float array for the given key.

func (*Object) PutInt

func (o *Object) PutInt(key string, v int32)

PutInt inserts an int (int32) value for the given key.

func (*Object) PutIntArray

func (o *Object) PutIntArray(key string, v []int32)

PutIntArray inserts an int array for the given key.

func (*Object) PutLong

func (o *Object) PutLong(key string, v int64)

PutLong inserts a long (int64) value for the given key.

func (*Object) PutLongArray

func (o *Object) PutLongArray(key string, v []int64)

PutLongArray inserts a long array for the given key.

func (*Object) PutNull

func (o *Object) PutNull(key string)

PutNull inserts a null value for the given key.

func (*Object) PutSFSArray

func (o *Object) PutSFSArray(key string, v *Array)

PutSFSArray inserts a nested SFSArray for the given key.

func (*Object) PutSFSObject

func (o *Object) PutSFSObject(key string, v *Object)

PutSFSObject inserts a nested SFSObject for the given key.

func (*Object) PutShort

func (o *Object) PutShort(key string, v int16)

PutShort inserts a short (int16) value for the given key.

func (*Object) PutShortArray

func (o *Object) PutShortArray(key string, v []int16)

PutShortArray inserts a short array for the given key.

func (*Object) PutText

func (o *Object) PutText(key string, v string)

PutText inserts a text string value for the given key.

func (*Object) PutUtfString

func (o *Object) PutUtfString(key string, v string)

PutUtfString inserts a UTF-8 string value for the given key.

func (*Object) PutUtfStringArray

func (o *Object) PutUtfStringArray(key string, v []string)

PutUtfStringArray inserts a string array for the given key.

func (*Object) RemoveElement

func (o *Object) RemoveElement(key string)

RemoveElement removes the entry with the given key from the object. If the key does not exist, it does nothing.

func (*Object) Size

func (o *Object) Size() int

Size returns the number of entries in the object.

type TypeID

type TypeID byte

TypeID identifies the data type of a value in the SFS binary protocol.

const (
	TypeNull        TypeID = 0
	TypeBool        TypeID = 1
	TypeByte        TypeID = 2
	TypeShort       TypeID = 3
	TypeInt         TypeID = 4
	TypeLong        TypeID = 5
	TypeFloat       TypeID = 6
	TypeDouble      TypeID = 7
	TypeUTFString   TypeID = 8
	TypeBoolArray   TypeID = 9
	TypeByteArray   TypeID = 10
	TypeShortArray  TypeID = 11
	TypeIntArray    TypeID = 12
	TypeLongArray   TypeID = 13
	TypeFloatArray  TypeID = 14
	TypeDoubleArray TypeID = 15
	TypeStringArray TypeID = 16
	TypeSFSArray    TypeID = 17
	TypeSFSObject   TypeID = 18
	TypeText        TypeID = 19
)

func (TypeID) String

func (t TypeID) String() string

String returns the human-readable name of a type ID.

type Value

type Value struct {
	Type TypeID
	Data interface{} // Concrete type depends on Type; see package docs.
}

Value holds a typed value from an SFS packet.

Directories

Path Synopsis
cmd
sfs command
examples
basic_usage command

Jump to

Keyboard shortcuts

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