High-performance bidirectional RPC over TCP with MessagePack framing — Go, Python, Rust interop
Project description
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 { return a + b })
// 2. Call remote function using client
client, _ := callwire.Connect("localhost:9090")
addFunc := callwire.RefWithClient[int](client, "add")
result, _ := addFunc(10, 20) // 30
Python
from callwire import export, serve, Client
# 1. Export local function
@export
def add(a, b):
return a + b
# 2. Call remote function
client = Client()
client.connect("localhost", 9090)
result = client.call("add", [10, 20]) # 30
Rust
use callwire::{Client, register_unary, serve_on};
// 1. Export local function
register_unary("add", |(a, b): (i64, i64)| -> Result<i64, String> {
Ok(a + b)
});
// 2. Call remote function
let client = Client::connect("127.0.0.1:9090").await.unwrap();
let result: i64 = client.import("add", &(10i64, 20i64)).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{CertPem: cert, KeyPem: key}
callwire.ServeWithTLS("0.0.0.0:9090", cfg)
// Client
clientCfg := callwire.TLSConfig{CAPem: caCert}
client, _ := callwire.ConnectWithReconnectTLS("localhost:9090", clientCfg)
Python TLS Client
client = Client()
client.connect("localhost", 9090, tls={
"cafile": "ca.pem",
"certfile": "client.pem", # for mTLS
"keyfile": "client.key" # for mTLS
})
Rust TLS Client
let client_cfg = callwire::TlsConfig {
cert_pem: vec![],
key_pem: vec![],
ca_pem: Some(ca_pem), // Server CA cert
};
let client = client_cfg.connect("127.0.0.1:9090").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 { return "Hello " + name })
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
from callwire import DiscoverPool
pool = DiscoverPool("127.0.0.1:29090", "hello-service")
client = pool.get()
result = client.call("say_hello", ["World"])
Rust DiscoverPool
use callwire::DiscoverPool;
let pool = DiscoverPool::new("127.0.0.1:29090", "hello-service").await.unwrap();
let client = pool.get().unwrap();
let res: String = client.import("say_hello", &("World".to_string(),)).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
cd go/callwire && go test -v ./...
# Python tests
cd python && .venv/bin/python3 -m unittest discover -s . -p "test_*.py"
# Rust tests
cd rust && cargo test -- --nocapture
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file callwire-2.0.0.tar.gz.
File metadata
- Download URL: callwire-2.0.0.tar.gz
- Upload date:
- Size: 9.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
38aa261a7dfcbe12fb3de1a3722625c9fd8723d823a565917469701324140936
|
|
| MD5 |
b15f6d9412c3a0efdbd911014c023be0
|
|
| BLAKE2b-256 |
496f2aaf4a0d1358be1efcf4f649f190fffe00edaf6b6607f9a3a5865ecb77be
|
File details
Details for the file callwire-2.0.0-py3-none-any.whl.
File metadata
- Download URL: callwire-2.0.0-py3-none-any.whl
- Upload date:
- Size: 11.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4c01fc699597ff2ce60bcfe719a36844ef626e9c2ee8aa2961ca2abc2cb45b8d
|
|
| MD5 |
34e676b6e02a35862c75469e8f232537
|
|
| BLAKE2b-256 |
257cd47ae54a95e4aeccfd81f95fe7cf6ab057cd8b6a9278796b3283ce38036c
|