Skip to main content

VCLConnection

Struct VCLConnection 

Source
pub struct VCLConnection { /* private fields */ }
Expand description

A secure VCL Protocol connection over UDP.

Each connection manages its own cryptographic state: independent send/receive hash chains, nonce tracking, shared secret, and Ed25519 key pair.

§Example — Server

use vcl_protocol::connection::VCLConnection;

#[tokio::main]
async fn main() {
    let mut server = VCLConnection::bind("127.0.0.1:8080").await.unwrap();
    server.accept_handshake().await.unwrap();

    loop {
        match server.recv().await {
            Ok(packet) => println!("{}", String::from_utf8_lossy(&packet.payload)),
            Err(e)     => { eprintln!("{}", e); break; }
        }
    }
}

§Example — Client

use vcl_protocol::connection::VCLConnection;

#[tokio::main]
async fn main() {
    let mut client = VCLConnection::bind("127.0.0.1:0").await.unwrap();
    client.connect("127.0.0.1:8080").await.unwrap();
    client.send(b"Hello!").await.unwrap();
    client.close().unwrap();
}

Implementations§

Source§

impl VCLConnection

Source

pub async fn bind(addr: &str) -> Result<Self, VCLError>

Bind a new VCL connection to a local UDP address.

Use "127.0.0.1:0" to let the OS assign a port (typical for clients).

§Errors

Returns VCLError::IoError if the socket cannot be bound.

Source

pub fn subscribe(&mut self) -> Receiver<VCLEvent>

Subscribe to connection events.

Returns an async mpsc::Receiver<VCLEvent> with a channel capacity of 64. Call this before connect() or accept_handshake() to receive the VCLEvent::Connected event.

Events are sent with try_send — if the channel is full, events are dropped silently.

Source

pub fn set_timeout(&mut self, secs: u64)

Set the inactivity timeout in seconds (default: 60).

If no send() or recv() occurs within this duration, the next operation returns VCLError::Timeout. Set to 0 to disable the timeout.

Source

pub fn get_timeout(&self) -> u64

Get the current inactivity timeout in seconds.

Source

pub fn last_activity(&self) -> Instant

Get the Instant of the last send() or recv() activity.

Source

pub fn set_shared_key(&mut self, private_key: &[u8])

Override the Ed25519 signing key with a pre-shared key.

⚠️ For testing only. Never use a pre-shared key in production.

Source

pub async fn connect(&mut self, addr: &str) -> Result<(), VCLError>

Connect to a remote VCL server and perform the X25519 handshake.

After this returns Ok(()), the connection is ready to send() and recv(). Emits VCLEvent::Connected if subscribed.

§Errors
Source

pub async fn accept_handshake(&mut self) -> Result<(), VCLError>

Accept an incoming X25519 handshake from a client (server side).

Blocks until a ClientHello is received. After this returns Ok(()), the connection is ready to send() and recv(). Emits VCLEvent::Connected if subscribed.

§Errors
Source

pub async fn send(&mut self, data: &[u8]) -> Result<(), VCLError>

Encrypt, sign, and send a data packet to the peer.

§Errors
Source

pub async fn ping(&mut self) -> Result<(), VCLError>

Send a ping to the peer to check liveness and measure round-trip latency.

The pong reply is handled transparently inside recv() — you never see Pong packets directly. Subscribe to events to receive VCLEvent::PongReceived { latency }.

⚠️ You must keep calling recv() for the pong to be processed.

§Errors

Same as send().

Source

pub async fn rotate_keys(&mut self) -> Result<(), VCLError>

Initiate a mid-session key rotation using a fresh X25519 ephemeral exchange.

Sends our new public key to the peer (encrypted with the current key), waits for the peer’s new public key, and atomically switches to the new shared secret on both sides.

Emits VCLEvent::KeyRotated on success.

⚠️ The peer must be actively calling recv() during rotation. ⚠️ Do not call send() while rotate_keys() is awaiting a response.

§Errors
Source

pub async fn recv(&mut self) -> Result<VCLPacket, VCLError>

Receive the next data packet from the peer.

Control packets (Ping, Pong, KeyRotation) are handled transparently — this method loops internally until a Data packet arrives.

On success, packet.payload contains the decrypted data.

§Errors
Source

pub fn close(&mut self) -> Result<(), VCLError>

Gracefully close the connection and clear all cryptographic state.

After calling close(), all further operations return VCLError::ConnectionClosed. Emits VCLEvent::Disconnected if subscribed.

§Errors

Returns VCLError::ConnectionClosed if already closed.

Source

pub fn is_closed(&self) -> bool

Returns true if the connection has been closed.

Source

pub fn get_public_key(&self) -> Vec<u8>

Get the local Ed25519 public key (32 bytes).

Source

pub fn get_shared_secret(&self) -> Option<[u8; 32]>

Get the current X25519 shared secret, or None if the handshake has not completed or the connection is closed.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more