[asterisk-scf-commits] asterisk-scf/release/media_rtp_pjmedia.git branch "master" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Wed Jul 20 12:47:33 CDT 2011


branch "master" has been updated
       via  af994c8365ccb27170e6fd1976c4974f40ade216 (commit)
      from  e495e075f2f28738b0d8236dd76b353316240f41 (commit)

Summary of changes:
 config/RtpConfigurator.py                          |   32 +
 .../{test_component.config => test_rtp_ice.config} |   24 +-
 .../MediaRTPPJMedia/RtpConfigurationIf.ice         |  377 ++++++----
 .../MediaRTPPJMedia/RtpStateReplicationIf.ice      |    4 +
 src/CMakeLists.txt                                 |   29 +-
 src/Configuration.h                                |   57 ++
 src/ICEConfiguration.cpp                           |   32 +
 src/ICEConfiguration.h                             |   68 ++
 src/ICETransport.cpp                               |  775 ++++++++++++++++++++
 src/ICETransport.h                                 |   90 +++
 src/MediaRTPpjmedia.cpp                            |  136 +++-
 src/NATConfig.cpp                                  |   50 ++
 src/NATConfig.h                                    |   76 ++
 src/NATModule.cpp                                  |   84 +++
 src/NATModule.h                                    |   63 ++
 src/PJLibConfiguration.cpp                         |   32 +
 src/PJLibConfiguration.h                           |   65 ++
 src/PJMediaEndpoint.cpp                            |   45 ++
 src/PJMediaEndpoint.h                              |   60 ++
 src/PJMediaEnvironment.cpp                         |   56 ++
 src/PJMediaEnvironment.h                           |  132 ++++
 src/PJMediaTransport.cpp                           |   83 +++
 src/PJMediaTransport.h                             |   74 ++
 src/PJUtil.h                                       |   49 ++
 src/RTPConfiguration.cpp                           |  594 +++++++++++++---
 src/RTPConfiguration.h                             |   41 +-
 src/RTPSession.cpp                                 |  573 ++++++++++-----
 src/RTPSession.h                                   |   98 +--
 src/RTPSink.cpp                                    |   92 ++--
 src/RTPSink.h                                      |   20 +-
 src/RTPSource.cpp                                  |   83 ++-
 src/RTPSource.h                                    |   14 +-
 src/ReplicationAdapter.h                           |   43 ++
 src/RtpStateReplicator.h                           |   10 +-
 src/RtpStateReplicatorApp.cpp                      |    1 +
 src/RtpStateReplicatorListener.cpp                 |   61 +-
 src/SRTPConfiguration.cpp                          |   55 ++
 src/SRTPConfiguration.h                            |   74 ++
 src/SRTPTransport.cpp                              |  110 +++
 src/SRTPTransport.h                                |   68 ++
 src/SessionAdapter.h                               |   60 ++
 src/UDPTransport.cpp                               |   86 +++
 src/UDPTransport.h                                 |   68 ++
 test/CMakeLists.txt                                |   11 +
 test/TestRTPICE.cpp                                |  368 ++++++++++
 45 files changed, 4362 insertions(+), 661 deletions(-)
 copy config/{test_component.config => test_rtp_ice.config} (71%)
 create mode 100755 src/Configuration.h
 create mode 100644 src/ICEConfiguration.cpp
 create mode 100644 src/ICEConfiguration.h
 create mode 100644 src/ICETransport.cpp
 create mode 100644 src/ICETransport.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/PJMediaEndpoint.cpp
 create mode 100644 src/PJMediaEndpoint.h
 create mode 100644 src/PJMediaEnvironment.cpp
 create mode 100644 src/PJMediaEnvironment.h
 create mode 100644 src/PJMediaTransport.cpp
 create mode 100644 src/PJMediaTransport.h
 create mode 100644 src/PJUtil.h
 create mode 100644 src/ReplicationAdapter.h
 create mode 100644 src/SRTPConfiguration.cpp
 create mode 100644 src/SRTPConfiguration.h
 create mode 100644 src/SRTPTransport.cpp
 create mode 100644 src/SRTPTransport.h
 create mode 100644 src/SessionAdapter.h
 create mode 100644 src/UDPTransport.cpp
 create mode 100644 src/UDPTransport.h
 create mode 100644 test/TestRTPICE.cpp


- Log -----------------------------------------------------------------
commit af994c8365ccb27170e6fd1976c4974f40ade216
Author: Brent Eagles <beagles at digium.com>
Date:   Wed Jul 20 15:11:57 2011 -0230

    Changes for SRTP and NAT traversal support as well as some refactoring:
    
        - configurator
        - added and implemented interface for "kicking" off media transport once
           offer/answer negotiation was completed
        - discovery changes to include srtp support in query.
        - Added an "environment class" that contains accessors to feature
          specific configuration classes and instance wide pjmedia/pjlib
          constructs.
        - Created a base class, PJMediaTransport, to wrap/provide common
          functionality.
        - Moved UDP specific code to be provided by the PJMediaTransport base class,
          UDPTransport. Amongst other things, it provides support for adding
          transport specific facets to the related session object.
        - Added another subclass of the PJMediaTransport based on instantiating
          a pjmedia provide ICE transport. This overrides the localAddress accessor
          of the base class to return the result of the STUN binding request
          performed by the ICE transport.
        - Added another subclass of PJMediaTransport for instantiating the
          pjmedia provided SRTP transport. This transport
          basically is a "wrapper" around the actual implementation transport.
        - Added an implementation of InteractiveConnectionAgent that is
          added as a facet when the the related RTPSession servant is activated.
        - Added support for generating AsteriskSCF::System::NAT::Candidate instances
          from the candidate data provided by the ICE session. These are
          made available through the InteractiveConnectionAgent facet.
          NOTE: there are a lot of details in the various RFCs that may require
          modification not just the generation of these objects, but when they
          can be properly created. It may also require a listener to notify
          "users" of the media session of changes to the candidate list, etc.
        - Added "adapter" interfaces to break the physical dependency between
          the RTPSession implementation and the related sources and sinks as
          well as the replication listener.
        - Added new configuration elements for the ICE transport.
        - Added a short test suite (incomplete) that directly manipulates some
          of the ICE related functionality... much more is necessary really.

diff --git a/config/RtpConfigurator.py b/config/RtpConfigurator.py
index 018a1e0..a0f7ab7 100755
--- a/config/RtpConfigurator.py
+++ b/config/RtpConfigurator.py
@@ -46,6 +46,38 @@ class RtpSectionVisitors(Configurator.SectionVisitors):
         ipv6BindingItem = AsteriskSCF.Configuration.MediaRTPPJMedia.V1.BindingIPv6Item()
         mapper.map('ipv6bind', ipv6BindingItem, 'address', AsteriskSCF.Configuration.MediaRTPPJMedia.V1.BindingIPv6AddressItemName, config.get, None)
 
+        srtpEnableItem = AsteriskSCF.Configuration.MediaRTPPJMedia.V1.EnableSRTPItem()
+        mapper.map('enablesrtp', srtpEnableItem, 'enabled', AsteriskSCF.Configuration.MediaRTPPJMedia.V1.EnableSRTPItemName, config.get, True)
+
+        for option in config.options(section):
+            mapper.execute(group, section, option)
+
+        mapper.finish(group)
+
+        self.groups.append(group)
+
+    def visit_rtpoverice(self, config, section):
+        group = AsteriskSCF.Configuration.MediaRTPPJMedia.V1.RTPICEConfigurationGroup()
+        group.configurationItems = { }
+
+        mapper = Configurator.OptionMapper()
+
+        stunServerItem = AsteriskSCF.Configuration.MediaRTPPJMedia.V1.STUNServerItem()
+        mapper.map('stunserverhost', stunServerItem, 'address', AsteriskSCF.Configuration.MediaRTPPJMedia.V1.STUNServerItemName, config.get, None)
+        mapper.map('stunserverport', stunServerItem, 'port', AsteriskSCF.Configuration.MediaRTPPJMedia.V1.STUNServerItemName, config.getint, 3478)
+        
+        turnServerItem = AsteriskSCF.Configuration.MediaRTPPJMedia.V1.TURNServerItem()
+        mapper.map('turnserverhost', turnServerItem, 'address', AsteriskSCF.Configuration.MediaRTPPJMedia.V1.TURNServerItemName, config.get, None)
+        mapper.map('turnserverport', turnServerItem, 'port', AsteriskSCF.Configuration.MediaRTPPJMedia.V1.TURNServerItemName, config.getint, 3478)
+
+        rtpOverICEItem = AsteriskSCF.Configuration.MediaRTPPJMedia.V1.RTPICETransportFlagsItem()
+        mapper.map('rtpovericeenable', rtpOverICEItem, 'enableICE', AsteriskSCF.Configuration.MediaRTPPJMedia.V1.RTPICETransportFlagsItemName, config.get, None)
+        mapper.map('rtpovericewithturn', rtpOverICEItem, 'enableTURN', AsteriskSCF.Configuration.MediaRTPPJMedia.V1.RTPICETransportFlagsItemName, config.get, None)
+
+        rtpICELimits = AsteriskSCF.Configuration.MediaRTPPJMedia.V1.RTPICETransportLimitsItem()
+        mapper.map('rtpicemaxcandidates', rtpICELimits, 'maxCandidates', AsteriskSCF.Configuration.MediaRTPPJMedia.V1.RTPICELimitsItemName, config.getint, 10)
+        mapper.map('rtpicemaxcalls', rtpICELimits, 'maxCalls', AsteriskSCF.Configuration.MediaRTPPJMedia.V1.RTPICELimitsItemName, config.getint, 50)
+
         for option in config.options(section):
             mapper.execute(group, section, option)
 
diff --git a/config/test_rtp_ice.config b/config/test_rtp_ice.config
new file mode 100644
index 0000000..adb150b
--- /dev/null
+++ b/config/test_rtp_ice.config
@@ -0,0 +1,74 @@
+# This is a configuration file used in conjunction with the media_rtp_pjmedia test driver
+
+#
+# Icebox Configuration
+#
+RtpConfiguration.Name=rtpoice
+IceBox.InheritProperties=1
+IceBox.LoadOrder=ServiceDiscovery,MediaRTPpjmedia,MediaRTPpjmediaTest
+
+# RtpStateReplicator Configuration
+
+# Adapter parameters for this component
+RtpStateReplicator.Endpoints=tcp:udp
+
+# A proxy to the service locator management service
+LocatorServiceManagement.Proxy=LocatorServiceManagement:tcp -p 4422
+
+# A proxy to the service locator service
+LocatorService.Proxy=LocatorService:tcp -p 4411
+
+#
+# media_rtp_pjmedia Configuration
+#
+
+IceBox.Service.MediaRTPpjmedia=media_rtp_pjmedia:create
+
+# Adapter parameters for this component
+MediaRTPpjmediaAdapter.Endpoints=default
+MediaRTPpjmediaAdapterLocal.Endpoints=default
+MediaRTPpjmediaAdapterLogger.Endpoints=default
+
+# A proxy to the service locator management service
+ServiceLocatorManagementProxy=LocatorServiceManagement:tcp -p 4422
+
+# A proxy to the service locator service
+ServiceLocatorProxy=LocatorService:tcp -p 4411
+
+#
+# media_rtp_pjmedia_test Configuration
+#
+
+IceBox.Service.MediaRTPpjmediaTest=media_rtp_pjmedia_ice_test:create
+
+#
+# Service Locator Configuration
+#
+
+IceBox.Service.ServiceDiscovery=service_locator:create
+
+AsteriskSCFIceStorm.InstanceName=AsteriskSCFIceStorm
+AsteriskSCFIceStorm.TopicManager.Endpoints=default -p 10000
+AsteriskSCFIceStorm.Publish.Endpoints=tcp -p 10001:udp -p 10001
+AsteriskSCFIceStorm.Trace.TopicManager=2
+AsteriskSCFIceStorm.Transient=1
+AsteriskSCFIceStorm.Flush.Timeout=2000
+TopicManager.Proxy=AsteriskSCFIceStorm/TopicManager:default -p 10000
+
+#RtpStateReplicatorIceStorm.InstanceName=RtpStateReplicatorIceStorm
+#RtpStateReplicatorIceStorm.TopicManager.Endpoints=default -p 10005
+#RtpStateReplicatorIceStorm.Publish.Endpoints=default -p 10006
+#RtpStateReplicatorIceStorm.Trace.TopicManager=2
+#RtpStateReplicatorIceStorm.Transient=1
+#RtpStateReplicatorIceStorm.Flush.Timeout=2000
+#RtpStateReplicatorTopicManager.Proxy=RtpStateReplicatorIceStorm/TopicManager:default -p 10005
+
+ServiceLocatorManagementAdapter.Endpoints=tcp -p 4422
+ServiceLocatorAdapter.Endpoints=tcp -p 4411
+ServiceLocatorLocalAdapter.Endpoints=tcp -p 4412
+LocatorService.Proxy=LocatorService:tcp -p 4411
+
+LoggerAdapter.Endpoints=default
+Ice.ThreadPool.Client.Size=4
+Ice.ThreadPool.Server.Size=4
+Rtp.Standalone=true
diff --git a/slice/AsteriskSCF/Configuration/MediaRTPPJMedia/RtpConfigurationIf.ice b/slice/AsteriskSCF/Configuration/MediaRTPPJMedia/RtpConfigurationIf.ice
index 7f41167..1198f65 100644
--- a/slice/AsteriskSCF/Configuration/MediaRTPPJMedia/RtpConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/MediaRTPPJMedia/RtpConfigurationIf.ice
@@ -16,7 +16,6 @@
 
 #pragma once
 
-#include <Ice/BuiltinSequences.ice>
 #include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.ice>
 #include <AsteriskSCF/System/Component/ConfigurationIf.ice>
 
@@ -32,145 +31,243 @@ module MediaRTPPJMedia
 ["suppress"]
 module V1
 {
-   /**
-    * Service locator category for finding the configuration service
-    */
-   const string ConfigurationDiscoveryCategory = "RtpConfiguration";
-
-   /**
-    * Service locator parameters class for discovering the configuration service
-    */
-   unsliceable class RtpConfigurationParams extends AsteriskSCF::Core::Discovery::V1::ServiceLocatorParams
-   {
-       /**
-	* Unique name for the configuration service
-	*/
-       string name;
-   };
-
-   /**
-    * Local visitor class for visiting RTP configuration groups
-    */
-   local class RtpConfigurationGroupVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationGroupVisitor
-   {
-   };
-
-   /**
-    * Generic RTP configuration group
-    */
-   ["visitor:RtpConfigurationGroupVisitor"] class RtpConfigurationGroup extends AsteriskSCF::System::Configuration::V1::ConfigurationGroup
-   {
-   };
-
-   /**
-    * General RTP configuration group that contains general items related to the RTP component as a whole
-    */
-   class RtpGeneralGroup extends RtpConfigurationGroup
-   {
-   };
-
-   /**
-    * Local visitor class for visiting RTP configuration items
-    */
-   local class RtpConfigurationItemVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationItemVisitor
-   {
-   };
-
-   /**
-    * Generic RTP configuration item
-    */
-   ["visitor:RtpConfigurationItemVisitor"] class RtpConfigurationItem extends AsteriskSCF::System::Configuration::V1::ConfigurationItem
-   {
-   };
-
-   /**
-    * Name that the port ranges configuration item should be inserted as
-    */
-   const string PortRangesItemName = "ports";
-
-   /**
-    * Port ranges configuration item
-    *
-    * This must be added to the general configuration group using the constant string
-    * in PortRangesItemName
-    *
-    */
-   class PortRangesItem extends RtpConfigurationItem
-   {
-       /**
-	* Start port for RTP and RTCP sockets.
-	*
-	* Default value is 10000.
-	*
-	*/
-       int startPort = 10000;
-
-       /**
-	* End port for RTP and RTCP sockets.
-	*
-	* Default value is 20000.
-	*
-	*/
-       int endPort = 20000;
-   };
-
-   /**
-    * Name that the worker thread count configuration item should be inserted as
-    */
-   const string WorkerThreadCountItemName = "workerThreadCount";
-
-   /**
-    * Worker thread count for incoming media configuration item
-    *
-    * This must be added to the general configuration group using the constant string
-    * in WorkerThreadCountItemName
-    *
-    */
-   class WorkerThreadCountItem extends RtpConfigurationItem
-   {
-       /**
-	* Number of threads that should handle incoming media.
-	*
-	* Default value is 4.
-	*/
-       int count = 4;
-   };
-
-   /**
-    * Name that the IPv4 binding configuration item should be inserted as
-    */
-   const string BindingIPv4AddressItemName = "bindingIPv4";
-
-   /**
-    * Binding address for IPv4 traffic
-    */
-   class BindingIPv4Item extends RtpConfigurationItem
-   {
-       /**
-	* Address that IPv4 sessions should be binded to.
-	*
-	* Default value is all.
-	*/
-       string address;
-   };
-
-   /**
-    * Name that the IPv6 binding configuration item should be inserted as
-    */
-   const string BindingIPv6AddressItemName = "bindingIPv6";
-
-   /**
-    * Binding address for IPv6 traffic
-    */
-   class BindingIPv6Item extends RtpConfigurationItem
-   {
-       /**
-	* Address that IPv6 sessions should be binded to.
-	*
-	* Default value is all.
-	*/
-       string address;
-   };
+    /**
+     * Service locator category for finding the configuration service
+     */
+    const string ConfigurationDiscoveryCategory = "RtpConfiguration";
+
+    /**
+     * Service locator parameters class for discovering the configuration service
+     */
+    unsliceable class RtpConfigurationParams extends AsteriskSCF::Core::Discovery::V1::ServiceLocatorParams
+    {
+        /**
+         * Unique name for the configuration service
+         */
+        string name;
+    };
+
+    /**
+     * Local visitor class for visiting RTP configuration groups
+     */
+    local class RtpConfigurationGroupVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationGroupVisitor
+    {
+    };
+
+    /**
+     * Generic RTP configuration group
+     */
+    ["visitor:RtpConfigurationGroupVisitor"] class RtpConfigurationGroup extends AsteriskSCF::System::Configuration::V1::ConfigurationGroup
+    {
+    };
+
+    /**
+     * General RTP configuration group that contains general items related to the RTP component as a whole
+     */
+    class RtpGeneralGroup extends RtpConfigurationGroup
+    {
+    };
+
+    /**
+     * Local visitor class for visiting RTP configuration items
+     */
+    local class RtpConfigurationItemVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationItemVisitor
+    {
+    };
+
+    /**
+     * Generic RTP configuration item
+     */
+    ["visitor:RtpConfigurationItemVisitor"] class RtpConfigurationItem extends AsteriskSCF::System::Configuration::V1::ConfigurationItem
+    {
+    };
+
+    /**
+     * Name that the port ranges configuration item should be inserted as
+     */
+    const string PortRangesItemName = "ports";
+
+    /**
+     * Port ranges configuration item
+     *
+     * This must be added to the general configuration group using the constant string
+     * in PortRangesItemName
+     *
+     */
+    class PortRangesItem extends RtpConfigurationItem
+    {
+        /**
+         * Start port for RTP and RTCP sockets.
+         *
+         * Default value is 10000.
+         *
+         */
+        int startPort = 10000;
+
+        /**
+         * End port for RTP and RTCP sockets.
+         *
+         * Default value is 20000.
+         *
+         */
+        int endPort = 20000;
+    };
+
+    /**
+     * Name that the SRTP flag configuration item should be inserted as
+     **/
+    const string EnableSRTPItemName = "srtpEnable";
+
+    /**
+     *
+     * Enable SRTP on the current transport.
+     *
+     **/
+    class EnableSRTPItem extends RtpConfigurationItem
+    {
+        /**
+         * Flag to enable SRTP.
+         **/
+        bool enabled;
+    };
+
+    /**
+     * Name that the worker thread count configuration item should be inserted as
+     */
+    const string WorkerThreadCountItemName = "workerThreadCount";
+
+    /**
+     * Worker thread count for incoming media configuration item
+     *
+     * This must be added to the general configuration group using the constant string
+     * in WorkerThreadCountItemName
+     *
+     */
+    class WorkerThreadCountItem extends RtpConfigurationItem
+    {
+        /**
+         * Number of threads that should handle incoming media.
+         *
+         * Default value is 4.
+         */
+        int count = 4;
+    };
+
+    /**
+     * Name that the IPv4 binding configuration item should be inserted as
+     */
+    const string BindingIPv4AddressItemName = "bindingIPv4";
+
+    /**
+     * Binding address for IPv4 traffic
+     */
+    class BindingIPv4Item extends RtpConfigurationItem
+    {
+        /**
+         * Address that IPv4 sessions should be binded to.
+         *
+         * Default value is all.
+         */
+        string address;
+    };
+
+    /**
+     * Name that the IPv6 binding configuration item should be inserted as
+     */
+    const string BindingIPv6AddressItemName = "bindingIPv6";
+
+    /**
+     * Binding address for IPv6 traffic
+     */
+    class BindingIPv6Item extends RtpConfigurationItem
+    {
+        /**
+         * Address that IPv6 sessions should be binded to.
+         *
+         * Default value is all.
+         */
+        string address;
+    };
+
+    /*
+     * Configuration group for ICE enabled RTP.
+     */
+    class RTPICEConfigurationGroup extends RtpConfigurationGroup
+    {
+    };
+
+    /**
+     * Name that the STUN server configuration item should be inserted as.
+     */
+    const string STUNServerItemName = "stunServer";
+
+    /**
+     * Hostname for the STUN server.
+     */
+    class STUNServerItem extends RtpConfigurationItem
+    {
+        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 RtpConfigurationItem
+    {
+        string address;
+        int port;
+    };
+
+    /**
+     * Name that the ICE transport configuration flags item should be inserted as.
+     */
+    const string RTPICETransportFlagsItemName = "iceFlags";
+
+    /**
+     * Configuration item with option flags for the ICE transport.
+     */
+    class RTPICETransportFlagsItem extends RtpConfigurationItem
+    {
+        /**
+         * 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 RTPICELimitsItemName = "iceLimits";
+
+    /**
+     * Configuration item for configurable limits for the ICE transport.
+     */
+    class RTPICETransportLimitsItem extends RtpConfigurationItem
+    {
+        /**
+         * The maximum number of candidates to gather and publish.
+         */
+        int maxCandidates;
+
+        /**
+         * The maximum number of ICE negotiated flows to allow.
+         */
+        int maxCalls;
+    };
 
 }; /* module V1 */
 
diff --git a/slice/AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice b/slice/AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice
index b9b08d7..ff9d0d2 100644
--- a/slice/AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice
+++ b/slice/AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice
@@ -78,6 +78,9 @@ module V1
 	string mComparatorId;
     };
 
+    /**
+     * TODO: Data members in Slice defined classes should not have `m' prefixes.
+     */
     class RtpSessionStateItem extends RtpStateItem
     {
 	Ice::Identity mSessionIdentity;
@@ -87,6 +90,7 @@ module V1
 	AsteriskSCF::Media::V1::FormatSeq mFormats;
 	AsteriskSCF::Media::RTP::V1::PayloadMap mPayloadstoFormats;
 	bool mIPv6;
+        bool mSRTP;
     };
 
     class RtpStreamSinkStateItem extends RtpStateItem
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3909e11..13185bd 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -13,12 +13,39 @@ astscf_component_add_files(media_rtp_pjmedia RtpStateReplicatorListener.cpp)
 astscf_component_add_files(media_rtp_pjmedia RtpStateReplicator.h)
 astscf_component_add_files(media_rtp_pjmedia RTPConfiguration.cpp)
 astscf_component_add_files(media_rtp_pjmedia RTPConfiguration.h)
+astscf_component_add_files(media_rtp_pjmedia PJLibConfiguration.cpp)
+astscf_component_add_files(media_rtp_pjmedia PJLibConfiguration.h)
+astscf_component_add_files(media_rtp_pjmedia PJMediaEnvironment.cpp)
+astscf_component_add_files(media_rtp_pjmedia PJMediaEnvironment.h)
+astscf_component_add_files(media_rtp_pjmedia PJMediaTransport.cpp)
+astscf_component_add_files(media_rtp_pjmedia PJMediaTransport.h)
+astscf_component_add_files(media_rtp_pjmedia PJMediaEndpoint.cpp)
+astscf_component_add_files(media_rtp_pjmedia PJMediaEndpoint.h)
+astscf_component_add_files(media_rtp_pjmedia UDPTransport.cpp)
+astscf_component_add_files(media_rtp_pjmedia UDPTransport.h)
+astscf_component_add_files(media_rtp_pjmedia PJUtil.h)
+astscf_component_add_files(media_rtp_pjmedia ReplicationAdapter.h)
+astscf_component_add_files(media_rtp_pjmedia SessionAdapter.h)
+astscf_component_add_files(media_rtp_pjmedia Configuration.h)
+astscf_component_add_files(media_rtp_pjmedia NATConfig.cpp)
+astscf_component_add_files(media_rtp_pjmedia NATConfig.h)
+astscf_component_add_files(media_rtp_pjmedia NATModule.cpp)
+astscf_component_add_files(media_rtp_pjmedia NATModule.h)
+astscf_component_add_files(media_rtp_pjmedia ICEConfiguration.cpp)
+astscf_component_add_files(media_rtp_pjmedia ICEConfiguration.h)
+astscf_component_add_files(media_rtp_pjmedia ICETransport.cpp)
+astscf_component_add_files(media_rtp_pjmedia ICETransport.h)
+astscf_component_add_files(media_rtp_pjmedia SRTPConfiguration.cpp)
+astscf_component_add_files(media_rtp_pjmedia SRTPConfiguration.h)
+astscf_component_add_files(media_rtp_pjmedia SRTPTransport.cpp)
+astscf_component_add_files(media_rtp_pjmedia SRTPTransport.h)
 astscf_component_add_slices(media_rtp_pjmedia PROJECT AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice)
 astscf_component_add_slices(media_rtp_pjmedia PROJECT AsteriskSCF/Configuration/MediaRTPPJMedia/RtpConfigurationIf.ice)
 astscf_component_add_boost_libraries(media_rtp_pjmedia core thread)
 astscf_component_add_slice_collection_libraries(media_rtp_pjmedia ASTSCF)
 astscf_component_build_icebox(media_rtp_pjmedia)
-target_link_libraries(media_rtp_pjmedia logging-client)
+target_link_libraries(media_rtp_pjmedia logging-client astscf-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/Configuration.h b/src/Configuration.h
new file mode 100755
index 0000000..dbe7f25
--- /dev/null
+++ b/src/Configuration.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 "PJLibConfiguration.h"
+#include "NATConfig.h"
+#include "ICEConfiguration.h"
+#include "SRTPConfiguration.h"
+
+#include <Ice/PropertiesF.h>
+#include <string>
+#include <IceUtil/Shared.h>
+
+namespace AsteriskSCF
+{
+namespace PJMediaRTP
+{
+
+/**
+ * Base class for objects providing RTP service specific configuration data.
+ */
+
+class RTPConfiguration : public virtual IceUtil::Shared
+{
+public:
+    virtual ~RTPConfiguration() {}
+
+    virtual PJLibConfigurationPtr libConfig() const = 0;
+    virtual NATConfigPtr natConfig() const = 0;
+    virtual ICEConfigurationPtr ICEConfig() const = 0;
+    virtual SRTPConfigurationPtr srtpConfig() const = 0;
+
+    virtual int getStartPort() = 0;
+    virtual int getEndPort() = 0;
+    virtual int getWorkerThreadCount() = 0;
+    virtual std::string getBindIPv4Address() = 0;
+    virtual std::string getBindIPv6Address() = 0;
+};
+
+typedef IceUtil::Handle<RTPConfiguration> RTPConfigurationPtr;
+
+} /* End of namespace PJMediaRTP */
+} /* End of namespace AsteriskSCF */
diff --git a/src/ICEConfiguration.cpp b/src/ICEConfiguration.cpp
new file mode 100644
index 0000000..4ea0aaf
--- /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::PJMediaRTP;
+
+ICEConfigurationPtr AsteriskSCF::PJMediaRTP::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..450d4df
--- /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 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. 
+ **/
+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 PJMediaRTP */
+} /* End of namespace AsteriskSCF */
diff --git a/src/ICETransport.cpp b/src/ICETransport.cpp
new file mode 100644
index 0000000..b1ef798
--- /dev/null
+++ b/src/ICETransport.cpp
@@ -0,0 +1,775 @@
+/*
+ * 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::PJMediaRTP;
+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.MediaRTP");
+}
+
+namespace 
+{
+
+class ICEAgentImpl : public InteractiveConnectionAgent
+{
+public:
+
+    ICEAgentImpl(const Ice::ObjectAdapterPtr& adapter, const Ice::Identity& id) :
+        mAdapter(adapter),
+        mId(id),
+        mShuttingDown(false),
+        mNATType(AsteriskSCF::System::NAT::V1::Unknown),
+        mRole(UndefinedRole),
+        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);
+            mTransport = transport;
+            if (iceInfo->role == PJ_ICE_SESS_ROLE_CONTROLLING)
+            {
+                setRole(Controlling);
+            }
+            else
+            {
+                setRole(Controlled);
+            }
+
+            //
+            // 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;
+            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->baseAddress = baseAddress;
+                            candidateObj->basePort = basePort; 
+                        }
+                        else
+                        {
+                            candidateObj->baseAddress = candidateObj->mappedAddress;
+                            candidateObj->basePort = candidateObj->mappedPort;
+                        }
+                        //
+                        // 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)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+        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;
+    };
+    typedef std::map<pjmedia_transport*, 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)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    TransportMap::iterator i = mTransportMap.find(transport);
+    if (i != mTransportMap.end())
+    {
+        i->second.transport = callback;
+        callback->onSetupComplete(transport, PJ_SUCCESS);
+    }
+    else
+    {
+        CallbackRecord r;
+        r.connected = false;
+        r.transport = callback;
+        mTransportMap.insert(make_pair(transport, r));
+    }
+}
+
+void ICECallbackAdapter::addAgent(pjmedia_transport* transport, const ICEAgentImplPtr& agent)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    TransportMap::iterator i = mTransportMap.find(transport);
+
+    if (i != mTransportMap.end())
+    {
+        i->second.agent = agent;
+        if (i->second.connected)
+        {
+            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(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(transport);
+                if (i == mTransportMap.end())
+                {
+                    CallbackRecord r;
+                    r.connected = success(status);
+                    mTransportMap.insert(make_pair(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;
+        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())
+                {
+                    assert(false);
+                    //
+                    // This is a problem, it is very unlikely that this should
+                    // happen when things are working as they should.
+                    //
+                }
+                else
+                {
+                    //
+                    // We've negotiated a valid flow with on this leg. We should query every
+                    // detail of relevance from the current media session.
+                    //
+                    if (i->second.agent)
+                    {
+                        i->second.agent->onSetupComplete(transport, status);
+                    }
+                }
+            }
+            break;
+        case PJ_ICE_STRANS_OP_KEEP_ALIVE:
+            //
+            // Keep alive has successfully completed. FWICT this should not get here.
+            // 
+            break;
+    };
+}
+
+}
+
+ICETransport::~ICETransport()
+{
+    //
+    // TODO : cleanup ICE transport, the transport itself is closed by the parent class.
+    // 
+    ICECallbackAdapter::removeEntry(mTransport);
+}
+
+void ICETransport::onSetupComplete(pjmedia_transport* transport, int status)
+{
+    if (fail(status))
+    {
+        //
+        // TODO!
+        //
+        return;
+    }
+
+    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);
+        }
+    }
+
+    if (iceInfo != 0 && iceInfo->role == PJ_ICE_SESS_ROLE_CONTROLLING)
+    {
+        if (mLastKnownAddr && pj_sockaddr_cmp(&info.sock_info.rtp_addr_name, mLastKnownAddr.get()))
+        {
+            //
+            // Address has changed! We need to let Session listeners know!
+            // TODO! 
+            //
+            pj_memcpy(mLastKnownAddr.get(), &info.sock_info.rtp_addr_name, sizeof(pj_sockaddr));
+        }
+    }
+    boost::unique_lock<boost::mutex> lock(mLock);
+    mLocalAddress = fromInfo(info);
+    mMonitor.notify_one();
+}
+
+AddressPtr ICETransport::localAddress() 
+{
+    boost::unique_lock<boost::mutex> lock(mLock);
+    if (mLocalAddress)
+    {
+        return mLocalAddress;
+    }
+    for (size_t i = 0; i < 5 && !mLocalAddress; ++i)
+    {
+        mMonitor.wait(lock);
+    }
+    return mLocalAddress;
+}
+
+AddressPtr ICETransport::remoteAddress() 
+{
+    boost::unique_lock<boost::mutex> lock(mLock);
+    return mRemoteAddress;
+}
+
+void ICETransport::addFacets(const Ice::ObjectAdapterPtr& adapter, const Ice::Identity& id)
+{
+    ICEAgentImplPtr agent = new ICEAgentImpl(adapter, id);
+    ICECallbackAdapter::addAgent(mTransport, agent);
+    adapter->addFacet(agent, id, InteractiveConnectionAgentFacetName);
+}
+
+ICETransportPtr ICETransport::create(const PJMediaEndpointPtr& ep, const PJMediaEnvironmentPtr& config)
+{
+    ICETransportPtr transport(new ICETransport(ep, config));
+    transport->start();
+
+    //
+    // TODO: I need to temporarily insert a wait-until-fail loop for the ICE steps so the transport information
+    // is available when the transport create call returns. The source/sink's won't have valid information until then.
+    //
+    return transport;
+}
+
+ICETransport::ICETransport(const PJMediaEndpointPtr& ep, const PJMediaEnvironmentPtr& configObject) :
+    PJMediaTransport(0),
+    mEndpoint(ep),
+    mConfig(configObject),
+    mEnableRTCP(false)
+{
+}
+
+void ICETransport::start()
+{
+    pjmedia_transport* t;
+    PJICECallbackPtr callback(new pjmedia_ice_cb);
+    callback->on_ice_complete = &ICECallbackAdapter::onICEComplete;
+    NATModulePtr natModule = NATModule::create(mConfig, mEndpoint);
+    pj_status_t result = pjmedia_ice_create(mEndpoint->endpoint(), "ASCF_ICE_MEDIA", (mEnableRTCP ? 2 : 1), 
+        natModule->configuration(), callback.get(), &t);
+    if (fail(result))
+    {
+        throw InternalInitializationException("Unable to create new ICE media transport");
+    }
+    ICECallbackAdapter::addEntry(t, shared_from_this());
+    mTransport = t;
+    mCallback = callback;
+    mNATModule = natModule;
+}
diff --git a/src/ICETransport.h b/src/ICETransport.h
new file mode 100644
index 0000000..678a830
--- /dev/null
+++ b/src/ICETransport.h
@@ -0,0 +1,90 @@
+/*
+ * 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 "PJMediaTransport.h"
+#include "PJMediaEndpoint.h"
+#include "PJMediaEnvironment.h"
+#include <Ice/PropertiesF.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include "NATModule.h"
+
+//
+// Forward declarations.
+// 
+struct pjmedia_transport;
+union pj_sockaddr;
+struct pjmedia_ice_cb;
+
+namespace AsteriskSCF
+{
+namespace PJMediaRTP
+{
+
+class ICETransport;
+typedef boost::shared_ptr<ICETransport> ICETransportPtr;
+typedef boost::shared_ptr<pjmedia_ice_cb> PJICECallbackPtr;
+typedef boost::shared_ptr<pj_sockaddr> PJSockAddrPtr;
+
+class ICETransport : public boost::enable_shared_from_this<ICETransport>,  public PJMediaTransport
+{
+public:
+
+    ~ICETransport();
+    void onSetupComplete(pjmedia_transport* transport, int status);
+
+    //
+    // Overrides of PJMediaTransport
+    //
+    AsteriskSCF::Helpers::AddressPtr localAddress();
+    AsteriskSCF::Helpers::AddressPtr remoteAddress();
+    void addFacets(const Ice::ObjectAdapterPtr& adapter, const Ice::Identity& id);
+
+    /**
+     * The Microsoft VS 2010 C++ compiler doesn't like the forward declaration of ICETransport 
+     * before the enable_shared_from_this<> base class/template instantiation.
+     **/
+    static ICETransportPtr
+        create(const PJMediaEndpointPtr& ep, const PJMediaEnvironmentPtr& configObject);
+
+private:
+    boost::mutex mLock;
+    boost::condition_variable mMonitor;
+    AsteriskSCF::Helpers::AddressPtr mLocalAddress;
+    AsteriskSCF::Helpers::AddressPtr mRemoteAddress;
+    PJICECallbackPtr mCallback;
+    PJSockAddrPtr mLastKnownAddr;
+    NATModulePtr mNATModule;
+    PJMediaEndpointPtr mEndpoint;
+    PJMediaEnvironmentPtr mConfig;
+    bool mEnableRTCP;
+
+    ICETransport(const PJMediaEndpointPtr& ep, const PJMediaEnvironmentPtr& configObject);
+
+    void start();
+
+    //
+    // Hidden and unimplemented.
+    //
+    ICETransport(const ICETransport&);
+    void operator=(const ICETransport&);
+};
+
+
+} /* End of namespace PJMediaRTP */
+} /* End of namespace AsteriskSCF */
diff --git a/src/MediaRTPpjmedia.cpp b/src/MediaRTPpjmedia.cpp
index 6f59f07..c8304b3 100644
--- a/src/MediaRTPpjmedia.cpp
+++ b/src/MediaRTPpjmedia.cpp
@@ -40,6 +40,8 @@
 #include "RTPConfiguration.h"
 #include "RtpConfigurationIf.h"
 
+#include "PJMediaEnvironment.h"
+
 using namespace std;
 using namespace AsteriskSCF::Core::Discovery::V1;
 using namespace AsteriskSCF::Media::V1;
@@ -50,6 +52,7 @@ using namespace AsteriskSCF::System::Configuration::V1;
 using namespace AsteriskSCF::System::Component::V1;
 using namespace AsteriskSCF::System::Logging;
 using namespace AsteriskSCF::Discovery;
+using namespace AsteriskSCF::PJMediaRTP;
 
 namespace
 {
@@ -66,11 +69,17 @@ static const string MediaComparatorServiceId("RTPMediaServiceComparator");
 class RTPMediaServiceImpl : public RTPMediaService
 {
 public:
-    RTPMediaServiceImpl(const Ice::ObjectAdapterPtr&, const ReplicaPtr&,
+    RTPMediaServiceImpl(const Ice::ObjectAdapterPtr&, const ReplicaPrx&,
 	const AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx>&,
 	const ConfigurationServiceImplPtr&);
     RTPSessionPrx allocate(const RTPServiceLocatorParamsPtr&, const Ice::Current&);
-    pj_pool_factory *getPoolFactory() { return &mCachingPool.factory; };
+    pj_pool_factory *getPoolFactory() { return mEnvironment->poolFactory(); };
+
+    PJMediaEnvironmentPtr getEnvironment()
+    {
+        return mEnvironment;
+    }
+
 private:
     /**
      * A pointer to the object adapter that objects should be added to.
@@ -78,19 +87,14 @@ private:
     Ice::ObjectAdapterPtr mAdapter;
 
     /**
-     * Memory caching pool.
+     * The media environment object.
      */
-    pj_caching_pool mCachingPool;
+    PJMediaEnvironmentPtr mEnvironment;
 
     /**
-     * Memory pool.
+     * A proxy for the replica service
      */
-    pj_pool_t* mMemoryPool;
-
-    /**
-     * A pointer to the replica service.
-     */
-    ReplicaPtr mReplicaService;
+    ReplicaPrx mReplicaServicePrx;
 
     /**
      * A pointer to the configuration service.
@@ -101,6 +105,10 @@ private:
      * A proxy to the state replicator.
      */
     AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx> mStateReplicator;
+
+#if CONTROL_POINTS_ENABLED
+    AsteriskSCF::PJMediaRTPTesting mMediaServiceSwitchBoard;
+#endif
 };
 
 /**
@@ -179,6 +187,11 @@ private:
 class RTPMediaServiceCompareServiceImpl : public ServiceLocatorParamsCompare
 {
 public:
+    RTPMediaServiceCompareServiceImpl(const ConfigurationServiceImplPtr& config) :
+        mConfig(config)
+    {
+    }
+
     bool isSupported(const ServiceLocatorParamsPtr& locatorParams, const Ice::Current&)
     {
 	RTPServiceLocatorParamsPtr params;
@@ -199,9 +212,48 @@ public:
 	    result = false;
 #endif
 	}
+        //
+        // We can ignore the SRTP criteria since we support it one way or the other.
+        //
+        if (!result)
+        {
+            return false;
+        }
+        
+        RTPOverICEServiceLocatorParamsPtr iceParams = RTPOverICEServiceLocatorParamsPtr::dynamicCast(locatorParams);
+        if (iceParams)
+        {
+            if (iceParams->enableRTPOverICE)
+            {
+                NATConfigPtr natConfig = mConfig->natConfig();
+
+                if (natConfig && natConfig->isSTUNEnabled())
+                {
+                    if (iceParams->enableTURN)
+                    {
+                        if (!natConfig->isTURNEnabled())
+                        {
+                            result = false;
+                        }
+                    }
+                }
+                else
+                {
+                    result = false;
+                }
+            }
+            //
+            // We ignore the else case because we can definitely do non-ICE related stuff... its not clear
+            // that negative matches in this case should be exclusionary. Actual ICE usage will be specified
+            // when the RTP session is allocated.
+            //
+        }
 
 	return result;
     };
+
+private:
+    ConfigurationServiceImplPtr mConfig;
 };
 
 /**
@@ -246,6 +298,11 @@ private:
     ReplicaPtr mReplicaService;
 
     /**
+     * A proxy to the replica control object.
+     */
+    ReplicaPrx mReplicaServicePrx;
+
+    /**
      * Instance of our configuration service implementation.
      */
     ConfigurationServiceImplPtr mConfigurationService;
@@ -420,17 +477,15 @@ typedef IceUtil::Handle<RtpConfigurationCompare> RtpConfigurationComparePtr;
 /**
  * Constructor for the RTPMediaServiceImpl class.
  */
-RTPMediaServiceImpl::RTPMediaServiceImpl(const Ice::ObjectAdapterPtr& adapter, const ReplicaPtr& replicaService,
+RTPMediaServiceImpl::RTPMediaServiceImpl(const Ice::ObjectAdapterPtr& adapter, const ReplicaPrx& replicaService,
     const AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx>& stateReplicator,
     const ConfigurationServiceImplPtr& configurationService) :
-    mAdapter(adapter), mReplicaService(replicaService), mConfigurationService(configurationService),
+    mAdapter(adapter), 
+    mEnvironment(PJMediaEnvironment::create(adapter->getCommunicator()->getProperties(), configurationService)),
+    mReplicaServicePrx(replicaService), 
+    mConfigurationService(configurationService),
     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", 1000, 1000, NULL);
 }
 
 /**
@@ -438,10 +493,8 @@ RTPMediaServiceImpl::RTPMediaServiceImpl(const Ice::ObjectAdapterPtr& adapter, c
  */
 RTPSessionPrx RTPMediaServiceImpl::allocate(const RTPServiceLocatorParamsPtr& params, const Ice::Current&)
 {
-    RTPSessionImplPtr session =
-        new RTPSessionImpl(mAdapter, params, &mCachingPool.factory, mReplicaService, mStateReplicator,
-	    mConfigurationService);
-    return session->getProxy();
+    return AsteriskSCF::PJMediaRTP::RTPSession::create(mAdapter, IceUtil::generateUUID(), params, mEnvironment,
+            mReplicaServicePrx, mStateReplicator, mConfigurationService);
 }
 
 /**
@@ -482,12 +535,10 @@ void MediaRTPpjmediaApp::start(const std::string&, const Ice::CommunicatorPtr& c
     mLocalAdapter = mCommunicator->createObjectAdapter("MediaRTPpjmediaAdapterLocal");
 
     mReplicaService = new ReplicaImpl(mLocalAdapter);
-    mLocalAdapter->add(mReplicaService, mCommunicator->stringToIdentity(ReplicaServiceId));
-
-    mConfigurationService = new ConfigurationServiceImpl();
-    ConfigurationServicePrx mConfigurationServiceProxy = ConfigurationServicePrx::uncheckedCast(
-	mLocalAdapter->addWithUUID(mConfigurationService));
+    mReplicaServicePrx = ReplicaPrx::uncheckedCast(mLocalAdapter->add(mReplicaService, mCommunicator->stringToIdentity(ReplicaServiceId)));
 
+    mConfigurationService = ConfigurationServiceImpl::create();
+    ConfigurationServicePrx mConfigurationServiceProxy = mConfigurationService->activate(mLocalAdapter, IceUtil::generateUUID());
     mLocalAdapter->activate();
 
     mGlobalAdapter = mCommunicator->createObjectAdapter("MediaRTPpjmediaAdapter");
@@ -505,7 +556,7 @@ void MediaRTPpjmediaApp::start(const std::string&, const Ice::CommunicatorPtr& c
     RtpStateReplicatorParamsPtr replicatorParams = new RtpStateReplicatorParams();
     replicatorParams->category = StateReplicatorDiscoveryCategory;
     replicatorParams->mName =
-        mCommunicator->getProperties()->getPropertyWithDefault("Sip.StateReplicatorName", "default");
+        mCommunicator->getProperties()->getPropertyWithDefault("Rtp.StateReplicatorName", "default");
 
     try
     {  
@@ -518,7 +569,7 @@ void MediaRTPpjmediaApp::start(const std::string&, const Ice::CommunicatorPtr& c
     }
 
     RTPMediaServiceImplPtr rtpmediaservice =
-        new RTPMediaServiceImpl(mGlobalAdapter, mReplicaService, mStateReplicator, mConfigurationService);
+        new RTPMediaServiceImpl(mGlobalAdapter, mReplicaServicePrx, mStateReplicator, mConfigurationService);
 
     if (mCommunicator->getProperties()->getPropertyWithDefault("Rtp.Standalone", "false") == "true")
     {
@@ -550,7 +601,7 @@ void MediaRTPpjmediaApp::start(const std::string&, const Ice::CommunicatorPtr& c
     if (mStateReplicator)
     {
         mReplicatorListener =
-            new RtpStateReplicatorListenerI(mGlobalAdapter, rtpmediaservice->getPoolFactory(), mGeneralState,
+            new RtpStateReplicatorListenerI(mGlobalAdapter, rtpmediaservice->getEnvironment(), mGeneralState,
 		mConfigurationService);
         mReplicatorListenerProxy =
             RtpStateReplicatorListenerPrx::uncheckedCast(mLocalAdapter->addWithUUID(mReplicatorListener));
@@ -567,7 +618,7 @@ void MediaRTPpjmediaApp::start(const std::string&, const Ice::CommunicatorPtr& c
 	}
     }
 
-    ServiceLocatorParamsComparePtr rtpmediacomparatorservice = new RTPMediaServiceCompareServiceImpl();
+    ServiceLocatorParamsComparePtr rtpmediacomparatorservice = new RTPMediaServiceCompareServiceImpl(mConfigurationService);
     ServiceLocatorParamsComparePrx RTPMediaComparatorServiceProxy = ServiceLocatorParamsComparePrx::uncheckedCast(
 	mGlobalAdapter->add(rtpmediacomparatorservice, mCommunicator->stringToIdentity(MediaComparatorServiceId)));
     
@@ -581,14 +632,31 @@ void MediaRTPpjmediaApp::start(const std::string&, const Ice::CommunicatorPtr& c
     RTPMediaServicePrx RTPMediaServiceProxy = RTPMediaServicePrx::uncheckedCast(mGlobalAdapter->add(rtpmediaservice,
 	    mCommunicator->stringToIdentity(MediaServiceId)));
 
... 4550 lines suppressed ...


-- 
asterisk-scf/release/media_rtp_pjmedia.git



More information about the asterisk-scf-commits mailing list