[asterisk-scf-commits] asterisk-scf/integration/media_transport_udptl.git branch "baserep" created.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Fri Dec 16 08:43:58 CST 2011


branch "baserep" has been created
        at  c906b0aeb75f07f9c15f17be1bd43eddd4a4df7d (commit)

- Log -----------------------------------------------------------------
commit c906b0aeb75f07f9c15f17be1bd43eddd4a4df7d
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Fri Dec 16 08:44:00 2011 -0600

    Renamed UdptlStateReplicatorApp.cpp, which also now uses base replicator class.

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9f196d1..e05320a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -52,7 +52,7 @@ pjproject_link(MediaTransportUDPTL pjnath)
 astscf_component_install(MediaTransportUDPTL)
 
 astscf_component_init(UdptlStateReplicator)
-astscf_component_add_files(UdptlStateReplicator UdptlStateReplicatorApp.cpp)
+astscf_component_add_files(UdptlStateReplicator ComponentStateReplicator.cpp)
 astscf_component_add_files(UdptlStateReplicator UdptlStateReplicator.h)
 astscf_component_add_slices(UdptlStateReplicator PROJECT AsteriskSCF/Replication/UDPTL/UdptlStateReplicationIf.ice)
 astscf_component_add_slices(UdptlStateReplicator PROJECT AsteriskSCF/Configuration/UDPTL/UdptlConfigurationIf.ice)
diff --git a/src/ComponentStateReplicator.cpp b/src/ComponentStateReplicator.cpp
new file mode 100644
index 0000000..1a521fc
--- /dev/null
+++ b/src/ComponentStateReplicator.cpp
@@ -0,0 +1,104 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include <Ice/Ice.h>
+
+#include <AsteriskSCF/Component/ComponentStateReplicator.h>
+#include <AsteriskSCF/logger.h>
+#include <AsteriskSCF/Media/UDPTL/MediaUDPTLIf.h>
+
+#include "UdptlConfigurationIf.h"
+#include "UdptlStateReplicator.h"
+
+using namespace std;
+using namespace AsteriskSCF::Core;
+using namespace AsteriskSCF::Discovery;
+using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::System::Component::V1;
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::Media::UDPTL::V1;
+using namespace AsteriskSCF::Replication::UDPTL::V1;
+using namespace AsteriskSCF::Configuration::UDPTL::V1;
+
+namespace
+{
+Logger lg = getLoggerFactory().getLogger("AsteriskSCF.MediaUDPTL");
+}
+
+class ComponentStateReplicator : public AsteriskSCF::Component::ComponentStateReplicator
+{
+public:
+    ComponentStateReplicator() :
+      AsteriskSCF::Component::ComponentStateReplicator(lg, 
+          AsteriskSCF::Replication::UDPTL::V1::StateReplicatorComponentCategory, 
+          true)  // if true, supports configuration
+    {
+    }
+
+    ~ComponentStateReplicator() {};
+
+    ///////////////////////////////////////////////////
+    // Required overrides
+
+    void createPrimaryServices();
+    void preparePrimaryServicesForDiscovery();
+
+private:
+    UdptlStateReplicatorIPtr mStateReplicator;
+    UdptlStateReplicatorPrx mStateReplicatorPrx;
+    LocatorRegistrationWrapperPtr mStateReplicatorRegistration;
+};
+
+static const string ServiceDiscoveryId("UdptlStateReplicatorService");
+
+/**
+ * Register this component's primary public interfaces with the Service Locator.
+ * This enables other Asterisk SCF components to locate our interfaces.
+ */
+void ComponentStateReplicator::preparePrimaryServicesForDiscovery()
+{
+    try
+    {
+        // Wrap our authentication extensions point for the Service Locator.
+        mStateReplicatorRegistration = wrapServiceForRegistration(mStateReplicatorPrx,
+                                                                  AsteriskSCF::Replication::UDPTL::V1::StateReplicatorDiscoveryCategory);
+        managePrimaryService(mStateReplicatorRegistration);
+    }
+    catch(const std::exception& e)
+    {
+        lg(Error) << "Unable to publish component interfaces in " << getName() << BOOST_CURRENT_FUNCTION <<
+            ". Exception: " << e.what();
+        throw; // rethrow
+    }
+}
+
+void ComponentStateReplicator::createPrimaryServices()
+{
+    // Create the state replicator servant
+    mStateReplicator = new UdptlStateReplicatorI();
+
+    mStateReplicatorPrx = UdptlStateReplicatorPrx::uncheckedCast(
+       getServiceAdapter()->add(mStateReplicator, getCommunicator()->stringToIdentity(ServiceDiscoveryId)));
+}
+
+extern "C"
+{
+ASTSCF_DLL_EXPORT IceBox::Service* create(Ice::CommunicatorPtr)
+{
+    return new ComponentStateReplicator;
+}
+}
+
diff --git a/src/UdptlStateReplicatorApp.cpp b/src/UdptlStateReplicatorApp.cpp
deleted file mode 100644
index a9b3c8a..0000000
--- a/src/UdptlStateReplicatorApp.cpp
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Asterisk SCF -- An open-source communications framework.
- *
- * Copyright (C) 2011, Digium, Inc.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk SCF project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE.txt file
- * at the top of the source tree.
- */
-
-#include <Ice/Ice.h>
-#include <IceUtil/UUID.h>
-#include <IceStorm/IceStorm.h>
-#include <IceBox/IceBox.h>
-
-#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
-#include <AsteriskSCF/System/Component/ComponentServiceIf.h>
-#include <AsteriskSCF/Logger/IceLogger.h>
-#include <AsteriskSCF/logger.h>
-#include <AsteriskSCF/CollocatedIceStorm/CollocatedIceStorm.h>
-#include <AsteriskSCF/System/Component/ConfigurationIf.h>
-#include <AsteriskSCF/Media/UDPTL/MediaUDPTLIf.h>
-
-#include "UdptlConfigurationIf.h"
-#include "UdptlStateReplicator.h"
-
-using namespace std;
-using namespace AsteriskSCF::Core;
-using namespace AsteriskSCF::Core::Discovery::V1;
-using namespace AsteriskSCF::System::Component::V1;
-using namespace AsteriskSCF::System::Logging;
-using namespace AsteriskSCF::Media::UDPTL::V1;
-using namespace AsteriskSCF::Replication::UDPTL::V1;
-using namespace AsteriskSCF::Configuration::UDPTL::V1;
-using namespace AsteriskSCF::CollocatedIceStorm;
-using namespace AsteriskSCF::System::Configuration::V1;
-
-namespace
-{
-Logger lg = getLoggerFactory().getLogger("AsteriskSCF.MediaUDPTL");
-}
-
-class UdptlStateReplicatorService : public IceBox::Service
-{
-public:
-    UdptlStateReplicatorService() { };
-    ~UdptlStateReplicatorService()
-    {
-        mComponentService = 0;
-        mAdapter = 0;
-        mStateReplicator = 0;
-    mConfigurationReplicator = 0;
-    };
-    virtual void start(const string &name, const Ice::CommunicatorPtr& ic, const Ice::StringSeq& args);
-    virtual void stop();
-
-private:
-    void initialize(const string& appName, const Ice::CommunicatorPtr& ic);
-    void registerWithServiceLocator(const Ice::CommunicatorPtr& ic);
-    void deregisterFromServiceLocator();
-    std::string mAppName;
-    Ice::ObjectAdapterPtr mAdapter;
-    ServiceLocatorManagementPrx mServiceLocatorManagement;
-    Discovery::V1::ServiceManagementPrx mComponentServiceManagement;
-    Discovery::V1::ServiceManagementPrx mStateReplicationManagement;
-    ConfiguredIceLoggerPtr mIceLogger;
-    ComponentServicePtr mComponentService;
-    UdptlStateReplicatorIPtr mStateReplicator;
-    ConfigurationReplicatorPtr mConfigurationReplicator;
-    CollocatedIceStormPtr mIceStorm;
-    Ice::ObjectPrx mConfigurationPublisher;
-    Discovery::V1::ServiceManagementPrx mConfigurationManagement;
-};
-
-static const string ComponentServiceId("UdptlStateReplicatorComponent");
-static const string ServiceDiscoveryId("UdptlStateReplicatorService");
-
-/**
- * This class provides implementation for the ComponentService interface, which
- * every Asterisk SCF component is expected to publish.
- */
-class ComponentServiceImpl : public ComponentService
-{
-public:
-    ComponentServiceImpl(UdptlStateReplicatorService &service) : mService(service) {}
-
-public: // Overrides of the ComponentService interface.
-    virtual void suspend(const ::Ice::Current& = ::Ice::Current())
-    {
-        // TBD
-    }
-
-    virtual void resume(const ::Ice::Current& = ::Ice::Current())
-    {
-        // TBD
-    }
-
-    virtual void shutdown(const ::Ice::Current& = ::Ice::Current())
-    {
-        // TBD
-    }
-
-private:
-    UdptlStateReplicatorService& mService;
-};
-
-class ConfigurationReplicatorI : public ConfigurationReplicator
-{
-public:
-    ConfigurationReplicatorI(const IceStorm::TopicPrx& topic) : mConfigurationReplicationTopic(topic) { };
-    void registerConfigurationService(const AsteriskSCF::System::Configuration::V1::ConfigurationServicePrx&, const Ice::Current&);
-private:
-    IceStorm::TopicPrx mConfigurationReplicationTopic;    
-};
-
-void ConfigurationReplicatorI::registerConfigurationService(const AsteriskSCF::System::Configuration::V1::ConfigurationServicePrx& service, const Ice::Current&)
-{
-    if (mConfigurationReplicationTopic)
-    {
-        IceStorm::QoS qos;
-        qos["reliability"] = "ordered";
-    
-        try
-        {
-            mConfigurationReplicationTopic->subscribeAndGetPublisher(qos, service);
-        }
-        catch (const IceStorm::AlreadySubscribed&)
-        {
-            // This is perfectly okay actually, it just means what they wanted us to do
-            // is already done.
-        }
-    }
-}
-
-/**
- * Register this component's primary public interfaces with the Service Locator.
- * This enables other Asterisk SCF components to locate our interfaces.
- */
-void UdptlStateReplicatorService::registerWithServiceLocator(const Ice::CommunicatorPtr& ic)
-{
-    try
-    {
-        // Get a proxy to the management interface for the Service Locator, so we can add ourselves into the system discovery mechanisms.
-        mServiceLocatorManagement =
-            ServiceLocatorManagementPrx::checkedCast(ic->propertyToProxy("LocatorServiceManagement.Proxy"));
-
-        if (mServiceLocatorManagement == 0)
-        {
-            lg(Error) << "Unable to obtain proxy to LocatorServiceManagement interface. Check config file. "
-                "This component can't be found until this is corrected.";
-            return;
-        }
-
-        // Get a proxy to our ComponentService interface and add it to the Service Locator.
-        Ice::ObjectPrx componentServiceObjectPrx = mAdapter->createDirectProxy(ic->stringToIdentity(ComponentServiceId));
-        ComponentServicePrx componentServicePrx = ComponentServicePrx::checkedCast(componentServiceObjectPrx);
-
-        // The GUID passed in to add service needs to be unique for reporting.
-        string componentServiceGuid(AsteriskSCF::Replication::UDPTL::V1::StateReplicatorComponentCategory);
-        mComponentServiceManagement = ServiceManagementPrx::uncheckedCast(
-            mServiceLocatorManagement->addService(componentServicePrx, componentServiceGuid));
-
-        // Add category as a parameter to enable other components look this component up.
-        ServiceLocatorParamsPtr genericparams = new ServiceLocatorParams();
-        genericparams->category = AsteriskSCF::Replication::UDPTL::V1::StateReplicatorComponentCategory;
-        genericparams->service =  ic->getProperties()->getPropertyWithDefault(mAppName + ".ServiceName", "default");
-        genericparams->id = mAppName;
-        mComponentServiceManagement->addLocatorParams(genericparams, "");
-
-        Ice::ObjectPrx stateReplicatorObjectPrx = mAdapter->createDirectProxy(ic->stringToIdentity(ServiceDiscoveryId));
-        UdptlStateReplicatorPrx stateReplicatorPrx = UdptlStateReplicatorPrx::checkedCast(stateReplicatorObjectPrx);
-
-        string stateReplicationGuid(AsteriskSCF::Replication::UDPTL::V1::StateReplicatorDiscoveryCategory);
-        mStateReplicationManagement = ServiceManagementPrx::uncheckedCast(
-            mServiceLocatorManagement->addService(stateReplicatorPrx, stateReplicationGuid));
-
-        ServiceLocatorParamsPtr discoveryParams = new ServiceLocatorParams;
-        discoveryParams->category = AsteriskSCF::Replication::UDPTL::V1::StateReplicatorDiscoveryCategory;
-        discoveryParams->service = ic->getProperties()->getPropertyWithDefault(mAppName + ".ServiceName", "default");
-        discoveryParams->id = mAppName;
-        mStateReplicationManagement->addLocatorParams(discoveryParams, "");
-
-        // Publish the configuration service IceStorm topic so everybody gets configuration
-        mConfigurationManagement = ServiceManagementPrx::uncheckedCast(
-        mServiceLocatorManagement->addService(mConfigurationPublisher, ""));
-
-        // Populate the configuration parameters with details so we can be found
-        ServiceLocatorParamsPtr configurationParams = new ServiceLocatorParams();
-        configurationParams->category = ConfigurationDiscoveryCategory;
-        configurationParams->service = ic->getProperties()->getPropertyWithDefault(mAppName + ".ServiceName", "default");
-        configurationParams->id = mAppName;
-        mConfigurationManagement->addLocatorParams(configurationParams, "");
-
-        // TBD... We may have other interfaces to publish to the Service Locator.
-    }
-    catch(...)
-    {
-        lg(Error) << "Exception in " << mAppName << " registerWithServiceLocator()";
-    }
-}
-
-/**
- * Deregister this component's primary public interfaces from the Service Locator.
- * This is done at shutdown, and whenever we want to keep other services from locating
- * our interfaces.
- */
-void UdptlStateReplicatorService::deregisterFromServiceLocator()
-{
-    try
-    {
-        mComponentServiceManagement->unregister();
-        mConfigurationManagement->unregister();
-    }
-    catch(...)
-    {
-        lg(Error) << "Had trouble in deregisterFromServiceLocator().";
-    }
-}
-
-void UdptlStateReplicatorService::initialize(const string& appName, const Ice::CommunicatorPtr& ic)
-{
-    mIceStorm = new CollocatedIceStorm(appName, ic->getProperties());
-
-    IceStorm::TopicManagerPrx topicManager = mIceStorm->createTopicManagerProxy(ic);
-
-    IceStorm::TopicPrx topic;
-
-    if (topicManager)
-    {
-        try
-        {
-        topic = topicManager->retrieve("ConfigurationReplication");
-        }
-        catch (const IceStorm::NoSuchTopic&)
-        {
-            try
-            {
-                topic = topicManager->create("ConfigurationReplication");
-            }
-            catch (const IceStorm::TopicExists&)
-            {
-                lg(Error) << "Oh snap! Race condition creating topic, aborting";
-                return;
-            }
-        }
-    // There is no cast here on purpose as this is just going to get passed to
-    // the service locator which just takes a plain ol' proxy anyway.
-    mConfigurationPublisher = topic->getPublisher();
-    }
-    else
-    {
-        lg(Info) << "IceStorm topic manager proxy not present, unable to perform configuration replication.";
-    }
-
-    mAdapter = ic->createObjectAdapter(appName + ".Adapter");
-
-    // setup logging client
-    mIceLogger = createIceLogger(mAdapter);
-    getLoggerFactory().setLogOutput(mIceLogger->getLogger());
-
-    mAppName = appName;
-    // Create and publish our ComponentService interface support.
-    mComponentService = new ComponentServiceImpl(*this);
-    mAdapter->add(mComponentService, ic->stringToIdentity(ComponentServiceId));
-    mStateReplicator = new UdptlStateReplicatorI();
-    mAdapter->add(mStateReplicator, ic->stringToIdentity(ServiceDiscoveryId));
-    mConfigurationReplicator = new ConfigurationReplicatorI(topic);
-    mAdapter->addFacet(mConfigurationReplicator, ic->stringToIdentity(ServiceDiscoveryId),
-    ReplicatorFacet);
-
-    mAdapter->activate();
-}
-
-void UdptlStateReplicatorService::start(const string &name, const Ice::CommunicatorPtr& ic, const Ice::StringSeq&)
-{
-    initialize(name, ic);
-    // Plug into the Asterisk SCF discovery system so that the interfaces we provide
-    // can be located.
-    registerWithServiceLocator(ic);
-}
-
-void UdptlStateReplicatorService::stop()
-{
-    // Remove our interfaces from the service locator.
-    deregisterFromServiceLocator();
-
-    // Stop our local IceStorm instance
-    mIceStorm->stop();
-}
-
-extern "C"
-{
-ASTSCF_DLL_EXPORT IceBox::Service* create(Ice::CommunicatorPtr)
-{
-    return new UdptlStateReplicatorService;
-}
-}
-

commit f81a97fd1a98ad26cf04cf4a5a21b1a1061df926
Author: Joshua Colp <jcolp at digium.com>
Date:   Mon Oct 3 21:02:23 2011 -0300

    Fix comment.

diff --git a/src/UDPTransport.h b/src/UDPTransport.h
index a9c3085..14b12ea 100644
--- a/src/UDPTransport.h
+++ b/src/UDPTransport.h
@@ -48,7 +48,7 @@ public:
         bool expectIPv6); 
 
     //
-    // Primary version.
+    // Replication version.
     //
     static UDPTransportPtr create(const PJMediaEndpointPtr& ep, 
         const UDPTLConfigurationPtr& configObject,

commit 848dbf738d83b45a180169aa81b808658a5b7474
Merge: dc3a2a8 7ee97e4
Author: Joshua Colp <jcolp at digium.com>
Date:   Mon Oct 3 21:01:28 2011 -0300

    Merge branch 'master' of git.asterisk.org:asterisk-scf/integration/mediatransportudptl


commit dc3a2a89b282a8957c49d118b37e8791fcceea3d
Author: Joshua Colp <jcolp at digium.com>
Date:   Mon Oct 3 20:59:43 2011 -0300

    Remove comment about comparator. There actually is none in here...

diff --git a/src/Component.cpp b/src/Component.cpp
index 0589c3b..a88da51 100644
--- a/src/Component.cpp
+++ b/src/Component.cpp
@@ -460,10 +460,6 @@ void Component::onRegisterPrimaryServices()
 
 void Component::onStart() 
 {
-    // Note: I don't think this is necessary. If we make the 
-    // comparator computed from a "service" identifier (which could default
-    // to "default"), there's nothing replicated here that the standby component
-    // couldn't already determine itself. 
     if (getReplicationContext()->isReplicating() == true)
     {
         UdptlReplicationContextPtr udptlReplicationContext = 

commit 7ee97e4877a0d560373e4e9a190563fc8eeab6bf
Author: Joshua Colp <jcolp at digium.com>
Date:   Thu Sep 29 18:00:26 2011 -0300

    Windowsify things.

diff --git a/src/UDPTLSink.cpp b/src/UDPTLSink.cpp
index 5170139..319e530 100644
--- a/src/UDPTLSink.cpp
+++ b/src/UDPTLSink.cpp
@@ -119,8 +119,7 @@ void StreamSinkUDPTLImpl::write(const AsteriskSCF::Media::V1::FrameSeq& frames,
 
     for (FrameSeq::const_iterator frame = frames.begin(); frame != frames.end(); ++frame)
     {
-        const int bufsize = udptl_get_far_max_datagram(mImpl->mUdptl);
-        uint8_t buf[bufsize];
+        uint8_t buf[1400];
         int len = 0;
 
         ByteSeqPayloadPtr payload = ByteSeqPayloadPtr::dynamicCast((*frame)->payload);
diff --git a/src/udptl.c b/src/udptl.c
index 3b66f5a..ccb9d27 100644
--- a/src/udptl.c
+++ b/src/udptl.c
@@ -48,7 +48,6 @@
  * - app_fax.c
  */
 
-#include <sys/time.h>
 #include <signal.h>
 #include <fcntl.h>
 #include <string.h>
@@ -255,18 +254,18 @@ struct udptl_frame *udptl_rx_packet(struct udptl *s, uint8_t *buf, unsigned int
 {
 	int stat1;
 	int stat2;
-	int i;
-	int j;
+	unsigned int i;
+	unsigned int j;
 	int k;
 	int l;
-	int m;
+	unsigned int m;
 	int x;
 	int limit;
 	int which;
 	unsigned int ptr;
 	unsigned int count;
 	int total_count;
-	int seq_no;
+	unsigned int seq_no;
 	const uint8_t *ifp = NULL;
 	const uint8_t *data = NULL;
 	unsigned int ifp_len = 0;
@@ -274,7 +273,7 @@ struct udptl_frame *udptl_rx_packet(struct udptl *s, uint8_t *buf, unsigned int
 	const uint8_t *bufs[ARRAY_LEN(s->f) - 1];
 	unsigned int lengths[ARRAY_LEN(s->f) - 1];
 	int span;
-	int entries;
+	unsigned int entries;
 	int ifp_no;
 
 	ptr = 0;
@@ -403,7 +402,7 @@ struct udptl_frame *udptl_rx_packet(struct udptl *s, uint8_t *buf, unsigned int
 					for (j = 0; j < s->rx[l].fec_len[m]; j++) {
 						s->rx[which].buf[j] = s->rx[l].fec[m][j];
 						for (k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK)
-							s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0;
+							s->rx[which].buf[j] ^= (s->rx[k].buf_len > (int)j) ? s->rx[k].buf[j] : 0;
 					}
 					s->rx[which].buf_len = s->rx[l].fec_len[m];
 					repaired[which] = 1;
@@ -450,7 +449,7 @@ int udptl_build_packet(struct udptl *s, uint8_t *buf, unsigned int buflen, uint8
 	uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2];
 	int i;
 	int j;
-	int seq;
+	unsigned int seq;
 	int entry;
 	int entries;
 	int span;
@@ -592,7 +591,14 @@ static void calculate_local_max_datagram(struct udptl *udptl)
 		break;
 	}
 	/* add 5% extra space for insurance, but no larger than LOCAL_FAX_MAX_DATAGRAM */
-	udptl->local_max_datagram = MIN(new_max * 1.05, LOCAL_FAX_MAX_DATAGRAM);
+	if (LOCAL_FAX_MAX_DATAGRAM > (new_max * 1.05))
+	{
+		udptl->local_max_datagram = (int)(new_max * 1.05);
+	}
+	else
+	{
+		udptl->local_max_datagram = LOCAL_FAX_MAX_DATAGRAM;
+	}
 }
 
 static void calculate_far_max_ifp(struct udptl *udptl)
@@ -658,7 +664,7 @@ static void calculate_far_max_ifp(struct udptl *udptl)
 		break;
 	}
 	/* subtract 5% of space for insurance */
-	udptl->far_max_ifp = new_max * 0.95;
+	udptl->far_max_ifp = (int)(new_max * 0.95);
 }
 
 enum t38_ec_modes udptl_get_error_correction_scheme(const struct udptl *udptl)

commit 3b1dd8ecd661bcab230acfd7e6ae3a7e2e759d7a
Author: Joshua Colp <jcolp at digium.com>
Date:   Wed Sep 28 15:56:48 2011 -0300

    Add test for STUN/ICE support. Working on extending it.

diff --git a/config/test_udptl_ice.conf b/config/test_udptl_ice.conf
new file mode 100644
index 0000000..0d24c2f
--- /dev/null
+++ b/config/test_udptl_ice.conf
@@ -0,0 +1,67 @@
+# This is a configuration file used in conjunction with the MediaTransportUDPTL test driver
+
+#
+# Icebox Configuration
+#
+
+UdptlConfiguration.Name=UdptlStateReplicator
+
+IceBox.InheritProperties=1
+IceBox.LoadOrder=ServiceDiscovery,UdptlStateReplicator,MediaTransportUDPTL,TestMediaTransportUDPTL
+
+Ice.Override.Timeout=5000
+
+# RtpStateReplicator Configuration
+IceBox.Service.UdptlStateReplicator=UdptlStateReplicator:create
+
+# Adapter parameters for this component
+UdptlStateReplicator.Adapter.Endpoints=tcp:udp
+
+# A proxy to the service locator management service
+LocatorServiceManagement.Proxy=LocatorServiceManagement:tcp -p 4412
+
+# A proxy to the service locator service
+LocatorService.Proxy=LocatorService:tcp -p 4411
+
+#
+# MediaTransportUDPTL Configuration
+#
+
+IceBox.Service.MediaTransportUDPTL=MediaTransportUDPTL:create
+
+# Adapter parameters for this component
+MediaTransportUDPTLAdapter.Endpoints=default
+MediaTransportUDPTLAdapterLocal.Endpoints=default
+MediaTransportUDPTLAdapterLogger.Endpoints=default
+
+#
+# TestMediaTransportUDPTL Configuration
+#
+
+IceBox.Service.TestMediaTransportUDPTL=MediaTransportUDPTL_ice_test:create
+
+#
+# Service Locator Configuration
+#
+
+IceBox.Service.ServiceDiscovery=service_locator:create
+
+ServiceDiscovery.IceStorm.InstanceName=ServiceDiscovery
+ServiceDiscovery.IceStorm.TopicManager.Endpoints=default -p 10000
+ServiceDiscovery.IceStorm.Publish.Endpoints=tcp -p 10001:udp -p 10001
+ServiceDiscovery.IceStorm.Trace.TopicManager=2
+ServiceDiscovery.IceStorm.Transient=1
+ServiceDiscovery.IceStorm.Flush.Timeout=2000
+
+UdptlStateReplicator.IceStorm.InstanceName=UdptlStateReplicator
+UdptlStateReplicator.IceStorm.TopicManager.Endpoints=default -p 10005
+UdptlStateReplicator.IceStorm.Publish.Endpoints=default -p 10006
+UdptlStateReplicator.IceStorm.Trace.TopicManager=2
+UdptlStateReplicator.IceStorm.Transient=1
+UdptlStateReplicator.IceStorm.Flush.Timeout=2000
+
+ServiceDiscovery.Management.ServiceAdapter.Endpoints=tcp -p 4412
+ServiceDiscovery.Locator.ServiceAdapter.Endpoints=tcp -p 4411
+ServiceDiscovery.BackplaneAdapter.Endpoints=default
+
+LoggerAdapter.Endpoints=default
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index ac980f6..e12c557 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -14,5 +14,15 @@ astscf_component_add_slice_collection_libraries(MediaTransportUDPTL_test_v6 ASTS
 astscf_component_build_icebox(MediaTransportUDPTL_test_v6)
 set_property(TARGET MediaTransportUDPTL_test_v6 PROPERTY COMPILE_DEFINITIONS IPV6_TEST)
 
+astscf_component_init(MediaTransportUDPTL_ice_test)
+astscf_component_add_files(MediaTransportUDPTL_ice_test TestUDPTLICE.cpp)
+astscf_component_add_slices(MediaTransportUDPTL_ice_test PROJECT AsteriskSCF/Replication/UDPTL/UdptlStateReplicationIf.ice)
+astscf_component_add_slices(MediaTransportUDPTL_ice_test PROJECT AsteriskSCF/Configuration/UDPTL/UdptlConfigurationIf.ice)
+astscf_component_add_boost_libraries(MediaTransportUDPTL_ice_test unit_test_framework thread date_time)
+astscf_component_add_slice_collection_libraries(MediaTransportUDPTL_ice_test ASTSCF)
+astscf_component_build_icebox(MediaTransportUDPTL_ice_test)
+pjproject_link(MediaTransportUDPTL_ice_test pjlib)
+
 astscf_test_icebox(MediaTransportUDPTL_test config/test_component.config)
 astscf_test_icebox(MediaTransportUDPTL_test_v6 config/test_component_v6.config)
+astscf_test_icebox(MediaTransportUDPTL_ice_test config/test_udptl_ice.conf)
diff --git a/test/TestUDPTLICE.cpp b/test/TestUDPTLICE.cpp
new file mode 100644
index 0000000..402a55a
--- /dev/null
+++ b/test/TestUDPTLICE.cpp
@@ -0,0 +1,270 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+
+#define BOOST_TEST_MODULE UdptlICETestModule
+#define BOOST_TEST_NO_MAIN
+
+#include <AsteriskSCF/Testing/IceBoxBoostTest.h>
+
+#include "UdptlConfigurationIf.h"
+#include "UdptlStateReplicationIf.h"
+
+#include <boost/test/debug.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+#include <Ice/Ice.h>
+#include <Ice/BuiltinSequences.h>
+
+#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
+#include <AsteriskSCF/Media/MediaIf.h>
+#include <AsteriskSCF/Media/UDPTL/MediaUDPTLIf.h>
+
+//
+// An attempt to get some reasonable code coverage and verify that the basic *premise* of the functionality works as
+// expected. HOWEVER, nothing beats live testing. Due the the dependency on external agencies (STUN server, TURN server,
+// NAT firewall, etc) there isn't much in the way of real functional testing that we can drive from a single icebox
+// instance. A HOW_TO_TEST document would be a good idea and is a major TODO.
+//
+
+using namespace std;
+using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::Media::V1;
+using namespace AsteriskSCF::Media::UDPTL::V1;
+using namespace AsteriskSCF::System::Configuration::V1;
+using namespace AsteriskSCF::Replication::UDPTL::V1;
+using namespace AsteriskSCF::Configuration::UDPTL::V1;
+
+namespace
+{
+
+class TestReplicatorListener : public UdptlStateReplicatorListener
+{
+public:
+    void stateRemoved(const Ice::StringSeq&, const Ice::Current&)
+    {
+    }
+
+    void stateSet(const UdptlStateItemSeq&, const Ice::Current&)
+    {
+    }
+    
+private:
+    
+};
+
+class IceEnvironment
+{
+public:
+    IceEnvironment()
+    {
+        Ice::InitializationData data;
+        data.properties = IceBoxTestEnv.communicator->getProperties();
+        mCommunicator = Ice::initialize(IceBoxTestEnv.argc, IceBoxTestEnv.argv, data);
+        mAdapter = mCommunicator->createObjectAdapterWithEndpoints("TestAdapter", "default");
+        
+        //
+        // We will be making calls on proxies instantiated on this adapter, so we should activated here.
+        //
+        mAdapter->activate();
+    }
+
+    ~IceEnvironment()
+    {
+        if (mCommunicator)
+        {
+            mCommunicator->shutdown();
+        }
+    }
+
+    Ice::CommunicatorPtr getCommunicator()
+    {
+        return mCommunicator;
+    }
+
+    Ice::ObjectAdapterPtr getObjectAdapter()
+    {
+        return mAdapter;
+    }
+
+private:
+    Ice::CommunicatorPtr mCommunicator;
+    Ice::ObjectAdapterPtr mAdapter;
+};
+
+class TestFixture
+{
+public:
+    TestFixture()
+    {
+        BOOST_TEST_MESSAGE("Creating test fixture");
+        ::boost::debug::detect_memory_leaks(false);
+        ::boost::unit_test::unit_test_log.set_stream(cout);
+    }
+
+    ~TestFixture()
+    {
+        BOOST_TEST_MESSAGE("Destroying test fixture");
+    }
+};
+
+BOOST_GLOBAL_FIXTURE(TestFixture);
+
+UDPTLMediaServicePrx locateMediaService(const ServiceLocatorPrx& locator)
+{
+    UDPTLOverICEServiceLocatorParamsPtr query = new UDPTLOverICEServiceLocatorParams;
+    query->category = "udptl";
+    query->enableICE = true;
+    query->enableTURN = false;
+    return UDPTLMediaServicePrx::checkedCast(locator->locate(query));
+}
+
+ConfigurationServicePrx locateConfigurationService(const ServiceLocatorPrx& locator)
+{
+    ServiceLocatorParamsPtr query = new ServiceLocatorParams;
+    query->category = ConfigurationDiscoveryCategory;
+    return ConfigurationServicePrx::uncheckedCast(locator->locate(query));
+}
+
+ServiceLocatorPrx getLocator(const Ice::CommunicatorPtr& comm)
+{
+    return ServiceLocatorPrx::checkedCast(comm->propertyToProxy("LocatorService.Proxy"));
+}
+
+BOOST_AUTO_TEST_CASE(UdptlSessionWithICEEnabled)
+{
+    IceEnvironment iceEnv;
+    bool testResult = false;
+    try
+    {
+        ServiceLocatorPrx locator;
+        BOOST_REQUIRE_NO_THROW(locator = getLocator(iceEnv.getCommunicator()));
+        BOOST_REQUIRE(locator != 0);
+
+        //
+        // It's actually pretty handy that this icebox test suite probably
+        // shares the configuration file that hosts the media service!
+        //
+        ConfigurationServicePrx configPrx;
+        BOOST_REQUIRE_NO_THROW(
+            configPrx = locateConfigurationService(locator));
+        BOOST_REQUIRE(configPrx != 0);
+        UDPTLICEConfigurationGroupPtr iceGroup = new UDPTLICEConfigurationGroup;
+
+        STUNServerItemPtr stunServerCfg = new STUNServerItem;
+        stunServerCfg->address = "stun.xten.com";
+        stunServerCfg->port = 3478;
+        iceGroup->configurationItems[STUNServerItemName] = stunServerCfg;
+
+        UDPTLICETransportFlagsItemPtr iceFlags = new UDPTLICETransportFlagsItem;
+        iceFlags->enableICE = true;
+        iceFlags->enableTURN = false;
+        iceGroup->configurationItems[UDPTLICETransportFlagsItemName] = iceFlags;
+
+        ConfigurationGroupSeq s;
+        s.push_back(iceGroup);
+        configPrx->setConfiguration(s);
+
+        UDPTLMediaServicePrx servicePrx;
+        {
+            UDPTLOverICEServiceLocatorParamsPtr query = new UDPTLOverICEServiceLocatorParams;
+            query->category = "udptl";
+            query->enableICE = true;
+            query->enableTURN = false;
+            servicePrx = UDPTLMediaServicePrx::checkedCast(locator->locate(query));
+        }
+        BOOST_REQUIRE(servicePrx);
+        try
+        {
+            UDPTLOverICEServiceLocatorParamsPtr query = new UDPTLOverICEServiceLocatorParams;
+            query->category = "udptl";
+            query->enableICE = true;
+            query->enableTURN = false;
+            UDPTLSessionPrx sessionPrx;
+            BOOST_REQUIRE_NO_THROW(sessionPrx = servicePrx->allocate(query));
+            BOOST_REQUIRE(sessionPrx != 0);
+            sessionPrx->ice_ping(); // To silence unused arg warning.
+            sessionPrx->release();
+            testResult = true;
+        }
+        catch (const SessionAllocationFailure& ex)
+        {
+            BOOST_TEST_MESSAGE(ex.what());
+        }
+    }
+    catch (const Ice::Exception& ex)
+    {
+        BOOST_FAIL(ex.what());
+    }
+    BOOST_CHECK(testResult);
+}
+
+BOOST_AUTO_TEST_CASE(UdptlSessionAllocationFailure)
+{
+    IceEnvironment iceEnv;
+    bool testResult = false;
+    try
+    {
+        ServiceLocatorPrx locator;
+        BOOST_REQUIRE_NO_THROW(locator = getLocator(iceEnv.getCommunicator()));
+        BOOST_REQUIRE(locator != 0);
+        UDPTLMediaServicePrx servicePrx;
+        BOOST_REQUIRE_NO_THROW(servicePrx = locateMediaService(locator));
+        BOOST_REQUIRE(servicePrx);
+
+        //
+        // It's actually pretty handy that this icebox test suite probably
+        // shares the configuration file that hosts the media service!
+        //
+        ConfigurationServicePrx configPrx;
+        BOOST_REQUIRE_NO_THROW(
+            configPrx = locateConfigurationService(locator));
+        UDPTLICEConfigurationGroupPtr iceGroup = new UDPTLICEConfigurationGroup;
+        UDPTLICETransportFlagsItemPtr iceFlags = new UDPTLICETransportFlagsItem;
+        iceFlags->enableICE = false;
+        iceFlags->enableTURN = false;
+        iceGroup->configurationItems[UDPTLICETransportFlagsItemName] = iceFlags;
+        ConfigurationGroupSeq s;
+        s.push_back(iceGroup);
+        BOOST_REQUIRE_NO_THROW(configPrx->setConfiguration(s));
+        try
+        {
+            UDPTLOverICEServiceLocatorParamsPtr query = new UDPTLOverICEServiceLocatorParams;
+            query->category = "udptl";
+            query->enableICE = true;
+            query->enableTURN = true;
+            UDPTLSessionPrx sessionPrx = servicePrx->allocate(query);
+            sessionPrx->ice_ping();
+        }
+        catch (const SessionAllocationFailure& ex)
+        {
+            testResult = true;
+            BOOST_TEST_MESSAGE(ex.what());
+        }
+    }
+    catch (const Ice::Exception& ex)
+    {
+        BOOST_TEST_MESSAGE(ex.what());
+    }
+    BOOST_CHECK(testResult);
+}
+
+}
+
+
+
+

commit 35178480df903a5e326aaade1c8f0c11a1ff7b81
Author: Joshua Colp <jcolp at digium.com>
Date:   Tue Sep 27 12:20:37 2011 -0300

    Use the ICE transport when needed.

diff --git a/src/UDPTLSession.cpp b/src/UDPTLSession.cpp
index b5d2edb..b0203a5 100644
--- a/src/UDPTLSession.cpp
+++ b/src/UDPTLSession.cpp
@@ -22,6 +22,7 @@
 #include "PJMediaTransport.h"
 #include "PJMediaEndpoint.h"
 #include "UDPTransport.h"
+#include "ICETransport.h"
 
 #include <pjlib.h>
 #include <pjmedia.h>
@@ -230,7 +231,22 @@ UDPTLSessionImpl::UDPTLSessionImpl(const Ice::ObjectAdapterPtr& adapter,
     mReplicationContext(replicationContext),
     mUdptl(udptl_create())
 {
-    mTransport = UDPTransport::create(mEndpoint, configurationService, params->ipv6);
+    UDPTLOverICEServiceLocatorParamsPtr iceParams(UDPTLOverICEServiceLocatorParamsPtr::dynamicCast(params));
+    if (iceParams && iceParams->enableICE)
+    {
+        if (mEnvironment->natConfig() && mEnvironment->natConfig()->isSTUNEnabled())
+        {
+            mTransport = ICETransport::create(mEndpoint, env);
+        }
+        else
+        {
+            throw SessionAllocationFailure("ICE/NAT features not enabled for this component instance");
+        }
+    }
+    else
+    {
+        mTransport = UDPTransport::create(mEndpoint, configurationService, params->ipv6);
+    }
 
     // Initialize our session state item enough so that the state items for the source and sink can also be initialized.
     mSessionStateItem->key = mSessionStateItem->sessionId = IceUtil::generateUUID();
@@ -256,7 +272,14 @@ UDPTLSessionImpl::UDPTLSessionImpl(const Ice::ObjectAdapterPtr& adapter,
     mReplicationContext(replicationContext),
     mUdptl(udptl_create())
 {
-    mTransport = UDPTransport::create(mEndpoint, configurationService, port, ipv6);
+    if (mEnvironment->natConfig() && mEnvironment->natConfig()->isSTUNEnabled())
+    {
+        mTransport = ICETransport::create(mEndpoint, env);
+    }
+    else
+    {
+        mTransport = UDPTransport::create(mEndpoint, configurationService, port, ipv6);
+    }
 }
 
 /**

commit df6cc81d885647e69b43c44390cece5beeb5f9c7
Author: Joshua Colp <jcolp at digium.com>
Date:   Tue Sep 27 12:07:51 2011 -0300

    Bring over ICE/STUN transport stuff from RTP to be used with UDPTL.

diff --git a/config/UdptlConfigurator.py b/config/UdptlConfigurator.py
index bde1039..7be2ea0 100755
--- a/config/UdptlConfigurator.py
+++ b/config/UdptlConfigurator.py
@@ -54,6 +54,36 @@ class UdptlSectionVisitors(Configurator.SectionVisitors):
 
         self.groups.append(group)
 
+        def visit_udptloverice(self, config, section):
+            group = AsteriskSCF.Configuration.UDPTL.V1.UDPTLICEConfigurationGroup()
+            group.configurationItems = { }
+
+            mapper = Configurator.OptionMapper()
+
+            stunServerItem = AsteriskSCF.Configuration.UDPTL.V1.STUNServerItem()
+            mapper.map('stunserverhost', stunServerItem, 'address', AsteriskSCF.Configuration.UDPTL.V1.STUNServerItemName, config.get, None)
+            mapper.map('stunserverport', stunServerItem, 'port', AsteriskSCF.Configuration.UDPTL.V1.STUNServerItemName, config.getint, 3478)
+
+            turnServerItem = AsteriskSCF.Configuration.UDPTL.V1.TURNServerItem()
+            mapper.map('turnserverhost', turnServerItem, 'address', AsteriskSCF.Configuration.UDPTL.V1.TURNServerItemName, config.get, None)
+            mapper.map('turnserverport', turnServerItem, 'port', AsteriskSCF.Configuration.UDPTL.V1.TURNServerItemName, config.getint, 3478)
+
+            udptlOverICEItem = AsteriskSCF.Configuration.UDPTL.V1.UDPTLICETransportFlagsItem()
+            mapper.map('udptlovericeenable', udptlOverICEItem, 'enableICE', AsteriskSCF.Configuration.UDPTL.V1.UDPTLICETransportFlagsItemName, config.get, None)
+            mapper.map('udptlovericewithturn', udptlOverICEItem, 'enableTURN', AsteriskSCF.Configuration.UDPTL.V1.UDPTLICETransportFlagsItemName, config.get, None)
+
+            udptlICELimits = AsteriskSCF.Configuration.UDPTL.V1.UDPTLICETransportLimitsItem()
+            mapper.map('udptlicemaxcandidates', udptlICELimits, 'maxCandidates', AsteriskSCF.Configuration.UDPTL.V1.UDPTLICELimitsItemName, config.getint, 10)
+            mapper.map('udptlicemaxcalls', udptlICELimits, 'maxCalls', AsteriskSCF.Configuration.UDPTL.V1.UDPTLICELimitsItemName, config.getint, 50)
+
+            for option in config.options(section):
+                mapper.execute(group, section, option)
+                
+            mapper.finish(group)
+                
+            self.groups.append(group)
+
+
 # In order to do service locator based lookup we need to pass in a params object
 serviceLocatorParams = AsteriskSCF.Core.Discovery.V1.ServiceLocatorParams()
 serviceLocatorParams.category = AsteriskSCF.Configuration.UDPTL.V1.ConfigurationDiscoveryCategory
diff --git a/config/test_component.config b/config/test_component.config
index c4bc8a3..241a91c 100644
--- a/config/test_component.config
+++ b/config/test_component.config
@@ -60,5 +60,6 @@ UdptlStateReplicator.IceStorm.Flush.Timeout=2000
 
 ServiceDiscovery.Management.ServiceAdapter.Endpoints=tcp -p 4412
 ServiceDiscovery.Locator.ServiceAdapter.Endpoints=tcp -p 4411
+ServiceDiscovery.BackplaneAdapter.Endpoints=default
 
 LoggerAdapter.Endpoints=default
diff --git a/slice/AsteriskSCF/Configuration/UDPTL/UdptlConfigurationIf.ice b/slice/AsteriskSCF/Configuration/UDPTL/UdptlConfigurationIf.ice
index 3b4a9dd..4dd1ccd 100644
--- a/slice/AsteriskSCF/Configuration/UDPTL/UdptlConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/UDPTL/UdptlConfigurationIf.ice
@@ -159,6 +159,86 @@ module V1
         int fecEntries;
     };
 
+    /*
+     * Configuration group for ICE enabled UDPTL.
+     */
+    class UDPTLICEConfigurationGroup extends UdptlConfigurationGroup
+    {
+    };
+
+    /**
+     * Name that the STUN server configuration item should be inserted as.
+     */
+    const string STUNServerItemName = "stunServer";
+
+    /**
+     * Hostname for the STUN server.
+     */
+    class STUNServerItem extends UdptlConfigurationItem
+    {
+        string address;
+        int port;
+    };
+
+    /**
+     * Name that the TURN server configuration item should be inserted as.
+     */
+    const string TURNServerItemName = "turnServer";
+
+    /**
+     * Hostname for the TURN server.
+     */
+    class TURNServerItem extends UdptlConfigurationItem
+    {
+        string address;
+        int port;
+    };
+
+    /**
+     * Name that the ICE transport configuration flags item should be inserted as.
+     */
+    const string UDPTLICETransportFlagsItemName = "iceFlags";
+
+    /**
+     * Configuration item with option flags for the ICE transport.
+     */
+    class UDPTLICETransportFlagsItem extends UdptlConfigurationItem
+    {
+        /**
+         * If the configuration option is present, it's most likely
+         * because we want to enable STUN and ICE
+         */
+        bool enableICE = true;
+
+        /**
+         * Using a TURN server as a candidate should be a selectable option
+         * since a TURN server isn't always available. Setting this to true
+         * while enableICE is false has no effect.
+         */
+        bool enableTURN = true;
+    };
+
+    /**
+     * Name that ICE option items should be inserted as.
+     */
+    const string UDPTLICELimitsItemName = "iceLimits";
+
+    /**
+     * Configuration item for configurable limits for the ICE transport.
+     */
+    class UDPTLICETransportLimitsItem extends UdptlConfigurationItem
+    {
+        /**
+         * The maximum number of candidates to gather and publish.
+         */
+        int maxCandidates;
+
+        /**
+         * The maximum number of ICE negotiated flows to allow.
+         */
+        int maxCalls;
+    };
+
 }; /* module V1 */
 
 }; /* module UDPTL */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 348e029..9f196d1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -30,6 +30,14 @@ astscf_component_add_files(MediaTransportUDPTL PJMediaEndpoint.h)
 astscf_component_add_files(MediaTransportUDPTL PJUtil.h)
 astscf_component_add_files(MediaTransportUDPTL UDPTransport.cpp)
 astscf_component_add_files(MediaTransportUDPTL UDPTransport.h)
+astscf_component_add_files(MediaTransportUDPTL ICETransport.cpp)
+astscf_component_add_files(MediaTransportUDPTL ICETransport.h)
+astscf_component_add_files(MediaTransportUDPTL NATModule.cpp)
+astscf_component_add_files(MediaTransportUDPTL NATModule.h)
+astscf_component_add_files(MediaTransportUDPTL NATConfig.cpp)
+astscf_component_add_files(MediaTransportUDPTL NATConfig.h)
+astscf_component_add_files(MediaTransportUDPTL ICEConfiguration.cpp)
+astscf_component_add_files(MediaTransportUDPTL ICEConfiguration.h)
 astscf_component_add_slices(MediaTransportUDPTL PROJECT AsteriskSCF/Replication/UDPTL/UdptlStateReplicationIf.ice)
 astscf_component_add_slices(MediaTransportUDPTL PROJECT AsteriskSCF/Configuration/UDPTL/UdptlConfigurationIf.ice)
 astscf_component_add_boost_libraries(MediaTransportUDPTL core thread)
diff --git a/src/Configuration.h b/src/Configuration.h
index 0bed468..ef179c9 100755
--- a/src/Configuration.h
+++ b/src/Configuration.h
@@ -21,6 +21,8 @@
 #include <IceUtil/Shared.h>
 
 #include "PJLibConfiguration.h"
+#include "NATConfig.h"
+#include "ICEConfiguration.h"
 
 namespace AsteriskSCF
 {
@@ -37,6 +39,9 @@ class UDPTLConfiguration : public virtual IceUtil::Shared
 public:
     virtual ~UDPTLConfiguration() {}
 
+    virtual NATConfigPtr natConfig() const = 0;
+    virtual ICEConfigurationPtr ICEConfig() const = 0;
+
     virtual int getStartPort() = 0;
     virtual int getEndPort() = 0;
     virtual std::string getBindIPv4Address() = 0;
diff --git a/src/ICEConfiguration.cpp b/src/ICEConfiguration.cpp
new file mode 100644
index 0000000..5ed3aed
--- /dev/null
+++ b/src/ICEConfiguration.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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::UDPTL;
+
+ICEConfigurationPtr AsteriskSCF::UDPTL::ICEConfiguration::create(int maxCand, int maxClls)
+{
+    return ICEConfigurationPtr(new ICEConfiguration(maxCand, maxClls));
+}
+
+ICEConfiguration::ICEConfiguration(int maxCand, int maxClls) :
+    mMaxCandidates(maxCand),
+    mMaxCalls(maxClls)
+{
+}
diff --git a/src/ICEConfiguration.h b/src/ICEConfiguration.h
new file mode 100644
index 0000000..597b973
--- /dev/null
+++ b/src/ICEConfiguration.h
@@ -0,0 +1,68 @@
+/*
+ * 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 UDPTL
+{
+
+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. 
+ **/
+class ICEConfiguration
+{
+public:
+
+    int maxCandidates() const
+    {
+        return mMaxCandidates;
+    }
+
+    int maxCalls() const
+    {
+        return mMaxCalls;
+    }
+
+    /**
+     * Create configuration instance!
+     **/
+    static ICEConfigurationPtr create(int maxCand, int maxClls);
+    
+private:
+    int mMaxCandidates;
+    int mMaxCalls;
+
+    ICEConfiguration(int maxCandidates, int maxCalls);
+
+    //
+    // Hidden and not implemented.
+    //
+    ICEConfiguration(const ICEConfiguration&);
+    void operator=(const ICEConfiguration&);
+};
+
+} /* End of namespace UDPTL */
+} /* End of namespace AsteriskSCF */
diff --git a/src/ICETransport.cpp b/src/ICETransport.cpp
new file mode 100644
index 0000000..7c083f2
--- /dev/null
+++ b/src/ICETransport.cpp
@@ -0,0 +1,803 @@
+/*
+ * 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 "ICETransport.h"
+#include "PJUtil.h"
+
+#include <pjmedia.h>
+#include <pjlib.h>
+#include <pjnath.h>
+
+#include <AsteriskSCF/System/ExceptionsIf.h>
+#include <map>
+#include <boost/thread.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+#include <AsteriskSCF/System/NAT/NATTraversalIf.h>
+#include <Ice/Ice.h>
+#include <sstream>
+#include <AsteriskSCF/logger.h>
+#include <IceUtil/UUID.h>
+
+using namespace AsteriskSCF::UDPTL;
+using namespace AsteriskSCF::System::V1;
+using namespace AsteriskSCF::PJUtil;
+using namespace std;
+using namespace AsteriskSCF::Helpers;
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::System::NAT::V1;
+
+namespace
+{
+Logger logger = getLoggerFactory().getLogger("AsteriskSCF.MediaUDPTL");
+}
+
+namespace 
+{
+
+class ICEAgentImpl : public InteractiveConnectionAgent
+{
+public:
+
+    ICEAgentImpl(const Ice::ObjectAdapterPtr& adapter, const Ice::Identity& id, const PJMediaEnvironmentPtr& env,
+        const PJMediaEndpointPtr& ep) :
+        mAdapter(adapter),
+        mId(id),
+        mShuttingDown(false),
+        mNATType(AsteriskSCF::System::NAT::V1::Unknown),
+        mRole(UndefinedRole),
+        mEnv(env),
+        mEndpoint(ep),
+        mTransport(0)
+    {
+    }
+
+    AgentType getAgentType(const Ice::Current&)
+    {
+        return Full;
+    }
+
+    DetectedNATType getNATType(const Ice::Current&)
+    {
+        boost::shared_lock<boost::shared_mutex> lock(mLock);
+        stateCheck();
+        return mNATType;
+    }
+
+    Role getRole(const Ice::Current&)
+    {
+        boost::shared_lock<boost::shared_mutex> lock(mLock);
+        stateCheck();
+        return mRole;
+    }
+
+    void negotiate_async(const AMD_InteractiveConnectionAgent_negotiatePtr& callback,
+        const string& hostname, Ice::Int port, const CandidateSeq& candidates,
+        const Ice::Current&)
+    {
+
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+        stateCheck();
+        if (mCurrentNegotiation)
+        {
+            pjmedia_transport_media_stop(mTransport);
+            mCurrentNegotiation->ice_exception(NegotiationInterrupted("New negotiate() request"));
+            //
+            // TODO: are we going to support cancellable negotiations.
+            //
+        }
+        mCurrentNegotiation = callback;
+
+        //
+        // So how this works is we create a remote SDP and call pjmedia_transport_start() easy peasy. (Same deal 
+        //
+        pjmedia_sdp_session* remoteSDPSession = 
+            static_cast<pjmedia_sdp_session*>(pj_pool_zalloc(mEnv->memoryPool(), sizeof(pjmedia_sdp_session)));
+
+
+        //
+        // TODO: I think the ICE transport ignores a lot of this stuff, but I'm going to add it for the time
+        // being anyways.
+        //
+
+        //
+        // Missing details, user, id, version, net type?
+        //
+        pj_strdup2(mEnv->memoryPool(), &remoteSDPSession->name, "ASCFMEDIA");
+        pj_strdup2(mEnv->memoryPool(), &remoteSDPSession->origin.user, "");
+        AddressPtr remoteHost(new Address(hostname, port));
+
+        remoteSDPSession->conn = static_cast<pjmedia_sdp_conn*>(pj_pool_zalloc(mEnv->memoryPool(), sizeof(pjmedia_sdp_conn)));
+        pj_strdup2(mEnv->memoryPool(), &remoteSDPSession->conn->net_type, "IN");
+        pj_strdup2(mEnv->memoryPool(), &remoteSDPSession->origin.net_type, "IN");
+
+        //
+        // TODO: Look at whether the members can point to the same memory without issues.
+        //
+        if (remoteHost->isIPV6())
+        {
+            pj_strdup2(mEnv->memoryPool(), &remoteSDPSession->origin.addr_type, "IP6");
+            pj_strdup2(mEnv->memoryPool(), &remoteSDPSession->conn->addr_type, "IP6");
+        }
+        else
+        {
+            pj_strdup2(mEnv->memoryPool(), &remoteSDPSession->origin.addr_type, "IP4");
+            pj_strdup2(mEnv->memoryPool(), &remoteSDPSession->conn->addr_type, "IP4");
+        }
+        pj_strdup2(mEnv->memoryPool(), &remoteSDPSession->origin.addr, remoteHost->address().c_str());
+        pj_strdup2(mEnv->memoryPool(), &remoteSDPSession->conn->addr, remoteHost->address().c_str());
+        remoteSDPSession->attr_count = 0;
+
+        //
+        // Cut n' paste from current SIP session manager... icky. TODO: sift through and see what of this
+        // can be discarded for this purpose.
+        //
+        remoteSDPSession->media_count = 1;
+        pjmedia_sdp_media* media =
+            static_cast<pjmedia_sdp_media*>(pj_pool_zalloc(mEnv->memoryPool(), sizeof(pjmedia_sdp_media)));
+        remoteSDPSession->media[0] = media;
+        pj_strdup2(mEnv->memoryPool(), &media->desc.media, "audio");
+        media->desc.port = (pj_uint16_t) port; // XXX --- this is not going to be correct here.. we don't actually have this!
+        media->desc.port_count = 1;
+        pj_strdup2(mEnv->memoryPool(), &media->desc.transport, "RTP/AVP");
+
+        // Populate the stream with codec details
+        remoteSDPSession->media[0]->desc.fmt_count = 1;
+        remoteSDPSession->media[0]->attr_count = 0;
+
+        // TODO: We should iterate over the formats to produce this instead of hardcoding
+        pjmedia_sdp_rtpmap rtpmap;
+        pjmedia_sdp_attr *attr;
+
+        // This is hardcoded value for ULAW for now
+        pj_strdup2(mEnv->memoryPool(), &media->desc.fmt[0], "0");
+        rtpmap.pt = media->desc.fmt[0];
+        rtpmap.clock_rate = 8000;
+        pj_strdup2(mEnv->memoryPool(), &rtpmap.enc_name, "PCMU");
+        rtpmap.param.slen = 0;
+        pjmedia_sdp_rtpmap_to_attr(mEnv->memoryPool(), &rtpmap, &attr);
+        remoteSDPSession->media[0]->attr[remoteSDPSession->media[0]->attr_count++] = attr;
+
+        // Might as well add sendrecv
+        attr = static_cast<pjmedia_sdp_attr*>(pj_pool_zalloc(mEnv->memoryPool(), sizeof(pjmedia_sdp_attr)));
+        pj_strdup2(mEnv->memoryPool(), &attr->name, "sendrecv");
+        remoteSDPSession->media[0]->attr[remoteSDPSession->media[0]->attr_count++] = attr;
+
+        //
+        // I was concerned about the fact that for a given SIP session, there might be multiple media
+        // streams and multiple candidates. I'm not sure that its actually too much of an issue even 
+        // if multiple media types are muxed on a single ICE negotiated flow, but there will need to be
+        // some redesign to pull in the multiple media streams associated with the session. For the moment
+        // we will operation under the premise that we are dealing with a single media stream.
+        // TODO: the SIP session gateway contains similar code, but from the offer perspective. This stuff
+        // should be refactored into a pjproject utility library.
+        //
+        //
+        pjmedia_sdp_media* currentMedia = remoteSDPSession->media[0];
+        for (CandidateSeq::const_iterator i = candidates.begin(); i != candidates.end(); ++i)
+        {
+            CandidatePtr candidate = *i;
+            ostringstream os;
+            os << "candidate:" << candidate->foundation << ' ' << candidate->componentId <<  " UDP " << 
+                candidate->priority << ' ' << candidate->mappedAddress << ' ' << candidate->mappedPort << " typ ";
+            string hostType;
+            switch (candidate->type)
+            {
+            case Host:
+                hostType = "host";
+                break;
+            case ServerReflexive:
+                hostType = "srflx";
+                break;
+            case PeerReflexive:
+                hostType = "prflx";
+                break;
+            case Relayed:
+                hostType = "relay";
+                break;
+            }
+            os << hostType;
+            if (candidate->type != Host)
+            {
+                os << " raddr " << candidate->baseAddress << " rport " << candidate->basePort;
+            }
+            string t = os.str();
+            pj_str_t candidateStr = pj_str(const_cast<char*>(t.c_str()));
+            pjmedia_sdp_attr* newAttribute = pjmedia_sdp_attr_create(mEnv->memoryPool(), 
+                "candidate", &candidateStr);
+            pjmedia_sdp_attr_add(&currentMedia->attr_count, currentMedia->attr, newAttribute);
+        }
+        pjmedia_sdp_session localSession;
+        pjmedia_transport_encode_sdp(mTransport, mEnv->memoryPool(), &localSession, 0, 0);
+        pjmedia_transport_media_start(mTransport, mEnv->memoryPool(), &localSession, remoteSDPSession, 0);
+    }
+
+    CandidateSeq getCandidates(const Ice::Current&)
+    {
+        boost::shared_lock<boost::shared_mutex> lock(mLock);
+        return mCandidates;
+    }
+
+    void onSetupComplete(pjmedia_transport* transport, pj_status_t status)
+    {
+        if (fail(status))
+        {
+            ostringstream err;
+            err << "Setup/negotiation failed with pj_status_t value of " << status;
+            throw NegotiationError(err.str());
+        }
+
+        pjmedia_transport_info info;
+        pjmedia_transport_info_init(&info);
+        pjmedia_transport_get_info(transport, &info);
+
+        pjmedia_ice_transport_info* iceInfo = 0;
+        for (unsigned i = 0; i < info.specific_info_cnt; ++i)
+        {
+            if (info.spc_info[i].type == PJMEDIA_TRANSPORT_TYPE_ICE)
+            {
+                iceInfo = (pjmedia_ice_transport_info*)(info.spc_info[i].buffer);
+            }
+        }
+
+        assert(iceInfo != 0);
+
+        //
+        // While we just did the assert, we use an if statement as well to
+        // prevent crashing in release builds.
+        //
+        if (iceInfo)
+        {
+            boost::unique_lock<boost::shared_mutex> lock(mLock);
+            if (mTransport)
+            {
+                //
+                // duplicate call.
+                //
+                return;
+            }
+            mTransport = transport;
+            if (iceInfo->role == PJ_ICE_SESS_ROLE_CONTROLLING)
+            {
+                setRole(Controlling);
+            }
+            else
+            {
+                setRole(Controlled);
+            }
+
+            pjmedia_transport_media_create(mTransport, mEnv->memoryPool(), 0, 0, 0);
+
+            //
+            // Ok, so the pjmedia ice transport won't let use get at the actual
+            // candidate structures, so what we have to do is get the SDP from
+            // the transport and convert what we find there to our Ice structures.
+            //
+            pjmedia_sdp_session* sdpSession;
+            unsigned streamCount = 1; // The 1 doesn't matter, this is just to initialize the basic structure.
+            pjmedia_endpt_create_sdp(mEndpoint->endpoint(), mEnv->memoryPool(), streamCount, &info.sock_info, &sdpSession);
+            pjmedia_transport_encode_sdp(mTransport, mEnv->memoryPool(), sdpSession, 0, 0);
+            for (size_t i = 0; i < sdpSession->media_count; ++i)
+            {
+                const string candidateName("candidate");
+                pjmedia_sdp_media* media = sdpSession->media[i];
+                ostringstream errorMessage;
+                for (size_t j = 0; j < media->attr_count; ++j)
+                {
+                    pjmedia_sdp_attr* attr = media->attr[j];
+                    if (string(attr->name.ptr, attr->name.slen) == candidateName)
+                    {
+                        //
+                        // Now we get to parse a candidate string!
+                        //
+                        string value(attr->value.ptr, attr->value.slen);
+                        istringstream is(value);
+                        string foundation;
+                        if (!(is >> foundation))
+                        {
+                            errorMessage << "Unable to parse ICE candidate value (foundation) : " << value;
+                            break;
+                        }
+
+                        int componentId;
+                        if (!(is >> componentId))
+                        {
+                            errorMessage << "Unable to parse ICE candidate value (component id) : " << value;
+                            break;
+                        }
+
+                        //
+                        // We don't care about the transport right now.. we are assuming UDP.
+                        //
+                        string transportDummy;
+                        if (!(is >> transportDummy))
+                        {
+                            errorMessage << "Unable to parse ICE candidate value (transport) : " << value;
+                            break;
+                        }
+
+                        int priority;
+                        if (!(is >> priority))
+                        {
+                            errorMessage << "Unable to parse ICE candidate value (priority) : " << value;
+                            break;
+                        }
+
+                        string connectionAddress;
+                        if (!(is >> connectionAddress))
+                        {
+                            errorMessage << "Unable to parse ICE candidate value (connection address) : " << value;
+                            break;
+                        }
+
+                        unsigned port;
+                        if (!(is >> port))
+                        {
+                            errorMessage << "Unable to parse ICE candidate value (connection port) : " << value;
+                            break;
+                        }
+
+                        string candidateTypePrefix;
+                        if (!(is >> candidateTypePrefix))
+                        {
+                            errorMessage << "Unable to parse ICE candidate constant (typ) : " << value;
+                            break;
+                        }
+
+                        string candidateType;
+                        if (!(is >> candidateType))
+                        {
+                            errorMessage << "Unable to parse ICE candidate value (candidate type) : " << value;
+                            break;
+                        }
+
+
+                        CandidatePtr candidateObj = new Candidate;
+                        candidateObj->sessionId = IceUtil::generateUUID(); // this should be the object id.
+                        candidateObj->componentId = 1; // At least until we implement RTCP.
+                        candidateObj->priority = priority;
+                        candidateObj->baseAddress = connectionAddress;
+                        candidateObj->basePort = port;
+                        candidateObj->transport = UDP;
+
+                        if (candidateType == "host")
+                        {
+                            candidateObj->type = Host;
+                        }
+                        else if (candidateType == "srflx")
+                        {
+                            candidateObj->type = ServerReflexive;
+                        }
+                        else if (candidateType == "prflx")
+                        {
+                            candidateObj->type = PeerReflexive;
+                        }
+                        else if (candidateType == "relay")
+                        {
+                            candidateObj->type = Relayed;
+                        }
+                        else
+                        {
+                            errorMessage << "Unable to determine the candidate type, skipping : " << value;
+                        }
+
+                        if (candidateType != "host")
+                        {
+                            string dummy;
+                            if (!(is >> dummy))
+                            {
+                                errorMessage << "Unable to parse ICE candidate constant (raddr) : " << value;
+                                break;
+                            }
+
+                            string baseAddress;
+                            if (!(is >> baseAddress))
+                            {
+                                errorMessage << "Unable to parse ICE candidate value (rel-addr) : " << value;
+                                break;
+                            }
+
+                            if (!(is >> dummy))
+                            {
+                                errorMessage << "Unable to parse ICE candidate constant (rport) : " << value;
+                                break;
+                            }
+
+                            unsigned basePort;
+                            if (!(is >> basePort))
+                            {
+                                errorMessage << "Unable to parse ICE candidate value (rel-port) : " << value;
+                                break;
+                            }
+                            candidateObj->mappedAddress = candidateObj->baseAddress;
+                            candidateObj->mappedPort = candidateObj->basePort;
+                            candidateObj->baseAddress = baseAddress;
+                            candidateObj->basePort = basePort; 
+                        }
+                        else
+                        {
+                            candidateObj->mappedAddress = "";
+                            candidateObj->mappedPort = 0;
+                        }
+                        //
+                        // And we ignore the rest.
+                        //
+                        mCandidates.push_back(candidateObj);
+                    }
+                    string err(errorMessage.str());
+                    if (!err.empty())
+                    {
+                        throw invalid_argument(err);
+                    }
+                }
+            }
+            if (mCurrentNegotiation)
+            {
+                if (mCandidates.size() == 0)
+                {
+                    logger(Error) << "No candidates after negotiation, looks like fail";
+                    mCurrentNegotiation->ice_exception(NoValidCandidates());
+                    throw invalid_argument("no valid candidates, did negotiation fail?");
+                }
+                mCurrentNegotiation->ice_response(mCandidates[0]);
+                mCurrentNegotiation = 0;
+                if (mCandidates.size() > 1)
+                {
+                    logger(Warning) << "More than one candidate after negotiation!";
+                }
+            }
+        }
+    }
+
+    void shutdown()
+    {
+        {
+            boost::unique_lock<boost::shared_mutex> lock(mLock);
+            if (mShuttingDown)
+            {
+                return;
+            }
+            mShuttingDown = true;
+            if (mCurrentNegotiation)
+            {
+                pjmedia_transport_media_stop(mTransport);
+                mCurrentNegotiation->ice_exception(NegotiationInterrupted("Shutting down."));
+            }
+        }
+        mAdapter->removeFacet(mId, "ICEAgent");
+    }
+
+    void setNATType(DetectedNATType natType)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+        mNATType = natType;
+    }
+
+    void setRole(Role role)
+    {
+        mRole = role;
+    }
+
+private:
+    boost::shared_mutex mLock;
+    Ice::ObjectAdapterPtr mAdapter;
+    Ice::Identity mId;
+    bool mShuttingDown;
+    DetectedNATType mNATType;
+    Role mRole;
+    CandidateSeq mCandidates;
+    PJMediaEnvironmentPtr mEnv;
+    PJMediaEndpointPtr mEndpoint;
+    pjmedia_transport* mTransport;
+    AMD_InteractiveConnectionAgent_negotiatePtr mCurrentNegotiation;
+
+    void stateCheck()
+    {
+        if (mShuttingDown)
+        {
+            throw Ice::ObjectNotExistException(__FILE__, __LINE__);
+        }
+    }
+};
+
+typedef IceUtil::Handle<ICEAgentImpl> ICEAgentImplPtr;
+
+class ICECallbackAdapter
+{
+public:
+    static void addEntry(pjmedia_transport* transport, const ICETransportPtr& callback);
+    static void addAgent(pjmedia_transport* transport, const ICEAgentImplPtr& agent);
+    static void removeEntry(pjmedia_transport* transport);
+    static void onICEComplete(pjmedia_transport* transport, pj_ice_strans_op operation, pj_status_t status);
+
+    struct CallbackRecord
+    {
+        bool connected;
+        ICETransportPtr transport;
+        ICEAgentImplPtr agent;
+
+        CallbackRecord() :
+            connected(false)
+        {
+        }
+    };
+    typedef std::map<unsigned long long, CallbackRecord> TransportMap;
+
+private:
+    static TransportMap mTransportMap;
+    static boost::shared_mutex mLock;
+};
+
+//
+// Static member initializations.
+//
+ICECallbackAdapter::TransportMap ICECallbackAdapter::mTransportMap;
+boost::shared_mutex ICECallbackAdapter::mLock;
+
+//
+// For some reason the ICE media transport doesn't have the concept of associating user data with a transport, so we
+// have to map it "out of band". The problem is, there is a race condition in that the ICE completion callack could be
+// invoked before we get a chance to add the transport.  The solution to that is to allow an entry to be created when
+// 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.
+// 
+void ICECallbackAdapter::addEntry(pjmedia_transport* transport, const ICETransportPtr& callback)
+{
+    bool alreadyKnown = false;
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+        TransportMap::iterator i = mTransportMap.find(reinterpret_cast<unsigned long long>(transport));
+        if (i != mTransportMap.end())
+        {
+            i->second.transport = callback;
+            alreadyKnown = true;
+            callback->onSetupComplete(transport, PJ_SUCCESS);
+
+            if (i->second.agent)
+            {
+                i->second.agent->onSetupComplete(transport, PJ_SUCCESS);
+            }
+        }
+        else
+        {
+            CallbackRecord r;
+            r.connected = false;
+            r.transport = callback;
+            mTransportMap.insert(make_pair(reinterpret_cast<unsigned long long>(transport), r));
+        }
+    }
+}
+
+void ICECallbackAdapter::addAgent(pjmedia_transport* transport, const ICEAgentImplPtr& agent)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    TransportMap::iterator i = mTransportMap.find(reinterpret_cast<unsigned long long>(transport));
+
+    if (i != mTransportMap.end())
+    {
+        i->second.agent = agent;
+        if (i->second.connected == true && i->second.transport.get() != 0)
+        {
+            try
+            {
+                agent->onSetupComplete(transport, PJ_SUCCESS);
+            }
+            catch(const invalid_argument& ex)
+            {
+                logger(Error) << "Agent added to map but the setup seems incorrect: " << ex.what();
+            }
+        }
+    }
+    //
+    // The entry really should always be found, but there could be a race
+    // condition if things are shutting down before everything was cleanly
+    // activated.
+    //
+}
+
+void ICECallbackAdapter::removeEntry(pjmedia_transport* t)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    TransportMap::iterator i = mTransportMap.find(reinterpret_cast<unsigned long long>(t));
+    if (i != mTransportMap.end())
+    {
+        if (i->second.agent)
+        {
+            i->second.agent->shutdown();
+        }
+        mTransportMap.erase(i);
+    }
+}
+
+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)
+    {
+        case PJ_ICE_STRANS_OP_INIT:
+            //
+            // Initialization is complete. At this point we know what candidates we can offer.
+            //
+            {
+                boost::unique_lock<boost::shared_mutex> lock(mLock);
+                TransportMap::iterator i = mTransportMap.find(reinterpret_cast<unsigned long long>(transport));
+                if (i == mTransportMap.end())
+                {
+                    CallbackRecord r;
+                    r.connected = success(status);
+                    mTransportMap.insert(make_pair(reinterpret_cast<unsigned long long>(transport), r));
+                }
+                else
+                {
+                    i->second.connected = success(status);
+                    i->second.transport->onSetupComplete(transport, status);
+                    if (i->second.agent)
+                    {
+                        i->second.agent->onSetupComplete(transport, status);
+                    }
+                }
+            }
+            break;
... 9044 lines suppressed ...


-- 
asterisk-scf/integration/media_transport_udptl.git



More information about the asterisk-scf-commits mailing list