chore: rename quicproquo → quicprochat in docs, Docker, CI, and packaging
Rename all project references from quicproquo/qpq to quicprochat/qpc across documentation, Docker configuration, CI workflows, packaging scripts, operational configs, and build tooling. - Docker: crate paths, binary names, user/group, data dirs, env vars - CI: workflow crate references, binary names, artifact names - Docs: all markdown files under docs/, SDK READMEs, book.toml - Packaging: OpenWrt Makefile, init script, UCI config (file renames) - Scripts: justfile, dev-shell, screenshot, cross-compile, ai_team - Operations: Prometheus config, alert rules, Grafana dashboard - Config: .env.example (QPQ_* → QPC_*), CODEOWNERS paths - Top-level: README, CONTRIBUTING, ROADMAP, CLAUDE.md
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
# quicproquo Go SDK
|
||||
# quicprochat Go SDK
|
||||
|
||||
Go client library for the [quicproquo](https://github.com/nicholasgasior/quicproquo) E2E encrypted messenger.
|
||||
Go client library for the [quicprochat](https://github.com/nicholasgasior/quicprochat) E2E encrypted messenger.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Go 1.21+
|
||||
- A running quicproquo server
|
||||
- A running quicprochat server
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
go get quicproquo.dev/sdk/go
|
||||
go get quicprochat.dev/sdk/go
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
@@ -22,14 +22,14 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"quicproquo.dev/sdk/go/qpq"
|
||||
"quicprochat.dev/sdk/go/qpc"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Connect to a local server (dev mode)
|
||||
client, err := qpq.Connect(ctx, qpq.Options{
|
||||
client, err := qpc.Connect(ctx, qpc.Options{
|
||||
Addr: "127.0.0.1:5001",
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
@@ -68,7 +68,7 @@ func main() {
|
||||
|
||||
| Method | Description |
|
||||
|---|---|
|
||||
| `qpq.Connect(ctx, opts)` | Connect to a server, returns `*Client` |
|
||||
| `qpc.Connect(ctx, opts)` | Connect to a server, returns `*Client` |
|
||||
| `client.Close()` | Disconnect |
|
||||
|
||||
### Authentication
|
||||
@@ -106,7 +106,7 @@ For testing without OPAQUE, use `SetSessionToken` with a token obtained by other
|
||||
|
||||
- `proto/node/` -- Generated Cap'n Proto Go types from `schemas/node.capnp`
|
||||
- `transport/` -- QUIC + TLS 1.3 transport and Cap'n Proto RPC framing
|
||||
- `qpq/` -- High-level client API (auth, messaging, channels)
|
||||
- `qpc/` -- High-level client API (auth, messaging, channels)
|
||||
- `cmd/example/` -- Example usage
|
||||
|
||||
## Regenerating Proto Types
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Command example demonstrates basic usage of the quicproquo Go SDK.
|
||||
// Command example demonstrates basic usage of the quicprochat Go SDK.
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"quicproquo.dev/sdk/go/qpq"
|
||||
"quicprochat.dev/sdk/go/qpq"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module quicproquo.dev/sdk/go
|
||||
module quicprochat.dev/sdk/go
|
||||
|
||||
go 1.25.7
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# node.capnp — Go-annotated copy of the quicproquo node schema.
|
||||
# node.capnp — Go-annotated copy of the quicprochat node schema.
|
||||
# This adds Go package annotations needed by capnpc-go.
|
||||
@0xd5ca5648a9cc1c28;
|
||||
|
||||
using Go = import "/go.capnp";
|
||||
$Go.package("node");
|
||||
$Go.import("quicproquo.dev/sdk/go/proto/node");
|
||||
$Go.import("quicprochat.dev/sdk/go/proto/node");
|
||||
|
||||
interface NodeService {
|
||||
uploadKeyPackage @0 (identityKey :Data, package :Data, auth :Auth) -> (fingerprint :Data);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Package qpq provides the high-level Go API for interacting with a quicproquo server.
|
||||
// Package qpq provides the high-level Go API for interacting with a quicprochat server.
|
||||
//
|
||||
// It wraps the generated Cap'n Proto types and transport layer into an
|
||||
// ergonomic client that handles authentication, key management, and messaging.
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"quicproquo.dev/sdk/go/proto/node"
|
||||
"quicproquo.dev/sdk/go/transport"
|
||||
"quicprochat.dev/sdk/go/proto/node"
|
||||
"quicprochat.dev/sdk/go/transport"
|
||||
)
|
||||
|
||||
// Options configures the connection to a quicproquo server.
|
||||
// Options configures the connection to a quicprochat server.
|
||||
type Options struct {
|
||||
// Addr is the host:port of the server (e.g. "127.0.0.1:5001").
|
||||
Addr string
|
||||
@@ -30,7 +30,7 @@ type Message struct {
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// Client is the high-level quicproquo client.
|
||||
// Client is the high-level quicprochat client.
|
||||
type Client struct {
|
||||
conn *transport.Connection
|
||||
token []byte // session token from OPAQUE login
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Package transport provides the low-level QUIC+TLS connection to a quicproquo server
|
||||
// Package transport provides the low-level QUIC+TLS connection to a quicprochat server
|
||||
// and bootstraps the Cap'n Proto RPC client over a single bidirectional QUIC stream.
|
||||
package transport
|
||||
|
||||
@@ -14,10 +14,10 @@ import (
|
||||
"capnproto.org/go/capnp/v3/rpc"
|
||||
"github.com/quic-go/quic-go"
|
||||
|
||||
"quicproquo.dev/sdk/go/proto/node"
|
||||
"quicprochat.dev/sdk/go/proto/node"
|
||||
)
|
||||
|
||||
// ConnectOptions configures the connection to a quicproquo server.
|
||||
// ConnectOptions configures the connection to a quicprochat server.
|
||||
type ConnectOptions struct {
|
||||
// Addr is the host:port of the server (e.g. "127.0.0.1:5001").
|
||||
Addr string
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
# QuicProQuo Java SDK
|
||||
# QuicProChat Java SDK
|
||||
|
||||
Java wrapper over `libquicproquo_ffi` via JNI for JVM and Android.
|
||||
Java wrapper over `libquicprochat_ffi` via JNI for JVM and Android.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- JDK 17+
|
||||
- `libquicproquo_ffi` built for the target platform
|
||||
- `libquicprochat_ffi` built for the target platform
|
||||
- JNI bridge compiled (shared with Kotlin SDK: `../kotlin/jni/`)
|
||||
|
||||
## Building
|
||||
|
||||
```sh
|
||||
# Build Rust FFI library
|
||||
cargo build --release -p quicproquo-ffi
|
||||
cargo build --release -p quicprochat-ffi
|
||||
|
||||
# Build Java SDK
|
||||
./gradlew build
|
||||
@@ -21,7 +21,7 @@ cargo build --release -p quicproquo-ffi
|
||||
## Usage
|
||||
|
||||
```java
|
||||
import dev.quicproquo.QpqClient;
|
||||
import dev.quicprochat.QpqClient;
|
||||
|
||||
try (QpqClient client = new QpqClient("127.0.0.1:5001", "ca.pem")) {
|
||||
client.login("alice", "secret");
|
||||
@@ -45,6 +45,6 @@ try (QpqClient client = new QpqClient("127.0.0.1:5001", "ca.pem")) {
|
||||
|
||||
## Structure
|
||||
|
||||
- `src/main/java/dev/quicproquo/QpqClient.java` -- High-level client
|
||||
- `src/main/java/dev/quicproquo/NativeBridge.java` -- JNI declarations
|
||||
- `src/main/java/dev/quicprochat/QpqClient.java` -- High-level client
|
||||
- `src/main/java/dev/quicprochat/NativeBridge.java` -- JNI declarations
|
||||
- JNI C bridge shared with Kotlin SDK at `../kotlin/jni/`
|
||||
|
||||
@@ -2,7 +2,7 @@ plugins {
|
||||
java
|
||||
}
|
||||
|
||||
group = "dev.quicproquo"
|
||||
group = "dev.quicprochat"
|
||||
version = "0.1.0"
|
||||
|
||||
java {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package dev.quicproquo;
|
||||
package dev.quicprochat;
|
||||
|
||||
/**
|
||||
* JNI bridge to libquicproquo_ffi native library.
|
||||
* JNI bridge to libquicprochat_ffi native library.
|
||||
*
|
||||
* <p>Load the library with:
|
||||
* <pre>{@code
|
||||
* System.loadLibrary("quicproquo_ffi");
|
||||
* System.loadLibrary("quicprochat_ffi");
|
||||
* }</pre>
|
||||
*/
|
||||
final class NativeBridge {
|
||||
@@ -16,7 +16,7 @@ final class NativeBridge {
|
||||
static final int QPQ_NOT_CONNECTED = 4;
|
||||
|
||||
static {
|
||||
System.loadLibrary("quicproquo_ffi");
|
||||
System.loadLibrary("quicprochat_ffi");
|
||||
}
|
||||
|
||||
static native long nativeConnect(String server, String caCert, String serverName);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package dev.quicproquo;
|
||||
package dev.quicprochat;
|
||||
|
||||
/** OPAQUE authentication failed (bad credentials). */
|
||||
public class QpqAuthException extends QpqException {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package dev.quicproquo;
|
||||
package dev.quicprochat;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
@@ -7,9 +7,9 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* High-level quicproquo client for JVM.
|
||||
* High-level quicprochat client for JVM.
|
||||
*
|
||||
* <p>Wraps {@code libquicproquo_ffi} via JNI.
|
||||
* <p>Wraps {@code libquicprochat_ffi} via JNI.
|
||||
*
|
||||
* <pre>{@code
|
||||
* try (QpqClient client = new QpqClient("127.0.0.1:5001", "ca.pem")) {
|
||||
@@ -26,7 +26,7 @@ public final class QpqClient implements AutoCloseable {
|
||||
new TypeToken<List<String>>() {}.getType();
|
||||
|
||||
/**
|
||||
* Connect to a quicproquo server.
|
||||
* Connect to a quicprochat server.
|
||||
*
|
||||
* @param server server address as {@code host:port}
|
||||
* @param caCertPath path to PEM-encoded CA certificate
|
||||
@@ -36,7 +36,7 @@ public final class QpqClient implements AutoCloseable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a quicproquo server with explicit TLS server name.
|
||||
* Connect to a quicprochat server with explicit TLS server name.
|
||||
*
|
||||
* @param server server address as {@code host:port}
|
||||
* @param caCertPath path to PEM-encoded CA certificate
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.quicproquo;
|
||||
package dev.quicprochat;
|
||||
|
||||
/** Base exception for quicproquo SDK errors. */
|
||||
/** Base exception for quicprochat SDK errors. */
|
||||
public class QpqException extends RuntimeException {
|
||||
public QpqException(String message) { super(message); }
|
||||
public QpqException(String message, Throwable cause) { super(message, cause); }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package dev.quicproquo;
|
||||
package dev.quicprochat;
|
||||
|
||||
/** Operation timed out. */
|
||||
public class QpqTimeoutException extends QpqException {
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
# QuicProQuo Kotlin SDK
|
||||
# QuicProChat Kotlin SDK
|
||||
|
||||
Kotlin/JVM wrapper over `libquicproquo_ffi` via JNI for Android and JVM platforms.
|
||||
Kotlin/JVM wrapper over `libquicprochat_ffi` via JNI for Android and JVM platforms.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Kotlin 1.9+ / JDK 17+
|
||||
- `libquicproquo_ffi` built for the target architecture
|
||||
- JNI bridge compiled (`jni/dev_quicproquo_NativeBridge.c`)
|
||||
- `libquicprochat_ffi` built for the target architecture
|
||||
- JNI bridge compiled (`jni/dev_quicprochat_NativeBridge.c`)
|
||||
|
||||
## Building the Native Library
|
||||
|
||||
```sh
|
||||
# Linux (JVM)
|
||||
cargo build --release -p quicproquo-ffi
|
||||
cargo build --release -p quicprochat-ffi
|
||||
|
||||
# Android (aarch64)
|
||||
cargo build --release -p quicproquo-ffi --target aarch64-linux-android
|
||||
cargo build --release -p quicprochat-ffi --target aarch64-linux-android
|
||||
|
||||
# Android (armv7)
|
||||
cargo build --release -p quicproquo-ffi --target armv7-linux-androideabi
|
||||
cargo build --release -p quicprochat-ffi --target armv7-linux-androideabi
|
||||
```
|
||||
|
||||
### Compiling the JNI Bridge
|
||||
|
||||
```sh
|
||||
cd jni
|
||||
gcc -shared -fPIC -o libquicproquo_jni.so \
|
||||
gcc -shared -fPIC -o libquicprochat_jni.so \
|
||||
-I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" \
|
||||
dev_quicproquo_NativeBridge.c \
|
||||
-L ../../../../target/release -lquicproquo_ffi
|
||||
dev_quicprochat_NativeBridge.c \
|
||||
-L ../../../../target/release -lquicprochat_ffi
|
||||
```
|
||||
|
||||
## Installation
|
||||
@@ -37,7 +37,7 @@ gcc -shared -fPIC -o libquicproquo_jni.so \
|
||||
|
||||
```kotlin
|
||||
dependencies {
|
||||
implementation(files("libs/quicproquo-0.1.0.jar"))
|
||||
implementation(files("libs/quicprochat-0.1.0.jar"))
|
||||
}
|
||||
```
|
||||
|
||||
@@ -46,7 +46,7 @@ Or include as a local project module.
|
||||
## Usage
|
||||
|
||||
```kotlin
|
||||
import dev.quicproquo.QpqClient
|
||||
import dev.quicprochat.QpqClient
|
||||
|
||||
val client = QpqClient("127.0.0.1:5001", caCertPath = "ca.pem")
|
||||
|
||||
@@ -86,16 +86,16 @@ try {
|
||||
|
||||
## Structure
|
||||
|
||||
- `src/main/kotlin/dev/quicproquo/QpqClient.kt` -- High-level client
|
||||
- `src/main/kotlin/dev/quicproquo/NativeBridge.kt` -- JNI declarations
|
||||
- `src/main/kotlin/dev/quicproquo/QpqError.kt` -- Exception types
|
||||
- `jni/dev_quicproquo_NativeBridge.c` -- JNI C bridge to FFI
|
||||
- `src/main/kotlin/dev/quicprochat/QpqClient.kt` -- High-level client
|
||||
- `src/main/kotlin/dev/quicprochat/NativeBridge.kt` -- JNI declarations
|
||||
- `src/main/kotlin/dev/quicprochat/QpqError.kt` -- Exception types
|
||||
- `jni/dev_quicprochat_NativeBridge.c` -- JNI C bridge to FFI
|
||||
|
||||
## Android Integration
|
||||
|
||||
1. Add the native libraries to `src/main/jniLibs/<abi>/`:
|
||||
- `arm64-v8a/libquicproquo_ffi.so`
|
||||
- `armeabi-v7a/libquicproquo_ffi.so`
|
||||
- `arm64-v8a/libquicprochat_ffi.so`
|
||||
- `armeabi-v7a/libquicprochat_ffi.so`
|
||||
2. Add the JNI bridge library alongside
|
||||
3. The `NativeBridge` class loads the library via `System.loadLibrary`
|
||||
|
||||
@@ -107,5 +107,5 @@ rustup target add aarch64-linux-android armv7-linux-androideabi
|
||||
|
||||
# Build with the NDK linker
|
||||
CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android21-clang \
|
||||
cargo build --release -p quicproquo-ffi --target aarch64-linux-android
|
||||
cargo build --release -p quicprochat-ffi --target aarch64-linux-android
|
||||
```
|
||||
|
||||
@@ -2,7 +2,7 @@ plugins {
|
||||
kotlin("jvm") version "1.9.22"
|
||||
}
|
||||
|
||||
group = "dev.quicproquo"
|
||||
group = "dev.quicprochat"
|
||||
version = "0.1.0"
|
||||
|
||||
repositories {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/**
|
||||
* JNI bridge between Kotlin/Java and libquicproquo_ffi.
|
||||
* JNI bridge between Kotlin/Java and libquicprochat_ffi.
|
||||
*
|
||||
* Compile with:
|
||||
* gcc -shared -fPIC -o libquicproquo_jni.so \
|
||||
* gcc -shared -fPIC -o libquicprochat_jni.so \
|
||||
* -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" \
|
||||
* dev_quicproquo_NativeBridge.c \
|
||||
* -L ../../../../target/release -lquicproquo_ffi
|
||||
* dev_quicprochat_NativeBridge.c \
|
||||
* -L ../../../../target/release -lquicprochat_ffi
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Forward declarations for libquicproquo_ffi functions. */
|
||||
/* Forward declarations for libquicprochat_ffi functions. */
|
||||
typedef struct QpqHandle QpqHandle;
|
||||
|
||||
extern QpqHandle* qpq_connect(const char* server, const char* ca_cert, const char* server_name);
|
||||
@@ -27,7 +27,7 @@ extern void qpq_free_string(char* ptr);
|
||||
/* --- JNI exports --- */
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_dev_quicproquo_NativeBridge_nativeConnect(
|
||||
Java_dev_quicprochat_NativeBridge_nativeConnect(
|
||||
JNIEnv* env, jclass cls,
|
||||
jstring server, jstring caCert, jstring serverName)
|
||||
{
|
||||
@@ -45,7 +45,7 @@ Java_dev_quicproquo_NativeBridge_nativeConnect(
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_dev_quicproquo_NativeBridge_nativeLogin(
|
||||
Java_dev_quicprochat_NativeBridge_nativeLogin(
|
||||
JNIEnv* env, jclass cls,
|
||||
jlong handle, jstring username, jstring password)
|
||||
{
|
||||
@@ -61,7 +61,7 @@ Java_dev_quicproquo_NativeBridge_nativeLogin(
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_dev_quicproquo_NativeBridge_nativeSend(
|
||||
Java_dev_quicprochat_NativeBridge_nativeSend(
|
||||
JNIEnv* env, jclass cls,
|
||||
jlong handle, jstring recipient, jbyteArray message)
|
||||
{
|
||||
@@ -78,7 +78,7 @@ Java_dev_quicproquo_NativeBridge_nativeSend(
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_dev_quicproquo_NativeBridge_nativeReceive(
|
||||
Java_dev_quicprochat_NativeBridge_nativeReceive(
|
||||
JNIEnv* env, jclass cls,
|
||||
jlong handle, jint timeoutMs)
|
||||
{
|
||||
@@ -97,7 +97,7 @@ Java_dev_quicproquo_NativeBridge_nativeReceive(
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_dev_quicproquo_NativeBridge_nativeDisconnect(
|
||||
Java_dev_quicprochat_NativeBridge_nativeDisconnect(
|
||||
JNIEnv* env, jclass cls, jlong handle)
|
||||
{
|
||||
QpqHandle* h = (QpqHandle*)(uintptr_t)handle;
|
||||
@@ -107,7 +107,7 @@ Java_dev_quicproquo_NativeBridge_nativeDisconnect(
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_dev_quicproquo_NativeBridge_nativeLastError(
|
||||
Java_dev_quicprochat_NativeBridge_nativeLastError(
|
||||
JNIEnv* env, jclass cls, jlong handle)
|
||||
{
|
||||
QpqHandle* h = (QpqHandle*)(uintptr_t)handle;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package dev.quicproquo
|
||||
package dev.quicprochat
|
||||
|
||||
/**
|
||||
* JNI bridge to libquicproquo_ffi native library.
|
||||
* JNI bridge to libquicprochat_ffi native library.
|
||||
*
|
||||
* Load the library with:
|
||||
* ```kotlin
|
||||
* System.loadLibrary("quicproquo_ffi")
|
||||
* System.loadLibrary("quicprochat_ffi")
|
||||
* ```
|
||||
*
|
||||
* Or set `java.library.path` to the directory containing the shared object.
|
||||
*/
|
||||
internal object NativeBridge {
|
||||
|
||||
/** Status codes (mirrors crates/quicproquo-ffi/src/lib.rs). */
|
||||
/** Status codes (mirrors crates/quicprochat-ffi/src/lib.rs). */
|
||||
const val QPQ_OK = 0
|
||||
const val QPQ_ERROR = 1
|
||||
const val QPQ_AUTH_FAILED = 2
|
||||
@@ -20,7 +20,7 @@ internal object NativeBridge {
|
||||
const val QPQ_NOT_CONNECTED = 4
|
||||
|
||||
init {
|
||||
System.loadLibrary("quicproquo_ffi")
|
||||
System.loadLibrary("quicprochat_ffi")
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package dev.quicproquo
|
||||
package dev.quicprochat
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import java.io.Closeable
|
||||
|
||||
/**
|
||||
* High-level quicproquo client for Android/JVM.
|
||||
* High-level quicprochat client for Android/JVM.
|
||||
*
|
||||
* Wraps `libquicproquo_ffi` via JNI to provide a Kotlin-native API.
|
||||
* Wraps `libquicprochat_ffi` via JNI to provide a Kotlin-native API.
|
||||
*
|
||||
* ```kotlin
|
||||
* val client = QpqClient("127.0.0.1:5001", caCertPath = "ca.pem")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.quicproquo
|
||||
package dev.quicprochat
|
||||
|
||||
/** Base exception for quicproquo SDK errors. */
|
||||
/** Base exception for quicprochat SDK errors. */
|
||||
open class QpqException(message: String, cause: Throwable? = null) :
|
||||
RuntimeException(message, cause)
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# quicproquo Python SDK
|
||||
# quicprochat Python SDK
|
||||
|
||||
Python client library for the [quicproquo](https://github.com/nicholasgasior/quicproquo) E2E encrypted messenger.
|
||||
Python client library for the [quicprochat](https://github.com/nicholasgasior/quicprochat) E2E encrypted messenger.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.10+
|
||||
- A running quicproquo server
|
||||
- A running quicprochat server
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
pip install quicproquo
|
||||
pip install quicprochat
|
||||
```
|
||||
|
||||
For development:
|
||||
@@ -27,7 +27,7 @@ Uses [aioquic](https://github.com/aiortc/aioquic) for native QUIC transport with
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from quicproquo import QpqClient, ConnectOptions
|
||||
from quicprochat import QpqClient, ConnectOptions
|
||||
|
||||
async def main():
|
||||
client = await QpqClient.connect(ConnectOptions(
|
||||
@@ -61,15 +61,15 @@ asyncio.run(main())
|
||||
|
||||
### 2. Rust FFI (synchronous)
|
||||
|
||||
Wraps `libquicproquo_ffi` via CFFI for full Rust crypto stack (MLS, hybrid KEM, OPAQUE) at native speed.
|
||||
Wraps `libquicprochat_ffi` via CFFI for full Rust crypto stack (MLS, hybrid KEM, OPAQUE) at native speed.
|
||||
|
||||
```sh
|
||||
# Build the FFI library first
|
||||
cargo build --release -p quicproquo-ffi
|
||||
cargo build --release -p quicprochat-ffi
|
||||
```
|
||||
|
||||
```python
|
||||
from quicproquo import QpqClient, ConnectOptions
|
||||
from quicprochat import QpqClient, ConnectOptions
|
||||
|
||||
client = QpqClient.connect_ffi(ConnectOptions(
|
||||
addr="127.0.0.1:5001",
|
||||
@@ -138,7 +138,7 @@ client.close_sync()
|
||||
|
||||
## Wire Format
|
||||
|
||||
The SDK implements the qpq v2 wire format:
|
||||
The SDK implements the qpc v2 wire format:
|
||||
|
||||
```
|
||||
[method_id:u16][req_id:u32][len:u32][protobuf payload]
|
||||
@@ -148,12 +148,12 @@ Each RPC is sent over its own QUIC bidirectional stream.
|
||||
|
||||
## Structure
|
||||
|
||||
- `quicproquo/client.py` -- High-level client API
|
||||
- `quicproquo/transport.py` -- QUIC transport (aioquic)
|
||||
- `quicproquo/ffi.py` -- Rust FFI transport (CFFI)
|
||||
- `quicproquo/proto.py` -- Protobuf encode/decode (no codegen)
|
||||
- `quicproquo/wire.py` -- v2 wire format framing
|
||||
- `quicproquo/types.py` -- Data types and exceptions
|
||||
- `quicprochat/client.py` -- High-level client API
|
||||
- `quicprochat/transport.py` -- QUIC transport (aioquic)
|
||||
- `quicprochat/ffi.py` -- Rust FFI transport (CFFI)
|
||||
- `quicprochat/proto.py` -- Protobuf encode/decode (no codegen)
|
||||
- `quicprochat/wire.py` -- v2 wire format framing
|
||||
- `quicprochat/types.py` -- Data types and exceptions
|
||||
- `examples/bot.py` -- Async echo bot example
|
||||
- `examples/ffi_demo.py` -- Synchronous FFI example
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Example: async echo bot using the quicproquo Python SDK.
|
||||
"""Example: async echo bot using the quicprochat Python SDK.
|
||||
|
||||
Connects to a qpq server, authenticates, and echoes back any received
|
||||
messages with a "[bot] " prefix.
|
||||
@@ -19,7 +19,7 @@ import asyncio
|
||||
import signal
|
||||
import sys
|
||||
|
||||
from quicproquo import QpqClient, ConnectOptions
|
||||
from quicprochat import QpqClient, ConnectOptions
|
||||
|
||||
|
||||
async def run_bot(opts: ConnectOptions, token: bytes, identity_key: bytes) -> None:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Example: synchronous messaging using the Rust FFI backend.
|
||||
|
||||
Requires libquicproquo_ffi to be built:
|
||||
cargo build --release -p quicproquo-ffi
|
||||
Requires libquicprochat_ffi to be built:
|
||||
cargo build --release -p quicprochat-ffi
|
||||
|
||||
Set QPQ_LIB_PATH if the library is not in the default search path.
|
||||
|
||||
@@ -15,7 +15,7 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
|
||||
from quicproquo import QpqClient, ConnectOptions
|
||||
from quicprochat import QpqClient, ConnectOptions
|
||||
|
||||
|
||||
def main() -> None:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"""quicproquo -- Python SDK for the quicproquo E2E encrypted messenger.
|
||||
"""quicprochat -- Python SDK for the quicprochat E2E encrypted messenger.
|
||||
|
||||
Two transport backends are available:
|
||||
|
||||
1. **FFI** (``QpqClient.connect_ffi``): wraps the Rust ``libquicproquo_ffi``
|
||||
1. **FFI** (``QpqClient.connect_ffi``): wraps the Rust ``libquicprochat_ffi``
|
||||
shared library via CFFI. This gives you the full Rust crypto stack
|
||||
(MLS, hybrid KEM, OPAQUE) at native speed.
|
||||
|
||||
@@ -11,8 +11,8 @@ Two transport backends are available:
|
||||
operations must be supplied externally.
|
||||
"""
|
||||
|
||||
from quicproquo.client import QpqClient
|
||||
from quicproquo.types import (
|
||||
from quicprochat.client import QpqClient
|
||||
from quicprochat.types import (
|
||||
ConnectOptions,
|
||||
Envelope,
|
||||
ChannelResult,
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
"""High-level quicproquo client.
|
||||
"""High-level quicprochat client.
|
||||
|
||||
Provides both async (QUIC transport) and sync (FFI transport) APIs for
|
||||
interacting with a quicproquo server.
|
||||
interacting with a quicprochat server.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from quicproquo.types import (
|
||||
from quicprochat.types import (
|
||||
ConnectOptions,
|
||||
Envelope,
|
||||
ChannelResult,
|
||||
HealthInfo,
|
||||
ConnectionError,
|
||||
)
|
||||
from quicproquo.transport import QuicTransport
|
||||
from quicproquo.ffi import FfiTransport
|
||||
from quicproquo import proto, wire
|
||||
from quicprochat.transport import QuicTransport
|
||||
from quicprochat.ffi import FfiTransport
|
||||
from quicprochat import proto, wire
|
||||
|
||||
|
||||
class QpqClient:
|
||||
"""High-level quicproquo client.
|
||||
"""High-level quicprochat client.
|
||||
|
||||
Use ``QpqClient.connect()`` for the async QUIC transport, or
|
||||
``QpqClient.connect_ffi()`` for the synchronous Rust FFI backend.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""CFFI bindings to ``libquicproquo_ffi`` (the Rust C FFI layer).
|
||||
"""CFFI bindings to ``libquicprochat_ffi`` (the Rust C FFI layer).
|
||||
|
||||
This module loads the shared library and exposes a synchronous Python API
|
||||
that mirrors the C functions in ``crates/quicproquo-ffi/src/lib.rs``.
|
||||
that mirrors the C functions in ``crates/quicprochat-ffi/src/lib.rs``.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -13,14 +13,14 @@ from typing import Optional
|
||||
|
||||
import cffi
|
||||
|
||||
from quicproquo.types import (
|
||||
from quicprochat.types import (
|
||||
QpqError,
|
||||
AuthError,
|
||||
TimeoutError,
|
||||
ConnectionError,
|
||||
)
|
||||
|
||||
# Status codes (must match crates/quicproquo-ffi/src/lib.rs).
|
||||
# Status codes (must match crates/quicprochat-ffi/src/lib.rs).
|
||||
QPQ_OK = 0
|
||||
QPQ_ERROR = 1
|
||||
QPQ_AUTH_FAILED = 2
|
||||
@@ -54,23 +54,23 @@ def _load_lib() -> object:
|
||||
# Explicit environment variable.
|
||||
os.environ.get("QPQ_LIB_PATH", ""),
|
||||
# Common cargo build output locations.
|
||||
str(Path(__file__).resolve().parents[3] / "target" / "release" / "libquicproquo_ffi.so"),
|
||||
str(Path(__file__).resolve().parents[3] / "target" / "debug" / "libquicproquo_ffi.so"),
|
||||
str(Path(__file__).resolve().parents[3] / "target" / "release" / "libquicprochat_ffi.so"),
|
||||
str(Path(__file__).resolve().parents[3] / "target" / "debug" / "libquicprochat_ffi.so"),
|
||||
# macOS dylib.
|
||||
str(
|
||||
Path(__file__).resolve().parents[3]
|
||||
/ "target"
|
||||
/ "release"
|
||||
/ "libquicproquo_ffi.dylib"
|
||||
/ "libquicprochat_ffi.dylib"
|
||||
),
|
||||
str(
|
||||
Path(__file__).resolve().parents[3]
|
||||
/ "target"
|
||||
/ "debug"
|
||||
/ "libquicproquo_ffi.dylib"
|
||||
/ "libquicprochat_ffi.dylib"
|
||||
),
|
||||
# System library path.
|
||||
"libquicproquo_ffi.so",
|
||||
"libquicprochat_ffi.so",
|
||||
]
|
||||
|
||||
for path in search_paths:
|
||||
@@ -83,8 +83,8 @@ def _load_lib() -> object:
|
||||
continue
|
||||
|
||||
raise OSError(
|
||||
"Could not find libquicproquo_ffi. Set QPQ_LIB_PATH or build with "
|
||||
"`cargo build --release -p quicproquo-ffi`."
|
||||
"Could not find libquicprochat_ffi. Set QPQ_LIB_PATH or build with "
|
||||
"`cargo build --release -p quicprochat-ffi`."
|
||||
)
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ def _check_error(handle: object, code: int) -> None:
|
||||
|
||||
|
||||
class FfiTransport:
|
||||
"""Synchronous transport wrapping ``libquicproquo_ffi``.
|
||||
"""Synchronous transport wrapping ``libquicprochat_ffi``.
|
||||
|
||||
Provides the same logical operations as ``QuicTransport`` but backed
|
||||
by the Rust client library through C FFI.
|
||||
|
||||
@@ -14,8 +14,8 @@ import asyncio
|
||||
import ssl
|
||||
from typing import Any
|
||||
|
||||
from quicproquo.types import ConnectionError, TimeoutError
|
||||
from quicproquo.wire import HEADER_SIZE, encode_frame, decode_header
|
||||
from quicprochat.types import ConnectionError, TimeoutError
|
||||
from quicprochat.wire import HEADER_SIZE, encode_frame, decode_header
|
||||
|
||||
|
||||
def _make_protocol_class() -> type:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Data types and exceptions for the quicproquo Python SDK."""
|
||||
"""Data types and exceptions for the quicprochat Python SDK."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -12,7 +12,7 @@ from typing import Optional
|
||||
|
||||
|
||||
class QpqError(Exception):
|
||||
"""Base exception for quicproquo SDK errors."""
|
||||
"""Base exception for quicprochat SDK errors."""
|
||||
|
||||
|
||||
class AuthError(QpqError):
|
||||
@@ -34,7 +34,7 @@ class ConnectionError(QpqError):
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ConnectOptions:
|
||||
"""Options for connecting to a quicproquo server.
|
||||
"""Options for connecting to a quicprochat server.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
@@ -12,7 +12,7 @@ import struct
|
||||
HEADER_FMT = "!HII" # network byte-order: u16 + u32 + u32
|
||||
HEADER_SIZE = struct.calcsize(HEADER_FMT)
|
||||
|
||||
# Method IDs (mirrors quicproquo-proto/src/lib.rs::method_ids).
|
||||
# Method IDs (mirrors quicprochat-proto/src/lib.rs::method_ids).
|
||||
# Auth (100-103)
|
||||
OPAQUE_REGISTER_START = 100
|
||||
OPAQUE_REGISTER_FINISH = 101
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Tests for the manual protobuf encode/decode layer."""
|
||||
|
||||
from quicproquo.proto import (
|
||||
from quicprochat.proto import (
|
||||
encode_health,
|
||||
decode_health_response,
|
||||
encode_resolve_user,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Tests for SDK data types and exceptions."""
|
||||
|
||||
from quicproquo.types import (
|
||||
from quicprochat.types import (
|
||||
ConnectOptions,
|
||||
Envelope,
|
||||
ChannelResult,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Tests for the v2 wire format encoder/decoder."""
|
||||
|
||||
from quicproquo.wire import (
|
||||
from quicprochat.wire import (
|
||||
HEADER_SIZE,
|
||||
encode_frame,
|
||||
decode_header,
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
# QuicProQuo Ruby SDK
|
||||
# QuicProChat Ruby SDK
|
||||
|
||||
Ruby FFI gem wrapping `libquicproquo_ffi` for the quicproquo E2E encrypted messenger.
|
||||
Ruby FFI gem wrapping `libquicprochat_ffi` for the quicprochat E2E encrypted messenger.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Ruby 3.1+
|
||||
- `libquicproquo_ffi` built for the target platform
|
||||
- `libquicprochat_ffi` built for the target platform
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
gem install quicproquo
|
||||
gem install quicprochat
|
||||
```
|
||||
|
||||
Or add to your Gemfile:
|
||||
|
||||
```ruby
|
||||
gem "quicproquo"
|
||||
gem "quicprochat"
|
||||
```
|
||||
|
||||
## Building the Native Library
|
||||
|
||||
```sh
|
||||
cargo build --release -p quicproquo-ffi
|
||||
cargo build --release -p quicprochat-ffi
|
||||
```
|
||||
|
||||
Set `QPQ_LIB_PATH` if the library is not in the default search path.
|
||||
Set `QPC_LIB_PATH` if the library is not in the default search path.
|
||||
|
||||
## Usage
|
||||
|
||||
```ruby
|
||||
require "quicproquo"
|
||||
require "quicprochat"
|
||||
|
||||
# Block form (auto-disconnect)
|
||||
QuicProQuo::Client.open("127.0.0.1:5001", ca_cert: "ca.pem") do |client|
|
||||
QuicProChat::Client.open("127.0.0.1:5001", ca_cert: "ca.pem") do |client|
|
||||
client.login("alice", "secret")
|
||||
client.send("bob", "hello from Ruby!")
|
||||
|
||||
@@ -42,7 +42,7 @@ QuicProQuo::Client.open("127.0.0.1:5001", ca_cert: "ca.pem") do |client|
|
||||
end
|
||||
|
||||
# Manual lifecycle
|
||||
client = QuicProQuo::Client.new("127.0.0.1:5001", ca_cert: "ca.pem")
|
||||
client = QuicProChat::Client.new("127.0.0.1:5001", ca_cert: "ca.pem")
|
||||
client.login("alice", "secret")
|
||||
client.send("bob", "hello")
|
||||
client.disconnect
|
||||
@@ -65,18 +65,18 @@ client.disconnect
|
||||
```ruby
|
||||
begin
|
||||
client.login("alice", "wrong")
|
||||
rescue QuicProQuo::AuthError => e
|
||||
rescue QuicProChat::AuthError => e
|
||||
puts "Auth failed: #{e.message}"
|
||||
rescue QuicProQuo::TimeoutError => e
|
||||
rescue QuicProChat::TimeoutError => e
|
||||
puts "Timeout: #{e.message}"
|
||||
rescue QuicProQuo::Error => e
|
||||
rescue QuicProChat::Error => e
|
||||
puts "Error: #{e.message}"
|
||||
end
|
||||
```
|
||||
|
||||
## Structure
|
||||
|
||||
- `lib/quicproquo/client.rb` -- High-level client
|
||||
- `lib/quicproquo/ffi_bindings.rb` -- FFI function declarations
|
||||
- `lib/quicproquo/errors.rb` -- Exception classes
|
||||
- `lib/quicprochat/client.rb` -- High-level client
|
||||
- `lib/quicprochat/ffi_bindings.rb` -- FFI function declarations
|
||||
- `lib/quicprochat/errors.rb` -- Exception classes
|
||||
- `examples/demo.rb` -- Usage example
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Example: quicproquo Ruby SDK demo.
|
||||
# Example: quicprochat Ruby SDK demo.
|
||||
#
|
||||
# Usage:
|
||||
# ruby demo.rb --server 127.0.0.1:5001 --ca-cert ca.pem \
|
||||
# --user alice --pass secret --recipient bob --message "hello"
|
||||
|
||||
require "optparse"
|
||||
require_relative "../lib/quicproquo"
|
||||
require_relative "../lib/quicprochat"
|
||||
|
||||
options = {
|
||||
server: "127.0.0.1:5001",
|
||||
@@ -26,7 +26,7 @@ OptionParser.new do |opts|
|
||||
opts.on("--message TEXT", "Message") { |v| options[:message] = v }
|
||||
end.parse!
|
||||
|
||||
QuicProQuo::Client.open(options[:server], ca_cert: options[:ca_cert]) do |client|
|
||||
QuicProChat::Client.open(options[:server], ca_cert: options[:ca_cert]) do |client|
|
||||
puts "Connected to #{options[:server]}"
|
||||
|
||||
client.login(options[:user], options[:pass])
|
||||
|
||||
23
sdks/ruby/lib/quicprochat.rb
Normal file
23
sdks/ruby/lib/quicprochat.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "quicprochat/ffi_bindings"
|
||||
require_relative "quicprochat/client"
|
||||
require_relative "quicprochat/errors"
|
||||
require_relative "quicprochat/version"
|
||||
|
||||
# Ruby SDK for the quicprochat E2E encrypted messenger.
|
||||
#
|
||||
# Two usage patterns:
|
||||
#
|
||||
# # Block form (auto-disconnect)
|
||||
# QuicProChat::Client.open("127.0.0.1:5001", ca_cert: "ca.pem") do |client|
|
||||
# client.login("alice", "secret")
|
||||
# client.send("bob", "hello")
|
||||
# end
|
||||
#
|
||||
# # Manual lifecycle
|
||||
# client = QuicProChat::Client.new("127.0.0.1:5001", ca_cert: "ca.pem")
|
||||
# client.login("alice", "secret")
|
||||
# client.disconnect
|
||||
module QuicProChat
|
||||
end
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
require "json"
|
||||
|
||||
module QuicProQuo
|
||||
# High-level quicproquo client for Ruby.
|
||||
module QuicProChat
|
||||
# High-level quicprochat client for Ruby.
|
||||
#
|
||||
# Wraps +libquicproquo_ffi+ via the +ffi+ gem.
|
||||
# Wraps +libquicprochat_ffi+ via the +ffi+ gem.
|
||||
#
|
||||
# client = QuicProQuo::Client.new("127.0.0.1:5001", ca_cert: "ca.pem")
|
||||
# client = QuicProChat::Client.new("127.0.0.1:5001", ca_cert: "ca.pem")
|
||||
# client.login("alice", "secret")
|
||||
# client.send("bob", "hello")
|
||||
# messages = client.receive(timeout_ms: 5000)
|
||||
@@ -15,12 +15,12 @@ module QuicProQuo
|
||||
#
|
||||
# Or use the block form for automatic cleanup:
|
||||
#
|
||||
# QuicProQuo::Client.open("127.0.0.1:5001", ca_cert: "ca.pem") do |c|
|
||||
# QuicProChat::Client.open("127.0.0.1:5001", ca_cert: "ca.pem") do |c|
|
||||
# c.login("alice", "secret")
|
||||
# c.send("bob", "hello")
|
||||
# end
|
||||
class Client
|
||||
# Connect to a quicproquo server.
|
||||
# Connect to a quicprochat server.
|
||||
#
|
||||
# @param server [String] Server address as +host:port+.
|
||||
# @param ca_cert [String] Path to PEM-encoded CA certificate.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module QuicProQuo
|
||||
# Base error for quicproquo SDK.
|
||||
module QuicProChat
|
||||
# Base error for quicprochat SDK.
|
||||
class Error < StandardError; end
|
||||
|
||||
# OPAQUE authentication failed (bad credentials).
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
require "ffi"
|
||||
|
||||
module QuicProQuo
|
||||
# Low-level FFI bindings to libquicproquo_ffi.
|
||||
module QuicProChat
|
||||
# Low-level FFI bindings to libquicprochat_ffi.
|
||||
#
|
||||
# The library is located via:
|
||||
# 1. QPQ_LIB_PATH environment variable
|
||||
@@ -12,7 +12,7 @@ module QuicProQuo
|
||||
module FFIBindings
|
||||
extend FFI::Library
|
||||
|
||||
# Status codes (mirrors crates/quicproquo-ffi/src/lib.rs).
|
||||
# Status codes (mirrors crates/quicprochat-ffi/src/lib.rs).
|
||||
QPQ_OK = 0
|
||||
QPQ_ERROR = 1
|
||||
QPQ_AUTH_FAILED = 2
|
||||
@@ -22,14 +22,14 @@ module QuicProQuo
|
||||
# Locate and load the shared library.
|
||||
LIB_SEARCH_PATHS = [
|
||||
ENV.fetch("QPQ_LIB_PATH", nil),
|
||||
File.expand_path("../../../../target/release/libquicproquo_ffi.so", __dir__),
|
||||
File.expand_path("../../../../target/debug/libquicproquo_ffi.so", __dir__),
|
||||
File.expand_path("../../../../target/release/libquicproquo_ffi.dylib", __dir__),
|
||||
File.expand_path("../../../../target/debug/libquicproquo_ffi.dylib", __dir__),
|
||||
"quicproquo_ffi",
|
||||
File.expand_path("../../../../target/release/libquicprochat_ffi.so", __dir__),
|
||||
File.expand_path("../../../../target/debug/libquicprochat_ffi.so", __dir__),
|
||||
File.expand_path("../../../../target/release/libquicprochat_ffi.dylib", __dir__),
|
||||
File.expand_path("../../../../target/debug/libquicprochat_ffi.dylib", __dir__),
|
||||
"quicprochat_ffi",
|
||||
].compact.freeze
|
||||
|
||||
lib_path = LIB_SEARCH_PATHS.find { |p| File.exist?(p) } || "quicproquo_ffi"
|
||||
lib_path = LIB_SEARCH_PATHS.find { |p| File.exist?(p) } || "quicprochat_ffi"
|
||||
ffi_lib lib_path
|
||||
|
||||
# QpqHandle* qpq_connect(const char*, const char*, const char*)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module QuicProQuo
|
||||
module QuicProChat
|
||||
VERSION = "0.1.0"
|
||||
end
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "quicproquo/ffi_bindings"
|
||||
require_relative "quicproquo/client"
|
||||
require_relative "quicproquo/errors"
|
||||
require_relative "quicproquo/version"
|
||||
|
||||
# Ruby SDK for the quicproquo E2E encrypted messenger.
|
||||
#
|
||||
# Two usage patterns:
|
||||
#
|
||||
# # Block form (auto-disconnect)
|
||||
# QuicProQuo::Client.open("127.0.0.1:5001", ca_cert: "ca.pem") do |client|
|
||||
# client.login("alice", "secret")
|
||||
# client.send("bob", "hello")
|
||||
# end
|
||||
#
|
||||
# # Manual lifecycle
|
||||
# client = QuicProQuo::Client.new("127.0.0.1:5001", ca_cert: "ca.pem")
|
||||
# client.login("alice", "secret")
|
||||
# client.disconnect
|
||||
module QuicProQuo
|
||||
end
|
||||
@@ -1,12 +1,12 @@
|
||||
Gem::Specification.new do |s|
|
||||
s.name = "quicproquo"
|
||||
s.name = "quicprochat"
|
||||
s.version = "0.1.0"
|
||||
s.summary = "Ruby SDK for quicproquo E2E encrypted messenger"
|
||||
s.description = "Ruby FFI bindings to libquicproquo_ffi for the quicproquo " \
|
||||
s.summary = "Ruby SDK for quicprochat E2E encrypted messenger"
|
||||
s.description = "Ruby FFI bindings to libquicprochat_ffi for the quicprochat " \
|
||||
"end-to-end encrypted messaging system."
|
||||
s.authors = ["quicproquo contributors"]
|
||||
s.authors = ["quicprochat contributors"]
|
||||
s.license = "MIT"
|
||||
s.homepage = "https://github.com/nicholasgasior/quicproquo"
|
||||
s.homepage = "https://github.com/nicholasgasior/quicprochat"
|
||||
|
||||
s.required_ruby_version = ">= 3.1"
|
||||
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
// swift-tools-version: 5.9
|
||||
// QuicProQuo Swift SDK — wraps libquicproquo_ffi for iOS/macOS.
|
||||
// QuicProChat Swift SDK — wraps libquicprochat_ffi for iOS/macOS.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "QuicProQuo",
|
||||
name: "QuicProChat",
|
||||
platforms: [
|
||||
.iOS(.v15),
|
||||
.macOS(.v13),
|
||||
],
|
||||
products: [
|
||||
.library(name: "QuicProQuo", targets: ["QuicProQuo"]),
|
||||
.library(name: "QuicProChat", targets: ["QuicProChat"]),
|
||||
],
|
||||
targets: [
|
||||
.systemLibrary(
|
||||
name: "CQuicProQuo",
|
||||
name: "CQuicProChat",
|
||||
pkgConfig: nil,
|
||||
providers: []
|
||||
),
|
||||
.target(
|
||||
name: "QuicProQuo",
|
||||
dependencies: ["CQuicProQuo"],
|
||||
path: "Sources/QuicProQuo"
|
||||
name: "QuicProChat",
|
||||
dependencies: ["CQuicProChat"],
|
||||
path: "Sources/QuicProChat"
|
||||
),
|
||||
.testTarget(
|
||||
name: "QuicProQuoTests",
|
||||
dependencies: ["QuicProQuo"],
|
||||
path: "Tests/QuicProQuoTests"
|
||||
name: "QuicProChatTests",
|
||||
dependencies: ["QuicProChat"],
|
||||
path: "Tests/QuicProChatTests"
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
# QuicProQuo Swift SDK
|
||||
# QuicProChat Swift SDK
|
||||
|
||||
Swift wrapper over `libquicproquo_ffi` for iOS and macOS.
|
||||
Swift wrapper over `libquicprochat_ffi` for iOS and macOS.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Xcode 15+ / Swift 5.9+
|
||||
- iOS 15+ or macOS 13+
|
||||
- `libquicproquo_ffi` built for the target architecture
|
||||
- `libquicprochat_ffi` built for the target architecture
|
||||
|
||||
## Building the Native Library
|
||||
|
||||
```sh
|
||||
# iOS (device)
|
||||
cargo build --release -p quicproquo-ffi --target aarch64-apple-ios
|
||||
cargo build --release -p quicprochat-ffi --target aarch64-apple-ios
|
||||
|
||||
# iOS Simulator (Apple Silicon)
|
||||
cargo build --release -p quicproquo-ffi --target aarch64-apple-ios-sim
|
||||
cargo build --release -p quicprochat-ffi --target aarch64-apple-ios-sim
|
||||
|
||||
# macOS
|
||||
cargo build --release -p quicproquo-ffi --target aarch64-apple-darwin
|
||||
cargo build --release -p quicprochat-ffi --target aarch64-apple-darwin
|
||||
```
|
||||
|
||||
## Installation
|
||||
@@ -37,13 +37,13 @@ Or add the library search path to your Xcode project:
|
||||
|
||||
```
|
||||
LIBRARY_SEARCH_PATHS = $(PROJECT_DIR)/../target/release
|
||||
OTHER_LDFLAGS = -lquicproquo_ffi
|
||||
OTHER_LDFLAGS = -lquicprochat_ffi
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```swift
|
||||
import QuicProQuo
|
||||
import QuicProChat
|
||||
|
||||
let client = try QpqClient(
|
||||
server: "127.0.0.1:5001",
|
||||
@@ -88,9 +88,9 @@ do {
|
||||
|
||||
## Structure
|
||||
|
||||
- `Sources/CQuicProQuo/` -- C module map and FFI header
|
||||
- `Sources/QuicProQuo/QpqClient.swift` -- High-level Swift client
|
||||
- `Sources/QuicProQuo/QpqError.swift` -- Error types
|
||||
- `Sources/CQuicProChat/` -- C module map and FFI header
|
||||
- `Sources/QuicProChat/QpqClient.swift` -- High-level Swift client
|
||||
- `Sources/QuicProChat/QpqError.swift` -- Error types
|
||||
|
||||
## Cross-Compilation
|
||||
|
||||
@@ -98,7 +98,7 @@ For iOS devices, add the Rust target and build:
|
||||
|
||||
```sh
|
||||
rustup target add aarch64-apple-ios
|
||||
cargo build --release -p quicproquo-ffi --target aarch64-apple-ios
|
||||
cargo build --release -p quicprochat-ffi --target aarch64-apple-ios
|
||||
```
|
||||
|
||||
Copy the library to your Xcode project's framework search path.
|
||||
|
||||
5
sdks/swift/Sources/CQuicProChat/module.modulemap
Normal file
5
sdks/swift/Sources/CQuicProChat/module.modulemap
Normal file
@@ -0,0 +1,5 @@
|
||||
module CQuicProChat {
|
||||
header "quicprochat_ffi.h"
|
||||
link "quicprochat_ffi"
|
||||
export *
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
// quicproquo_ffi.h — C header for libquicproquo_ffi.
|
||||
// quicprochat_ffi.h — C header for libquicprochat_ffi.
|
||||
//
|
||||
// Mirrors the extern "C" functions from crates/quicproquo-ffi/src/lib.rs.
|
||||
// Mirrors the extern "C" functions from crates/quicprochat-ffi/src/lib.rs.
|
||||
|
||||
#ifndef QUICPROQUO_FFI_H
|
||||
#define QUICPROQUO_FFI_H
|
||||
#ifndef QUICPROCHAT_FFI_H
|
||||
#define QUICPROCHAT_FFI_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
@@ -22,7 +22,7 @@ extern "C" {
|
||||
// Opaque handle type.
|
||||
typedef struct QpqHandle QpqHandle;
|
||||
|
||||
// Connect to a quicproquo server. Returns NULL on failure.
|
||||
// Connect to a quicprochat server. Returns NULL on failure.
|
||||
QpqHandle* qpq_connect(const char* server, const char* ca_cert, const char* server_name);
|
||||
|
||||
// Authenticate with OPAQUE credentials.
|
||||
@@ -49,4 +49,4 @@ void qpq_free_string(char* ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // QUICPROQUO_FFI_H
|
||||
#endif // QUICPROCHAT_FFI_H
|
||||
@@ -1,5 +0,0 @@
|
||||
module CQuicProQuo {
|
||||
header "quicproquo_ffi.h"
|
||||
link "quicproquo_ffi"
|
||||
export *
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import Foundation
|
||||
import CQuicProQuo
|
||||
import CQuicProChat
|
||||
|
||||
/// High-level quicproquo client for iOS/macOS.
|
||||
/// High-level quicprochat client for iOS/macOS.
|
||||
///
|
||||
/// Wraps ``libquicproquo_ffi`` to provide a Swift-native API for
|
||||
/// Wraps ``libquicprochat_ffi`` to provide a Swift-native API for
|
||||
/// connecting, authenticating, and messaging.
|
||||
///
|
||||
/// ```swift
|
||||
@@ -20,7 +20,7 @@ public final class QpqClient: @unchecked Sendable {
|
||||
private var handle: OpaquePointer?
|
||||
private let lock = NSLock()
|
||||
|
||||
/// Connect to a quicproquo server.
|
||||
/// Connect to a quicprochat server.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - server: Server address as ``host:port``.
|
||||
@@ -1,4 +1,4 @@
|
||||
/// Errors returned by the QuicProQuo SDK.
|
||||
/// Errors returned by the QuicProChat SDK.
|
||||
public enum QpqError: Error, Sendable, CustomStringConvertible {
|
||||
/// Connection to the server failed.
|
||||
case connectionFailed(String)
|
||||
@@ -1,13 +1,13 @@
|
||||
# @quicproquo/client
|
||||
# @quicprochat/client
|
||||
|
||||
TypeScript SDK for [quicproquo](https://github.com/nicholasgasior/quicproquo) --
|
||||
TypeScript SDK for [quicprochat](https://github.com/nicholasgasior/quicprochat) --
|
||||
an E2E encrypted group messenger built on MLS (RFC 9420), hybrid post-quantum
|
||||
key exchange (X25519 + ML-KEM-768), and sealed sender envelopes.
|
||||
|
||||
## Features
|
||||
|
||||
- **WASM-powered crypto** -- Ed25519 signatures, hybrid KEM, sealed sender,
|
||||
message padding, safety numbers -- all compiled from the Rust `quicproquo-core`
|
||||
message padding, safety numbers -- all compiled from the Rust `quicprochat-core`
|
||||
crate via `wasm-pack`.
|
||||
- **High-level client API** -- `QpqClient` wraps transport + crypto into a
|
||||
type-safe interface for resolving users, creating channels, and exchanging
|
||||
@@ -20,7 +20,7 @@ key exchange (X25519 + ML-KEM-768), and sealed sender envelopes.
|
||||
## Quick start
|
||||
|
||||
```typescript
|
||||
import { QpqClient } from "@quicproquo/client";
|
||||
import { QpqClient } from "@quicprochat/client";
|
||||
|
||||
// Crypto-only (no server needed)
|
||||
const client = await QpqClient.offline();
|
||||
@@ -37,7 +37,7 @@ console.log("Valid:", client.verify(alice.publicKey, msg, sig));
|
||||
|
||||
## Server connection
|
||||
|
||||
The native qpq server speaks Cap'n Proto RPC over QUIC/TCP with Noise_XX.
|
||||
The native qpc server speaks Cap'n Proto RPC over QUIC/TCP with Noise_XX.
|
||||
Browsers cannot open raw TCP sockets, so a WebSocket bridge proxy is required
|
||||
for full server connectivity:
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>quicproquo -- E2E Encrypted Messenger Demo</title>
|
||||
<title>quicprochat -- E2E Encrypted Messenger Demo</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #0d1117;
|
||||
@@ -201,7 +201,7 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>quicproquo</h1>
|
||||
<h1>quicprochat</h1>
|
||||
<p class="subtitle">E2E Encrypted Messenger -- Browser Demo</p>
|
||||
|
||||
<!-- Connection Bar -->
|
||||
@@ -273,7 +273,7 @@
|
||||
<!-- Sign & Verify -->
|
||||
<div style="margin-top:0.75rem;">
|
||||
<h2 style="font-size:1rem;">Sign & Verify</h2>
|
||||
<input type="text" id="sign-msg" placeholder="Message to sign (Alice's key)" value="Hello, quicproquo!">
|
||||
<input type="text" id="sign-msg" placeholder="Message to sign (Alice's key)" value="Hello, quicprochat!">
|
||||
<div class="row">
|
||||
<button class="crypto-btn" id="btn-sign" disabled>Sign (Alice)</button>
|
||||
<button class="crypto-btn" id="btn-verify" disabled>Verify (Alice pubkey)</button>
|
||||
|
||||
4
sdks/typescript/package-lock.json
generated
4
sdks/typescript/package-lock.json
generated
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@quicproquo/client",
|
||||
"name": "@quicprochat/client",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@quicproquo/client",
|
||||
"name": "@quicprochat/client",
|
||||
"version": "0.1.0",
|
||||
"devDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@quicproquo/client",
|
||||
"name": "@quicprochat/client",
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* High-level quicproquo client.
|
||||
* High-level quicprochat client.
|
||||
*
|
||||
* Combines the WASM crypto layer with a WebSocket transport to provide
|
||||
* a type-safe API for interacting with a quicproquo server.
|
||||
* a type-safe API for interacting with a quicprochat server.
|
||||
*
|
||||
* The crypto helpers work standalone (no server connection required).
|
||||
* Server RPC methods require a WebSocket bridge proxy since the native
|
||||
@@ -30,7 +30,7 @@ export class QpqClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a quicproquo server via WebSocket bridge.
|
||||
* Connect to a quicprochat server via WebSocket bridge.
|
||||
*
|
||||
* NOTE: The server must expose a WebSocket-to-capnp bridge endpoint.
|
||||
* See the project documentation for bridge proxy setup.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @quicproquo/client -- TypeScript SDK for quicproquo E2E encrypted messenger.
|
||||
* @quicprochat/client -- TypeScript SDK for quicprochat E2E encrypted messenger.
|
||||
*
|
||||
* The SDK provides:
|
||||
* - WASM-powered crypto (Ed25519, hybrid X25519+ML-KEM-768, sealed sender)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Transport abstraction for communicating with a quicproquo server.
|
||||
* Transport abstraction for communicating with a quicprochat server.
|
||||
*
|
||||
* The native qpq server speaks Cap'n Proto RPC over QUIC/TCP + Noise_XX.
|
||||
* Browsers cannot open raw TCP sockets, so this SDK assumes a WebSocket
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/** Options for connecting to a quicproquo server. */
|
||||
/** Options for connecting to a quicprochat server. */
|
||||
export interface ConnectOptions {
|
||||
/** WebSocket URL, e.g. ws://host:port or wss://host:port */
|
||||
addr: string;
|
||||
|
||||
4
sdks/typescript/wasm-crypto/Cargo.lock
generated
4
sdks/typescript/wasm-crypto/Cargo.lock
generated
@@ -429,12 +429,12 @@ name = "qpq-wasm-crypto"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"quicproquo-core",
|
||||
"quicprochat-core",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quicproquo-core"
|
||||
name = "quicprochat-core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@quicproquo/web",
|
||||
"name": "@quicprochat/web",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -9,7 +9,7 @@
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@quicproquo/client": "file:../typescript"
|
||||
"@quicprochat/client": "file:../typescript"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#58a6ff" />
|
||||
<title>quicproquo</title>
|
||||
<title>quicprochat</title>
|
||||
<link rel="manifest" href="manifest.json" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
@@ -12,7 +12,7 @@
|
||||
<div id="app">
|
||||
<!-- Login screen -->
|
||||
<div id="login-screen" class="screen">
|
||||
<h1>quicproquo</h1>
|
||||
<h1>quicprochat</h1>
|
||||
<p class="subtitle">End-to-end encrypted messenger</p>
|
||||
<form id="login-form">
|
||||
<input id="server-input" type="text" placeholder="Server (ws://host:port)" value="ws://127.0.0.1:9000" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "quicproquo",
|
||||
"name": "quicprochat",
|
||||
"short_name": "qpq",
|
||||
"description": "End-to-end encrypted group messenger",
|
||||
"start_url": "/",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* quicproquo web client — dark theme */
|
||||
/* quicprochat web client — dark theme */
|
||||
:root {
|
||||
--bg: #0d1117;
|
||||
--bg-surface: #161b22;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* quicproquo Service Worker — provides offline caching and background
|
||||
* quicprochat Service Worker — provides offline caching and background
|
||||
* notification support for the PWA.
|
||||
*/
|
||||
|
||||
@@ -67,11 +67,11 @@ self.addEventListener("push", (event) => {
|
||||
try {
|
||||
payload = event.data.json();
|
||||
} catch {
|
||||
payload = { title: "quicproquo", body: event.data.text() };
|
||||
payload = { title: "quicprochat", body: event.data.text() };
|
||||
}
|
||||
|
||||
event.waitUntil(
|
||||
self.registration.showNotification(payload.title || "quicproquo", {
|
||||
self.registration.showNotification(payload.title || "quicprochat", {
|
||||
body: payload.body || "New message",
|
||||
icon: "/icon-192.png",
|
||||
badge: "/icon-192.png",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* quicproquo web client — main application.
|
||||
* quicprochat web client — main application.
|
||||
*
|
||||
* Connects the TS SDK, WASM crypto, IndexedDB store, and the DOM together.
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Stores conversations, messages, and identity state in the browser.
|
||||
*/
|
||||
|
||||
const DB_NAME = "quicproquo";
|
||||
const DB_NAME = "quicprochat";
|
||||
const DB_VERSION = 1;
|
||||
|
||||
export interface StoredConversation {
|
||||
|
||||
Reference in New Issue
Block a user