pub struct State(/* private fields */);Expand description
State of an IRC network.
This is used by ellidri to maintain a consistent state of the network. Note that this is just
an Arc to the real data, so it’s cheap to clone and clones share the same data.
At the time of writing, this only support the client-to-server API, so the network can only consist of one server. Maybe in the long term it will support incoming messages from other servers.
The API is designed with async support only, because this type heavily relies on tokio.
§Example
// Initialize a `StateConfig` and create the state.
let sasl_backend = auth::choose_provider(config::SaslBackend::None, None).unwrap();
let state = State::new(config::State {
domain: "ellidri.dev".to_owned(),
..config::State::sample()
}, sasl_backend);
// Each client is identified by its address.
let client_addr = std::net::SocketAddr::from(([127, 0, 0, 1], 12345));
// The state uses a MPSC queue and pushes the messages meant to be sent
// to the client onto the queue.
let (msg_queue, mut outgoing_msgs) = tokio::sync::mpsc::unbounded_channel();
state.peer_joined(client_addr, msg_queue).await;
// `handle_message` is used to pass messages from the client to the state.
let nick = Message::parse("NICK ser\r\n").unwrap();
let user = Message::parse("USER ser 0 * :ser\r\n").unwrap();
state.handle_message(&client_addr, nick).await;
state.handle_message(&client_addr, user).await;
// The user has registered, so the state should have pushed
// the welcome message, the motd, etc. onto the queue.
// It is safe to unwrap here while the peer is saved in the state.
let msg = outgoing_msgs.recv().await.unwrap();
// Outgoing messages implement `AsRef<[u8]>`, so they can be used with `std::io::Write`.
// They also implement `AsRef<str>` because they are UTF-8 encoded.
// Note that one call to `recv` can contain multiple IRC messages.
let msg: &str = msg.as_ref();
let mut lines = msg.split("\r\n");
// The first IRC message from the server is RPL_WELCOME.
assert_eq!(lines.next().unwrap(),
":ellidri.dev 001 ser :Welcome home, ser!ser@127.0.0.1");Implementations§
Source§impl State
impl State
Sourcepub fn new(config: State, auth_provider: Box<dyn Provider>) -> Self
pub fn new(config: State, auth_provider: Box<dyn Provider>) -> Self
Intialize the IRC state from the given configuration.
Sourcepub async fn peer_joined(
&self,
addr: SocketAddr,
queue: UnboundedSender<MessageQueueItem>,
)
pub async fn peer_joined( &self, addr: SocketAddr, queue: UnboundedSender<MessageQueueItem>, )
Adds a new connection to the state.
Each connection is identified by its address. The queue is used to push messages back to the peer.
Sourcepub async fn peer_quit(&self, addr: &SocketAddr, err: Option<Error>)
pub async fn peer_quit(&self, addr: &SocketAddr, err: Option<Error>)
Removes the given connection from the state, with an optional error.
If the peer has quit unexpctedly, err should be set to Some and reflect the cause of
the quit, so that other peers can be correctly informed.
Sourcepub async fn handle_message(
&self,
addr: &SocketAddr,
msg: Message<'_>,
) -> Result<(), ()>
pub async fn handle_message( &self, addr: &SocketAddr, msg: Message<'_>, ) -> Result<(), ()>
Updates the state according to the given message from the given client.