# QuicProQuo Ruby SDK

Ruby FFI gem wrapping `libquicproquo_ffi` for the quicproquo E2E encrypted messenger.

## Prerequisites

- Ruby 3.1+
- `libquicproquo_ffi` built for the target platform

## Installation

```sh
gem install quicproquo
```

Or add to your Gemfile:

```ruby
gem "quicproquo"
```

## Building the Native Library

```sh
cargo build --release -p quicproquo-ffi
```

Set `QPQ_LIB_PATH` if the library is not in the default search path.

## Usage

```ruby
require "quicproquo"

# 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 from Ruby!")

  messages = client.receive(timeout_ms: 5000)
  messages.each { |msg| puts msg }
end

# Manual lifecycle
client = QuicProQuo::Client.new("127.0.0.1:5001", ca_cert: "ca.pem")
client.login("alice", "secret")
client.send("bob", "hello")
client.disconnect
```

## API

| Method | Description |
|---|---|
| `Client.new(server, ca_cert:, server_name:)` | Connect to server |
| `Client.open(server, **opts) { \|c\| ... }` | Connect with auto-disconnect |
| `client.login(username, password)` | OPAQUE authentication |
| `client.send(recipient, message)` | Send message by username |
| `client.receive(timeout_ms: 5000)` | Receive pending messages |
| `client.disconnect` | Disconnect |
| `client.connected?` | Connection status |

## Error Handling

```ruby
begin
  client.login("alice", "wrong")
rescue QuicProQuo::AuthError => e
  puts "Auth failed: #{e.message}"
rescue QuicProQuo::TimeoutError => e
  puts "Timeout: #{e.message}"
rescue QuicProQuo::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
- `examples/demo.rb` -- Usage example
