Registering a protocol
We've now successfully created a custom protocol. The next step is the
register the protocol with the ProtocolRegistry
.
We'll define a new function inside the Dchat
implementation called
register_protocol()
. It will invoke the ProtocolRegistry
using the
handle to the p2p network contained in the Dchat
struct. It will then
call register()
on the registry and pass the ProtocolDchat
constructor.
info!("Registering Dchat protocol");
let registry = p2p.protocol_registry();
registry
.register(net::session::SESSION_DEFAULT, move |channel, _p2p| {
let msgs_ = msgs.clone();
async move { ProtocolDchat::init(channel, msgs_).await }
})
.await;
register
takes a closure with two arguments, channel
and p2p
. We
use move
to capture these values. We then create an async closure
that captures these values and the value msgs
and use them to call
ProtocolDchat::init
in the async block.
The code would be expressed more simply as:
registry.register(!net::SESSION_SEED, async move |channel, _p2p| {
ProtocolDchat::init(channel, msgs).await
})
.await;
However we cannot do this due to limitation with async closures. So
instead we wrap the async move
in a move
in order to capture the
variables needed by ProtocolDchat::init
.
Notice the use of a bitflag
. We use !SESSION_SEED
to specify that
this protocol should be performed by all sessions aside from the
seed session.
Also notice that register_protocol
requires a DchatMsgsBuffer
that we
send to the ProtocolDchat
constructor. We'll create the DchatMsgsBuffer
in main
and pass it to Dchat::new
. Let's add DchatMsgsBuffer
to the
Dchat
struct definition first.
struct Dchat {
p2p: net::P2pPtr,
recv_msgs: DchatMsgsBuffer,
}
And initialize it:
async_daemonize!(realmain);
async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
//...
let msgs: DchatMsgsBuffer = Arc::new(Mutex::new(vec![DchatMsg { msg: String::new() }]));
let mut dchat = Dchat::new(p2p.clone(), msgs);
//...
}
Now try running dchatd
with lilith
and seeing what debug output you
get. Keep an eye out for the following:
[DEBUG] (1) net: Channel::subscribe_msg() [START, command="DchatMsg", address=tcp://127.0.0.1:50105]
[DEBUG] (1) net: Channel::subscribe_msg() [END, command="DchatMsg", address=tcp://127.0.0.1:50105]
[DEBUG] (1) net: Attached ProtocolDchat
If you see that, we have successfully:
- Implemented a custom
Message
and created aMessageSubscription
. - Implemented a custom
Protocol
and registered it with theProtocolRegistry
.