[asterisk-scf-commits] asterisk-scf/integration/sip.git branch "telephone-events" created.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Tue Jul 5 17:06:14 CDT 2011


branch "telephone-events" has been created
        at  bd25df69bafa9d87b5c427a11422fc0c0c0fc5bd (commit)

- Log -----------------------------------------------------------------
commit bd25df69bafa9d87b5c427a11422fc0c0c0fc5bd
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Jul 5 17:06:06 2011 -0500

    Add initial parsing of DTMF INFO requests.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 46ecafd..ff47c0e 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -22,6 +22,7 @@
 #include "SipStateReplicator.h"
 
 #include <IceUtil/UUID.h>
+#include <boost/lexical_cast.hpp>
 
 #include <AsteriskSCF/Core/Endpoint/EndpointIf.h>
 #include <AsteriskSCF/Core/Routing/RoutingIf.h>
@@ -911,9 +912,84 @@ void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdat
     enqueueSessionWork(new HandleReferOperation(inv, tsx, tdata, replaces_param, to_tag_param, from_tag_param, target, session, mSessionRouter, mModule.id), inv);
 }
 
+bool PJSipSessionModule::isDTMF(pjsip_rx_data *rdata)
+{
+    // We should determine how to handle matters based on the "Info-Package" header,
+    // but DTMF via INFO existed long before the Info-Package RFC was published.
+    // An official document defining DTMF over INFO is still in the draft stage as
+    // of July 2011. We will thus use the Info-Package or the Content-Type header
+    // to determine if this is DTMF.
+
+    pj_str_t str_info_pkg;
+    pj_cstr(&str_info_pkg, "Info-Package");
+    pjsip_generic_string_hdr *info_package =
+        static_cast<pjsip_generic_string_hdr *>(pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_info_pkg, NULL));
+
+    pj_str_t dtmf;
+    pj_cstr(&dtmf, "dtmf");
+    if (info_package && !pj_strcmp(&info_package->hvalue, &dtmf))
+    {
+        return true;
+    }
+
+    //No biggie. I just said that not many are actually going to use Info-Package.
+    //Check if the content-type is "application/dtmf-relay"
+    pj_str_t application;
+    pj_str_t dtmf_relay;
+    pj_cstr(&application, "application");
+    pj_cstr(&dtmf_relay, "dtmf-relay");
+    if (!pj_strcmp(&rdata->msg_info.ctype->media.type, &application) && 
+            !pj_strcmp(&rdata->msg_info.ctype->media.subtype, &dtmf_relay))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+char PJSipSessionModule::getDTMFInfoSignal(pjsip_msg_body *body)
+{
+    char *data = static_cast<char *>(body->data);
+    std::string dataStr(data, body->len);
+
+    size_t signalPos = dataStr.find("Signal= ");
+    if (signalPos == std::string::npos)
+    {
+        //XXX Uh...
+    }
+
+    return dataStr.at(signalPos + sizeof("Signal= "));
+}
+
+int PJSipSessionModule::getDTMFInfoDuration(pjsip_msg_body *body)
+{
+    char *data = static_cast<char *>(body->data);
+    std::string dataStr(data, body->len);
+
+    size_t durationPos = dataStr.find("Duration= ");
+    if (durationPos == std::string::npos)
+    {
+        //XXX Uh...
+    }
+
+    std::string duration(dataStr.substr(durationPos + sizeof("Duration= ")));
+    return boost::lexical_cast<int>(duration);
+}
+
 void PJSipSessionModule::handleInfo(pjsip_inv_session *inv, pjsip_rx_data *rdata)
 {
-    //STUB
+    // The only INFO package we handle for now is "dtmf". We need to verify that
+    // what we have received is actually DTMF and not some other INFO package.
+
+    if (!isDTMF(rdata))
+    {
+        return;
+    }
+
+    //It's DTMF! Grab the info we need! HA THAT WAS A PUN YOU JERK!
+    char dtmf = getDTMFInfoSignal(rdata->msg_info.msg->body);
+    int duration = getDTMFInfoDuration(rdata->msg_info.msg->body);
+
     return;
 }
 
diff --git a/src/PJSipSessionModule.h b/src/PJSipSessionModule.h
index 5b08405..6337e57 100644
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@ -122,6 +122,9 @@ private:
     void handleInviteResponse(pjsip_inv_session *inv, pjsip_rx_data *rdata, pjsip_dialog *dlg);
     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);
+    char getDTMFInfoSignal(pjsip_msg_body *body);
+    int getDTMFInfoDuration(pjsip_msg_body *body);
     pjsip_inv_callback mInvCallback;
     pjsip_ua_init_param mUaParam;
     const std::string mName;

commit 5c5e10ab63ed39300e37d63cac1f8154956db1a5
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Jul 5 16:07:26 2011 -0500

    Initial code to be able to detect an incoming INFO.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index b6719d5..46ecafd 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -911,6 +911,12 @@ void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdat
     enqueueSessionWork(new HandleReferOperation(inv, tsx, tdata, replaces_param, to_tag_param, from_tag_param, target, session, mSessionRouter, mModule.id), inv);
 }
 
+void PJSipSessionModule::handleInfo(pjsip_inv_session *inv, pjsip_rx_data *rdata)
+{
+    //STUB
+    return;
+}
+
 pj_bool_t PJSipSessionModule::on_rx_request(pjsip_rx_data *rdata)
 {
     pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
@@ -929,12 +935,20 @@ pj_bool_t PJSipSessionModule::on_rx_request(pjsip_rx_data *rdata)
         }
         break;
     case PJSIP_OTHER_METHOD:
+        pj_str_t info;
+        pj_cstr(&info, "INFO");
         if (dlg && !pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, pjsip_get_refer_method()))
         {
             // We are essentially stopping the pjsip code from sending a 500 here, but this will actually be handled
             // within the transaction code
             break;
         }
+        //PJSIP has no knowledge of the INFO method, so we do a straight string comparison dot dot dot
+        else if (dlg && !pj_strcmp(&rdata->msg_info.msg->line.req.method.name, &info))
+        {
+            // Like with REFER, we actually handle this in the transaction code.
+            break;
+        }
     default:
         pjsip_endpt_respond_stateless(mEndpoint, rdata, 405, NULL, NULL, NULL);
         break;
@@ -1322,6 +1336,14 @@ void PJSipSessionModule::invOnTsxStateChanged(pjsip_inv_session *inv, pjsip_tran
     {
         handleRefer(inv, e->body.tsx_state.src.rdata);
     }
+
+    pj_str_t info;
+    pj_cstr(&info, "INFO");
+    if (tsx->role == PJSIP_ROLE_UAS && tsx->state == PJSIP_TSX_STATE_TRYING &&
+            !pj_strcmp(&tsx->method.name, &info))
+    {
+        handleInfo(inv, e->body.tsx_state.src.rdata);
+    }
     //This will be our key point for updating transaction state.  This function will not be called until after a module
     //has registered itself as the transaction user, so this won't be called on the initial INVITE we receive.
     //
diff --git a/src/PJSipSessionModule.h b/src/PJSipSessionModule.h
index 7b4cd30..5b08405 100644
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@ -121,6 +121,7 @@ private:
     void handleNewInvite(pjsip_rx_data *rdata);
     void handleInviteResponse(pjsip_inv_session *inv, pjsip_rx_data *rdata, pjsip_dialog *dlg);
     void handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdata);
+    void handleInfo(pjsip_inv_session *inv, pjsip_rx_data *rdata);
     pjsip_inv_callback mInvCallback;
     pjsip_ua_init_param mUaParam;
     const std::string mName;

-----------------------------------------------------------------------


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list