use crate::handle_msg::HandleMessage;
use crate::handle_msg::HandleMessageWithJsep;
use crate::japrotocol::JaResponse;
use crate::japrotocol::JaSuccessProtocol;
use crate::japrotocol::PluginInnerData;
use crate::japrotocol::ResponseType;
use crate::japrotocol::ServerInfoRsp;
use crate::tgenerator::GenerateTransaction;
use crate::Error;
use serde::de::DeserializeOwned;
use std::fmt::Debug;
use std::ops::Deref;
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::mpsc;
#[cfg(not(target_family = "wasm"))]
pub trait MaybeSend: Send {}
#[cfg(not(target_family = "wasm"))]
impl<T: Send> MaybeSend for T {}
#[cfg(target_family = "wasm")]
pub trait MaybeSend {}
#[cfg(target_family = "wasm")]
impl<T> MaybeSend for T {}
#[cfg(not(target_family = "wasm"))]
pub trait MaybeSync: Sync {}
#[cfg(not(target_family = "wasm"))]
impl<T: Sync> MaybeSync for T {}
#[cfg(target_family = "wasm")]
pub trait MaybeSync {}
#[cfg(target_family = "wasm")]
impl<T> MaybeSync for T {}
pub struct ConnectionParams {
pub url: String,
pub capacity: usize,
pub apisecret: Option<String>,
pub server_root: String,
}
#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
pub trait JanusInterface: Debug + MaybeSend + MaybeSync + 'static {
async fn make_interface(
conn_params: ConnectionParams,
transaction_generator: impl GenerateTransaction,
) -> Result<Self, Error>
where
Self: Sized;
async fn create(&self, timeout: Duration) -> Result<u64, Error>;
async fn server_info(&self, timeout: Duration) -> Result<ServerInfoRsp, Error>;
async fn attach(
&self,
session_id: u64,
plugin_id: String,
timeout: Duration,
) -> Result<(u64, mpsc::UnboundedReceiver<JaResponse>), Error>;
fn has_keep_alive(&self) -> bool;
async fn keep_alive(&self, session_id: u64, timeout: Duration) -> Result<(), Error>;
async fn destroy(&self, session_id: u64, timeout: Duration) -> Result<(), Error>;
async fn fire_and_forget_msg(&self, message: HandleMessage) -> Result<String, Error>;
async fn send_msg_waiton_ack(
&self,
message: HandleMessage,
timeout: Duration,
) -> Result<String, Error>;
async fn internal_send_msg_waiton_rsp(
&self,
message: HandleMessage,
timeout: Duration,
) -> Result<JaResponse, Error>;
async fn fire_and_forget_msg_with_jsep(
&self,
message: HandleMessageWithJsep,
) -> Result<String, Error>;
async fn send_msg_waiton_ack_with_jsep(
&self,
message: HandleMessageWithJsep,
timeout: Duration,
) -> Result<String, Error>;
async fn send_handle_request(&self, request: HandleMessage) -> Result<(), Error>;
async fn send_handle_request_waiton_ack(
&self,
request: HandleMessage,
timeout: Duration,
) -> Result<String, Error>;
fn name(&self) -> Box<str> {
"Janus Interface".to_string().into_boxed_str()
}
}
impl dyn JanusInterface {
#[tracing::instrument(level = tracing::Level::TRACE, skip_all)]
pub async fn send_msg_waiton_rsp<R>(
&self,
message: HandleMessage,
timeout: Duration,
) -> Result<R, Error>
where
R: DeserializeOwned,
{
let response = self.internal_send_msg_waiton_rsp(message, timeout).await?;
let result = match response.janus {
ResponseType::Success(JaSuccessProtocol::Plugin { plugin_data }) => {
match plugin_data.data {
PluginInnerData::Error { error_code, error } => {
tracing::error!(
"Plugin response error: {{ code: {error_code}, error: {error} }}"
);
return Err(Error::PluginResponseError { error_code, error });
}
PluginInnerData::Data(data) => match serde_json::from_value::<R>(data) {
Ok(result) => result,
Err(error) => {
tracing::error!("Failed to parse with error {error:#?}");
return Err(Error::UnexpectedResponse);
}
},
}
}
_ => {
tracing::error!("Request failed");
return Err(Error::UnexpectedResponse);
}
};
Ok(result)
}
}
#[derive(Clone)]
pub struct JanusInterfaceImpl {
inner: Arc<dyn JanusInterface>,
}
impl Deref for JanusInterfaceImpl {
type Target = Arc<dyn JanusInterface>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl JanusInterfaceImpl {
pub fn new(interface: impl JanusInterface) -> Self {
Self {
inner: Arc::new(interface),
}
}
}
impl Debug for JanusInterfaceImpl {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Interface")
.field(&self.inner.name())
.finish()
}
}