Callwire v2
A high-performance, bidirectional RPC framework for Go, Python, and Rust over TCP with MessagePack framing. Both sides of any connection can act as a client and server simultaneously.
[!IMPORTANT] Language-Agnostic Design: Callwire is designed around a simple, clean, and fully-specified wire protocol. You can implement clients and servers in any language by following the SPEC.md.
Features
- Multi-Language: First-class support for Go, Python, and Rust.
- Bidirectional: Connection-symmetric. Clients can serve endpoints and servers can invoke client functions over the same socket.
- TLS & mTLS: Secure transport with server authentication and optional Mutual TLS (mTLS).
- Service Discovery: Built-in lightweight registry server and auto-refreshing client
DiscoverPool. - Dynamic Reconnections: Auto-reconnect with exponential backoff on connection drops.
- Batch API: Concurrent RPC multiplexing on a single connection.
Quick Start
Go
import "github.com/emaad/callwire"
// 1. Export local function
callwire.Export("add", func(a, b int) int )
// 2. Call remote function using client
client, _ := callwire.Connect("localhost:9090")
addFunc := callwire.RefWithClient[int](client, "add")
result, _ := addFunc(10, 20) // 30
Python
# 1. Export local function
return +
# 2. Call remote function
=
= # 30
Rust
use ;
// 1. Export local function
register_unary;
// 2. Call remote function
let client = connect.await.unwrap;
let result: i64 = client.import.await.unwrap; // 30
TLS & Mutual TLS (mTLS)
Callwire v2 supports standard TLS and client certificate verification (mTLS).
Go TLS Server & Client
// Server
cfg := callwire.TLSConfig
callwire.ServeWithTLS("0.0.0.0:9090", cfg)
// Client
clientCfg := callwire.TLSConfig
client, _ := callwire.ConnectWithReconnectTLS("localhost:9090", clientCfg)
Python TLS Client
=
Rust TLS Client
let client_cfg = TlsConfig ;
let client = client_cfg.connect.await.unwrap;
Service Discovery
Callwire features a built-in Service Discovery registry (itself powered by Callwire RPC).
Go Registry & Worker Setup
// 1. Start the registry server
callwire.ServeRegistry("127.0.0.1:29090")
// 2. Start a worker and register it
callwire.Export("say_hello", func(name string) string )
go callwire.Serve("127.0.0.1:29091")
callwire.RegisterWith("127.0.0.1:29090", "hello-service", "127.0.0.1:29091")
// 3. Resolve and call using DiscoverPool
pool, _ := callwire.NewDiscoverPool("127.0.0.1:29090", "hello-service")
sayHello := callwire.DiscoverRef[string](pool, "say_hello")
reply, _ := sayHello("World") // "Hello World"
Python DiscoverPool
=
=
=
Rust DiscoverPool
use DiscoverPool;
let pool = new.await.unwrap;
let client = pool.get.unwrap;
let res: String = client.import.await.unwrap;
Configuration
| Env Var | Default | Description |
|---|---|---|
CALLWIRE_HOST |
localhost |
Default hostname for auto-serving & clients |
CALLWIRE_PORT |
9090 |
Default port for auto-serving & clients |
CALLWIRE_AUTO |
1 |
Set to 0 to disable automatic server launching on Export |
Developer Testing
Run the full cross-language integration and unit suites:
# Go tests
&&
# Python tests
&&
# Rust tests
&&