Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.oxd.sh/llms.txt

Use this file to discover all available pages before exploring further.

Setup

Place liboxaccel.so (or .dylib / .dll) and oxaccel.h in your project directory.

cgo bindings

package accel

/*
#cgo LDFLAGS: -L${SRCDIR} -loxaccel
#cgo linux LDFLAGS: -lpthread -ldl -lm
#cgo darwin LDFLAGS: -framework Security -framework CoreFoundation
#include "oxaccel.h"
#include <stdlib.h>
*/
import "C"

import (
	"errors"
	"unsafe"
)

type Context struct {
	ctx *C.OxAccel
}

type Config struct {
	APIKey          string
	RelayHost       string
	RelayPort       uint16
	EnableFEC       bool
	EnableCompress  bool
	EnableMultipath bool
}

type Stats struct {
	PacketsSent uint64
	PacketsRecv uint64
	BytesSent   uint64
	BytesRecv   uint64
}

func New(cfg Config) (*Context, error) {
	apiKey := C.CString(cfg.APIKey)
	defer C.free(unsafe.Pointer(apiKey))

	host := C.CString(cfg.RelayHost)
	defer C.free(unsafe.Pointer(host))

	ccfg := C.OxAccelConfig{
		api_key:            apiKey,
		relay_host:         host,
		relay_port:         C.uint16_t(cfg.RelayPort),
		enable_fec:         C.bool(cfg.EnableFEC),
		enable_compression: C.bool(cfg.EnableCompress),
		enable_multipath:   C.bool(cfg.EnableMultipath),
	}

	ctx := C.ox_accel_create(&ccfg)
	if ctx == nil {
		return nil, errors.New("ox_accel_create failed")
	}
	return &Context{ctx: ctx}, nil
}

func (c *Context) Connect() error {
	err := C.ox_accel_connect(c.ctx)
	if err != C.OxAccelError_Ok {
		return errors.New("ox_accel_connect failed")
	}
	return nil
}

func (c *Context) Send(data []byte) error {
	err := C.ox_accel_send(c.ctx, (*C.uint8_t)(&data[0]), C.size_t(len(data)))
	if err != C.OxAccelError_Ok {
		return errors.New("ox_accel_send failed")
	}
	return nil
}

func (c *Context) Recv(buf []byte) (int, error) {
	var outLen C.size_t
	err := C.ox_accel_recv(c.ctx, (*C.uint8_t)(&buf[0]), C.size_t(len(buf)), &outLen)
	if err != C.OxAccelError_Ok {
		return 0, errors.New("ox_accel_recv failed")
	}
	return int(outLen), nil
}

func (c *Context) Stats() Stats {
	var s C.AccelStats
	C.ox_accel_stats(c.ctx, &s)
	return Stats{
		PacketsSent: uint64(s.packets_sent),
		PacketsRecv: uint64(s.packets_recv),
		BytesSent:   uint64(s.bytes_sent),
		BytesRecv:   uint64(s.bytes_recv),
	}
}

func (c *Context) Close() {
	if c.ctx != nil {
		C.ox_accel_destroy(c.ctx)
		c.ctx = nil
	}
}

func Version() string {
	return C.GoString(C.ox_accel_version())
}

Usage

package main

import (
	"fmt"
	"log"
	"myapp/accel"
)

func main() {
	ctx, err := accel.New(accel.Config{
		APIKey:     "your-api-key",
		RelayHost:  "relay.oxd.sh",
		RelayPort:  51820,
		EnableFEC:  true,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer ctx.Close()

	if err := ctx.Connect(); err != nil {
		log.Fatal(err)
	}

	// Send
	ctx.Send([]byte("hello"))

	// Receive
	buf := make([]byte, 65536)
	n, _ := ctx.Recv(buf)
	fmt.Printf("Received %d bytes\n", n)

	// Stats
	s := ctx.Stats()
	fmt.Printf("TX: %d packets, RX: %d packets\n",
		s.PacketsSent, s.PacketsRecv)
}
cgo has overhead per call (~100ns). For high-frequency send/recv, batch multiple messages or use the C API directly from a goroutine pinned with runtime.LockOSThread().