Module client

Module client 

Source
Expand description

Client implementation

§Tokio-based clients for the Zeek WebSocket API

This module provides a trait ZeekClient and a Service which can be used to create full asynchronous clients for the Zeek WebSocket API under [tokio]. Users implement ZeekClient to specify the runtime behavior of the client. After implementing ZeekClient for a client type it needs to be wrapped in a Service, e.g.,

struct Client {
    outbox: Option<Outbox>
}

impl ZeekClient for Client {
    async fn connected(&mut self, _endpoint: String, _version: String) {}
    async fn event(&mut self, _topic: String, _event: zeek_websocket::Event) {}
    async fn error(&mut self, _error: zeek_websocket::protocol::ProtocolError) {}
}

let service = Service::new(|outbox| Client {
    outbox: Some(outbox)
});

Service::new passes along an Outbox which can be used to publish (topic, Event) tuples to Zeek with Outbox::send. Clients should store the Outbox since after it is dropped the Service will close the connection to Zeek; one way to control the lifetime of the API connection is to store an Option<Outbox> in the client so it can explicitly be reset to None.

The service needs to explicitly be started with Service::serve which will return a Future which will become ready once the service has terminated, either due to connection shutdown or a fatal error.

§Example

This example implements a client which publishes an event to Zeek and waits for the response before exiting. The hypothetical event here is echo,

global echo: event(message: string);

and the server will publish back the event on the same topic. Since the client is subscribed on the topic it publishes to it will see the response, and can then reset its internally held Outbox to signal to the Service that the connection should be closed.

struct Client {
    outbox: Option<Outbox>,
};

impl ZeekClient for Client {
    async fn connected(&mut self, endpoint: String, version: String) {
        // Once connected send a single echo event. The server will send
        // the event back to us.
        if let Some(outbox) = &self.outbox {
            outbox
                .send("/topic".to_owned(), Event::new("echo", ["hello!"]))
                .await
                .unwrap();
        }
    }

    async fn event(&mut self, topic: String, event: Event) {
        // If we see the `echo` event from the server drop our `outbox`.
        // This will cause the service to terminate.
        if &event.name == "echo" {
            self.outbox.take();
        }
    }

    async fn error(&mut self, error: protocol::ProtocolError) {
        todo!()
    }
}

let uri = "ws://localhost:8080/v1/messages/json".try_into().unwrap();

let service = Service::new(|outbox| Client {
    outbox: Some(outbox),
});

service
    .serve(
        "my-client",
        uri,
        Subscriptions::from(&["/topic"]),
    )
    .await.unwrap();

Structs§

Outbox
Handle for publishing into a Service.
Service
Runtime for a ZeekClient.
ServiceConfig
Configuration for a Service.

Enums§

Error
Error enum for client-related errors.

Traits§

ZeekClient