[asterisk-scf-commits] asterisk-scf/integration/sip.git branch "error-handling" created.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Wed Dec 21 17:01:02 CST 2011


branch "error-handling" has been created
        at  ebd73dfcec878ee6d776aa8d2e55180dc9fc31c4 (commit)

- Log -----------------------------------------------------------------
commit ebd73dfcec878ee6d776aa8d2e55180dc9fc31c4
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Dec 21 16:33:18 2011 -0600

    Add handling to the client registration code.

diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
index 7bd036c..25e2bed 100644
--- a/src/SipClientRegistration.cpp
+++ b/src/SipClientRegistration.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "SipClientRegistration.h"
+#include "PJUtil.h"
 #include <boost/numeric/conversion/cast.hpp>
 
 using namespace AsteriskSCF::System::Logging;
@@ -157,7 +158,11 @@ void SipRegistrationClient::createPJSIPRegistration(
         pjsip_endpoint *pjEndpoint,
         const SipEndpointPtr& sipEndpoint)
 {
-    pjsip_regc_create(pjEndpoint, this, regCallback, &mReg);
+    if (fail(pjsip_regc_create(pjEndpoint, this, regCallback, &mReg)))
+    {
+        lg(Warning) << "Unable to create client registration for endpoint " << sipEndpoint->getName();
+        return;
+    }
 
     std::vector<pj_str_t> pjContacts;
     std::transform(confItem->contacts.begin(), confItem->contacts.end(), std::back_inserter(pjContacts), MakeContact(mReg));
@@ -178,7 +183,7 @@ void SipRegistrationClient::createPJSIPRegistration(
     pj_str_t fromURL;
     pj_strdup2(pjsip_regc_get_pool(mReg), &fromURL, confItem->aor.c_str());
 
-    pjsip_regc_init(
+    if (fail(pjsip_regc_init(
             mReg,
             &serverURL,
             &fromURL,
@@ -186,7 +191,10 @@ void SipRegistrationClient::createPJSIPRegistration(
             boost::numeric_cast<int>(pjContacts.size()),
             &pjContacts.front(),
             confItem->defaultExpiration
-            );
+            )))
+    {
+        lg(Warning) << "Unable to initialize client registration for endpoint " << sipEndpoint->getName();
+    }
 
     setContacts(confItem->contacts);
 }
@@ -201,8 +209,10 @@ void SipRegistrationClient::destroy()
 void SipRegistrationClient::destroyPJSIPRegistration()
 {
     pjsip_tx_data *tdata;
-    pjsip_regc_unregister(mReg, &tdata);
-    pjsip_regc_send(mReg, tdata);
+    if (success(pjsip_regc_unregister(mReg, &tdata)))
+    {
+        pjsip_regc_send(mReg, tdata);
+    }
 
     pjsip_regc_destroy(mReg);
 }
@@ -260,11 +270,20 @@ void SipRegistrationClient::sendRegister()
     std::vector<pj_str_t> contacts;
     std::transform(mContacts.begin(), mContacts.end(), std::back_inserter(contacts), MakeContact(mReg));
 
-    pjsip_regc_update_contact(mReg, boost::numeric_cast<int>(contacts.size()), &contacts.front());
+    if (fail(pjsip_regc_update_contact(mReg, boost::numeric_cast<int>(contacts.size()), &contacts.front())))
+    {
+        lg(Warning) << "Unable to update contacts for client registration for endpoint " << mEndpointName;
+    }
 
     pjsip_tx_data *tdata;
-    pjsip_regc_register(mReg, PJ_TRUE, &tdata);
-    pjsip_regc_send(mReg, tdata);
+    if (success(pjsip_regc_register(mReg, PJ_TRUE, &tdata)))
+    {
+        pjsip_regc_send(mReg, tdata);
+    }
+    else
+    {
+        lg(Warning) << "Unable to create outbound REGISTER request for endpoint " << mEndpointName;
+    }
 }
 
 void SipRegistrationClient::handleRegisterResponse(pjsip_regc_cbparam *param)
@@ -307,18 +326,16 @@ void SipRegistrationClient::handleRegisterResponse(pjsip_regc_cbparam *param)
     }
 }
 
-//XXX This function seems like it may fit better into AuthManager
-//or some more central place since it could be useful for authentication
-//responses for any type of request. This is mostly not REGISTER-specific, in
-//other words.
 void SipRegistrationClient::authenticate(pjsip_rx_data *rdata)
 {
     std::vector<pjsip_cred_info> creds;
     mManager->getAuthCredentials(rdata, creds, mEndpointName);
     if (!creds.empty())
     {
-        pjsip_regc_set_credentials(mReg, boost::numeric_cast<int>(creds.size()), &creds.front());
-        sendRegister();
+        if (success(pjsip_regc_set_credentials(mReg, boost::numeric_cast<int>(creds.size()), &creds.front())))
+        {
+            sendRegister();
+        }
     }
     return;
 }
diff --git a/src/SipTransfer.cpp b/src/SipTransfer.cpp
index 4aab2f5..9ff5140 100644
--- a/src/SipTransfer.cpp
+++ b/src/SipTransfer.cpp
@@ -138,9 +138,8 @@ void TransferListener::indicated(
         pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq, false);
         if (tdata)
         {
-            //XXX We could stand to add more possible responses here, but for now
-            //just getting things working is my top priority, and we conform to
-            //RFC 3515.
+            //We could stand to add more possible responses here, but these
+            //are enough to conform to RFC 3515.
             switch (stopped->response->isdnCode)
             {
                 //Busy

commit 42cae73f7b36c51647d18de0c893bc32b2b3040f
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Dec 21 15:18:14 2011 -0600

    Add some error handling in the transfer code.

diff --git a/src/SipTransfer.cpp b/src/SipTransfer.cpp
index bb35b4b..4aab2f5 100644
--- a/src/SipTransfer.cpp
+++ b/src/SipTransfer.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "SipTransfer.h"
+#include "PJUtil.h"
 
 #include <boost/algorithm/string.hpp>
 #include <IceUtil/UUID.h>
@@ -32,7 +33,11 @@ Logger lg = getLoggerFactory().getLogger("AsteriskSCF.SipSessionGateway");
 pjsip_tx_data* createNotify(pjsip_dialog *dlg, pj_int32_t cseq, bool active)
 {
     pjsip_tx_data *tdata;
-    pjsip_dlg_create_request(dlg, pjsip_get_notify_method(), -1, &tdata);
+    
+    if (AsteriskSCF::SipSessionManager::fail(pjsip_dlg_create_request(dlg, pjsip_get_notify_method(), -1, &tdata)))
+    {
+        return 0;
+    }
 
     pjsip_event_hdr *event = pjsip_event_hdr_create(tdata->pool);
     pj_strdup2(tdata->pool, &event->event_type, "refer");
@@ -120,43 +125,55 @@ void TransferListener::indicated(
     {
         lg(Debug) << "Got the connected indication. Should send a 200 sipfrag NOTIFY";
         pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq, false);
-        addNotifyBody(tdata, "SIP/2.0 200 OK");
-        pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
+        if (tdata)
+        {
+            addNotifyBody(tdata, "SIP/2.0 200 OK");
+            pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
+        }
         shutdown(source);
     }
     else if ((stopped = StoppedIndicationPtr::dynamicCast(event)))
     {
         lg(Debug) << "Got the stopped indication. Should send some sort of final response sipfrag NOTIFY";
         pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq, false);
-        //XXX We could stand to add more possible responses here, but for now
-        //just getting things working is my top priority, and we conform to
-        //RFC 3515.
-        switch (stopped->response->isdnCode)
+        if (tdata)
         {
-            //Busy
-            case 17:
-                addNotifyBody(tdata, "SIP/2.0 486 Busy Here");
-            //RFC 3515 section 2.4.5 says that we can send a 503 for any reference
-            //that fails.
-            default:
-                addNotifyBody(tdata, "SIP/2.0 503 Service Unavailable");
+            //XXX We could stand to add more possible responses here, but for now
+            //just getting things working is my top priority, and we conform to
+            //RFC 3515.
+            switch (stopped->response->isdnCode)
+            {
+                //Busy
+                case 17:
+                    addNotifyBody(tdata, "SIP/2.0 486 Busy Here");
+                //RFC 3515 section 2.4.5 says that we can send a 503 for any reference
+                //that fails.
+                default:
+                    addNotifyBody(tdata, "SIP/2.0 503 Service Unavailable");
+            }
+            pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
         }
-        pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
         shutdown(source);
     }
     else if ((ringing = RingingIndicationPtr::dynamicCast(event)))
     {
         lg(Debug) << "Got a ringing indication. Should send a 180 sipfrag NOTIFY";
         pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq, true);
-        addNotifyBody(tdata, "SIP/2.0 180 Ringing");
-        pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
+        if (tdata)
+        {
+            addNotifyBody(tdata, "SIP/2.0 180 Ringing");
+            pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
+        }
     }
     else if ((progressing = ProgressingIndicationPtr::dynamicCast(event)))
     {
         lg(Debug) << "Got a progressing indication. Should send a 183 sipfrag NOTIFY";
         pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq, true);
-        addNotifyBody(tdata, "SIP/2.0 183 Session Progress");
-        pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
+        if (tdata)
+        {
+            addNotifyBody(tdata, "SIP/2.0 183 Session Progress");
+            pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
+        }
     }
 }
 
@@ -516,8 +533,11 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
             
             //Go ahead and send the 100 Trying sipfrag
             pjsip_tx_data *tdata = createNotify(mInv->dlg, mReferCSeq, true);
-            addNotifyBody(tdata, "SIP/2.0 100 Trying");
-            pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+            if (tdata)
+            {
+                addNotifyBody(tdata, "SIP/2.0 100 Trying");
+                pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+            }
 
             mSessionRouter->begin_connectBridgedSessionsWithDestination(operationId, session->getSessionProxy(), mTarget, false, mHook->getProxy(), d);
             return Complete;
@@ -551,8 +571,11 @@ SuspendableWorkResult HandleReferOperation::calledBack(const Ice::AsyncResultPtr
     {
         lg(Debug) << "ConnectBridgedSessionsWithDestination sending 404 due to destination not found.";
         pjsip_tx_data *tdata = createNotify(mInv->dlg, mReferCSeq, false);
-        addNotifyBody(tdata, "SIP/2.0 404 Not Found");
-        pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+        if (tdata)
+        {
+            addNotifyBody(tdata, "SIP/2.0 404 Not Found");
+            pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+        }
         //Only blind transfers have the session creation hook to get rid of
         if (mBlindTransfer)
         {
@@ -564,8 +587,11 @@ SuspendableWorkResult HandleReferOperation::calledBack(const Ice::AsyncResultPtr
     {
         lg(Debug) << "ConnectBridgedSessionsCallback sending 400 due to exception:  " << e.what();
         pjsip_tx_data *tdata = createNotify(mInv->dlg, mReferCSeq, false);
-        addNotifyBody(tdata, "SIP/2.0 400 Bad Request");
-        pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+        if (tdata)
+        {
+            addNotifyBody(tdata, "SIP/2.0 400 Bad Request");
+            pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+        }
         //Only blind transfers have the session creation hook to get rid of
         if (mBlindTransfer)
         {
@@ -581,8 +607,11 @@ SuspendableWorkResult HandleReferOperation::calledBack(const Ice::AsyncResultPtr
     if (!mBlindTransfer)
     {
         pjsip_tx_data *tdata = createNotify(mInv->dlg, mReferCSeq, false);
-        addNotifyBody(tdata, "SIP/2.0 200 OK");
-        pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+        if (tdata)
+        {
+            addNotifyBody(tdata, "SIP/2.0 200 OK");
+            pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+        }
     }
     return Complete;
 }

commit 4a89ea9575ab09615b34115caf3c3eb026e760b3
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Dec 21 14:47:22 2011 -0600

    Add some protection against failure returns from PJSIP calls in the registrar.

diff --git a/src/PJSipRegistrarModule.cpp b/src/PJSipRegistrarModule.cpp
index 99704d1..0b4f8ed 100644
--- a/src/PJSipRegistrarModule.cpp
+++ b/src/PJSipRegistrarModule.cpp
@@ -24,6 +24,7 @@
 #include "PJSipRegistrarModule.h"
 #include "PJSipManager.h"
 #include "SipReplicationContext.h"
+#include "PJUtil.h"
 
 using namespace AsteriskSCF::SIP::Registration::V1;
 using namespace AsteriskSCF::System::Logging;
@@ -465,9 +466,6 @@ void PJSipRegistrarModule::replicateState(
     mRegistrar->getQueue()->enqueueWork(new ReplicateState(mReplicationContext, aor, existingBindings, newBindings, removedBindings, mRegistrar));
 }
 
-//XXX This and the method that queues this work should
-//have different names. It's easy to get confused with
-//UpdateBinding, and this could stand to be more descriptive
 class AddAndRemoveBindings : public Work
 {
 public:
@@ -730,11 +728,17 @@ bool PJSipRegistrarModule::checkAuth(pjsip_rx_data *rdata, pjsip_transaction *ts
     }
 
     pjsip_tx_data *tdata;
-    pjsip_endpt_create_response(tsx->endpt, rdata, 401, NULL, &tdata);
+    if (fail(pjsip_endpt_create_response(tsx->endpt, rdata, 401, NULL, &tdata)))
+    {
+        return false;
+    }
     
     authInstance->addDigests(tdata, digests);
     
-    pjsip_tsx_send_msg(tsx, tdata);
+    if (fail(pjsip_tsx_send_msg(tsx, tdata)))
+    {
+        return false;
+    }
     
     mAuthManager->scheduleAuthTimeout(authInstance, registrarAuthTimeout);
     return true;
@@ -755,7 +759,11 @@ pj_bool_t PJSipRegistrarModule::on_rx_request(pjsip_rx_data *rdata)
     lg(Debug) << "Registrar Module handling a new incoming REGISTER request";
 
     pjsip_transaction *tsx;
-    pjsip_tsx_create_uas(&mModule, rdata, &tsx);
+    if (fail(pjsip_tsx_create_uas(&mModule, rdata, &tsx)))
+    {
+        return PJ_TRUE;
+    }
+
     pjsip_tsx_recv_msg(tsx, rdata);
 
     if (checkAuth(rdata, tsx, NonDialog))
@@ -783,8 +791,11 @@ pj_bool_t PJSipRegistrarModule::on_rx_request(pjsip_rx_data *rdata)
     if (!verifyContacts(registerContacts))
     {
         pjsip_tx_data *tdata;
-        pjsip_endpt_create_response(tsx->endpt, rdata, 400, NULL, &tdata);
-        pjsip_tsx_send_msg(tsx, tdata);
+        if (success(pjsip_endpt_create_response(tsx->endpt, rdata, 400, NULL, &tdata)))
+        {
+            pjsip_tsx_send_msg(tsx, tdata);
+        }
+        return PJ_TRUE;
     }
 
     BindingWrapperSeq newBindings;
@@ -819,15 +830,17 @@ pj_bool_t PJSipRegistrarModule::on_rx_request(pjsip_rx_data *rdata)
         }
     }
 
-    mRegistrar->addAndRemoveBindings(aor, newBindings, removedBindings, mRegistrar->getQueue());
-
     // We enqueue the SIP response to make sure we send it and replicate state AFTER we have updated
     // our internal bindings.
     pjsip_tx_data *tdata;
-    pjsip_endpt_create_response(tsx->endpt, rdata, 200, NULL, &tdata);
-    mRegistrar->getQueue()->enqueueWork(new Response(tsx, tdata, aor, mRegistrar));
+    if (success(pjsip_endpt_create_response(tsx->endpt, rdata, 200, NULL, &tdata)))
+    {
+        mRegistrar->addAndRemoveBindings(aor, newBindings, removedBindings, mRegistrar->getQueue());
 
-    replicateState(aor, existingBindings, newBindings, removedBindings);
+        mRegistrar->getQueue()->enqueueWork(new Response(tsx, tdata, aor, mRegistrar));
+
+        replicateState(aor, existingBindings, newBindings, removedBindings);
+    }
 
     return PJ_TRUE;
 }

commit 13e4e6a3c7f90bb2bd53f9fe87bd51a957cc5742
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Dec 21 11:31:56 2011 -0600

    * Add proper interpretation of SIP response codes
    * Regroup the switch statement in PJSipSessionModule.cpp to be a bit more compact

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 7682e7d..e1766ee 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -1456,20 +1456,15 @@ void PJSipSessionModule::handleInviteResponse(pjsip_inv_session* inv,
 
     ConnectedLinePtr connected = getConnectedID(rdata);
 
-    //Commented because they are currently unused. They
-    //will be once the individual cases are mapped out.
-    //pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
-    //pjsip_module *module = pjsip_ua_instance();
-    //
-    //XXX There are a BUNCH of response codes we need
-    //to add code to handle.
-
     lg(Debug) << "Queuing a HandleInviteResponseOperation";
     enqueueSessionWork(new HandleInviteResponseOperation(respCode, inv->state, session, connected), inv);
 }
 
 //There are some rejection codes that we can actually do something with other than
 //just kill the code.
+//
+//Codes that may not possibly result in retrying the call should not be handled in this
+//function.
 void PJSipSessionModule::handleInviteRejection(pjsip_inv_session* inv,
     pjsip_rx_data* rdata, pjsip_transaction* tsx)
 {
@@ -1587,113 +1582,72 @@ protected:
             //Cause codes for each SIP response are taken from RFC 3398 Section 8.2.6.1 (plus errata ID 2161)
             switch (mInv->cause)
             {
-            case 400: // Bad Request
-                response->isdnCode = 41;
-                break;
-            case 401: // Unauthorized
-                response->isdnCode = 21;
-                break;
-            case 402: // Payment Required
-                response->isdnCode = 21;
-                break;
-            case 403: // Forbidden
-                response->isdnCode = 21;
-                break;
             case 404: // Not Found
+            case 485: // Ambiguous
+            case 604: // Does Not Exist Anymore
                 response->isdnCode = 1;
                 break;
-            case 405: // Method not allowed
-                response->isdnCode = 63;
+            case 486: // Busy Here
+            case 600: // Busy Everywhere
+                response->isdnCode = 17;
                 break;
-            case 406: // Not Acceptable
-                response->isdnCode = 79;
+            case 480: // Temporarily Unavailable
+                response->isdnCode = 18;
                 break;
+            case 401: // Unauthorized
+            case 402: // Payment Required
+            case 403: // Forbidden
             case 407: // Proxy Authentication Required
+            case 603: // Decline
                 response->isdnCode = 21;
                 break;
-            case 408: // Request Timeout
-                response->isdnCode = 102;
-                break;
             case 410: // Gone
                 response->isdnCode = 22;
                 break;
-            case 413: // Request Entity Too Long
-                response->isdnCode = 127;
-                break;
-            case 414: // Request-URI Too Long
-                response->isdnCode = 127;
-                break;
-            case 415: // Unsupported Media Type
-                response->isdnCode = 79;
-                break;
-            case 416: // Unsupported URI Scheme
-                response->isdnCode = 127;
-                break;
-            case 420: // Bad Extension
-                response->isdnCode = 127;
-                break;
-            case 421: // Extension Required
-                response->isdnCode = 127;
-                break;
-            case 423: // Interval Too Brief
-                response->isdnCode = 127;
-                break;
-            case 480: // Temporarily Unavailable
-                response->isdnCode = 18;
-                break;
-            case 481: // Call/Transaction Does Not Exist
-                response->isdnCode = 41;
-                break;
             case 482: // Loop Detected
-                response->isdnCode = 25;
-                break;
             case 483: // Too Many Hops
                 response->isdnCode = 25;
                 break;
             case 484: // Address Incomplete
                 response->isdnCode = 28;
                 break;
-            case 485: // Ambiguous
-                response->isdnCode = 1;
-                break;
-            case 486: // Busy Here
-                response->isdnCode = 17;
+            case 502: // Bad Gateway
+                response->isdnCode = 38;
                 break;
+            case 400: // Bad Request
+            case 481: // Call/Transaction Does Not Exist
             case 500: // Server Internal Error
+            case 503: // Service Unavailable
                 response->isdnCode = 41;
                 break;
+            case 405: // Method not allowed
+                response->isdnCode = 63;
+                break;
+            case 406: // Not Acceptable
+            case 415: // Unsupported Media Type
             case 501: // Not Implemented
                 response->isdnCode = 79;
                 break;
-            case 502: // Bad Gateway
-                response->isdnCode = 38;
-                break;
-            case 503: // Service Unavailable
-                response->isdnCode = 41;
-                break;
+            case 408: // Request Timeout
             case 504: // Server Time-out
                 response->isdnCode = 102;
                 break;
+            case 413: // Request Entity Too Long
+            case 414: // Request-URI Too Long
+            case 416: // Unsupported URI Scheme
+            case 420: // Bad Extension
+            case 421: // Extension Required
+            case 423: // Interval Too Brief
             case 505: // Version Not Supported
-                response->isdnCode = 127;
-                break;
             case 513: // Message Too Large
                 response->isdnCode = 127;
                 break;
-            case 600: // Busy Everywhere
-                response->isdnCode = 17;
-                break;
-            case 603: // Decline
-                response->isdnCode = 21;
-                break;
-            case 604: // Does Not Exist Anymore
-                response->isdnCode = 1;
-                break;
             default:
                 // 487, 488, and 606 have no mapping. Also,
                 // other types of ends to sessions (like normal clearing)
                 // will end up here.
                 response->isdnCode = 0;
+                break;
             }
 
             if (session)
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 2bb6eda..e3fda77 100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -2234,13 +2234,70 @@ public:
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
         pjsip_tx_data *packet;
-        // Assume a 503 until proven otherwise
-        unsigned int code = 503;
+        unsigned int code;
 
-        // TODO: Convert ALL response codes to equivalent SIP ones, and allow configuration to change it
-        if (mResponse->isdnCode == 17)
+        switch (mResponse->isdnCode)
         {
-            code = 486;
+            case 1: // unallocated number
+            case 2: // no route to network
+            case 3: // no route to destination
+            case 26: // non-selected user clearing
+                code = 404;
+                break;
+            case 18: // no user responding
+                code = 408;
+                break;
+            case 21: // call rejected
+            case 55: // incoming calls barred within CUG
+            case 57: // bearer capability not authorized
+            case 87: // user not member of CUG
+                code = 403;
+                break;
+            case 22: // number changed
+            case 23: // redirection to new destination
+                code = 410;
+                break;
+            case 19: // no answer from the user
+            case 20: // subscriber absent
+            case 31: // normal unspecified
+                code = 480;
+                break;
+            case 28: // address incomplete
+                code = 484;
+                break;
+            case 17: // user busy
+                code = 486;
+                break;
+            case 65: // bearer capability not implemented
+            case 70: // only restricted digital avail
+                code = 488;
+                break;
+            case 111: // protocol error
+            case 127: // interworking unspecified
+                code = 500;
+                break;
+            case 29: // facility rejected
+            case 79: // service or option not implemented
+                code = 501;
+                break;
+            case 27: // destination out of order
+                code = 502;
+                break;
+            case 34: // no circuit available
+            case 38: // network out of order
+            case 41: // temporary failure
+            case 42: // switching equipment congestion
+            case 47: // resource unavailable
+            case 58: // bearer capability not presently available
+            case 88: // incompatible destination
+                code = 503;
+                break;
+            case 102: // recovery of timer expiry
+                code = 504;
+                break;
+            default: // everything else...
+                code = 503;
+                break;
         }
 
         // We have to check the existence of packet due to an edge case that we can trigger here.

commit 83eca4eb339607702566d0a4f0eeb34081ed6f59
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Dec 20 18:35:48 2011 -0600

    Add some further failure response code handling for outgoing INVITEs.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 6a49109..7682e7d 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -791,19 +791,6 @@ ConnectedLinePtr PJSipSessionModule::getConnectedID(pjsip_rx_data *rdata)
 
 void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
 {
-    //What do we do here?
-    //
-    //First we need to identify who this is coming from.
-    //If it's someone we recognize, then we can figure
-    //out whether we need to send a 401/407 request.
-    //For now, we don't have any sort of configured users,
-    //so we skip this step. Instead, we'll skip ahead to
-    //creating an endpoint, creating the invite session,
-    //sending a 100 trying, finding the remote endpoint
-    //to call, and placing a call to it.
-
-    //XXX Put caller identification code in here!
-
     //We handle most of the processing here synchronously since
     //at this point there is no associated session, plus the lead-up
     //to creating a session is not especially intensive.
@@ -854,8 +841,6 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
     PJSipTransactionModInfo *tsx_mod_info = new PJSipTransactionModInfo(tsx);
     tsx->mod_data[mModule.id] = (void *)tsx_mod_info;
 
-    //XXX The sdp argument is NULL for now, but can be changed if we
-    //know what has been configured for this particular caller.
     pjsip_inv_session *inv_session;
     if (pjsip_inv_create_uas(dlg, rdata, NULL, 0, &inv_session) != PJ_SUCCESS)
     {
@@ -876,10 +861,6 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
     pjsip_timer_setting_default(&session_timer_settings);
     pjsip_timer_init_session(inv_session, &session_timer_settings);
 
-    //XXX This marks the last time we actually make use of the 
-    //rdata in this function. The times past this point are to get
-    //data from within the rdata. We can just as easily get that
-    //earlier.
     if (pjsip_inv_initial_answer(inv_session, rdata, 100, NULL, NULL, &tdata) != PJ_SUCCESS)
     {
         lg(Warning) << "Failed to create 100 Trying response";
@@ -1512,8 +1493,8 @@ void PJSipSessionModule::handleInviteRejection(pjsip_inv_session* inv,
             //XXX The actual sending of the message should probably be done as
             //a queued operation.
             pjsip_inv_send_msg(inv, tdata);
+            return;
         }
-        return;
     }
 }
 
@@ -1602,19 +1583,119 @@ protected:
             SipSessionPtr session = session_mod_info->getSessionPtr();
             AsteriskSCF::SessionCommunications::V1::ResponseCodePtr response =
                 new AsteriskSCF::SessionCommunications::V1::ResponseCode();
-            if (mInv->cause == 486)
+
+            //Cause codes for each SIP response are taken from RFC 3398 Section 8.2.6.1 (plus errata ID 2161)
+            switch (mInv->cause)
             {
+            case 400: // Bad Request
+                response->isdnCode = 41;
+                break;
+            case 401: // Unauthorized
+                response->isdnCode = 21;
+                break;
+            case 402: // Payment Required
+                response->isdnCode = 21;
+                break;
+            case 403: // Forbidden
+                response->isdnCode = 21;
+                break;
+            case 404: // Not Found
+                response->isdnCode = 1;
+                break;
+            case 405: // Method not allowed
+                response->isdnCode = 63;
+                break;
+            case 406: // Not Acceptable
+                response->isdnCode = 79;
+                break;
+            case 407: // Proxy Authentication Required
+                response->isdnCode = 21;
+                break;
+            case 408: // Request Timeout
+                response->isdnCode = 102;
+                break;
+            case 410: // Gone
+                response->isdnCode = 22;
+                break;
+            case 413: // Request Entity Too Long
+                response->isdnCode = 127;
+                break;
+            case 414: // Request-URI Too Long
+                response->isdnCode = 127;
+                break;
+            case 415: // Unsupported Media Type
+                response->isdnCode = 79;
+                break;
+            case 416: // Unsupported URI Scheme
+                response->isdnCode = 127;
+                break;
+            case 420: // Bad Extension
+                response->isdnCode = 127;
+                break;
+            case 421: // Extension Required
+                response->isdnCode = 127;
+                break;
+            case 423: // Interval Too Brief
+                response->isdnCode = 127;
+                break;
+            case 480: // Temporarily Unavailable
+                response->isdnCode = 18;
+                break;
+            case 481: // Call/Transaction Does Not Exist
+                response->isdnCode = 41;
+                break;
+            case 482: // Loop Detected
+                response->isdnCode = 25;
+                break;
+            case 483: // Too Many Hops
+                response->isdnCode = 25;
+                break;
+            case 484: // Address Incomplete
+                response->isdnCode = 28;
+                break;
+            case 485: // Ambiguous
+                response->isdnCode = 1;
+                break;
+            case 486: // Busy Here
                 response->isdnCode = 17;
-            }
-            else if (PJSIP_IS_STATUS_IN_CLASS(mInv->cause, 500))
-            {
-                response->isdnCode = 34;
-            }
-            else
-            {
-                // TODO: See what cause is on a normal call completion
+                break;
+            case 500: // Server Internal Error
+                response->isdnCode = 41;
+                break;
+            case 501: // Not Implemented
+                response->isdnCode = 79;
+                break;
+            case 502: // Bad Gateway
+                response->isdnCode = 38;
+                break;
+            case 503: // Service Unavailable
+                response->isdnCode = 41;
+                break;
+            case 504: // Server Time-out
+                response->isdnCode = 102;
+                break;
+            case 505: // Version Not Supported
+                response->isdnCode = 127;
+                break;
+            case 513: // Message Too Large
+                response->isdnCode = 127;
+                break;
+            case 600: // Busy Everywhere
+                response->isdnCode = 17;
+                break;
+            case 603: // Decline
+                response->isdnCode = 21;
+                break;
+            case 604: // Does Not Exist Anymore
+                response->isdnCode = 1;
+                break;
+            default:
+                // 487, 488, and 606 have no mapping. Also,
+                // other types of ends to sessions (like normal clearing)
+                // will end up here.
                 response->isdnCode = 0;
             }
+
             if (session)
             {
                 std::vector<AsteriskSCF::SessionCommunications::V1::SessionListenerPrx> listeners = session->getListeners();
@@ -1728,7 +1809,7 @@ void PJSipSessionModule::invOnStateChanged(pjsip_inv_session *inv, pjsip_event *
         inv->invite_tsx->mod_data[mModule.id] = (void *) tsx_mod_info;
         inv->dlg->mod_data[mModule.id] = (void *) dlg_mod_info;
         dlg_mod_info->mDialogState->sessionId = session_mod_info->mSessionState->sessionId;
-	dlg_mod_info->mPending = false;
+        dlg_mod_info->mPending = false;
         tsx_mod_info->mTransactionState->sessionId = session_mod_info->mSessionState->sessionId;
         lg(Debug) << "Replicating state on new outbound INVITE.";
         replicateState(dlg_mod_info, tsx_mod_info, session_mod_info);

commit fb4c184ad83d54886cfe7c50f01e2fb726592a8c
Merge: 44a2f27 71b8947
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Dec 20 13:14:11 2011 -0600

    Merge branch 'registrar-bugs'


commit 44a2f27c3a9ed47cb881c88c02ea6f91b3ee3084
Merge: 2862a33 4aa216e
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon Dec 19 17:07:16 2011 -0600

    Merge branch 'redirect'


commit 2862a336044a0f52462db837cc4b03660d2bb253
Merge: 1a97744 4a1aef0
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon Dec 19 15:47:38 2011 -0600

    Merge branch 'party-id'


commit 1a97744ee7f2f88feb3b50df841da9735a8330d7
Merge: f73dd30 8e2b79a
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon Dec 19 12:04:50 2011 -0600

    Merge branch 'master' of git.asterisk.org:asterisk-scf/release/sip


commit f73dd308884f91c014f55fd09665a35c6c7e1463
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon Dec 19 12:04:28 2011 -0600

    Use the proper from header in outgoing REGISTER requests.

diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
index c792230..7bd036c 100644
--- a/src/SipClientRegistration.cpp
+++ b/src/SipClientRegistration.cpp
@@ -169,14 +169,15 @@ void SipRegistrationClient::createPJSIPRegistration(
     pj_str_t serverURL;
     pj_strdup2(pjsip_regc_get_pool(mReg), &serverURL, server.str().c_str());
 
-    std::stringstream from;
-    from << "\"" << mEndpointName << "\" <sip:" << mEndpointName << "@" << config.transportConfig.address <<  ">";
-    pj_str_t fromURL;
-    pj_strdup2(pjsip_regc_get_pool(mReg), &fromURL, from.str().c_str());
-
+    // In a REGISTER, the To header contains the address of record
     pj_str_t toURL;
     pj_strdup2(pjsip_regc_get_pool(mReg), &toURL, confItem->aor.c_str());
 
+    // According to RFC 3261 section 10.2, the from header should be the same
+    // as the to unless this is a third-party registration.
+    pj_str_t fromURL;
+    pj_strdup2(pjsip_regc_get_pool(mReg), &fromURL, confItem->aor.c_str());
+
     pjsip_regc_init(
             mReg,
             &serverURL,

commit 71b8947e8a8c78340a498139339e3940280078bd
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon Dec 19 11:47:58 2011 -0600

    Use proper priority for the registrar module.

diff --git a/src/PJSipRegistrarModuleConstruction.cpp b/src/PJSipRegistrarModuleConstruction.cpp
index a42e6ee..47754f0 100644
--- a/src/PJSipRegistrarModuleConstruction.cpp
+++ b/src/PJSipRegistrarModuleConstruction.cpp
@@ -86,12 +86,7 @@ PJSipRegistrarModule::PJSipRegistrarModule(
 {
     registrarModule = this;
     mModule.name = pj_str(registrarModuleName);
-    // This is the highest priority module. We do this
-    // so that on outgoing messages, the transport information
-    // will have been filled in by the transport layer. This way
-    // what we log is exactly the same as what goes out over the
-    // wire.
-    mModule.priority = 0;
+    mModule.priority = PJSIP_MOD_PRIORITY_APPLICATION;
     mModule.load = registrarLoad;
     mModule.start = registrarStart;
     mModule.stop = registrarStop;

commit 8e2b79a5ae36f492a421a6f24c8d834ed72836d1
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Fri Dec 16 17:59:23 2011 -0600

    Added direct include of <boost/enable_shared_from_this.hpp>. The code was relying on an indirect inclusion that wasn't there on Windows.

diff --git a/src/PJSipManager.h b/src/PJSipManager.h
index c2c797d..98813be 100644
--- a/src/PJSipManager.h
+++ b/src/PJSipManager.h
@@ -23,6 +23,7 @@
 
 #include <Ice/Ice.h>
 
+#include <boost/enable_shared_from_this.hpp> 
 #include <boost/shared_ptr.hpp>
 #include <boost/thread/locks.hpp>
 

commit a19f5bae3e04bba3c314643a66e8cf94545cf57f
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Dec 14 17:36:12 2011 -0600

    Address review feedback
    
    * Use a const_iterator where I can.
    * Change the equality operators back to how they were. Turns out that I did not
      need to alter them at all. The '*' comparison only needed to be used in one place
      and it's a place I had failed to alter.

diff --git a/src/PJSipRegistrarModule.cpp b/src/PJSipRegistrarModule.cpp
index c8447b8..99704d1 100644
--- a/src/PJSipRegistrarModule.cpp
+++ b/src/PJSipRegistrarModule.cpp
@@ -98,12 +98,12 @@ BindingWrapper::BindingWrapper(
 
 bool BindingWrapper::operator==(const BindingWrapper& rhs)
 {
-    return (mBinding->contact == rhs.mBinding->contact) || rhs.mBinding->contact == "*" || mBinding->contact == "*";
+    return (mBinding->contact == rhs.mBinding->contact);
 }
 
 bool BindingWrapper::operator==(const BindingPtr& rhs)
 {
-    return (mBinding->contact == rhs->contact) || rhs->contact == "*" || mBinding->contact == "*";
+    return (mBinding->contact == rhs->contact);
 }
 
 void BindingWrapper::cancelRegistrationExpiration()
@@ -638,7 +638,7 @@ BindingWrapperSeq::iterator PJSipRegistrarModule::findMatchingBinding(pjsip_cont
     for (BindingWrapperSeq::iterator iter = bindings.begin(); iter != bindings.end(); ++iter)
     {
         lg(Debug) << "Comparing REGISTER contact " << contactURIStr << " with binding contact " << (*iter)->mBinding->contact;
-        if (contactURIStr == (*iter)->mBinding->contact)
+        if (contactURIStr == (*iter)->mBinding->contact || contactURIStr == "*")
         {
             lg(Debug) << "Found matching binding " << (*iter)->mBinding->contact;
             return iter;

commit 3dcea8b184feec0f4e8b6f45835135c2d9d00fa8
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Dec 8 15:59:56 2011 -0600

    s/BindingDict/BindingsDict/g

diff --git a/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice b/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
index f9eab87..4e3467d 100644
--- a/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
+++ b/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
@@ -179,7 +179,7 @@ module V1
       /**
        * The bindings whose states are being set/removed
        */
-      AsteriskSCF::SIP::Registration::V1::BindingDict bindings;
+      AsteriskSCF::SIP::Registration::V1::BindingsDict bindings;
       /**
        * In the case of setting state, this distinguishes if
        * the bindings are new. If not, then the bindings are
diff --git a/src/PJSipRegistrarModule.cpp b/src/PJSipRegistrarModule.cpp
index 188d682..c8447b8 100644
--- a/src/PJSipRegistrarModule.cpp
+++ b/src/PJSipRegistrarModule.cpp
@@ -243,12 +243,12 @@ public:
 
     void execute()
     {
-        BindingDict returnedBindings;
+        BindingsDict returnedBindings;
         //XXX
         //This is suboptimal. What may work better is to maintain 
         //parallel maps of BindingWrappers and Bindings so that
         //we can quickly return the appropriate information instead of
-        //having to construct a BindingDict on each call.
+        //having to construct a BindingsDict on each call.
 
         BindingWrapperDict& regBindings = mRegistrar->getBindings();
         for (BindingWrapperDict::iterator iter = regBindings.begin();
@@ -360,7 +360,7 @@ ContactDict RegistrarI::createContactDict(const BindingWrapperDict& bindings)
     return dict;
 }
 
-BindingDict RegistrarI::createBindingDict(const std::string& aor, const BindingWrapperSeq& bindings)
+BindingsDict RegistrarI::createBindingsDict(const std::string& aor, const BindingWrapperSeq& bindings)
 {
     BindingSeq returnedBindings;
     for (BindingWrapperSeq::const_iterator seqIter = bindings.begin();
@@ -368,7 +368,7 @@ BindingDict RegistrarI::createBindingDict(const std::string& aor, const BindingW
     {
         returnedBindings.push_back((*seqIter)->mBinding);
     }
-    BindingDict dict;
+    BindingsDict dict;
     dict.insert(make_pair(aor, returnedBindings));
     return dict;
 }
@@ -412,7 +412,7 @@ public:
         {
             if (!mNewBindings.empty())
             {
-                BindingDict newDict = mRegistrar->createBindingDict(mAOR, mNewBindings);
+                BindingsDict newDict = mRegistrar->createBindingsDict(mAOR, mNewBindings);
                 SipRegistrarStateItemPtr newItem(new SipRegistrarStateItem(mAOR, mAOR, newDict, true));
                 SipStateItemSeq items;
                 items.push_back(newItem);
@@ -421,7 +421,7 @@ public:
 
             if (!mExistingBindings.empty())
             {
-                BindingDict existingDict = mRegistrar->createBindingDict(mAOR, mExistingBindings);
+                BindingsDict existingDict = mRegistrar->createBindingsDict(mAOR, mExistingBindings);
                 SipRegistrarStateItemPtr existingItem(new SipRegistrarStateItem(mAOR, mAOR, existingDict, false));
                 SipStateItemSeq items;
                 items.push_back(existingItem);
@@ -430,7 +430,7 @@ public:
 
             if (!mRemovedBindings.empty())
             {
-                BindingDict removedDict = mRegistrar->createBindingDict(mAOR, mRemovedBindings);
+                BindingsDict removedDict = mRegistrar->createBindingsDict(mAOR, mRemovedBindings);
                 SipRegistrarStateItemPtr removedItem(new SipRegistrarStateItem(mAOR, mAOR, removedDict, false));
                 SipStateItemSeq items;
                 items.push_back(removedItem);
diff --git a/src/PJSipRegistrarModule.h b/src/PJSipRegistrarModule.h
index d64ec6d..0d5d4e4 100644
--- a/src/PJSipRegistrarModule.h
+++ b/src/PJSipRegistrarModule.h
@@ -77,7 +77,7 @@ public:
             BindingWrapperSeq& bindings);
 
     
-    AsteriskSCF::SIP::Registration::V1::BindingDict createBindingDict(const std::string& aor, const BindingWrapperSeq& bindings);
+    AsteriskSCF::SIP::Registration::V1::BindingsDict createBindingsDict(const std::string& aor, const BindingWrapperSeq& bindings);
     AsteriskSCF::SIP::Registration::V1::ContactDict createContactDict(const BindingWrapperDict& bindings);
 
     std::vector<AsteriskSCF::SIP::Registration::V1::RegistrarListenerPrx>& getListeners();
diff --git a/src/SipStateReplicatorListener.cpp b/src/SipStateReplicatorListener.cpp
index 7f5e01b..1a0ff69 100644
--- a/src/SipStateReplicatorListener.cpp
+++ b/src/SipStateReplicatorListener.cpp
@@ -111,7 +111,7 @@ public:
             const PJSipRegistrarModulePtr& regModule,
             const SipRegistrarStateItemPtr& regItem)
     {
-        for (BindingDict::iterator dictIter = regItem->bindings.begin();
+        for (BindingsDict::iterator dictIter = regItem->bindings.begin();
                 dictIter != regItem->bindings.end(); ++dictIter)
         {
             BindingSeq bindings = dictIter->second;
@@ -217,7 +217,7 @@ public:
     {
         //For new registrations, we need to create a sequence of BindingWrappers and call the registrar's
         //addAndRemoveBindings() function.
-        for (BindingDict::iterator dictIter = regItem->bindings.begin();
+        for (BindingsDict::iterator dictIter = regItem->bindings.begin();
                 dictIter != regItem->bindings.end(); ++dictIter)
         {
             BindingSeq bindings = dictIter->second;
@@ -235,7 +235,7 @@ public:
 
     void setExistingRegistrationState(const PJSipRegistrarModulePtr& regModule, const SipRegistrarStateItemPtr& regItem)
     {
-        for (BindingDict::iterator dictIter = regItem->bindings.begin();
+        for (BindingsDict::iterator dictIter = regItem->bindings.begin();
                 dictIter != regItem->bindings.end(); ++dictIter)
         {
             BindingWrapperSeq& bindings = regModule->getRegistrar()->getAORBindingWrappers(dictIter->first);

commit 0d797e41516ab19f437456fe7714425d441382d3
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Dec 8 15:19:18 2011 -0600

    ASTSCF-400: Use an IceUtil::TimerTask in the registrar.

diff --git a/src/PJSipRegistrarModule.cpp b/src/PJSipRegistrarModule.cpp
index e7494ab..188d682 100644
--- a/src/PJSipRegistrarModule.cpp
+++ b/src/PJSipRegistrarModule.cpp
@@ -42,12 +42,17 @@ namespace AsteriskSCF
 namespace SipSessionManager
 {
 
-class RegistrationExpired : public Work
+class RegistrationExpired : public Work, public IceUtil::TimerTask
 {
 public:
     RegistrationExpired(const BindingWrapperPtr& wrapper)
         : mWrapper(wrapper) { }
 
+    void runTimerTask()
+    {
+        mWrapper->mRegModule->getRegistrar()->getQueue()->enqueueWork(this);
+    }
+
     void execute()
     {
         lg(Debug) << "Detected expiration of binding " << mWrapper->mBinding->contact;
@@ -79,32 +84,18 @@ private:
     BindingWrapperPtr mWrapper;
 };
 
-static void registrationExpired(pj_timer_heap_t *, struct pj_timer_entry *entry)
-{
-    BindingWrapper *wrapper = static_cast<BindingWrapper *>(entry->user_data);
-    wrapper->mRegModule->getRegistrar()->getQueue()->enqueueWork(new RegistrationExpired(wrapper));
-}
-
-static int expirationId;
-
 BindingWrapper::BindingWrapper(
         int expiration,
         const BindingPtr& binding,
         const PJSipRegistrarModulePtr& regModule,
         pjsip_endpoint *endpt,
         const std::string& aor)
-    : mRegModule(regModule), mBinding(binding), mEndpoint(endpt), mAOR(aor)
+    : mRegModule(regModule), mBinding(binding), mEndpoint(endpt), mAOR(aor), mTimer(new IceUtil::Timer)
 {
-    pj_timer_entry_init(&mEntry, expirationId++, this, registrationExpired);
     lg(Debug) << "Scheduling binding " << mBinding->contact << " for expiration in " << expiration << " seconds.";
     scheduleRegistrationExpiration(expiration);
 }
 
-BindingWrapper::~BindingWrapper()
-{
-    cancelRegistrationExpiration();
-}
-
 bool BindingWrapper::operator==(const BindingWrapper& rhs)
 {
     return (mBinding->contact == rhs.mBinding->contact) || rhs.mBinding->contact == "*" || mBinding->contact == "*";
@@ -117,13 +108,14 @@ bool BindingWrapper::operator==(const BindingPtr& rhs)
 
 void BindingWrapper::cancelRegistrationExpiration()
 {
-    pjsip_endpt_cancel_timer(mEndpoint, &mEntry);
+    mTimer->cancel(mTimerTask);
+    mTimerTask = 0;
 }
 
 void BindingWrapper::scheduleRegistrationExpiration(int expiration)
 {
-    pj_time_val delay = {expiration, 0};
-    pjsip_endpt_schedule_timer(mEndpoint, &mEntry, &delay);
+    mTimerTask = new RegistrationExpired(this);
+    mTimer->schedule(mTimerTask, IceUtil::Time::seconds(expiration));
 }
 
 class UpdateBinding : public Work
@@ -344,6 +336,7 @@ void RegistrarI::removeBinding(BindingWrapperSeq& currentBindings, BindingWrappe
 {
     lg(Debug) << "Removing binding " << wrapper->mBinding->contact;
     currentBindings.erase(std::remove(currentBindings.begin(), currentBindings.end(), wrapper), currentBindings.end());
+    wrapper->cancelRegistrationExpiration();
 }
 
 void RegistrarI::removeAOR(const std::string& aor)
@@ -707,11 +700,9 @@ public:
         : mTsx(tsx), mTdata(tdata), mAOR(aor), mRegistrar(registrar) { }
     void execute()
     {
-        lg(Debug) << "In the Response thing";
         BindingWrapperSeq wrappers = mRegistrar->getAORBindingWrappers(mAOR);
         for (BindingWrapperSeq::const_iterator iter = wrappers.begin(); iter != wrappers.end(); ++iter)
         {
-            lg(Debug) << "Should be adding contact " << (*iter)->mBinding->contact;
             pjsip_contact_hdr *contact = pjsip_contact_hdr_create(mTdata->pool);
             contact->uri = pjsip_parse_uri(mTdata->pool, (char*) (*iter)->mBinding->contact.c_str(), (*iter)->mBinding->contact.size(), PJSIP_URI_IN_FROMTO_HDR);
             contact->expires = (*iter)->mBinding->expiration - time(0);
diff --git a/src/PJSipRegistrarModule.h b/src/PJSipRegistrarModule.h
index b86edf2..d64ec6d 100644
--- a/src/PJSipRegistrarModule.h
+++ b/src/PJSipRegistrarModule.h
@@ -177,8 +177,6 @@ public:
             pjsip_endpoint *endpt,
             const std::string& aor);
 
-    ~BindingWrapper();
-
     /**
      * Called when a binding expires.
      */
@@ -204,8 +202,9 @@ public:
     PJSipRegistrarModulePtr mRegModule;
     AsteriskSCF::SIP::Registration::V1::BindingPtr mBinding;
     pjsip_endpoint *mEndpoint;
-    pj_timer_entry mEntry;
     const std::string mAOR;
+    IceUtil::TimerPtr mTimer;
+    IceUtil::TimerTaskPtr mTimerTask;
 };
 
 void registrarAuthTimeout(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry);
diff --git a/src/SipRegistrarListener.cpp b/src/SipRegistrarListener.cpp
index be963a2..4400925 100644
--- a/src/SipRegistrarListener.cpp
+++ b/src/SipRegistrarListener.cpp
@@ -102,7 +102,7 @@ void SipDefaultRegistrarListener::contactsRemoved(const BindingUpdateSeq& contac
         for (SipEndpointSeq::iterator endpointIter = endpoints.begin();
                 endpointIter != endpoints.end(); ++endpointIter)
         {
-            lg(Debug) << "Removing contacts " << " from AoR " << iter->aor;
+            lg(Debug) << "Removing contacts from AoR " << iter->aor;
             //Setting the endpoint's target address to be empty is the method we currently use
             //to make the endpoint inaccessible. Once endpoints can support multiple addresses,
             //it'll be a bit less hacky since we can just remove a specific contact from the list.

commit 9a5e2f42a121488eb42ae79b59856d0481bf459c
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Dec 8 11:04:21 2011 -0600

    Fixes for ASTSCF-403, ASTSCF-402, and ASTSCF-401
    
    * Add Contact header(s) to outgoing 200 OK responses
    * Match a '*' contact to all stored contacts.
    * Notify RegistrarListeners of bindings removed due to expiration.

diff --git a/src/PJSipRegistrarModule.cpp b/src/PJSipRegistrarModule.cpp
index f25624e..e7494ab 100644
--- a/src/PJSipRegistrarModule.cpp
+++ b/src/PJSipRegistrarModule.cpp
@@ -59,6 +59,17 @@ public:
         {
             registrar->removeAOR(mWrapper->mAOR);
         }
+
+        BindingWrapperSeq wrappers(1, mWrapper);
+        BindingUpdateSeq removedBindingUpdateSeq(registrar->createBindingUpdateSeq(mWrapper->mAOR, wrappers));
+        std::vector<RegistrarListenerPrx>& listeners = registrar->getListeners();
+        for (std::vector<RegistrarListenerPrx>::iterator iter = listeners.begin();
+                iter != listeners.end(); ++iter)
+        {
+            lg(Debug) << "Alerting listener " << (*iter)->ice_getIdentity().name << " about removal of binding due to expiration.";
+            (*iter)->contactsRemoved(removedBindingUpdateSeq);
+        }
+
         BindingWrapperSeq emptySeq;
         BindingWrapperSeq toRemove;
         toRemove.push_back(mWrapper);
@@ -96,12 +107,12 @@ BindingWrapper::~BindingWrapper()
 
 bool BindingWrapper::operator==(const BindingWrapper& rhs)
 {
-    return mBinding->contact == rhs.mBinding->contact;
+    return (mBinding->contact == rhs.mBinding->contact) || rhs.mBinding->contact == "*" || mBinding->contact == "*";
 }
 
 bool BindingWrapper::operator==(const BindingPtr& rhs)
 {
-    return mBinding->contact == rhs->contact;
+    return (mBinding->contact == rhs->contact) || rhs->contact == "*" || mBinding->contact == "*";
 }
 
 void BindingWrapper::cancelRegistrationExpiration()
@@ -692,15 +703,27 @@ BindingWrapperPtr PJSipRegistrarModule::createNewBinding(pjsip_contact_hdr *cont
 class Response : public Work
 {
 public:
-    Response(pjsip_transaction *tsx, pjsip_tx_data *tdata)
-        : mTsx(tsx), mTdata(tdata) { }
+    Response(pjsip_transaction *tsx, pjsip_tx_data *tdata, const std::string& aor, const RegistrarIPtr& registrar)
+        : mTsx(tsx), mTdata(tdata), mAOR(aor), mRegistrar(registrar) { }
     void execute()
     {
+        lg(Debug) << "In the Response thing";
+        BindingWrapperSeq wrappers = mRegistrar->getAORBindingWrappers(mAOR);
+        for (BindingWrapperSeq::const_iterator iter = wrappers.begin(); iter != wrappers.end(); ++iter)
+        {
+            lg(Debug) << "Should be adding contact " << (*iter)->mBinding->contact;
+            pjsip_contact_hdr *contact = pjsip_contact_hdr_create(mTdata->pool);
+            contact->uri = pjsip_parse_uri(mTdata->pool, (char*) (*iter)->mBinding->contact.c_str(), (*iter)->mBinding->contact.size(), PJSIP_URI_IN_FROMTO_HDR);
+            contact->expires = (*iter)->mBinding->expiration - time(0);
+            pjsip_msg_add_hdr(mTdata->msg, (pjsip_hdr*) contact);
+        }
         pjsip_tsx_send_msg(mTsx, mTdata);
     }
 private:
     pjsip_transaction *mTsx;
     pjsip_tx_data *mTdata;
+    const std::string mAOR;
+    RegistrarIPtr mRegistrar;
 };
 
 bool PJSipRegistrarModule::checkAuth(pjsip_rx_data *rdata, pjsip_transaction *tsx, RequestType type)
@@ -811,7 +834,7 @@ pj_bool_t PJSipRegistrarModule::on_rx_request(pjsip_rx_data *rdata)
     // our internal bindings.
     pjsip_tx_data *tdata;
     pjsip_endpt_create_response(tsx->endpt, rdata, 200, NULL, &tdata);
-    mRegistrar->getQueue()->enqueueWork(new Response(tsx, tdata));
+    mRegistrar->getQueue()->enqueueWork(new Response(tsx, tdata, aor, mRegistrar));
 
     replicateState(aor, existingBindings, newBindings, removedBindings);
 

commit 12fe1df571ef939b60e2dadf99fc488b1edd6a4f
Author: Brent Eagles <beagles at digium.com>
Date:   Tue Dec 6 17:31:41 2011 -0330

    Modify all unit tests to use the loopback adapter.

diff --git a/config/test_sip.conf b/config/test_sip.conf
index ad26db5..e94f85d 100644
--- a/config/test_sip.conf
+++ b/config/test_sip.conf
@@ -3,22 +3,22 @@
 # Adapter parameters for this component
 # The IP address and port specified here *must* match between master and slave
 # for Ice proxies to remain valid.
-SipSessionManagerAdapter.Endpoints=tcp -p 9985
+SipSessionManagerAdapter.Endpoints=tcp -h 127.0.0.1 -p 9985
 SipSessionManagerAdapter.ThreadPool.Size=4
 
 # Adapter parameters for the object adapter unique to this instance of the component
 # This should have a specified IP address and port so the replica control utility can find it.
-SipSessionManagerLocalAdapter.Endpoints=default
+SipSessionManagerLocalAdapter.Endpoints=default -h 127.0.0.1 
 SipSessionManagerLocalAdapter.ThreadPool.Size=4
 
 # A proxy to the IceStorm topic manager
-TopicManager.Proxy=AsteriskSCFIceStorm/TopicManager:default -p 10000
+TopicManager.Proxy=AsteriskSCFIceStorm/TopicManager:default  -h 127.0.0.1 -p 10000
 
 # A proxy to the service locator management service
-LocatorServiceManagement.Proxy=LocatorServiceManagement:tcp -p 4422
+LocatorServiceManagement.Proxy=LocatorServiceManagement:tcp  -h 127.0.0.1 -p 4422
 
 # A proxy to the service locator service
-LocatorService.Proxy=LocatorService:tcp -p 4411
+LocatorService.Proxy=LocatorService:tcp -h 127.0.0.1  -p 4411
 
 # ID to use when registering with the routing service
 # Useful if registering multiple active SIP session managers
diff --git a/config/test_sip_state_replicator.conf b/config/test_sip_state_replicator.conf
index e7e7c6f..bf46ede 100644
--- a/config/test_sip_state_replicator.conf
+++ b/config/test_sip_state_replicator.conf
@@ -1,15 +1,15 @@
 # Adapter parameters for this component
-SipStateReplicator.Endpoints=default
+SipStateReplicator.Endpoints=default -h 127.0.0.1
 SipStateReplicator.ThreadPool.Size=4
 
 # A proxy to the IceStorm topic manager
-TopicManager.Proxy=AsteriskSCFIceStorm/TopicManager:default -p 10000
+TopicManager.Proxy=AsteriskSCFIceStorm/TopicManager:default  -h 127.0.0.1 -p 10000
 
 # A proxy to the service locator management service
-LocatorServiceManagement.Proxy=LocatorServiceManagement:tcp -p 4422
+LocatorServiceManagement.Proxy=LocatorServiceManagement:tcp  -h 127.0.0.1 -p 4422
 
 # A proxy to the service locator service
-LocatorService.Proxy=LocatorService:tcp -p 4411
+LocatorService.Proxy=LocatorService:tcp  -h 127.0.0.1 -p 4411
 
 # The name of the state replicator
 SipStateReplicator.Name=default
@@ -18,9 +18,9 @@ IceBox.InheritProperties = 1
 IceBox.Service.SipStateReplicator=SipStateReplicator:create
 
 SipStateReplicatorIceStorm.InstanceName=SipStateReplicatorIceStorm
-SipStateReplicatorIceStorm.TopicManager.Endpoints=default -p 10007
-SipStateReplicatorIceStorm.Publish.Endpoints=default -p 10008
+SipStateReplicatorIceStorm.TopicManager.Endpoints=default -h 127.0.0.1  -p 10007
+SipStateReplicatorIceStorm.Publish.Endpoints=default -h 127.0.0.1  -p 10008
 SipStateReplicatorIceStorm.Trace.TopicManager=2
 SipStateReplicatorIceStorm.Transient=1
 SipStateReplicatorIceStorm.Flush.Timeout=2000
-SipStateReplicatorTopicManager.Proxy=SipStateReplicatorIceStorm/TopicManager:default -p 10007
+SipStateReplicatorTopicManager.Proxy=SipStateReplicatorIceStorm/TopicManager:default  -h 127.0.0.1 -p 10007

commit 4a1aef04a21ab0c33493b745b2123bcea00ff073
Author: Mark Michelson <mmichelson at digium.com>
Date:   Fri Dec 2 15:57:43 2011 -0600

    Adjust so that getInfo() gets identity information.
    
    This meant that things bled out a bit, but it'll be all right.

diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 0763f35..2bb6eda 100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -137,59 +137,6 @@ public:
 
     }
 
-    AsteriskSCF::SessionCommunications::V1::SessionInfoPtr getInfo()
-    {
-        AsteriskSCF::SessionCommunications::V1::SessionInfoPtr sessioninfo =
-            new AsteriskSCF::SessionCommunications::V1::SessionInfo();
-        
-        /* TODO: Utilize locking so this becomes safe
-           if (!mImplPriv->mInviteSession || mImplPriv->mInviteSession->state == PJSIP_INV_STATE_NULL)
-           {
-           sessioninfo->currentState = "ready";
-           }
-           else if (mImplPriv->mInviteSession->state == PJSIP_INV_STATE_CALLING)
-           {
-           sessioninfo->currentState = "outbound";
-           }
-           else if (mImplPriv->mInviteSession->state == PJSIP_INV_STATE_INCOMING)
-           {
-           sessioninfo->currentState = "inbound";
-           }
-           else if (mImplPriv->mInviteSession->state == PJSIP_INV_STATE_EARLY)
-           {
-           sessioninfo->currentState = "early";
-           }
-           else if (mImplPriv->mInviteSession->state == PJSIP_INV_STATE_CONNECTING)
-           {
-           sessioninfo->currentState = "connecting";
-           }
-           else if (mImplPriv->mInviteSession->state == PJSIP_INV_STATE_CONFIRMED)
-           {
-           sessioninfo->currentState = "connected";
-           }
-           else if (mImplPriv->mInviteSession->state == PJSIP_INV_STATE_DISCONNECTED)
-           {
-           sessioninfo->currentState = "disconnected";
-           }
-        */
-        return sessioninfo;
-    }
-
-    void addListener(const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener)
-    {
-        mListeners.push_back(listener);
-        if (mInviteSession)
-        {
-            PJSipSessionModInfo *session_mod_info =
-                static_cast<PJSipSessionModInfo*>(
-                    mInviteSession->mod_data[mManager->getSessionModule()->getModule().id]);
-            if (session_mod_info)
-            {
-                session_mod_info->updateSessionState(mInviteSession);
-            }
-            mManager->getSessionModule()->replicateState(NULL, NULL, session_mod_info);
-        }
-    }
 
     void removeListener(const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener)
     {
@@ -1454,22 +1401,20 @@ public:
     AddListenerOperation(
             const AsteriskSCF::SessionCommunications::V1::AMD_Session_addListenerPtr& cb,
             const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
-            const boost::shared_ptr<SipSessionPriv>& sessionPriv)
-        : mCb(cb), mListener(listener), mImplPriv(sessionPriv) { }
+            const SipSessionPtr& session)
+        : mCb(cb), mListener(listener), mSession(session) { }
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
         lg(Debug) << "Executing addListener operation";
-        mImplPriv->addListener(mListener);
-        AsteriskSCF::SessionCommunications::V1::SessionInfoPtr sessionInfo =
-            mImplPriv->getInfo();
-        mCb->ice_response(sessionInfo);
+        mSession->addListener(mListener);
+        mCb->ice_response(mSession->getInfo());
         return Complete;
     }
 private:
     AsteriskSCF::SessionCommunications::V1::AMD_Session_addListenerPtr mCb;
     AsteriskSCF::SessionCommunications::V1::SessionListenerPrx mListener;
-    boost::shared_ptr<SipSessionPriv> mImplPriv;
+    SipSessionPtr mSession;
 };
 
 void SipSession::addListener_async(
@@ -1478,7 +1423,23 @@ void SipSession::addListener_async(
         const Ice::Current&)
 {
     lg(Debug) << "Queueing addListener operation";
-    enqueueSessionWork(new AddListenerOperation(cb, listener, mImplPriv));
+    enqueueSessionWork(new AddListenerOperation(cb, listener, this));
+}
+
+void SipSession::addListener(const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener)
+{
+    mImplPriv->mListeners.push_back(listener);
+    if (mImplPriv->mInviteSession)
+    {
+        PJSipSessionModInfo *session_mod_info =
+            static_cast<PJSipSessionModInfo*>(
+                mImplPriv->mInviteSession->mod_data[mImplPriv->mManager->getSessionModule()->getModule().id]);
+        if (session_mod_info)
+        {
+            session_mod_info->updateSessionState(mImplPriv->mInviteSession);
+        }
+        mImplPriv->mManager->getSessionModule()->replicateState(NULL, NULL, session_mod_info);
+    }
 }
 
 class IndicateOperation : public SuspendableWork
@@ -1661,22 +1622,19 @@ class GetInfoOperation : public SuspendableWork
 public:
     GetInfoOperation(
             const AsteriskSCF::SessionCommunications::V1::AMD_Session_getInfoPtr& cb,
-            const boost::shared_ptr<SipSessionPriv>& sessionPriv)
-        : mCb(cb), mImplPriv(sessionPriv) { }
+            const SipSessionPtr& session)
+        : mCb(cb), mSession(session) { }
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
         lg(Debug) << "Executing a GetInfo operation";
-        AsteriskSCF::SessionCommunications::V1::SessionInfoPtr sessionInfo =
-            mImplPriv->getInfo();
-
-        mCb->ice_response(sessionInfo);
+        mCb->ice_response(mSession->getInfo());
         return Complete;
     }
 
 private:
     AsteriskSCF::SessionCommunications::V1::AMD_Session_getInfoPtr mCb;
-    boost::shared_ptr<SipSessionPriv> mImplPriv;
+    SipSessionPtr mSession;
 };
 
 /**
@@ -1687,7 +1645,50 @@ void SipSession::getInfo_async(
         const Ice::Current&)
 {
     lg(Debug) << "queuing a getInfo operation";
-    enqueueSessionWork(new GetInfoOperation(cb, mImplPriv));
+    enqueueSessionWork(new GetInfoOperation(cb, this));
+}
+
+AsteriskSCF::SessionCommunications::V1::SessionInfoPtr SipSession::getInfo()
+{
+    AsteriskSCF::SessionCommunications::V1::SessionInfoPtr sessioninfo =
+        new AsteriskSCF::SessionCommunications::V1::SessionInfo();
+    
+    /*
+       if (!mImplPriv->mInviteSession || mImplPriv->mInviteSession->state == PJSIP_INV_STATE_NULL)
+       {
+       sessioninfo->currentState = "ready";
+       }
+       else if (mImplPriv->mInviteSession->state == PJSIP_INV_STATE_CALLING)
+       {
+       sessioninfo->currentState = "outbound";
+       }
+       else if (mImplPriv->mInviteSession->state == PJSIP_INV_STATE_INCOMING)
+       {
+       sessioninfo->currentState = "inbound";
+       }
+       else if (mImplPriv->mInviteSession->state == PJSIP_INV_STATE_EARLY)
+       {
+       sessioninfo->currentState = "early";
+       }
+       else if (mImplPriv->mInviteSession->state == PJSIP_INV_STATE_CONNECTING)
+       {
+       sessioninfo->currentState = "connecting";
+       }
+       else if (mImplPriv->mInviteSession->state == PJSIP_INV_STATE_CONFIRMED)
+       {
+       sessioninfo->currentState = "connected";
+       }
+       else if (mImplPriv->mInviteSession->state == PJSIP_INV_STATE_DISCONNECTED)
+       {
+       sessioninfo->currentState = "disconnected";
+       }
+    */
+
+    sessioninfo->connectedLine = getConnectedLine();
+    sessioninfo->sessionOwner = getSessionOwnerId();
+    sessioninfo->callerID = getCaller();
+
+    return sessioninfo;
 }
 
 class GetMediaSessionOperation : public SuspendableWork
@@ -1897,25 +1898,23 @@ public:
     SetBridgeOperation(
             const AsteriskSCF::SessionCommunications::V1::AMD_Session_setBridgePtr& cb,
             const SipSessionPtr& session,
-            const boost::shared_ptr<SipSessionPriv>& sessionPriv,
             const AsteriskSCF::SessionCommunications::V1::BridgePrx& bridge,
             const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
             const Ice::Current& current)
-        : mCb(cb), mSession(session), mImplPriv(sessionPriv), mBridge(bridge), mListener(listener), mCurrent(current) { }
+        : mCb(cb), mSession(session), mBridge(bridge), mListener(listener), mCurrent(current) { }
     
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
         lg(Debug) << "Executing a SetBridge operation";
         mSession->setBridge(mBridge);
-        mImplPriv->addListener(mListener);
-        mCb->ice_response(mImplPriv->getInfo());
+        mSession->addListener(mListener);
+        mCb->ice_response(mSession->getInfo());
         return Complete;
     }
 
 private:
     AsteriskSCF::SessionCommunications::V1::AMD_Session_setBridgePtr mCb;
     SipSessionPtr mSession;
-    boost::shared_ptr<SipSessionPriv> mImplPriv;
     AsteriskSCF::SessionCommunications::V1::BridgePrx mBridge;
     AsteriskSCF::SessionCommunications::V1::SessionListenerPrx mListener;
     Ice::Current mCurrent;
@@ -1931,7 +1930,7 @@ void SipSession::setBridge_async(
     const Ice::Current& current)
 {
     lg(Debug) << "queuing a setBridge operation";
-    enqueueSessionWork(new SetBridgeOperation(cb, this, mImplPriv, bridge, listener, current));
+    enqueueSessionWork(new SetBridgeOperation(cb, this, bridge, listener, current));
 }
 
 /**
@@ -2397,6 +2396,43 @@ ConnectedLinePtr SipSession::getConnectedLine()
     return id;
 }
 
+/**
+ * Gets the SessionOwnerId party identification record for this Session.
+ * This is an internal method, intended to be called from within a queued operation.
+ */
+SessionOwnerIdPtr SipSession::getSessionOwnerId()
+{
+    SessionOwnerIdPtr id = 0;
+    AsteriskSCF::SessionCommunications::V1::SessionCookies cookies;
+    cookies.push_back(new SessionOwnerId());
+    AsteriskSCF::SessionCommunications::V1::SessionCookies results = getCookies(cookies);
+
+    if (!results.empty())
+    {
+        id = SessionOwnerIdPtr::dynamicCast(results.front());
+    }
+
+    return id;
+}
+
+/**
+ * Gets the Caller party identification record for this Session.
+ * This is an internal method, intended to be called from within a queued operation.
+ */
+CallerPtr SipSession::getCaller()
+{
+    CallerPtr id = 0;
+    AsteriskSCF::SessionCommunications::V1::SessionCookies cookies;
+    cookies.push_back(new Caller());
+    AsteriskSCF::SessionCommunications::V1::SessionCookies results = getCookies(cookies);
+
+    if (!results.empty())
+    {
+        id = CallerPtr::dynamicCast(results.front());
+    }
+
+    return id;
+}
 /** 
  * Gets the ConnectedLine party identification record for this Session.
  */
diff --git a/src/SipSession.h b/src/SipSession.h
index 9dfe0a3..31073d6 100644
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@ -162,6 +162,8 @@ public:
             const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx&,
             const Ice::Current&);
 
+    void addListener(const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener);
+
     void indicate_async(
             const AsteriskSCF::SessionCommunications::V1::AMD_Session_indicatePtr& cb,
             const AsteriskSCF::SessionCommunications::V1::IndicationPtr&, const Ice::Current&);
@@ -174,6 +176,8 @@ public:
             const AsteriskSCF::SessionCommunications::V1::AMD_Session_getInfoPtr& cb,
             const Ice::Current&);
 
+    AsteriskSCF::SessionCommunications::V1::SessionInfoPtr getInfo();
+
     void getMediaSession_async(
             const AsteriskSCF::SessionCommunications::V1::AMD_Session_getMediaSessionPtr& cb,
             const Ice::Current&);
@@ -234,6 +238,16 @@ public:
      * This is an internal method and should only be called from queued operations
      */
     AsteriskSCF::SessionCommunications::PartyIdentification::V1::ConnectedLinePtr getConnectedLine();
+    /**
+     * Gets the SessionOwnerId for the session.
+     * This is an internal method and should only be called from queued operations
+     */
+    AsteriskSCF::SessionCommunications::PartyIdentification::V1::SessionOwnerIdPtr getSessionOwnerId();
+    /**
+     * Gets the Caller for the session.
+     * This is an internal method and should only be called from queued operations
+     */
+    AsteriskSCF::SessionCommunications::PartyIdentification::V1::CallerPtr getCaller();
 
     void getStreams_async(
         const AsteriskSCF::SessionCommunications::V1::AMD_Session_getStreamsPtr&,
diff --git a/src/SipTransfer.cpp b/src/SipTransfer.cpp
index ee2bcaf..bb35b4b 100644
--- a/src/SipTransfer.cpp
+++ b/src/SipTransfer.cpp
@@ -480,7 +480,7 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
 
             lg(Debug) << "handleRefer() calling router connectBridgedSessions(). ";
 
-            mSessionRouter->begin_connectBridgedSessions(operationId, mSession->getSessionProxy(), other_session->getSessionProxy(), false, other_session->getConnectedLine(), d);
+            mSessionRouter->begin_connectBridgedSessions(operationId, mSession->getSessionProxy(), other_session->getSessionProxy(), false, d);
             pjsip_dlg_dec_lock(other_dlg);
             return Complete;
         }

commit fa4ad6ffcb5786b086e07b5d81845be5bb2e91bd
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Dec 1 13:18:22 2011 -0600

    Remove unnecessary debug lines from the code of codes.

diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index d3c04ba..0763f35 100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -947,7 +947,6 @@ void SipSession::setSelfAsCaller()
 
 void SipSession::setSessionOwnerId(const SessionOwnerIdPtr& owner)
 {
-    lg(Debug) << "!!!!!! Setting owner id on session " << mImplPriv->mEndpoint->getName();
     mImplPriv->mSessionCookies[owner->ice_id()] = owner;
     mImplPriv->cookiesUpdated();
 }
@@ -2385,8 +2384,6 @@ void SipSession::getSessionOwnerId_async(const AMD_Session_getSessionOwnerIdPtr&
 ConnectedLinePtr SipSession::getConnectedLine()
 {
 
-    lg(Debug) << "!!!!!!! Getting ConnectedLine for session " << mImplPriv->mEndpoint->getName();
-
     ConnectedLinePtr id = 0;
     AsteriskSCF::SessionCommunications::V1::SessionCookies cookies;
     cookies.push_back(new ConnectedLine());
@@ -2394,7 +2391,6 @@ ConnectedLinePtr SipSession::getConnectedLine()
 
     if (!results.empty())
     {
-        lg(Debug) << "!!!!!!!!! Found ConnectedLine";
         id = ConnectedLinePtr::dynamicCast(results.front());
     }
 

commit e9bef7f80aa63e9b09c9c63c481cbd7f7d69d271
Merge: ddf99b1 8ec91ed
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Dec 1 10:57:48 2011 -0600

    Merge branch 'master' into party-id
    
    Conflicts:
    	src/PJSipSessionModule.cpp

diff --cc src/PJSipSessionModule.cpp
index 721f9ce,5d1d207..2150d50
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@@ -26,7 -26,7 +26,8 @@@
  
  #include <IceUtil/UUID.h>
  #include <boost/lexical_cast.hpp>
 +#include <boost/algorithm/string.hpp>
+ #include <boost/numeric/conversion/cast.hpp>
  
  #include <AsteriskSCF/Core/Endpoint/EndpointIf.h>
  #include <AsteriskSCF/Core/Routing/RoutingIf.h>
@@@ -1507,9 -1171,39 +1484,39 @@@ void PJSipSessionModule::handleInviteRe
      //to add code to handle.
  
      lg(Debug) << "Queuing a HandleInviteResponseOperation";
 -    enqueueSessionWork(new HandleInviteResponseOperation(respCode, inv->state, session), inv);
 +    enqueueSessionWork(new HandleInviteResponseOperation(respCode, inv->state, session, connected), inv);
  }
  
+ //There are some rejection codes that we can actually do something with other than
+ //just kill the code.
+ void PJSipSessionModule::handleInviteRejection(pjsip_inv_session* inv,
+     pjsip_rx_data* rdata, pjsip_transaction* tsx)
+ {
+     int respCode = rdata->msg_info.msg->line.status.code;
+     PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)inv->mod_data[mModule.id];
+     SipSessionPtr session = session_mod_info->getSessionPtr();
+ 
+     if (respCode == 401 || respCode == 407)
+     {
+         //Aw peas, they be wanting to authenticate, boooooooooiiiiiiiiiii
+         std::vector<pjsip_cred_info> creds;
+         mAuthManager->getAuthCredentials(rdata, creds, session->getEndpoint()->getName());
+         if (creds.size() != 0)
+         {
+             pjsip_inv_uac_restart(inv, PJ_FALSE);
+             pjsip_auth_clt_set_credentials(&inv->dlg->auth_sess,
+                     boost::numeric_cast<int>(creds.size()), &creds.front());
+             pjsip_tx_data *tdata;
+             pjsip_auth_clt_reinit_req(&inv->dlg->auth_sess,
+                     rdata, tsx->last_tx, &tdata);
+             //XXX The actual sending of the message should probably be done as
+             //a queued operation.
+             pjsip_inv_send_msg(inv, tdata);
+         }
+         return;
+     }
+ }
+ 
  class TransactionStateOperation : public SipQueueableOperation
  {
  public:
diff --cc src/PJSipSessionModule.h
index 3b9c3a0,59e840a..d761e1c
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@@ -144,74 -140,9 +144,76 @@@ public
  
  private:
      void handleNewInvite(pjsip_rx_data *rdata);
 +
 +    /**
 +     * Gets the value of the Privacy setting and returns true if
 +     * the value is set to "id"
 +     */
 +    bool getPrivacy(pjsip_rx_data *rdata);
 +    /**
 +     * Generic method to get Ids from a header name.
 +     * 
 +     * This can be used for any header type that does not
 +     * have specific parameters that need to be read.
 +     */
 +    void getIds(const char *headerName,
 +            pjsip_rx_data *rdata,
 +            bool privacySet,
 +            AsteriskSCF::SessionCommunications::PartyIdentification::V1::IdSeq& ids);
 +    /**
 +     * Get the IDs in Diversion headers.
 +     *
 +     * This will also parse the reason parameters from the headers.
 +     */
 +    void getRedirectionIds(pjsip_rx_data *rdata,
 +            bool privacySet,
 +            ReasonIdSeq& ids);
 +
 +    /**
 +     * Get the IDs from Remote-Party-ID headers.
 +     *
 +     * This will also parse the privacy and screen parameters.
 +     */
 +    void getRemotePartyIds(pjsip_rx_data *rdata,
 +            bool privacySet,
 +            AsteriskSCF::SessionCommunications::PartyIdentification::V1::IdSeq& ids);
 +
 +    /**
 +     * Generic method to get a specific parameter from a header
 +     */
 +    std::string getParam(const std::string& headerVal, const char *paramName);
 +
 +    /**
 +     * Translate a reason string into the appropriate slice enum value
 +     */
 +    AsteriskSCF::SessionCommunications::PartyIdentification::V1::Reason translateReason(const std::string& reason);
 +
 +    /**
 +     * Get caller ID
 +     *
 +     * This will first attempt to find P-Asserted-Identity headers. If none are present, it
 +     * will use the From header to find the caller ID.
 +     */
 +    AsteriskSCF::SessionCommunications::PartyIdentification::V1::CallerPtr getCallerID(pjsip_rx_data *rdata);
 +
 +    /**
 +     * Get the connected ID
 +     *
 +     * This will first attempt to find P-Asserted-Identity headers. If none are present, it
 +     * will search for Remote-Party-ID headers.
 +     */
 +    AsteriskSCF::SessionCommunications::PartyIdentification::V1::ConnectedLinePtr getConnectedID(pjsip_rx_data *rdata);
 +
 +    /**
 +     * Get Redirections
 +     *
 +     * This will attempt to find Diversion headers.
 +     */
 +    AsteriskSCF::SessionCommunications::PartyIdentification::V1::RedirectionsPtr getRedirections(pjsip_rx_data *rdata, pjsip_sip_uri *ruri);
 +
      void handleInviteResponse(pjsip_inv_session *inv, pjsip_rx_data *rdata, pjsip_dialog *dlg);
+     void handleInviteRejection(pjsip_inv_session *inv, pjsip_rx_data *rdata, pjsip_transaction *tsx);
+     void handleNonInviteAuthentication(pjsip_inv_session *inv, pjsip_rx_data *rdata, pjsip_dialog *dlg, pjsip_transaction *tsx);
      void handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdata);
      void handleInfo(pjsip_inv_session *inv, pjsip_rx_data *rdata);
      bool isDTMF(pjsip_rx_data *rdata);

commit 8ec91edd2b48b4359a86eb83922c877394006dcc
Merge: 3cd729f 585a242
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Dec 1 10:27:16 2011 -0600

    Merge branch 'master' of git.asterisk.org:asterisk-scf/release/sip


commit 3cd729fbb9dc4d0a75185a443f9f433552ddf47d
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Nov 30 13:38:16 2011 -0600

    Remove an unnecessary #include

diff --git a/src/SipEndpointFactory.h b/src/SipEndpointFactory.h
index e8102a9..115fd8e 100644
--- a/src/SipEndpointFactory.h
+++ b/src/SipEndpointFactory.h
@@ -23,7 +23,6 @@
 #include <AsteriskSCF/Core/Endpoint/EndpointIf.h>
 #include <AsteriskSCF/SessionCommunications/SessionCommunicationsExtensionPointsIf.h>
 #include <AsteriskSCF/SIP/SIPRegistrarIf.h>
-#include <AsteriskSCF/logger.h>
 #include "SipReplicationContext.h"
 #include "PJSipManager.h"
 

commit a0abb129f930f8dfe4e3c625323dcd08a34923f5
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Nov 30 12:23:38 2011 -0600

    s/moduleHookVector/ModuleHookVector/

diff --git a/src/AuthManager.cpp b/src/AuthManager.cpp
index d5e75f9..277eac3 100644
--- a/src/AuthManager.cpp
+++ b/src/AuthManager.cpp
@@ -48,7 +48,7 @@ public:
 class ServerAuthInstancePriv
 {
 public:
-    ServerAuthInstancePriv(pjsip_rx_data *rdata, const moduleHookVector &moduleHooks,
+    ServerAuthInstancePriv(pjsip_rx_data *rdata, const ModuleHookVector &moduleHooks,
             RequestType type, pjsip_endpoint *endpoint, const Logger &logger)
         : mEndpoint(endpoint),
         mPool(pjsip_endpt_create_pool(mEndpoint, "auth%p", 500, 256)),
@@ -61,7 +61,7 @@ public:
             return;
         }
 
... 4681 lines suppressed ...


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list