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

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


branch "master" has been updated
       via  5cc1decf6fbf407a4d477f74f7832af9bf1df66d (commit)
      from  f3ac2038009f50b1ff84d203999dc79f2a0aea56 (commit)

Summary of changes:
 config/SipConfigurator.py                          |   58 ++-
 config/test_sip.conf                               |    2 +
 .../SipSessionManager/SipConfigurationIf.ice       |  794 +++++++++++---------
 src/CMakeLists.txt                                 |   20 +
 src/DebugUtil.h                                    |   33 +
 src/{PJSipLoggingModule.h => NATOptions.h}         |   30 +-
 src/PJSipLoggingModule.cpp                         |    1 +
 src/PJSipManager.cpp                               |  258 ++++---
 src/PJSipManager.h                                 |   61 +-
 src/PJSipModule.h                                  |    3 +-
 src/PJSipSessionModule.cpp                         |   38 +-
 src/PJUtil.h                                       |   37 +
 src/STUNModule.cpp                                 |  157 ++++
 src/STUNModule.h                                   |  101 +++
 src/STUNTransport.cpp                              |  416 ++++++++++
 src/STUNTransport.h                                |   44 ++
 src/STUNTransportConfig.cpp                        |  131 ++++
 src/STUNTransportConfig.h                          |   52 ++
 src/SipConfiguration.cpp                           |  191 ++++-
 src/SipConfiguration.h                             |    2 +-
 src/SipEndpoint.cpp                                |   47 +-
 src/SipEndpoint.h                                  |   63 ++-
 src/SipEndpointFactory.cpp                         |    6 +-
 src/SipEndpointFactory.h                           |    4 +-
 src/SipModule.h                                    |   68 ++
 src/SipSession.cpp                                 |  336 ++++++++-
 src/SipSession.h                                   |   44 +-
 src/SipSessionManagerApp.cpp                       |   12 +-
 src/SipStateReplicator.h                           |    2 +-
 src/SipStateReplicatorListener.cpp                 |   13 +-
 src/TCPTransport.cpp                               |  111 +++
 src/TCPTransport.h                                 |   41 +
 src/TLSTransport.cpp                               |   93 +++
 src/TLSTransport.h                                 |   43 ++
 src/Transports.cpp                                 |   71 ++
 src/Transports.h                                   |   74 ++
 src/UDPTransport.cpp                               |  117 +++
 src/UDPTransport.h                                 |   41 +
 38 files changed, 2976 insertions(+), 639 deletions(-)
 create mode 100644 src/DebugUtil.h
 copy src/{PJSipLoggingModule.h => NATOptions.h} (50%)
 create mode 100644 src/PJUtil.h
 create mode 100644 src/STUNModule.cpp
 create mode 100644 src/STUNModule.h
 create mode 100644 src/STUNTransport.cpp
 create mode 100644 src/STUNTransport.h
 create mode 100644 src/STUNTransportConfig.cpp
 create mode 100644 src/STUNTransportConfig.h
 create mode 100644 src/SipModule.h
 mode change 100644 => 100755 src/SipSession.cpp
 create mode 100644 src/TCPTransport.cpp
 create mode 100644 src/TCPTransport.h
 create mode 100644 src/TLSTransport.cpp
 create mode 100644 src/TLSTransport.h
 create mode 100644 src/Transports.cpp
 create mode 100644 src/Transports.h
 create mode 100644 src/UDPTransport.cpp
 create mode 100644 src/UDPTransport.h


- Log -----------------------------------------------------------------
commit 5cc1decf6fbf407a4d477f74f7832af9bf1df66d
Author: Brent Eagles <beagles at digium.com>
Date:   Wed Jul 20 15:14:12 2011 -0230

    - Added a little workaround to deal with unavailability of default udp transport at
        initialization (it *could* conceivably be configured in afterwards).
    - Added flag to SipConfigurator.py to allow underscores in identifiers in Slice
    - Added transport and module hashtables to PJSipManager along with
      modifiers and accessors for same. This allows functionality to be
      added without having to propogate additional arguments around that
      might never be used.
      NOTE: While I am not a fan of this approach, it seemed the most direct
      route to take. An improvement would be take that stuff out of PJSipManager
      and put it in a separate class and pass that around instead.
    
    - Added STUNModule to encapsulate initialization of pj_nath library.
    
    - Added a Transport base class that encapsulates some common
      functions.
    
    - Moved TLS, UDP, TCP transport code out of PJSipManager into subsclasses of
      Transport. With the exception of a default UDP transport, all other transports are constructed
      through configuration.
    
    - Added a STUN transport, also a subclass of transport. Default transport
      behavior is modified to return a local address provided by the STUN
      binding request.
    
    - Added configuration handler for STUNTransport.
    
    - Added transport selection code in SipSession for STUN. This
      can be extended in the future to force selection of different transports
      based on session/endpoint configuration. By default pjsip is
      supposed to select the transport based on details of the dialog
      setup, but this just allows you to force it based on properties.
    
    - Modified dialog creation to build a contact URI with the external
      address for the SIP signalling through a NAT.
    
    - Added media_sdp modifier code if RTP over ICE is turned on which
      gets the InteractiveConnection facet off of the MediaSession.
      NOTE: I'm not completely sold on using a facet here, but where
      we are talking about conditionally available features it seemed
      like a good fit.
    - PJSipManager is now being passed along as a boost::shared_ptr based
      PJSipManagerPtr. This seems to work ok, but did change a lot of
      method signatures.
    - Add STUN configuration handler, which will in turn allocate the
      STUN transport.
    - Add transport collection (albeit temporarily... most likely) to PJSipManager. Transports
      are now added to the transport map, but will also be reaped after they are destroyed. ie.
      the transports do not need to tell the manager that they are dead, it'll ask later
      on and release the reference.
    - For STUN enabled endpoints only (for the time being):
       - enable explicit transport selection for the setting up dialog
    - Other transports can initialize the transport selection structure, but it's not used
      at the moment.
    - Enable SDP generation for candidates.

diff --git a/config/SipConfigurator.py b/config/SipConfigurator.py
index 1d34378..2d61c7a 100755
--- a/config/SipConfigurator.py
+++ b/config/SipConfigurator.py
@@ -19,12 +19,13 @@
 # Sip configurator
 
 # Bring in the common configuration infrastructure
-import Ice, Configurator, sys, os
+import Ice, Configurator, sys, os, traceback
 
 # Load our component specific configuration definitions
-Ice.loadSlice("-I" + os.environ["ASTSCF_HOME"] + " -I" + Ice.getSliceDir() + " --all ../slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice")
+Ice.loadSlice("--underscore -I" + os.environ["ASTSCF_HOME"] + " -I" + Ice.getSliceDir() + " --all ../slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice")
 import AsteriskSCF.Configuration.SipSessionManager.V1
 
+
 # Add our own visitor implementations for the sections we support
 class SipSectionVisitors(Configurator.SectionVisitors):
     def visit_general(self, config, section):
@@ -80,6 +81,27 @@ class SipSectionVisitors(Configurator.SectionVisitors):
 
         self.groups.append(group)
 
+    def visit_transport_stun(self, config, section):
+        group = AsteriskSCF.Configuration.SipSessionManager.V1.SipSTUNTransportGroup()
+        group.name = section
+        group.configurationItems = {}
+        mapper = Configurator.OptionMapper()
+
+        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipSignalingSTUNHostItem()
+        mapper.map('stunhost', item, 'address', 'stunServer', config.get, None)
+        mapper.map('stunport', item, 'port', 'stunServer', config.getint, 3478)
+
+        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipHostItem()
+        mapper.map('baseaddress', item, 'host', 'baseAddress', config.get, None)
+        mapper.map('baseport', item, 'port', 'baseAddress', config.getint, 4512)
+
+        for option in config.options(section):
+            mapper.execute(group, section, option)
+
+        mapper.finish(group)
+
+        self.groups.append(group)
+
     def visit_endpoint(self, config, section):
         group = AsteriskSCF.Configuration.SipSessionManager.V1.SipEndpointGroup()
         group.name = section
@@ -97,6 +119,33 @@ class SipSectionVisitors(Configurator.SectionVisitors):
         mapper.map('targethost', item, 'host', 'targetaddress', config.get, None)
         mapper.map('targetport', item, 'port', 'targetaddress', config.getint, 5060)
 
+        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipSignalingNATItem()
+        mapper.map('enablestun', item, 'stun', 'enableSTUN', config.get, None)
+
+        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipMediaNATItem()
+        mapper.map('enablertpoverice', item, 'enableICE', 'enableRTPICE', config.get, None)
+        mapper.map('enableturn', item, 'enableTURN', 'enableRTPICE', config.get, None)
+
+        item = AsteriskSCF.Configuration.SipSessionManager.V1.SRTPCryptoItem()
+               
+        class CryptoKeyHandler:
+                def __init__(self, config, keyItem):
+                    self.config = config
+                    self.item = keyItem
+
+                def getSuite(self, section, item):
+                    self.item.suite = self.config.get(section, item)
+
+                def getKey(self, section, item):
+                    self.item.cryptoKey = self.config.get(section, item)
+                    
+        item.cryptoKeys = [ AsteriskSCF.Configuration.SipSessionManager.V1.SRTPCryptoKey() ]
+        mapper.map('enableauth', item, 'enableAuthentication', 'srtpCryptoSettings', config.get, None)
+        mapper.map('enableencryption', item, 'enableEncryption', 'srtpCryptoSettings', config.get, None)
+        handler = CryptoKeyHandler(config, item.cryptoKeys[0])
+        mapper.map('ciphersuite', item, 'suite', 'srtpCryptoSettings', handler.getSuite, None)
+        mapper.map('cryptokey', item, 'cryptoKey', 'srtpCryptoSettings', handler.getKey, None)
+
         class AllowableCallDirectionTransformer():
             def __init__(self, config):
                 self.config = config
@@ -157,6 +206,8 @@ class SipSectionVisitors(Configurator.SectionVisitors):
             mapper.execute(group, section, option)
         mapper.finish(group)
 
+        self.groups.append(group)
+
         try:
             formats = config.get(section, 'formats')
             configuredFormats = formats.split(',')
@@ -177,10 +228,9 @@ class SipSectionVisitors(Configurator.SectionVisitors):
 
                 group.configurationItems[format] = item
         except:
+            traceback.print_exc()
             print 'No configured formats for endpoint ' + section
 
-        self.groups.append(group)
-
     def visit_unsupported(self, config, section):
         if config.get(section, 'type') == 'transport-udp':
             self.visit_transport_udp(config, section)
diff --git a/config/test_sip.conf b/config/test_sip.conf
index b96ee9c..53416f1 100644
--- a/config/test_sip.conf
+++ b/config/test_sip.conf
@@ -39,6 +39,8 @@ Sip.StateReplicatorListener=no
 # Endpoints that we know about
 Sip.Endpoints=cisco 18005558355
 
+Sip.Standalone=true
+
 # This is Josh's phone
 Sip.Endpoint.cisco.Session.CallDirection=Both
 
diff --git a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
index f37030d..c0c85fb 100644
--- a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
@@ -32,412 +32,462 @@ module SipSessionManager
 ["suppress"]
 module V1
 {
-   /**
-    * Service locator category for finding the configuration service
-    */
-   const string ConfigurationDiscoveryCategory = "SipConfiguration";
-
-   /**
-    * Service locator parameters class for discovering the configuration service
-    */
-   unsliceable class SipConfigurationParams extends AsteriskSCF::Core::Discovery::V1::ServiceLocatorParams
-   {
-       /**
-	* Unique name for the configuration service
-	*/
-       string name;
-   };
-
-   /**
-    * Local visitor class for visiting SIP configuration groups
-    */
-   local class SipConfigurationGroupVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationGroupVisitor
-   {
-   };
-
-   /**
-    * Generic SIP configuration group
-    */
-   ["visitor:SipConfigurationGroupVisitor"] class SipConfigurationGroup extends AsteriskSCF::System::Configuration::V1::ConfigurationGroup
-   {
-   };
-
-   /**
-    * General SIP configuration group that contains general items related to the SIP component as a whole
-    */
-   class SipGeneralGroup extends SipConfigurationGroup
-   {
-   };
-
-   /**
-    * Local visitor class for visiting SIP configuration items
-    */
-   local class SipConfigurationItemVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationItemVisitor
-   {
-   };
 
-   /**
-    * Generic SIP configuration item
-    */
-   ["visitor:SipConfigurationItemVisitor"] class SipConfigurationItem extends AsteriskSCF::System::Configuration::V1::ConfigurationItem
-   {
-   };
-
-   /**
-    * SIP Endpoint group, used to configure an endpoint
-    */
-   class SipEndpointGroup extends SipConfigurationGroup
-   {
-      /**
-       * Name of the endpoint being configured
-       */
-      string name;
-   };
-
-   /**
-    * SIP Domain group, used to configure a specific domain
-    */
-   class SipDomainGroup extends SipConfigurationGroup
-   {
-      /**
-       * Name of the domain being configured
-       */
-      string domain;
-   };
-
-   /**
-    * Domain item for bindings
-    */
-   class SipBindingsItem extends SipConfigurationItem
-   {
-      /**
-       * Addresses the domain is reachable over
-       */
-      Ice::StringSeq bindings;
-   };
+/**
+ * Service locator category for finding the configuration service
+ */
+const string ConfigurationDiscoveryCategory = "SipConfiguration";
 
-   /**
-    * Generic SIP transport group that others derive from, primarily created since each one has
-    * the requirement of a name
-    */
-   class SipTransportGroup extends SipConfigurationGroup
-   {
-      /**
-       * Name of the specific transport. Since each one may have multiple transports this differentiates
-       * them.
-       */
-      string name;
-   };
+/**
+ * Service locator parameters class for discovering the configuration service
+ */
+unsliceable class SipConfigurationParams extends AsteriskSCF::Core::Discovery::V1::ServiceLocatorParams
+{
+    /**
+     * Unique name for the configuration service
+     */
+    string name;
+};
+
+/**
+ * Local visitor class for visiting SIP configuration groups
+ */
+local class SipConfigurationGroupVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationGroupVisitor
+{
+};
 
-   /**
-    * Host information configuration item
-    */
-   class SipHostItem extends SipConfigurationItem
-   {
-      /**
-       * String containing the IP address or string address
-       */
-      string host;
-
-      /**
-       * Port number
-       */
-      int port;
-   };
+/**
+ * Generic SIP configuration group
+ */
+["visitor:SipConfigurationGroupVisitor"] class SipConfigurationGroup extends AsteriskSCF::System::Configuration::V1::ConfigurationGroup
+{
+};
 
-   /**
-    * Source transport address configuration item
-    */
-   class SipSourceTransportAddressItem extends SipHostItem
-   {
-   };
+/**
+ * General SIP configuration group that contains general items related to the SIP component as a whole
+ */
+class SipGeneralGroup extends SipConfigurationGroup
+{
+};
 
-   /**
-    * Target destination address configuration item
-    */
-   class SipTargetDestinationAddressItem extends SipHostItem
-   {
-   };
+/**
+ * Local visitor class for visiting SIP configuration items
+ */
+local class SipConfigurationItemVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationItemVisitor
+{
+};
 
-   /**
-    * Crypto certificate configuration item
-    */
-   class SipCryptoCertificateItem extends SipConfigurationItem
-   {
-      /**
-       * Full location of certificate authority file
-       */
-      string certificateAuthority;
-
-      /**
-       * Full location of certificate file
-       */
-      string certificate;
-
-      /**
-       * Full location of private key file
-       */
-      string privateKey;
-
-      /**
-       * Password to open private key file
-       */
-      string privateKeyPassword;
-   };
+/**
+ * Generic SIP configuration item
+ */
+["visitor:SipConfigurationItemVisitor"] class SipConfigurationItem extends AsteriskSCF::System::Configuration::V1::ConfigurationItem
+{
+};
 
-   /**
-    * Crypto requirement configuration item
-    */
-   class SipCryptoRequirementsItem extends SipConfigurationItem
-   {
-       /**
-	* Require verification of server certificate
-	*/
-       bool requireVerifiedServer = false;
-
-       /**
-	* Require verification of client certificate
-	*/
-       bool requireVerifiedClient = false;
-
-       /**
-	* Require client certificate be present
-	*/
-       bool requireClientCertificate = false;
-   };
+/**
+ * SIP Endpoint group, used to configure an endpoint
+ */
+class SipEndpointGroup extends SipConfigurationGroup
+{
+    /**
+     * Name of the endpoint being configured
+     */
+    string name;
+};
+
+/**
+ * SIP Domain group, used to configure a specific domain
+ */
+class SipDomainGroup extends SipConfigurationGroup
+{
+    /**
+     * Name of the domain being configured
+     */
+    string domain;
+};
+
+/**
+ * Domain item for bindings
+ */
+class SipBindingsItem extends SipConfigurationItem
+{
+    /**
+     * Addresses the domain is reachable over
+     */
+    Ice::StringSeq bindings;
+};
+
+/**
+ * Generic SIP transport group that others derive from, primarily created since each one has
+ * the requirement of a name
+ */
+class SipTransportGroup extends SipConfigurationGroup
+{
+    /**
+     * Name of the specific transport. Since each one may have multiple transports this differentiates
+     * them.
+     */
+    string name;
+};
+
+/**
+ * Host information configuration item
+ */
+class SipHostItem extends SipConfigurationItem
+{
+    /**
+     * String containing the IP address or string address
+     */
+    string host;
+
+    /**
+     * Port number
+     */
+    int port;
+};
+
+/**
+ * Source transport address configuration item
+ */
+class SipSourceTransportAddressItem extends SipHostItem
+{
+};
 
-   /**
-    * TLS protocol methods
-    */
-   enum TLSProtocolMethod
-   {
-       PROTOCOLMETHODUNSPECIFIED,
-       PROTOCOLMETHODTLSV1,
-       PROTOCOLMETHODSSLV2,
-       PROTOCOLMETHODSSLV3,
-       PROTOCOLMETHODSSLV23,
-   };
+/**
+ * Target destination address configuration item
+ */
+class SipTargetDestinationAddressItem extends SipHostItem
+{
+};
 
-   /**
-    * General crypto configuration item
-    */
-   class SipCryptoItem extends SipConfigurationItem
-   {
-       /**
-	* TLS protocol method to use
-	*/
-       TLSProtocolMethod protocolMethod = PROTOCOLMETHODUNSPECIFIED;
-
-       /**
-	* Supported ciphers (OpenSSL format)
-	*/
-       string supportedCiphers;
-
-       /**
-	* Server name
-	*/
-       string serverName;
-
-       /**
-	* TLS negotiation timeout in seconds
-	*/
-       int timeout = 0;
-   };
+/**
+ * Crypto certificate configuration item
+ */
+class SipCryptoCertificateItem extends SipConfigurationItem
+{
+    /**
+     * Full location of certificate authority file
+     */
+    string certificateAuthority;
+
+    /**
+     * Full location of certificate file
+     */
+    string certificate;
+
+    /**
+     * Full location of private key file
+     */
+    string privateKey;
+
+    /**
+     * Password to open private key file
+     */
+    string privateKeyPassword;
+};
+
+/**
+ * Crypto requirement configuration item
+ */
+class SipCryptoRequirementsItem extends SipConfigurationItem
+{
+    /**
+     * Require verification of server certificate
+     */
+    bool requireVerifiedServer = false;
+
+    /**
+     * Require verification of client certificate
+     */
+    bool requireVerifiedClient = false;
+
+    /**
+     * Require client certificate be present
+     */
+    bool requireClientCertificate = false;
+};
+
+/**
+ * TLS protocol methods
+ */
+enum TLSProtocolMethod
+{
+    PROTOCOLMETHODUNSPECIFIED,
+    PROTOCOLMETHODTLSV1,
+    PROTOCOLMETHODSSLV2,
+    PROTOCOLMETHODSSLV3,
+    PROTOCOLMETHODSSLV23,
+};
+
+/**
+ * General crypto configuration item
+ */
+class SipCryptoItem extends SipConfigurationItem
+{
+    /**
+     * TLS protocol method to use
+     */
+    TLSProtocolMethod protocolMethod = PROTOCOLMETHODUNSPECIFIED;
+
+    /**
+     * Supported ciphers (OpenSSL format)
+     */
+    string supportedCiphers;
+
+    /**
+     * Server name
+     */
+    string serverName;
+
+    /**
+     * TLS negotiation timeout in seconds
+     */
+    int timeout = 0;
+};
+    
+/**
+ * SRTP Crypto Key information.
+ */
+class SRTPCryptoKey
+{
+    /**
+     * The cipher suite name.
+     */
+    string suite;
 
-   /**
-    * Routing service configuration item
-    */
-   class SipRoutingItem extends SipConfigurationItem
-   {
-      /**
-       * Name of the routing service to use
-       */
-      string routingServiceName;
-   };
+    /**
+     * The key information for the suite.
+     */
+    string cryptoKey;
+};
 
-   /**
-    * RTP Media service configuration item
-    */
-   class SipRTPMediaServiceItem extends SipConfigurationItem
-   {
-      /**
-       * Name of the RTP media service to use
-       */
-      string mediaServiceName;
-
-      /**
-       * Whether to choose an IPv6 RTP media service or not
-       */
-      bool requireIPv6 = false;
-   };
+sequence<SRTPCryptoKey> SRTPCryptoKeySeq;
 
-   /**
-    * Signaling NAT configuration item
-    */
-   class SipSignalingNATItem extends SipConfigurationItem
-   {
-      /**
-       * Boolean for whether STUN is enabled
-       */
-      bool stun;
-   };
+/**
+ * SRTP crypto configuration.
+ */
+class SRTPCryptoItem extends SipConfigurationItem
+{
 
-   /**
-    * Media NAT configuration item
-    */
-   class SipMediaNATItem extends SipConfigurationItem
-   {
-      /**
-       * Boolean for whether symmetric RTP is enabled
-       */
-      bool symmetricRTP;
-
-      /**
-       * Boolean for whether STUN is enabled
-       */
-      bool stun;
-
-      /**
-       * Boolean for whether ICE is enabled
-       */
-      bool interactiveconnectivityestablishment;
-
-      /**
-       * Boolean for whether TURN is enabled
-       */
-      bool turn;
-   };
+    /**
+     * Most of the time the following values will be false. They can be overriden to be true however.
+     */
+    bool enableAuthentication;
+    bool enableEncryption;
 
-   /**
-    * Access control lists item
-    */
-   class SipACLItem extends SipConfigurationItem
-   {
-      /**
-       * Name of this ACL item. A user may want to have multiple.
-       */
-      string name;
-
-      /**
-       * Ranges of allowed hosts
-       */
-      Ice::StringSeq allowRanges;
-
-      /**
-       * Specific allowed hosts
-       */
-      Ice::StringSeq allowHosts;
-
-      /**
-       * Ranges of denied hosts
-       */
-      Ice::StringSeq denyRanges;
-
-      /**
-       * Specific denied hosts
-       */
-      Ice::StringSeq denyHosts;
-   };
+    /**
+     * The suites and keys supported by this endpoint.
+     */
+    SRTPCryptoKeySeq cryptoKeys;
+};
 
+/**
+ * Routing service configuration item
+ */
+class SipRoutingItem extends SipConfigurationItem
+{
+    /**
+     * Name of the routing service to use
+     */
+    string routingServiceName;
+};
+
+/**
+ * RTP Media service configuration item
+ */
+class SipRTPMediaServiceItem extends SipConfigurationItem
+{
+    /**
+     * Name of the RTP media service to use
+     */
+    string mediaServiceName;
+
+    /**
+     * Whether to choose an IPv6 RTP media service or not
+     */
+    bool requireIPv6 = false;
+};
+
+/**
+ * Signaling NAT configuration item
+ */
+class SipSignalingNATItem extends SipConfigurationItem
+{
+    /**
+     * Boolean for whether STUN is enabled
+     */
+    bool stun;
+};
+
+/**
+ * STUN server to be used by Sip signalling.
+ */
+class SipSignalingSTUNHostItem extends SipConfigurationItem
+{
+    /**
+     * Address for the STUN server.
+     **/
+    string address;
+
+    /**
+     * Port for the STUN host.
+     */
+    int port;
+};
+
+/**
+ * Media NAT configuration item
+ */
+class SipMediaNATItem extends SipConfigurationItem
+{
+    /**
+     * Boolean for whether ICE is enabled
+     */
+    bool enableICE;
+
+    /**
+     * Boolean for whether TURN is enabled
+     */
+    bool enableTURN;
+};
+
+/**
+ * Access control lists item
+ */
+class SipACLItem extends SipConfigurationItem
+{
+    /**
+     * Name of this ACL item. A user may want to have multiple.
+     */
+    string name;
+
+    /**
+     * Ranges of allowed hosts
+     */
+    Ice::StringSeq allowRanges;
+
+    /**
+     * Specific allowed hosts
+     */
+    Ice::StringSeq allowHosts;
+
+    /**
+     * Ranges of denied hosts
+     */
+    Ice::StringSeq denyRanges;
+
+    /**
+     * Specific denied hosts
+     */
+    Ice::StringSeq denyHosts;
+};
+
+/**
+ * Allowable call directions
+ */
+enum SipAllowableCallDirection
+{
+    Disabled,
+    Inbound,
+    Outbound,
+    Both,
+};
+
+/**
+ * Allowable call direction item
+ */
+class SipAllowableCallDirectionItem extends SipConfigurationItem
+{
+    /**
+     * What direction is permitted for this endpoint
+     */
+    SipAllowableCallDirection callDirection = Both;
+};
+
+/**
+* Allowable media format item
+*/
+class SipMediaFormatItem extends SipConfigurationItem
+{
    /**
-    * Allowable call directions
+    * Name of the media format
     */
-   enum SipAllowableCallDirection
-   {
-      Disabled,
-      Inbound,
-      Outbound,
-      Both,
-   };
+   string name;
 
    /**
-    * Allowable call direction item
+    * Sample rate for frames
+    *
+    * This is specified in Hz and has a default value of 8000. 
     */
-   class SipAllowableCallDirectionItem extends SipConfigurationItem
-   {
-      /**
-       * What direction is permitted for this endpoint
-       */
-      SipAllowableCallDirection callDirection = Both;
-   };
+   int sampleRate = 8000;
 
    /**
-    * Allowable media format item
+    * Amount of audio in frames
+    *
+    * This is specified in 
     */
-   class SipMediaFormatItem extends SipConfigurationItem
-   {
-       /**
-        * Name of the media format
-        */
-       string name;
-
-       /**
-        * Sample rate for frames
-        *
-        * This is specified in Hz and has a default value of 8000. 
-        */
-       int sampleRate = 8000;
-
-       /**
-        * Amount of audio in frames
-        *
-        * This is specified in 
-        */
-       int frameSize;
-
-       /**
-        * Any format specific parameters
-        */
-       Ice::StringSeq formatSpecific;
-   };
+   int frameSize;
 
    /**
-    * User agent presentation configuration item
+    * Any format specific parameters
     */
-   class SipUserAgentItem extends SipConfigurationItem
-   {
-      /**
-       * String that our user agent should appear as
-       */
-      string userAgent;
-   };
+   Ice::StringSeq formatSpecific;
+};
 
-   /**
-    * Transport information configuration item
-    */
-   class SipEndpointTransportItem extends SipConfigurationItem
-   {
-       /**
-	* What directions to require secure transport in
-	*/
-       SipAllowableCallDirection secureTransport = Disabled;
-   };
+/**
+ * User agent presentation configuration item
+ */
+class SipUserAgentItem extends SipConfigurationItem
+{
+    /**
+     * String that our user agent should appear as
+     */
+    string userAgent;
+};
+
+/**
+ * Transport information configuration item
+ */
+class SipEndpointTransportItem extends SipConfigurationItem
+{
+    /**
+     * What directions to require secure transport in
+     */
+    SipAllowableCallDirection secureTransport = Disabled;
+};
+
+/**
+ * Group of configuration items related to a UDP transport
+ */
+class SipUDPTransportGroup extends SipTransportGroup
+{
+};
 
-   /**
-    * Group of configuration items related to a UDP transport
-   */
-   class SipUDPTransportGroup extends SipTransportGroup
-   {
-   };
+/**
+ * Group of configuration items related to a TCP transport
+ */
+class SipTCPTransportGroup extends SipTransportGroup
+{
+};
 
-   /**
-    * Group of configuration items related to a TCP transport
-    */
-   class SipTCPTransportGroup extends SipTransportGroup
-   {
-   };
+/**
+ * Group of configuration items related to a TLS transport
+ */
+class SipTLSTransportGroup extends SipTransportGroup
+{
+};
 
-   /**
-    * Group of configuration items related to a TLS transport
-    */
-   class SipTLSTransportGroup extends SipTransportGroup
-   {
-   };
+/**
+ * Group of configuration items related to a STUN enabled transport
+ */
+class SipSTUNTransportGroup extends SipTransportGroup
+{
+};
 
 }; /* module V1 */
 
 }; /* module SipSessionManager */
 
-}; /* module Replication */
+}; /* module Configuration */
 
 }; /* module AsteriskSCF */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b4570ac..88354c0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -36,6 +36,24 @@ astscf_component_add_files(SipSessionManager SipConfiguration.cpp)
 astscf_component_add_files(SipSessionManager SipConfiguration.h)
 astscf_component_add_files(SipSessionManager SipStateReplicatorListener.cpp)
 astscf_component_add_files(SipSessionManager SipStateReplicator.h)
+astscf_component_add_files(SipSessionManager Transports.cpp)
+astscf_component_add_files(SipSessionManager Transports.h)
+astscf_component_add_files(SipSessionManager UDPTransport.cpp)
+astscf_component_add_files(SipSessionManager UDPTransport.h)
+astscf_component_add_files(SipSessionManager TCPTransport.cpp)
+astscf_component_add_files(SipSessionManager TCPTransport.h)
+astscf_component_add_files(SipSessionManager TLSTransport.cpp)
+astscf_component_add_files(SipSessionManager TLSTransport.h)
+astscf_component_add_files(SipSessionManager PJUtil.h)
+astscf_component_add_files(SipSessionManager DebugUtil.h)
+astscf_component_add_files(SipSessionManager SipModule.h)
+astscf_component_add_files(SipSessionManager STUNModule.cpp)
+astscf_component_add_files(SipSessionManager STUNModule.h)
+astscf_component_add_files(SipSessionManager STUNTransport.cpp)
+astscf_component_add_files(SipSessionManager STUNTransport.h)
+astscf_component_add_files(SipSessionManager STUNTransportConfig.cpp)
+astscf_component_add_files(SipSessionManager STUNTransportConfig.h)
+astscf_component_add_files(SipSessionManager NATOptions.h)
 astscf_component_add_files(SipSessionManager SipRegistrarListener.cpp)
 astscf_component_add_files(SipSessionManager SipRegistrarListener.h)
 astscf_component_add_slices(SipSessionManager PROJECT SipIf.ice)
@@ -46,8 +64,10 @@ astscf_component_add_boost_libraries(SipSessionManager core)
 astscf_component_add_slice_collection_libraries(SipSessionManager ASTSCF)
 astscf_component_build_icebox(SipSessionManager)
 target_link_libraries(SipSessionManager logging-client astscf-ice-util-cpp ${OPENSSL_LIBRARIES})
+
 pjproject_link(SipSessionManager pjsip)
 pjproject_link(SipSessionManager pjmedia)
+pjproject_link(SipSessionManager pjnath)
 pjproject_link(SipSessionManager pjlib-util)
 pjproject_link(SipSessionManager pjlib)
 astscf_component_install(SipSessionManager)
diff --git a/src/DebugUtil.h b/src/DebugUtil.h
new file mode 100644
index 0000000..cf65974
--- /dev/null
+++ b/src/DebugUtil.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <Ice/Ice.h>
+#include <boost/current_function.hpp>
+#include <string>
+
+namespace AsteriskSCF
+{
+
+#define FUNLOG \
+    __FILE__ << ':' << __LINE__ << '(' << BOOST_CURRENT_FUNCTION << ')'
+
+inline std::string objectIdFromCurrent(const Ice::Current& current)
+{
+    return current.adapter->getCommunicator()->identityToString(current.id);
+}
+
+} /* End of namespace AsteriskSCF */
diff --git a/src/NATOptions.h b/src/NATOptions.h
new file mode 100644
index 0000000..2319c50
--- /dev/null
+++ b/src/NATOptions.h
@@ -0,0 +1,37 @@
+/*
+ * 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 <boost/shared_ptr.hpp>
+
+namespace AsteriskSCF
+{
+namespace SipSessionManager
+{
+struct NATEndpointOptions 
+{
+    bool enableICE;
+    bool enableTURN;
+    bool enableSIPSTUN;
+
+    NATEndpointOptions(bool ice, bool turn, bool sip) :
+        enableICE(ice), enableTURN(turn), enableSIPSTUN(sip) 
+    {
+    }
+};
+} /* End of namespace SipSessionManager */
+} /* End of namespace AsteriskSCF */
diff --git a/src/PJSipLoggingModule.cpp b/src/PJSipLoggingModule.cpp
index acfe04f..214e7f2 100644
--- a/src/PJSipLoggingModule.cpp
+++ b/src/PJSipLoggingModule.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "PJSipLoggingModule.h"
+#include <AsteriskSCF/logger.h>
 
 #include <AsteriskSCF/logger.h>
 
diff --git a/src/PJSipManager.cpp b/src/PJSipManager.cpp
index 87f0e2d..ec7d202 100644
--- a/src/PJSipManager.cpp
+++ b/src/PJSipManager.cpp
@@ -16,14 +16,25 @@
 
 #include "PJSipManager.h"
 #include <AsteriskSCF/logger.h>
+#include <AsteriskSCF/System/ExceptionsIf.h>
 
 #include <boost/lexical_cast.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/locks.hpp>
+#include <vector>
+
+#include "PJUtil.h"
+#include "STUNModule.h"
+#include "UDPTransport.h"
+#include <boost/lexical_cast.hpp>
 
 using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::System::V1;
+using namespace std;
 
 namespace
 {
-Logger lg = getLoggerFactory().getLogger("AsteriskSCF.SipSessionManager");
+Logger logger = getLoggerFactory().getLogger("AsteriskSCF.SipSessionManager");
 const std::string RegistrarId("SipRegistrar");
 }
 
@@ -38,47 +49,44 @@ using namespace AsteriskSCF::SIP::Registration::V1;
 
 static void *monitorThread(void *endpt)
 {
-    pjsip_endpoint *endpoint = static_cast<pjsip_endpoint *> (endpt);
+    PJSipManager* endpoint = reinterpret_cast<PJSipManager*> (endpt);
     for (;;)
     {
-        // No timeout is a bad idea in the long run, but for now,
-        // let's just go with it.
-	    pj_time_val timeout = {0, 10};
-        pjsip_endpt_handle_events(endpoint, &timeout);
+        endpoint->handleEvents();
     }
 
     return NULL;
 }
 
-PJSipManager::PJSipManager(const Ice::PropertiesPtr& props)
+PJSipManagerPtr AsteriskSCF::SipSessionManager::PJSipManager::create(const Ice::PropertiesPtr& properties)
 {
-    pj_status_t status = pj_init();
-    if (status != PJ_SUCCESS)
+    PJSipManagerPtr result(new PJSipManager);
+    result->initializeDefaultTransports(properties);
+    STUNModulePtr stunModule = STUNModule::create(result, properties, logger);
+    result->addModule("STUN", stunModule);
+    return result;
+}
+
+
+PJSipManager::~PJSipManager()
+{
+    for (SipModuleMap::iterator i = mModules.begin(); i != mModules.end(); ++i)
     {
-        lg(Error) << "Failed to Initialize PJSIP";
+        i->second->destroy();
+        i->second.reset();
     }
-    // The third parameter is just copied from
-    // example code from PJLIB. This can be adjusted
-    // if necessary.
-    pj_caching_pool_init(&mCachingPool, NULL, 1024 * 1024);
-    pjsip_endpt_create(&mCachingPool.factory, "SIP", &mEndpoint);
-    setTransports(mEndpoint, props);
-    mMemoryPool = pj_pool_create(&mCachingPool.factory, "SIP", 1024, 1024, NULL);
-    if (!mMemoryPool)
+    //
+    // It's pretty important that the transports don't take a reference to the PJSipManager,
+    // otherwise we'd never get here.
+    //
+    for (map<string, TransportPtr>::iterator i = mTransports.begin(); i != mTransports.end(); ++i)
     {
-        lg(Error) << "Failed to create a memory pool";
-    }
-
-    // The default stack size might be set in config_site.h for
-    // specific platforms. 
-    status = pj_thread_create(mMemoryPool, "SIP", (pj_thread_proc *) &monitorThread,
-        mEndpoint, PJ_THREAD_DEFAULT_STACK_SIZE, 0, &mPjThread);
-    if (status != PJ_SUCCESS)
-    {
-        lg(Error) << "Failed to create SIP maintenance thread";
+        i->second->destroy();
+        i->second.reset();
     }
 }
 
+
 void PJSipManager::registerSessionModule(const boost::shared_ptr<SipEndpointFactory>& endpointFactoryPtr,
         const AsteriskSCF::Discovery::SmartProxy<
             AsteriskSCF::SessionCommunications::V1::SessionRouterPrx>& sessionRouter,
@@ -128,112 +136,160 @@ PJSipRegistrarModulePtr PJSipManager::getRegistrarModule()
     return mRegistrarModule;
 }
 
-bool PJSipManager::setTransports(pjsip_endpoint *endpoint, const Ice::PropertiesPtr& props)
+void PJSipManager::addTransport(const string& id, const TransportPtr& transport)
 {
-    //XXX We'll also want to allow for TCP and TLS-specific
-    //addresses to be specified.
-    pj_sockaddr udpAddr;
-    pj_status_t status;
-    std::string udpBindAddr = props->getProperty("Sip.Transport.UdpBindAddr");
-
-    if (udpBindAddr.empty())
+    //
+    // Reap destroyed transports and add the new one.
+    // 
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    map<string, TransportPtr>::iterator i = mTransports.begin();
+    while (i != mTransports.end())
     {
-	return true;
+        if (i->second->isDestroyed())
+        {
+            mTransports.erase(i);
+        }
+        else
+        {
+            ++i;
+        }
     }
+    mTransports.insert(make_pair(id, transport));
+}
 
-    pj_str_t udpString;
-    pj_cstr(&udpString, udpBindAddr.c_str());
-    //UNSPEC family means "you figure out the address family, pjlib!"
-    pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &udpString, &udpAddr);
-    if (udpAddr.addr.sa_family == pj_AF_INET())
+TransportPtr PJSipManager::getTransport(const string& id)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    map<string, TransportPtr>::iterator i = mTransports.begin();
+    while (i != mTransports.end())
     {
-        //XXX The fourth parameter should probably be controlled through
-        //configuration. PJSIP reference says it should be the number of
-        //processors on the machine.
-        //
-        status = pjsip_udp_transport_start(endpoint, &udpAddr.ipv4, NULL, 2, &mUdpTransport);
-        if (status != PJ_SUCCESS)
+        if (i->second->isDestroyed())
         {
-            lg(Error) << "Failed to create IPv4 UDP transport. DANG!";
+            mTransports.erase(i);
         }
-    }
-    else if (udpAddr.addr.sa_family == pj_AF_INET6())
-    {
-        status = pjsip_udp_transport_start6(endpoint, &udpAddr.ipv6, NULL, 2, &mUdpTransport);
-        if (status != PJ_SUCCESS)
+        else
         {
-            lg(Error) << "Failed to create IPv4 UDP transport. DANG!";
+            ++i;
         }
     }
-    //XXX Note that TCP and TLS stuff should be done here. Also note that
-    //currently PJSIP does not have functions for starting IPv6 TCP or
-    //TLS transports, so we'll have to modify the code to allow for it.
-    return true;
+    i = mTransports.find(id);
+    if (i != mTransports.end())
+    {
+        return i->second;
+    }
+    return TransportPtr();
 }
 
-pjsip_transport *PJSipManager::createUDPTransport(std::string address, int port)
+void PJSipManager::addModule(const string& moduleName, const SipModulePtr& module)
 {
-    pj_sockaddr udpAddr;
-    pj_status_t status;
-    pj_str_t udpString;
-    pj_cstr(&udpString, address.c_str());
-    pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &udpString, &udpAddr);
-    pj_sockaddr_set_port(&udpAddr, boost::lexical_cast<pj_uint16_t>(port));
-
-    pjsip_transport *udpTransport = NULL;
-    if (udpAddr.addr.sa_family == pj_AF_INET())
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    SipModuleMap::iterator i = mModules.find(moduleName);
+    if (i != mModules.end())
     {
-	status = pjsip_udp_transport_start(mEndpoint, &udpAddr.ipv4, NULL, 2, &udpTransport);
-    }
-    else if (udpAddr.addr.sa_family == pj_AF_INET6())
-    {
-	status = pjsip_udp_transport_start6(mEndpoint, &udpAddr.ipv6, NULL, 2, &udpTransport);
+        mModules.erase(i);
     }
+    mModules.insert(make_pair(moduleName, module));
+}
 
-    if (status != PJ_SUCCESS)
+SipModulePtr PJSipManager::getModule(const string& moduleName)
+{
+    boost::shared_lock<boost::shared_mutex> lock(mLock);
+    SipModuleMap::const_iterator i = mModules.find(moduleName);
+    if (i != mModules.end())
     {
-	lg(Error) << "Failed to create UDP transport.";
+        return i->second;
     }
+    return SipModulePtr();
+}
 
-    return udpTransport;
+void PJSipManager::handleEvents()
+{
+    onHandleEvents(mModules);
+    const pj_time_val delay = {0, 10};
+    pjsip_endpt_handle_events(mEndpoint, &delay);
 }
 
-pjsip_tpfactory *PJSipManager::createTCPTransport(std::string address, int port)
+pj_caching_pool* PJSipManager::getCachingPool()
 {
-    pj_sockaddr tcpAddr;
-    pj_str_t tcpString;
-    pj_cstr(&tcpString, address.c_str());
-    pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &tcpString, &tcpAddr);
-    pj_sockaddr_set_port(&tcpAddr, boost::lexical_cast<pj_uint16_t>(port));
+    return &mCachingPool;
+}
 
-    pjsip_tpfactory *tcpTransport = NULL;
+pj_pool_t* PJSipManager::getMemoryPool()
+{
+    return mMemoryPool;
+}
 
-    if (pjsip_tcp_transport_start(mEndpoint, &tcpAddr, 2, &tcpTransport) != PJ_SUCCESS)
+void PJSipManager::initializeDefaultTransports(const Ice::PropertiesPtr& properties)
+{
+    string bindAddress = properties->getPropertyWithDefault("Sip.Transport.UdpBindAddr", "0.0.0.0:5060");
+    string addressPart;
+    int portPart = 5060;
+    size_t colon = bindAddress.rfind(':');
+    if (colon != string::npos)
     {
-	lg(Error) << "Failed to create TCP transport.";
+        addressPart = bindAddress.substr(0, colon);
+        portPart = boost::lexical_cast<int>(bindAddress.substr(colon+1));
+    }
+    else
+    {
+        addressPart = bindAddress;
+    }
+    //
+    // It is entirely possible that the default transport is instantiable. We'll eat this error for 
+    // now, but it might be better to abort out.
+    //
+    TransportPtr defaultUDPTransport = createUDPTransport(shared_from_this(), addressPart, portPart);
+    if (defaultUDPTransport)
+    {
+        mTransports.insert(make_pair(defaultUDPTransport->id(), defaultUDPTransport));
+    }
+    else
+    {
+        logger(Error) << "Unable to create default transport";
     }
-
-    return tcpTransport;
 }
 
-pjsip_tpfactory *PJSipManager::createTLSTransport(std::string address, int port, pjsip_tls_setting *)
+PJSipManager::PJSipManager() :
+    mEndpoint(0),
+    mSessionModule(0),
+    mLoggingModule(0),
+    mPjThread(0),
+    mMemoryPool(0)
 {
-    pj_sockaddr tlsAddr;
-    pj_str_t tlsString;
-    pj_cstr(&tlsString, address.c_str());
-    pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &tlsString, &tlsAddr);
-    pj_sockaddr_set_port(&tlsAddr, boost::lexical_cast<pj_uint16_t>(port));
-
-    pjsip_tpfactory *tlsTransport = NULL;
+    memset(&mCachingPool, 0, sizeof(mCachingPool));
 
-#if PJSIP_HAS_TLS_TRANSPORT
-    if (pjsip_tls_transport_start(mEndpoint, tlsSettings, &tlsAddr, NULL, 2, &tlsTransport) != PJ_SUCCESS)
-#endif
+    pj_status_t status = pj_init();
+    if (fail(status))
     {
-        lg(Error) << "Failed to create TLS transport.";
+        const char* message = "Failed to Initialize PJSIP";
+        logger(Error) << message;
+        throw InternalInitializationException(message);
     }
+    // The third parameter is just copied from
+    // example code from PJLIB. This can be adjusted
+    // if necessary.
+    pj_caching_pool_init(&mCachingPool, NULL, 1024 * 1024);
+    pjsip_endpt_create(&mCachingPool.factory, "SIP", &mEndpoint);
 
-    return tlsTransport;
+    //
+    // Careful! This was after the setTransports call, so reordering it might cause issues.
+    //
+    mMemoryPool = pj_pool_create(&mCachingPool.factory, "SIP", 1024, 1024, NULL);
+    if (!mMemoryPool)
+    {
+        const char* message = "Failed to create a memory pool";
+        logger(Error) << message;
+        throw InternalInitializationException(message);
+    }
+    
+    status = pj_thread_create(mMemoryPool, "SIP", (pj_thread_proc *) &monitorThread,
+        this, PJ_THREAD_DEFAULT_STACK_SIZE * 2, 0, &mPjThread);
+    if (fail(status))
+    {
+        const char* message = "Failed to create SIP maintenance thread";
+        logger(Error) << message;
+        throw InternalInitializationException(message);
+    }
 }
 
 }; //End namespace SipSessionManager
diff --git a/src/PJSipManager.h b/src/PJSipManager.h
index 226a674..921455f 100644
--- a/src/PJSipManager.h
+++ b/src/PJSipManager.h
@@ -30,6 +30,8 @@
 
 #include "PJSipSessionModule.h"
 #include "PJSipLoggingModule.h"
+#include "Transports.h"
+#include "SipModule.h"
 #include "PJSipRegistrarModule.h"
 
 namespace AsteriskSCF
@@ -38,18 +40,22 @@ namespace AsteriskSCF
 namespace SipSessionManager
 {
 
-/**
- * This class is responsible for providing
- * access to the pjsip_endpt for the Asterisk
- * SCF SIP component.
+class PJSipManager;
+typedef boost::shared_ptr<PJSipManager> PJSipManagerPtr;
+
+/*
+ * This class is responsible for providing access to the pjsip_endpoint for the Asterisk SCF SIP component.
  *
- * In addition, it provides some common functions
- * that many SIP services will use.
+ * In addition, it provides some common functions that many SIP services will use.
  */
-class PJSipManager
+class PJSipManager : public boost::enable_shared_from_this<PJSipManager>
 {
 public:
-    PJSipManager(const Ice::PropertiesPtr& props);
+
+    static PJSipManagerPtr create(const Ice::PropertiesPtr& properties);
+
+    virtual ~PJSipManager();
+
     /**
      * Get a handle to the PJSipEndpoint for operations
      * that may require it
@@ -66,6 +72,10 @@ public:
      */
     PJSipLoggingModulePtr getLoggingModule();
 
+    pj_caching_pool* getCachingPool();
+    
+    pj_pool_t* getMemoryPool();
+
     /**
      * Get a reference to the PJSIP registrar module
      */
@@ -99,23 +109,23 @@ public:
             const AsteriskSCF::Discovery::SmartProxy<AsteriskSCF::Replication::SipSessionManager::V1::SipStateReplicatorPrx>& stateReplicator,
             Ice::ObjectAdapterPtr& adapter);
 
-    /**
-     * Create a UDP transport.
-     */
-    pjsip_transport *createUDPTransport(std::string, int);
 
+    //
+    // TODO: move this transport collection stuff to a transport manager or something.
+    // PJSipManager does not need it.
+    //
     /**
-     * Create a TCP transport.
-     */
-    pjsip_tpfactory *createTCPTransport(std::string, int);
+     * Add a transport the module. 
+     **/
+    void addTransport(const std::string& id, const TransportPtr& transport);
+    TransportPtr getTransport(const std::string& id);
 
-    /**
-     * Create a TLS transport.
-     */
-    pjsip_tpfactory *createTLSTransport(std::string, int, pjsip_tls_setting*);
+    void addModule(const std::string& id, const SipModulePtr& module);
+    SipModulePtr getModule(const std::string& moduleName);
+
+    void handleEvents();
 
 private:
-    static PJSipManager *mInstance;
     pjsip_endpoint *mEndpoint;
     PJSipSessionModulePtr mSessionModule;
     PJSipLoggingModulePtr mLoggingModule;
@@ -123,12 +133,15 @@ private:
     pj_thread_t *mPjThread;
     pj_caching_pool mCachingPool;
     pj_pool_t *mMemoryPool;
-    pjsip_transport *mUdpTransport;
 
-    bool setTransports(pjsip_endpoint *endpoint, const Ice::PropertiesPtr& props);
-};
+    boost::shared_mutex mLock;
+    SipModuleMap mModules;
+    std::map<std::string, TransportPtr> mTransports;
 
-typedef boost::shared_ptr<PJSipManager> PJSipManagerPtr;
+    void initializeDefaultTransports(const Ice::PropertiesPtr& properties);
+
+    PJSipManager();
+};
 
 /**
  * Wrapper class around pj_thread_desc.
diff --git a/src/PJSipModule.h b/src/PJSipModule.h
index 354f5ba..175dd33 100644
--- a/src/PJSipModule.h
+++ b/src/PJSipModule.h
@@ -16,11 +16,10 @@
 
 #pragma once
 
+#include <pjlib.h>
 #include <string>
-
 #include <pjsip.h>
 #include <pjsip_ua.h>
-#include <pjlib.h>
 
 #include <SipStateReplicationIf.h>
 
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 7128453..221ca19 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -1011,8 +1011,13 @@ void PJSipSessionModule::on_tsx_state(pjsip_transaction*, pjsip_event*)
 class HandleInviteResponseOperation : public SipQueueableOperation
 {
 public:
-    HandleInviteResponseOperation(int respCode, const int invState, const SipSessionPtr& session)
-        : mRespCode(respCode), mInvState(invState), mSession(session) { }
+    HandleInviteResponseOperation(int respCode, const int invState,
+            const SipSessionPtr& session) :
+        mRespCode(respCode),
+        mInvState(invState),
+        mSession(session)
+    {
+    }
 
 protected:
     SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
@@ -1112,7 +1117,8 @@ protected:
         }
         return Complete;
     }
-private:   
+private:
+    pjsip_inv_session* mInviteSession;
     int mRespCode;
     const int mInvState;
     SipSessionPtr mSession;
@@ -1432,9 +1438,10 @@ protected:
         PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)mInv->mod_data[mModuleId];
         SipSessionPtr session = session_mod_info->getSessionPtr();
 
+        //
         // In case there is no stream level connection details store this away
+        //
         std::string destination(pj_strbuf(&remote_sdp->conn->addr), pj_strlen(&remote_sdp->conn->addr));
-
 	StreamSinkSeq sinks = session->getSinks();
 
         // Each stream has its own set of formats, so go to that granularity
@@ -1479,6 +1486,29 @@ protected:
 
             // TODO: Add format parsing stuff here so we can determine the formats actually negotiated
         }
+
+        //
+        // Assuming all of the pre-setup for the sinks/sources went ok, then we can tell
+        // the session to start off any negotiated connections.
+        //
+	try
+        {
+            const pjmedia_sdp_session* local;
+            pj_status_t result = pjmedia_sdp_neg_get_active_local(mInv->neg, &local);
+            if (result == PJ_SUCCESS)
+            {
+                session->startMedia(local, remote_sdp);
+            }
+        }
+	catch (const AsteriskSCF::Media::RTP::V1::InvalidAddress&)
+	{
+	    pjsip_tx_data *packet;
+            if (pjsip_inv_end_session(mInv, 488, NULL, &packet) == PJ_SUCCESS)
+            {
+                pjsip_inv_send_msg(mInv, packet);
+            }
+            return Complete;
+	}
         return Complete;
     }
 
diff --git a/src/PJUtil.h b/src/PJUtil.h
new file mode 100644
index 0000000..c30a1a6
--- /dev/null
+++ b/src/PJUtil.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <pjlib.h>
+
+namespace AsteriskSCF
+{
+namespace SipSessionManager
+{
+
+inline bool success(pj_status_t r)
+{
+    return r == PJ_SUCCESS;
+}
+
+inline bool fail(pj_status_t r)
+{
+    return !success(r);
+}
+
+} /* End of namespace SipSessionManager */
+} /* End of namespace AsteriskSCF */
diff --git a/src/STUNModule.cpp b/src/STUNModule.cpp
new file mode 100644
index 0000000..3678e5e
--- /dev/null
+++ b/src/STUNModule.cpp
@@ -0,0 +1,157 @@
+/*
+ * 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 "STUNModule.h"
+#include <pjlib.h>
+#include <pjnath.h>
+#include <Ice/Properties.h>
+#include <AsteriskSCF/logger.h>
+#include "PJSipManager.h"
+
+#include <pjnath/stun_sock.h>
+#include <pjnath/stun_session.h>
+#include <AsteriskSCF/System/ExceptionsIf.h>
+#include "DebugUtil.h"
+#include "PJUtil.h"
+
+using namespace AsteriskSCF::System::V1;
+using namespace AsteriskSCF::SipSessionManager;
+using namespace AsteriskSCF::System::Logging;
+
+namespace AsteriskSCF
+{
+namespace SipSessionManager
+{
+
+const pj_time_val DEFAULT_PROCESSING_TIMEOUT = { 0 /* seconds */, 100 /* milliseconds */ };
+
+//
+// Public methods.
+//
+STUNModule::~STUNModule()
+{
+    destroyImpl();
+}
+
+void STUNModule::destroy()
+{
+    destroyImpl();
+}
+
+void STUNModule::onHandleEvents()
+{
+    //
+    // Since the STUN module currently has it's own ioqueue and timer heap, we need to run them in a timely
+    // fashion. Every poll of the pjsip library seems appropriate.
+    // TODO: It may be possible to simply use the SIP endpoint's ioqueue for STUN transports, but
+    // this seems safter for the time being.
+    //
+    boost::shared_lock<boost::shared_mutex> lock(mLock);
+    pj_ioqueue_poll(mConfig->ioqueue, mTimeout.get());
+    pj_timer_heap_poll(mConfig->timer_heap, 0);
+}
+
+pj_stun_config* STUNModule::getConfig()
+{
+    return mConfig.get();
+}
+
+pj_pool_t* STUNModule::getPool()
+{
+    return mPool;
+}
+
+//
+// Static public
+//
+boost::shared_ptr<STUNModule> STUNModule::create(const PJSipManagerPtr& sipManager,
+        const Ice::PropertiesPtr& properties, const Logger& logger)
+{
+    logger(Debug) << FUNLOG << " : initializing STUN module";
+    pj_status_t status = pjnath_init();
+    if (fail(status))
+    {
+        const char* message = "Unable to initialize PJNATH library.";
+        logger(Error) << message;
+        throw InternalInitializationException(message);
+    }
+
+    boost::shared_ptr<pj_stun_config> config(new pj_stun_config);
+    
+    //
+    // We set the pool, queue, etc. to 0 because they are initialized later on.
+    // TODO: We may be able to use the main SIP ioqueue and timer heap. If so
+    // we can remove the poll method on this object.
+    //
+    pj_stun_config_init(config.get(), &sipManager->getCachingPool()->factory, 0, 0, 0);
+
+    status = pj_timer_heap_create(sipManager->getMemoryPool(), 
+            properties->getPropertyAsIntWithDefault("Sip.PJSip.TimerHeap.Size", 1000), 
+            &(config->timer_heap));
+    
+    if (fail(status))
+    {
+        //
+        // No far we haven't allocated anything that won't clean up after itself, so we can just throw here.
+        //
+        const char* message = "Unable to initialize timer heap.";
+        logger(Error) << message;
+        throw InternalInitializationException(message);
+    }
+
+    status = pj_ioqueue_create(sipManager->getMemoryPool(), properties->getPropertyAsIntWithDefault("Sip.PJSip.IOQueue.MaxSize", 16), 
+            &(config->ioqueue));
+    if (fail(status))
+    {
+        //
+        // Now we should probably clean up that timer heap!
+        //
+        pj_timer_heap_destroy(config->timer_heap);
+        const char* message = "Unable to initialize IO queue.";
+        logger(Error) << message;
+        throw InternalInitializationException(message);
+    }
+    return STUNModulePtr(new STUNModule(config));
+}
+
+//
+// Protected methods.
+//
+
+/**
+ * Construct the STUNModule object to "hold" the PJNATH STUN resources.
+ * TODO: we might want to make that processing timeout configurable.
+ **/
+STUNModule::STUNModule(const boost::shared_ptr<pj_stun_config>& config) :
+    mConfig(config),
+    mTimeout(new pj_time_val(DEFAULT_PROCESSING_TIMEOUT)),
+    mPool(pj_pool_create(mConfig->pf, "STUNMEMPL", 16 * 1024, 1024, 0))
+{
+}
+
+//
+// Private methods.
+//
+void STUNModule::destroyImpl()
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    pj_ioqueue_destroy(mConfig->ioqueue);
+    pj_timer_heap_destroy(mConfig->timer_heap);
+    pj_pool_release(mPool);
+    mConfig.reset();
+}
+}
+}
diff --git a/src/STUNModule.h b/src/STUNModule.h
new file mode 100644
index 0000000..492b213
--- /dev/null
+++ b/src/STUNModule.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include "SipModule.h"
+#include <Ice/PropertiesF.h>
+
+//
+// Forward declarations.
+//
+struct pj_stun_config;
+struct pj_caching_pool;
+struct pj_time_val;
+struct pj_pool_t;
+
+namespace AsteriskSCF
+{
+namespace System
+{
+namespace Logging
+{
+class Logger;
... 2918 lines suppressed ...


-- 
asterisk-scf/release/sip.git



More information about the asterisk-scf-commits mailing list