[asterisk-scf-commits] asterisk-scf/integration/sip.git branch "party-id" created.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Fri Oct 7 17:16:06 CDT 2011
branch "party-id" has been created
at 3fff8394ae39b9151fc277e18e8249fca07b6882 (commit)
- Log -----------------------------------------------------------------
commit 3fff8394ae39b9151fc277e18e8249fca07b6882
Author: Mark Michelson <mmichelson at digium.com>
Date: Fri Oct 7 17:14:58 2011 -0500
Set session owner ID based on parsed data.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 2192f88..cb70181 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -430,6 +430,7 @@ protected:
mSession->setDialog(mInv->dlg);
mSession->setTelephonyEventSourcesAndSinks(mCaller->getConfig());
+ mSession->setSessionOwnerId(mCallerID);
// Create an SDP offer or answer
const pjmedia_sdp_session *remote_sdp = NULL;
@@ -1210,6 +1211,7 @@ protected:
}
}
}
+ mSession->setSessionOwnerId(mConnected);
return Complete;
}
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 3db5ee3..2c2b9e5 100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -936,6 +936,12 @@ void SipSession::setSelfAsCaller()
mImplPriv->mSessionCookies[dialed->ice_id()] = dialed;
}
+void SipSession::setSessionOwnerId(const SessionOwnerIdPtr& owner)
+{
+ mImplPriv->mSessionCookies[owner->ice_id()] = owner;
+ mImplPriv->cookiesUpdated();
+}
+
class CheckDirectConnectionsOperation : public SuspendableWork
{
public:
diff --git a/src/SipSession.h b/src/SipSession.h
index 50da5f9..3ac4ba2 100644
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@ -348,6 +348,9 @@ public:
void setSelfAsCaller();
+ //Must be called from a queued operation
+ void setSessionOwnerId(const AsteriskSCF::SessionCommunications::PartyIdentification::V1::SessionOwnerIdPtr& owner);
+
private:
SipSession(const Ice::ObjectAdapterPtr&, const SipEndpointPtr&, const std::string&,
const std::vector<AsteriskSCF::SessionCommunications::V1::SessionListenerPrx>&,
commit e80f5d91f5454462a110a261eca4038112124b02
Author: Mark Michelson <mmichelson at digium.com>
Date: Fri Oct 7 16:16:08 2011 -0500
Parse connected line data on SIP responses.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index c175836..2192f88 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -406,8 +406,9 @@ public:
pjsip_inv_session *inv,
pjsip_tx_data *tdata,
pjsip_dialog *replacedDialog,
- const std::string destination)
- : mSessionModule(module), mCaller(caller), mSessionRouter(router), mInv(inv), mTdata(tdata), mReplacedDialog(replacedDialog), mDestination(destination) { }
+ const std::string destination,
+ const CallerPtr& callerID)
+ : mSessionModule(module), mCaller(caller), mSessionRouter(router), mInv(inv), mTdata(tdata), mReplacedDialog(replacedDialog), mDestination(destination), mCallerID(callerID) { }
protected:
SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
@@ -529,9 +530,10 @@ private:
pjsip_dialog *mReplacedDialog;
const std::string mDestination;
SipSessionPtr mSession;
+ CallerPtr mCallerID;
};
-void getIds(const char *headerName, pjsip_rx_data *rdata, IdSeq& ids)
+void PJSipSessionModule::getIds(const char *headerName, pjsip_rx_data *rdata, IdSeq& ids)
{
pj_str_t hdrName;
pj_cstr(&hdrName, headerName);
@@ -566,6 +568,21 @@ CallerPtr PJSipSessionModule::getCallerID(pjsip_rx_data *rdata)
return caller;
}
+ConnectedLinePtr PJSipSessionModule::getConnectedID(pjsip_rx_data *rdata)
+{
+ ConnectedLinePtr connected(new ConnectedLine);
+ getIds("P-Asserted-Identity", rdata, connected->ids);
+ if (!connected->ids.empty())
+ {
+ return connected;
+ }
+
+ //There were no P-Asserted-Identity headers present. Maybe
+ //they've used Remote-Party-ID instead...
+ getIds("Remote-Party-ID", rdata, connected->ids);
+ return connected;
+}
+
void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
{
//What do we do here?
@@ -727,10 +744,8 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
//Now let's see if they've identified themselves somehow...
CallerPtr callerID = getCallerID(rdata);
- // See if any SDP was present on this INVITE
-
lg(Debug) << "Queueing a SessionCreationOperation";
- sessionWork->enqueueWork(new SessionCreationOperation(this, caller, mSessionRouter, inv_session, tdata, replaced_dlg, destination));
+ sessionWork->enqueueWork(new SessionCreationOperation(this, caller, mSessionRouter, inv_session, tdata, replaced_dlg, destination, callerID));
}
void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdata)
@@ -1106,10 +1121,11 @@ class HandleInviteResponseOperation : public SipQueueableOperation
{
public:
HandleInviteResponseOperation(int respCode, const int invState,
- const SipSessionPtr& session) :
+ const SipSessionPtr& session, const ConnectedLinePtr& connected) :
mRespCode(respCode),
mInvState(invState),
- mSession(session)
+ mSession(session),
+ mConnected(connected)
{
}
@@ -1216,6 +1232,7 @@ private:
int mRespCode;
const int mInvState;
SipSessionPtr mSession;
+ ConnectedLinePtr mConnected;
};
void PJSipSessionModule::handleInviteResponse(pjsip_inv_session* inv,
@@ -1224,6 +1241,9 @@ void PJSipSessionModule::handleInviteResponse(pjsip_inv_session* inv,
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();
+
+ 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);
@@ -1233,7 +1253,7 @@ void PJSipSessionModule::handleInviteResponse(pjsip_inv_session* inv,
//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);
}
class TransactionStateOperation : public SipQueueableOperation
diff --git a/src/PJSipSessionModule.h b/src/PJSipSessionModule.h
index a107219..c28e055 100644
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@ -140,7 +140,9 @@ public:
private:
void handleNewInvite(pjsip_rx_data *rdata);
+ void getIds(const char *headerName, pjsip_rx_data *rdata, AsteriskSCF::SessionCommunications::PartyIdentification::V1::IdSeq& ids);
AsteriskSCF::SessionCommunications::PartyIdentification::V1::CallerPtr getCallerID(pjsip_rx_data *rdata);
+ AsteriskSCF::SessionCommunications::PartyIdentification::V1::ConnectedLinePtr getConnectedID(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);
commit 9d4f48a5bf3fe0be58fcd0c0eb4260be64de6005
Author: Mark Michelson <mmichelson at digium.com>
Date: Fri Oct 7 15:04:48 2011 -0500
Streamline the ID extraction routine some.
This will make it much easier to get IDs from arbitrary headers
easily on all types of messages.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 4c3222a..c175836 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -531,21 +531,15 @@ private:
SipSessionPtr mSession;
};
-CallerPtr PJSipSessionModule::getCallerID(pjsip_rx_data *rdata)
+void getIds(const char *headerName, pjsip_rx_data *rdata, IdSeq& ids)
{
- //Strategy: If there is a P-Asserted-Identity header (or headers)
- //present, then use those to fill the caller ID information in. If
- //there is not a P-Asserted-Identity header, then use the From header
- //to fill in this information.
-
- pj_str_t pai;
- pj_cstr(&pai, "P-Asserted-Identity");
- pjsip_fromto_hdr *paiHdr = (pjsip_fromto_hdr *) &rdata->msg_info.msg->hdr;
+ pj_str_t hdrName;
+ pj_cstr(&hdrName, headerName);
- CallerPtr caller(new Caller);
- while ((paiHdr = (pjsip_fromto_hdr *) pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &pai, paiHdr->next)))
+ pjsip_fromto_hdr *hdr = (pjsip_fromto_hdr *) &rdata->msg_info.msg->hdr;
+ while ((hdr = (pjsip_fromto_hdr *) pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &hdrName, hdr->next)))
{
- pjsip_name_addr *idNameAddr = (pjsip_name_addr*) paiHdr->uri;
+ pjsip_name_addr *idNameAddr = (pjsip_name_addr*) hdr->uri;
NamePtr name(new Name(std::string(pj_strbuf(&idNameAddr->display), pj_strlen(&idNameAddr->display))));
@@ -553,9 +547,14 @@ CallerPtr PJSipSessionModule::getCallerID(pjsip_rx_data *rdata)
NumberPtr number (new Number(std::string(pj_strbuf(&idURI->user), pj_strlen(&idURI->user))));
IdPtr id(new Id(name, number));
- caller->ids.push_back(id);
+ ids.push_back(id);
}
+}
+CallerPtr PJSipSessionModule::getCallerID(pjsip_rx_data *rdata)
+{
+ CallerPtr caller(new Caller);
+ getIds("P-Asserted-Identity", rdata, caller->ids);
if (!caller->ids.empty())
{
return caller;
@@ -563,14 +562,7 @@ CallerPtr PJSipSessionModule::getCallerID(pjsip_rx_data *rdata)
//There were no P-Asserted-Identity headers present. On an incoming call, we'll get caller ID from the
//From header instead.
- pjsip_name_addr *from = (pjsip_name_addr *) rdata->msg_info.from->uri;
- NamePtr name(new Name(std::string(pj_strbuf(&from->display), pj_strlen(&from->display))));
- pjsip_sip_uri *fromURI = (pjsip_sip_uri *) pjsip_uri_get_uri(from);
- NumberPtr number(new Number(std::string(pj_strbuf(&fromURI->user), pj_strlen(&fromURI->user))));
-
- IdPtr id(new Id(name, number));
- caller->ids.push_back(id);
-
+ getIds("From", rdata, caller->ids);
return caller;
}
commit bc4bd784fbed179b74e0d37926ac3601fb4577d5
Author: Mark Michelson <mmichelson at digium.com>
Date: Fri Oct 7 14:29:55 2011 -0500
* Use From header for caller ID if no PAI is present
* Don't use generic string header. use fromto header instead.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 66562fb..4c3222a 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -540,18 +540,12 @@ CallerPtr PJSipSessionModule::getCallerID(pjsip_rx_data *rdata)
pj_str_t pai;
pj_cstr(&pai, "P-Asserted-Identity");
- pjsip_generic_string_hdr *paiHdr = (pjsip_generic_string_hdr *) &rdata->msg_info.msg->hdr;
+ pjsip_fromto_hdr *paiHdr = (pjsip_fromto_hdr *) &rdata->msg_info.msg->hdr;
CallerPtr caller(new Caller);
- while ((paiHdr = (pjsip_generic_string_hdr *) pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &pai, paiHdr->next)))
+ while ((paiHdr = (pjsip_fromto_hdr *) pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &pai, paiHdr->next)))
{
- //The reason for the use of a string here instead of just passing paiHdr->hvalue to
- //pjsip_parse_uri() is that the documentation is quite clear that the string passed to
- //pjsip_parse_uri() must be null-terminated. pj_str_t strings are not null-terminated.
- //If there's a better way of doing this, let me know, because this just feels weird, especially
- //with the cast.
- std::string URI(pj_strbuf(&paiHdr->hvalue), pj_strlen(&paiHdr->hvalue));
- pjsip_name_addr *idNameAddr = (pjsip_name_addr*) pjsip_parse_uri(rdata->tp_info.pool, (char *)URI.c_str(), URI.size(), PJSIP_PARSE_URI_AS_NAMEADDR);
+ pjsip_name_addr *idNameAddr = (pjsip_name_addr*) paiHdr->uri;
NamePtr name(new Name(std::string(pj_strbuf(&idNameAddr->display), pj_strlen(&idNameAddr->display))));
@@ -561,6 +555,22 @@ CallerPtr PJSipSessionModule::getCallerID(pjsip_rx_data *rdata)
IdPtr id(new Id(name, number));
caller->ids.push_back(id);
}
+
+ if (!caller->ids.empty())
+ {
+ return caller;
+ }
+
+ //There were no P-Asserted-Identity headers present. On an incoming call, we'll get caller ID from the
+ //From header instead.
+ pjsip_name_addr *from = (pjsip_name_addr *) rdata->msg_info.from->uri;
+ NamePtr name(new Name(std::string(pj_strbuf(&from->display), pj_strlen(&from->display))));
+ pjsip_sip_uri *fromURI = (pjsip_sip_uri *) pjsip_uri_get_uri(from);
+ NumberPtr number(new Number(std::string(pj_strbuf(&fromURI->user), pj_strlen(&fromURI->user))));
+
+ IdPtr id(new Id(name, number));
+ caller->ids.push_back(id);
+
return caller;
}
commit cf506fd0d7be69ef2e8b061387b21e92d36afc2a
Author: Mark Michelson <mmichelson at digium.com>
Date: Fri Oct 7 14:06:48 2011 -0500
Parse the P-Asserted-Identity header on incoming INVITEs.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 9504d47..66562fb 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -70,6 +70,7 @@ using namespace AsteriskSCF::System::ThreadPool::V1;
using namespace AsteriskSCF::System::WorkQueue::V1;
using namespace AsteriskSCF::WorkQueue;
using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::SessionCommunications::PartyIdentification::V1;
PJSipSessionModInfo::PJSipSessionModInfo(pjsip_inv_session *inv_session,
const SipSessionPtr& session, const SessionWorkPtr& sessionWork) :
@@ -530,6 +531,39 @@ private:
SipSessionPtr mSession;
};
+CallerPtr PJSipSessionModule::getCallerID(pjsip_rx_data *rdata)
+{
+ //Strategy: If there is a P-Asserted-Identity header (or headers)
+ //present, then use those to fill the caller ID information in. If
+ //there is not a P-Asserted-Identity header, then use the From header
+ //to fill in this information.
+
+ pj_str_t pai;
+ pj_cstr(&pai, "P-Asserted-Identity");
+ pjsip_generic_string_hdr *paiHdr = (pjsip_generic_string_hdr *) &rdata->msg_info.msg->hdr;
+
+ CallerPtr caller(new Caller);
+ while ((paiHdr = (pjsip_generic_string_hdr *) pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &pai, paiHdr->next)))
+ {
+ //The reason for the use of a string here instead of just passing paiHdr->hvalue to
+ //pjsip_parse_uri() is that the documentation is quite clear that the string passed to
+ //pjsip_parse_uri() must be null-terminated. pj_str_t strings are not null-terminated.
+ //If there's a better way of doing this, let me know, because this just feels weird, especially
+ //with the cast.
+ std::string URI(pj_strbuf(&paiHdr->hvalue), pj_strlen(&paiHdr->hvalue));
+ pjsip_name_addr *idNameAddr = (pjsip_name_addr*) pjsip_parse_uri(rdata->tp_info.pool, (char *)URI.c_str(), URI.size(), PJSIP_PARSE_URI_AS_NAMEADDR);
+
+ NamePtr name(new Name(std::string(pj_strbuf(&idNameAddr->display), pj_strlen(&idNameAddr->display))));
+
+ pjsip_sip_uri *idURI = (pjsip_sip_uri *) pjsip_uri_get_uri(idNameAddr);
+ NumberPtr number (new Number(std::string(pj_strbuf(&idURI->user), pj_strlen(&idURI->user))));
+
+ IdPtr id(new Id(name, number));
+ caller->ids.push_back(id);
+ }
+ return caller;
+}
+
void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
{
//What do we do here?
@@ -688,6 +722,9 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
lg(Debug) << "Call is destined for " << destination;
}
+ //Now let's see if they've identified themselves somehow...
+ CallerPtr callerID = getCallerID(rdata);
+
// See if any SDP was present on this INVITE
lg(Debug) << "Queueing a SessionCreationOperation";
diff --git a/src/PJSipSessionModule.h b/src/PJSipSessionModule.h
index 9305f0f..a107219 100644
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@ -140,6 +140,7 @@ public:
private:
void handleNewInvite(pjsip_rx_data *rdata);
+ AsteriskSCF::SessionCommunications::PartyIdentification::V1::CallerPtr getCallerID(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);
commit 621bee585d88c664857a403cc9eb4022dcb504db
Author: Mark Michelson <mmichelson at digium.com>
Date: Fri Oct 7 12:10:12 2011 -0500
Add connected line information to INVITE responses.
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 3b18a12..3db5ee3 100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -1523,6 +1523,7 @@ public:
// If the indication produced a packet send it out
if (status == PJ_SUCCESS)
{
+ addConnected(packet);
pjsip_inv_send_msg(mImplPriv->mInviteSession, packet);
}
@@ -1531,6 +1532,41 @@ public:
}
private:
+ void addConnected(pjsip_tx_data *packet)
+ {
+ AsteriskSCF::SessionCommunications::V1::SessionCookieDict::const_iterator iter =
+ mImplPriv->mSessionCookies.find(ConnectedLine::ice_staticId());
+
+ if (iter == mImplPriv->mSessionCookies.end())
+ {
+ lg(Debug) << "No Connected line cookie present";
+ return;
+ }
+
+ CallerPtr caller = CallerPtr::dynamicCast(iter->second);
+ for (IdSeq::iterator id = caller->ids.begin(); id != caller->ids.end(); ++id)
+ {
+ std::string connectedName = (*id)->partyName->partyName;
+ std::string connectedNumber = (*id)->partyNumber->partyNumber;
+
+ pj_str_t paiHeader;
+ pj_cstr(&paiHeader, "P-Asserted-Identity");
+ if (connectedName.empty())
+ {
+ connectedName = connectedNumber;
+ }
+ pj_str_t paiValue;
+ std::stringstream ss;
+ ss << "\"" << connectedName << "\" <" << connectedNumber << "@" << /*XXX WTF goes here? */ "..." << ">;party=called";
+ pj_cstr(&paiValue, ss.str().c_str());
+
+ pjsip_generic_string_hdr *hdr =
+ pjsip_generic_string_hdr_create(packet->pool, &paiHeader, &paiValue);
+
+ pjsip_msg_add_hdr(packet->msg, (pjsip_hdr*) hdr);
+ }
+ }
+
AsteriskSCF::SessionCommunications::V1::AMD_Session_indicatePtr mCb;
AsteriskSCF::SessionCommunications::V1::IndicationPtr mIndication;
boost::shared_ptr<SipSessionPriv> mImplPriv;
commit b6d1c108babdd3564101ddc567182860e75a99e3
Author: Mark Michelson <mmichelson at digium.com>
Date: Fri Oct 7 11:34:38 2011 -0500
Add caller information on outgoing INVITEs.
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 3182731..3b18a12 100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -1970,6 +1970,8 @@ public:
addReferredBy(packet);
+ addCaller(packet);
+
// Boom! Houston, we have transmission.
pjsip_inv_send_msg(mImplPriv->mInviteSession, packet);
return Complete;
@@ -2011,6 +2013,41 @@ private:
pjsip_msg_add_hdr(packet->msg, (pjsip_hdr*) hdr);
}
+
+ void addCaller(pjsip_tx_data *packet)
+ {
+ AsteriskSCF::SessionCommunications::V1::SessionCookieDict::const_iterator iter =
+ mImplPriv->mSessionCookies.find(Caller::ice_staticId());
+
+ if (iter == mImplPriv->mSessionCookies.end())
+ {
+ lg(Debug) << "No Caller cookie present";
+ return;
+ }
+
+ CallerPtr caller = CallerPtr::dynamicCast(iter->second);
+ for (IdSeq::iterator id = caller->ids.begin(); id != caller->ids.end(); ++id)
+ {
+ std::string callerName = (*id)->partyName->partyName;
+ std::string callerNumber = (*id)->partyNumber->partyNumber;
+
+ pj_str_t paiHeader;
+ pj_cstr(&paiHeader, "P-Asserted-Identity");
+ if (callerName.empty())
+ {
+ callerName = callerNumber;
+ }
+ pj_str_t paiValue;
+ std::stringstream ss;
+ ss << "\"" << callerName << "\" <" << callerNumber << "@" << /*XXX WTF goes here? */ "..." << ">;party=calling";
+ pj_cstr(&paiValue, ss.str().c_str());
+
+ pjsip_generic_string_hdr *hdr =
+ pjsip_generic_string_hdr_create(packet->pool, &paiHeader, &paiValue);
+
+ pjsip_msg_add_hdr(packet->msg, (pjsip_hdr*) hdr);
+ }
+ }
SipSessionPtr mSession;
boost::shared_ptr<SipSessionPriv> mImplPriv;
};
commit f9c355bfc60299b4ef25d5375aa53aacc9fee9e8
Author: Mark Michelson <mmichelson at digium.com>
Date: Thu Oct 6 13:41:27 2011 -0500
Fix 64 bit builds where size_t and int are different sizes.
diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
index a4e03d5..9aee763 100644
--- a/src/SipClientRegistration.cpp
+++ b/src/SipClientRegistration.cpp
@@ -15,6 +15,7 @@
*/
#include "SipClientRegistration.h"
+#include <boost/numeric/conversion/cast.hpp>
using namespace AsteriskSCF::System::Logging;
@@ -212,7 +213,7 @@ void SipRegistrationClient::createPJSIPRegistration(
&serverURL,
&fromURL,
&toURL,
- pjContacts.size(),
+ boost::numeric_cast<int>(pjContacts.size()),
&pjContacts.front(),
confItem->defaultExpiration
);
@@ -289,7 +290,7 @@ 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, contacts.size(), &contacts.front());
+ pjsip_regc_update_contact(mReg, boost::numeric_cast<int>(contacts.size()), &contacts.front());
pjsip_tx_data *tdata;
pjsip_regc_register(mReg, PJ_TRUE, &tdata);
@@ -391,7 +392,7 @@ void SipRegistrationClient::authenticate(pjsip_rx_data *rdata)
}
if (creds.size() != 0)
{
- pjsip_regc_set_credentials(mReg, creds.size(), &creds.front());
+ pjsip_regc_set_credentials(mReg, boost::numeric_cast<int>(creds.size()), &creds.front());
sendRegister();
}
return;
commit 9920aea9b6e4647f41f3464e605d282154c9f9b9
Author: Mark Michelson <mmichelson at digium.com>
Date: Thu Oct 6 11:16:08 2011 -0500
Use the proper name for the constant for default registration since it has changed.
diff --git a/config/SipConfigurator.py b/config/SipConfigurator.py
index 01acf32..c7c9f6f 100755
--- a/config/SipConfigurator.py
+++ b/config/SipConfigurator.py
@@ -130,7 +130,7 @@ class SipSectionVisitors(Configurator.SectionVisitors):
item = AsteriskSCF.Configuration.SipSessionManager.V1.SipClientRegistrationItem()
mapper.map('aor', item, 'aor', 'registration', config.get, None)
- mapper.map('expiration', item, 'defaultExpiration', 'registration', config.getint, AsteriskSCF.Configuration.SipSessionManager.V1.DefaultExpiration)
+ mapper.map('expiration', item, 'defaultExpiration', 'registration', config.getint, AsteriskSCF.Configuration.SipSessionManager.V1.DefaultRegistrationExpirationSeconds)
handler = RegistrationContactHandler(config)
mapper.map('contacts', item, 'contacts', 'registration', handler.get, None)
commit 0ca99918a255c76ca856ce1a1f4090b6d18834c2
Author: Mark Michelson <mmichelson at digium.com>
Date: Wed Oct 5 17:02:55 2011 -0500
Clarify documentation and change name of the method used to respond to an authentication challenge.
diff --git a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
index 6b74279..49f0d96 100644
--- a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
@@ -591,7 +591,7 @@ struct ContactInfo
sequence<ContactInfo> ContactInfoSeq;
-const int DefaultExpiration = 3600;
+const int DefaultRegistrationExpirationSeconds = 3600;
class SipClientRegistrationItem extends SipConfigurationItem
{
@@ -606,8 +606,8 @@ class SipClientRegistrationItem extends SipConfigurationItem
ContactInfoSeq contacts;
/**
* The expiration to use for any contacts
- * with no explicit expiration set. Units
- * for expiration are seconds.
+ * with no explicit expiration set (i.e. a 0 expiration).
+ * Units for expiration are seconds.
*/
int defaultExpiration;
};
diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
index ba624f7..a4e03d5 100644
--- a/src/SipClientRegistration.cpp
+++ b/src/SipClientRegistration.cpp
@@ -373,7 +373,7 @@ void SipRegistrationClient::authenticate(pjsip_rx_data *rdata)
ClientAuthSeq auths;
Ice::StringSeq realms = getRealms(rdata);
- HookResult result = (*iter)->getCredentials(mEndpointName, realms, auths);
+ HookResult result = (*iter)->respondToChallenge(mEndpointName, realms, auths);
if (result.status == Succeeded)
{
std::vector<pjsip_cred_info> creds;
commit 929a1cff9ce65f6e5b18f3d0dc0cf761b3683f47
Merge: 5e0ba08 1094f86
Author: Mark Michelson <mmichelson at digium.com>
Date: Wed Oct 5 11:10:44 2011 -0500
Merge branch 'master' into client-registration
commit 1094f862471a5cdc8955aecca1bbbeebba31b44c
Author: Joshua Colp <jcolp at digium.com>
Date: Wed Oct 5 12:56:44 2011 -0300
Only initialize pjlib once.
diff --git a/src/Component.cpp b/src/Component.cpp
index 37e6a7f..0e0a591 100644
--- a/src/Component.cpp
+++ b/src/Component.cpp
@@ -414,11 +414,6 @@ void Component::onPreInitialize()
{
try
{
- // Initialize PJSIP
- // NOTE: Should use PJSipManager::create now.
- mPJSipManager = PJSipManager::create(getName(), getCommunicator()->getProperties());
- lg(Debug) << "Created PJSIP manager";
-
//As nice as it is of IceBox to provide us with a communicator,
//we're going to create our own so that we can provide it with a threadhook.
//Yes, this could be done via a plugin, but this is easier. Go away.
@@ -426,6 +421,11 @@ void Component::onPreInitialize()
id.threadHook = new AsteriskSCF::PJLib::ThreadHook("Ice");
id.properties = getCommunicator()->getProperties();
+ // Initialize PJSIP
+ // NOTE: Should use PJSipManager::create now.
+ mPJSipManager = PJSipManager::create(getName(), getCommunicator()->getProperties());
+ lg(Debug) << "Created PJSIP manager";
+
setCommunicator(Ice::initialize(id));
}
catch(const std::exception& e)
diff --git a/src/PJSipManager.cpp b/src/PJSipManager.cpp
index e4f1054..803edac 100644
--- a/src/PJSipManager.cpp
+++ b/src/PJSipManager.cpp
@@ -267,13 +267,6 @@ PJSipManager::PJSipManager() :
{
memset(&mCachingPool, 0, sizeof(mCachingPool));
- pj_status_t status = pj_init();
- if (fail(status))
- {
- const char* message = "Failed to Initialize PJSIP";
- logger(Error) << message;
- throw InternalInitializationException(message);
- }
// The third parameter is just copied from
// example code from PJLIB. This can be adjusted
// if necessary.
@@ -291,7 +284,7 @@ PJSipManager::PJSipManager() :
throw InternalInitializationException(message);
}
- status = pj_thread_create(mMemoryPool, "SIP", (pj_thread_proc *) &monitorThread,
+ pj_status_t status = pj_thread_create(mMemoryPool, "SIP", (pj_thread_proc *) &monitorThread,
this, PJ_THREAD_DEFAULT_STACK_SIZE * 2, 0, &mPjThread);
if (fail(status))
{
commit 5e0ba080e24eaa73a77601f50733047fc4b4aff3
Merge: 83d4e07 030ca07
Author: Mark Michelson <mmichelson at digium.com>
Date: Tue Oct 4 18:25:42 2011 -0500
Merge branch 'master' into client-registration
Conflicts:
src/Component.cpp
commit 83d4e0737de244e6c1a64e8dac6dd12c04f8ec96
Author: Mark Michelson <mmichelson at digium.com>
Date: Tue Oct 4 17:34:42 2011 -0500
Set the replica proxy in the endpoint factory after it has actually been initialized.
diff --git a/src/Component.cpp b/src/Component.cpp
index 405ee50..53974e8 100644
--- a/src/Component.cpp
+++ b/src/Component.cpp
@@ -529,8 +529,7 @@ void Component::createPrimaryServices()
getBackplaneAdapter(),
mPJSipManager,
getServiceLocator(),
- sipReplicationContext,
- getReplicaProxy()));
+ sipReplicationContext));
lg(Debug) << "Created SIP endpoint factory";
// Locate the Routing Service so that we can do routing. This is done here so it can be
@@ -575,6 +574,10 @@ void Component::createBackplaneServices()
getBackplaneAdapter()->addWithUUID(mConfigurationService));
lg(Debug) << "Created SIP Configuration Implementation";
+ // We have to wait until this point to add the replica proxy to
+ // the endpoint factory because prior to this point the replica hasn't
+ // been created.
+ mEndpointFactory->setReplicaProxy(getReplicaProxy());
}
catch(const Ice::Exception& e)
{
diff --git a/src/SipConfiguration.cpp b/src/SipConfiguration.cpp
index ab28759..a505fff 100644
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@ -1888,9 +1888,7 @@ void ConfigurationServiceImpl::setConfiguration(const AsteriskSCF::System::Confi
void visitSipRegistrationGroup(const SipRegistrationGroupPtr& group)
{
- std::cout << "!!!!!!!!!!!!!! How's it going? !!!!!!!!!!!!" << std::endl;
genericSet<SipRegistrationGroupPtr>(mImpl->getData(), group);
- std::cout << "!!!!!!!!!!!!!! FINE? !!!!!!!!!!!!" << std::endl;
}
void visitIdentityGroup(const IdentityGroupPtr& group)
{
diff --git a/src/SipEndpointFactory.cpp b/src/SipEndpointFactory.cpp
index 2be256d..4b8682c 100644
--- a/src/SipEndpointFactory.cpp
+++ b/src/SipEndpointFactory.cpp
@@ -20,6 +20,7 @@
#include "SipEndpointFactory.h"
using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::System::Component::V1;
namespace
{
@@ -77,5 +78,10 @@ void SipEndpointFactory::generateRoutingDestinations(AsteriskSCF::Core::Routing:
}
}
+void SipEndpointFactory::setReplicaProxy(const ReplicaPrx& replica)
+{
+ mReplica = replica;
+}
+
}; // end SipSessionManager
}; // end AsteriskSCF
diff --git a/src/SipEndpointFactory.h b/src/SipEndpointFactory.h
index fbefdd2..7d792b5 100644
--- a/src/SipEndpointFactory.h
+++ b/src/SipEndpointFactory.h
@@ -43,14 +43,12 @@ public:
const Ice::ObjectAdapterPtr& backplaneAdapter,
const PJSipManagerPtr& manager,
const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
- const SipReplicationContextPtr& replicationContext,
- const AsteriskSCF::System::Component::V1::ReplicaPrx& replica) :
+ const SipReplicationContextPtr& replicationContext) :
mAdapter(adapter),
mBackplaneAdapter(backplaneAdapter),
mManager(manager),
mServiceLocator(serviceLocator),
- mReplicationContext(replicationContext),
- mReplica(replica){};
+ mReplicationContext(replicationContext) { }
SipEndpointPtr createEndpoint(std::string);
@@ -60,6 +58,8 @@ public:
void generateRoutingDestinations(AsteriskSCF::Core::Routing::V1::RegExSeq&);
+ void setReplicaProxy(const AsteriskSCF::System::Component::V1::ReplicaPrx& replica);
+
private:
/**
* A pointer to the object adapter that endpoints will be added to.
commit 030ca07ce06155cc17518f07099650ab7b862d4a
Author: Ken Hunt <ken.hunt at digium.com>
Date: Tue Oct 4 12:07:29 2011 -0500
Passing the component's ComponentService discovery category to the base Component (in constructor), namespace flattening was causing it to select the wrong category.
diff --git a/src/Component.cpp b/src/Component.cpp
index 1d63c04..37e6a7f 100644
--- a/src/Component.cpp
+++ b/src/Component.cpp
@@ -112,7 +112,7 @@ class Component : public AsteriskSCF::Component::Component
{
public:
Component()
- : AsteriskSCF::Component::Component(lg, ComponentServiceDiscoveryCategory),
+ : AsteriskSCF::Component::Component(lg, AsteriskSCF::SIP::V1::ComponentServiceDiscoveryCategory),
mListeningToReplicator(false)
{
}
commit d686a273766e9ee293d9050c9dbfc3748b62eeaf
Merge: b634595 ee3a950
Author: Mark Michelson <mmichelson at digium.com>
Date: Tue Oct 4 10:55:45 2011 -0500
Merge branch 'master' into client-registration
diff --cc src/SipEndpoint.cpp
index 3371038,2e59ea0..822fbe7
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@@ -327,75 -319,19 +338,86 @@@ void SipEndpoint::setSecureTransport(en
void SipEndpoint::setDTMFMethod(AsteriskSCF::Configuration::SipSessionManager::V1::SipDTMFOption dtmf)
{
mImplPriv->mConfig.sessionConfig.dtmf = dtmf;
+ if (mImplPriv->mConfig.sessionConfig.dtmf ==
+ AsteriskSCF::Configuration::SipSessionManager::V1::RFC4733)
+ {
+ //For RFC 4733, we need to include information in the SDP about
+ //the format, so we need to add a new format to the endpoint's
+ //configured formats.
+
+ //XXX For now, we're just adding some hard-coded values. We should probably
+ //be a bit more flexible here in the face of changes or something.
+ addFormat("rfc4733", 8000, 0, Ice::StringSeq());
+ }
}
+class MatchRegistration
+{
+public:
+ MatchRegistration(const std::string& aor)
+ : mAOR(aor) { }
+
+ bool operator()(const SipClientRegistrationItemPtr& item)
+ {
+ return item->aor == mAOR;
+ }
+private:
+ const std::string mAOR;
+};
+
+void SipEndpoint::updateClientRegistrations(SipClientRegistrationItemSeq& items)
+{
+ lg(Debug) << "Updating client registrations for endpoint " << mImplPriv->mName;
+
+ //First step is to find registrations that exist for this endpoint but
+ //that no longer appear in configuration. These must be KILLED!!!!!
+
+ for (std::map<std::string, SipRegistrationClientPtr>::iterator iter = mImplPriv->mClientRegistrations.begin();
+ iter != mImplPriv->mClientRegistrations.end(); )
+ {
+ SipClientRegistrationItemSeq::iterator toRemove = std::find_if(items.begin(), items.end(), MatchRegistration(iter->first));
+ if (toRemove != items.end())
+ {
+ iter->second->destroy();
+ mImplPriv->mClientRegistrations.erase(iter++);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+
+ //Next we go through the configured registrations and either update existing
+ //client registrations or create new ones.
+ for (SipClientRegistrationItemSeq::iterator item = items.begin();
+ item != items.end(); ++item)
+ {
+ std::map<std::string, SipRegistrationClientPtr>::iterator iter =
+ mImplPriv->mClientRegistrations.find((*item)->aor);
+
+ if (iter != mImplPriv->mClientRegistrations.end())
+ {
+ //Updating one that exists
+ iter->second->updateRegistration(*item, mImplPriv->mManager->getEndpoint(), this);
+ }
+ else
+ {
+ //New one!
+ mImplPriv->mClientRegistrations[(*item)->aor] =
+ new SipRegistrationClient(
+ *item,
+ mImplPriv->mManager->getEndpoint(),
+ this,
+ mImplPriv->mManager->getClientRegistrationManager(),
+ mImplPriv->mReplicationContext,
+ mImplPriv->mBackplaneAdapter,
+ mImplPriv->mReplica);
+
+ mImplPriv->mClientRegistrations[(*item)->aor]->activate();
+ }
+ }
+}
+
void SipEndpoint::setRTPOverIPv6(bool enabled)
{
mImplPriv->mConfig.sessionConfig.rtpOverIPv6 = enabled;
commit d1c51b7c05833b65bffdc3599253dd6690580d34
Author: Joshua Colp <jcolp at digium.com>
Date: Mon Oct 3 20:04:29 2011 -0300
Add T.38 UDPTL support.
diff --git a/config/Sip.config b/config/Sip.config
index 7946dba..e72b415 100644
--- a/config/Sip.config
+++ b/config/Sip.config
@@ -89,8 +89,32 @@ direction=both
securetransport=none
# Whether to use IPv6 for media transport or not
rtpoveripv6=no
+# Whether to use IPv6 for UDPTL transport or not
+udptloveripv6=no
+
+#
+# Configure endpoint to create ICE enabled UDPTL streams. Disabled by default.
+#
+# udptloverice=false
+
+#
+# Configure endpoint to enable TURN support for ICE enabled UDPTL streams. ICE must be enabled
+# for this to have an effect. Disable by default.
+#
+# udptlwithturn=false
+
# Allowable media formats for the endpoint. Each format is separated using , and follows the format
# <name>/<sample rate>@<frame size>;<format specific parameters>
+#
+# If you would like to enable T.38 you can specify t38udptl here. This will enable T.38 with no overridden
+# datagram and no error correction scheme. To override the datagram add maxdatagram with a value in the format
+# specific parameters section. To enable error correction add errorcorrect with either fec, redundancy, or none
+# as the value.
+#
+# Example of T.38 with an overridden max datagram of 400: t38udptl;maxdatagram=400
+# Example of T.38 with fec error correction: t38udptl;errorcorrect=fec
+# Example of T.38 with overridden max datagram and fec error correction: t38udptl;maxdatagram=400&errorcorrect=fec
+#
formats=ulaw/8000,alaw/8000
# Whether media should be allowed to flow directly between endpoints or not
diff --git a/config/SipConfigurator.py b/config/SipConfigurator.py
index 5505f2a..f6c09b7 100755
--- a/config/SipConfigurator.py
+++ b/config/SipConfigurator.py
@@ -206,6 +206,11 @@ class SipSectionVisitors(Configurator.SectionVisitors):
item = AsteriskSCF.Configuration.SipSessionManager.V1.DirectMediaItem()
mapper.map('directmedia', item, 'enabled', 'directmedia', config.getboolean, None)
+ item = AsteriskSCF.Configuration.SipSessionManager.V1.SipUDPTLMediaServiceItem()
+ mapper.map('udptloveripv6', item, 'requireIPv6', 'udptlmediaservice', config.getboolean, None)
+ mapper.map('udptloverice', item, 'enableICE', 'udptlmediaservice', config.getboolean, None)
+ mapper.map('udptlwithturn', item, 'enableTURN', 'udptlmediaservice', config.getboolean, None)
+
item = AsteriskSCF.Configuration.SipSessionManager.V1.SipCryptoCertificateItem()
mapper.map('certificateauthorityfile', item, 'certificateAuthority', 'cryptocert', config.get, None)
mapper.map('certificatefile', item, 'certificate', 'cryptocert', config.get, None)
@@ -263,21 +268,43 @@ class SipSectionVisitors(Configurator.SectionVisitors):
formats = config.get(section, 'formats')
configuredFormats = formats.split(',')
for format in configuredFormats:
- name, found, rest = format.partition('/')
- sampleRate, found, rest = rest.partition('@')
- frameSize, found, formatSpecific = rest.partition(';')
-
item = AsteriskSCF.Configuration.SipSessionManager.V1.SipMediaFormatItem()
- item.name = name
- if sampleRate:
- item.sampleRate = sampleRate
- if frameSize:
- item.frameSize = frameSize
+
+ front, found, rest = format.partition('/')
+ if found:
+ item.name = front
+ else:
+ rest = front
+
+ front, found, rest = rest.partition('@')
+ if found:
+ if item.name:
+ item.sampleRate = front
+ else:
+ item.name = front
+ else:
+ rest = front
+
+ front, found, rest = rest.partition(';')
+ if found:
+ if item.name:
+ item.frameSize = front
+ else:
+ item.name = front
+ else:
+ rest = front
+
item.formatSpecific = [ ]
- if formatSpecific:
- item.formatSpecific.append(formatSpecific)
- group.configurationItems[format] = item
+ if not item.name:
+ item.name = format
+
+ if item.name:
+ while rest:
+ front, found, rest = rest.partition('&')
+ item.formatSpecific.append(front)
+
+ group.configurationItems[format] = item
except:
print 'No configured formats for endpoint ' + section
diff --git a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
index c22c91b..3641291 100644
--- a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
@@ -334,6 +334,32 @@ class SipRTPMediaServiceItem extends SipConfigurationItem
};
/**
+ * UDPTL Media service configuration item
+ */
+class SipUDPTLMediaServiceItem extends SipConfigurationItem
+{
+ /**
+ * Name of the UDPTL media service to use
+ */
+ string mediaServiceName;
+
+ /**
+ * Whether to choose an IPv6 UDPTL media service or not
+ */
+ bool requireIPv6 = false;
+
+ /**
+ * Boolean for whether ICE is enabled
+ */
+ bool enableICE = false;
+
+ /**
+ * Boolean for whether TURN is enabled
+ */
+ bool enableTURN = false;
+};
+
+/**
* Signaling NAT configuration item
*/
class SipSignalingNATItem extends SipConfigurationItem
diff --git a/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice b/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
index f982668..f9eab87 100644
--- a/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
+++ b/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
@@ -19,6 +19,7 @@
#include <Ice/Identity.ice>
#include <AsteriskSCF/Media/MediaIf.ice>
#include <AsteriskSCF/Media/RTP/MediaRTPIf.ice>
+#include <AsteriskSCF/Media/UDPTL/MediaUDPTLIf.ice>
#include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.ice>
#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.ice>
#include <AsteriskSCF/System/Component/ConfigurationIf.ice>
@@ -140,6 +141,7 @@ module V1
};
dictionary<string, AsteriskSCF::Media::RTP::V1::RTPSession*> RTPMediaSessionDict;
+ sequence<AsteriskSCF::Media::UDPTL::V1::UDPTLSession*> UDPTLMediaSessionSeq;
class SipSessionStateItem extends SipStateItem
{
@@ -153,6 +155,7 @@ module V1
AsteriskSCF::Media::V1::StreamSinkSeq sinks;
AsteriskSCF::Media::V1::StreamInformationDict streams;
RTPMediaSessionDict rtpMediaSessions;
+ UDPTLMediaSessionSeq udptlMediaSessions;
AsteriskSCF::SessionCommunications::V1::SessionListenerSeq listeners;
AsteriskSCF::SessionCommunications::V1::Bridge *bridge;
AsteriskSCF::SessionCommunications::V1::SessionCookieDict cookies;
diff --git a/src/NATOptions.h b/src/NATOptions.h
index 2319c50..5c71700 100644
--- a/src/NATOptions.h
+++ b/src/NATOptions.h
@@ -27,9 +27,11 @@ struct NATEndpointOptions
bool enableICE;
bool enableTURN;
bool enableSIPSTUN;
+ bool enableUDPTLICE;
+ bool enableUDPTLTURN;
- NATEndpointOptions(bool ice, bool turn, bool sip) :
- enableICE(ice), enableTURN(turn), enableSIPSTUN(sip)
+ NATEndpointOptions(bool ice, bool turn, bool sip, bool udptlice, bool udptlturn) :
+ enableICE(ice), enableTURN(turn), enableSIPSTUN(sip), enableUDPTLICE(udptlice), enableUDPTLTURN(udptlturn)
{
}
};
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 3b97fd4..9504d47 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -108,6 +108,7 @@ void PJSipSessionModInfo::updateSessionState(pjsip_inv_session *inv_session)
mSessionState->sources = mSession->getMediaSources();
mSessionState->sinks = mSession->getMediaSinks();
mSessionState->rtpMediaSessions = mSession->getRTPMediaSessions();
+ mSessionState->udptlMediaSessions = mSession->getUDPTLMediaSessions();
mSessionState->listeners = mSession->getListeners();
mSessionState->streams = mSession->getStreams();
try
@@ -1508,14 +1509,8 @@ private:
ServiceLocatorPrx mServiceLocator;
};
-void PJSipSessionModule::invOnMediaUpdate(pjsip_inv_session *inv, pj_status_t status)
+void PJSipSessionModule::invOnMediaUpdate(pjsip_inv_session *inv, pj_status_t)
{
- if (status != PJ_SUCCESS)
- {
- // We have nothing, zip, nada, kablamo, in common.
- return;
- }
-
lg(Debug) << "Queuing HandleMediaUpdate";
enqueueSessionWork(new HandleMediaUpdate(inv, mModule.id, mServiceLocator), inv);
}
diff --git a/src/SipConfiguration.cpp b/src/SipConfiguration.cpp
index f4c07ef..cd00465 100644
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@ -310,6 +310,11 @@ class EndpointConfigHelper : public boost::enable_shared_from_this<EndpointConfi
mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateMediaService, mConfig, service));
};
+ void visitSipUDPTLMediaServiceItem(const SipUDPTLMediaServiceItemPtr& service)
+ {
+ mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateUDPTLMediaService, mConfig, service));
+ };
+
void visitSipEndpointTransportItem(const SipEndpointTransportItemPtr& transport)
{
mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateTransport, mConfig, transport));
@@ -460,6 +465,13 @@ public:
mEndpoint->setRTPOverIPv6(service->requireIPv6);
}
+ void updateUDPTLMediaService(const SipUDPTLMediaServiceItemPtr& service)
+ {
+ mEndpoint->setUDPTLOverIPv6(service->requireIPv6);
+ mEndpoint->enableUDPTLICE(service->enableICE);
+ mEndpoint->enableUDPTLTURN(service->enableTURN);
+ }
+
void updateTransport(const SipEndpointTransportItemPtr& transport)
{
mEndpoint->setSecureTransport(translateCallDirection(transport->secureTransport));
diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index d017a06..f03e3ac 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -337,12 +337,26 @@ void SipEndpoint::setRTPOverIPv6(bool enabled)
mImplPriv->mConfig.sessionConfig.rtpOverIPv6 = enabled;
}
-
void SipEndpoint::setDirectMedia(bool enabled)
{
mImplPriv->mConfig.sessionConfig.directMedia = enabled;
}
+void SipEndpoint::setUDPTLOverIPv6(bool enabled)
+{
+ mImplPriv->mConfig.sessionConfig.udptlOverIPv6 = enabled;
+}
+
+void SipEndpoint::enableUDPTLICE(bool enabled)
+{
+ mImplPriv->mConfig.sessionConfig.udptlOverICE = enabled;
+}
+
+void SipEndpoint::enableUDPTLTURN(bool enabled)
+{
+ mImplPriv->mConfig.sessionConfig.udptlWithTURN = enabled;
+}
+
void SipEndpoint::setMediaNATOptions(bool useICE, bool useTURN)
{
mImplPriv->mConfig.sessionConfig.rtpOverICE = useICE;
@@ -446,8 +460,10 @@ AsteriskSCF::SessionCommunications::V1::SessionPrx SipEndpoint::createSession(
true,
mImplPriv->mConfig,
NATEndpointOptions(mImplPriv->mConfig.sessionConfig.rtpOverICE,
- mImplPriv->mConfig.sessionConfig.rtpICEIncludeTURN,
- mImplPriv->mConfig.transportConfig.enableNAT));
+ mImplPriv->mConfig.sessionConfig.rtpICEIncludeTURN,
+ mImplPriv->mConfig.transportConfig.enableNAT,
+ mImplPriv->mConfig.sessionConfig.udptlOverICE,
+ mImplPriv->mConfig.sessionConfig.udptlWithTURN));
mImplPriv->mSessions.push_back(session);
@@ -475,7 +491,9 @@ AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const s
mImplPriv->mConfig,
NATEndpointOptions(mImplPriv->mConfig.sessionConfig.rtpOverICE,
mImplPriv->mConfig.sessionConfig.rtpICEIncludeTURN,
- mImplPriv->mConfig.transportConfig.enableNAT)
+ mImplPriv->mConfig.transportConfig.enableNAT,
+ mImplPriv->mConfig.sessionConfig.udptlOverICE,
+ mImplPriv->mConfig.sessionConfig.udptlWithTURN)
);
mImplPriv->mSessions.push_back(session);
@@ -493,28 +511,32 @@ SipSessionPtr SipEndpoint::createSession
const Ice::Identity& controllerid,
const Ice::Identity& mediaid,
const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionDict& mediasessions,
+ const AsteriskSCF::Replication::SipSessionManager::V1::UDPTLMediaSessionSeq& udptlMediaSessions,
const AsteriskSCF::Media::V1::StreamSourceSeq& sources,
const AsteriskSCF::Media::V1::StreamSinkSeq& sinks)
{
SipSessionPtr session = SipSession::create
- (mImplPriv->mAdapter,
- this,
- destination,
- sessionid,
- controllerid,
- mediaid,
- mediasessions,
- sources,
- sinks,
- mImplPriv->mManager,
- mImplPriv->mServiceLocator,
- mImplPriv->mReplicationContext,
- 0,
- false,
- mImplPriv->mConfig,
- NATEndpointOptions(mImplPriv->mConfig.sessionConfig.rtpOverICE,
- mImplPriv->mConfig.sessionConfig.rtpICEIncludeTURN,
- mImplPriv->mConfig.transportConfig.enableNAT));
+ (mImplPriv->mAdapter,
+ this,
+ destination,
+ sessionid,
+ controllerid,
+ mediaid,
+ mediasessions,
+ udptlMediaSessions,
+ sources,
+ sinks,
+ mImplPriv->mManager,
+ mImplPriv->mServiceLocator,
+ mImplPriv->mReplicationContext,
+ 0,
+ false,
+ mImplPriv->mConfig,
+ NATEndpointOptions(mImplPriv->mConfig.sessionConfig.rtpOverICE,
+ mImplPriv->mConfig.sessionConfig.rtpICEIncludeTURN,
+ mImplPriv->mConfig.transportConfig.enableNAT,
+ mImplPriv->mConfig.sessionConfig.udptlOverICE,
+ mImplPriv->mConfig.sessionConfig.udptlWithTURN));
mImplPriv->mSessions.push_back(session);
return session;
@@ -767,6 +789,36 @@ SDPDescriptorPtr SipEndpoint::getDescriptor(const FormatPtr& format)
return 0;
}
+SDPDescriptorPtr SipEndpoint::getInterpretedDescriptor(const FormatPtr& format)
+{
+ for (std::vector<ConfiguredFormatPtr>::const_iterator configuredFormat = mImplPriv->mFormats.begin();
+ configuredFormat != mImplPriv->mFormats.end();
+ ++configuredFormat)
+ {
+ if ((*configuredFormat)->getFormat()->name == format->name)
+ {
+ return (*configuredFormat)->getDescriptorService()->getDescriptor(format);
+ }
+ }
+
+ return 0;
+}
+
+FormatPtr SipEndpoint::getFormat(const FormatPtr& format)
+{
+ for (std::vector<ConfiguredFormatPtr>::const_iterator configuredFormat = mImplPriv->mFormats.begin();
+ configuredFormat != mImplPriv->mFormats.end();
+ ++configuredFormat)
+ {
+ if ((*configuredFormat)->getFormat()->name == format->name)
+ {
+ return (*configuredFormat)->getFormat();
+ }
+ }
+
+ return 0;
+}
+
StreamInformationDict SipEndpoint::getStreamTopology()
{
StreamInformationDict topology;
@@ -776,6 +828,12 @@ StreamInformationDict SipEndpoint::getStreamTopology()
configuredFormat != mImplPriv->mFormats.end();
++configuredFormat)
{
+ // Initial stream topology does not support T.38 streams
+ if ((*configuredFormat)->getDescriptor()->type == "image")
+ {
+ continue;
+ }
+
// See if a stream already exists for this type
StreamInformationDict::iterator stream = topology.find((*configuredFormat)->getDescriptor()->type);
diff --git a/src/SipEndpoint.h b/src/SipEndpoint.h
index 0a07081..037b1b3 100644
--- a/src/SipEndpoint.h
+++ b/src/SipEndpoint.h
@@ -161,6 +161,12 @@ public:
bool rtpOverIPv6;
// Whether we are allowing direct media or not
bool directMedia;
+ // Whether we are using IPv6 for UDPTL transport or not.
+ bool udptlOverIPv6;
+ // Whether ICE is enabled for UDPTL.
+ bool udptlOverICE;
+ // Whether TURN is enabled for UDPTL.
+ bool udptlWithTURN;
// The method by which we will transmit
// DTMF to an endpoint
AsteriskSCF::Configuration::SipSessionManager::V1::SipDTMFOption dtmf;
@@ -321,6 +327,7 @@ public:
AsteriskSCF::SipSessionManager::SipSessionPtr createSession(const std::string&);
AsteriskSCF::SipSessionManager::SipSessionPtr createSession(const std::string&, const Ice::Identity&, const Ice::Identity&,
const Ice::Identity&, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionDict&,
+ const AsteriskSCF::Replication::SipSessionManager::V1::UDPTLMediaSessionSeq&,
const AsteriskSCF::Media::V1::StreamSourceSeq&, const AsteriskSCF::Media::V1::StreamSinkSeq&);
void removeSession(const AsteriskSCF::SessionCommunications::V1::SessionPtr&);
@@ -336,6 +343,9 @@ public:
void setSecureTransport(enum Direction);
void setRTPOverIPv6(bool);
void setDirectMedia(bool);
+ void setUDPTLOverIPv6(bool);
+ void enableUDPTLICE(bool);
+ void enableUDPTLTURN(bool);
void addFormat(const std::string& name, int sampleRate, int frameSize, const Ice::StringSeq& formatSpecific);
/**
@@ -345,11 +355,21 @@ public:
const AsteriskSCF::Media::SDP::V1::SDPDescriptorPtr&);
/**
- * API call which returns a descriptor given a media format.
+ * API call which returns a locally cached descriptor given a media format.
*/
AsteriskSCF::Media::SDP::V1::SDPDescriptorPtr getDescriptor(const AsteriskSCF::Media::V1::FormatPtr&);
/**
+ * API call which returns a descriptor given a media format.
+ */
+ AsteriskSCF::Media::SDP::V1::SDPDescriptorPtr getInterpretedDescriptor(const AsteriskSCF::Media::V1::FormatPtr&);
+
+ /**
+ * API call which returns the local format given a media format.
+ */
+ AsteriskSCF::Media::V1::FormatPtr getFormat(const AsteriskSCF::Media::V1::FormatPtr&);
+
+ /**
* API call which returns the stream topology to be used for an SDP offer.
*/
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index dce14ab..3182731 100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -40,6 +40,9 @@
#include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
#include <AsteriskSCF/Media/SDP/MediaSDPIf.h>
#include <AsteriskSCF/Media/RTP/MediaRTCPIf.h>
+#include <AsteriskSCF/Media/UDPTL/MediaUDPTLIf.h>
+#include <AsteriskSCF/Media/Formats/T38UdptlFormat.h>
+#include <AsteriskSCF/Media/NetworkIf.h>
#include <AsteriskSCF/SessionCookies/SipSessionManager/SipSessionCookiesIf.h>
#include <AsteriskSCF/Collections/HandleSet.h>
#include "NATOptions.h"
@@ -52,6 +55,9 @@ using namespace AsteriskSCF::Media::RTP::V1;
using namespace AsteriskSCF::Media::V1;
using namespace AsteriskSCF::Media;
using namespace AsteriskSCF::Media::SDP::V1;
+using namespace AsteriskSCF::Media::UDPTL::V1;
+using namespace AsteriskSCF::Media::Formats::T38Udptl::V1;
+using namespace AsteriskSCF::Network::V1;
using namespace AsteriskSCF::System::V1;
using namespace AsteriskSCF::Helpers;
using namespace std;
@@ -284,6 +290,11 @@ public:
RTPMediaSessionDict mRTPSessions;
/**
+ * A vector of UDPTL media sessions belonging to this session.
+ */
+ UDPTLMediaSessionSeq mUDPTLSessions;
+
+ /**
* A vector of media sources associated with this endpoint.
*/
AsteriskSCF::Media::V1::StreamSourceSeq mSources;
@@ -1276,37 +1287,39 @@ SipSessionPtr SipSession::create(const Ice::ObjectAdapterPtr& adapter,
* Factory used by a standby component to create replicas.
*/
SipSessionPtr SipSession::create(const Ice::ObjectAdapterPtr& adapter,
- const SipEndpointPtr& endpoint,
- const std::string& destination,
- const Ice::Identity& sessionid,
- const Ice::Identity& controllerid,
- const Ice::Identity& mediaid,
- const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionDict& mediasessions,
- const AsteriskSCF::Media::V1::StreamSourceSeq& sources,
- const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
- const PJSipManagerPtr& manager,
- const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
- const SipReplicationContextPtr& replicationContext,
- const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx& oneShotHook,
- bool isUAC,
- const SipEndpointConfig &config,
- const NATEndpointOptions& natOptions)
+ const SipEndpointPtr& endpoint,
+ const std::string& destination,
+ const Ice::Identity& sessionid,
+ const Ice::Identity& controllerid,
+ const Ice::Identity& mediaid,
+ const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionDict& mediasessions,
+ const AsteriskSCF::Replication::SipSessionManager::V1::UDPTLMediaSessionSeq& udptlMediaSessions,
+ const AsteriskSCF::Media::V1::StreamSourceSeq& sources,
+ const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
+ const PJSipManagerPtr& manager,
+ const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
+ const SipReplicationContextPtr& replicationContext,
+ const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx& oneShotHook,
+ bool isUAC,
+ const SipEndpointConfig &config,
+ const NATEndpointOptions& natOptions)
{
SipSessionPtr newSession = new SipSession(adapter,
- endpoint,
- destination,
- sessionid,
- controllerid,
- mediaid,
- mediasessions,
- sources,
- sinks,
- manager,
- serviceLocator,
- replicationContext,
- isUAC,
- config,
- natOptions);
+ endpoint,
+ destination,
+ sessionid,
+ controllerid,
+ mediaid,
+ mediasessions,
+ udptlMediaSessions,
+ sources,
+ sinks,
+ manager,
+ serviceLocator,
+ replicationContext,
+ isUAC,
+ config,
+ natOptions);
AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookSeq hooks =
newSession->mImplPriv->mManager->getSessionModule()->getSessionCreationHooks();
@@ -1376,6 +1389,7 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter,
const Ice::Identity& controllerid,
const Ice::Identity& mediaid,
const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionDict& mediasessions,
+ const AsteriskSCF::Replication::SipSessionManager::V1::UDPTLMediaSessionSeq& udptlMediaSessions,
const AsteriskSCF::Media::V1::StreamSourceSeq& sources,
const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
const PJSipManagerPtr& manager,
@@ -1401,6 +1415,7 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter,
adapter->addFacet(directMedia, sessionid, directMediaConnectionFacet);
mImplPriv->mRTPSessions = mediasessions;
+ mImplPriv->mUDPTLSessions = udptlMediaSessions;
mImplPriv->mSources = sources;
mImplPriv->mSinks = sinks;
@@ -2434,6 +2449,19 @@ public:
lg(Error) << "Exception caught while trying to release a media session\n" << ex.what();
}
}
+
+ for (UDPTLMediaSessionSeq::const_iterator i = mSessionPriv->mUDPTLSessions.begin();
+ i != mSessionPriv->mUDPTLSessions.end(); ++i)
+ {
+ try
+ {
+ (*i)->release();
+ }
+ catch (const Ice::Exception& ex)
+ {
+ lg(Error) << "Exception caught while trying to release a udptl session\n" << ex.what();
+ }
+ }
}
mSessionPriv->mEndpoint->removeSession(mSession);
return Complete;
@@ -2710,111 +2738,224 @@ pjmedia_sdp_session *SipSession::createSDPOffer(const AsteriskSCF::Media::V1::St
// Update the stream with the actual formats
stream->second->formats = formats;
- RTPServiceLocatorParamsPtr params = new RTPServiceLocatorParams();
- params->category = "rtp";
- params->formats = stream->second->formats;
- params->ipv6 = mImplPriv->mEndpoint->getConfig().sessionConfig.rtpOverIPv6;
+ // Determine what media this stream is carrying
+ AudioFormatPtr audio;
+ VideoFormatPtr video;
+ T38UdptlFormatPtr t38;
- // Try to find a factory for RTP sessions matching what we need
- RTPMediaServicePrx factory = RTPMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
-
- // If none exist we can't provide the stream
- if (factory == 0)
+ // If this stream contains an audio or video format the stream is transported using RTP
+ if ((audio = AudioFormatPtr::dynamicCast(formats.front())) || (video = VideoFormatPtr::dynamicCast(formats.front())))
{
- continue;
- }
+ RTPServiceLocatorParamsPtr params = new RTPServiceLocatorParams();
+ params->category = "rtp";
+ params->formats = stream->second->formats;
+ params->ipv6 = mImplPriv->mEndpoint->getConfig().sessionConfig.rtpOverIPv6;
+
+ // Try to find a factory for RTP sessions matching what we need
+ RTPMediaServicePrx factory = RTPMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
+
+ if (factory == 0)
+ {
+ continue;
+ }
- // Allocate a new RTP session to carry the media formats we have in common
+ // Allocate a new RTP session to carry the media formats we have in common
- RTPOptionsPtr options(new RTPOptions());
- RTPAllocationOutputsPtr outputs;
+ RTPOptionsPtr options(new RTPOptions());
+ RTPAllocationOutputsPtr outputs;
- SipEndpointConfig& config = mImplPriv->mEndpoint->getConfig();
- if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SipSessionManager::V1::RFC4733)
- {
- options->handleTelephonyEvents = true;
- }
+ SipEndpointConfig& config = mImplPriv->mEndpoint->getConfig();
+ if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SipSessionManager::V1::RFC4733)
+ {
+ options->handleTelephonyEvents = true;
+ }
- RTPSessionPrx session = factory->allocate(params, options, outputs);
+ RTPSessionPrx session = factory->allocate(params, options, outputs);
- // Double check to make sure they actually gave us a sesson back... they could have had a problem
- if (session == 0)
- {
- continue;
- }
+ // Double check to make sure they actually gave us a sesson back... they could have had a problem
+ if (session == 0)
+ {
+ continue;
+ }
- if (outputs)
- {
- mImplPriv->mExternalEventSources = outputs->eventSources;
- mImplPriv->mExternalEventSinks = outputs->eventSinks;
- }
+ if (outputs)
+ {
+ mImplPriv->mExternalEventSources = outputs->eventSources;
+ mImplPriv->mExternalEventSinks = outputs->eventSinks;
+ }
- // RTP sessions should only provide a single sink, so grab it and update the connection details with that
- // of the remote party
- StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(session->getSinks().front());
- mImplPriv->mSinks.push_back(sink);
- stream->second->sinks.push_back(sink);
+ // RTP sessions should only provide a single sink, so grab it and update the connection details with that
+ // of the remote party
+ StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(session->getSinks().front());
+ mImplPriv->mSinks.push_back(sink);
+ stream->second->sinks.push_back(sink);
- // Ditto goes for source
- StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(session->getSources().front());
- mImplPriv->mSources.push_back(source);
- stream->second->sources.push_back(source);
+ // Ditto goes for source
+ StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(session->getSources().front());
+ mImplPriv->mSources.push_back(source);
+ stream->second->sources.push_back(source);
- // Update the SIP session with some RTP session details
- mImplPriv->mRTPSessions.insert(make_pair(boost::lexical_cast<std::string>(mImplPriv->mSDP->media_count), session));
+ // Update the SIP session with some RTP session details
+ mImplPriv->mRTPSessions.insert(make_pair(boost::lexical_cast<std::string>(mImplPriv->mSDP->media_count), session));
+
+ // Add the stream to the SDP
+ pjmedia_sdp_media *media = allocate_from_pool<pjmedia_sdp_media>(mImplPriv->mDialog->pool);
- // Add the stream to the SDP
- pjmedia_sdp_media *media = allocate_from_pool<pjmedia_sdp_media>(mImplPriv->mDialog->pool);
+ // The media count is purposely not incremented here since it is done when the stream is added to the sequence
+ // of streams
+ mImplPriv->mSDP->media[mImplPriv->mSDP->media_count] = media;
+ pj_strdup2(mImplPriv->mDialog->pool, &media->desc.media, mImplPriv->mEndpoint->getDescriptor(
+ stream->second->formats.front())->type.c_str());
- // The media count is purposely not incremented here since it is done when the stream is added to the sequence
- // of streams
- mImplPriv->mSDP->media[mImplPriv->mSDP->media_count] = media;
- pj_strdup2(mImplPriv->mDialog->pool, &media->desc.media, mImplPriv->mEndpoint->getDescriptor(
- stream->second->formats.front())->type.c_str());
+ pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "RTP/AVP");
- // TODO: This should not be hardcoded
- pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "RTP/AVP");
+ // Add connection level details
+ media->conn = allocate_from_pool<pjmedia_sdp_conn>(mImplPriv->mDialog->pool);
+ pj_strdup2(mImplPriv->mDialog->pool, &media->conn->net_type, "IN");
- // Add connection level details
- media->conn = allocate_from_pool<pjmedia_sdp_conn>(mImplPriv->mDialog->pool);
- pj_strdup2(mImplPriv->mDialog->pool, &media->conn->net_type, "IN");
+ if (params->ipv6 == true)
+ {
+ pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP6");
+ }
+ else
+ {
+ pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP4");
+ }
- if (params->ipv6 == true)
- {
- pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP6");
+ pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr, source->getLocalAddress().c_str());
+
+ // If session level connection information has not yet been set then set it to us
+ if (!mImplPriv->mSDP->conn)
+ {
+ mImplPriv->mSDP->conn = media->conn;
+ }
+
+ media->desc.port = (pj_uint16_t) source->getLocalPort();
+ media->desc.port_count = 1;
+
+ RTCP::V1::RTCPSessionPrx rtcpSession;
+ if ((rtcpSession = RTCP::V1::RTCPSessionPrx::checkedCast(session, RTCP::V1::SessionFacet)))
+ {
+ pjmedia_sdp_attr *attr = allocate_from_pool<pjmedia_sdp_attr>(mImplPriv->mDialog->pool);
+ pj_strdup2(mImplPriv->mDialog->pool, &attr->name, "rtcp");
+ pj_strdup2(mImplPriv->mDialog->pool, &attr->value, boost::lexical_cast<std::string>(rtcpSession->getLocalPort()).c_str());
+ media->attr[media->attr_count++] = attr;
+ }
+
+ PayloadMap payloads;
+
+ // Add all of the formats to the SDP
+ addFormatstoSDP(stream->second->formats, media, payloads);
+
+ // Push the payload mapping to the RTP session so it'll correctly map things
+ session->associatePayloads(payloads);
}
- else
+ else if ((t38 = T38UdptlFormatPtr::dynamicCast(formats.front())))
{
- pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP4");
- }
+ UDPTLServiceLocatorParamsPtr params;
- pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr, source->getLocalAddress().c_str());
+ if (mImplPriv->mNatOptions.enableUDPTLICE)
+ {
+ AsteriskSCF::Media::UDPTL::V1::UDPTLOverICEServiceLocatorParamsPtr iceParams =
+ new AsteriskSCF::Media::UDPTL::V1::UDPTLOverICEServiceLocatorParams;
+ params = iceParams;
+ iceParams->enableICE = true;
+ iceParams->enableTURN = mImplPriv->mNatOptions.enableUDPTLTURN;
+ }
+ else
+ {
+ params = new AsteriskSCF::Media::UDPTL::V1::UDPTLServiceLocatorParams;
+ }
- // If session level connection information has not yet been set then set it to us
- if (!mImplPriv->mSDP->conn)
- {
- mImplPriv->mSDP->conn = media->conn;
- }
+ params->category = "udptl";
+ params->ipv6 = mImplPriv->mEndpoint->getConfig().sessionConfig.udptlOverIPv6;
- media->desc.port = (pj_uint16_t) source->getLocalPort();
- media->desc.port_count = 1;
+ UDPTLMediaServicePrx factory = UDPTLMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
+ if (factory == 0)
+ {
+ continue;
+ }
- RTCP::V1::RTCPSessionPrx rtcpSession;
- if ((rtcpSession = RTCP::V1::RTCPSessionPrx::checkedCast(session, RTCP::V1::SessionFacet)))
- {
- pjmedia_sdp_attr *attr = allocate_from_pool<pjmedia_sdp_attr>(mImplPriv->mDialog->pool);
- pj_strdup2(mImplPriv->mDialog->pool, &attr->name, "rtcp");
- pj_strdup2(mImplPriv->mDialog->pool, &attr->value, boost::lexical_cast<std::string>(rtcpSession->getLocalPort()).c_str());
- media->attr[media->attr_count++] = attr;
- }
+ UDPTLSessionPrx session = factory->allocate(params);
+ if (session == 0)
+ {
+ continue;
+ }
- PayloadMap payloads;
+ StreamSinkUDPTLPrx sink = StreamSinkUDPTLPrx::uncheckedCast(session->getSinks().front());
+ mImplPriv->mSinks.push_back(sink);
+ stream->second->sinks.push_back(sink);
+
+ StreamSourceUDPTLPrx source = StreamSourceUDPTLPrx::uncheckedCast(session->getSources().front());
+ mImplPriv->mSources.push_back(source);
+ stream->second->sources.push_back(source);
+
+ mImplPriv->mUDPTLSessions.push_back(session);
+
+ // Add the stream to the SDP
+ mImplPriv->mSDP->media_count = 0;
- // Add all of the formats to the SDP
- addFormatstoSDP(stream->second->formats, media, payloads);
+ // Since we may be replacing an existing stream go ahead and remove it
+ mImplPriv->mStreams.erase(boost::lexical_cast<std::string>(mImplPriv->mSDP->media_count));
+
+ pjmedia_sdp_media *media = allocate_from_pool<pjmedia_sdp_media>(mImplPriv->mDialog->pool);
+ // The media count is purposely not incremented here since it is done when the stream is added to the sequence
+ // of streams
+ mImplPriv->mSDP->media[mImplPriv->mSDP->media_count] = media;
+
+ pj_strdup2(mImplPriv->mDialog->pool, &media->desc.media, mImplPriv->mEndpoint->getDescriptor(
+ stream->second->formats.front())->type.c_str());
+
+ pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "UDPTL");
+
+ pj_strdup2(mImplPriv->mDialog->pool, &media->desc.fmt[media->desc.fmt_count++], "t38");
+
+ // Add connection level details
+ media->conn = allocate_from_pool<pjmedia_sdp_conn>(mImplPriv->mDialog->pool);
+ pj_strdup2(mImplPriv->mDialog->pool, &media->conn->net_type, "IN");
+
+ if (params->ipv6 == true)
+ {
+ pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP6");
+ }
+ else
+ {
+ pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP4");
+ }
+
+ AddressInformation info = source->getLocalDetails();
+
+ pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr, info.ipAddress.c_str());
+
+ // If session level connection information has not yet been set then set it to us
+ if (!mImplPriv->mSDP->conn)
+ {
+ mImplPriv->mSDP->conn = media->conn;
+ }
+
+ media->desc.port = (pj_uint16_t) info.port;
+ media->desc.port_count = 1;
- // Push the payload mapping to the RTP session so it'll correctly map things
- session->associatePayloads(payloads);
+ // Use the configured format to set the error correction
+ T38UdptlFormatPtr t38Configuration = T38UdptlFormatPtr::dynamicCast(mImplPriv->mEndpoint->getFormat(t38));
+
+ t38->errorCorrection = t38Configuration->errorCorrection;
+
+ SDPDescriptorPtr ourDescriptor = mImplPriv->mEndpoint->getInterpretedDescriptor(t38);
+ for (SDPFormatParameterSeq::const_iterator parameter = ourDescriptor->parameters.begin();
+ parameter != ourDescriptor->parameters.end();
+ ++parameter)
+ {
+ pjmedia_sdp_attr *attr = allocate_from_pool<pjmedia_sdp_attr>(mImplPriv->mDialog->pool);
+ pj_strdup2(mImplPriv->mDialog->pool, &attr->name, (*parameter).c_str());
+ media->attr[media->attr_count++] = attr;
+ }
+ }
+ else
+ {
+ // The media format type is just unknown to us, so we can not create a stream for this
+ continue;
+ }
// Make the caller aware of this new stream
newStreams.insert(make_pair(boost::lexical_cast<std::string>(mImplPriv->mSDP->media_count), stream->second));
@@ -2903,11 +3044,21 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
{
SDPDescriptorPtr descriptor = new SDPDescriptor();
- std::string payload = std::string(pj_strbuf(&offer->media[stream]->desc.fmt[format]),
- pj_strlen(&offer->media[stream]->desc.fmt[format]));
- descriptor->payload = boost::lexical_cast<int>(payload);
descriptor->type = std::string(pj_strbuf(&offer->media[stream]->desc.media),
pj_strlen(&offer->media[stream]->desc.media));
+ std::string payload = std::string(pj_strbuf(&offer->media[stream]->desc.fmt[format]),
+ pj_strlen(&offer->media[stream]->desc.fmt[format]));
+
+ // If this is for T.38 it is actually special
+ if (descriptor->type == "image" && (payload == "T38" || payload == "t38"))
+ {
+ descriptor->payload = 96;
+ descriptor->subtype = "UDPTL";
+ }
+ else
+ {
+ descriptor->payload = boost::lexical_cast<int>(payload);
+ }
// Some devices rely solely on the payload for known formats (such as PCMU) so the following format
// parameters are completely optional
@@ -2992,8 +3143,29 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
continue;
}
- // Update the stream with the formats
- ourStream->formats = formats;
+ // Update the stream with the formats
+ ourStream->formats = formats;
+
+ // Record the old state so we can relay the state change to the controller if needed
+ StreamState oldState = ourStream->state;
+
+ // Determine the state of the stream and update it
+ if (pjmedia_sdp_media_find_attr2(offer->media[stream], "sendonly", NULL))
+ {
+ ourStream->state = SendOnly;
+ }
+ else if (pjmedia_sdp_media_find_attr2(offer->media[stream], "recvonly", NULL))
+ {
+ ourStream->state = ReceiveOnly;
+ }
+ else if (pjmedia_sdp_media_find_attr2(offer->media[stream], "inactive", NULL))
+ {
+ ourStream->state = Inactive;
+ }
+ else if (pjmedia_sdp_media_find_attr2(offer->media[stream], "sendrecv", NULL))
+ {
+ ourStream->state = SendAndReceive;
+ }
// Assume that no connection level details exist until proven otherwise
std::string connection = destination;
@@ -3003,193 +3175,366 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
pj_strlen(&offer->media[stream]->conn->addr));
}
- RTPSessionPrx session;
+ AudioFormatPtr audio;
+ VideoFormatPtr video;
+ T38UdptlFormatPtr t38;
- // If no sink and no source is present then this stream has no RTP session yet so find one
- if (ourStream->sinks.empty() && ourStream->sources.empty())
- {
- RTPServiceLocatorParamsPtr params;
- if (mImplPriv->mNatOptions.enableICE)
- {
- AsteriskSCF::Media::RTP::V1::RTPOverICEServiceLocatorParamsPtr iceParams =
- new AsteriskSCF::Media::RTP::V1::RTPOverICEServiceLocatorParams;
- params = iceParams;
- iceParams->enableRTPOverICE = true;
- iceParams->enableTURN = mImplPriv->mNatOptions.enableTURN;
- }
- else
+ if ((audio = AudioFormatPtr::dynamicCast(formats.front())) || (video = VideoFormatPtr::dynamicCast(formats.front())))
{
- params = new AsteriskSCF::Media::RTP::V1::RTPServiceLocatorParams;
- }
-
- params->category = "rtp";
- params->formats = formats;
-
- // See what address family the connection address is in so we can request the right RTP service
- if (connection.find(":") != std::string::npos)
+ // If this is a modified stream make sure the transport is RTP, if not clear things out
+ if (!ourStream->sinks.empty())
{
- params->ipv6 = true;
+ StreamSinkRTPPrx rtpSink = StreamSinkRTPPrx::checkedCast(ourStream->sinks.front());
+ if (!rtpSink)
+ {
+ ourStream->sinks.clear();
+ newStreams.erase(boost::lexical_cast<std::string>(stream));
+ newStreams.insert(make_pair(boost::lexical_cast<std::string>(stream), ourStream));
+ }
}
- else
+
+ if (!ourStream->sources.empty())
{
- params->ipv6 = false;
+ StreamSourceRTPPrx rtpSource = StreamSourceRTPPrx::checkedCast(ourStream->sources.front());
+ if (!rtpSource)
+ {
+ ourStream->sources.clear();
+ newStreams.erase(boost::lexical_cast<std::string>(stream));
+ newStreams.insert(make_pair(boost::lexical_cast<std::string>(stream), ourStream));
+ }
}
- // Try to find a factory for RTP sessions matching what we need
- RTPMediaServicePrx factory = RTPMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
+ RTPSessionPrx session;
- // If none exist we can't provide accept the stream
- if (factory == 0)
+ // If no sink and no source is present then this stream has no RTP session yet so find one
+ if (ourStream->sinks.empty() && ourStream->sources.empty())
{
- // The only time this should ever occur is on the initial INVITE so removing the stream from everywhere
- // is perfectly acceptable since nothing has seen it
- mImplPriv->mStreams.erase(boost::lexical_cast<std::string>(stream));
- newStreams.erase(boost::lexical_cast<std::string>(stream));
- continue;
+ RTPServiceLocatorParamsPtr params;
+ if (mImplPriv->mNatOptions.enableICE)
+ {
+ AsteriskSCF::Media::RTP::V1::RTPOverICEServiceLocatorParamsPtr iceParams =
+ new AsteriskSCF::Media::RTP::V1::RTPOverICEServiceLocatorParams;
+ params = iceParams;
+ iceParams->enableRTPOverICE = true;
+ iceParams->enableTURN = mImplPriv->mNatOptions.enableTURN;
+ }
+ else
+ {
+ params = new AsteriskSCF::Media::RTP::V1::RTPServiceLocatorParams;
+ }
+
+ params->category = "rtp";
+ params->formats = formats;
+
+ // See what address family the connection address is in so we can request the right RTP service
+ if (connection.find(":") != std::string::npos)
+ {
+ params->ipv6 = true;
+ }
+ else
+ {
+ params->ipv6 = false;
... 7752 lines suppressed ...
--
asterisk-scf/integration/sip.git
More information about the asterisk-scf-commits
mailing list