diff --git a/README.md b/README.md index be1a445..cc587bb 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,18 @@ The softphone exposes the following resources on port `6060`. Break specified call_id out of conference +/calls/{call_id}/join/{call_to_join_id} +POST + +Merges the current call (call_id) with another running call (call_to_join_id) + + +/calls/{call_id}/unjoin/{call_to_unjoin_id} +POST + +Break specified call_id out of conference with call_to_unjoin_id + + /calls/{call_id}/transfer POST diff --git a/tinyphone/phone.cpp b/tinyphone/phone.cpp index b43be6a..be580ec 100644 --- a/tinyphone/phone.cpp +++ b/tinyphone/phone.cpp @@ -531,5 +531,59 @@ namespace tp { return true; } -} + bool TinyPhone::Join(SIPCall* call, SIPCall* call_to_join) { + try { + call_to_join->UnHoldCall(); + } catch(...) { + PJ_LOG(3, (__FILENAME__, "TinyPhone::Join UnHoldCall Error")); + return false; + } + + AudioMedia aud_med, aud_med2; + try { + aud_med = call->getAudioMedia(-1); + aud_med2 = call_to_join->getAudioMedia(-1); + } catch(...) { + PJ_LOG(3, (__FILENAME__, "TinyPhone::Join getAudioMedia Error")); + return false; + } + + try { + aud_med.startTransmit(aud_med2); + aud_med2.startTransmit(aud_med); + } catch(...) { + PJ_LOG(3, (__FILENAME__, "TinyPhone::Join startTransmit Error")); + return false; + } + + return true; + } + bool TinyPhone::Unjoin(SIPCall* call, SIPCall* call_to_unjoin) { + try { + call_to_unjoin->HoldCall(); + } catch(...) { + PJ_LOG(3, (__FILENAME__, "TinyPhone::Unjoin HoldCall Error")); + return false; + } + + AudioMedia aud_med, aud_med2; + try { + aud_med = call->getAudioMedia(-1); + aud_med2 = call_to_unjoin->getAudioMedia(-1); + } catch(...) { + PJ_LOG(3, (__FILENAME__, "TinyPhone::Unjoin getAudioMedia Error")); + return false; + } + + try { + aud_med.stopTransmit(aud_med2); + aud_med2.stopTransmit(aud_med); + } catch(...) { + PJ_LOG(3, (__FILENAME__, "TinyPhone::Unjoin stopTransmit Error")); + return false; + } + + return true; + } +} diff --git a/tinyphone/phone.h b/tinyphone/phone.h index 52f4f62..bd1914d 100644 --- a/tinyphone/phone.h +++ b/tinyphone/phone.h @@ -122,6 +122,9 @@ namespace tp { bool Conference(SIPCall* call); bool BreakConference(SIPCall* call); + + bool Join(SIPCall* call, SIPCall* call_to_join); + bool Unjoin(SIPCall* call, SIPCall* call_to_unjoin); void HangupAllCalls(); diff --git a/tinyphone/server.cpp b/tinyphone/server.cpp index d967f49..5f124cf 100644 --- a/tinyphone/server.cpp +++ b/tinyphone/server.cpp @@ -591,7 +591,95 @@ void TinyPhoneHttpServer::Start() { return tp::response(200, response); } }); - + + CROW_ROUTE(app, "/calls//join/") + .methods("POST"_method) + ([&phone](int call_id, int call_to_join_id) { + pj_thread_auto_register(); + + SIPCall* call = phone.CallById(call_id); + SIPCall* call_to_join = phone.CallById(call_to_join_id); + + if (call == nullptr) { + return tp::response(400, { + { "message", "Current Call Not Found" }, + { "call_id" , call_id }, + { "call_to_join_id" , call_to_join_id }, + }); + } + else if (call_to_join == nullptr) { + return tp::response(400, { + { "message", "Call To Join Not Found" }, + { "call_id" , call_id }, + { "call_to_join_id" , call_to_join_id } + }); + } + else if (call->HoldState() == +HoldStatus::LOCAL_HOLD) { + json response = { + { "message", "Bad Request, CallOnHold Currently" }, + { "call_id" , call_id }, + { "call_to_join_id" , call_to_join_id }, + { "status", "400" } + }; + + return tp::response(400, response); + } + else { + json response = { + { "message", "Calls Join Triggered" }, + { "call_id" , call_id }, + { "call_to_join_id" , call_to_join_id }, + { "response", phone.Join(call, call_to_join) } + }; + + return tp::response(200, response); + } + }); + + CROW_ROUTE(app, "/calls//unjoin/") + .methods("POST"_method) + ([&phone](int call_id, int call_to_unjoin_id) { + pj_thread_auto_register(); + + SIPCall* call = phone.CallById(call_id); + SIPCall* call_to_unjoin = phone.CallById(call_to_unjoin_id); + + if (call == nullptr) { + return tp::response(400, { + { "message", "Current Call Not Found" }, + { "call_id" , call_id }, + { "call_to_unjoin_id" , call_to_unjoin_id }, + }); + } + else if (call_to_unjoin == nullptr) { + return tp::response(400, { + { "message", "Call To Unjoin Not Found" }, + { "call_id" , call_id }, + { "call_to_unjoin_id" , call_to_unjoin_id } + }); + } + else if (call->HoldState() == +HoldStatus::LOCAL_HOLD) { + json response = { + { "message", "Bad Request, CallOnHold Currently" }, + { "call_id" , call_id }, + { "call_to_unjoin_id" , call_to_unjoin_id }, + { "status", "400" } + }; + + return tp::response(400, response); + } + else { + json response = { + { "message", "Calls Unjoin Triggered" }, + { "call_id" , call_id }, + { "call_to_unjoin_id" , call_to_unjoin_id }, + { "response", phone.Unjoin(call, call_to_unjoin) } + }; + + return tp::response(200, response); + } + }); + CROW_ROUTE(app, "/calls//transfer") .methods("POST"_method) ([&phone](const crow::request& req, int call_id) {