webrtc-connection 0.2.0

WebRTC connection.
Documentation
use cs_utils::random_str;
use tokio::try_join;
use tokio::io::duplex;
use webrtc::{peer_connection::configuration::RTCConfiguration, ice_transport::ice_server::RTCIceServer};
use connection_utils::{Channel, Connected};

use crate::rtc_connection::RtcConnection;

type TConnection = Box<dyn Connected>;
type TChannel = Box<dyn Channel>;

/// Creates an RTC Connection pair.
pub async fn create_connection_pair() -> (TConnection, TConnection) {
    let (stream1, stream2 ) = duplex(4096);

    let rtc_config1 = RTCConfiguration {
        ice_servers: vec![RTCIceServer {
            urls: vec!["stun:stun.l.google.com:19302".to_owned()],
            ..Default::default()
        }],
        ..Default::default()
    };

    let rtc_config2 = RTCConfiguration {
        ice_servers: vec![RTCIceServer {
            urls: vec!["stun:stun.l.google.com:19302".to_owned()],
            ..Default::default()
        }],
        ..Default::default()
    };

    let (client_connection, server_connection) = try_join!(
        tokio::spawn(async move {
            let connection = RtcConnection::new(
                Box::new(stream1),
                rtc_config1,
            )
            .await
            .expect("Cannot create RTC connection.");

            return connection
                .connect()
                .await
                .expect("Failed to connect.");
        }),
        tokio::spawn(async move {
            let connection = RtcConnection::new(
                Box::new(stream2),
                rtc_config2,
            )
            .await
            .expect("Cannot create RTC connection.");
    
            return connection
                .listen()
                .await
                .expect("Failed to connect.");
        }),
    ).unwrap();

    return (client_connection, server_connection);
}

/// Creates a data channel pair on a connection.
pub async fn create_channel_pair(
    mut client_connection: TConnection,
    mut server_connection: TConnection,
) -> ((TConnection, TChannel), (TConnection, TChannel)) {
    // create data channel
    let data_channel_label = format!("channel:{}", random_str(8));
    let (client_channel, server_channel) = try_join!(
        tokio::spawn(async move {
            let data_channel = client_connection
                .channel(data_channel_label)
                .await
                .expect("Cannot create data channel.");

            return (client_connection, data_channel);
        }),
        tokio::spawn(async move {
            let mut on_remote_channel = server_connection.on_remote_channel()
                .expect("Cannot get \"on_remote_channel\" stream.");

            while let Some(channel) = on_remote_channel.recv().await {
                server_connection.off_remote_channel(on_remote_channel).unwrap();

                return (server_connection, channel);
            }

            panic!("Failed to receive a remote data channel.");
        }),
    ).unwrap();

    return (client_channel, server_channel);
}

/// Creates a vector of `channels_count` data channels on a single connection.
pub async fn create_channels(
    channels_count: usize,
) -> Vec<(TChannel, TChannel)> {
    // create connection
    let (
        mut client_connection,
        mut server_connection,
    ) = create_connection_pair().await;

    let channels = {
        let mut result = vec![];

        for _ in 0..channels_count {
            let (
                (client_connection2, client_channel),
                (server_connection2, server_channel)) = create_channel_pair(
                client_connection,
                server_connection,
            ).await;

            client_connection = client_connection2;
            server_connection = server_connection2;
    
            result.push((client_channel, server_channel));
        }

        result
    };

    return channels;
}