use crate::signaling::{SignalingTransport, SignalingMessage};
use async_trait::async_trait;
use std::net::SocketAddr;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct GossipPeerId {
pub id: String, }
impl std::fmt::Display for GossipPeerId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.id)
}
}
impl std::str::FromStr for GossipPeerId {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(GossipPeerId { id: s.to_string() })
}
}
#[derive(Debug, thiserror::Error)]
pub enum GossipError {
#[error("Network error: {0}")]
NetworkError(String),
#[error("Serialization error: {0}")]
SerializationError(#[from] serde_json::Error),
}
pub struct GossipSignalingTransport {
gossip_network: std::sync::Arc<YourGossipNetwork>,
message_receiver: tokio::sync::mpsc::Receiver<(GossipPeerId, SignalingMessage)>,
}
impl GossipSignalingTransport {
pub fn new(gossip_network: std::sync::Arc<YourGossipNetwork>) -> Self {
let (tx, rx) = tokio::sync::mpsc::channel(100);
gossip_network.set_signaling_callback(move |from_peer, data| {
match serde_json::from_slice::<SignalingMessage>(&data) {
Ok(message) => {
let peer_id = GossipPeerId { id: from_peer };
let _ = tx.try_send((peer_id, message));
}
Err(e) => {
tracing::warn!("Failed to deserialize signaling message: {}", e);
}
}
});
Self {
gossip_network,
message_receiver: rx,
}
}
}
#[async_trait]
impl SignalingTransport for GossipSignalingTransport {
type PeerId = GossipPeerId;
type Error = GossipError;
async fn send_message(
&self,
peer: &GossipPeerId,
message: SignalingMessage,
) -> Result<(), GossipError> {
let data = serde_json::to_vec(&message)
.map_err(GossipError::SerializationError)?;
self.gossip_network
.send_to_peer(&peer.id, b"WEBRTC_SIGNALING", &data)
.await
.map_err(|e| GossipError::NetworkError(e.to_string()))?;
Ok(())
}
async fn receive_message(&self) -> Result<(GossipPeerId, SignalingMessage), GossipError> {
self.message_receiver
.recv()
.await
.ok_or_else(|| GossipError::NetworkError("Channel closed".to_string()))
}
async fn discover_peer_endpoint(
&self,
peer: &GossipPeerId,
) -> Result<Option<SocketAddr>, GossipError> {
match self.gossip_network.get_peer_endpoint(&peer.id) {
Some(endpoint) => Ok(Some(endpoint)),
None => Ok(None), }
}
}
pub struct YourGossipNetwork {
}
impl YourGossipNetwork {
pub fn set_signaling_callback<F>(&self, _callback: F)
where
F: Fn(String, Vec<u8>) + Send + Sync + 'static,
{
}
pub async fn send_to_peer(
&self,
_peer_id: &str,
_topic: &[u8],
_data: &[u8],
) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
pub fn get_peer_endpoint(&self, _peer_id: &str) -> Option<SocketAddr> {
None
}
}
pub async fn create_webrtc_with_gossip() -> anyhow::Result<()> {
use crate::prelude::*;
use crate::identity::PeerIdentityString;
let gossip_network = std::sync::Arc::new(YourGossipNetwork { });
let gossip_transport = GossipSignalingTransport::new(gossip_network);
let service = WebRtcService::<PeerIdentityString, GossipSignalingTransport>::builder()
.with_identity("alice-bob-charlie-david")
.build()
.await?;
service.start().await?;
let call_id = service.initiate_call(
"eve-frank-grace-henry",
MediaConstraints::video_call()
).await?;
Ok(())
}