From edcccf85f6b564811f6cfa2a55cb2b9acc962c63 Mon Sep 17 00:00:00 2001
From: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
Date: Fri, 15 Apr 2011 17:02:33 -0400
Subject: [PATCH] [#5571] Handle exception when SDP negotiation fails

---
 sflphone-common/src/iax/iaxvoiplink.cpp |  2 +-
 sflphone-common/src/iax/iaxvoiplink.h   |  2 +-
 sflphone-common/src/managerimpl.cpp     | 13 ++++---
 sflphone-common/src/sip/sipvoiplink.cpp | 50 +++++++++++--------------
 sflphone-common/src/sip/sipvoiplink.h   | 14 +++----
 sflphone-common/src/voiplink.h          |  2 +-
 6 files changed, 39 insertions(+), 44 deletions(-)

diff --git a/sflphone-common/src/iax/iaxvoiplink.cpp b/sflphone-common/src/iax/iaxvoiplink.cpp
index 51cbd95f63..079a968f2b 100644
--- a/sflphone-common/src/iax/iaxvoiplink.cpp
+++ b/sflphone-common/src/iax/iaxvoiplink.cpp
@@ -513,7 +513,7 @@ IAXVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl) throw(
 
 
 bool
-IAXVoIPLink::answer (const CallID& id)
+IAXVoIPLink::answer (const CallID& id) throw (VoipLinkException)
 {
     IAXCall* call = getIAXCall (id);
     call->setCodecMap (Manager::instance().getCodecDescriptorMap());
diff --git a/sflphone-common/src/iax/iaxvoiplink.h b/sflphone-common/src/iax/iaxvoiplink.h
index e516f457a7..7efba3be40 100644
--- a/sflphone-common/src/iax/iaxvoiplink.h
+++ b/sflphone-common/src/iax/iaxvoiplink.h
@@ -120,7 +120,7 @@ class IAXVoIPLink : public VoIPLink
          * @return bool true on success
          *		  false otherwise
          */
-        virtual bool answer (const CallID& id);
+        virtual bool answer (const CallID& id) throw (VoipLinkException);
 
         /**
          * Hangup a call
diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp
index 5253480a3d..fedd051993 100644
--- a/sflphone-common/src/managerimpl.cpp
+++ b/sflphone-common/src/managerimpl.cpp
@@ -363,11 +363,14 @@ bool ManagerImpl::answerCall (const CallID& call_id)
         }
 
     }
-
-    if (!getAccountLink (account_id)->answer (call_id)) {
-        // error when receiving...
-        removeCallAccount (call_id);
-        return false;
+    try {
+        if (!getAccountLink (account_id)->answer (call_id)) {
+            removeCallAccount (call_id);
+            return false;
+        }
+    }
+    catch(VoipLinkException &e) {
+    	_error("Manager: Error: %s", e.what());
     }
 
     // if it was waiting, it's waiting no more
diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp
index a3f5bf8ee6..01c2082ab6 100644
--- a/sflphone-common/src/sip/sipvoiplink.cpp
+++ b/sflphone-common/src/sip/sipvoiplink.cpp
@@ -636,7 +636,7 @@ void SIPVoIPLink::sendUnregister (AccountID id) throw(VoipLinkException)
     account->setRegister (false);
 }
 
-Call *SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl) throw (VoipLinkException) // throw (SIPVoipLinkException)
+Call *SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl) throw (VoipLinkException)
 {
     SIPAccount * account = NULL;
     pj_status_t status;
@@ -727,7 +727,7 @@ Call *SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl)
 }
 
 bool
-SIPVoIPLink::answer (const CallID& id)
+SIPVoIPLink::answer (const CallID& id) throw (VoipLinkException)
 {
     pj_status_t status = PJ_SUCCESS;
     pjsip_tx_data *tdata;
@@ -737,49 +737,41 @@ SIPVoIPLink::answer (const CallID& id)
 
     SIPCall *call = getSIPCall (id);
 
-//    AccountID account_id = Manager::instance().getAccountFromCall (id);
-//    SIPAccount *account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (account_id));
-
-    if (call==0) {
-        _debug ("UserAgent: SIPCall %s doesn't exists while answering", id.c_str());
-        return false;
+    if (call==NULL) {
+        throw VoipLinkException("Call is NULL while answering");
     }
 
     inv_session = call->getInvSession();
 
-//    if (! (account->getServiceRoute().empty())) {
-//
-//        pjsip_route_hdr *route_set = createRouteSet(account);
-//        pjsip_dlg_set_route_set (inv_session->dlg, route_set);
-//    }
-
     if (status == PJ_SUCCESS) {
 
-        _debug ("SIPVoIPLink: UserAgent: SDP Negociation success! : call %s ", call->getCallId().c_str());
+        _debug ("UserAgent: SDP Negociation success! : call %s ", call->getCallId().c_str());
         // Create and send a 200(OK) response
-        status = pjsip_inv_answer (inv_session, PJSIP_SC_OK, NULL, NULL, &tdata);
-        PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
-        status = pjsip_inv_send_msg (inv_session, tdata);
-        PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
+        if((status = pjsip_inv_answer (inv_session, PJSIP_SC_OK, NULL, NULL, &tdata)) != PJ_SUCCESS) {
+        	throw VoipLinkException("Could not init invite request answer (200 OK)");
+        }
+        if((status = pjsip_inv_send_msg (inv_session, tdata)) != PJ_SUCCESS) {
+        	throw VoipLinkException("Could not send invite request answer (200 OK)");
+        }
 
         call->setConnectionState (Call::Connected);
         call->setState (Call::Active);
 
         return true;
     } else {
-        // Create and send a 488/Not acceptable here
-        // because the SDP negociation failed
-        status = pjsip_inv_answer (inv_session, PJSIP_SC_NOT_ACCEPTABLE_HERE, NULL, NULL,
-                                   &tdata);
-        PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
-        status = pjsip_inv_send_msg (inv_session, tdata);
-        PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
-
+        // Create and send a 488/Not acceptable because the SDP negociation failed
+        if((status = pjsip_inv_answer (inv_session, PJSIP_SC_NOT_ACCEPTABLE_HERE, NULL, NULL, &tdata)) != PJ_SUCCESS) {
+        	throw VoipLinkException("Could not init invite answer (488 not acceptable here)");
+        }
+        if((status = pjsip_inv_send_msg (inv_session, tdata)) != PJ_SUCCESS) {
+        	throw VoipLinkException("Could not init invite request answer (488 NOT ACCEPTABLE HERE)");
+        }
         // Terminate the call
-        _debug ("SIPVoIPLink: UserAgent: SDP Negociation failed, terminate call %s ", call->getCallId().c_str());
+        _debug ("UserAgent: SDP Negociation failed, terminate call %s ", call->getCallId().c_str());
 
-        if (call->getAudioRtp())
+        if (call->getAudioRtp()) {
             call->getAudioRtp()->stop ();
+        }
 
         removeCall (call->getCallId());
 
diff --git a/sflphone-common/src/sip/sipvoiplink.h b/sflphone-common/src/sip/sipvoiplink.h
index f418463cf0..76fc825538 100644
--- a/sflphone-common/src/sip/sipvoiplink.h
+++ b/sflphone-common/src/sip/sipvoiplink.h
@@ -35,9 +35,9 @@
 #ifndef SIPVOIPLINK_H
 #define SIPVOIPLINK_H
 
-#include "voiplink.h"
-#include "hooks/urlhook.h"
-#include "../im/InstantMessaging.h"
+#include <map>
+#include <sstream>
+#include <exception>
 
 //////////////////////////////
 /* PJSIP imports */
@@ -48,9 +48,9 @@
 #include <pjnath/stun_config.h>
 ///////////////////////////////
 
-#include <map>
-#include <sstream>
-#include <exception>
+#include "voiplink.h"
+#include "hooks/urlhook.h"
+#include "../im/InstantMessaging.h"
 
 class EventThread;
 class SIPCall;
@@ -162,7 +162,7 @@ class SIPVoIPLink : public VoIPLink
          * @param id The call identifier
          * @return int True on success
          */
-        virtual bool answer (const CallID& id);
+        virtual bool answer (const CallID& id) throw (VoipLinkException);
 
         /**
          * Hang up the call
diff --git a/sflphone-common/src/voiplink.h b/sflphone-common/src/voiplink.h
index abe68c5bbf..2b1cefd6b9 100644
--- a/sflphone-common/src/voiplink.h
+++ b/sflphone-common/src/voiplink.h
@@ -134,7 +134,7 @@ class VoIPLink
          * @param id The call identifier
          * @return bool True on success
          */
-        virtual bool answer (const CallID& id) = 0;
+        virtual bool answer (const CallID& id) throw (VoipLinkException) = 0;
 
         /**
          * Hang up a call
-- 
GitLab