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.
Architecture
React Native bridges to the C library through platform-specific native modules:Android native module
1. Place native libraries
android/app/src/main/jniLibs/
arm64-v8a/liboxaccel.so
arm64-v8a/liboxaccel_jni.so
armeabi-v7a/liboxaccel.so
armeabi-v7a/liboxaccel_jni.so
2. Create the module
// android/app/src/main/java/sh/oxd/accel/OxAccelModule.java
package sh.oxd.accel;
import com.facebook.react.bridge.*;
import java.nio.ByteBuffer;
import android.util.Base64;
public class OxAccelModule extends ReactContextBaseJavaModule {
static { System.loadLibrary("oxaccel_jni"); }
private static native long nCreate(String apiKey, String relayHost, int port,
boolean fec, boolean compression, boolean multipath);
private static native int nConnect(long ctx);
private static native int nSend(long ctx, ByteBuffer data, int len);
private static native int nRecv(long ctx, ByteBuffer buf, int bufLen);
private static native long[] nStats(long ctx);
private static native void nDestroy(long ctx);
private static native String nVersion();
private long ctx = 0;
OxAccelModule(ReactApplicationContext context) { super(context); }
@Override public String getName() { return "OxAccel"; }
@ReactMethod
public void create(ReadableMap config, Promise promise) {
ctx = nCreate(
config.getString("apiKey"),
config.getString("relayHost"),
config.getInt("relayPort"),
config.getBoolean("enableFec"),
config.getBoolean("enableCompression"),
config.getBoolean("enableMultipath")
);
promise.resolve(ctx != 0);
}
@ReactMethod
public void connect(Promise promise) {
int err = nConnect(ctx);
if (err == 0) promise.resolve(null);
else promise.reject("ACCEL_ERR", "Connect failed: " + err);
}
@ReactMethod
public void send(String base64Data, Promise promise) {
byte[] data = Base64.decode(base64Data, Base64.NO_WRAP);
ByteBuffer buf = ByteBuffer.allocateDirect(data.length);
buf.put(data).flip();
int err = nSend(ctx, buf, data.length);
if (err == 0) promise.resolve(null);
else promise.reject("ACCEL_ERR", "Send failed: " + err);
}
@ReactMethod
public void recv(Promise promise) {
ByteBuffer buf = ByteBuffer.allocateDirect(65536);
int received = nRecv(ctx, buf, 65536);
if (received >= 0) {
byte[] data = new byte[received];
buf.get(data, 0, received);
promise.resolve(Base64.encodeToString(data, Base64.NO_WRAP));
} else {
promise.reject("ACCEL_ERR", "Recv failed");
}
}
@ReactMethod
public void destroy(Promise promise) {
if (ctx != 0) { nDestroy(ctx); ctx = 0; }
promise.resolve(null);
}
}
iOS native module
1. Add bridging header
// ios/OxAccel-Bridging-Header.h
#include "oxaccel.h"
2. Create the module
// ios/OxAccelModule.swift
import Foundation
@objc(OxAccelModule)
class OxAccelModule: NSObject {
private var ctx: OpaquePointer?
@objc func create(_ config: NSDictionary, resolve: RCTPromiseResolveBlock,
reject: RCTPromiseRejectBlock) {
var cfg = OxAccelConfig(
api_key: strdup(config["apiKey"] as? String ?? ""),
relay_host: strdup(config["relayHost"] as? String ?? "relay.oxd.sh"),
relay_port: UInt16(config["relayPort"] as? Int ?? 51820),
enable_fec: config["enableFec"] as? Bool ?? true,
enable_compression: config["enableCompression"] as? Bool ?? false,
enable_multipath: config["enableMultipath"] as? Bool ?? true
)
ctx = ox_accel_create(&cfg)
free(UnsafeMutablePointer(mutating: cfg.api_key))
free(UnsafeMutablePointer(mutating: cfg.relay_host))
resolve(ctx != nil)
}
@objc func connect(_ resolve: RCTPromiseResolveBlock,
reject: RCTPromiseRejectBlock) {
guard let ctx = ctx else { reject("ERR", "Not created", nil); return }
let err = ox_accel_connect(ctx)
if err == Ok { resolve(nil) }
else { reject("ERR", "Connect failed: \(err.rawValue)", nil) }
}
@objc func send(_ base64: String, resolve: RCTPromiseResolveBlock,
reject: RCTPromiseRejectBlock) {
guard let ctx = ctx, let data = Data(base64Encoded: base64) else {
reject("ERR", "Invalid", nil); return
}
let err = data.withUnsafeBytes { buf in
ox_accel_send(ctx, buf.baseAddress?.assumingMemoryBound(to: UInt8.self), buf.count)
}
if err == Ok { resolve(nil) }
else { reject("ERR", "Send failed: \(err.rawValue)", nil) }
}
@objc func destroy(_ resolve: RCTPromiseResolveBlock,
reject: RCTPromiseRejectBlock) {
if let ctx = ctx { ox_accel_destroy(ctx); self.ctx = nil }
resolve(nil)
}
}
TypeScript usage
import { NativeModules } from 'react-native';
const { OxAccel } = NativeModules;
await OxAccel.create({
apiKey: 'your-api-key',
relayHost: 'relay.oxd.sh',
relayPort: 51820,
enableFec: true,
enableCompression: false,
enableMultipath: true,
});
await OxAccel.connect();
// Send (base64-encoded data over the bridge)
const data = btoa('hello world');
await OxAccel.send(data);
// Cleanup
await OxAccel.destroy();
React Native’s JS bridge requires serialized data. Binary payloads are base64-encoded across the bridge, then decoded on the native side before passing to
ox_accel_send. For high-frequency sends, consider using TurboModules with JSI for direct memory access.