[asterisk-scf-commits] asterisk-scf/integration/sip.git branch "srtp-support" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Fri Jul 15 14:29:32 CDT 2011


branch "srtp-support" has been updated
       via  ce3452047ab8259656834884f5a3592378016360 (commit)
       via  fc8f71159530653f06e3217ec733058ce033d4fb (commit)
       via  7d43289b0a830b2c545b4509ca3df7d8dd510186 (commit)
      from  f8d408d74e5c80cd8113668d839a66ada330dfeb (commit)

Summary of changes:
 config/Sip.config                                  |    4 +-
 config/SipConfigurator.py                          |   46 +-
 .../SipSessionManager/SipConfigurationIf.ice       |   48 +-
 .../SipSessionManager/SipStateReplicationIf.ice    |    6 +-
 src/PJSipSessionModule.cpp                         |  205 +++---
 src/SipConfiguration.cpp                           |   25 +-
 src/SipEndpoint.cpp                                |  218 +++++-
 src/SipEndpoint.h                                  |   35 +-
 src/SipSession.cpp                                 |  864 +++++++++++++-------
 src/SipSession.h                                   |   28 +-
 src/SipStateReplicatorListener.cpp                 |    2 +-
 11 files changed, 983 insertions(+), 498 deletions(-)


- Log -----------------------------------------------------------------
commit ce3452047ab8259656834884f5a3592378016360
Merge: f8d408d fc8f711
Author: Brent Eagles <beagles at digium.com>
Date:   Fri Jul 15 14:53:06 2011 -0230

    Merge remote-tracking branch 'origin/master' into srtp-support with resolved conflicts.

diff --cc config/SipConfigurator.py
index 3dca24c,1d34378..07d87d6
--- a/config/SipConfigurator.py
+++ b/config/SipConfigurator.py
@@@ -119,42 -97,6 +119,22 @@@ class SipSectionVisitors(Configurator.S
          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 MapSRTPSupportToValues:
-             def __init__(self, config):
-                 self.config = config
- 
-             def get(self, section, item):
-                 stringVal = self.config.get(section, item)
-                 if stringVal == None:
-                     return AsteriskSCF.Configuration.SipSessionManager.V1.SRTPCryptoSupportOptions.SRTP_DISABLED
-                 v = stringVal.lower()
-                 if v == 'disabled':
-                     return AsteriskSCF.Configuration.SipSessionManager.V1.SRTPCryptoSupportOptions.SRTP_DISABLED
-                 elif v == 'optional':
-                     return AsteriskSCF.Configuration.SipSessionManager.V1.SRTPCryptoSupportOptions.SRTP_OPTIONAL
-                 elif v == 'required':
-                     return AsteriskSCF.Configuration.SipSessionManager.V1.SRTPCryptoSupportOptions.SRTP_REQUIRED
-                 else:
-                     print 'Unrecognized value for SRTP support option. Valid options are disabled, optional or required. Disabling'
-                     return AsteriskSCF.Configuration.SipSessionManager.V1.SRTPCryptoSupportOptions.SRTP_DISABLED
 +                
-         srtpSupportMapper = MapSRTPSupportToValues(config)
 +        item.cryptoKeys = [ AsteriskSCF.Configuration.SipSessionManager.V1.SRTPCryptoKey() ]
-         mapper.map('srtpsupport', item, 'srtpSupportOptions', 'srtpCryptoSettings', srtpSupportMapper.get, None)
-         mapper.map('disableauth', item, 'disableAuthentication', 'srtpCryptoSettings', config.get, None)
-         mapper.map('disableencrption', item, 'disableEncryption', 'srtpCrytpoSettings', config.get, None)
++        mapper.map('enableauth', item, 'enableAuthentication', 'srtpCryptoSettings', config.get, True)
++        mapper.map('enableencryption', item, 'enableEncryption', 'srtpCrytpoSettings', config.get, True)
 +        mapper.map('ciphersuite', item.cryptoKeys[0], 'suite', 'srtpCryptoSettings', config.get, None)
 +        mapper.map('cryptokey', item.cryptoKeys[0], 'cryptoKey', 'srtpCryptoSettings', config.get, None)
 +
          class AllowableCallDirectionTransformer():
              def __init__(self, config):
                  self.config = config
diff --cc slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
index 37cc7a4,f37030d..0a1d091
--- a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
@@@ -32,453 -32,407 +32,427 @@@ module SipSessionManage
  ["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;
 -   };
 -
 -   /**
 -    * 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
 -   {
 -   };
 -
 -   /**
 -    * Target destination address configuration item
 -    */
 -   class SipTargetDestinationAddressItem extends SipHostItem
 -   {
 -   };
 -
 -   /**
 -    * 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;
 -   };
 -
 -   /**
 -    * 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;
 -   };
 -
 -   /**
 -    * 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;
 -   };
 -
 -   /**
 -    * 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
 -   {
 -       /**
 -        * 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;
 -   };
 -
 -   /**
 -    * 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 TCP transport
 -    */
 -   class SipTCPTransportGroup extends SipTransportGroup
 -   {
 -   };
 -
 -   /**
 -    * Group of configuration items related to a TLS transport
 -    */
 -   class SipTLSTransportGroup extends SipTransportGroup
 -   {
 -   };
 +
 +/**
 + * 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;
 +};
 +
 +/**
 + * Generic SIP transport group that others derive from, primarily created since each one has
 + * the requirement of a name
 + */
- ["visitor:SipConfigurationGroupVisitor"] class SipTransportGroup extends SipConfigurationGroup
++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
 + */
- ["visitor:SipConfigurationItemVisitor"] class SipHostItem extends SipConfigurationItem
++class SipHostItem extends SipConfigurationItem
 +{
 +    /**
 +     * String containing the IP address or string address
 +     */
 +    string host;
 +
 +    /**
 +     * Port number
 +     */
 +    int port;
 +};
 +
 +/**
 + * Source transport address configuration item
 + */
- ["visitor:SipConfigurationItemVisitor"] class SipSourceTransportAddressItem extends SipHostItem
++class SipSourceTransportAddressItem extends SipHostItem
 +{
 +};
 +
 +/**
 + * Target destination address configuration item
 + */
- ["visitor:SipConfigurationItemVisitor"] class SipTargetDestinationAddressItem extends SipHostItem
++class SipTargetDestinationAddressItem extends SipHostItem
 +{
 +};
 +
 +/**
 + * 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 support options.
-  */
- enum SRTPCryptoSupportOptions
- {
-     /**
-      * SRTP is completely disabled for this endpoint.
-      */
-     SRTP_DISABLED, 
-     /**
-      * SRTP is optional. This implies media will be encrypted if both ends of a
-      * media flow are properly configured for SRTP, but will still flow even if
-      * they are not.
-      */
-     SRTP_OPTIONAL,
-     /**
-      * SRTP is absolutely required. Media should not flow unless both ends
-      * of a media flow are properly configured for SRTP.
-      */
-     SRTP_REQUIRED
- };
 +    
 +/**
 + * SRTP Crypto Key information.
 + */
 +class SRTPCryptoKey
 +{
 +    /**
 +     * The cipher suite name.
 +     */
 +    string suite;
 +
 +    /**
 +     * The key information for the suite.
 +     */
 +    string cryptoKey;
 +};
 +
 +sequence<SRTPCryptoKey> SRTPCryptoKeySeq;
 +
 +/**
 + * SRTP crypto configuration.
 + */
 +class SRTPCryptoItem extends SipConfigurationItem
 +{
-     /**
-      * Options for the crypto function support.
-      */
-     SRTPCryptoSupportOptions srtpSupportOptions;
 +
 +    /**
-      * Most of the time the following values will be false. They can be overrident to be true however.
++     * Most of the time the following values will be false. They can be overriden to be true however.
 +     */
-     bool disableAuthentication;
-     bool disableEncryption;
++    bool enableAuthentication;
++    bool enableEncryption;
 +
 +    /**
 +     * 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;
 +};
 +
 +/**
 + * 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
 + */
- ["visitor:SipConfigurationGroupVisitor"] class SipUDPTransportGroup extends SipTransportGroup
++class SipUDPTransportGroup extends SipTransportGroup
 +{
 +};
 +
 +/**
 + * Group of configuration items related to a TCP transport
 + */
- ["visitor:SipConfigurationGroupVisitor"] class SipTCPTransportGroup extends SipTransportGroup
++class SipTCPTransportGroup extends SipTransportGroup
 +{
 +};
 +
 +/**
 + * Group of configuration items related to a TLS transport
 + */
- ["visitor:SipConfigurationGroupVisitor"] class SipTLSTransportGroup extends SipTransportGroup
++class SipTLSTransportGroup extends SipTransportGroup
 +{
 +};
 +
 +/**
 + * Group of configuration items related to a STUN enabled transport
 + */
- ["visitor:SipConfigurationGroupVisitor"] class SipSTUNTransportGroup extends SipTransportGroup
++class SipSTUNTransportGroup extends SipTransportGroup
 +{
 +};
  
  }; /* module V1 */
  
diff --cc src/PJSipSessionModule.cpp
index c49776f,7128453..221ca19
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@@ -969,14 -1011,8 +1011,13 @@@ void PJSipSessionModule::on_tsx_state(p
  class HandleInviteResponseOperation : public SipQueueableOperation
  {
  public:
-     HandleInviteResponseOperation(pjsip_inv_session* inv, int respCode, const int invState,
 -    HandleInviteResponseOperation(int respCode, const int invState, const SipSessionPtr& session)
 -        : mRespCode(respCode), mInvState(invState), mSession(session) { }
++    HandleInviteResponseOperation(int respCode, const int invState,
 +            const SipSessionPtr& session) :
-         mInviteSession(inv),
 +        mRespCode(respCode),
 +        mInvState(invState),
 +        mSession(session)
 +    {
 +    }
  
  protected:
      SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
@@@ -1394,118 -1429,56 +1435,80 @@@ protected
  	    return Complete;
          }
  
-         const pjmedia_sdp_conn *remote_conn = remote_sdp->media[0]->conn ? remote_sdp->media[0]->conn : remote_sdp->conn;
- 
          PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)mInv->mod_data[mModuleId];
          SipSessionPtr session = session_mod_info->getSessionPtr();
-         std::string destination(pj_strbuf(&remote_conn->addr), pj_strlen(&remote_conn->addr));
  
++        //
+         // 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
+         for (unsigned int stream = 0; stream < remote_sdp->media_count; stream++)
+         {
+ 	    // Do some sanity checking to confirm we have a stream setup for their answer stream
+             if (sinks.size() < (stream + 1))
+             {
+                 continue;
+             }
+ 
+             // Assume no stream level details until proven otherwise
+             std::string connection = destination;
+             if (remote_sdp->media[stream]->conn)
+             {
+                 connection = std::string(pj_strbuf(&remote_sdp->media[stream]->conn->addr),
+                                          pj_strlen(&remote_sdp->media[stream]->conn->addr));
+             }
+ 
+             // TODO: Add parsing of RTCP attribute
+ 
+             // The order of the media lines should match our offer so we can get the sink to update
+             // connection details on based on what stream number this is, easy!
+             StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(sinks[stream]);
+ 
+             // If this throws an exception then they answered with an address that is incompatible
+             // for the session, so we abort since our relationship with the other side seems to be
+             // broken
+             try
+             {
+                 sink->setRemoteDetails(connection, remote_sdp->media[stream]->desc.port);
+             }
+             catch (const InvalidAddress&)
+             {
+                 pjsip_tx_data *packet;
+                 if (pjsip_inv_end_session(mInv, 488, NULL, &packet) == PJ_SUCCESS)
+                 {
+                     pjsip_inv_send_msg(mInv, packet);
+                 }
+                 return Complete;
+             }
+ 
+             // 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
- 	{
- 	    session->setRemoteDetails(destination, remote_sdp->media[0]->desc.port);
++        {
 +            const pjmedia_sdp_session* local;
 +            pj_status_t result = pjmedia_sdp_neg_get_active_local(mInv->neg, &local);
 +            if (result == PJ_SUCCESS)
 +            {
-                 if (result == PJ_SUCCESS)
-                 {
-                     session->startMedia(local, remote_sdp);
-                 }
++                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;
 +	}
- 
-         // Each stream has its own set of formats, so go to that granularity
-         for (unsigned int stream = 0; stream < remote_sdp->media_count; stream++)
-         {
-             // We should have the parsing of the connection information here
- 
-             // We should have the parsing of the rtcp attribute here
- 
-             FormatSeq formats;
- 
-             // Next step is to see what formats exist on this stream
-             for (unsigned int format = 0; format < remote_sdp->media[stream]->desc.fmt_count; format++)
-             {
-                 FormatDiscoverySDPPtr params = new FormatDiscoverySDP();
-                 params->category = "media_format";
-                 std::stringstream(pj_strbuf(&remote_sdp->media[stream]->desc.fmt[format])) >> params->payload;
-                 params->type = std::string(pj_strbuf(&remote_sdp->media[stream]->desc.media),
-                         pj_strlen(&remote_sdp->media[stream]->desc.media));
- 
-                 // Some devices rely solely on the payload for known formats (such as PCMU) so the following format
-                 // parameters are optional
-                 const pjmedia_sdp_attr *attr;
-                 if ((attr = pjmedia_sdp_media_find_attr2(remote_sdp->media[stream], "rtpmap",
-                                         &remote_sdp->media[stream]->desc.fmt[format])))
-                 {
-                     pjmedia_sdp_rtpmap *rtpmap;
-                     if ((pjmedia_sdp_attr_to_rtpmap(mInv->pool_active, attr, &rtpmap)) == PJ_SUCCESS)
-                     {
-                         params->subtype = std::string(pj_strbuf(&rtpmap->enc_name), pj_strlen(&rtpmap->enc_name));
-                         params->samplerate = rtpmap->clock_rate;
-                     }
-                 }
- 
-                 // Next we move on to the format specific parameters
-                 if ((attr = pjmedia_sdp_media_find_attr2(remote_sdp->media[stream], "fmtp",
-                                         &remote_sdp->media[stream]->desc.fmt[format])))
-                 {
-                     pjmedia_sdp_fmtp fmtp;
-                     if ((pjmedia_sdp_attr_get_fmtp(attr, &fmtp)) == PJ_SUCCESS)
-                     {
-                         std::string parameter = std::string(pj_strbuf(&fmtp.fmt_param), pj_strlen(&fmtp.fmt_param));
-                         params->parameters.push_back(parameter);
-                     }
-                 }
- 
-                 // Next up are attributes that are not specific to the format, such as ptime
-                 for (unsigned int attribute = 0; attribute < remote_sdp->media[stream]->attr_count; attribute++)
-                 {
-                     // Attributes we already touch above OR know aren't helpful to the media format component don't need to
-                     // be given to it, obviously
-                     if (!pj_strcmp2(&remote_sdp->media[stream]->attr[attribute]->name, "rtpmap") ||
-                         !pj_strcmp2(&remote_sdp->media[stream]->attr[attribute]->name, "fmtp") ||
-                         !pj_strcmp2(&remote_sdp->media[stream]->attr[attribute]->name, "rtcp") ||
-                         !pj_strcmp2(&remote_sdp->media[stream]->attr[attribute]->name, "sendrecv") ||
-                         !pj_strcmp2(&remote_sdp->media[stream]->attr[attribute]->name, "sendonly") ||
-                         !pj_strcmp2(&remote_sdp->media[stream]->attr[attribute]->name, "recvonly"))
-                     {
-                         continue;
-                     }
- 
-                     std::string parameter = std::string(pj_strbuf(&remote_sdp->media[stream]->attr[attribute]->name),
-                             pj_strlen(&remote_sdp->media[stream]->attr[attribute]->name)) + ':' +
-                         std::string(pj_strbuf(&remote_sdp->media[stream]->attr[attribute]->value),
-                                 pj_strlen(&remote_sdp->media[stream]->attr[attribute]->value));
-                     params->parameters.push_back(parameter);
-                 }
- 
-                 try
-                 {
-                     MediaFormatServicePrx service = MediaFormatServicePrx::uncheckedCast(mServiceLocator->locate(params));
- 
-                     // It is entirely possible for the service locator to not find a service that knows about this media
-                     // format
-                     if (service != 0)
-                     {
-                         formats.push_back(FormatPtr::dynamicCast(service->getFormat(params)));
-                     }
-                 }
-                 catch (...)
-                 {
-                     // If we get here the format just isn't supported...
-                 }
-             }
-         }
          return Complete;
      }
  
diff --cc src/SipConfiguration.cpp
index 56f40df,d4077a8..3e12ea4
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@@ -189,7 -183,12 +189,7 @@@ class EndpointConfigHelper : public boo
          {
              mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateDirection, mConfig, direction));
          }
-         
+ 
 -	void visitSipMediaFormatItem(const SipMediaFormatItemPtr& format)
 -	{
 -            mUpdates.push_back(boost::bind(&EndpointConfigHelper::addFormat, mConfig, format));
 -	}
 -        
          void visitSipSourceTransportAddressItem(const SipSourceTransportAddressItemPtr& source)
          {
              mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateSource, mConfig, source));
@@@ -294,49 -288,6 +294,32 @@@ public
  	mEndpoint->setSecureTransport(translateCallDirection(transport->secureTransport));
      }
  
 +    void updateSRTP(const SRTPCryptoItemPtr& srtpOptions)
 +    {
-         SipEndpointMediaSRTPConfig srtpConfig;
-         switch (srtpOptions->srtpSupportOptions)
-         {
-         case SRTP_DISABLED:
-             srtpConfig.supportOptions = SipEndpointMediaSRTPConfig::Disabled;
-             break;
- 
-         case SRTP_OPTIONAL:
-             srtpConfig.supportOptions = SipEndpointMediaSRTPConfig::Optional;
-             break;
- 
-         case SRTP_REQUIRED:
-             srtpConfig.supportOptions = SipEndpointMediaSRTPConfig::Required;
-             break;
- 
-         default:
-             assert("Unexpected value" == 0);
-         }
-         srtpConfig.enableEncryption = !srtpOptions->disableEncryption;
-         srtpConfig.enableAuthentication = !srtpOptions->disableAuthentication;
++        SipEndpointMediaSRTPConfig srtpConfig(mEndpoint->getConfig().srtpConfig);
++        srtpConfig.enableEncryption = srtpOptions->enableEncryption;
++        srtpConfig.enableAuthentication = srtpOptions->enableAuthentication;
 +        srtpConfig.cryptoKeys.clear();
 +        if (!srtpOptions->cryptoKeys.empty())
 +        {
 +            CryptoKey newKey;
 +            newKey.suite = srtpOptions->cryptoKeys[0]->suite;
 +            newKey.cryptoKey = srtpOptions->cryptoKeys[0]->cryptoKey;
 +            srtpConfig.cryptoKeys.push_back(newKey);
 +        }
 +        mEndpoint->setSRTPOptions(srtpConfig);
 +    }
 +
 +    void updateMediaNATOptions(const SipMediaNATItemPtr& item)
 +    {
 +        mEndpoint->setMediaNATOptions(item->enableICE, item->enableTURN);
 +    }
 +
 +    void updateSignalingNAT(const SipSignalingNATItemPtr& item)
 +    {
 +        mEndpoint->setSignalingNATOptions(item->stun);
 +    }
 +
      void updated(const UpdateCommandList& updates)
      {
          //
diff --cc src/SipEndpoint.cpp
index b3a7dc8,ac3518a..f0d0e8b
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@@ -21,9 -21,13 +21,14 @@@
  
  #include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
  #include <AsteriskSCF/logger.h>
 +#include "NATOptions.h"
+ #include <AsteriskSCF/Media/MediaIf.h>
+ #include <AsteriskSCF/Media/SDP/MediaSDPIf.h>
  
  using namespace AsteriskSCF::System::Logging;
+ using namespace AsteriskSCF::Media::V1;
+ using namespace AsteriskSCF::Media::SDP::V1;
+ using namespace AsteriskSCF::Core::Discovery::V1;
  
  namespace
  {
@@@ -145,22 -266,20 +270,36 @@@ void SipEndpoint::setRTPOverIPv6(bool e
      mImplPriv->mConfig.sessionConfig.rtpOverIPv6 = enabled;
  }
  
 +void SipEndpoint::setMediaNATOptions(bool useICE, bool useTURN)
 +{
 +    mImplPriv->mConfig.sessionConfig.rtpOverICE = useICE;
 +    mImplPriv->mConfig.sessionConfig.rtpICEIncludeTURN = useTURN;
 +}
 +
 +void SipEndpoint::setSRTPOptions(const SipEndpointMediaSRTPConfig& srtpConfig)
 +{
 +    mImplPriv->mConfig.srtpConfig = srtpConfig;
 +}
 +
 +void SipEndpoint::setSignalingNATOptions(bool enable)
 +{
 +    mImplPriv->mConfig.transportConfig.enableNAT = enable;
 +}
 +
+ void SipEndpoint::addFormat(const std::string& name, int sampleRate, int frameSize, const Ice::StringSeq& formatSpecific)
+ {
+     SDPDescriptorServiceLocatorParamsPtr params = new SDPDescriptorServiceLocatorParams();
+     params->category = "Media/SDP_Descriptor";
+     params->name = name;
+ 
+     ConfiguredFormatPtr configuredFormat = new ConfiguredFormat(name, sampleRate, frameSize, formatSpecific);
+     Callback_ServiceLocator_locatePtr descriptorCB = newCallback_ServiceLocator_locate(
+         configuredFormat, &ConfiguredFormat::locateCB, &ConfiguredFormat::locateFailureCB);
+ 
+     mImplPriv->mFormats.push_back(configuredFormat);
+     mImplPriv->mServiceLocator->begin_locate(params, descriptorCB);
+ }
+ 
  Direction SipEndpointConfig::stringToDirection(const std::string& directionString)
  {
      if (directionString == "Both")
@@@ -229,14 -343,13 +368,15 @@@ AsteriskSCF::SipSessionManager::SipSess
  }
  
  AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const std::string& destination,
-         const Ice::Identity& sessionid, const Ice::Identity& mediaid,
-         const AsteriskSCF::Media::V1::SessionPrx& mediasession, const AsteriskSCF::Media::V1::StreamSourceSeq& sources,
-         const AsteriskSCF::Media::V1::StreamSinkSeq& sinks)
+                                                                          const Ice::Identity& sessionid, const Ice::Identity& mediaid,
+                                                                          const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
+                                                                          const AsteriskSCF::Media::V1::StreamSourceSeq& sources,
+                                                                          const AsteriskSCF::Media::V1::StreamSinkSeq& sinks)
  {
-     SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, sessionid, mediaid, mediasession,
+     SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, sessionid, mediaid, mediasessions,
 -            sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica, false);
 +            sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica, false,
 +            NATEndpointOptions(mImplPriv->mConfig.sessionConfig.rtpOverICE, mImplPriv->mConfig.sessionConfig.rtpICEIncludeTURN,
 +                mImplPriv->mConfig.transportConfig.enableNAT));
      mImplPriv->mSessions.push_back(session);
      return session;
  }
diff --cc src/SipEndpoint.h
index 89f110b,ebf4d87..c6fb482
--- a/src/SipEndpoint.h
+++ b/src/SipEndpoint.h
@@@ -156,44 -142,6 +157,37 @@@ public
      // Whether we are using IPv6 for media transport
      // or not.
      bool rtpOverIPv6;
 +    // 
 +    // Enables ICE transport.
 +    //
 +    bool rtpOverICE;
 +    //
 +    // Enables TURN as a viable mechanism for traversing NATs.
 +    //
 +    bool rtpICEIncludeTURN;
 +
 +    SipEndpointSessionConfig() :
 +        rtpOverIPv6(false),
 +        rtpOverICE(false),
 +        rtpICEIncludeTURN(false)
 +    {
 +    }
 +};
 +
 +class CryptoKey
 +{
 +public:
 +    std::string suite;
 +    std::string cryptoKey;
 +};
 +typedef std::vector<CryptoKey> CryptoKeys;
 +
 +class SipEndpointMediaSRTPConfig
 +{
 +public:
-     enum 
-     {
-         Disabled,
-         Optional,
-         Required
-     } supportOptions;
- 
 +    bool enableAuthentication;
 +    bool enableEncryption;
 +    CryptoKeys cryptoKeys;
  };
  
  /**
@@@ -314,11 -261,24 +314,28 @@@ public
      void setCallDirection(enum Direction);
      void setSecureTransport(enum Direction);
      void setRTPOverIPv6(bool);
+     void addFormat(const std::string& name, int sampleRate, int frameSize, const Ice::StringSeq& formatSpecific);
+ 
+     /**
+      * API call which returns a proxy to an SDP descriptor service given a descriptor.
+      */
+     AsteriskSCF::Media::SDP::V1::SDPDescriptorServicePrx getDescriptorService(
+         const AsteriskSCF::Media::SDP::V1::SDPDescriptorPtr&);
+     
+     /**
+      * API call which returns a descriptor given a media format.
+      */
+     AsteriskSCF::Media::SDP::V1::SDPDescriptorPtr getDescriptor(const AsteriskSCF::Media::V1::FormatPtr&);
+ 
+     /**
+      * API call which returns the stream topology to be used for an SDP offer.
+      */
+     StreamTopologyMap getStreamTopology();
  
 +    void setMediaNATOptions(bool useICE, bool useTURN);
 +    void setSRTPOptions(const SipEndpointMediaSRTPConfig& srtpConfig);
 +    void setSignalingNATOptions(bool enable);
 +
  private:
      /**
       * Private implementation details.
diff --cc src/SipSession.cpp
index 8f613ad,6210963..044455b
mode 100755,100644..100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@@ -27,13 -28,14 +28,16 @@@
  
  #include <AsteriskSCF/System/WorkQueue/WorkQueueIf.h>
  #include <AsteriskSCF/logger.h>
 -#include <AsteriskSCF/Media/MediaIf.h>
 -#include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
 +#include <AsteriskSCF/System/NAT/NATTraversalIf.h>
+ #include <AsteriskSCF/Media/SDP/MediaSDPIf.h>
 +#include "NATOptions.h"
  
  using namespace AsteriskSCF::System::Logging;
 -using namespace AsteriskSCF::Media::V1;
 +using namespace AsteriskSCF::System::NAT::V1;
  using namespace AsteriskSCF::Media::RTP::V1;
++using namespace AsteriskSCF::Media::V1;
+ using namespace AsteriskSCF::Media::SDP::V1;
 +using namespace std;
  
  namespace
  {
@@@ -89,14 -91,11 +93,15 @@@ public
       * Constructor for the SipSessionPriv class.
       */
      SipSessionPriv(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPtr& endpoint,
 -        const std::string& destination, PJSipManager *manager,
 +        const std::string& destination, const PJSipManagerPtr& manager,
          const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
 -        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica)
 +        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
 +        const NATEndpointOptions& natOptions)
          : mAdapter(adapter), mDialog(0), mInviteSession(0), mEndpoint(endpoint), mDestination(destination),
-           mManager(manager), mServiceLocator(serviceLocator), mReplica(replica), mNatOptions(natOptions) 
 -          mManager(manager), mServiceLocator(serviceLocator), mReplica(replica), mSDP(0), mSDPFinalized(false) { };
++          mManager(manager), mServiceLocator(serviceLocator), mReplica(replica), mNatOptions(natOptions), mSDP(0),
++          mSDPFinalized(false)
 +    { 
 +    }
  
      AsteriskSCF::SessionCommunications::V1::SessionInfoPtr getInfo()
      {
@@@ -262,12 -261,30 +267,31 @@@
  
      SessionWorkPtr mSessionWork;
  
 +    NATEndpointOptions mNatOptions;
++
+     /**
+      * SDP that has been produced for this session.
+      */
+     pjmedia_sdp_session *mSDP;
+ 
+     /**
+      * Whether the SDP has been finalized or not.
+      */
+     bool mSDPFinalized;
  };
  
+ /**
+  * Template for allocating from a pool.
+  */
+ template<typename T>
+ inline T *allocate_from_pool(pj_pool_t *pool)
+ {
+     return static_cast<T*>(pj_pool_zalloc(pool, sizeof(T)));
+ }
+ 
  void SipSession::initializePJSIPStructs()
  {
 -    pj_str_t local_uri, remote_uri;
 -    SipEndpointConfig &config = mImplPriv->mEndpoint->getConfig();
 +    SipEndpointConfig& config = mImplPriv->mEndpoint->getConfig();
      
      std::string prefix;
      if (config.transportConfig.secureTransport == OUTBOUND || config.transportConfig.secureTransport == BOTH)
@@@ -422,12 -375,12 +445,12 @@@ SipSession::SipSession(const Ice::Objec
   * Replica constructor.
   */
  SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPtr& endpoint,
 -                       const std::string& destination, const Ice::Identity& sessionid,
 -                       const Ice::Identity& mediaid, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
 -                       const AsteriskSCF::Media::V1::StreamSourceSeq& sources, const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
 -                       PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
 -                       const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC)
 -    : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica))
 +        const std::string& destination, const Ice::Identity& sessionid,
-         const Ice::Identity& mediaid, const AsteriskSCF::Media::V1::SessionPrx& mediasession,
++        const Ice::Identity& mediaid, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
 +        const AsteriskSCF::Media::V1::StreamSourceSeq& sources, const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
 +        const PJSipManagerPtr& manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
 +        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC, const NATEndpointOptions& natOptions)
 +    : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica, natOptions))
  {
      mImplPriv->mSessionProxy =
          AsteriskSCF::SessionCommunications::V1::SessionPrx::uncheckedCast(adapter->add(this, sessionid));
@@@ -1122,13 -1070,12 +1140,106 @@@ void SipSession::destroy(
      enqueueSessionWork(new DestroyOperation(this, mImplPriv));
  }
  
++void SipSession::addKeys(const SipEndpointMediaSRTPConfig& config, pjmedia_sdp_media* mediaSDP)
++{
++    if(!config.cryptoKeys.empty())
++    {
++        //
++        // NOTE: AFAICT, we should really be able to supply multiple potential cyphersuites and keys.
++        // However, the configuration tool doesn't currently support that so what we'll do for now
++        // is provide support in the code and deal with the configuration issue later.
++        //
++        int index = 1;
++        for (CryptoKeys::const_iterator i = config.cryptoKeys.begin();
++             i != config.cryptoKeys.end(); ++i)
++        {
++            char attrbuf[1024];
++            if (i->cryptoKey.empty())
++            {
++                pj_ansi_sprintf(attrbuf, "%d %s", index++, i->suite.c_str());
++            }
++            else
++            {
++                pj_ansi_sprintf(attrbuf, "%d %s inline:%s", index++, i->suite.c_str(), i->cryptoKey.c_str());
++            }
++            pj_str_t srtpAttr = pj_str(attrbuf);
++            pjmedia_sdp_attr* a = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "crypto", &srtpAttr);
++            pjmedia_sdp_attr_add(&mediaSDP->attr_count, mediaSDP->attr, a);
++        }
++    }
++}
++
++void SipSession::addNATAttributes(const SipEndpointSessionConfig& config, const InteractiveConnectionAgentPrx& iceAgent,
++    pjmedia_sdp_session* mediaSession)
++{
++    if (!iceAgent || mediaSession == 0)
++    {
++        return;
++    }
++
++    if (config.rtpOverICE)
++    {
++        string natType = boost::lexical_cast<string>(static_cast<unsigned>(iceAgent->getNATType()));
++        pj_str_t natTypeStr = pj_str(const_cast<char*>(natType.c_str()));
++        pjmedia_sdp_attr* a = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "X-nat", &natTypeStr);
++        pjmedia_sdp_attr_add(&mediaSession->attr_count, mediaSession->attr, a);
++    }
++}
++
++void SipSession::addCandidates(const SipEndpointSessionConfig& config, const InteractiveConnectionAgentPrx& iceAgent,
++    pjmedia_sdp_media* mediaSDP)
++{
++    if (!iceAgent || mediaSDP == 0)
++    {
++        return;
++    }
++
++    if (config.rtpOverICE)
++    {
++        CandidateSeq candidates = iceAgent->getCandidates();
++        for (CandidateSeq::const_iterator j = candidates.begin(); j != candidates.end(); ++j)
++        {
++            CandidatePtr candidate = *j;
++            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();
++            lg(Debug) << "Adding candidate :" << t;
++            pj_str_t candidateStr = pj_str(const_cast<char*>(t.c_str()));
++            pjmedia_sdp_attr* newAttribute = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, 
++                "candidate", &candidateStr);
++            pjmedia_sdp_attr_add(&mediaSDP->attr_count, mediaSDP->attr, newAttribute);
++        }
++    }
++}
++
  /**
-  * Internal function called to produce an SDP session structure.
+  * Internal function called to produce an SDP session structure without any streams.
   */
- pjmedia_sdp_session *SipSession::createSDPOffer()
+ pjmedia_sdp_session *SipSession::createSDP()
  {
-     pjmedia_sdp_session *sdp = static_cast<pjmedia_sdp_session*>(
-         pj_pool_zalloc(mImplPriv->mDialog->pool, sizeof(pjmedia_sdp_session)));
+     pjmedia_sdp_session *sdp = allocate_from_pool<pjmedia_sdp_session>(mImplPriv->mDialog->pool);
  
      pj_strdup2(mImplPriv->mDialog->pool, &sdp->origin.user, "AsteriskSCF");
      pj_time_val tv;
@@@ -1136,284 -1083,418 +1247,452 @@@
      sdp->origin.version = sdp->origin.id = (pj_uint32_t) (tv.sec + 2208988800UL);
      pj_strdup2(mImplPriv->mDialog->pool, &sdp->origin.net_type, "IN");
  
-     // Right now we only support a single stream so go and get it
-     AsteriskSCF::Media::RTP::V1::StreamSourceRTPPrx stream =
-         AsteriskSCF::Media::RTP::V1::StreamSourceRTPPrx::uncheckedCast(mImplPriv->mSources.front());
+     sdp->origin.addr = *pj_gethostname();
  
-     std::string address = stream->getLocalAddress();
-     AsteriskSCF::Helpers::AddressPtr streamAddr(new AsteriskSCF::Helpers::Address(stream->getLocalAddress(), 
-             stream->getLocalPort()));
+     std::string address = std::string(pj_strbuf(&sdp->origin.addr), pj_strlen(&sdp->origin.addr));
  
-     if (streamAddr->isIPV6())
 -    lg(Debug) << "The local address we are placing in our SDP is " << address;
 -    if (address.find(":") != std::string::npos)
++    if (address.find(':') != string::npos)
      {
- 	pj_strdup2(mImplPriv->mDialog->pool, &sdp->origin.addr_type, "IP6");
+         pj_strdup2(mImplPriv->mDialog->pool, &sdp->origin.addr_type, "IP6");
      }
      else
      {
- 	pj_strdup2(mImplPriv->mDialog->pool, &sdp->origin.addr_type, "IP4");
+         pj_strdup2(mImplPriv->mDialog->pool, &sdp->origin.addr_type, "IP4");
      }
  
-     sdp->origin.addr = *pj_gethostname();
      sdp->name = sdp->origin.user;
-     sdp->time.start = 0;
-     sdp->time.stop = 0;
-     sdp->attr_count = 0;
--
-     // Add connection details at the session level since we currently only support one media stream.
-     sdp->conn = static_cast<pjmedia_sdp_conn*>(pj_pool_zalloc(mImplPriv->mDialog->pool, sizeof(pjmedia_sdp_conn)));
-     sdp->conn->net_type = sdp->origin.net_type;
-     sdp->conn->addr_type = sdp->origin.addr_type;
-     pj_strdup2(mImplPriv->mDialog->pool, &sdp->conn->addr, address.c_str());
-     
-     SipEndpointConfig config = mImplPriv->mEndpoint->getConfig();
+     return sdp;
+ }
  
-     // Add a single media stream
-     sdp->media_count = 1;
-     pjmedia_sdp_media* media =
-         static_cast<pjmedia_sdp_media*>(pj_pool_zalloc(mImplPriv->mDialog->pool, sizeof(pjmedia_sdp_media)));
-     sdp->media[0] = media;
-     pj_strdup2(mImplPriv->mDialog->pool, &media->desc.media, "audio");
-     media->desc.port = (pj_uint16_t) stream->getLocalPort();
-     media->desc.port_count = 1;
-     if (config.srtpConfig.supportOptions == SipEndpointMediaSRTPConfig::Disabled)
-     {
-         pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "RTP/AVP");
-     }
-     else
+ /**
+  * Internal function called to add formats to an SDP media stream
+  */
+ void SipSession::addFormatstoSDP(const FormatSeq& formats, pjmedia_sdp_media *media, PayloadMap& payloads)
+ {
+     // Start dynamic payload assignment at 96
+     int dynamicPayload = 96;
+ 
+     // Iterate through each format adding it to the SDP
+     for (FormatSeq::const_iterator mediaformat = formats.begin();
+          mediaformat != formats.end();
+          ++mediaformat)
      {
-         pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "RTP/SAVP");
-     }
+         // Attempt to get our configured descriptor
+         SDPDescriptorPtr ourDescriptor = mImplPriv->mEndpoint->getDescriptor((*mediaformat));
  
-     // Populate the stream with codec details
-     sdp->media[0]->desc.fmt_count = 1;
-     sdp->media[0]->attr_count = 0;
+         // This should not happen... if we can not get our descriptor then there is a disassociation
+         // between their SDP and our SDP
+         if (!ourDescriptor)
+         {
+             continue;
+         }
  
-     // TODO: We should iterate over the formats to produce this instead of hardcoding
-     pjmedia_sdp_rtpmap rtpmap;
-     pjmedia_sdp_attr *attr;
+         int payload = ourDescriptor->payload;
  
-     if (config.srtpConfig.supportOptions != SipEndpointMediaSRTPConfig::Disabled &&
-             !config.srtpConfig.cryptoKeys.empty())
-     {
-         //
-         // NOTE: AFAICT, we should really be able to supply multiple potential cyphersuites and keys.
-         // However, the configuration tool doesn't currently support that so what we'll do for now
-         // is provide support in the code and deal with the configuration issue later.
-         //
-         int index = 1;
-         for (CryptoKeys::const_iterator i = config.srtpConfig.cryptoKeys.begin();
-              i != config.srtpConfig.cryptoKeys.end(); ++i)
+         // If we have been told to assign a dynamic payload ourselves do so
+         if (payload == -1)
          {
-             char attrbuf[1024];
-             if (i->cryptoKey.empty())
+             // Ensure we don't assign a payload that has been specified by checking the payload -> format mapping
+             for (; dynamicPayload < 130; dynamicPayload++)
              {
-                 pj_ansi_sprintf(attrbuf, "%d %s", index++, i->suite.c_str());
+                 if (payloads.find(dynamicPayload) == payloads.end())
+                 {
+                     payload = dynamicPayload;
+                     break;
+                 }
              }
-             else
+ 
+             // If the payload still has not been decided we have no more room in the dynamic payload range
+             if (payload == -1)
              {
-                 pj_ansi_sprintf(attrbuf, "%d %s inline:%s", index++, i->suite.c_str(), i->cryptoKey.c_str());
+                 continue;
              }
-             pj_str_t srtpAttr = pj_str(attrbuf);
-             pjmedia_sdp_attr* a = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "crypto", &srtpAttr);
-             pjmedia_sdp_attr_add(&sdp->media[0]->attr_count, sdp->media[0]->attr, a);
          }
-     }
  
-     // This is hardcoded value for ULAW for now
-     pj_strdup2(mImplPriv->mDialog->pool, &media->desc.fmt[0], "0");
-     rtpmap.pt = media->desc.fmt[0];
-     rtpmap.clock_rate = 8000;
-     pj_strdup2(mImplPriv->mDialog->pool, &rtpmap.enc_name, "PCMU");
-     rtpmap.param.slen = 0;
-     pjmedia_sdp_rtpmap_to_attr(mImplPriv->mDialog->pool, &rtpmap, &attr);
-     sdp->media[0]->attr[sdp->media[0]->attr_count++] = attr;
- 
-     // Might as well add sendrecv
-     attr = static_cast<pjmedia_sdp_attr*>(pj_pool_zalloc(mImplPriv->mDialog->pool, sizeof(pjmedia_sdp_attr)));
-     pj_strdup2(mImplPriv->mDialog->pool, &attr->name, "sendrecv");
-     sdp->media[0]->attr[sdp->media[0]->attr_count++] = attr;
-         
-     if (config.sessionConfig.rtpOverICE)
-     {
-         lg(Debug) << "RTP over ICE enabled, retrieving and encoding candidates";
-         bool sdpAttrSet = false;
-         size_t mediaIndex = 0;
-         std::vector<AsteriskSCF::Media::RTP::V1::RTPSessionPrx> sessions = mImplPriv->mRTPSessions;
-         for (std::vector<AsteriskSCF::Media::RTP::V1::RTPSessionPrx>::const_iterator i = sessions.begin();
-             i != sessions.end(); ++i)
+         // Add the format to the 'm' line
+         pj_strdup2(mImplPriv->mDialog->pool, &media->desc.fmt[media->desc.fmt_count++],
+                    boost::lexical_cast<std::string>(payload).c_str());
+ 
+         // Add an rtpmap attribute line for the format
+         pjmedia_sdp_rtpmap rtpmap;
+         pjmedia_sdp_attr *attr;
+ 
+         rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
+         rtpmap.clock_rate = ourDescriptor->samplerate;
+         pj_strdup2(mImplPriv->mDialog->pool, &rtpmap.enc_name, ourDescriptor->subtype.c_str());
+         rtpmap.param.slen = 0;
+         pjmedia_sdp_rtpmap_to_attr(mImplPriv->mDialog->pool, &rtpmap, &attr);
+         media->attr[media->attr_count++] = attr;
+ 
+         // Add any fmtp attributes for the format
+         for (SDPFormatParameterSeq::const_iterator parameter = ourDescriptor->parameters.begin();
+              parameter != ourDescriptor->parameters.end();
+              ++parameter)
          {
-             InteractiveConnectionAgentPrx natFacet = InteractiveConnectionAgentPrx::checkedCast(*i, 
-                 InteractiveConnectionAgentFacetName);
-             if (natFacet)
-             {
-                 CandidateSeq candidates = natFacet->getCandidates();
-                 if (!sdpAttrSet)
-                 {
-                     pj_str_t natTypeStr;
-                     char natTypeBuf[20];
-                     //
-                     // TODO: proper enum mapping function, just in case!
-                     //
-                     pj_ansi_sprintf(natTypeBuf, "%d", static_cast<unsigned>(natFacet->getNATType()));
-                     natTypeStr = pj_str(natTypeBuf);
-                     pjmedia_sdp_attr* a = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "X-nat", &natTypeStr);
-                     pjmedia_sdp_attr_add(&sdp->attr_count, sdp->attr, a);
-                     sdpAttrSet = true;
-                 }
-                 ///
-                 // create candidate lines!
-                 //
-                 pjmedia_sdp_media* currentMedia = sdp->media[mediaIndex];
-                 //
-                 // TODO - ice user & password
-                 //
-                 for (CandidateSeq::const_iterator j = candidates.begin(); j != candidates.end(); ++j)
-                 {
-                     CandidatePtr candidate = *j;
-                     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();
-                     lg(Debug) << "Adding candidate :" << t;
-                     pj_str_t candidateStr = pj_str(const_cast<char*>(t.c_str()));
-                     pjmedia_sdp_attr* newAttribute = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, 
-                         "candidate", &candidateStr);
-                     pjmedia_sdp_attr_add(&currentMedia->attr_count, currentMedia->attr, newAttribute);
-                 }
-             }
-             break; // XXX - we are currently only dealing with one media stream.. this loop really should be over the
-                    // whole thing.
+             attr = allocate_from_pool<pjmedia_sdp_attr>(mImplPriv->mDialog->pool);
+             std::string parameters = "fmtp:" + boost::lexical_cast<std::string>(payload) + " " + (*parameter);
+             pj_strdup2(mImplPriv->mDialog->pool, &attr->name, parameters.c_str());
+             media->attr[media->attr_count++] = attr;
          }
+ 
+         payloads.insert(std::make_pair(payload, (*mediaformat)));
      }
  }
  
  /**
-  * Internal function called to request needed RTP sessions. 
-  * NOTE: this only gets called from the constructor so locking is not an issue.
+  * Internal function called to produce an SDP session structure using configuration.
   */
- void SipSession::requestRTPSessions(AsteriskSCF::Media::V1::FormatSeq& formats, bool ipv6)
+ pjmedia_sdp_session *SipSession::createSDPOffer()
  {
-     // TODO: This needs to be improved for multiple streams
- 
-     AsteriskSCF::Media::RTP::V1::RTPServiceLocatorParamsPtr params;
+     // If SDP has already been produced then just return it, don't recreate it
+     if (mImplPriv->mSDPFinalized == true)
+     {
+         return mImplPriv->mSDP;
+     }
  
-     SipEndpointConfig config = mImplPriv->mEndpoint->getConfig();
+     // Retrieve the stream topology from the endpoint
+     StreamTopologyMap streams = mImplPriv->mEndpoint->getStreamTopology();
  
-     //
-     // We allocate streams with ICE features enabled by providing alternate
-     // parameters to locate and allocate methods.
-     //
-     if (mImplPriv->mNatOptions.enableICE)
+     // If there are no streams then we can not create an SDP offer
+     if (streams.empty())
      {
-         AsteriskSCF::Media::RTP::V1::RTPOverICEServiceLocatorParamsPtr iceParams = 
-             new AsteriskSCF::Media::RTP::V1::RTPOverICEServiceLocatorParams;
-         params = iceParams;
-         iceParams->enableRTPOverICE = true;
-         iceParams->enableTURN = mImplPriv->mNatOptions.enableTURN;
+         return 0;
      }
-     else
+ 
+     // Create the most common part of the SDP if not already done
+     if (!mImplPriv->mSDP)
      {
-         params = new AsteriskSCF::Media::RTP::V1::RTPServiceLocatorParams;
+         mImplPriv->mSDP = createSDP();
      }
-     params->category = "rtp";
-     params->formats = formats;
-     params->ipv6 = ipv6;
-     params->srtpCapable = (config.srtpConfig.supportOptions != SipEndpointMediaSRTPConfig::Disabled);
  
-     try
++    SipEndpointConfig config = mImplPriv->mEndpoint->getConfig();
++
+     // Iterate through each stream present in the topology
+     for (StreamTopologyMap::const_iterator stream = streams.begin();
+          stream != streams.end();
+          ++stream)
      {
-         AsteriskSCF::Media::RTP::V1::RTPMediaServicePrx factory =
-             AsteriskSCF::Media::RTP::V1::RTPMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
-         if (!factory)
 -        RTPServiceLocatorParamsPtr params = new RTPServiceLocatorParams();
++        RTPServiceLocatorParamsPtr params;
++        if (mImplPriv->mNatOptions.enableICE)
 +        {
-             assert("Location request has returned a nil proxy, this should throw!" == 0);
-             //
-             // TODO: throw!
-             //
++            AsteriskSCF::Media::RTP::V1::RTPOverICEServiceLocatorParamsPtr iceParams = 
++                new AsteriskSCF::Media::RTP::V1::RTPOverICEServiceLocatorParams;
++            params = iceParams;
++            iceParams->enableRTPOverICE = true;
++            iceParams->enableTURN = mImplPriv->mNatOptions.enableTURN;
 +        }
-         AsteriskSCF::Media::RTP::V1::RTPSessionPrx session = factory->allocate(params);
++        else
++        {
++            params = new AsteriskSCF::Media::RTP::V1::RTPServiceLocatorParams;
++        }
+         params->category = "rtp";
+         params->formats = stream->second;
 -        params->ipv6 = mImplPriv->mEndpoint->getConfig().sessionConfig.rtpOverIPv6;
++        params->ipv6 = config.sessionConfig.rtpOverIPv6;
++        params->srtpCapable = (!config.srtpConfig.cryptoKeys.empty());
+ 
+         // Try to find a factory for RTP sessions matching what we need
+         RTPMediaServicePrx factory = RTPMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
  
-         if (!session)
+         // If none exist we can't provide the stream
+         if (factory == 0)
          {
-             assert("Allocation of rtp streams failed! This should've thrown an exception!" == 0);
-             //
-             // TODO Throw!
-             //
+             continue;
+         }
+ 
+         // Allocate a new RTP session to carry the media formats we have in common
+         RTPSessionPrx session = factory->allocate(params);
+ 
+         // Double check to make sure they actually gave us a sesson back... they could have had a problem
+         if (session == 0)
+         {
+             continue;
          }
+ 
+         // RTP sessions should only provide a single sink, so grab it and update the connection details with that
+         // of the remote party
+         StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(session->getSinks().front());
+         mImplPriv->mSinks.push_back(sink);
+ 
+         // Ditto goes for source
+         StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(session->getSources().front());
+         mImplPriv->mSources.push_back(source);
+ 
+         // Update the SIP session with some RTP session details
          mImplPriv->mRTPSessions.push_back(session);
  
-         // Create a local copy of the sources, this won't get changed by the RTP session so it's all good
-         mImplPriv->mSources = session->getSources();
+         // Add the stream to the SDP
+         pjmedia_sdp_media *media = allocate_from_pool<pjmedia_sdp_media>(mImplPriv->mDialog->pool);
+         mImplPriv->mSDP->media[mImplPriv->mSDP->media_count++] = media;
+         pj_strdup2(mImplPriv->mDialog->pool, &media->desc.media, mImplPriv->mEndpoint->getDescriptor(stream->second.front())->type.c_str());
  
-         // Create a local copy of the sinks, this won't get changed by the RTP session so it's all good
-         mImplPriv->mSinks = session->getSinks();
 -        // TODO: This should not be hardcoded
 -        pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "RTP/AVP");
++        if (config.srtpConfig.cryptoKeys.empty())
++        {
++            pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "RTP/AVP");
++        }
++        else
++        {
++            pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "RTP/SAVP");
++        }
  
-         // For testing push a static payload mapping for ULAW into the RTP session
-         AsteriskSCF::Media::RTP::V1::PayloadMap payloads;
-         AsteriskSCF::Media::V1::AudioFormatPtr format = new AsteriskSCF::Media::V1::AudioFormat();
-         format->name = "ulaw";
-         format->sampleRate = 8000;
-         format->frameSize = 20;
-         format->maximumFrameSize = 20;
-         format->minimumFrameSize = 20;
-         payloads.insert(std::make_pair(0, format));
+         // Add connection level details
+         media->conn = allocate_from_pool<pjmedia_sdp_conn>(mImplPriv->mDialog->pool);
+         pj_strdup2(mImplPriv->mDialog->pool, &media->conn->net_type, "IN");
  
-         session->associatePayloads(payloads);
+         if (params->ipv6 == true)
+         {
+             pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP6");
+         }
+         else
+         {
+             pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP4");
+         }
  
-         if (params->srtpCapable && !config.srtpConfig.cryptoKeys.empty())
+         pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr, source->getLocalAddress().c_str());
+ 
+         // If session level connection information has not yet been set then set it to us
+         if (!mImplPriv->mSDP->conn)
          {
-             SRTPSessionPrx srtpPrx = SRTPSessionPrx::checkedCast(session);
-             if (!srtpPrx && config.srtpConfig.supportOptions == SipEndpointMediaSRTPConfig::Required)
-             {
-                 //
-                 // TODO throw.
-                 //
... 480 lines suppressed ...


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list