[asterisk-scf-commits] asterisk-scf/integration/media_rtp_pjmedia.git branch "nat-traversal" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Mon May 16 14:08:16 CDT 2011
branch "nat-traversal" has been updated
via 063e9b5292bd991bebe02973acdaf2e78aa167fa (commit)
via d02e5d1a88c30417aac41b2ee76c4a58dce6abc8 (commit)
via d3030cb2eb13578921d5c4087d05e758aa47c842 (commit)
via 531ffcae24172273c8952b97d2360e4097992268 (commit)
from d129982f703ddde8692228e71454c6cc94b443d9 (commit)
Summary of changes:
CMakeLists.txt | 37 ---
src/CMakeLists.txt | 56 ++---
src/ICEConfiguration.cpp | 40 +++
src/ICEConfiguration.h | 71 +++++
src/MediaRTPpjmedia.cpp | 40 ++--
src/NATConfig.cpp | 102 +++++++
src/NATConfig.h | 75 ++++++
src/NATModule.cpp | 72 +++++
src/NATModule.h | 57 ++++
src/PJLibConfiguration.cpp | 38 +++
src/PJLibConfiguration.h | 64 +++++
src/PJMediaEnvironment.cpp | 58 ++++
src/PJMediaEnvironment.h | 96 +++++++
src/{ServiceConfig.h => PJUtil.h} | 25 +-
src/RTPICESession.cpp | 517 +++++++++++++++---------------------
src/RTPICESession.h | 31 +++
src/RTPSession.cpp | 36 ++--
src/RTPSession.h | 34 +--
src/RTPSink.cpp | 16 +-
src/RTPSink.h | 8 +
src/RTPSource.cpp | 12 +-
src/RTPSource.h | 6 +
src/RtpStateReplicator.h | 25 +-
src/RtpStateReplicatorListener.cpp | 12 +-
test/CMakeLists.txt | 13 +-
25 files changed, 1047 insertions(+), 494 deletions(-)
create mode 100644 src/ICEConfiguration.cpp
create mode 100644 src/ICEConfiguration.h
create mode 100644 src/NATConfig.cpp
create mode 100644 src/NATConfig.h
create mode 100644 src/NATModule.cpp
create mode 100644 src/NATModule.h
create mode 100644 src/PJLibConfiguration.cpp
create mode 100644 src/PJLibConfiguration.h
create mode 100644 src/PJMediaEnvironment.cpp
create mode 100644 src/PJMediaEnvironment.h
copy src/{ServiceConfig.h => PJUtil.h} (63%)
- Log -----------------------------------------------------------------
commit 063e9b5292bd991bebe02973acdaf2e78aa167fa
Author: Brent Eagles <beagles at digium.com>
Date: Mon May 16 15:56:05 2011 -0230
Commit in progress changes.
- pull out support classes into separate files
- fix renaming
- move pjmedia initialization into a class and have the existing construction work off of it
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 046cc47..ad6dc88 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,5 +1,4 @@
-include_directories(${utils_dir}/StateReplicator/include)
-include_directories(${utils_dir}/SmartProxy/include)
+include_directories(${utils_dir}/include)
include_directories(${API_INCLUDE_DIR})
if(NOT logger_dir)
message(FATAL_ERROR "The logger directory could not be found ${logger_dir}")
@@ -18,6 +17,19 @@ asterisk_scf_component_add_file(media_rtp_pjmedia RTPSource.h)
asterisk_scf_component_add_file(media_rtp_pjmedia RTPSink.h)
asterisk_scf_component_add_file(media_rtp_pjmedia RTPICESession.cpp)
asterisk_scf_component_add_file(media_rtp_pjmedia RTPICESession.h)
+asterisk_scf_component_add_file(media_rtp_pjmedia NATModule.cpp)
+asterisk_scf_component_add_file(media_rtp_pjmedia NATModule.h)
+asterisk_scf_component_add_file(media_rtp_pjmedia NATConfig.cpp)
+asterisk_scf_component_add_file(media_rtp_pjmedia NATConfig.h)
+asterisk_scf_component_add_file(media_rtp_pjmedia ICEConfiguration.cpp)
+asterisk_scf_component_add_file(media_rtp_pjmedia ICEConfiguration.h)
+asterisk_scf_component_add_file(media_rtp_pjmedia PJMediaEnvironment.cpp)
+asterisk_scf_component_add_file(media_rtp_pjmedia PJMediaEnvironment.h)
+asterisk_scf_component_add_file(media_rtp_pjmedia PJLibConfiguration.cpp)
+asterisk_scf_component_add_file(media_rtp_pjmedia PJLibConfiguration.h)
+asterisk_scf_component_add_file(media_rtp_pjmedia PJUtil.h)
+asterisk_scf_component_add_file(media_rtp_pjmedia ServiceConfig.h)
+
asterisk_scf_component_add_file(media_rtp_pjmedia RtpStateReplicatorListener.cpp)
asterisk_scf_component_add_file(media_rtp_pjmedia RtpStateReplicator.h)
asterisk_scf_component_add_slice(media_rtp_pjmedia ../local-slice/RtpStateReplicationIf.ice)
@@ -25,6 +37,7 @@ asterisk_scf_component_add_boost_libraries(media_rtp_pjmedia core thread)
asterisk_scf_component_build_icebox(media_rtp_pjmedia)
target_link_libraries(media_rtp_pjmedia logging-client)
target_link_libraries(media_rtp_pjmedia asterisk-scf-api)
+target_link_libraries(media_rtp_pjmedia ice-util-cpp)
pjproject_link(media_rtp_pjmedia pjlib)
pjproject_link(media_rtp_pjmedia pjlib-util)
pjproject_link(media_rtp_pjmedia pjmedia)
diff --git a/src/ICEConfiguration.cpp b/src/ICEConfiguration.cpp
new file mode 100644
index 0000000..2cdc1c7
--- /dev/null
+++ b/src/ICEConfiguration.cpp
@@ -0,0 +1,40 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, 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 "ICEConfiguration.h"
+#include <Ice/Properties.h>
+
+using namespace std;
+using namespace AsteriskSCF::PJMediaRTP;
+
+ICEConfigurationPtr AsteriskSCF::PJMediaRTP::ICEConfiguration::create(const Ice::PropertiesPtr& props,
+ const string& propertyPrefix)
+{
+ string prefix(propertyPrefix);
+ if (!prefix.empty() && prefix.back() != '.')
+ {
+ prefix += '.';
+ }
+ int maxCandidates = props->getPropertyAsIntWithDefault(prefix + "ICE.MaxCandidates", 2);
+ int maxCalls = props->getPropertyAsIntWithDefault(prefix + "ICE.MaxCalls", 2);
+ return ICEConfigurationPtr(new ICEConfiguration(maxCandidates, maxCalls));
+}
+
+ICEConfiguration::ICEConfiguration(int maxCandidates, int maxCalls) :
+ mMaxCandidates(maxCandidates),
+ mMaxCalls(maxCalls)
+{
+}
diff --git a/src/ICEConfiguration.h b/src/ICEConfiguration.h
new file mode 100644
index 0000000..31c265a
--- /dev/null
+++ b/src/ICEConfiguration.h
@@ -0,0 +1,71 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, 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.
+ */
+
+#pragma once
+
+#include <Ice/PropertiesF.h>
+#include <string>
+#include <boost/shared_ptr.hpp>
+
+namespace AsteriskSCF
+{
+namespace PJMediaRTP
+{
+
+class ICEConfiguration;
+typedef boost::shared_ptr<ICEConfiguration> ICEConfigurationPtr;
+
+/**
+ * ICEConfiguration is fairly minimal at the moment, but may grow in the future. The intent is to reduce code
+ * duplication when dealing with pjproject related configuration. This is also an immutable object, so locking is not an
+ * issue.
+ **/
+class ICEConfiguration
+{
+public:
+
+ int maxCandidates() const
+ {
+ return mMaxCandidates;
+ }
+
+ int maxCalls() const
+ {
+ return mMaxCalls;
+ }
+
+ /**
+ * Create configuration instance from Ice properties. TODO: This could be extended by adding additional factory
+ * overrides.
+ **/
+ static ICEConfigurationPtr create(const Ice::PropertiesPtr& props,
+ const std::string& propertyPrefix);
+
+private:
+ int mMaxCandidates;
+ int mMaxCalls;
+
+ ICEConfiguration(int maxCandidates, int maxCalls);
+
+ //
+ // Hidden and not implemented.
+ //
+ ICEConfiguration(const ICEConfiguration&);
+ void operator=(const ICEConfiguration&);
+};
+
+} /* End of namespace ICEMediaSession */
+} /* End of namespace AsteriskSCF */
diff --git a/src/MediaRTPpjmedia.cpp b/src/MediaRTPpjmedia.cpp
index 247a5af..fe5954c 100644
--- a/src/MediaRTPpjmedia.cpp
+++ b/src/MediaRTPpjmedia.cpp
@@ -30,20 +30,23 @@
#include <AsteriskSCF/System/Component/ReplicaIf.h>
#include <AsteriskSCF/Logger/IceLogger.h>
#include <AsteriskSCF/logger.h>
-#include <AsteriskSCF/SmartProxy.h>
+#include <AsteriskSCF/Discovery/SmartProxy.h>
#include "RtpStateReplicationIf.h"
#include "RTPSession.h"
#include "RtpStateReplicator.h"
+#include "PJMediaEnvironment.h"
+
using namespace std;
using namespace AsteriskSCF::Core::Discovery::V1;
using namespace AsteriskSCF::Media::V1;
using namespace AsteriskSCF::Media::RTP::V1;
using namespace AsteriskSCF::System::Component::V1;
using namespace AsteriskSCF::System::Logging;
-using namespace AsteriskSCF::SmartProxy;
+using namespace AsteriskSCF::Discovery;
+using namespace AsteriskSCF::PJMediaRTP;
namespace
{
@@ -60,24 +63,16 @@ class RTPMediaServiceImpl : public RTPMediaService
{
public:
RTPMediaServiceImpl(const Ice::ObjectAdapterPtr&, const ReplicaPtr&,
- const AsteriskSCF::SmartProxy::SmartProxy<RtpStateReplicatorPrx>&);
+ const AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx>&);
RTPSessionPrx allocate(const FormatSeq&, const Ice::Current&);
- pj_pool_factory *getPoolFactory() { return &mCachingPool.factory; };
+ pj_pool_factory *getPoolFactory() { return mEnvironment->poolFactory(); };
private:
/**
* A pointer to the object adapter that objects should be added to.
*/
Ice::ObjectAdapterPtr mAdapter;
- /**
- * Memory caching pool.
- */
- pj_caching_pool mCachingPool;
-
- /**
- * Memory pool.
- */
- pj_pool_t* mMemoryPool;
+ PJMediaEnvironmentPtr mEnvironment;
/**
* A pointer to the replica service.
@@ -87,7 +82,7 @@ private:
/**
* A proxy to the state replicator.
*/
- AsteriskSCF::SmartProxy::SmartProxy<RtpStateReplicatorPrx> mStateReplicator;
+ AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx> mStateReplicator;
};
/**
@@ -214,7 +209,7 @@ private:
/**
* A proxy to the state replicator.
*/
- AsteriskSCF::SmartProxy::SmartProxy<RtpStateReplicatorPrx> mStateReplicator;
+ AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx> mStateReplicator;
/**
* An instance of the general state information class.
@@ -328,14 +323,11 @@ private:
* Constructor for the RTPMediaServiceImpl class.
*/
RTPMediaServiceImpl::RTPMediaServiceImpl(const Ice::ObjectAdapterPtr& adapter, const ReplicaPtr& replicaService,
- const AsteriskSCF::SmartProxy::SmartProxy<RtpStateReplicatorPrx>& stateReplicator) :
- mAdapter(adapter), mReplicaService(replicaService), mStateReplicator(stateReplicator)
+ const AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx>& stateReplicator) :
+ mAdapter(adapter), mEnvironment(PJMediaEnvironment::create(adapter->getCommunicator()->getProperties(), "")),
+ mReplicaService(replicaService), mStateReplicator(stateReplicator)
+
{
- /* Initialize the memory caching pool using default policy as specified by pjlib. */
- pj_caching_pool_init(&mCachingPool, &pj_pool_factory_default_policy, 0);
-
- /* Initialize the memory pool that pjmedia will draw from. */
- mMemoryPool = pj_pool_create(&mCachingPool.factory, "media_rtp_pjmedia", 1024, 1024, 0);
}
/**
@@ -344,7 +336,7 @@ RTPMediaServiceImpl::RTPMediaServiceImpl(const Ice::ObjectAdapterPtr& adapter, c
RTPSessionPrx RTPMediaServiceImpl::allocate(const FormatSeq& formats, const Ice::Current&)
{
RTPSessionImplPtr session =
- new RTPSessionImpl(mAdapter, formats, &mCachingPool.factory, mReplicaService, mStateReplicator);
+ new RTPSessionImpl(mAdapter, formats, mEnvironment->poolFactory(), mReplicaService, mStateReplicator);
return session->getProxy();
}
@@ -410,7 +402,7 @@ void MediaRTPpjmediaApp::start(const std::string&, const Ice::CommunicatorPtr& c
try
{
- AsteriskSCF::SmartProxy::SmartProxy<RtpStateReplicatorPrx> pw(locator, replicatorParams, lg);
+ AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx> pw(locator, replicatorParams, lg);
mStateReplicator = pw;
}
catch (...)
diff --git a/src/NATConfig.cpp b/src/NATConfig.cpp
new file mode 100644
index 0000000..750118a
--- /dev/null
+++ b/src/NATConfig.cpp
@@ -0,0 +1,102 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, 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 "NATConfig.h"
+
+#include <Ice/Properties.h>
+#include <AsteriskSCF/System/ExceptionsIf.h>
+#include <pjnath.h>
+#include <AsteriskSCF/logger.h>
+
+using namespace std;
+using namespace AsteriskSCF::Helpers;
+using namespace AsteriskSCF::System::V1;
+using namespace AsteriskSCF::PJMediaRTP;
+using namespace AsteriskSCF::System::Logging;
+
+namespace
+{
+Logger logger = getLoggerFactory().getLogger("AsteriskSCF.MediaRTP");
+}
+
+NATConfigPtr AsteriskSCF::PJMediaRTP::NATConfig::create(const Ice::PropertiesPtr& props,
+ const string& propertyPrefix)
+{
+ string prefix(propertyPrefix);
+ if (!prefix.empty() && prefix.back() != '.')
+ {
+ prefix += '.';
+ }
+
+ string hostname = props->getProperty(prefix + "Media.STUN.Server");
+ //
+ // XXX:
+ // This actually isn't necessarily an error, the STUN server can be determined from
+ // DNS records. Let's leave it for now.
+ //
+ //
+ if (hostname.empty())
+ {
+ throw InternalInitializationException("No STUN server configured");
+ }
+
+ bool hasSTUN = true;
+ Ice::Int portProperty = props->getPropertyAsIntWithDefault(prefix + "Media.STUN.Port", PJ_STUN_PORT);
+ if (portProperty > UINT_MAX)
+ {
+ logger(Warning) << "Property `Media.STUN.Port' is out of range for IP port numbers, defaulting to "
+ << PJ_STUN_PORT;
+ portProperty = PJ_STUN_PORT;
+ }
+
+ AddressSeq candidates(DNSQuery::create(hostname, portProperty)->execute());
+ if (candidates.empty())
+ {
+ throw InternalInitializationException("Unable to resolve configured STUN server");
+ }
+ AddressPtr stunAddress = candidates.front();
+
+ //
+ // We read the properties even if TURN isn't enabled since we might make this runtime
+ // switchable at some point and there is no harm in avoiding extra obstacles.
+ //
+ hostname = props->getProperty(prefix + "Media.TURN.Server.Hostname");
+ bool hasTURN = false;
+ AddressPtr turnAddress;
+ if (!hostname.empty())
+ {
+ portProperty = props->getPropertyAsIntWithDefault(prefix + "Media.TURN.Server.Port", 3479);
+ candidates = DNSQuery::create(hostname, portProperty)->execute();
+ if (!candidates.empty())
+ {
+ if (props->getPropertyAsIntWithDefault(prefix + "Media.TURN.Enable", 0) > 0)
+ {
+ hasTURN = true;
+ }
+ turnAddress = candidates.front();
+ }
+ }
+ return NATConfigPtr(new NATConfig(stunAddress, turnAddress, hasSTUN, hasTURN));
+}
+
+NATConfig::NATConfig(const AddressPtr& stunServer, const AddressPtr& turnServer,
+ bool enableSTUN, bool enableTURN) :
+ mSTUNServer(stunServer),
+ mTURNServer(turnServer),
+ mSTUNEnabled(enableSTUN),
+ mTURNEnabled(enableTURN)
+{
+}
diff --git a/src/NATConfig.h b/src/NATConfig.h
new file mode 100644
index 0000000..df86342
--- /dev/null
+++ b/src/NATConfig.h
@@ -0,0 +1,75 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, 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.
+ */
+
+#pragma once
+
+#include <AsteriskSCF/Helpers/Network.h>
+#include <Ice/PropertiesF.h>
+#include <boost/shared_ptr.hpp>
+#include <string>
+
+namespace AsteriskSCF
+{
+namespace PJMediaRTP
+{
+
+class NATConfig;
+typedef boost::shared_ptr<NATConfig> NATConfigPtr;
+
+class NATConfig
+{
+public:
+
+ AsteriskSCF::Helpers::AddressPtr stunServer() const
+ {
+ return mSTUNServer;
+ }
+
+ bool isSTUNEnabled() const
+ {
+ return mSTUNEnabled;
+ }
+
+ AsteriskSCF::Helpers::AddressPtr turnServer() const
+ {
+ return mTURNServer;
+ }
+
+ bool isTURNEnabled() const
+ {
+ return mTURNEnabled;
+ }
+
+ static NATConfigPtr create(const Ice::PropertiesPtr& properties, const std::string& prefix);
+private:
+ AsteriskSCF::Helpers::AddressPtr mSTUNServer;
+ AsteriskSCF::Helpers::AddressPtr mTURNServer;
+ bool mSTUNEnabled;
+ bool mTURNEnabled;
+
+ NATConfig(const AsteriskSCF::Helpers::AddressPtr& stunServer,
+ const AsteriskSCF::Helpers::AddressPtr& turnServer,
+ bool stunEnabled,
+ bool turnEnabled);
+
+ //
+ // Hidden and unimplemented.
+ //
+ NATConfig(const NATConfig&);
+ void operator=(const NATConfig&);
+};
+} /* End of namespace PJMediaRTP */
+} /* End of namespace AsteriskSCF */
diff --git a/src/NATModule.cpp b/src/NATModule.cpp
new file mode 100644
index 0000000..d788709
--- /dev/null
+++ b/src/NATModule.cpp
@@ -0,0 +1,72 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, 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 "NATModule.h"
+#include <pjmedia.h>
+#include <pjnath.h>
+#include "PJUtil.h"
+#include <AsteriskSCF/System/ExceptionsIf.h>
+
+using namespace AsteriskSCF::PJMediaRTP;
+using namespace AsteriskSCF::System::V1;
+using namespace AsteriskSCF::PJUtil;
+
+NATModulePtr AsteriskSCF::PJMediaRTP::NATModule::create(const PJMediaEnvironmentPtr& environ)
+{
+ boost::shared_ptr<pj_ice_strans_cfg> transcfg(new pj_ice_strans_cfg);
+ pj_ice_strans_cfg_default(transcfg.get());
+ pj_stun_config_init(&transcfg->stun_cfg, environ->poolFactory(), 0,
+ pjmedia_endpt_get_ioqueue(environ->endpoint()), 0);
+ pj_status_t result = pj_timer_heap_create(environ->memoryPool(), environ->libConfig()->timerHeapSize(),
+ &transcfg->stun_cfg.timer_heap);
+ if (fail(result))
+ {
+ throw InternalInitializationException("Unable to initialize tier heap.");
+ }
+
+ pj_strdup2(environ->memoryPool(), &transcfg->stun.server, environ->natConfig()->stunServer()->hostname().c_str());
+ transcfg->stun.port = environ->natConfig()->stunServer()->port();
+ transcfg->stun.max_host_cands = environ->ICEConfig()->maxCandidates();
+ if (environ->natConfig()->isTURNEnabled())
+ {
+ pj_strdup2(environ->memoryPool(), &transcfg->turn.server, environ->natConfig()->turnServer()->hostname().c_str());
+ transcfg->turn.port = environ->natConfig()->turnServer()->port();
+ }
+
+ NATModulePtr moduleObj(new NATModule(transcfg));
+ moduleObj->startImpl();
+ return moduleObj;
+}
+
+NATModule::NATModule(const boost::shared_ptr<pj_ice_strans_cfg>& transConfig) :
+ mTransactionConfig(transConfig)
+{
+}
+
+NATModule::~NATModule()
+{
+ destroyImpl();
+}
+
+void NATModule::destroyImpl()
+{
+ pj_timer_heap_destroy(mTransactionConfig->stun_cfg.timer_heap);
+}
+
+void NATModule::startImpl()
+{
+}
+
diff --git a/src/NATModule.h b/src/NATModule.h
new file mode 100644
index 0000000..9b4c4bd
--- /dev/null
+++ b/src/NATModule.h
@@ -0,0 +1,57 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, 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.
+ */
+
+#pragma once
+
+#include "PJMediaEnvironment.h"
+#include <boost/shared_ptr.hpp>
+
+//
+// Forward declarations.
+//
+struct pj_ice_strans_cfg;
+
+namespace AsteriskSCF
+{
+namespace PJMediaRTP
+{
+class NATModule;
+typedef boost::shared_ptr<NATModule> NATModulePtr;
+
+class NATModule
+{
+public:
+ ~NATModule();
+
+ static NATModulePtr create(const PJMediaEnvironmentPtr& environ);
+
+private:
+ boost::shared_ptr<pj_ice_strans_cfg> mTransactionConfig;
+
+ NATModule(const boost::shared_ptr<pj_ice_strans_cfg>& transactionConfig);
+
+ void destroyImpl();
+ void startImpl();
+
+ //
+ // Hidden and unimplemented.
+ //
+ NATModule(const NATModule&);
+ void operator=(const NATModule&);
+};
+
+} /* End of namespace PJMediaRTP */
+} /* End of namespace AsteriskSCF */
diff --git a/src/PJLibConfiguration.cpp b/src/PJLibConfiguration.cpp
new file mode 100644
index 0000000..62018ff
--- /dev/null
+++ b/src/PJLibConfiguration.cpp
@@ -0,0 +1,38 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, 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 "PJLibConfiguration.h"
+#include <Ice/Properties.h>
+
+using namespace std;
+using namespace AsteriskSCF::PJMediaRTP;
+
+PJLibConfigurationPtr AsteriskSCF::PJMediaRTP::PJLibConfiguration::create(const Ice::PropertiesPtr& props,
+ const string& propertyPrefix)
+{
+ string prefix(propertyPrefix);
+ if (!prefix.empty() && prefix.back() != '.')
+ {
+ prefix += '.';
+ }
+ int timerHeapSize = props->getPropertyAsIntWithDefault(prefix + "TimerHeap.Size", 1000);
+ return PJLibConfigurationPtr(new PJLibConfiguration(timerHeapSize));
+}
+
+PJLibConfiguration::PJLibConfiguration(int timerHeapSize) :
+ mTimerHeapSize(timerHeapSize)
+{
+}
diff --git a/src/PJLibConfiguration.h b/src/PJLibConfiguration.h
new file mode 100644
index 0000000..d0cc641
--- /dev/null
+++ b/src/PJLibConfiguration.h
@@ -0,0 +1,64 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, 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.
+ */
+
+#pragma once
+
+#include <Ice/PropertiesF.h>
+#include <string>
+#include <boost/shared_ptr.hpp>
+
+namespace AsteriskSCF
+{
+namespace PJMediaRTP
+{
+
+/**
+ * PJLibConfiguration is fairly minimal at the moment, but may grow in the future. The intent is to reduce code
+ * duplication when dealing with pjproject related configuration. This is also an immutable object, so locking is not an
+ * issue.
+ **/
+class PJLibConfiguration
+{
+public:
+
+ int timerHeapSize() const
+ {
+ return mTimerHeapSize;
+ }
+
+ /**
+ * Create configuration instance from Ice properties. TODO: This could be extended by adding additional factory
+ * overrides.
+ **/
+ static boost::shared_ptr<PJLibConfiguration> create(const Ice::PropertiesPtr& props,
+ const std::string& propertyPrefix);
+
+private:
+ int mTimerHeapSize;
+
+ PJLibConfiguration(int timerHeapSize);
+
+ //
+ // Hidden, not implemented.
+ //
+ PJLibConfiguration(const PJLibConfiguration&);
+ void operator=(const PJLibConfiguration&);
+};
+
+typedef boost::shared_ptr<PJLibConfiguration> PJLibConfigurationPtr;
+
+} /* end of namespace PJMediaRTP */
+} /* End of namespace AsteriskSCF */
diff --git a/src/PJMediaEnvironment.cpp b/src/PJMediaEnvironment.cpp
new file mode 100644
index 0000000..12975d9
--- /dev/null
+++ b/src/PJMediaEnvironment.cpp
@@ -0,0 +1,58 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, 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 "PJMediaEnvironment.h"
+#include <ICE/Properties.h>
+#include <pjlib.h>
+#include <pjmedia.h>
+#include <pjnath.h>
+#include "PJUtil.h"
+#include <AsteriskSCF/System/ExceptionsIf.h>
+
+using namespace std;
+using namespace AsteriskSCF::PJMediaRTP;
+using namespace AsteriskSCF::System::V1;
+using namespace AsteriskSCF::PJUtil;
+
+PJMediaEnvironmentPtr AsteriskSCF::PJMediaRTP::PJMediaEnvironment::create(const Ice::PropertiesPtr& props, const string& propertyPrefix)
+{
+ return PJMediaEnvironmentPtr(
+ new PJMediaEnvironment(PJLibConfiguration::create(props, propertyPrefix),
+ ICEConfiguration::create(props, propertyPrefix),
+ NATConfig::create(props, propertyPrefix)));
+}
+
+PJMediaEnvironment::PJMediaEnvironment(const PJLibConfigurationPtr& libConfig,
+ const ICEConfigurationPtr& iceConfig,
+ const NATConfigPtr& natConfig) :
+ mPJLibConfig(libConfig),
+ mICEConfig(iceConfig),
+ mNATConfig(natConfig),
+ mCachingPool(new pj_caching_pool)
+{
+ pj_caching_pool_init(mCachingPool.get(), & pj_pool_factory_default_policy, 0);
+ mPoolFactory = &(mCachingPool->factory);
+
+ //
+ // TODO: should these values come from configuration.
+ //
+ mMemoryPool = pj_pool_create(mPoolFactory, "media_rtp_pjmedia", 1024, 1024, 0);
+ pj_status_t result = pjmedia_endpt_create(mPoolFactory, 0, 1, &mEndpoint);
+ if (fail(result))
+ {
+ throw InternalInitializationException("Unable to create PJMEDIA endpoint.");
+ }
+}
diff --git a/src/PJMediaEnvironment.h b/src/PJMediaEnvironment.h
new file mode 100644
index 0000000..d1dc494
--- /dev/null
+++ b/src/PJMediaEnvironment.h
@@ -0,0 +1,96 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, 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.
+ */
+
+#pragma once
+
+#include "PJLibConfiguration.h"
+#include "NATConfig.h"
+#include "ICEConfiguration.h"
+
+#include <Ice/PropertiesF.h>
+#include <string>
+#include <boost/shared_ptr.hpp>
+
+//
+// Forward declarations.
+//
+struct pj_pool_factory;
+struct pjmedia_endpt;
+struct pj_pool_t;
+struct pj_caching_pool;
+
+namespace AsteriskSCF
+{
+namespace PJMediaRTP
+{
+
+class PJMediaEnvironment;
+typedef boost::shared_ptr<PJMediaEnvironment> PJMediaEnvironmentPtr;
+
+class PJMediaEnvironment
+{
+public:
+
+ PJLibConfigurationPtr libConfig() const
+ {
+ return mPJLibConfig;
+ }
+
+ NATConfigPtr natConfig() const
+ {
+ return mNATConfig;
+ }
+
+ ICEConfigurationPtr ICEConfig() const
+ {
+ return mICEConfig;
+ }
+
+ pj_pool_factory* poolFactory() const
+ {
+ return mPoolFactory;
+ }
+
+ pjmedia_endpt* endpoint() const
+ {
+ return mEndpoint;
+ }
+
+ pj_pool_t* memoryPool() const
+ {
+ return mMemoryPool;
+ }
+
+ static PJMediaEnvironmentPtr create(const Ice::PropertiesPtr& props, const std::string& prefix);
+
+private:
+
+ PJLibConfigurationPtr mPJLibConfig;
+ ICEConfigurationPtr mICEConfig;
+ NATConfigPtr mNATConfig;
+
+ pj_pool_factory* mPoolFactory;
+ pjmedia_endpt* mEndpoint;
+ pj_pool_t* mMemoryPool;
+ boost::shared_ptr<pj_caching_pool> mCachingPool;
+
+ PJMediaEnvironment(const PJLibConfigurationPtr& libConfig,
+ const ICEConfigurationPtr& iceConfig,
+ const NATConfigPtr& natconfig);
+};
+
+} /* End of namespace PJMediaRTP */
+} /* End of namespace AsteriskSCF */
diff --git a/src/PJUtil.h b/src/PJUtil.h
new file mode 100644
index 0000000..e2383ec
--- /dev/null
+++ b/src/PJUtil.h
@@ -0,0 +1,40 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, 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.
+ */
+
+#pragma once
+
+#include <pjlib.h>
+
+namespace AsteriskSCF
+{
+namespace PJUtil
+{
+
+/**
+ * Simple result checking functions overloaded on pj_status_t result type.
+ **/
+inline bool success(pj_status_t r)
+{
+ return r == PJ_SUCCESS;
+}
+
+inline bool fail(pj_status_t r)
+{
+ return !success(r);
+}
+
+} /* End of namespace PJUtil */
+} /* End of namespace AsteriskSCF */
diff --git a/src/RTPICESession.cpp b/src/RTPICESession.cpp
index e141a8f..fc3035b 100644
--- a/src/RTPICESession.cpp
+++ b/src/RTPICESession.cpp
@@ -15,330 +15,46 @@
*/
#include "RTPICESession.h"
-
-#include <pjlib.h>
-#include <Ice/Ice.h>
-#include <IceUtil/UUID.h>
-
-#include <pjmedia.h>
-#include <pjnath.h>
-
-#include <AsteriskSCF/System/ExceptionsIf.h>
+#include "PJUtil.h"
#include "RtpStateReplicationIf.h"
#include "RTPSource.h"
#include "RTPSink.h"
-
#include "ServiceConfig.h"
+#include "NATConfig.h"
-#include <boost/bind.hpp>
+#include <pjlib.h>
+#include <pjmedia.h>
+#include <pjnath.h>
+#include <Ice/Ice.h>
+#include <IceUtil/UUID.h>
+#include <AsteriskSCF/System/ExceptionsIf.h>
+#include <AsteriskSCF/logger.h>
#include <AsteriskSCF/Helpers/Network.h>
using namespace std;
using namespace AsteriskSCF::System::V1;
using namespace AsteriskSCF::Media::V1;
using namespace AsteriskSCF::Media::RTP::V1;
-using namespace AsteriskSCF::RTPMedia;
using namespace AsteriskSCF::Helpers;
using namespace AsteriskSCF::PJMediaRTP;
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::PJUtil;
-//
-// Ideally this would be an anonymous namespace, but some compilers seem to have an issue with them
-//
-namespace ICEMediaSession
-{
-//
-// TODO: Move into header file.
-//
-static bool success(pj_status_t r)
-{
- return r == PJ_SUCCESS;
-}
-
-static bool fail(pj_status_t r)
+namespace
{
- return !success(r);
+Logger logger = getLoggerFactory().getLogger("AsteriskSCF.MediaRTP");
}
-typedef AsteriskSCF::SmartProxy::SmartProxy<RtpStateReplicatorPrx> StateReplicatorPrx;
-
//
-// NOTE: This is a bit of a placeholder for a configuration abstraction. It makes a bit more sense
-// than inlining with initialization logic since config might come from anywhere.
-//
-class NATConfig: public IceUtil::Shared
-{
-public:
- NATConfig(const Ice::PropertiesPtr& props) :
- mHasSTUNSettings(false),
- mHasTURNSettings(false)
- {
- string hostname = props->getProperty("Media.STUN.Server");
- //
- // XXX:
- // This actually isn't necessarily an error, the STUN server can be determined from
- // DNS records. Let's leave it for now.
- //
- //
- if (hostname.empty())
- {
- throw InternalInitializationException("No STUN server configured");
- }
-
- mHasSTUNSettings = true;
- Ice::Int portProperty = props->getPropertyAsIntWithDefault("Media.STUN.Port", PJ_STUN_PORT);
- if (portProperty > UINT_MAX)
- {
- logger(Warning) << "Property `Media.STUN.Port' is out of range for IP port numbers, defaulting to "
- << PJ_STUN_PORT;
- portProperty = PJ_STUN_PORT;
- }
-
- AddressSeq candidates(DNSQuery::create(hostname, portProperty)->execute());
- if (candidates.empty())
- {
- throw InternalInitializationException("Unable to resolve configured STUN server");
- }
- mSTUNAddress = candidates.front();
-
- //
- // We read the properties even if TURN isn't enabled since we might make this runtime
- // switchable at some point and there is no harm in avoiding extra obstacles.
- //
- hostname = props->getProperty("Media.TURN.Server.Hostname");
- if (!hostname.empty())
- {
- portProperty = props->getPropertyAsIntWithDefault("Media.TURN.Server.Port", 3479);
- candidates = DNSQuery::create(hostname, portProperty)->execute();
- if (!candidates.empty())
- {
- if (props->getPropertyAsIntWithDefault("Media.TURN.Enable", 0) > 0)
- {
- mHasTURNSettings = true;
- }
- mTURNAddress = candidates.front();
- }
- }
- }
-
- AddressPtr stunServer()
- {
- return mSTUNAddress;
- }
-
- bool hasSTUN() const
- {
- //
- // This will always return true at the moment because we throw an exception in the constructor
- // if we don't have the settings. However, if that exception is removed for some reason, this
- // should return the actual value.
- //
- return mHasSTUNSettings;
- }
-
- AddressPtr turnServer()
- {
- return mTURNAddress;
- }
-
- bool hasTURN() const
- {
- return mHasTURNSettings;
- }
-
-private:
- AddressPtr mSTUNAddress;
- AddressPtr mTURNAddress;
- bool mHasSTUNSettings;
- bool mHasTURNSettings;
-};
-typedef IceUtil::Handle<NATConfig> NATConfigPtr;
-
-class PjLibConfiguration : public IceUtil::Shared
-{
-public:
- //
- // prefix makes a local copy on purpose!
- //
- PjLibConfiguration(const Ice::PropertiesPtr& p, std::string prefix)
- {
- if (!prefix.empty() && prefix.back() != '.')
- {
- prefix += '.';
- }
- mTimerHeapSize = p->getPropertyAsIntWithDefault(prefix + "TimerHeap.Size", 1000);
- }
-
- int timerHeapSize() const
- {
- return mTimerHeapSize;
- }
-
-private:
-
- Ice::Int mTimerHeapSize;
-};
-typedef IceUtil::Handle<PjLibConfiguration> PjLibConfigurationPtr;
-
-class ICEConfiguration : public PjLibConfiguration
-{
-public:
- ICEConfiguration(const Ice::PropertiesPtr& p, std::string prefix) :
- PjLibConfiguration(p, prefix)
- {
- if (!prefix.empty() && prefix.back() != '.')
- {
- prefix += '.';
- }
- mMaxCandidates = p->getPropertyAsIntWithDefault(prefix + "ICE.MaxCandidates", 2);
- }
-
- int maxCandidates() const
- {
- return mMaxCandidates;
- }
-
- int maxCalls() const
- {
- return mMaxCalls;
- }
-
-private:
- Ice::Int mMaxCandidates;
- Ice::Int mMaxCalls;
-};
-
-typedef IceUtil::Handle<ICEConfiguration> ICEConfigurationPtr;
-
+// Ideally this would be an anonymous namespace, but some compilers seem to have an issue with them
//
-// The NATModule takes care of some initialization and configuration details.
-//
-class NATModule : public IceUtil::Shared
+namespace ICEMediaSession
{
-public:
- NATModule(const PjlibEnvironmentPtr& environ, const Ice::PropertiesPtr& props, const Logger& logger) :
- mConfig(new NATConfig(props)),
- mICEConfig(new ICEConfiguration(props, "Media.PJMedia."))
- {
- pj_ice_strans_cfg_default(&mPjICECfg);
- pj_stun_config_init(&mPjICECfg.stun_cfg, environ->getPoolFactory(), 0
- pjmedia_endpoint_get_ioqueue(environ->getMediaEndpoint()), 0);
- pj_status_t result = pj_timer_heap_create(environ->getPool(), mPjICEConfig->timerHeapSize(),
- &mPjICECfg.stun_cfg.timer_heap);
- if (fail(result))
- {
- throw InternalInitializationException("Unable to initialize timer heap.");
- }
- pj_strdup2(environ->getPool(), mPjICECfg.stun.server, mConfig->stunServer()->hostname().c_str());
- mPjICECfg.stun.port = mConfig->stunServer()->port();
-
- mPjICECfg.stun.max_host_cands = mICEConfig->maxCandidates();
- if (mConfig->hasTURN())
- {
- pj_strdup2(environ->getPool(), mICE.turn.server, mConfig->turnServer()->hostname().c_str());
- mICE.turn.server.port = mConfig->turnServer()->port();
-
- //
- // TODO: TURN QoS settings.
- //
- }
- //
- // TODO: QoS.
- //
- }
- void start()
- {
- //
- // commence resolving STUN server, etc.
- //
- }
-
-protected:
- ~NATModule()
- {
- pj_time_heap_destroy(&mPjICECfg.timer_heap);
- }
-
-private:
- NATConfigPtr mNATConfig;
- ICEConfigPtr mICEConfig;
- pj_ice_strans_cfg mPjICECfg;
- size_t mMaxCalls;
-};
-
-typedef IceUtil::Handle<NATModule> NATModulePtr;
-
-class PjLibEnvironment : public IceUtil::Shared
-{
-public:
- PjLibEnvironment(pj_pool_factory* poolFactory, const Ice::PropertiesPtr& props, const Logger& logger) :
- mPoolFactory(poolFactory),
- mProperties(props),
- mMediaEndpoint(0),
- mPool(0),
- mLogger(logger)
- {
- pj_status_t result = pjmedia_endpt_create(mPjLib->getPoolFactory(), 0, 1, &mEndpoint);
- if (fail(result))
- {
- throw InternalInitializationException("Unable to create PJMEDIA endpoint.");
- }
- }
-
- pj_pool_factory* getPoolFactory() const
- {
- boost::shared_lock<boost::shared_mutex> lock(mLock);
- return mPoolFactory;
- }
-
- pjmedia_endpoint* getMediaEndpoint() const
- {
- boost::shared_lock<boost::shared_mutex> lock(mLock);
- return mMediaEndpoint;
- }
-
- pj_pool_t* getPool() const
- {
- boost::unique_lock<boost::shared_mutex> lock(mLock);
- if (!mPool)
- {
- pj_status_t result = pjmedia_endpt_create_pool(mMediaEndpoint, "SESSPOOL", 1024, 512);
- if (fail(result))
- {
- throw InternalInitializationException("Unable to initialize pool.");
- }
- }
- return mPool;
- }
-
- NATModulePtr getNATModule()
- {
- boost::unique_lock<boost::shared_mutex> lock(mLock);
- if (!mNATModule)
- {
- mNATModule = new NATModule(this, mProperties, mLogger);
- }
- }
-
- void destroy()
- {
- boost::unique_lock<boost::shared_mutex> lock(mLock);
- mNATModule = 0;
- }
-
-private:
- mutable boost::shared_mutex mLock;
- pj_pool_factory* mPoolFactory;
- Ice::PropertiesPtr mProperties;
- pjmedia_endpoint* mMediaEndpoint;
- NATModulePtr mNATModule;
- pj_pool_t* mPool;
- Logger mLogger;
-};
-typedef IceUtil::Handle<PjLibEnvironment> PjLibEnvironmentPtr;
+typedef AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx> StateReplicatorPrx;
class RTPSessionImpl : public RTPSession
{
@@ -349,8 +65,8 @@ public:
// amongst constructor versions and avoid exception prone calls in
// the constructor itself.
//
- RTPSessionImpl(const FormatSeq& formats, const PjLibEnvironmentPtr& pjLib,
- const ReplicatorPtr& replicaService, const StateReplicatorPrx& replicator);
+ RTPSessionImpl(const FormatSeq& formats, const PJMediaEnvironmentPtr& pjLib,
+ const StateReplicatorPrx& replicator);
void initialize();
@@ -370,32 +86,44 @@ public:
//
// RTPSession.
//
- void associatePayLoads(const PayLoadMap& mappings, const Ice::Current& current);
+ void associatePayloads(const AsteriskSCF::Media::RTP::V1::PayloadMap& mappings, const Ice::Current& current);
void useRTCP(bool enable, const Ice::Current& current);
RTCPSessionPrx getRTCPSession(const Ice::Current& current);
void release(const Ice::Current& current);
+ void onComplete(pj_ice_strans_op operationStatus, pj_status_t status);
+
//
// Internal methods.
//
private:
boost::shared_mutex mLock;
FormatSeq mFormats;
- PjLibEnvironmentPtr mPjLib;
- ReplicatorPtr mReplicaControl;
+ PJMediaEnvironmentPtr mMediaEnvironment;
StateReplicatorPrx mReplicator;
-
- //
- // TODO: Should the endpoint belong to a different object. Could a single endpoint
- // have multiple transports?
- //
- pjmedia_endpt* mEndpoint;
- pjmedia_transport* mTransport;
-
};
typedef IceUtil::Handle<RTPSessionImpl> RTPSessionImplPtr;
+class ICECallbackAdapter
+{
+
+public:
+ static void addEntry(pjmedia_transport* transport, const RTPSessionImplPtr& callback);
+ static void onICEComplete(pjmedia_transport* transport, pj_ice_strans_op operation, pj_status_t status);
+
+ struct CallbackRecord
+ {
+ bool connected;
+ RTPSessionImplPtr session;
+ };
+ typedef std::map<pjmedia_transport*, CallbackRecord> TransportMap;
+private:
+
+ static TransportMap mTransportMap;
+ static boost::shared_mutex mLock;
+};
+
class SinkImpl : public StreamSinkRTP
{
public:
@@ -452,46 +180,35 @@ public:
void destroy();
};
-/**
- *
- * Base class to allow some polymorphic behavior on different pjmedia based transports.
- *
- **/
-class PJMediaTransport : public IceUtil::Shared
+class PJMediaTransport
{
public:
-
- pjmedia_transport* getTransport()
- {
- boost::shared_lock<boost::shared_mutex> lock(mLock);
- return mTransport;
- }
+ virtual ~PJMediaTransport() {}
- Ice::Int getPort()
+ pjmedia_transport* getTransport() const
{
- boost::shared_lock<boost::shared_mutex> lock(mLock);
- return mPort;
-
- void destroy()
- {
- boost::unique_locK<boost::shared_mutex> lock(mLock);
- pjmedia_transport_close(mTransport);
- mPort = 0;
- mTransport = 0;
+ return mTransport;
}
protected:
- boost::shared_mutex mLock;
+
pjmedia_transport* mTransport;
- Ice::Int mPort;
- PJMediaTransport(pjmedia_transport* t, const Ice::Int p) :
- mTransport(t),
- mPort(p)
+ PJMediaTransport(pjmedia_transport* t) :
+ mTransport(t)
{
}
};
+typedef boost::shared_ptr<PJMediaTransport> PJMediaTransportPtr;
+
+//
+// ICE transport implementation.
+//
+class ICETransport;
+typedef boost::shared_ptr<ICETransport> ICETransportPtr;
+typedef boost::shared_ptr<pjmedia_ice_cb> PJICECallbackPtr;
+
class ICETransport : public PJMediaTransport
{
//
@@ -501,13 +218,34 @@ class ICETransport : public PJMediaTransport
void operator=(const ICETransport&);
public:
- static IceUtil::Handle<ICETransport> create(const PjLibEnvironmentPtr& pjlib)
+ static ICETransportPtr create(const PJMediaEnvironmentPtr& environment)
{
- pjmedia_ice_create(mPjLib->getMediaEndpoint(), "ASCF_ICE_MEDIA", 10, 0, &ICECallbackAdapter::onIceComplete,
- &mTransport);
+ pjmedia_transport* t;
+ PJICECallbackPtr callback(new pjmedia_ice_cb);
+ callback->on_ice_complete = &ICECallbackAdapter::onICEComplete;
+ pj_status_t result = pjmedia_ice_create(environment->endpoint(), "ASCF_ICE_MEDIA", 10, 0, callback.get(),
+ &t);
+ if (fail(result))
+ {
+ throw InternalInitializationException("Unable to create new ICE media transport");
+ }
}
+
+ ICETransport(pjmedia_transport* t, const PJICECallbackPtr& cb) :
+ PJMediaTransport(t),
+ mCallback(cb)
+ {
+ }
+
+private:
+ PJICECallbackPtr mCallback;
};
-typedef IceUtil::Handle<ICETransport> ICETransportPtr;
+
+//
+// UDP transport implementation.
+//
+class UDPTransport;
+typedef boost::shared_ptr<UDPTransport> UDPTransportPtr;
class UDPTransport : public PJMediaTransport
{
@@ -521,22 +259,22 @@ public:
//
// Replicant version.
//
- static IceUtil::Handle<UDPTransport> create(const PjLibEnvironmentPtr& pjlib, Ice::Int port)
+ static UDPTransportPtr create(const PJMediaEnvironmentPtr& environment, Ice::Int port)
{
pjmedia_transport* transport;
- pj_status_t result = pjmedia_transport_udp_create2(pjlib->getMediaEndpoint(), "RTP", 0, port, transport);
+ pj_status_t result = pjmedia_transport_udp_create2(environment->endpoint(), "RTP", 0, port, 0, &transport);
if (fail(result))
{
throw InternalInitializationException("Unable to initialize UDP media transport on "
"replicant, port conflict!");
}
- return new UDPTransport(transport, port);
+ return UDPTransportPtr(new UDPTransport(transport));
}
//
// Primary version.
//
- static IceUtil::Handle<UDPTransport> create(const PjLibEnvironmentPtr& pjlib, Ice::Int port)
+ static UDPTransportPtr create(const PJMediaEnvironmentPtr& pjlib, const Ice::PropertiesPtr& properties)
{
const Ice::Int minPort =
properties->getPropertyAsIntWithDefault("AsteriskSCF.Media.Transport.UDPTransport.MinPort",
@@ -552,28 +290,22 @@ public:
for (Ice::Int port = minPort; port < maxPort && port <= USHRT_MAX ; port +=2)
{
pjmedia_transport* transport;
- pj_result_t result = pjmedia_transport_udp_create2(pjlib->getMediaEndpoint(), "RTP", 0, port, 0, &transport);
+ pj_status_t result = pjmedia_transport_udp_create2(pjlib->endpoint(), "RTP", 0, port, 0, &transport);
if (success(result))
{
- return new UDPTransport(transport, port);
+ return UDPTransportPtr(new UDPTransport(transport));
}
}
throw InternalInitializationException("Unable to initialize UDP media transport");
}
private:
- UDPTransport(pjmedia_transport* t, const Ice::Int port) :
- PJMediaTransport(t, port)
+ UDPTransport(pjmedia_transport* t) :
+ PJMediaTransport(t)
{
}
};
-typedef IceUtil::Handle<UDPTransport> UDPTransportPtr;
-pjmedia_transport* PJMediaTransport::getTransport()
-{
- boost::shared_lock<boost::shared_mutex> lock(mLock);
- return mTransport;
-}
//
// For some reason the ICE media transport doesn't have the concept of associating user data with a transport, so we
@@ -582,130 +314,138 @@ pjmedia_transport* PJMediaTransport::getTransport()
// the ICE completion callback arrives and there isn't a table entry. When the addEntry runs, it will see the entry and
// simply update the appropriate field.
//
-class ICECallbackAdapter
+void ICECallbackAdapter::addEntry(pjmedia_transport* transport, const RTPSessionImplPtr& callback)
{
-public:
- struct CallbackRecord
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+ TransportMap::iterator i = mTransportMap.find(transport);
+ if (i != mTransportMap.end())
{
- bool connected;
- RTPSessionImplPtr session;
- };
- typedef std::map<pjmedia_transport*, CallbackRecord> TransportMap;
-
- static void addEntry(pjmedia_transport* transport, const RTPSessionImplPtr& callback)
+ i->second.session = callback;
+ }
+ else
{
- boost::unique_lock<boost::shared_mutex> lock(mLock);
- TransportMap::iterator i = mTransportMap.find(transport);
- if (i != mTransportMap.end())
- {
- i->second.session = callback;
- }
- else
- {
- CallbackRecord r;
- r.connected = false;
- r.session = callback;
- mTransportMap.insert(make_pair(transport, r));
- }
-
+ CallbackRecord r;
+ r.connected = false;
+ r.session = callback;
+ mTransportMap.insert(make_pair(transport, r));
}
- static void onICEComplete(pjmedia_transport* transport, pj_ice_strans_op operation, pj_status_t status)
+}
+
+void ICECallbackAdapter::onICEComplete(pjmedia_transport* transport, pj_ice_strans_op operation, pj_status_t status)
+{
+ //
+ // AFAICT, only PJ_ICE_STRANS_OP_NEGOTIATION should get here.
+ //
+ switch (operation)
{
//
- // AFAICT, only PJ_ICE_STRANS_OP_NEGOTIATION should get here.
- //
- switch (operation)
- {
+ // TODO: Fill out.
+ //
+ case PJ_ICE_STRANS_OP_INIT:
//
- // TODO: Fill out.
+ // Initialization is complete. FWICT, this should not get here.
//
- case PJ_ICE_STRANS_OP_INIT:
- //
- // Initialization is complete. FWICT, this should not get here.
- //
- break;
- case PJ_ICE_STRANS_OP_NEGOTIATION:
- //
- // Negotiation is complete.
- //
+ break;
+ case PJ_ICE_STRANS_OP_NEGOTIATION:
+ //
+ // Negotiation is complete.
+ //
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+ TransportMap::iterator i = mTransportMap.find(transport);
+ if (i == mTransportMap.end())
{
- boost::unique_lock<boost::shared_mutex> lock(mLock);
- TransportMap::iterator i = mTransportMap.find(transport);
- if (i == mTransportMap.end())
- {
- CallbackRecord r;
- r.connected = true;
- mTransportMap.insert(make_pair(transport, r));
- }
- else
- {
- i->second.connected = true;
- i->second.session->onComplete(operation, status);
- }
+ CallbackRecord r;
+ r.connected = true;
+ mTransportMap.insert(make_pair(transport, r));
}
- break;
- case PJ_ICE_STRANS_OP_KEEP_ALIVE:
- //
- // Keep alive has successfully completed. FWICT this should not get here.
- //
- break;
- default:
- };
- }
-
-private:
+ else
+ {
+ i->second.connected = true;
+ i->second.session->onComplete(operation, status);
+ }
+ }
+ break;
+ case PJ_ICE_STRANS_OP_KEEP_ALIVE:
+ //
+ // Keep alive has successfully completed. FWICT this should not get here.
+ //
+ break;
+ };
+}
- static TransportMap mTransportMap;
- static boost::shared_mutex mLock;
-};
+}
//
// Static member initializations.
//
-IceCallbackAdapter::TransportMap IceCallbackAdapter::mTransportMap;
-boost::shared_mutex IceCallbackAdapter::mLock;
+ICEMediaSession::ICECallbackAdapter::TransportMap ICEMediaSession::ICECallbackAdapter::mTransportMap;
+boost::shared_mutex ICEMediaSession::ICECallbackAdapter::mLock;
-}
using namespace ICEMediaSession;
-RTPSessionImpl::RTPSessionImpl(const FormatSeq& formats, const PjLibEnvironmentPtr& pjLib,
- const ReplicatorPtr& replicaService, const StateReplicatorPrx& replicator) :
+ICEMediaSession::RTPSessionImpl::RTPSessionImpl(const FormatSeq& formats, const PJMediaEnvironmentPtr& environment,
+ const StateReplicatorPrx& replicator) :
mFormats(formats),
- mPjLib(pjLib),
- mReplicaControl(replicaService),
- mReplicator(replicator),
- mBasePort(0),
- mInitialized(false)
+ mMediaEnvironment(environment),
+ mReplicator(replicator)
{
}
-void RTPSessionImpl::initialize(const Ice::PropertiesPtr& properties)
+void ICEMediaSession::RTPSessionImpl::initialize()
{
- boost::unique_lock<boost::shared_mutex> lock(mLock);
- pjmedia_ice_create(mPjLib->getMediaEndpoint(), "ASCF_ICE_MEDIA", 10, 0, &ICECallbackAdapter::onIceComplete,
- &mTransport);
- mInitialized = true;
+
}
-void RTPSessionImpl::destroy()
+void ICEMediaSession::RTPSessionImpl::destroy()
+{
+}
+
+StreamSourceSeq ICEMediaSession::RTPSessionImpl::getSources(const Ice::Current&)
+{
+ return StreamSourceSeq();
+}
+
+StreamSinkSeq ICEMediaSession::RTPSessionImpl::getSinks(const Ice::Current&)
+{
+ return StreamSinkSeq();
+}
+
+std::string ICEMediaSession::RTPSessionImpl::getId(const Ice::Current&)
+{
+ return "";
+}
+
+void ICEMediaSession::RTPSessionImpl::associatePayloads(const AsteriskSCF::Media::RTP::V1::PayloadMap& mappings,
+ const Ice::Current&)
+{
+}
+
+void ICEMediaSession::RTPSessionImpl::useRTCP(bool enable, const Ice::Current&)
+{
+}
+
+RTCPSessionPrx ICEMediaSession::RTPSessionImpl::getRTCPSession(const Ice::Current&)
+{
+ return 0;
+}
+
+void ICEMediaSession::RTPSessionImpl::release(const Ice::Current&)
+{
+}
+
+void ICEMediaSession::RTPSessionImpl::onComplete(pj_ice_strans_op operationStatus, pj_status_t status)
{
- boost::unique_lock<boost::shared_mutex> lock(mLock);
- if (mInitialized)
- {
- pjmedia_transport_close(&mTransport);
- mInitialized = false;
- }
}
-RTPSessionPrx AsteriskSCF::RTPMedia::RTPICESession::create(const Ice::ObjectAdapterPtr& adapter,
+RTPSessionPrx AsteriskSCF::PJMediaRTP::RTPICESession::create(const Ice::ObjectAdapterPtr& adapter,
const Ice::Identity& id,
- const FormatSeq& formats, pj_pool_factory* factory, const ReplicatPtr& replicaService,
- const AsteriskSCF::SmartProxy::SmartProxy<RtpStateReplicatorPrx>& stateReplicator)
+ const FormatSeq& formats, const PJMediaEnvironmentPtr& environment,
+ const AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx>& stateReplicator)
{
- RTPSessionImplPtr servant(new RTPSessionImpl(formats, new PjLibEnvironment(factory), replicaService,
+ ICEMediaSession::RTPSessionImplPtr servant(new ICEMediaSession::RTPSessionImpl(formats, environment,
stateReplicator));
assert(adapter);
- servant->initialize(adapter->getCommunicator()->getProperties());
return RTPSessionPrx::uncheckedCast(adapter->add(servant, id));
}
diff --git a/src/RTPICESession.h b/src/RTPICESession.h
index 8fdb320..bf6e583 100644
--- a/src/RTPICESession.h
+++ b/src/RTPICESession.h
@@ -19,11 +19,18 @@
#include <AsteriskSCF/Media/MediaIf.h>
#include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
#include <AsteriskSCF/System/Component/ReplicaIf.h>
-#include <AsteriskSCF/SmartProxy/SmartProxy.h>
+#include <AsteriskSCF/Discovery/SmartProxy.h>
+#include "RtpStateReplicationIf.h"
+#include "PJMediaEnvironment.h"
+
+//
+// Forward declarations.
+//
+struct pj_pool_factory;
namespace AsteriskSCF
{
-namespace RTPMedia
+namespace PJMediaRTP
{
class RTPICESession
@@ -32,9 +39,8 @@ public:
static AsteriskSCF::Media::RTP::V1::RTPSessionPrx create(const Ice::ObjectAdapterPtr& objectAdapter,
const Ice::Identity& id,
const AsteriskSCF::Media::V1::FormatSeq& formats,
- pj_pool_factory* factory,
- const ReplicaPtr& replicaService,
- const AsteriskSCF::SmartProxy::SmartProxy<
+ const PJMediaEnvironmentPtr& environment,
+ const AsteriskSCF::Discovery::SmartProxy<
AsteriskSCF::Media::RTP::V1::RtpStateReplicatorPrx>& stateReplicator
);
};
diff --git a/src/RTPSession.cpp b/src/RTPSession.cpp
index b9e6eea..ec6a746 100644
--- a/src/RTPSession.cpp
+++ b/src/RTPSession.cpp
@@ -14,32 +14,26 @@
* at the top of the source tree.
*/
-#include <pjlib.h>
-#include <Ice/Ice.h>
-#include <IceUtil/UUID.h>
-
-#include <pjmedia.h>
-
-#include <AsteriskSCF/Media/MediaIf.h>
-#include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
-#include <AsteriskSCF/System/Component/ReplicaIf.h>
-#include <AsteriskSCF/System/ExceptionsIf.h>
-#include <AsteriskSCF/SmartProxy.h>
-
#include "RtpStateReplicationIf.h"
-
#include "RTPSession.h"
#include "RTPSource.h"
#include "RTPSink.h"
#include "ServiceConfig.h"
+#include <pjlib.h>
+#include <Ice/Ice.h>
+#include <IceUtil/UUID.h>
+#include <AsteriskSCF/System/ExceptionsIf.h>
+
+#include <pjmedia.h>
+
using namespace std;
using namespace AsteriskSCF::Core::Discovery::V1;
using namespace AsteriskSCF::Media::V1;
using namespace AsteriskSCF::Media::RTP::V1;
using namespace AsteriskSCF::System::Component::V1;
using namespace AsteriskSCF::System::V1;
-using namespace AsteriskSCF::SmartProxy;
+using namespace AsteriskSCF::Discovery;
/**
* Private implementation details for the RTPSessionImpl class.
@@ -49,7 +43,7 @@ class RTPSessionImplPriv
public:
RTPSessionImplPriv(const Ice::ObjectAdapterPtr& adapter, const FormatSeq& formats,
const ReplicaPtr& replicaService,
- const AsteriskSCF::SmartProxy::SmartProxy<RtpStateReplicatorPrx>& stateReplicator) :
+ const AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx>& stateReplicator) :
mAdapter(adapter), mFormats(formats),
mSessionStateItem(new RtpSessionStateItem()),
mReplicaService(replicaService), mStateReplicator(stateReplicator) { };
@@ -118,7 +112,7 @@ public:
/**
* A proxy to the state replicator where we are sending updates to.
*/
- AsteriskSCF::SmartProxy::SmartProxy<RtpStateReplicatorPrx> mStateReplicator;
+ AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx> mStateReplicator;
};
@@ -132,7 +126,7 @@ public:
*/
RTPSessionImpl::RTPSessionImpl(const Ice::ObjectAdapterPtr& adapter, const FormatSeq& formats,
pj_pool_factory* factory, const ReplicaPtr& replicaService,
- const AsteriskSCF::SmartProxy::SmartProxy<RtpStateReplicatorPrx>& stateReplicator) :
+ const AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx>& stateReplicator) :
mImpl(new RTPSessionImplPriv(adapter, formats, replicaService, stateReplicator))
{
/* Add ourselves to the ICE ASM so we can be used. */
@@ -156,7 +150,7 @@ RTPSessionImpl::RTPSessionImpl(const Ice::ObjectAdapterPtr& adapter, const Forma
//
// The candidate ports increment by two to allow "room" for both a control and a data port.
//
- for (int port = DefaultRTPPortMinimum; port < DefaultRTPPortMaximum; port += 2)
+ for (int port = AsteriskSCF::PJMediaRTP::DefaultRTPPortMinimum; port < AsteriskSCF::PJMediaRTP::DefaultRTPPortMaximum; port += 2)
{
if ((status = pjmedia_transport_udp_create2(mImpl->mEndpoint, "RTP", NULL, port, 0, &mImpl->mTransport)) ==
PJ_SUCCESS)
@@ -191,7 +185,9 @@ RTPSessionImpl::RTPSessionImpl(const Ice::ObjectAdapterPtr& adapter, const Forma
RTPSessionImpl::RTPSessionImpl(const Ice::ObjectAdapterPtr& adapter, pj_pool_factory* factory,
const Ice::Identity& sessionIdentity, const Ice::Identity& sinkIdentity, const Ice::Identity& sourceIdentity,
Ice::Int port, const FormatSeq& formats) :
- mImpl(new RTPSessionImplPriv(adapter, formats, 0, *(new AsteriskSCF::SmartProxy::SmartProxy<RtpStateReplicatorPrx>)))
+///
+// MEMORY LEAK XXX->>>
+ mImpl(new RTPSessionImplPriv(adapter, formats, 0, *(new AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx>)))
{
mImpl->mProxy = RTPSessionPrx::uncheckedCast(adapter->add(this, sessionIdentity));
@@ -392,7 +388,7 @@ int RTPSessionImpl::getPayload(const FormatPtr& mediaformat)
/**
* API call which returns a pointer to the source.
*/
-StreamSourceRTPImplPtr RTPSessionImpl::getSource()
+StreamSourceRTPPtr RTPSessionImpl::getSource()
{
return mImpl->mStreamSource;
}
diff --git a/src/RTPSession.h b/src/RTPSession.h
index a8e4b7a..30127f9 100644
--- a/src/RTPSession.h
+++ b/src/RTPSession.h
@@ -8,6 +8,13 @@
#pragma once
+#include <AsteriskSCF/System/Component/ComponentServiceIf.h>
+#include <AsteriskSCF/System/Component/ReplicaIf.h>
+#include <AsteriskSCF/Discovery/SmartProxy.h>
+#include <AsteriskSCF/Media/MediaIf.h>
+#include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
+#include "RtpStateReplicationIf.h"
+
#include <boost/shared_ptr.hpp>
/**
@@ -15,25 +22,12 @@
*/
class RTPSessionImplPriv;
-/**
- * Forward definition for our private implementation of StreamSinkRTP.
- */
-class StreamSinkRTPImpl;
-
-/**
- * A typedef which creates a smart pointer type for StreamSinkRTPImpl.
- */
-typedef IceUtil::Handle<StreamSinkRTPImpl> StreamSinkRTPImplPtr;
+//
+// Forward declarations.
+//
-/**
- * Forward definition for our private implementation of StreamSourceRTP.
- */
-class StreamSourceRTPImpl;
-
-/**
- * A typedef which creates a smart pointer type for StreamSourceRTPImpl.
- */
-typedef IceUtil::Handle<StreamSourceRTPImpl> StreamSourceRTPImplPtr;
+struct pjmedia_transport;
+struct pj_pool_factory;
/**
* Implementation of the RTPSession interface as defined in MediaRTPIf.ice
@@ -43,7 +37,7 @@ class RTPSessionImpl : public AsteriskSCF::Media::RTP::V1::RTPSession
public:
RTPSessionImpl(const Ice::ObjectAdapterPtr&, const AsteriskSCF::Media::V1::FormatSeq&,
pj_pool_factory*, const AsteriskSCF::System::Component::V1::ReplicaPtr&,
- const AsteriskSCF::SmartProxy::SmartProxy<AsteriskSCF::Media::RTP::V1::RtpStateReplicatorPrx>&);
+ const AsteriskSCF::Discovery::SmartProxy<AsteriskSCF::Media::RTP::V1::RtpStateReplicatorPrx>&);
RTPSessionImpl(const Ice::ObjectAdapterPtr&, pj_pool_factory*, const Ice::Identity&, const Ice::Identity&,
const Ice::Identity&, Ice::Int, const AsteriskSCF::Media::V1::FormatSeq&);
AsteriskSCF::Media::V1::StreamSourceSeq getSources(const Ice::Current&);
@@ -59,7 +53,7 @@ public:
void setRemoteDetails(const std::string& address, Ice::Int port);
AsteriskSCF::Media::V1::FormatPtr getFormat(int payload);
int getPayload(const AsteriskSCF::Media::V1::FormatPtr& mediaformat);
- StreamSourceRTPImplPtr getSource();
+ AsteriskSCF::Media::RTP::V1::StreamSourceRTPPtr getSource();
... 939 lines suppressed ...
--
asterisk-scf/integration/media_rtp_pjmedia.git
More information about the asterisk-scf-commits
mailing list