use std::str::FromStr;
use internet2::addr::NodeAddr;
use lnp::p2p::bifrost::{BifrostApp, ChannelId};
use microservices::esb;
use microservices::esb::{ClientId, ServiceName};
use rgb_rpc::RpcMsg;
use storm::StormApp;
use storm_ext::ExtMsg as StormMsg;
use strict_encoding::{strict_deserialize, strict_serialize};
use crate::bus::{BusMsg, CtlMsg};
pub(crate) type Endpoints = esb::EndpointList<ServiceBus>;
pub type DaemonId = u64;
#[derive(Clone, PartialEq, Eq, Hash, Debug, Display, From, StrictEncode, StrictDecode)]
pub enum ServiceId {
#[display("rgbd")]
#[strict_encoding(value = 0x41)]
StormApp(StormApp),
#[display("client<{0}>")]
#[strict_encoding(value = 2)]
Client(ClientId),
#[display("bpd")]
#[strict_encoding(value = 0x10)]
Bp,
#[display("bucketd<{0}>")]
#[strict_encoding(value = 0x31)]
Bucket(DaemonId),
#[display("peerd<{0}>")]
#[from]
#[strict_encoding(value = 0x22)]
Peer(NodeAddr),
#[display("channel<{0:#x}>")]
#[from]
#[strict_encoding(value = 0x23)]
Channel(ChannelId),
#[display("msgapp<{0}>")]
#[strict_encoding(value = 0x25)]
MsgApp(BifrostApp),
#[display("chapp<{0}>")]
#[strict_encoding(value = 0x24)]
ChannelApp(BifrostApp),
#[display("other<{0}>")]
#[strict_encoding(value = 0xFF)]
Other(ServiceName),
}
impl ServiceId {
pub fn rgbd() -> ServiceId { ServiceId::StormApp(StormApp::RgbTransfers) }
pub fn stormd() -> ServiceId { ServiceId::MsgApp(BifrostApp::Storm) }
}
impl esb::ServiceAddress for ServiceId {}
impl From<ServiceId> for Vec<u8> {
fn from(daemon_id: ServiceId) -> Self {
strict_serialize(&daemon_id).expect("Memory-based encoding does not fail")
}
}
impl From<Vec<u8>> for ServiceId {
fn from(vec: Vec<u8>) -> Self {
strict_deserialize(&vec).unwrap_or_else(|_| {
ServiceId::Other(
ServiceName::from_str(&String::from_utf8_lossy(&vec))
.expect("ClientName conversion never fails"),
)
})
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display)]
pub(crate) enum ServiceBus {
#[display("RPC")]
Rpc,
#[display("CTL")]
Ctl,
#[display("STORM")]
Storm,
}
impl esb::BusId for ServiceBus {
type Address = ServiceId;
}
pub(crate) trait Responder
where
Self: esb::Handler<ServiceBus>,
esb::Error<ServiceId>: From<Self::Error>,
{
#[inline]
fn send_rpc(
&self,
endpoints: &mut Endpoints,
client_id: ClientId,
message: impl Into<RpcMsg>,
) -> Result<(), esb::Error<ServiceId>> {
endpoints.send_to(
ServiceBus::Rpc,
self.identity(),
ServiceId::Client(client_id),
BusMsg::Rpc(message.into()),
)
}
#[inline]
fn send_ctl(
&self,
endpoints: &mut Endpoints,
service_id: ServiceId,
message: impl Into<CtlMsg>,
) -> Result<(), esb::Error<ServiceId>> {
endpoints.send_to(ServiceBus::Ctl, self.identity(), service_id, BusMsg::Ctl(message.into()))
}
#[inline]
fn send_storm(
&self,
endpoints: &mut Endpoints,
message: impl Into<StormMsg>,
) -> Result<(), esb::Error<ServiceId>> {
endpoints.send_to(
ServiceBus::Storm,
self.identity(),
ServiceId::stormd(),
BusMsg::Storm(message.into()),
)
}
}