Jamsocket is a minimalist framework for developing stateful WebSocket applications.
Jamsocket apps implement the [SimpleJamsocketService] trait, which provides a way for the
app to hook into events when clients connect, disconnect, and send messages. Additionally,
Jamsocket provides a simple mechanism for invoking events in the future with a timer.
A simple chat server looks like this:
use jamsocket::*;
use std::collections::HashMap;
#[derive(Default)]
struct ChatServer {
client_to_nickname: HashMap<ClientId, String>,
}
impl SimpleJamsocketService for ChatServer {
fn new(room_id: &str, _: &impl JamsocketContext) -> Self {
Default::default()
}
fn connect(&mut self, client: ClientId, ctx: &impl JamsocketContext) {
let username = format!("client{}", u32::from(client));
ctx.send_message(client,
&format!("Welcome to the chat! Your name is {}. \
Send /nick <username> to change it.",
&username));
ctx.send_message(MessageRecipient::Broadcast,
&format!("{} has joined the chat", &username));
}
fn disconnect(&mut self, client: ClientId, ctx: &impl JamsocketContext) {
let username = self.client_to_nickname.remove(&client).unwrap();
ctx.send_message(MessageRecipient::Broadcast,
&format!("{} has left the chat", &username));
}
fn message(&mut self, client: ClientId, message: &str, ctx: &impl JamsocketContext) {
if let Some(new_nick) = message.strip_prefix("/nick ") {
let old_nick = self.client_to_nickname.insert(client, new_nick.to_string()).unwrap();
ctx.send_message(MessageRecipient::Broadcast,
&format!("{} is now known as {}", old_nick, new_nick));
} else {
let username = self.client_to_nickname.get(&client).unwrap();
ctx.send_message(MessageRecipient::Broadcast,
&format!("{}: {}", username, message));
}
}
}