[asterisk-scf-commits] asterisk-scf/integration/sip.git branch "transfer-improvements" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Mon Jul 25 17:56:56 CDT 2011
branch "transfer-improvements" has been updated
via f2ef25b81ccb00782d921aa14e3e891f4744dd09 (commit)
via 9993515f2d29a0808654f52bf981e488b2be42aa (commit)
via c4e9de5a78ef48217e9104205fe875f400c9f553 (commit)
via 1ed569652e73a9ed71484baee8f0e1ac972aa68f (commit)
via fcb2a102e93641937a78e8b22b01b1b677c429ca (commit)
via df60142aabdb696d31e49ba5c3047e1bbd25e7ff (commit)
via 822fc2955d56d229e8fffa38fc6209c6228ffb15 (commit)
via ca24fcab3d34ddf6a69bc18fe0a769339b2756fe (commit)
via e28f2fa146b52be92b5df7640ab6f8df24cfd7c5 (commit)
via 442b31018e098f0a9135da0f82d76d92d2ae9286 (commit)
via b09352f0fe360add36cc1977b6215781a33d42e1 (commit)
via 25b59a8ab75c40d5f80727357e9d939e827ab150 (commit)
via fcac39e702d0f487a386d26ed8277ce6902ce607 (commit)
via da14216b9dc0c8f37efd5d3a1a4d5591245b139d (commit)
via d5456aa0f5700ef9d53821e9695411fa2e0801fd (commit)
via e2a3f36be58aaf8457b09f2aadd7d4e897176532 (commit)
via b18bdac4a5042928247a0a708b7e62fe4cec801f (commit)
via 2b0ba42f2e557f5f5f3e5dba3b41f87a0937d8db (commit)
via c1891fda67849e50c553ccbba326ab431c8fa293 (commit)
via abc64b8ab827c6e1a59a6440f0c82ed4662cd8cb (commit)
via 5cc1decf6fbf407a4d477f74f7832af9bf1df66d (commit)
via f3ac2038009f50b1ff84d203999dc79f2a0aea56 (commit)
via e19711fb128b2538bd793dd6993fa1a89a99909e (commit)
via 4f79a16c7cb94d0b6aa5ed13c3bfdc81fc764641 (commit)
via 6577d75e59c8b2f4241103f48fd114da433c8597 (commit)
via 26ec91cf1ad7ae654b38a57e355d85cd7b2a6495 (commit)
via c36e88cc66b3a9f5e5cce710df4359e88079d9d9 (commit)
via b41a0dc88850f05a29d0adbf62016e22e625a26e (commit)
via 1b8c6f710bab05f5864611477838d6b56c673eb5 (commit)
via e528d7be81f34ac1789b74ad7415de949a1c19ed (commit)
via b61e242edd548a82eb5a492c7ffb16835746ceaa (commit)
via 32c65526dd56d0bc7e03148dfd407bfa40423fff (commit)
via f256218dea09a6d6e3e177b35d333b6881bc6ed7 (commit)
via ba77572c9c5e5d5abdff517a1f4e144440d5906f (commit)
via bd53a89af2c3104984d46c118e2b7b158155f25c (commit)
via c58ab8b3d3623ccd57d63077f902eda632faaf7d (commit)
via 59ccbfc493c091ebfe6d2a71d61026d9abf5a77c (commit)
via ef373b282be4a218a92e9981fc0c3163c181603b (commit)
via 0a84ba53e4041c3d0afcab7caf954529b60b6f63 (commit)
via 768256f0d324d42905eb9f3832c054193cd750b2 (commit)
via 162d8a50bf6df93a6bc24d06e9042b5026c088ee (commit)
via 41e944174785ff3370b4e165d491e8ff92cc0827 (commit)
via f860396ac01e1581dfe5f56ca30434c8b01b4270 (commit)
via be2641c8edb8a41556c4a0d9c2d86fb023917792 (commit)
via 1ea02fa8ec59f386d62f04a0ef3c1adb77fd5319 (commit)
via 3fa68dd21a3f9a62ca80400e48832d0e6225a2ea (commit)
via fc2f64b78c4c57c4c3b8fea3233a9fd3f52147f6 (commit)
via 575abed0a58ba2e9f321b8ccc121a32356c7288d (commit)
via b0d2423c8b01c4432c7289f9648213e16406174a (commit)
via 1dda9776c5a1f55037ac61f5290593e25a5677cb (commit)
via 34797f06098f619838f094d9af7ec1a8c3ad4724 (commit)
via cfa23a3f19760c5266a9f4be0ad9302c977bfe8a (commit)
via a6bfcd47c9f662ac6dd4a2318d96579737a12837 (commit)
via 57993cd407779a00004dc426cb282f06bccb5bd5 (commit)
via 413750665895171f8eae4c8d86ff672b04a8f7cd (commit)
via b874caeeddf70e7b3911a4312494c8ae6de1ffd4 (commit)
via 89e5e5522e81f9f9be4351eb6aab5f346a35586d (commit)
via 448088a4f28ccdf90471cb60642d28bd4fdfd589 (commit)
via abbaa0220ce9faf1e97fd4845ee7f78076436193 (commit)
via 0ffdaa56376184435e2ebb6b59dac42fbde51ab9 (commit)
via 47ce4d4e87b887297289ff6511bde2feb807a476 (commit)
via e2736843dca94388a5ad562b7096a53451e2d037 (commit)
via 9394b46cf8c83c0cfa83e73a34886aeb9f63913b (commit)
via 66b54622b2edd8c6f41fb76950e81121813804e2 (commit)
via 66c548481a50dbbaaa4f886d41af64cc39a5bfa3 (commit)
via b694e978ae5146b198914f8e114fff6333a75662 (commit)
via 1f56ea5e07117170b407e17cc298ea9a79b60860 (commit)
via 706a6986e046909d0035038412d759ba1e6c199c (commit)
via 1624b232fe8cd35ab4a88ae0aa7d74498d98e3c9 (commit)
via 591d2f8183dbed4dce5734ae09e5c2d2cb2de8c3 (commit)
via ae5e868cf90a06e489748299eca32564f248d52b (commit)
via 1a6d54ba8e42b022e2dea6c696ab26ebac0345a2 (commit)
via c5ed036baf4b2eea39a2496e8c8267be96766dc2 (commit)
via 433163526c9c788f53fb52ae4b389e3c77f7dc31 (commit)
via fa87159c9237db447843c6523f1daa7da2a67607 (commit)
via 9ab8adb83f3038c03b8c1619bebcabbffc4e352e (commit)
via cb2abe96f218864eb0088c343b3a91ffa6e578e8 (commit)
via 480dca6e1d5a251dd2ab680f776b46f37a052660 (commit)
via 871d682ad8f89f934e68326fa6b3d861479321da (commit)
via 2e6f61b3697981bb4a1af0a4f2738ff786668269 (commit)
via f8ba9bd5baffb67df87d1726c8635bb7d5d63ff2 (commit)
via 49064db0f2c505427f826c7fc9608e39d3a2ffe2 (commit)
via 72fce78916b051f6d76a4e61de9fb5d26eec10de (commit)
via 51d7a0addacb9eae0fc88bea5b010a0559b4b887 (commit)
via df0ebe1c9b2b5eb5b99f1a5e4140dd13b3a14622 (commit)
via 68f3e523c1a9ab857a1031926d7dff2760d26df1 (commit)
via c5eff00eb9e4e64bac262fbc8f0ff7631c9b5cf8 (commit)
via 5aa5e56f84e645b9c5238215ef4fdeb0eba28f20 (commit)
via dd490ab030f402537f7edac3d1fcd443bc602e68 (commit)
via 44db9747153ed1c73ff0d95cfc977ea5548403db (commit)
via 572289496c4142e8cc748cfb641efd846b2a8dc0 (commit)
via d4899c06c3c254cdff2ceb2db6d2121dc6ad1f01 (commit)
via 69d20d88cd1823c628ac51fdb9d5c86f545deede (commit)
via 65074861612bdb49965f66e09c55ccbec46f960d (commit)
via d23a05405132459594db5c41bd4485207a887cce (commit)
via 18220a9ec61fbb51381e8405c4b9c7e0e1c785a8 (commit)
via f63d75ebd26753eed1a2733ecbd21fe8f2a58044 (commit)
via b5c03db28904b7ab0b220ca5030a1dd4828169a1 (commit)
via e006915bdba4e8dead401dd98c896122e32b8974 (commit)
via 53b69af9a3afc348e8a00f2ca45ccd1225155c07 (commit)
via f3343d7b5205f981b8d4002991f233a4e4e9645e (commit)
via 53a20db873d9eb943ec65f9a6f10da125108ae94 (commit)
via 7651845251617268572d954cc1cc94d1c609f7f7 (commit)
via 529b6387bda5b3287a20d5166638d0ea08901e4d (commit)
via a90a0ae0e000a0679619e1dd2d0c065baaa5fb8c (commit)
via 1e847b293c9f7ec3e6b2f051768f59a07d66f7d7 (commit)
via d479d28083104c2f4ec3aa74f232c46a1ad2e231 (commit)
via 6913f102979144b1203fd032d1afffcf7cd8d09c (commit)
via 5f9e9fd318c13fa5d58c30a6d2ab85d33fe59866 (commit)
via 7837bf220f03f26090c509f427c003fc00deae76 (commit)
via 0910249b0079177bd957635dd46286b16e769247 (commit)
via fbfa98d635f3cd6737585691cf82b4e65a0f1570 (commit)
via b34fd7b76ef0badf930c078b692a56a8d36b6e23 (commit)
via 6a20f1ab5164bf1bbca0a3917ed5d3336773feeb (commit)
via 8635a95c6569029b979ea21c9a4de78f35dac2cb (commit)
via 41084ebbf79fb23cce9c1581b5f45c6aaffe7410 (commit)
via 783d705e83c78f171ebd2128c5dadecf8cb9e44d (commit)
via 8c1955a5240967abe7e74b8b7d5d3bc067c71842 (commit)
via aff68781848311763ebb92e299750dfe4b61eb5c (commit)
via f0d27ad5ba9caa722ce22b36975d1d4be70be762 (commit)
via 78914f7922bf4620086eef4a77bead6ff55cf79d (commit)
via f4195acb409cf8ecaac3d63e3c85a52e98bbd9b1 (commit)
via dc9a45bea83aa73e62865969c445f2a8212be462 (commit)
via 5a0a9a73584c42a5f188f3a1436512ccb6a01bbe (commit)
via acac1d74989f8aa6c28e9a9ef1b0ccb85197e30d (commit)
via 81ddb566141c01bece3cdb115aaef0727fcc1558 (commit)
from 4154f52ef1a545783458dcc089d359dab49598b2 (commit)
Summary of changes:
config/SipConfigurator.py | 58 ++-
config/test_sip.conf | 2 +
.../SipSessionManager/SipConfigurationIf.ice | 794 ++++++++++---------
.../SipSessionManager/SipStateReplicationIf.ice | 17 +
slice/SipIf.ice | 1 +
src/AuthManager.cpp | 440 +++++++++++
src/AuthManager.h | 183 +++++
src/CMakeLists.txt | 29 +
src/DebugUtil.h | 33 +
src/{PJSipLoggingModule.h => NATOptions.h} | 30 +-
src/PJSipLoggingModule.cpp | 1 +
src/PJSipManager.cpp | 327 ++++++---
src/PJSipManager.h | 83 ++-
src/PJSipModule.cpp | 15 +
src/PJSipModule.h | 12 +-
src/PJSipRegistrarModule.cpp | 831 ++++++++++++++++++++
src/PJSipRegistrarModule.h | 203 +++++
src/PJSipRegistrarModuleConstruction.cpp | 104 +++
src/PJSipSessionModule.cpp | 497 ++++---------
src/PJSipSessionModule.h | 29 +-
src/PJSipSessionModuleConstruction.cpp | 30 +-
src/PJUtil.h | 37 +
src/STUNModule.cpp | 157 ++++
src/STUNModule.h | 101 +++
src/STUNTransport.cpp | 416 ++++++++++
src/STUNTransport.h | 44 +
src/STUNTransportConfig.cpp | 131 +++
src/STUNTransportConfig.h | 52 ++
src/SipConfiguration.cpp | 191 ++++-
src/SipConfiguration.h | 2 +-
src/SipEndpoint.cpp | 75 ++-
src/SipEndpoint.h | 72 ++-
src/SipEndpointFactory.cpp | 17 +-
src/SipEndpointFactory.h | 7 +-
src/SipModule.h | 68 ++
src/SipRegistrarListener.cpp | 113 +++
src/SipRegistrarListener.h | 46 ++
src/SipSession.cpp | 429 +++++++++-
src/SipSession.h | 49 +-
src/SipSessionManagerApp.cpp | 129 +++-
src/SipSessionManagerEndpointLocator.cpp | 14 +-
src/SipStateReplicator.h | 3 +-
src/SipStateReplicatorListener.cpp | 185 +++++-
src/SipTransfer.cpp | 339 ++++++++
src/SipTransfer.h | 138 ++++
src/TCPTransport.cpp | 111 +++
src/TCPTransport.h | 41 +
src/TLSTransport.cpp | 93 +++
src/TLSTransport.h | 43 +
src/Transports.cpp | 71 ++
src/Transports.h | 74 ++
src/UDPTransport.cpp | 117 +++
src/UDPTransport.h | 41 +
53 files changed, 6090 insertions(+), 1035 deletions(-)
create mode 100644 src/AuthManager.cpp
create mode 100644 src/AuthManager.h
create mode 100644 src/DebugUtil.h
copy src/{PJSipLoggingModule.h => NATOptions.h} (50%)
create mode 100644 src/PJSipRegistrarModule.cpp
create mode 100644 src/PJSipRegistrarModule.h
create mode 100644 src/PJSipRegistrarModuleConstruction.cpp
create mode 100644 src/PJUtil.h
create mode 100644 src/STUNModule.cpp
create mode 100644 src/STUNModule.h
create mode 100644 src/STUNTransport.cpp
create mode 100644 src/STUNTransport.h
create mode 100644 src/STUNTransportConfig.cpp
create mode 100644 src/STUNTransportConfig.h
create mode 100644 src/SipModule.h
create mode 100644 src/SipRegistrarListener.cpp
create mode 100644 src/SipRegistrarListener.h
mode change 100644 => 100755 src/SipSession.cpp
create mode 100644 src/SipTransfer.cpp
create mode 100644 src/SipTransfer.h
create mode 100644 src/TCPTransport.cpp
create mode 100644 src/TCPTransport.h
create mode 100644 src/TLSTransport.cpp
create mode 100644 src/TLSTransport.h
create mode 100644 src/Transports.cpp
create mode 100644 src/Transports.h
create mode 100644 src/UDPTransport.cpp
create mode 100644 src/UDPTransport.h
- Log -----------------------------------------------------------------
commit f2ef25b81ccb00782d921aa14e3e891f4744dd09
Merge: 9993515 4154f52
Author: Mark Michelson <mmichelson at digium.com>
Date: Mon Jul 25 17:57:26 2011 -0500
Merge branch 'transfer-improvements' of git.asterisk.org:asterisk-scf/integration/sip into transfer-improvements
Conflicts:
src/PJSipSessionModule.cpp
commit 9993515f2d29a0808654f52bf981e488b2be42aa
Author: Mark Michelson <mmichelson at digium.com>
Date: Mon Jul 25 17:56:20 2011 -0500
Add some skeleton for the SessionListener and SessionCreationHooks to be used in transfers.
diff --git a/src/SipTransfer.cpp b/src/SipTransfer.cpp
index 75e5470..f67ce78 100644
--- a/src/SipTransfer.cpp
+++ b/src/SipTransfer.cpp
@@ -20,6 +20,7 @@
#include <IceUtil/UUID.h>
#include <AsteriskSCF/logger.h>
+#include <AsteriskSCF/SessionCommunications/SessionCommunicationsExtensionPointsIf.h>
using namespace AsteriskSCF::System::Logging;
@@ -35,7 +36,41 @@ namespace SipSessionManager
{
using namespace AsteriskSCF::SessionCommunications::V1;
+using namespace AsteriskSCF::SessionCommunications::ExtensionPoints::V1;
using namespace AsteriskSCF::System::WorkQueue::V1;
+using namespace AsteriskSCF::System::Hook::V1;
+
+class TransferListener : public SessionListener
+{
+ TransferListener()
+ {
+ }
+
+ void indicated(
+ const SessionPrx&,
+ const IndicationPtr&,
+ const SessionCookies&,
+ const Ice::Current&)
+ {
+ }
+};
+
+class TransferSessionCreationHook : public SessionCreationHook
+{
+ TransferSessionCreationHook()
+ {
+ }
+
+ HookResult modifySession(
+ const SessionCreationHookDataPtr&,
+ SessionCreationHookDataPtr&,
+ const Ice::Current&)
+ {
+ HookResult result;
+ result.status = Succeeded;
+ return result;
+ }
+};
HandleReferOperation::HandleReferOperation(
pjsip_inv_session *inv,
commit c4e9de5a78ef48217e9104205fe875f400c9f553
Author: Mark Michelson <mmichelson at digium.com>
Date: Mon Jul 25 16:58:21 2011 -0500
Move logic for transfers to a separate file.
This cleans things up quite a bit and will make adding the temporary session
listener, etc. much easier to follow once that is done.
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c5b8ec6..81f2bec 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -23,6 +23,8 @@ astscf_component_add_files(SipSessionManager PJSipManager.cpp)
astscf_component_add_files(SipSessionManager PJSipManager.h)
astscf_component_add_files(SipSessionManager PJSipModule.cpp)
astscf_component_add_files(SipSessionManager PJSipModule.h)
+astscf_component_add_files(SipSessionManager SipTransfer.cpp)
+astscf_component_add_files(SipSessionManager SipTransfer.h)
astscf_component_add_files(SipSessionManager PJSipSessionModule.cpp)
astscf_component_add_files(SipSessionManager PJSipSessionModuleConstruction.cpp)
astscf_component_add_files(SipSessionManager PJSipSessionModule.h)
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 12e75ac..91ce3c1 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -15,6 +15,7 @@
*/
#include "PJSipSessionModule.h"
+#include "SipTransfer.h"
#include "SipEndpoint.h"
#include "SipEndpointFactory.h"
#include "SipSession.h"
@@ -22,7 +23,6 @@
#include "SipStateReplicator.h"
#include <IceUtil/UUID.h>
-#include <boost/algorithm/string.hpp>
#include <AsteriskSCF/Core/Endpoint/EndpointIf.h>
#include <AsteriskSCF/Core/Routing/RoutingIf.h>
@@ -719,352 +719,6 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
sessionWork->enqueueWork(new SessionCreationOperation(this, caller, mSessionRouter, inv_session, tdata, replaced_dlg, destination));
}
-class HandleReferOperation : public SipQueueableOperation
-{
-public:
- HandleReferOperation(
- pjsip_inv_session *inv,
- pjsip_transaction *tsx,
- pjsip_tx_data *tdata,
- pjsip_param *replaces_param,
- pjsip_param *to_tag_param,
- pjsip_param *from_tag_param,
- const std::string& referredBy,
- const std::string& target,
- const SipSessionPtr& session,
- const AsteriskSCF::Discovery::SmartProxy<SessionRouterPrx>& sessionRouter,
- const int moduleId)
- : mInv(inv), mTsx(tsx), mTdata(tdata),
- mReplacesParam(replaces_param ? new pjsip_param(*replaces_param) : NULL),
- mToTagParam(to_tag_param ? new pjsip_param(*to_tag_param) : NULL),
- mFromTagParam(from_tag_param ? new pjsip_param(*from_tag_param) : NULL),
- mReferredBy(referredBy),
- mTarget(target),
- mSession(session), mSessionRouter(sessionRouter),
- mModuleId(moduleId), mReferCSeq(tsx->cseq), mWasWithDestination(false) {}
-
- ~HandleReferOperation()
- {
- delete mReplacesParam;
- delete mToTagParam;
- delete mFromTagParam;
- }
-
-protected:
- /**
- * This is what is initially called when the operation is queued.
- *
- * In this portion, we grab some essential data out of the target URI and use
- * it to call out to the routing service, either ConnectBridgedSessions or
- * ConnectBridgedSessionWithDestination.
- *
- * When this operation is successful, it will result in work for this session
- * being suspended until the routing service returns.
- */
- SuspendableWorkResult initial(const SuspendableWorkListenerPtr& workListener)
- {
- // Determine if this is a blind transfer or an attended transfer
-
- if (mReplacesParam)
- {
- pjsip_dialog *other_dlg = NULL;
-
- if (mToTagParam && mFromTagParam)
- {
- other_dlg = pjsip_ua_find_dialog(&mReplacesParam->value, &mToTagParam->value, &mFromTagParam->value,
- PJ_TRUE);
- }
- else
- {
- // It is possible for the to and from tag value to be present within the Replaces parameter value, so try to
- // parse it out
- std::string replaces_value_tmp = std::string(pj_strbuf(&mReplacesParam->value),
- pj_strlen(&mReplacesParam->value));
- std::vector<std::string> params;
-
- boost::split(params, replaces_value_tmp, boost::is_any_of(";"));
-
- //The first value will be the actual replaces value.
- std::string replaces = params.front();
-
- std::string to;
- std::string from;
- std::string fromTagParamName("from-tag=");
- std::string toTagParamName("to-tag=");
- for(std::vector<std::string>::iterator iter = params.begin();
- iter != params.end(); ++iter)
- {
- if (iter->compare(0, toTagParamName.size(), toTagParamName) == 0)
- {
- to = iter->substr(toTagParamName.size());
- }
- if (iter->compare(0, fromTagParamName.size(), fromTagParamName) == 0)
- {
- from = iter->substr(fromTagParamName.size());
- }
- }
-
- if (from.empty() || to.empty())
- {
- lg(Debug) << "handleRefer() sending 400 due to From or To missing. ";
- pjsip_dlg_modify_response(mInv->dlg, mTdata, 400, NULL);
- pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
- return Complete;
- }
-
- pj_str_t to_tag_str = pj_str((char*)to.c_str());
- pj_str_t from_tag_str = pj_str((char*)from.c_str());
- pj_str_t replaces_tag_str = pj_str((char*)replaces.c_str());
-
- other_dlg = pjsip_ua_find_dialog(&replaces_tag_str, &to_tag_str, &from_tag_str, PJ_TRUE);
- }
-
- if (!other_dlg)
- {
- lg(Debug) << "handleRefer() sending PJSIP_SC_CALL_TSX_DOES_NOT_EXIST due to no other_dlg. ";
- pjsip_dlg_modify_response(mInv->dlg, mTdata, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL);
- pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
- return Complete;
- }
-
- pjsip_inv_session *other_inv = pjsip_dlg_get_inv_session(other_dlg);
-
- if (!other_inv)
- {
- lg(Debug) << "handleRefer() sending PJSIP_SC_CALL_TSX_DOES_NOT_EXIST due to no other_inv. ";
- pjsip_dlg_modify_response(mInv->dlg, mTdata, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL);
- pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
- pjsip_dlg_dec_lock(other_dlg);
- return Complete;
- }
-
- if (other_inv->state >= PJSIP_INV_STATE_DISCONNECTED)
- {
- lg(Debug) << "handleRefer() sending PJSIP_SC_DECLINE due to state > PJSIP_INV_STATE_DISCONNECTED. ";
-
- pjsip_dlg_modify_response(mInv->dlg, mTdata, PJSIP_SC_DECLINE, NULL);
- pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
- pjsip_dlg_dec_lock(other_dlg);
- return Complete;
- }
-
- if (other_inv->state <= PJSIP_INV_STATE_EARLY && other_inv->role != PJSIP_ROLE_UAC)
- {
- lg(Debug) << "handleRefer() sending PJSIP_SC_CALL_TSX_DOES_NOT_EXIST due to other_inv->state < PJSIP_INV_STATE_EARLY and role not UAC. ";
-
- pjsip_dlg_modify_response(mInv->dlg, mTdata, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL);
- pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
- pjsip_dlg_dec_lock(other_dlg);
- return Complete;
- }
-
- PJSipSessionModInfo *other_session_mod_info = (PJSipSessionModInfo*)other_inv->mod_data[mModuleId];
- SipSessionPtr other_session = other_session_mod_info->getSessionPtr();
-
- //Go ahead and send a 202 for the REFER. We can send a NOTIFY later to indicate if something
- //on the outbound leg went awry.
- pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
- try
- {
- std::string operationId = ::IceUtil::generateUUID();
- SipAMICallbackPtr cb(new SipAMICallback(workListener, mSession, this, false, true));
- Ice::CallbackPtr d = Ice::newCallback(cb, &SipAMICallback::callback);
-
- lg(Debug) << "handleRefer() calling router connectBridgedSessions(). ";
- mSessionRouter->begin_connectBridgedSessions(operationId, mSession->getSessionProxy(), other_session->getSessionProxy(), d);
- pjsip_dlg_dec_lock(other_dlg);
- return Complete;
- }
- catch (const Ice::CommunicatorDestroyedException &)
- {
- lg(Debug) << "handleRefer() sending 503 due to communicator destruction";
- pjsip_dlg_modify_response(mInv->dlg, mTdata, 503, NULL);
- pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
- pjsip_dlg_dec_lock(other_dlg);
- return Complete;
- }
- }
- else
- {
- //Go ahead and send a 202 for the REFER. We can send a NOTIFY later to indicate if something
- //on the outbound leg went awry.
- pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
-
- // Now that we have the target user we can pass this into routing and go on our marry way
- try
- {
- std::string operationId = ::IceUtil::generateUUID();
- PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)mInv->mod_data[mModuleId];
- SipSessionPtr session = session_mod_info->getSessionPtr();
- SipAMICallbackPtr cb(new SipAMICallback(workListener, mSession, this, false, true));
- Ice::CallbackPtr d = Ice::newCallback(cb, &SipAMICallback::callback);
-
- lg(Debug) << "handleRefer() calling router connectBridgedSessionsWithDestination(). ";
- lg(Debug) << "Session to replace is with endpoint " << session->getEndpoint()->getName();
- lg(Debug) << "Destination is " << mTarget;
- mWasWithDestination = true;
- mSessionRouter->begin_connectBridgedSessionsWithDestination(operationId, session->getSessionProxy(), mTarget, 0, d);
- return Complete;
- }
- catch (const Ice::CommunicatorDestroyedException &)
- {
- lg(Debug) << "handleRefer() sending 503 due to communicator destruction";
- pjsip_dlg_modify_response(mInv->dlg, mTdata, 503, NULL);
- pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
- return Complete;
- }
- }
- };
-
- /**
- * Once the routing service has allowed for work to be resumed,
- * this is where the final work is done
- */
- SuspendableWorkResult calledBack(const SuspendableWorkListenerPtr&)
- {
- assert(mAsyncResult);
- SessionRouterPrx router = SessionRouterPrx::uncheckedCast(mAsyncResult->getProxy());
-
- // We need to send a NOTIFY to indicate how things went on the other leg.
- // XXX Once we have a subscription module written, we can actually use it.
-
- pjsip_tx_data *tdata = createNotify();
-
- try
- {
- if (mWasWithDestination)
- {
- router->end_connectBridgedSessionsWithDestination(mAsyncResult);
- }
- else
- {
- router->end_connectBridgedSessions(mAsyncResult);
- }
- }
- catch (const AsteriskSCF::Core::Routing::V1::DestinationNotFoundException &)
- {
- lg(Debug) << "ConnectBridgedSessionsWithDestination sending 404 due to destination not found.";
-
- addNotifyBody(tdata, "SIP/2.0 404 Not Found");
- pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
- return Complete;
- }
- catch (const std::exception &e)
- {
- lg(Debug) << "ConnectBridgedSessionsCallback sending 400 due to exception: " << e.what();
-
- addNotifyBody(tdata, "SIP/2.0 400 Bad Request");
- pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
- return Complete;
- }
-
- addNotifyBody(tdata, "SIP/2.0 200 OK");
- pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
-
- Ice::Current current;
- lg(Debug) << "ConnectBridgedSessionsCallback calling session->stop(). ";
- mSession->stop(new ResponseCode(16), current);
- return Complete;
- }
-
-private:
-
- pjsip_tx_data* createNotify()
- {
- pjsip_tx_data *tdata;
- pjsip_dlg_create_request(mInv->dlg, pjsip_get_notify_method(), -1, &tdata);
-
- pjsip_event_hdr *event = pjsip_event_hdr_create(tdata->pool);
- pj_strdup2(tdata->pool, &event->event_type, "refer");
- char idbuf[20];
- pj_ansi_snprintf(idbuf, sizeof(idbuf), "%d", mReferCSeq);
- pj_strdup2(tdata->pool, &event->id_param, idbuf);
- pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) event);
-
- pjsip_sub_state_hdr *subState = pjsip_sub_state_hdr_create(tdata->pool);
- pj_strdup2(tdata->pool, &subState->sub_state, "terminated");
- pj_strdup2(tdata->pool, &subState->reason_param, "noresource");
- pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) subState);
-
- return tdata;
- }
- void addNotifyBody(pjsip_tx_data *tdata, const char *bodyText)
- {
- pj_str_t type;
- pj_cstr(&type, "message");
- pj_str_t subtype;
- pj_cstr(&subtype, "sipfrag;version=2.0");
-
- pj_str_t bodyStr;
- pj_cstr(&bodyStr, bodyText);
- pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
- tdata->msg->body = body;
- }
- /**
- * The INVITE session, which contains the dialog on which the
- * REFER was received.
- */
- pjsip_inv_session *mInv;
- /**
- * The REFER transaction
- */
- pjsip_transaction *mTsx;
- /**
- * The transmission data for our REFER response. We set this
- * up to default to a 200 OK response and alter it if necessary.
- */
- pjsip_tx_data *mTdata;
- /**
- * The Replaces parameter from the URI in the Refer-To header
- * of the REFER that triggered this operation.
- */
- pjsip_param *mReplacesParam;
- /**
- * The to-tag parameter from the URI in the Refer-To header
- * of the REFER that triggered this operation.
- */
- pjsip_param *mToTagParam;
- /**
- * The from-tag parameter from the URI in the Refer-To header
- * of the REFER that triggered this operation.
- */
- pjsip_param *mFromTagParam;
- /**
- * The content from the Referred-By header, if one existed.
- * XXX We currently have this handy, but we don't actually do
- * anything with it. This is because we don't have a way to place
- * this information in the outgoing INVITE.
- */
- const std::string mReferredBy;
- /**
- * The user portion of the URI in the Refer-To header of the
- * REFER that triggered this operation.
- */
- const std::string mTarget;
- /**
- * The SipSession on which this work is executed
- */
- SipSessionPtr mSession;
- /**
- * Session router...nothing more to say really
- */
- AsteriskSCF::Discovery::SmartProxy<SessionRouterPrx> mSessionRouter;
- /**
- * The identifier of the PJSipSessionModule. Used for retrieving module data from mInv
- */
- const int mModuleId;
- /**
- * The CSeq of the REFER
- */
- pj_int32_t mReferCSeq;
- /**
- * Helps determine which end_* method to call on the session router when AMI completes.
- * XXX It may be more elegant to handle this by sending a cookie to the AMI method
- * instead.
- */
- bool mWasWithDestination;
-};
-
void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdata)
{
//rdata structures are not safe to shallow copy to a queuable operation. Get
diff --git a/src/SipTransfer.cpp b/src/SipTransfer.cpp
new file mode 100644
index 0000000..75e5470
--- /dev/null
+++ b/src/SipTransfer.cpp
@@ -0,0 +1,304 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include "SipTransfer.h"
+
+#include <boost/algorithm/string.hpp>
+#include <IceUtil/UUID.h>
+
+#include <AsteriskSCF/logger.h>
+
+using namespace AsteriskSCF::System::Logging;
+
+namespace
+{
+Logger lg = getLoggerFactory().getLogger("AsteriskSCF.SipSessionManager");
+}
+
+namespace AsteriskSCF
+{
+
+namespace SipSessionManager
+{
+
+using namespace AsteriskSCF::SessionCommunications::V1;
+using namespace AsteriskSCF::System::WorkQueue::V1;
+
+HandleReferOperation::HandleReferOperation(
+ pjsip_inv_session *inv,
+ pjsip_transaction *tsx,
+ pjsip_tx_data *tdata,
+ pjsip_param *replaces_param,
+ pjsip_param *to_tag_param,
+ pjsip_param *from_tag_param,
+ const std::string& referredBy,
+ const std::string& target,
+ const SipSessionPtr& session,
+ const AsteriskSCF::Discovery::SmartProxy<SessionRouterPrx>& sessionRouter,
+ const int moduleId)
+ : mInv(inv), mTsx(tsx), mTdata(tdata),
+ mReplacesParam(replaces_param ? new pjsip_param(*replaces_param) : NULL),
+ mToTagParam(to_tag_param ? new pjsip_param(*to_tag_param) : NULL),
+ mFromTagParam(from_tag_param ? new pjsip_param(*from_tag_param) : NULL),
+ mReferredBy(referredBy),
+ mTarget(target),
+ mSession(session), mSessionRouter(sessionRouter),
+ mModuleId(moduleId), mReferCSeq(tsx->cseq), mWasWithDestination(false) {}
+
+HandleReferOperation::~HandleReferOperation()
+{
+ delete mReplacesParam;
+ delete mToTagParam;
+ delete mFromTagParam;
+}
+
+SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListenerPtr& workListener)
+{
+ // Determine if this is a blind transfer or an attended transfer
+
+ if (mReplacesParam)
+ {
+ pjsip_dialog *other_dlg = NULL;
+
+ if (mToTagParam && mFromTagParam)
+ {
+ other_dlg = pjsip_ua_find_dialog(&mReplacesParam->value, &mToTagParam->value, &mFromTagParam->value,
+ PJ_TRUE);
+ }
+ else
+ {
+ // It is possible for the to and from tag value to be present within the Replaces parameter value, so try to
+ // parse it out
+ std::string replaces_value_tmp = std::string(pj_strbuf(&mReplacesParam->value),
+ pj_strlen(&mReplacesParam->value));
+ std::vector<std::string> params;
+
+ boost::split(params, replaces_value_tmp, boost::is_any_of(";"));
+
+ //The first value will be the actual replaces value.
+ std::string replaces = params.front();
+
+ std::string to;
+ std::string from;
+ std::string fromTagParamName("from-tag=");
+ std::string toTagParamName("to-tag=");
+ for(std::vector<std::string>::iterator iter = params.begin();
+ iter != params.end(); ++iter)
+ {
+ if (iter->compare(0, toTagParamName.size(), toTagParamName) == 0)
+ {
+ to = iter->substr(toTagParamName.size());
+ }
+ if (iter->compare(0, fromTagParamName.size(), fromTagParamName) == 0)
+ {
+ from = iter->substr(fromTagParamName.size());
+ }
+ }
+
+ if (from.empty() || to.empty())
+ {
+ lg(Debug) << "handleRefer() sending 400 due to From or To missing. ";
+ pjsip_dlg_modify_response(mInv->dlg, mTdata, 400, NULL);
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+ return Complete;
+ }
+
+ pj_str_t to_tag_str = pj_str((char*)to.c_str());
+ pj_str_t from_tag_str = pj_str((char*)from.c_str());
+ pj_str_t replaces_tag_str = pj_str((char*)replaces.c_str());
+
+ other_dlg = pjsip_ua_find_dialog(&replaces_tag_str, &to_tag_str, &from_tag_str, PJ_TRUE);
+ }
+
+ if (!other_dlg)
+ {
+ lg(Debug) << "handleRefer() sending PJSIP_SC_CALL_TSX_DOES_NOT_EXIST due to no other_dlg. ";
+ pjsip_dlg_modify_response(mInv->dlg, mTdata, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL);
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+ return Complete;
+ }
+
+ pjsip_inv_session *other_inv = pjsip_dlg_get_inv_session(other_dlg);
+
+ if (!other_inv)
+ {
+ lg(Debug) << "handleRefer() sending PJSIP_SC_CALL_TSX_DOES_NOT_EXIST due to no other_inv. ";
+ pjsip_dlg_modify_response(mInv->dlg, mTdata, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL);
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+ pjsip_dlg_dec_lock(other_dlg);
+ return Complete;
+ }
+
+ if (other_inv->state >= PJSIP_INV_STATE_DISCONNECTED)
+ {
+ lg(Debug) << "handleRefer() sending PJSIP_SC_DECLINE due to state > PJSIP_INV_STATE_DISCONNECTED. ";
+
+ pjsip_dlg_modify_response(mInv->dlg, mTdata, PJSIP_SC_DECLINE, NULL);
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+ pjsip_dlg_dec_lock(other_dlg);
+ return Complete;
+ }
+
+ if (other_inv->state <= PJSIP_INV_STATE_EARLY && other_inv->role != PJSIP_ROLE_UAC)
+ {
+ lg(Debug) << "handleRefer() sending PJSIP_SC_CALL_TSX_DOES_NOT_EXIST due to other_inv->state < PJSIP_INV_STATE_EARLY and role not UAC. ";
+
+ pjsip_dlg_modify_response(mInv->dlg, mTdata, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL);
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+ pjsip_dlg_dec_lock(other_dlg);
+ return Complete;
+ }
+
+ PJSipSessionModInfo *other_session_mod_info = (PJSipSessionModInfo*)other_inv->mod_data[mModuleId];
+ SipSessionPtr other_session = other_session_mod_info->getSessionPtr();
+
+ //Go ahead and send a 202 for the REFER. We can send a NOTIFY later to indicate if something
+ //on the outbound leg went awry.
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+ try
+ {
+ std::string operationId = ::IceUtil::generateUUID();
+ SipAMICallbackPtr cb(new SipAMICallback(workListener, mSession, this, false, true));
+ Ice::CallbackPtr d = Ice::newCallback(cb, &SipAMICallback::callback);
+
+ lg(Debug) << "handleRefer() calling router connectBridgedSessions(). ";
+ mSessionRouter->begin_connectBridgedSessions(operationId, mSession->getSessionProxy(), other_session->getSessionProxy(), d);
+ pjsip_dlg_dec_lock(other_dlg);
+ return Complete;
+ }
+ catch (const Ice::CommunicatorDestroyedException &)
+ {
+ lg(Debug) << "handleRefer() sending 503 due to communicator destruction";
+ pjsip_dlg_modify_response(mInv->dlg, mTdata, 503, NULL);
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+ pjsip_dlg_dec_lock(other_dlg);
+ return Complete;
+ }
+ }
+ else
+ {
+ //Go ahead and send a 202 for the REFER. We can send a NOTIFY later to indicate if something
+ //on the outbound leg went awry.
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+
+ // Now that we have the target user we can pass this into routing and go on our marry way
+ try
+ {
+ std::string operationId = ::IceUtil::generateUUID();
+ PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)mInv->mod_data[mModuleId];
+ SipSessionPtr session = session_mod_info->getSessionPtr();
+ SipAMICallbackPtr cb(new SipAMICallback(workListener, mSession, this, false, true));
+ Ice::CallbackPtr d = Ice::newCallback(cb, &SipAMICallback::callback);
+
+ lg(Debug) << "handleRefer() calling router connectBridgedSessionsWithDestination(). ";
+ lg(Debug) << "Session to replace is with endpoint " << session->getEndpoint()->getName();
+ lg(Debug) << "Destination is " << mTarget;
+ mWasWithDestination = true;
+ mSessionRouter->begin_connectBridgedSessionsWithDestination(operationId, session->getSessionProxy(), mTarget, 0, d);
+ return Complete;
+ }
+ catch (const Ice::CommunicatorDestroyedException &)
+ {
+ lg(Debug) << "handleRefer() sending 503 due to communicator destruction";
+ pjsip_dlg_modify_response(mInv->dlg, mTdata, 503, NULL);
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+ return Complete;
+ }
+ }
+};
+
+SuspendableWorkResult HandleReferOperation::calledBack(const SuspendableWorkListenerPtr&)
+{
+ assert(mAsyncResult);
+ SessionRouterPrx router = SessionRouterPrx::uncheckedCast(mAsyncResult->getProxy());
+
+ // We need to send a NOTIFY to indicate how things went on the other leg.
+ // XXX Once we have a subscription module written, we can actually use it.
+
+ pjsip_tx_data *tdata = createNotify();
+
+ try
+ {
+ if (mWasWithDestination)
+ {
+ router->end_connectBridgedSessionsWithDestination(mAsyncResult);
+ }
+ else
+ {
+ router->end_connectBridgedSessions(mAsyncResult);
+ }
+ }
+ catch (const AsteriskSCF::Core::Routing::V1::DestinationNotFoundException &)
+ {
+ lg(Debug) << "ConnectBridgedSessionsWithDestination sending 404 due to destination not found.";
+
+ addNotifyBody(tdata, "SIP/2.0 404 Not Found");
+ pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+ return Complete;
+ }
+ catch (const std::exception &e)
+ {
+ lg(Debug) << "ConnectBridgedSessionsCallback sending 400 due to exception: " << e.what();
+
+ addNotifyBody(tdata, "SIP/2.0 400 Bad Request");
+ pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+ return Complete;
+ }
+
+ addNotifyBody(tdata, "SIP/2.0 200 OK");
+ pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+
+ Ice::Current current;
+ lg(Debug) << "ConnectBridgedSessionsCallback calling session->stop(). ";
+ mSession->stop(new ResponseCode(16), current);
+ return Complete;
+}
+
+pjsip_tx_data* HandleReferOperation::createNotify()
+{
+ pjsip_tx_data *tdata;
+ pjsip_dlg_create_request(mInv->dlg, pjsip_get_notify_method(), -1, &tdata);
+
+ pjsip_event_hdr *event = pjsip_event_hdr_create(tdata->pool);
+ pj_strdup2(tdata->pool, &event->event_type, "refer");
+ char idbuf[20];
+ pj_ansi_snprintf(idbuf, sizeof(idbuf), "%d", mReferCSeq);
+ pj_strdup2(tdata->pool, &event->id_param, idbuf);
+ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) event);
+
+ pjsip_sub_state_hdr *subState = pjsip_sub_state_hdr_create(tdata->pool);
+ pj_strdup2(tdata->pool, &subState->sub_state, "terminated");
+ pj_strdup2(tdata->pool, &subState->reason_param, "noresource");
+ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) subState);
+
+ return tdata;
+}
+
+void HandleReferOperation::addNotifyBody(pjsip_tx_data *tdata, const char *bodyText)
+{
+ pj_str_t type;
+ pj_cstr(&type, "message");
+ pj_str_t subtype;
+ pj_cstr(&subtype, "sipfrag;version=2.0");
+
+ pj_str_t bodyStr;
+ pj_cstr(&bodyStr, bodyText);
+ pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
+ tdata->msg->body = body;
+}
+
+}; //end namespace SipSessionManager
+}; //end namespace AsteriskSCF
diff --git a/src/SipTransfer.h b/src/SipTransfer.h
new file mode 100644
index 0000000..1cb95b1
--- /dev/null
+++ b/src/SipTransfer.h
@@ -0,0 +1,138 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include "PJSipSessionModule.h"
+
+#include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
+
+namespace AsteriskSCF
+{
+
+namespace SipSessionManager
+{
+
+class HandleReferOperation : public SipQueueableOperation
+{
+public:
+ HandleReferOperation(
+ pjsip_inv_session *inv,
+ pjsip_transaction *tsx,
+ pjsip_tx_data *tdata,
+ pjsip_param *replaces_param,
+ pjsip_param *to_tag_param,
+ pjsip_param *from_tag_param,
+ const std::string& referredBy,
+ const std::string& target,
+ const SipSessionPtr& session,
+ const AsteriskSCF::Discovery::SmartProxy<AsteriskSCF::SessionCommunications::V1::SessionRouterPrx>& sessionRouter,
+ const int moduleId);
+
+ ~HandleReferOperation();
+
+protected:
+ /**
+ * This is what is initially called when the operation is queued.
+ *
+ * In this portion, we grab some essential data out of the target URI and use
+ * it to call out to the routing service, either ConnectBridgedSessions or
+ * ConnectBridgedSessionWithDestination.
+ *
+ * When this operation is successful, it will result in work for this session
+ * being suspended until the routing service returns.
+ */
+ AsteriskSCF::System::WorkQueue::V1::SuspendableWorkResult initial(
+ const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkListenerPtr& workListener);
+
+ /**
+ * Once the routing service has allowed for work to be resumed,
+ * this is where the final work is done
+ */
+ AsteriskSCF::System::WorkQueue::V1::SuspendableWorkResult calledBack(
+ const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkListenerPtr&);
+
+private:
+
+ pjsip_tx_data* createNotify();
+
+ void addNotifyBody(pjsip_tx_data *tdata, const char *bodyText);
+
+ /**
+ * The INVITE session, which contains the dialog on which the
+ * REFER was received.
+ */
+ pjsip_inv_session *mInv;
+ /**
+ * The REFER transaction
+ */
+ pjsip_transaction *mTsx;
+ /**
+ * The transmission data for our REFER response. We set this
+ * up to default to a 200 OK response and alter it if necessary.
+ */
+ pjsip_tx_data *mTdata;
+ /**
+ * The Replaces parameter from the URI in the Refer-To header
+ * of the REFER that triggered this operation.
+ */
+ pjsip_param *mReplacesParam;
+ /**
+ * The to-tag parameter from the URI in the Refer-To header
+ * of the REFER that triggered this operation.
+ */
+ pjsip_param *mToTagParam;
+ /**
+ * The from-tag parameter from the URI in the Refer-To header
+ * of the REFER that triggered this operation.
+ */
+ pjsip_param *mFromTagParam;
+ /**
+ * The content from the Referred-By header, if one existed.
+ * XXX We currently have this handy, but we don't actually do
+ * anything with it. This is because we don't have a way to place
+ * this information in the outgoing INVITE.
+ */
+ const std::string mReferredBy;
+ /**
+ * The user portion of the URI in the Refer-To header of the
+ * REFER that triggered this operation.
+ */
+ const std::string mTarget;
+ /**
+ * The SipSession on which this work is executed
+ */
+ SipSessionPtr mSession;
+ /**
+ * Session router...nothing more to say really
+ */
+ AsteriskSCF::Discovery::SmartProxy<AsteriskSCF::SessionCommunications::V1::SessionRouterPrx> mSessionRouter;
+ /**
+ * The identifier of the PJSipSessionModule. Used for retrieving module data from mInv
+ */
+ const int mModuleId;
+ /**
+ * The CSeq of the REFER
+ */
+ pj_int32_t mReferCSeq;
+ /**
+ * Helps determine which end_* method to call on the session router when AMI completes.
+ * XXX It may be more elegant to handle this by sending a cookie to the AMI method
+ * instead.
+ */
+ bool mWasWithDestination;
+};
+
+}; //end namespace SipSessionManager
+}; //end namespace AsteriskSCF
commit 1ed569652e73a9ed71484baee8f0e1ac972aa68f
Author: Mark Michelson <mmichelson at digium.com>
Date: Mon Jul 25 16:29:27 2011 -0500
Put one-shot hooks into session creation.
This should be all set up now...
Now to try to create a hook to use during transfers.
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 989f593..37d7fbe 100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -467,7 +467,7 @@ SipSession::SipSession(
const PJSipManagerPtr& manager,
const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
- const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx&,
+ const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx& oneShotHook,
bool /* ipv6 */,
bool isUAC,
const NATEndpointOptions& natOptions)
@@ -478,8 +478,6 @@ SipSession::SipSession(
mImplPriv->mListeners.push_back(listener);
}
- activateIceObjects(mImplPriv->mManager->getSessionModule()->getSessionCreationHooks());
-
mImplPriv->mMediaSession = new SipMediaSession(this);
mImplPriv->mMediaSessionProxy =
AsteriskSCF::Media::V1::SessionPrx::uncheckedCast(adapter->addWithUUID(mImplPriv->mMediaSession));
@@ -489,6 +487,14 @@ SipSession::SipSession(
lg(Debug) << "New session is UAC, so we're creating the necessary PJSIP structures";
initializePJSIPStructs();
}
+
+ AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookSeq hooks =
+ mImplPriv->mManager->getSessionModule()->getSessionCreationHooks();
+ if (oneShotHook)
+ {
+ hooks.push_back(oneShotHook);
+ }
+ activateIceObjects(hooks);
}
/**
@@ -505,13 +511,11 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter,
const PJSipManagerPtr& manager,
const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
- const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx&,
+ const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx& oneShotHook,
bool isUAC,
const NATEndpointOptions& natOptions)
: mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica, natOptions))
{
- activateIceObjects(mImplPriv->mManager->getSessionModule()->getSessionCreationHooks());
-
mImplPriv->mMediaSession = new SipMediaSession(this);
mImplPriv->mMediaSessionProxy =
AsteriskSCF::Media::V1::SessionPrx::uncheckedCast(adapter->add(mImplPriv->mMediaSession, mediaid));
@@ -524,6 +528,14 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter,
{
initializePJSIPStructs();
}
+
+ AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookSeq hooks =
+ mImplPriv->mManager->getSessionModule()->getSessionCreationHooks();
+ if (oneShotHook)
+ {
+ hooks.push_back(oneShotHook);
+ }
+ activateIceObjects(hooks);
}
class AddListenerOperation : public SuspendableWork
commit fcb2a102e93641937a78e8b22b01b1b677c429ca
Author: Mark Michelson <mmichelson at digium.com>
Date: Mon Jul 25 15:56:36 2011 -0500
Initial changes needed to satisfy one-shot hook slice API changes.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 09bc8d5..12e75ac 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -512,7 +512,7 @@ protected:
SuspendableWorkListenerPtr listener = 0;
SipAMICallbackPtr cb(new SipAMICallback(listener, mSession, this, false, true));
Ice::CallbackPtr d = Ice::newCallback(cb, &SipAMICallback::callback);
- mSessionRouter->begin_routeSession(operationId, mSession->getSessionProxy(), mDestination, d);
+ mSessionRouter->begin_routeSession(operationId, mSession->getSessionProxy(), mDestination, 0, d);
}
}
catch (const Ice::CommunicatorDestroyedException &)
@@ -903,7 +903,7 @@ protected:
lg(Debug) << "Session to replace is with endpoint " << session->getEndpoint()->getName();
lg(Debug) << "Destination is " << mTarget;
mWasWithDestination = true;
- mSessionRouter->begin_connectBridgedSessionsWithDestination(operationId, session->getSessionProxy(), mTarget, d);
+ mSessionRouter->begin_connectBridgedSessionsWithDestination(operationId, session->getSessionProxy(), mTarget, 0, d);
return Complete;
}
catch (const Ice::CommunicatorDestroyedException &)
diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index 8c5465a..0436a1a 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -354,8 +354,11 @@ std::string SipEndpoint::getId(const Ice::Current&)
return mImplPriv->mEndpointProxy->ice_getIdentity().name;
}
-AsteriskSCF::SessionCommunications::V1::SessionPrx SipEndpoint::createSession(const std::string& destination,
- const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener, const Ice::Current&)
+AsteriskSCF::SessionCommunications::V1::SessionPrx SipEndpoint::createSession(
+ const std::string& destination,
+ const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
+ const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx& oneShotHook,
+ const Ice::Current&)
{
std::cout << "Got call over Ice to create a session for endpoint " << mImplPriv->mName << std::endl;
@@ -367,7 +370,7 @@ AsteriskSCF::SessionCommunications::V1::SessionPrx SipEndpoint::createSession(co
}
SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, listener, mImplPriv->mManager,
- mImplPriv->mServiceLocator, mImplPriv->mReplica, mImplPriv->mConfig.sessionConfig.rtpOverIPv6, true,
+ mImplPriv->mServiceLocator, mImplPriv->mReplica, oneShotHook, mImplPriv->mConfig.sessionConfig.rtpOverIPv6, true,
NATEndpointOptions(mImplPriv->mConfig.sessionConfig.rtpOverICE, mImplPriv->mConfig.sessionConfig.rtpICEIncludeTURN,
mImplPriv->mConfig.transportConfig.enableNAT));
mImplPriv->mSessions.push_back(session);
@@ -378,7 +381,7 @@ AsteriskSCF::SessionCommunications::V1::SessionPrx SipEndpoint::createSession(co
AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const std::string& destination)
{
SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, 0, mImplPriv->mManager,
- mImplPriv->mServiceLocator, mImplPriv->mReplica, mImplPriv->mConfig.sessionConfig.rtpOverIPv6, false,
+ mImplPriv->mServiceLocator, mImplPriv->mReplica, 0, mImplPriv->mConfig.sessionConfig.rtpOverIPv6, false,
NATEndpointOptions(mImplPriv->mConfig.sessionConfig.rtpOverICE, mImplPriv->mConfig.sessionConfig.rtpICEIncludeTURN,
mImplPriv->mConfig.transportConfig.enableNAT)
);
@@ -393,7 +396,7 @@ AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const s
const AsteriskSCF::Media::V1::StreamSinkSeq& sinks)
{
SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, sessionid, mediaid, mediasessions,
- sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica, false,
+ sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica, 0, false,
NATEndpointOptions(mImplPriv->mConfig.sessionConfig.rtpOverICE, mImplPriv->mConfig.sessionConfig.rtpICEIncludeTURN,
mImplPriv->mConfig.transportConfig.enableNAT));
mImplPriv->mSessions.push_back(session);
diff --git a/src/SipEndpoint.h b/src/SipEndpoint.h
index 2ce13ff..ce2e7de 100644
--- a/src/SipEndpoint.h
+++ b/src/SipEndpoint.h
@@ -276,8 +276,11 @@ public:
* Interface implementation.
*/
std::string getId(const Ice::Current&);
- AsteriskSCF::SessionCommunications::V1::SessionPrx createSession(const std::string&,
- const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx&, const Ice::Current&);
+ AsteriskSCF::SessionCommunications::V1::SessionPrx createSession(
+ const std::string&,
+ const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx&,
+ const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx&,
+ const Ice::Current&);
AsteriskSCF::SessionCommunications::V1::SessionSeq getSessions(const Ice::Current&);
/**
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index fd5758e..989f593 100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -459,10 +459,18 @@ void SipSession::activateIceObjects(const AsteriskSCF::SessionCommunications::Ex
/**
* Default constructor.
*/
-SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPtr& endpoint,
- const std::string& destination, const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
- const PJSipManagerPtr& manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
- const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool /* ipv6 */, bool isUAC, const NATEndpointOptions& natOptions)
+SipSession::SipSession(
+ const Ice::ObjectAdapterPtr& adapter,
+ const SipEndpointPtr& endpoint,
+ const std::string& destination,
+ const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
+ const PJSipManagerPtr& manager,
+ const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
+ const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
+ const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx&,
+ bool /* ipv6 */,
+ bool isUAC,
+ const NATEndpointOptions& natOptions)
: mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica, natOptions))
{
if (listener != 0)
@@ -486,12 +494,20 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
/**
* Replica constructor.
*/
-SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPtr& endpoint,
- const std::string& destination, const Ice::Identity& /* sessionid */,
- const Ice::Identity& mediaid, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
- const AsteriskSCF::Media::V1::StreamSourceSeq& sources, const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
- const PJSipManagerPtr& manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
- const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC, const NATEndpointOptions& natOptions)
+SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter,
+ const SipEndpointPtr& endpoint,
+ const std::string& destination,
+ const Ice::Identity& /* sessionid */,
+ const Ice::Identity& mediaid,
+ const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
+ const AsteriskSCF::Media::V1::StreamSourceSeq& sources,
+ const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
+ const PJSipManagerPtr& manager,
+ const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
+ const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
+ const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx&,
+ bool isUAC,
+ const NATEndpointOptions& natOptions)
: mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica, natOptions))
{
activateIceObjects(mImplPriv->mManager->getSessionModule()->getSessionCreationHooks());
diff --git a/src/SipSession.h b/src/SipSession.h
index 165c411..9a88f77 100644
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@ -109,6 +109,7 @@ public:
const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx&, const PJSipManagerPtr& manager,
const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
+ const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx&,
bool ipv6, bool isUAC, const NATEndpointOptions& natOptions);
SipSession(const Ice::ObjectAdapterPtr&, const SipEndpointPtr&, const std::string&, const Ice::Identity&,
@@ -116,6 +117,7 @@ public:
const AsteriskSCF::Media::V1::StreamSourceSeq&, const AsteriskSCF::Media::V1::StreamSinkSeq&,
const PJSipManagerPtr& manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
+ const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx&,
bool isUAC, const NATEndpointOptions& natOptions);
bool operator==(const SipSession &other) const;
commit df60142aabdb696d31e49ba5c3047e1bbd25e7ff
Author: Mark Michelson <mmichelson at digium.com>
Date: Thu Jul 14 16:04:25 2011 -0500
Make helper functions for creating NOTIFY requests and their sipfrag bodies.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index d429b2f..09bc8d5 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -812,8 +812,6 @@ protected:
return Complete;
}
- lg(Debug) << "to: " << to << " from: " << from << " replaces: " << replaces;
-
pj_str_t to_tag_str = pj_str((char*)to.c_str());
pj_str_t from_tag_str = pj_str((char*)from.c_str());
pj_str_t replaces_tag_str = pj_str((char*)replaces.c_str());
@@ -929,23 +927,9 @@ protected:
// We need to send a NOTIFY to indicate how things went on the other leg.
// XXX Once we have a subscription module written, we can actually use it.
- pjsip_tx_data *tdata;
- pjsip_dlg_create_request(mInv->dlg, pjsip_get_notify_method(), -1, &tdata);
- pjsip_event_hdr *event = pjsip_event_hdr_create(tdata->pool);
- pj_cstr(&event->event_type, "refer");
- char idbuf[20];
- pj_ansi_snprintf(idbuf, sizeof(idbuf), "%d", mReferCSeq);
- pj_cstr(&event->id_param, idbuf);
- pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) event);
- pjsip_sub_state_hdr *subState = pjsip_sub_state_hdr_create(tdata->pool);
- pj_cstr(&subState->sub_state, "terminated");
- pj_cstr(&subState->reason_param, "noresource");
- pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) subState);
- pj_str_t type;
- pj_cstr(&type, "message");
- pj_str_t subtype;
- pj_cstr(&subtype, "sipfrag;version=2.0");
+ pjsip_tx_data *tdata = createNotify();
+
try
{
if (mWasWithDestination)
@@ -961,10 +945,7 @@ protected:
{
lg(Debug) << "ConnectBridgedSessionsWithDestination sending 404 due to destination not found.";
- pj_str_t bodyStr;
- pj_cstr(&bodyStr, "SIP/2.0 404 Not Found");
- pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
- tdata->msg->body = body;
+ addNotifyBody(tdata, "SIP/2.0 404 Not Found");
pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
return Complete;
}
@@ -972,18 +953,12 @@ protected:
{
lg(Debug) << "ConnectBridgedSessionsCallback sending 400 due to exception: " << e.what();
- pj_str_t bodyStr;
- pj_cstr(&bodyStr, "SIP/2.0 400 Bad Request");
- pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
- tdata->msg->body = body;
+ addNotifyBody(tdata, "SIP/2.0 400 Bad Request");
pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
return Complete;
}
- pj_str_t bodyStr;
- pj_cstr(&bodyStr, "SIP/2.0 200 OK");
- pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
- tdata->msg->body = body;
+ addNotifyBody(tdata, "SIP/2.0 200 OK");
pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
Ice::Current current;
@@ -993,6 +968,38 @@ protected:
}
private:
+
+ pjsip_tx_data* createNotify()
+ {
+ pjsip_tx_data *tdata;
+ pjsip_dlg_create_request(mInv->dlg, pjsip_get_notify_method(), -1, &tdata);
+
+ pjsip_event_hdr *event = pjsip_event_hdr_create(tdata->pool);
+ pj_strdup2(tdata->pool, &event->event_type, "refer");
+ char idbuf[20];
+ pj_ansi_snprintf(idbuf, sizeof(idbuf), "%d", mReferCSeq);
+ pj_strdup2(tdata->pool, &event->id_param, idbuf);
+ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) event);
+
+ pjsip_sub_state_hdr *subState = pjsip_sub_state_hdr_create(tdata->pool);
+ pj_strdup2(tdata->pool, &subState->sub_state, "terminated");
+ pj_strdup2(tdata->pool, &subState->reason_param, "noresource");
+ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) subState);
+
+ return tdata;
+ }
+ void addNotifyBody(pjsip_tx_data *tdata, const char *bodyText)
+ {
+ pj_str_t type;
+ pj_cstr(&type, "message");
+ pj_str_t subtype;
+ pj_cstr(&subtype, "sipfrag;version=2.0");
+
+ pj_str_t bodyStr;
+ pj_cstr(&bodyStr, bodyText);
+ pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
+ tdata->msg->body = body;
+ }
/**
* The INVITE session, which contains the dialog on which the
* REFER was received.
@@ -1104,7 +1111,6 @@ void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdat
// We only support SIP URIs, anything else is rubbish to us
if (!PJSIP_URI_SCHEME_IS_SIP(target_uri) && !PJSIP_URI_SCHEME_IS_SIPS(target_uri))
{
- // TODO: Place proper response code in here
lg(Debug) << "handleRefer() sending 400 due to non-SIP URI. ";
pjsip_dlg_respond(inv->dlg, rdata, 400, NULL, NULL, NULL);
return;
commit 822fc2955d56d229e8fffa38fc6209c6228ffb15
Author: Mark Michelson <mmichelson at digium.com>
Date: Thu Jul 14 15:28:37 2011 -0500
Use boost::split to get the parameters.
This makes the code a LOT cleaner and also reduces assumptions regarding
the number of parameters and their placement in the replaces header.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 330d356..d429b2f 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -22,6 +22,7 @@
#include "SipStateReplicator.h"
#include <IceUtil/UUID.h>
+#include <boost/algorithm/string.hpp>
#include <AsteriskSCF/Core/Endpoint/EndpointIf.h>
#include <AsteriskSCF/Core/Routing/RoutingIf.h>
@@ -779,12 +780,31 @@ protected:
// parse it out
std::string replaces_value_tmp = std::string(pj_strbuf(&mReplacesParam->value),
pj_strlen(&mReplacesParam->value));
- std::string fromTagParamName(";from-tag=");
- std::string toTagParamName(";to-tag=");
- size_t from_tag_pos = replaces_value_tmp.find(fromTagParamName);
- size_t to_tag_pos = replaces_value_tmp.find(toTagParamName);
+ std::vector<std::string> params;
- if (from_tag_pos == std::string::npos || to_tag_pos == std::string::npos)
+ boost::split(params, replaces_value_tmp, boost::is_any_of(";"));
+
+ //The first value will be the actual replaces value.
+ std::string replaces = params.front();
+
+ std::string to;
+ std::string from;
+ std::string fromTagParamName("from-tag=");
+ std::string toTagParamName("to-tag=");
+ for(std::vector<std::string>::iterator iter = params.begin();
+ iter != params.end(); ++iter)
+ {
+ if (iter->compare(0, toTagParamName.size(), toTagParamName) == 0)
+ {
+ to = iter->substr(toTagParamName.size());
+ }
+ if (iter->compare(0, fromTagParamName.size(), fromTagParamName) == 0)
+ {
+ from = iter->substr(fromTagParamName.size());
+ }
+ }
+
+ if (from.empty() || to.empty())
{
lg(Debug) << "handleRefer() sending 400 due to From or To missing. ";
pjsip_dlg_modify_response(mInv->dlg, mTdata, 400, NULL);
@@ -792,36 +812,11 @@ protected:
return Complete;
}
- size_t firstTagPos = std::min(from_tag_pos, to_tag_pos);
-
- // The position in the string where the value of the from tag starts.
- size_t fromTagValuePos = from_tag_pos + fromTagParamName.size();
-
- // The position in the string where the value of the to tag starts
- size_t toTagValuePos = to_tag_pos + toTagParamName.size();
-
- // The size of the tags. This isn't so much an accurate size as it is
- // what we need to pass in to the substr() function in order to extract
- // the proper value.
- //
- // If the from tag comes after the to tag, then the from tag extends until the
- // end of the string. Otherwise, it only extends as far as the beginning of the
- // to tag.
- size_t fromTagValueSize =
- from_tag_pos > to_tag_pos ? std::string::npos : to_tag_pos - fromTagValuePos;
-
- size_t toTagValueSize =
- to_tag_pos > from_tag_pos ? std::string::npos : from_tag_pos - toTagValuePos;
-
- std::string to_tag_value = replaces_value_tmp.substr(toTagValuePos, toTagValueSize);
- std::string from_tag_value = replaces_value_tmp.substr(fromTagValuePos, fromTagValueSize);
- std::string replaces_value = replaces_value_tmp.substr(0, firstTagPos);
-
- lg(Debug) << "to: " << to_tag_value << "from: " << from_tag_value << "replaces: " << replaces_value;
+ lg(Debug) << "to: " << to << " from: " << from << " replaces: " << replaces;
- pj_str_t to_tag_str = pj_str((char*)to_tag_value.c_str());
- pj_str_t from_tag_str = pj_str((char*)from_tag_value.c_str());
- pj_str_t replaces_tag_str = pj_str((char*)replaces_value.c_str());
+ pj_str_t to_tag_str = pj_str((char*)to.c_str());
+ pj_str_t from_tag_str = pj_str((char*)from.c_str());
+ pj_str_t replaces_tag_str = pj_str((char*)replaces.c_str());
other_dlg = pjsip_ua_find_dialog(&replaces_tag_str, &to_tag_str, &from_tag_str, PJ_TRUE);
}
commit ca24fcab3d34ddf6a69bc18fe0a769339b2756fe
Author: Mark Michelson <mmichelson at digium.com>
Date: Thu Jul 14 14:57:47 2011 -0500
Allow for the to-tag and from-tag parameters in the replaces header to be in any order.
This is my initial try at it, and I don't like it much. I think I'll try again using
boost's string splitting algorithm.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index cd1bf04..330d356 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -779,8 +779,10 @@ protected:
// parse it out
std::string replaces_value_tmp = std::string(pj_strbuf(&mReplacesParam->value),
pj_strlen(&mReplacesParam->value));
- size_t from_tag_pos = replaces_value_tmp.find(";from-tag=");
- size_t to_tag_pos = replaces_value_tmp.find(";to-tag=");
+ std::string fromTagParamName(";from-tag=");
+ std::string toTagParamName(";to-tag=");
+ size_t from_tag_pos = replaces_value_tmp.find(fromTagParamName);
+ size_t to_tag_pos = replaces_value_tmp.find(toTagParamName);
if (from_tag_pos == std::string::npos || to_tag_pos == std::string::npos)
{
@@ -790,9 +792,32 @@ protected:
return Complete;
}
- std::string to_tag_value = replaces_value_tmp.substr(to_tag_pos + 8, from_tag_pos - to_tag_pos - 8);
- std::string from_tag_value = replaces_value_tmp.substr(from_tag_pos + 10);
- std::string replaces_value = replaces_value_tmp.substr(0, to_tag_pos);
+ size_t firstTagPos = std::min(from_tag_pos, to_tag_pos);
+
+ // The position in the string where the value of the from tag starts.
+ size_t fromTagValuePos = from_tag_pos + fromTagParamName.size();
+
+ // The position in the string where the value of the to tag starts
+ size_t toTagValuePos = to_tag_pos + toTagParamName.size();
+
+ // The size of the tags. This isn't so much an accurate size as it is
+ // what we need to pass in to the substr() function in order to extract
+ // the proper value.
+ //
+ // If the from tag comes after the to tag, then the from tag extends until the
+ // end of the string. Otherwise, it only extends as far as the beginning of the
+ // to tag.
+ size_t fromTagValueSize =
+ from_tag_pos > to_tag_pos ? std::string::npos : to_tag_pos - fromTagValuePos;
+
+ size_t toTagValueSize =
+ to_tag_pos > from_tag_pos ? std::string::npos : from_tag_pos - toTagValuePos;
+
+ std::string to_tag_value = replaces_value_tmp.substr(toTagValuePos, toTagValueSize);
+ std::string from_tag_value = replaces_value_tmp.substr(fromTagValuePos, fromTagValueSize);
+ std::string replaces_value = replaces_value_tmp.substr(0, firstTagPos);
+
+ lg(Debug) << "to: " << to_tag_value << "from: " << from_tag_value << "replaces: " << replaces_value;
pj_str_t to_tag_str = pj_str((char*)to_tag_value.c_str());
pj_str_t from_tag_str = pj_str((char*)from_tag_value.c_str());
commit e28f2fa146b52be92b5df7640ab6f8df24cfd7c5
Author: Mark Michelson <mmichelson at digium.com>
Date: Thu Jul 14 14:18:50 2011 -0500
Couple of cleanup and error checking additions.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 05bd952..cd1bf04 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -1078,8 +1078,6 @@ void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdat
// So with what we have here, this will work 99.99% of the time. If someone
// tries to do something like refresh a subscription though, that will fail.
- // TODO: Provide method to send back suitable response
-
// Now parse the URI to get the actual target they want to refer to
pjsip_uri *target_uri = static_cast<pjsip_uri *>(pjsip_parse_uri(inv->dlg->pool, refer_to->hvalue.ptr, refer_to->hvalue.slen, 0));
@@ -1112,7 +1110,7 @@ void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdat
}
else
{
- target = std::string(pj_strbuf(&target_sip_uri->user), pj_strlen(&target_sip_uri->user));
+ target.assign(pj_strbuf(&target_sip_uri->user), pj_strlen(&target_sip_uri->user));
}
PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*) inv->mod_data[mModule.id];
@@ -1120,7 +1118,15 @@ void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdat
//Create our initial response that we can modify in the queueable operation.
pjsip_tx_data *tdata = 0;
- pjsip_dlg_create_response(inv->dlg, rdata, 202, NULL, &tdata);
+ pj_status_t status = pjsip_dlg_create_response(inv->dlg, rdata, 202, NULL, &tdata);
+
+ if (status != PJ_SUCCESS)
+ {
+ //Hm, we couldn't create a response. Let's hope this actually works...
+ lg(Error) << "Unable to create 202 Accepted response in response to REFER (Out of memory?)";
+ pjsip_dlg_respond(inv->dlg, rdata, 500, NULL, NULL, NULL);
+ return;
+ }
lg(Debug) << "Queuing a HandleReferOperation";
enqueueSessionWork(new HandleReferOperation(inv, tsx, tdata, replaces_param, to_tag_param, from_tag_param, referredByVal, target, session, mSessionRouter, mModule.id), inv);
commit 442b31018e098f0a9135da0f82d76d92d2ae9286
Author: Mark Michelson <mmichelson at digium.com>
Date: Thu Jul 14 14:04:22 2011 -0500
Parse and store the Referred-By header in a REFER.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 65533a6..05bd952 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -728,6 +728,7 @@ public:
pjsip_param *replaces_param,
pjsip_param *to_tag_param,
pjsip_param *from_tag_param,
+ const std::string& referredBy,
const std::string& target,
const SipSessionPtr& session,
const AsteriskSCF::Discovery::SmartProxy<SessionRouterPrx>& sessionRouter,
@@ -735,7 +736,9 @@ public:
: mInv(inv), mTsx(tsx), mTdata(tdata),
mReplacesParam(replaces_param ? new pjsip_param(*replaces_param) : NULL),
mToTagParam(to_tag_param ? new pjsip_param(*to_tag_param) : NULL),
- mFromTagParam(from_tag_param ? new pjsip_param(*from_tag_param) : NULL), mTarget(target),
+ mFromTagParam(from_tag_param ? new pjsip_param(*from_tag_param) : NULL),
+ mReferredBy(referredBy),
+ mTarget(target),
mSession(session), mSessionRouter(sessionRouter),
mModuleId(moduleId), mReferCSeq(tsx->cseq), mWasWithDestination(false) {}
@@ -1000,6 +1003,13 @@ private:
*/
pjsip_param *mFromTagParam;
/**
+ * The content from the Referred-By header, if one existed.
+ * XXX We currently have this handy, but we don't actually do
+ * anything with it. This is because we don't have a way to place
+ * this information in the outgoing INVITE.
+ */
+ const std::string mReferredBy;
+ /**
* The user portion of the URI in the Refer-To header of the
* REFER that triggered this operation.
*/
@@ -1046,7 +1056,27 @@ void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdat
return;
}
+ pj_str_t referredBy;
+ pj_cstr(&referredBy, "Referred-By");
+ pjsip_generic_string_hdr *referredByHdr =
+ static_cast<pjsip_generic_string_hdr*>(pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &referredBy, NULL));
+
+ std::string referredByVal;
+ if (referredByHdr)
+ {
+ referredByVal.assign(pj_strbuf(&referredByHdr->hvalue), pj_strlen(&referredByHdr->hvalue));
+ }
+
// TODO: Add support for subscription
+ //
+ // Currently, we send a NOTIFY as we are supposed to, but we don't actually
+ // have a full-blown subscription in use. This is for 2 reasons:
+ //
+ // 1. We don't have A subscription API defined yet.
+ // 2. REFERs are sort of fake subscriptions anyway.
+ //
+ // So with what we have here, this will work 99.99% of the time. If someone
+ // tries to do something like refresh a subscription though, that will fail.
// TODO: Provide method to send back suitable response
@@ -1093,7 +1123,7 @@ void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdat
pjsip_dlg_create_response(inv->dlg, rdata, 202, NULL, &tdata);
lg(Debug) << "Queuing a HandleReferOperation";
- enqueueSessionWork(new HandleReferOperation(inv, tsx, tdata, replaces_param, to_tag_param, from_tag_param, target, session, mSessionRouter, mModule.id), inv);
+ enqueueSessionWork(new HandleReferOperation(inv, tsx, tdata, replaces_param, to_tag_param, from_tag_param, referredByVal, target, session, mSessionRouter, mModule.id), inv);
}
pj_bool_t PJSipSessionModule::on_rx_request(pjsip_rx_data *rdata)
commit b09352f0fe360add36cc1977b6215781a33d42e1
Author: Mark Michelson <mmichelson at digium.com>
Date: Thu Jul 14 13:02:40 2011 -0500
Add Subscription-State header to outbound NOTIFY.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index ad22db8..65533a6 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -913,7 +913,11 @@ protected:
char idbuf[20];
pj_ansi_snprintf(idbuf, sizeof(idbuf), "%d", mReferCSeq);
pj_cstr(&event->id_param, idbuf);
- pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) event);
+ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) event);
+ pjsip_sub_state_hdr *subState = pjsip_sub_state_hdr_create(tdata->pool);
+ pj_cstr(&subState->sub_state, "terminated");
+ pj_cstr(&subState->reason_param, "noresource");
+ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) subState);
pj_str_t type;
pj_cstr(&type, "message");
commit 25b59a8ab75c40d5f80727357e9d939e827ab150
Author: Mark Michelson <mmichelson at digium.com>
Date: Thu Jul 14 10:51:15 2011 -0500
Add the ;id parameter to the event header in the NOTIFY we send.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index d1f552e..ad22db8 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -737,7 +737,7 @@ public:
mToTagParam(to_tag_param ? new pjsip_param(*to_tag_param) : NULL),
mFromTagParam(from_tag_param ? new pjsip_param(*from_tag_param) : NULL), mTarget(target),
mSession(session), mSessionRouter(sessionRouter),
- mModuleId(moduleId), mWasWithDestination(false) {}
+ mModuleId(moduleId), mReferCSeq(tsx->cseq), mWasWithDestination(false) {}
~HandleReferOperation()
{
@@ -910,6 +910,9 @@ protected:
pjsip_dlg_create_request(mInv->dlg, pjsip_get_notify_method(), -1, &tdata);
pjsip_event_hdr *event = pjsip_event_hdr_create(tdata->pool);
pj_cstr(&event->event_type, "refer");
+ char idbuf[20];
+ pj_ansi_snprintf(idbuf, sizeof(idbuf), "%d", mReferCSeq);
+ pj_cstr(&event->id_param, idbuf);
pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) event);
pj_str_t type;
@@ -1010,6 +1013,10 @@ private:
*/
const int mModuleId;
/**
+ * The CSeq of the REFER
+ */
+ pj_int32_t mReferCSeq;
+ /**
* Helps determine which end_* method to call on the session router when AMI completes.
* XXX It may be more elegant to handle this by sending a cookie to the AMI method
* instead.
commit fcac39e702d0f487a386d26ed8277ce6902ce607
Author: Mark Michelson <mmichelson at digium.com>
Date: Mon Jul 11 15:46:06 2011 -0500
Add version to sipfrag content type and remove unnecessary CRLFs.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 8883fc5..d1f552e 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -915,7 +915,7 @@ protected:
pj_str_t type;
pj_cstr(&type, "message");
pj_str_t subtype;
- pj_cstr(&subtype, "sipfrag");
+ pj_cstr(&subtype, "sipfrag;version=2.0");
try
{
if (mWasWithDestination)
@@ -932,7 +932,7 @@ protected:
lg(Debug) << "ConnectBridgedSessionsWithDestination sending 404 due to destination not found.";
pj_str_t bodyStr;
- pj_cstr(&bodyStr, "SIP/2.0 404 Not Found\r\n\r\n");
+ pj_cstr(&bodyStr, "SIP/2.0 404 Not Found");
pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
tdata->msg->body = body;
pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
@@ -943,7 +943,7 @@ protected:
lg(Debug) << "ConnectBridgedSessionsCallback sending 400 due to exception: " << e.what();
pj_str_t bodyStr;
- pj_cstr(&bodyStr, "SIP/2.0 400 Bad Request\r\n\r\n");
+ pj_cstr(&bodyStr, "SIP/2.0 400 Bad Request");
pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
tdata->msg->body = body;
pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
@@ -951,7 +951,7 @@ protected:
}
pj_str_t bodyStr;
- pj_cstr(&bodyStr, "SIP/2.0 200 OK\r\n\r\n");
+ pj_cstr(&bodyStr, "SIP/2.0 200 OK");
pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
tdata->msg->body = body;
pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
commit da14216b9dc0c8f37efd5d3a1a4d5591245b139d
Author: Mark Michelson <mmichelson at digium.com>
Date: Mon Jul 11 15:26:19 2011 -0500
Send an early 202 and then send a NOTIFY later...like you're supposed to do.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 9f2fe59..8883fc5 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -840,6 +840,9 @@ protected:
PJSipSessionModInfo *other_session_mod_info = (PJSipSessionModInfo*)other_inv->mod_data[mModuleId];
SipSessionPtr other_session = other_session_mod_info->getSessionPtr();
+ //Go ahead and send a 202 for the REFER. We can send a NOTIFY later to indicate if something
+ //on the outbound leg went awry.
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
try
{
std::string operationId = ::IceUtil::generateUUID();
@@ -862,6 +865,10 @@ protected:
}
else
{
+ //Go ahead and send a 202 for the REFER. We can send a NOTIFY later to indicate if something
+ //on the outbound leg went awry.
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+
// Now that we have the target user we can pass this into routing and go on our marry way
try
{
@@ -896,6 +903,19 @@ protected:
{
assert(mAsyncResult);
SessionRouterPrx router = SessionRouterPrx::uncheckedCast(mAsyncResult->getProxy());
+
+ // We need to send a NOTIFY to indicate how things went on the other leg.
+ // XXX Once we have a subscription module written, we can actually use it.
+ pjsip_tx_data *tdata;
+ pjsip_dlg_create_request(mInv->dlg, pjsip_get_notify_method(), -1, &tdata);
+ pjsip_event_hdr *event = pjsip_event_hdr_create(tdata->pool);
+ pj_cstr(&event->event_type, "refer");
+ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) event);
+
+ pj_str_t type;
+ pj_cstr(&type, "message");
+ pj_str_t subtype;
+ pj_cstr(&subtype, "sipfrag");
try
{
if (mWasWithDestination)
@@ -911,18 +931,30 @@ protected:
{
lg(Debug) << "ConnectBridgedSessionsWithDestination sending 404 due to destination not found.";
- pjsip_dlg_modify_response(mInv->dlg, mTdata, 404, NULL);
- pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+ pj_str_t bodyStr;
+ pj_cstr(&bodyStr, "SIP/2.0 404 Not Found\r\n\r\n");
+ pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
+ tdata->msg->body = body;
+ pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
return Complete;
}
catch (const std::exception &e)
{
lg(Debug) << "ConnectBridgedSessionsCallback sending 400 due to exception: " << e.what();
- pjsip_dlg_modify_response(mInv->dlg, mTdata, 400, NULL);
- pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+
+ pj_str_t bodyStr;
+ pj_cstr(&bodyStr, "SIP/2.0 400 Bad Request\r\n\r\n");
+ pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
+ tdata->msg->body = body;
+ pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
return Complete;
}
- pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+
+ pj_str_t bodyStr;
+ pj_cstr(&bodyStr, "SIP/2.0 200 OK\r\n\r\n");
+ pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
+ tdata->msg->body = body;
+ pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
Ice::Current current;
lg(Debug) << "ConnectBridgedSessionsCallback calling session->stop(). ";
@@ -1047,7 +1079,7 @@ void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdat
//Create our initial response that we can modify in the queueable operation.
pjsip_tx_data *tdata = 0;
- pjsip_dlg_create_response(inv->dlg, rdata, 200, NULL, &tdata);
+ pjsip_dlg_create_response(inv->dlg, rdata, 202, NULL, &tdata);
... 13121 lines suppressed ...
--
asterisk-scf/integration/sip.git
More information about the asterisk-scf-commits
mailing list