Metadata-Version: 2.4
Name: callwire
Version: 2.0.0
Summary: High-performance bidirectional RPC over TCP with MessagePack framing — Go, Python, Rust interop
Project-URL: Repository, https://github.com/emaad/callwire
Project-URL: Documentation, https://github.com/emaad/callwire/blob/main/SPEC.md
Project-URL: Bug Tracker, https://github.com/emaad/callwire/issues
Author: Emaad Akhter
License: MIT License
        
        Copyright (c) 2026 Emaad Akhter
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
Keywords: grpc-alternative,ipc,msgpack,rpc,tcp,tls
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: System :: Networking
Requires-Python: >=3.10
Requires-Dist: msgpack>=1.0
Description-Content-Type: text/markdown

# 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](file:///Users/emaad/Developer/callwire/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

```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

```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

```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

```go
// 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

```python
client = Client()
client.connect("localhost", 9090, tls={
    "cafile": "ca.pem",
    "certfile": "client.pem", # for mTLS
    "keyfile": "client.key"    # for mTLS
})
```

### Rust TLS Client

```rust
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

```go
// 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

```python
from callwire import DiscoverPool

pool = DiscoverPool("127.0.0.1:29090", "hello-service")
client = pool.get()
result = client.call("say_hello", ["World"])
```

### Rust DiscoverPool

```rust
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:

```bash
# 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
```
