diff --git a/src/comm_types.rs b/src/comm_types.rs index d1ccd14..dd2dcae 100644 --- a/src/comm_types.rs +++ b/src/comm_types.rs @@ -1,3 +1,5 @@ +use matrix_sdk::identifiers::RoomId; + #[derive(Clone, Debug)] pub struct TurnAuth { @@ -26,7 +28,8 @@ pub struct CallCandidateDesc { #[derive(Clone, Debug)] pub enum MatrixToCallManager { - StartActive(String), + StartActive(Box, String), + AnswerCall(String), IceCandidate(Vec), CloseActive(), TriggerCall(Option), diff --git a/src/matrixbot.rs b/src/matrixbot.rs index 80c6851..f26ea0a 100644 --- a/src/matrixbot.rs +++ b/src/matrixbot.rs @@ -6,7 +6,7 @@ use crate::{ config, }; use async_trait::async_trait; -use crossbeam_channel::{Receiver, Sender}; +use crossbeam_channel::{select, Receiver, Sender}; use js_int::UInt; use matrix_sdk::{ self, @@ -31,6 +31,7 @@ use matrix_sdk::{ Client, ClientConfig, EventEmitter, JsonStore, Room, Sas, SyncRoom, SyncSettings, }; use std::sync::Arc; +use tokio::{join, task, time::Duration}; use url::Url; // get the functions i need from my gstream module #[derive(Debug)] @@ -99,7 +100,7 @@ async fn handle_call_invite( _call_id: String, user: String, _server: String, - _offer: SessionDescription, + offer: SessionDescription, ) { let myself = client.user_id().await.unwrap(); @@ -107,25 +108,20 @@ async fn handle_call_invite( println!("Incoming call from {}", user); let message = MessageEventContent::Text(TextMessageEventContent { - body: format!("🎉🎊🥳 let's PARTY!! 🥳🎊🎉 {:?}", myself), /* This is renderng weirdly in vscode, - * ignore the spaces for my sanity */ + body: format!("Got call invite, trying to setup gst {:?}", myself), /* This is renderng weirdly in vscode, + * ignore the spaces for my sanity */ formatted: None, relates_to: None, }); - //client.share_group_session(room_id); - let encrypted = { - let room = client.get_joined_room(room_id).await; - match room { - Some(r) => r.read().await.is_encrypted(), - None => false, - } - }; - - println!("Encrypted?: {:?}", encrypted); + let offer_sdp: String = offer.sdp; + // Do the naive thing and just box a clone of the room to send + // This'll let us not have to worry about the lifetime on this side + let boxed_room = Box::new(room_id.clone()); client.room_send(room_id, message, None).await.unwrap(); + sender.send(StartActive(boxed_room, offer_sdp)).unwrap(); } async fn handle_call_answer( @@ -140,28 +136,17 @@ async fn handle_call_answer( { let myself = client.user_id().await.unwrap(); - println!("Incoming call from {}", user); + println!("Call Answer from {}", user); let message = MessageEventContent::Text(TextMessageEventContent { - body: format!("🎉🎊🥳 let's PARTY!! 🥳🎊🎉 {:?}", myself), /* This is renderng weirdly in vscode, - * ignore the spaces for my sanity */ + body: format!("got call answer, trying to accept {:?}", myself), /* This is renderng weirdly in vscode, + * ignore the spaces for my sanity */ formatted: None, relates_to: None, }); - //client.share_group_session(room_id); - let encrypted = { - let room = client.get_joined_room(room_id).await; - - match room { - Some(r) => r.read().await.is_encrypted(), - None => false, - } - }; - - println!("Encrypted?: {:?}", encrypted); - client.room_send(room_id, message, None).await.unwrap(); + sender.send(AnswerCall(answer.sdp)).unwrap(); } async fn handle_call_candidate( @@ -193,7 +178,7 @@ async fn handle_call_candidate( index: u64::from(item.sdp_m_line_index), }) .collect(); - let cm_message = MatrixToCallManager::IceCandidate(candidates_desc); + let cm_message = IceCandidate(candidates_desc); sender.send(cm_message).unwrap(); @@ -211,28 +196,17 @@ async fn handle_call_hangup( { let myself = client.user_id().await.unwrap(); - println!("Incoming call from {}", user); + println!("Call hangup from {}", user); let message = MessageEventContent::Text(TextMessageEventContent { - body: format!("🎉🎊🥳 let's PARTY!! 🥳🎊🎉 {:?}", myself), /* This is renderng weirdly in vscode, - * ignore the spaces for my sanity */ + body: format!("You hung up on me :( {:?}", myself), /* This is renderng weirdly in vscode, + * ignore the spaces for my sanity */ formatted: None, relates_to: None, }); - //client.share_group_session(room_id); - let encrypted = { - let room = client.get_joined_room(room_id).await; - - match room { - Some(r) => r.read().await.is_encrypted(), - None => false, - } - }; - - println!("Encrypted?: {:?}", encrypted); - client.room_send(room_id, message, None).await.unwrap(); + sender.send(CloseActive()).unwrap(); } #[async_trait] @@ -356,172 +330,185 @@ pub async fn sync_and_loop( // needed this to get it to stop complaining about the move below, /me shrugs let sender = &sender_channel.clone(); - client - .sync_forever(settings, async move |response| { - let client = &client_ref; + let sync_forever_fut = client.sync_forever(settings, async move |response| { + let client = &client_ref; - for event in &response.to_device.events { - let e_maybe = event.deserialize(); + for event in &response.to_device.events { + let e_maybe = event.deserialize(); - match e_maybe { - Ok(AnyToDeviceEvent::KeyVerificationStart(e)) => { - let sas = client - .get_verification(&e.content.transaction_id) - .await - .expect("Sas object wasn't created"); + match e_maybe { + Ok(AnyToDeviceEvent::KeyVerificationStart(e)) => { + let sas = client + .get_verification(&e.content.transaction_id) + .await + .expect("Sas object wasn't created"); - sas.accept().await.unwrap(); + sas.accept().await.unwrap(); + } + + Ok(AnyToDeviceEvent::KeyVerificationKey(e)) => { + let sas = client + .get_verification(&e.content.transaction_id) + .await + .expect("Sas object wasn't created"); + + tokio::spawn(wait_for_confirmation(sas)); + } + + Ok(AnyToDeviceEvent::KeyVerificationMac(e)) => { + let sas = client + .get_verification(&e.content.transaction_id) + .await + .expect("Sas object wasn't created"); + + if sas.is_done() { + print_result(sas); } + } + Ok(_) => (), // Unknown or unhandled event + Err(error) => { + eprintln!("Couldn't deserialize to to-device event: {:?} from {:?}", error, event); + } + } + } - Ok(AnyToDeviceEvent::KeyVerificationKey(e)) => { - let sas = client - .get_verification(&e.content.transaction_id) - .await - .expect("Sas object wasn't created"); + for (room_id, room) in response.rooms.join { + for rawevent in &room.timeline.events { + let event = rawevent.deserialize().unwrap(); - tokio::spawn(wait_for_confirmation(sas)); - } + // Check if it's a message type + if let Message(msg) = event { + match msg { + CallCandidates(e) => { + println!("incoming debug: {:?}", e); - Ok(AnyToDeviceEvent::KeyVerificationMac(e)) => { - let sas = client - .get_verification(&e.content.transaction_id) - .await - .expect("Sas object wasn't created"); + let SyncMessageEvent { + content: CandidatesEventContent { + call_id, candidates, .. + }, + sender: user, + .. + } = e; - if sas.is_done() { - print_result(sas); + let user_id = user.localpart(); + + let user_server = user.server_name(); + + println!("Content: {:?}", call_id); + + handle_call_candidate( + &sender, + client, + &room_id, + call_id, + user_id.to_string(), + user_server.to_string(), + candidates, + ) + .await; } - } - Ok(_) => (), // Unknown or unhandled event - Err(error) => { - eprintln!("Couldn't deserialize to to-device event: {:?} from {:?}", error, event); - } + CallInvite(e) => { + println!("incoming debug: {:?}", e); + + let SyncMessageEvent { + content: InviteEventContent { call_id, offer, .. }, + sender: user, + .. + } = e; + + let user_id = user.localpart(); + + let user_server = user.server_name(); + + println!("Content: {:?}", call_id); + + handle_call_invite( + &sender, + client, + &room_id, + call_id, + user_id.to_string(), + user_server.to_string(), + offer, + ) + .await; + } + CallHangup(e) => { + println!("incoming debug: {:?}", e); + + let SyncMessageEvent { + content: HangupEventContent { call_id, .. }, + sender: user, + .. + } = e; + + let user_id = user.localpart(); + + let user_server = user.server_name(); + + println!("Content: {:?}", call_id); + + handle_call_hangup( + &sender, + client, + &room_id, + call_id, + user_id.to_string(), + user_server.to_string(), + ) + .await; + } + CallAnswer(e) => { + println!("incoming debug: {:?}", e); + + let SyncMessageEvent { + content: AnswerEventContent { call_id, answer, .. }, + sender: user, + .. + } = e; + + let user_id = user.localpart(); + + let user_server = user.server_name(); + + println!("Content: {:?}", call_id); + + handle_call_answer( + &sender, + client, + &room_id, + call_id, + user_id.to_string(), + user_server.to_string(), + answer, + ) + .await; + } + e => { + println!("unhandled debug: {:?}", e); + } + }; + } else { + println!("Got unknown event type here: {:?}", event); } } + } + }); - for (room_id, room) in response.rooms.join { - for rawevent in &room.timeline.events { - let event = rawevent.deserialize().unwrap(); + let cm_task_fut = tokio::task::spawn(async move { + loop { + select!( + recv(receiver_channel) -> msg => match msg { + e => println!("DEBUG: {:?}", e), + }, + default(Duration::from_secs(1)) => println!("heartbeat"), + ); + tokio::task::yield_now().await; + } + }); - // Check if it's a message type - if let Message(msg) = event { - match msg { - CallCandidates(e) => { - println!("incoming debug: {:?}", e); - - let SyncMessageEvent { - content: CandidatesEventContent { - call_id, candidates, .. - }, - sender: user, - .. - } = e; - - let user_id = user.localpart(); - - let user_server = user.server_name(); - - println!("Content: {:?}", call_id); - - handle_call_candidate( - &sender, - client, - &room_id, - call_id, - user_id.to_string(), - user_server.to_string(), - candidates, - ) - .await; - } - CallInvite(e) => { - println!("incoming debug: {:?}", e); - - let SyncMessageEvent { - content: InviteEventContent { call_id, offer, .. }, - sender: user, - .. - } = e; - - let user_id = user.localpart(); - - let user_server = user.server_name(); - - println!("Content: {:?}", call_id); - - handle_call_invite( - &sender, - client, - &room_id, - call_id, - user_id.to_string(), - user_server.to_string(), - offer, - ) - .await; - } - CallHangup(e) => { - println!("incoming debug: {:?}", e); - - let SyncMessageEvent { - content: HangupEventContent { call_id, .. }, - sender: user, - .. - } = e; - - let user_id = user.localpart(); - - let user_server = user.server_name(); - - println!("Content: {:?}", call_id); - - handle_call_hangup( - &sender, - client, - &room_id, - call_id, - user_id.to_string(), - user_server.to_string(), - ) - .await; - } - CallAnswer(e) => { - println!("incoming debug: {:?}", e); - - let SyncMessageEvent { - content: AnswerEventContent { call_id, answer, .. }, - sender: user, - .. - } = e; - - let user_id = user.localpart(); - - let user_server = user.server_name(); - - println!("Content: {:?}", call_id); - - handle_call_answer( - &sender, - client, - &room_id, - call_id, - user_id.to_string(), - user_server.to_string(), - answer, - ) - .await; - } - e => { - println!("unhandled debug: {:?}", e); - } - }; - } else { - println!("Got unknown event type here: {:?}", event); - } - } - } - }) - .await; + // TODO check for errors + let (_r1, _r2) = join!(sync_forever_fut, cm_task_fut); Ok(()) }