[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
Tue Aug 2 11:35:13 CDT 2011


branch "master" has been updated
       via  f738f0c7b03d342bae114b88c46fc0a70d22e5ec (commit)
       via  9404329a8b8249a38809c708bfa55092635f2c92 (commit)
       via  6f8904c6e789bb9aa71600da73ab81cc06563572 (commit)
       via  f76eb1c42e1d092c857ab97b1b4d16217117eb72 (commit)
       via  857167eac79c21b941df3c6da33e18a781ce0200 (commit)
       via  4e0d5ca1bd9541b4008fc6509d1d35b023d8da85 (commit)
       via  8ad92e0f71d3a6c512290a47009599745b331a49 (commit)
       via  7f73fcd33096ed9ae2e62f766d16fe8b5cc14ff0 (commit)
       via  e808b0bd8e49f3db8b3a4dbb96c8f864b2516d3b (commit)
       via  3e10abd5f24d590a9473631e26f3388d948bb1aa (commit)
       via  460e021559101b15e5f4b6cc26ed6ccdaf32635a (commit)
       via  a6c749627f93884ec497b66cafa0f3fe21afb7d6 (commit)
       via  9c6e22b59b6f63216629692f7aaad9aef61af856 (commit)
       via  36a1f7d1dda63edfeb93da238084c6be4e63d330 (commit)
       via  a40b4875461e729ed6e2d04881f163c209ab269f (commit)
       via  4f837a1a907c55ee0ee181b9efca036fffa42cf9 (commit)
       via  1cd868e3e2c2b46501aa3c37fc92275349befc2f (commit)
       via  7fbb239ffea714b04ecd722e176b42d6c2e8b6f6 (commit)
       via  63876621702e4612a815f0ec09e8876ae1b1b969 (commit)
       via  25a7e17f104524927281ffdccb402e250d55441d (commit)
       via  7199e1b3e192331a72ef0b7a4565efcbcd84b6a3 (commit)
       via  1bc6f6ab98e4cb6d5700c0e738fce54417bd1ca3 (commit)
       via  bc7436f4c69f1f9c68fcbd5d5d0da32100c8f83d (commit)
       via  f10ab08b0e4f1226ad2ba213d98c2ab905f41b51 (commit)
       via  c3251d20e8eebdcc809f906abd0b021dd3c20045 (commit)
       via  548ff031608447bea09380e34f582050fb2ffbe9 (commit)
       via  26d2049b6e33bd12b5c522a0b15cd9da38c600ed (commit)
       via  5cd389dd2155476fee88c9464bf0e5b6d2a1ab37 (commit)
       via  61fe208d8f18a300137f4ea96518d1747cec2be8 (commit)
       via  b6c7ea6815ff93f17fd2355ef5f003712e0242fe (commit)
       via  de27bed2a112156fcd9d5af46ecb60bddc136554 (commit)
       via  6fed3a431208755055ab5a0cb697e8777e5a221c (commit)
       via  da5441b188e598254eb9d2cab3334341dec56f8e (commit)
       via  866381522f6a26c53e5395989ea8ee433c0e9d59 (commit)
       via  c93b75ba3affcf73ae553eb1a1913e92d40ff4fe (commit)
       via  5c240c011c171b75972122011149a30185945e04 (commit)
       via  33e084958ef7f2b355feb8f585d7a95c0a6ac94c (commit)
       via  c10b4677e95ed80276fd8b712e394c98c8692794 (commit)
       via  a815ad12e32d57dc4ece7488fe72ce0e82f5e4d9 (commit)
       via  bd25df69bafa9d87b5c427a11422fc0c0c0fc5bd (commit)
       via  5c5e10ab63ed39300e37d63cac1f8154956db1a5 (commit)
      from  753d3c79491352932e066826a03c3bd831e5a58f (commit)

Summary of changes:
 config/SipConfigurator.py                          |   15 ++
 .../SipSessionManager/SipConfigurationIf.ice       |   18 ++
 src/CMakeLists.txt                                 |    4 +
 src/PJSipSessionModule.cpp                         |  249 +++++++++++++++++++-
 src/PJSipSessionModule.h                           |    4 +
 src/SipConfiguration.cpp                           |    8 +
 src/SipEndpoint.cpp                                |   11 +-
 src/SipEndpoint.h                                  |    5 +
 src/SipSession.cpp                                 |  138 ++++++++++-
 src/SipSession.h                                   |   43 +++-
 src/SipTelephonyEventSink.cpp                      |  220 +++++++++++++++++
 src/SipTelephonyEventSink.h                        |   61 +++++
 src/SipTelephonyEventSource.cpp                    |  108 +++++++++
 src/SipTelephonyEventSource.h                      |   63 +++++
 14 files changed, 924 insertions(+), 23 deletions(-)
 create mode 100644 src/SipTelephonyEventSink.cpp
 create mode 100644 src/SipTelephonyEventSink.h
 create mode 100644 src/SipTelephonyEventSource.cpp
 create mode 100644 src/SipTelephonyEventSource.h


- Log -----------------------------------------------------------------
commit f738f0c7b03d342bae114b88c46fc0a70d22e5ec
Merge: 753d3c7 9404329
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Aug 2 11:34:19 2011 -0500

    Merge branch 'telephone-events'
    
    Conflicts:
    	slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
    	src/PJSipSessionModule.cpp
    	src/PJSipSessionModule.h
    	src/SipConfiguration.cpp
    	src/SipEndpoint.cpp
    	src/SipEndpoint.h
    	src/SipSession.cpp
    	src/SipSession.h

diff --cc slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
index 715e039,e2a477f..9cdafe8
--- a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
@@@ -32,458 -32,426 +32,476 @@@ 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;
 -   };
 +/**
 + * Service locator category for finding the configuration service
 + */
 +const string ConfigurationDiscoveryCategory = "SipConfiguration";
  
 -   /**
 -    * Local visitor class for visiting SIP configuration groups
 -    */
 -   local class SipConfigurationGroupVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationGroupVisitor
 -   {
 -   };
 +/**
 + * 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;
 +};
  
 -   /**
 -    * Generic SIP configuration group
 -    */
 -   ["visitor:SipConfigurationGroupVisitor"] class SipConfigurationGroup extends AsteriskSCF::System::Configuration::V1::ConfigurationGroup
 -   {
 -   };
 +/**
 + * Local visitor class for visiting SIP configuration groups
 + */
 +local class SipConfigurationGroupVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationGroupVisitor
 +{
 +};
  
 -   /**
 -    * General SIP configuration group that contains general items related to the SIP component as a whole
 -    */
 -   class SipGeneralGroup extends SipConfigurationGroup
 -   {
 -   };
 +/**
 + * Generic SIP configuration group
 + */
 +["visitor:SipConfigurationGroupVisitor"] class SipConfigurationGroup extends AsteriskSCF::System::Configuration::V1::ConfigurationGroup
 +{
 +};
  
 -   /**
 -    * Local visitor class for visiting SIP configuration items
 -    */
 -   local class SipConfigurationItemVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationItemVisitor
 -   {
 -   };
 +/**
 + * General SIP configuration group that contains general items related to the SIP component as a whole
 + */
 +class SipGeneralGroup extends SipConfigurationGroup
 +{
 +};
  
 -   /**
 -    * Generic SIP configuration item
 -    */
 -   ["visitor:SipConfigurationItemVisitor"] class SipConfigurationItem extends AsteriskSCF::System::Configuration::V1::ConfigurationItem
 -   {
 -   };
 +/**
 + * Local visitor class for visiting SIP configuration items
 + */
 +local class SipConfigurationItemVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationItemVisitor
 +{
 +};
  
 -   /**
 -    * SIP Endpoint group, used to configure an endpoint
 -    */
 -   class SipEndpointGroup extends SipConfigurationGroup
 -   {
 -      /**
 -       * Name of the endpoint being configured
 -       */
 -      string name;
 -   };
 +/**
 + * Generic SIP configuration item
 + */
 +["visitor:SipConfigurationItemVisitor"] class SipConfigurationItem extends AsteriskSCF::System::Configuration::V1::ConfigurationItem
 +{
 +};
  
 -   /**
 -    * SIP Domain group, used to configure a specific domain
 -    */
 -   class SipDomainGroup extends SipConfigurationGroup
 -   {
 -      /**
 -       * Name of the domain being configured
 -       */
 -      string domain;
 -   };
 +/**
 + * SIP Endpoint group, used to configure an endpoint
 + */
 +class SipEndpointGroup extends SipConfigurationGroup
 +{
 +    /**
 +     * Name of the endpoint being configured
 +     */
 +    string name;
 +};
  
 -   /**
 -    * Domain item for bindings
 -    */
 -   class SipBindingsItem extends SipConfigurationItem
 -   {
 -      /**
 -       * Addresses the domain is reachable over
 -       */
 -      Ice::StringSeq bindings;
 -   };
 +/**
 + * SIP Domain group, used to configure a specific domain
 + */
 +class SipDomainGroup extends SipConfigurationGroup
 +{
 +    /**
 +     * Name of the domain being configured
 +     */
 +    string domain;
 +};
  
 -   /**
 -    * 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;
 -   };
 +/**
 + * Domain item for bindings
 + */
 +class SipBindingsItem extends SipConfigurationItem
 +{
 +    /**
 +     * Addresses the domain is reachable over
 +     */
 +    Ice::StringSeq bindings;
 +};
  
 -   /**
 -    * Host information configuration item
 -    */
 -   class SipHostItem extends SipConfigurationItem
 -   {
 -      /**
 -       * String containing the IP address or string address
 -       */
 -      string host;
 -
 -      /**
 -       * Port number
 -       */
 -      int port;
 -   };
 +/**
 + * 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;
 +};
  
 -   /**
 -    * Source transport address configuration item
 -    */
 -   class SipSourceTransportAddressItem extends SipHostItem
 -   {
 -   };
 +/**
 + * Host information configuration item
 + */
 +class SipHostItem extends SipConfigurationItem
 +{
 +    /**
 +     * String containing the IP address or string address
 +     */
 +    string host;
  
 -   /**
 -    * Target destination address configuration item
 -    */
 -   class SipTargetDestinationAddressItem extends SipHostItem
 -   {
 -   };
 +    /**
 +     * Port number
 +     */
 +    int port;
 +};
  
 -   /**
 -    * 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;
 -   };
 +/**
 + * Source transport address configuration item
 + */
 +class SipSourceTransportAddressItem extends SipHostItem
 +{
 +};
  
 -   /**
 -    * 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;
 -   };
 +/**
 + * Target destination address configuration item
 + */
 +class SipTargetDestinationAddressItem extends SipHostItem
 +{
 +};
  
 -   /**
 -    * TLS protocol methods
 -    */
 -   enum TLSProtocolMethod
 -   {
 -       PROTOCOLMETHODUNSPECIFIED,
 -       PROTOCOLMETHODTLSV1,
 -       PROTOCOLMETHODSSLV2,
 -       PROTOCOLMETHODSSLV3,
 -       PROTOCOLMETHODSSLV23,
 -   };
 +/**
 + * Crypto certificate configuration item
 + */
 +class SipCryptoCertificateItem extends SipConfigurationItem
 +{
 +    /**
 +     * Full location of certificate authority file
 +     */
 +    string certificateAuthority;
  
 -   /**
 -    * 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;
 -   };
 +    /**
 +     * Full location of certificate file
 +     */
 +    string certificate;
  
 -   /**
 -    * Routing service configuration item
 -    */
 -   class SipRoutingItem extends SipConfigurationItem
 -   {
 -      /**
 -       * Name of the routing service to use
 -       */
 -      string routingServiceName;
 -   };
 +    /**
 +     * Full location of private key file
 +     */
 +    string privateKey;
  
 -   /**
 -    * 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;
 -   };
 +    /**
 +     * Password to open private key file
 +     */
 +    string privateKeyPassword;
 +};
  
 -   /**
 -    * Signaling NAT configuration item
 -    */
 -   class SipSignalingNATItem extends SipConfigurationItem
 -   {
 -      /**
 -       * Boolean for whether STUN is enabled
 -       */
 -      bool stun;
 -   };
 +/**
 + * Crypto requirement configuration item
 + */
 +class SipCryptoRequirementsItem extends SipConfigurationItem
 +{
 +    /**
 +     * Require verification of server certificate
 +     */
 +    bool requireVerifiedServer = false;
  
 -   /**
 -    * 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;
 -   };
 +    /**
 +     * Require verification of client certificate
 +     */
 +    bool requireVerifiedClient = false;
  
 -   /**
 -    * 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;
 -   };
 +    /**
 +     * Require client certificate be present
 +     */
 +    bool requireClientCertificate = false;
 +};
  
 -   /**
 -    * Allowable call directions
 -    */
 -   enum SipAllowableCallDirection
 -   {
 -      Disabled,
 -      Inbound,
 -      Outbound,
 -      Both,
 -   };
 +/**
 + * 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;
 +
 +    /**
 +     * The key information for the suite.
 +     */
 +    string cryptoKey;
 +};
 +
 +sequence<SRTPCryptoKey> SRTPCryptoKeySeq;
 +
 +/**
 + * SRTP crypto configuration.
 + */
 +class SRTPCryptoItem extends SipConfigurationItem
 +{
 +
 +    /**
 +     * Most of the time the following values will be false. They can be overriden to be true however.
 +     */
 +    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;
 +};
 +
 +/**
 +* Allowable media format item
 +*/
 +class SipMediaFormatItem extends SipConfigurationItem
 +{
     /**
 -    * Allowable call direction item
 +    * Name of the media format
      */
 -   class SipAllowableCallDirectionItem extends SipConfigurationItem
 -   {
 -      /**
 -       * What direction is permitted for this endpoint
 -       */
 -      SipAllowableCallDirection callDirection = Both;
 -   };
 +   string name;
  
     /**
 -    * Allowable media format item
 +    * Sample rate for frames
 +    *
 +    * This is specified in Hz and has a default value of 8000. 
      */
 -   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 sampleRate = 8000;
  
     /**
 -    * User agent presentation configuration item
 +    * Amount of audio in frames
 +    *
 +    * This is specified in 
      */
 -   class SipUserAgentItem extends SipConfigurationItem
 -   {
 -      /**
 -       * String that our user agent should appear as
 -       */
 -      string userAgent;
 -   };
 +   int frameSize;
  
     /**
 -    * Transport information configuration item
 +    * Format specific attributes.
      */
 -   class SipEndpointTransportItem extends SipConfigurationItem
 -   {
 -       /**
 -	* What directions to require secure transport in
 -	*/
 -       SipAllowableCallDirection secureTransport = Disabled;
 -   };
 +   Ice::StringSeq formatSpecific;
 +};
  
 +/**
 + * User agent presentation configuration item
 + */
 +class SipUserAgentItem extends SipConfigurationItem
 +{
      /**
 -     * Methods of transporting DTMF via SIP
 +     * String that our user agent should appear as
       */
 -    enum SipDTMFOption
 -    {
 -        Inband,
 -        RFC4733,
 -        INFO,
 -    };
 +    string userAgent;
 +};
  
 +/**
 + * Transport information configuration item
 + */
 +class SipEndpointTransportItem extends SipConfigurationItem
 +{
      /**
 -     * Denotes the method by which we will send DTMF to an endpoint
 +     * What directions to require secure transport in
       */
 -    class SipDTMFItem extends SipConfigurationItem
 -    {
 -        SipDTMFOption dtmf = RFC4733;
 -    };
 +    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
 +{
 +};
 +
++/**
++ * Methods of transporting DTMF via SIP
++ */
++enum SipDTMFOption
++{
++    Inband,
++    RFC4733,
++    INFO,
++};
++
++/**
++ * Denotes the method by which we will send DTMF to an endpoint
++ */
++class SipDTMFItem extends SipConfigurationItem
++{
++    SipDTMFOption dtmf = RFC4733;
++};
+ 
  }; /* module V1 */
  
  }; /* module SipSessionManager */
diff --cc src/PJSipSessionModule.cpp
index 0ceb682,062f997..44a1469
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@@ -20,11 -20,11 +20,13 @@@
  #include "SipSession.h"
  #include "PJSipManager.h"
  #include "SipStateReplicator.h"
+ #include "SipTelephonyEventSource.h"
  
  #include <IceUtil/UUID.h>
+ #include <boost/lexical_cast.hpp>
  
 +#include <boost/lexical_cast.hpp>
 +
  #include <AsteriskSCF/Core/Endpoint/EndpointIf.h>
  #include <AsteriskSCF/Core/Routing/RoutingIf.h>
  #include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
@@@ -99,18 -95,16 +101,18 @@@ void PJSipSessionModInfo::updateSession
      boost::unique_lock<boost::shared_mutex> lock(mLock);
      if (mSession)
      {
 -        mSessionState->mEndpointName = mSession->getEndpoint()->getName();
 -        mSessionState->mSessionObjectId = mSession->getSessionProxy()->ice_getIdentity();
 -        mSessionState->mMediaSessionObjectId = mSession->getMediaSessionProxy()->ice_getIdentity();
 -        mSessionState->mSources = mSession->getMediaSources();
 -        mSessionState->mSinks = mSession->getMediaSinks();
 -        mSessionState->mRTPMediaSessions = mSession->getRTPMediaSessions();
 -        mSessionState->mListeners = mSession->getListeners();
 +        mSessionState->endpointName = mSession->getEndpoint()->getName();
 +        mSessionState->sessionObjectId = mSession->getSessionProxy()->ice_getIdentity();
 +        mSessionState->mediaSessionObjectId = mSession->getMediaSessionProxy()->ice_getIdentity();
 +	    mSessionState->sessionControllerObjectId = mSession->getOurSessionControllerProxy()->ice_getIdentity();
-         mSessionState->sources = mSession->getSources();
-         mSessionState->sinks = mSession->getSinks();
++        mSessionState->sources = mSession->getMediaSources();
++        mSessionState->sinks = mSession->getMediaSinks();
 +        mSessionState->rtpMediaSessions = mSession->getRTPMediaSessions();
 +        mSessionState->listeners = mSession->getListeners();
 +	    mSessionState->streams = mSession->getStreams();
          try
          {
 -            mSessionState->mBridge = mSession->getBridge();
 +            mSessionState->bridge = mSession->getBridge();
          }
          catch (...)
          {
@@@ -459,18 -366,19 +461,20 @@@ protected
              return Complete;
          }
  
- 	mSession->setInviteSession(mInv);
- 	mSession->setDialog(mInv->dlg);
+         mSession->setInviteSession(mInv);
+         mSession->setDialog(mInv->dlg);
+ 
+         mSession->setTelephonyEventSourcesAndSinks(mCaller->getConfig());
  
          // Create an SDP offer or answer
- 	const pjmedia_sdp_session *remote_sdp = NULL;
+         const pjmedia_sdp_session *remote_sdp = NULL;
          pjmedia_sdp_session *sdp;
 +        StreamInformationDict streams;
  
- 	if (!mInv->neg || (pjmedia_sdp_neg_get_neg_remote(mInv->neg, &remote_sdp) != PJ_SUCCESS))
+         if (!mInv->neg || (pjmedia_sdp_neg_get_neg_remote(mInv->neg, &remote_sdp) != PJ_SUCCESS))
          {
              // No SDP was present in the INVITE so we need to create an offer
 -            sdp = mSession->createSDPOffer();
 +            sdp = mSession->createSDPOffer(StreamInformationDict(), streams);
          }
          else
          {
@@@ -1057,6 -957,218 +1061,219 @@@ void PJSipSessionModule::handleRefer(pj
      enqueueSessionWork(new HandleReferOperation(inv, tsx, tdata, replaces_param, to_tag_param, from_tag_param, target, session, mSessionRouter, mModule.id), inv);
  }
  
+ class HandleInfoDTMFOperation : public SipQueueableOperation
+ {
+ public:
+     HandleInfoDTMFOperation(
+             pjsip_inv_session *inv,
+             pjsip_transaction *tsx,
+             pjsip_tx_data *tdata,
+             const SipSessionPtr& session,
+             char dtmf,
+             int duration)
+         : mInv(inv), mTsx(tsx), mTdata(tdata), mSession(session), mDTMF(dtmf), mDuration(duration) { }
+ 
 -    SuspendableWorkResult initial(const SuspendableWorkListenerPtr& workListener)
++    SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
+     {
+         TelephonyEventPtr event;
+         if (mDTMF == '!')
+         {
+             event = new FlashEvent();
+         }
+         else
+         {
+             event = new EndDTMFEvent(mDTMF, mDuration);
+         }
+         SipTelephonyEventSourcePtr source = mSession->getSipTelephonyEventSource();
+         source->distributeToSinks(event);
+         pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
++        return Complete;
+     }
+ 
+ private:
+     pjsip_inv_session *mInv;
+     pjsip_transaction *mTsx;
+     pjsip_tx_data *mTdata;
+     SipSessionPtr mSession;
+     char mDTMF;
+     int mDuration;
+ };
+ 
+ bool PJSipSessionModule::isDTMF(pjsip_rx_data *rdata)
+ {
+     // We should determine how to handle matters based on the "Info-Package" header,
+     // but DTMF via INFO existed long before the Info-Package RFC was published.
+     // An official document defining DTMF over INFO is still in the draft stage as
+     // of July 2011. We will thus use the Info-Package or the Content-Type header
+     // to determine if this is DTMF.
+ 
+     pj_str_t str_info_pkg;
+     pj_cstr(&str_info_pkg, "Info-Package");
+     pjsip_generic_string_hdr *info_package =
+         static_cast<pjsip_generic_string_hdr *>(pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_info_pkg, NULL));
+ 
+     pj_str_t dtmf;
+     pj_cstr(&dtmf, "dtmf");
+     if (info_package && !pj_strcmp(&info_package->hvalue, &dtmf))
+     {
+         lg(Debug) << "Info-Package header suggests DTMF";
+         return true;
+     }
+ 
+     lg(Debug) << "No Info-Package header. Checking Content-Type";
+     //No biggie. I just said that not many are actually going to use Info-Package.
+     //Check if the content-type is "application/dtmf-relay"
+     pj_str_t application;
+     pj_str_t dtmf_relay;
+     pj_cstr(&application, "application");
+     pj_cstr(&dtmf_relay, "dtmf-relay");
+     if (!pj_strcmp(&rdata->msg_info.ctype->media.type, &application) && 
+             !pj_strcmp(&rdata->msg_info.ctype->media.subtype, &dtmf_relay))
+     {
+         lg(Debug) << "Content-Type is application/dtmf-relay";
+         return true;
+     }
+ 
+     return false;
+ }
+ 
+ class DTMFInfoException : public std::exception
+ {
+ public:
+     DTMFInfoException(const std::string& msg)
+         : mMsg(msg) { }
+ 
+     ~DTMFInfoException() throw() { }
+ 
+     const char *what() const throw()
+     {
+         return mMsg.c_str();
+     }
+ private:
+     const std::string mMsg;
+ };
+ 
+ char PJSipSessionModule::getDTMFInfoSignal(pjsip_msg_body *body)
+ {
+     char *data = static_cast<char *>(body->data);
+     std::string dataStr(data, body->len);
+     std::string signalStr("Signal=");
+     std::string altSignalStr("d=");
+     std::stringstream err;
+ 
+     size_t signalPos = dataStr.find(signalStr);
+     if (signalPos == std::string::npos)
+     {
+         signalPos = dataStr.find(altSignalStr);
+         if (signalPos == std::string::npos)
+         {
+             err << "Couldn't find " << signalStr << " or " << altSignalStr << " in DTMF INFO body";
+             throw DTMFInfoException(err.str());
+         }
+     }
+ 
+     //The pending draft for DTMF via INFO mandates a single space after
+     //'Signal=' but pre-existing implementations do not necessarily have
+     //any spaces and may do something silly like have multiple spaces.
+     size_t signalValuePos = dataStr.find_first_not_of(' ', signalPos + signalStr.size());
+     char retSignal = dataStr.at(signalValuePos);
+ 
+     //'!' is used by some endpoints to indicate a flash
+     std::string validDTMF("1234567890#*ABCD!");
+     if (!validDTMF.find(retSignal))
+     {
+         err << "Signal '" << retSignal << "' is not a valid DTMF signal";
+         throw DTMFInfoException(err.str());
+     }
+ 
+     return dataStr.at(signalValuePos);
+ }
+ 
+ int PJSipSessionModule::getDTMFInfoDuration(pjsip_msg_body *body)
+ {
+     char *data = static_cast<char *>(body->data);
+     std::string dataStr(data, body->len);
+     std::string durationStr("Duration=");
+     std::stringstream err;
+ 
+     size_t durationPos = dataStr.find(durationStr);
+     if (durationPos == std::string::npos)
+     {
+         err << "Couldn't find " << durationStr << " in DTMF INFO body";
+         throw DTMFInfoException(err.str());
+     }
+ 
+     //The pending draft for DTMF via INFO mandates a single space after
+     //'Duration=' but pre-existing implementations do not necessarily have
+     //any spaces and may do something silly like have multiple spaces.
+     size_t durationValuePos = durationPos + durationStr.size();
+     size_t durationBegin = dataStr.find_first_not_of(' ', durationValuePos);
+     size_t durationEnd = dataStr.find_first_not_of(" 1234567890", durationValuePos);
+     size_t durationSize = durationEnd - durationBegin;
+     std::string duration(dataStr.substr(durationBegin, durationSize));
+ 
+     int retDuration;
+     try
+     {
+         retDuration = boost::lexical_cast<int>(duration);
+     }
+     catch (const boost::bad_lexical_cast& ex)
+     {
+         throw DTMFInfoException(ex.what());
+     }
+ 
+     return retDuration;
+ }
+ 
+ void PJSipSessionModule::handleInfo(pjsip_inv_session *inv, pjsip_rx_data *rdata)
+ {
+ 
+     //Before we do anything, we need to figure out if we should even be handling this
+     //at all. If we don't have a telephony event source to handle this, then just
+     //ignore.
+     PJSipSessionModInfo *sessionModInfo = static_cast<PJSipSessionModInfo*>(inv->mod_data[mModule.id]);
+     SipSessionPtr session = sessionModInfo->getSessionPtr();
+ 
+     if (!session->isTelephonyEventSource())
+     {
+         //RFC 2976 Section 2.2 states that if we receive an INFO request with a body
+         //type we understand but have no intention of processing, we should respond
+         //with a 200 OK
+ 
+         pjsip_dlg_respond(inv->dlg, rdata, 200, NULL, NULL, NULL);
+         return;
+     }
+ 
+     // The only INFO package we handle for now is "dtmf". We need to verify that
+     // what we have received is actually DTMF and not some other INFO package.
+ 
+     if (!isDTMF(rdata))
+     {
+         return;
+     }
+ 
+     char dtmf;
+     int duration;
+     //It's DTMF! Grab the info we need! HA THAT WAS A PUN YOU JERK!
+     try
+     {
+         dtmf = getDTMFInfoSignal(rdata->msg_info.msg->body);
+         duration = getDTMFInfoDuration(rdata->msg_info.msg->body);
+     }
+     catch (const DTMFInfoException& ex)
+     {
+         lg(Error) << "Error processing DTMF INFO: " << ex.what();
+         pjsip_dlg_respond(inv->dlg, rdata, 400, NULL, NULL, NULL);
+         return;
+     }
+ 
+     pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
+     pjsip_tx_data *tdata;
+     pjsip_dlg_create_response(inv->dlg, rdata, 200, NULL, &tdata);
+     enqueueSessionWork(new HandleInfoDTMFOperation(inv, tsx, tdata, session, dtmf, duration), inv);
+     return;
+ }
+ 
  pj_bool_t PJSipSessionModule::on_rx_request(pjsip_rx_data *rdata)
  {
      pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
diff --cc src/PJSipSessionModule.h
index 3f9ed89,6337e57..e7f6e62
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@@ -143,9 -121,10 +143,13 @@@ private
      void handleNewInvite(pjsip_rx_data *rdata);
      void handleInviteResponse(pjsip_inv_session *inv, pjsip_rx_data *rdata, pjsip_dialog *dlg);
      void handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdata);
+     void handleInfo(pjsip_inv_session *inv, pjsip_rx_data *rdata);
+     bool isDTMF(pjsip_rx_data *rdata);
+     char getDTMFInfoSignal(pjsip_msg_body *body);
+     int getDTMFInfoDuration(pjsip_msg_body *body);
 +    bool checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv, AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type);
 +    void getURIParams(pjsip_uri *uri, AsteriskSCF::SIP::ExtensionPoint::V1::ParamDict &params);
 +    void createAuthManager(pjsip_endpoint *endpt);
      pjsip_inv_callback mInvCallback;
      pjsip_ua_init_param mUaParam;
      const std::string mName;
diff --cc src/SipConfiguration.cpp
index 65a40a2,eb8bf6f..d6a342a
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@@ -215,15 -209,10 +215,19 @@@ class EndpointConfigHelper : public boo
  	    mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateTransport, mConfig, transport));
  	};
  
 +        void visitSipMediaNATItem(const SipMediaNATItemPtr& item)
 +        {
 +            mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateMediaNATOptions, mConfig, item));
 +        }
 +
 +        void visitSipSignalingNATItem(const SipSignalingNATItemPtr& item)
 +        {
 +            mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateSignalingNAT, mConfig, item));
 +        }
+         void visitSipDTMFItem(const SipDTMFItemPtr& dtmf)
+         {
+             mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateDTMF, mConfig, dtmf));
+         };
  
      private:
  
@@@ -304,31 -293,10 +308,35 @@@ public
  	mEndpoint->setSecureTransport(translateCallDirection(transport->secureTransport));
      }
  
 +    void updateSRTP(const SRTPCryptoItemPtr& srtpOptions)
 +    {
 +        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 updateDTMF(const SipDTMFItemPtr& dtmf)
+     {
+         mEndpoint->setDTMFMethod(dtmf->dtmf);
+     }
  
      void updated(const UpdateCommandList& updates)
      {
diff --cc src/SipEndpoint.cpp
index 624da0c,a37281f..f8e0cf5
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@@ -368,10 -342,7 +373,10 @@@ AsteriskSCF::SessionCommunications::V1:
      }
  
      SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, listener, mImplPriv->mManager,
-         mImplPriv->mServiceLocator, mImplPriv->mReplica, mImplPriv->mConfig.sessionConfig.rtpOverIPv6, true, 
 -        mImplPriv->mServiceLocator, mImplPriv->mReplica, true, mImplPriv->mConfig);
++        mImplPriv->mServiceLocator, mImplPriv->mReplica, mImplPriv->mConfig.sessionConfig.rtpOverIPv6, true, mImplPriv->mConfig,
 +        NATEndpointOptions(mImplPriv->mConfig.sessionConfig.rtpOverICE, mImplPriv->mConfig.sessionConfig.rtpICEIncludeTURN,
 +            mImplPriv->mConfig.transportConfig.enableNAT));
 +
      mImplPriv->mSessions.push_back(session);
      std::cout << "And now we're returing a session proxy..." << std::endl;
      return session->getSessionProxy();
@@@ -380,11 -351,7 +385,11 @@@
  AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const std::string& destination)
  {
      SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, 0, mImplPriv->mManager,
-         mImplPriv->mServiceLocator, mImplPriv->mReplica, mImplPriv->mConfig.sessionConfig.rtpOverIPv6, false,
 -        mImplPriv->mServiceLocator, mImplPriv->mReplica, false, mImplPriv->mConfig);
++        mImplPriv->mServiceLocator, mImplPriv->mReplica, mImplPriv->mConfig.sessionConfig.rtpOverIPv6, false, mImplPriv->mConfig,
 +        NATEndpointOptions(mImplPriv->mConfig.sessionConfig.rtpOverICE, mImplPriv->mConfig.sessionConfig.rtpICEIncludeTURN,
 +            mImplPriv->mConfig.transportConfig.enableNAT)
 +        );
 +
      mImplPriv->mSessions.push_back(session);
      return session;
  }
@@@ -396,10 -362,8 +401,10 @@@ AsteriskSCF::SipSessionManager::SipSess
                                                                           const AsteriskSCF::Media::V1::StreamSourceSeq& sources,
                                                                           const AsteriskSCF::Media::V1::StreamSinkSeq& sinks)
  {
 -    SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, sessionid, mediaid, mediasessions,
 -            sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica, false, mImplPriv->mConfig);
 +    SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, sessionid, controllerid, mediaid, mediasessions,
-             sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica, false,
++            sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica, false, mImplPriv->mConfig,
 +            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 a0657d5,6991acb..d4afefc
--- a/src/SipEndpoint.h
+++ b/src/SipEndpoint.h
@@@ -157,37 -142,9 +158,40 @@@ public
      // Whether we are using IPv6 for media transport
      // or not.
      bool rtpOverIPv6;
+     // The method by which we will transmit
+     // DTMF to an endpoint
+     AsteriskSCF::Configuration::SipSessionManager::V1::SipDTMFOption dtmf;
 +    // 
 +    // 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:
 +    bool enableAuthentication;
 +    bool enableEncryption;
 +    CryptoKeys cryptoKeys;
  };
  
  /**
@@@ -330,10 -280,8 +334,11 @@@ public
      /**
       * 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);
 +    AsteriskSCF::Media::V1::StreamInformationDict getStreamTopology();
+     void setDTMFMethod(AsteriskSCF::Configuration::SipSessionManager::V1::SipDTMFOption dtmf);
  
  private:
      /**
diff --cc src/SipSession.cpp
index 1e494f6,a50c158..aa2c3f5
mode 100755,100644..100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@@ -295,30 -269,21 +297,42 @@@ public
      pjmedia_sdp_session *mSDP;
  
      /**
 -     * Whether the SDP has been finalized or not.
 +     * Streams present on the session.
 +     */
 +    StreamInformationDict mStreams;
 +
 +    /**
 +     * Newly added streams that are awaiting a response from the remote party on acceptance.
       */
 -    bool mSDPFinalized;
 +    StreamInformationDict mNewStreams;
 +
 +    /**
 +     * A proxy to the SessionController we are controlling.
 +     */
 +    AsteriskSCF::SessionCommunications::V1::SessionControllerPrx mSessionController;
 +
 +    /**
 +     * A pointer to the callback class used to send a response to the SessionController with which streams
 +     * have been added.
 +     */
 +    AsteriskSCF::SessionCommunications::V1::AMD_SessionController_addStreamsPtr mAddStreamsCb;
 +
 +    /**
 +     * A mapping for requested stream identifier to our stream identifier.
 +     */
 +    std::map<std::string, std::string> mAddStreamsMapping;
+ 
+     SipTelephonyEventSinkPtr mEventSink;
+ 
+     AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx mEventSinkPrx;
+ 
+     AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq mExternalEventSinks;
+     
+     SipTelephonyEventSourcePtr mEventSource;
+ 
+     AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx mEventSourcePrx;
+ 
+     AsteriskSCF::SessionCommunications::V1::TelephonyEventSourceSeq mExternalEventSources;
  };
  
  /**
@@@ -711,50 -357,29 +725,64 @@@ void SipSession::initializePJSIPStructs
      setInviteSession(inviteSession);
  }
  
 +void SipSession::activateIceObjects(const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookSeq& hooks)
 +{
 +    mImplPriv->mSessionProxy = 
 +        AsteriskSCF::SessionCommunications::V1::SessionPrx::uncheckedCast(mImplPriv->mAdapter->addWithUUID(this));
 +
 +    AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookDataPtr initial(new AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookData(mImplPriv->mSessionProxy, mImplPriv->mListeners));
 +
 +    AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookDataPtr in = initial;
 +
 +    for (AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookSeq::const_iterator iter = hooks.begin();
 +            iter != hooks.end(); ++iter)
 +    {
 +        AsteriskSCF::System::Hook::V1::HookResult result;
 +        AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookDataPtr out;
 +        try
 +        {
 +            result = (*iter)->modifySession(in, out);
 +        }
 +        catch (const Ice::Exception& ex)
 +        {
 +            lg(Warning) << "Exception caught while trying to set a decorator: " << ex.what();
 +            //XXX Probably should remove this hook from the list...
 +            continue;
 +        }
 +
 +        if (result.status == AsteriskSCF::System::Hook::V1::Succeeded)
 +        {
 +            lg(Debug) << "Setting our session proxy to be " << out->session->ice_getIdentity().name;
 +            mImplPriv->mPublicSessionProxy = out->session;
 +            mImplPriv->mListeners.clear();
 +            mImplPriv->mListeners = out->listeners;
 +            in = out;
 +        }
 +    }
 +}
+ void SipSession::setTelephonyEventSourcesAndSinks(const SipEndpointConfig& config)
+ {
+     if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SipSessionManager::V1::INFO)
+     {
+         mImplPriv->mEventSink = new SipTelephonyEventSink(mImplPriv->mSessionWork, mImplPriv->mInviteSession);
+         mImplPriv->mEventSinkPrx =
+             AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx::uncheckedCast(mImplPriv->mAdapter->addWithUUID(mImplPriv->mEventSink));
+ 
+         mImplPriv->mEventSource = new SipTelephonyEventSource(mImplPriv->mSessionWork);
+         mImplPriv->mEventSourcePrx =
+             AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx::uncheckedCast(mImplPriv->mAdapter->addWithUUID(mImplPriv->mEventSource));
+     }
+ }
  
  /**
   * Default constructor.
   */
  SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPtr& endpoint,
 -                       const std::string& destination,  const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
 -                       PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
 -                       const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC,
 -                       const SipEndpointConfig &config)
 -    : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica))
 +        const std::string& destination,  const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
 +        const PJSipManagerPtr& manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
-         const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool /* ipv6 */, bool isUAC, const NATEndpointOptions& natOptions)
++        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool /* ipv6 */, bool isUAC, const SipEndpointConfig &config,
++        const NATEndpointOptions& natOptions)
 +    : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica, natOptions))
  {
      if (listener != 0)
      {
@@@ -782,15 -405,16 +811,16 @@@
   * Replica constructor.
   */
  SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPtr& endpoint,
 -                       const std::string& destination, const Ice::Identity& sessionid,
 +                       const std::string& destination, const Ice::Identity& /* sessionid */,
 +                       const Ice::Identity& controllerid,
                         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,
 -                       const SipEndpointConfig &config)
 -    : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica))
 +                       const PJSipManagerPtr& manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
-                        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC, const NATEndpointOptions& natOptions)
++                       const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC, const SipEndpointConfig &config,
++                       const NATEndpointOptions& natOptions)
 +    : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica, natOptions))
  {
 -    mImplPriv->mSessionProxy =
 -        AsteriskSCF::SessionCommunications::V1::SessionPrx::uncheckedCast(adapter->add(this, sessionid));
 +    activateIceObjects(mImplPriv->mManager->getSessionModule()->getSessionCreationHooks());
  
      mImplPriv->mMediaSession = new SipMediaSession(this);
      mImplPriv->mMediaSessionProxy =
@@@ -1539,6 -1134,74 +1569,76 @@@ AsteriskSCF::SessionCommunications::V1:
      return mImplPriv->mSessionCookies;
  }
  
+ class GetSources : public SuspendableWork
+ {
+ public:
+     GetSources(
+             const AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSourcesPtr& cb,
+             const SipSessionPtr& session)
+         : mCB(cb), mSession(session) { }
+ 
+     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+     {
+         mCB->ice_response(mSession->getSources());
++        return Complete;
+     }
+ private:
+     AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSourcesPtr mCB;
+     SipSessionPtr mSession;
+ };
+ 
+ void SipSession::getSources_async(
+         const AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSourcesPtr& cb,
+         const Ice::Current&)
+ {
+     enqueueSessionWork(new GetSources(cb, this));
+ }
+ 
+ AsteriskSCF::SessionCommunications::V1::TelephonyEventSourceSeq SipSession::getSources()
+ {
+     AsteriskSCF::SessionCommunications::V1::TelephonyEventSourceSeq sources(mImplPriv->mExternalEventSources);
+     if (mImplPriv->mEventSource)
+     {
+         sources.push_back(mImplPriv->mEventSourcePrx);
+     }
+     return sources;
+ }
+ 
+ class GetSinks : public SuspendableWork
+ {
+ public:
+     GetSinks(
+             const AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSinksPtr& cb,
+             const SipSessionPtr& session)
+         : mCB(cb), mSession(session) { }
+ 
+     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+     {
+         mCB->ice_response(mSession->getSinks());
++        return Complete;
+     }
+ private:
+     AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSinksPtr mCB;
+     SipSessionPtr mSession;
+ };
+ 
+ void SipSession::getSinks_async(
+         const AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSinksPtr& cb,
+         const Ice::Current&)
+ {
+     enqueueSessionWork(new GetSinks(cb, this));
+ }
+ 
+ AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq SipSession::getSinks()
+ {
+     AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq sinks(mImplPriv->mExternalEventSinks);
+     if (mImplPriv->mEventSink)
+     {
+         sinks.push_back(mImplPriv->mEventSinkPrx);
+     }
+     return sinks;
+ }
+ 
  /**
   * Internal function called to destroy an endpoint. This is controlled by signaling.
   */
diff --cc src/SipSession.h
index fa89ad0,6e8d7a5..10faf86
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@@ -106,17 -100,17 +111,17 @@@ class SipSession : public AsteriskSCF::
  {
  public:
      SipSession(const Ice::ObjectAdapterPtr&, const SipEndpointPtr&, const std::string&,
 -        const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx&, PJSipManager *manager,
 +        const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx&, const PJSipManagerPtr& manager,
          const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
          const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
-         bool ipv6, bool isUAC, const NATEndpointOptions& natOptions);
 -        bool isUAC, const SipEndpointConfig& config);
++        bool ipv6, bool isUAC, const SipEndpointConfig& config, const NATEndpointOptions& natOptions);
  
 -    SipSession(const Ice::ObjectAdapterPtr&, const SipEndpointPtr&, const std::string&, const Ice::Identity&,
 -               const Ice::Identity&, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq&,
 -               const AsteriskSCF::Media::V1::StreamSourceSeq&, const AsteriskSCF::Media::V1::StreamSinkSeq&,
 -               PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
 -               const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
 -               bool isUAC, const SipEndpointConfig& config);
 +    SipSession(const Ice::ObjectAdapterPtr&, const SipEndpointPtr&, const std::string&, const Ice::Identity&, const Ice::Identity&,
 +        const Ice::Identity&, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq&,
 +        const AsteriskSCF::Media::V1::StreamSourceSeq&, const AsteriskSCF::Media::V1::StreamSinkSeq&,
 +        const PJSipManagerPtr& manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
 +        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
-         bool isUAC, const NATEndpointOptions& natOptions);
++        bool isUAC, const SipEndpointConfig& config, const NATEndpointOptions& natOptions);
  
      bool operator==(const SipSession &other) const;
  
@@@ -182,20 -174,27 +187,40 @@@
      AsteriskSCF::SessionCommunications::V1::SessionCookies getCookies();
      AsteriskSCF::SessionCommunications::V1::SessionCookieDict getAllCookies();
  
 +    void getStreams_async(
 +        const AsteriskSCF::SessionCommunications::V1::AMD_Session_getStreamsPtr&,
 +        const Ice::Current&);
 +
 +    void setAndGetSessionController_async(
 +        const AsteriskSCF::SessionCommunications::V1::AMD_Session_setAndGetSessionControllerPtr&,
 +        const AsteriskSCF::SessionCommunications::V1::SessionControllerPrx&,
 +        const Ice::Current&);
 +
 +    void removeSessionController_async(const AsteriskSCF::SessionCommunications::V1::AMD_Session_removeSessionControllerPtr&,
 +                                       const AsteriskSCF::SessionCommunications::V1::SessionControllerPrx&,
 +                                       const Ice::Current&);
 +
      /**
+      * TelephonySession overrides
+      */
+     void getSources_async(
+             const AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSourcesPtr&,
+             const Ice::Current&);
+     /**
+      * Only called from within a queued operation
+      */
+     AsteriskSCF::SessionCommunications::V1::TelephonyEventSourceSeq getSources();
+ 
+     void getSinks_async(
+             const AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSinksPtr&,
+             const Ice::Current&);
+ 
+     /**
+      * Only called from within a queued operation
+      */
+     AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq getSinks();
+ 
+     /**
       * Implementation specific functions.
       */
      void destroy();
diff --cc src/SipTelephonyEventSink.cpp
index 0000000,d7b320d..0e37c6c
mode 000000,100644..100644
--- a/src/SipTelephonyEventSink.cpp
+++ b/src/SipTelephonyEventSink.cpp
@@@ -1,0 -1,220 +1,220 @@@
+ /*
+  * Asterisk SCF -- An open-source communications framework.
+  *
+  * Copyright (C) 2010, Digium, Inc.
+  *
+  * See http://www.asterisk.org for more information about
+  * the Asterisk SCF project. Please do not directly contact
+  * any of the maintainers of this project for assistance;
+  * the project provides a web site, mailing lists and IRC
+  * channels for your use.
+  *
+  * This program is free software, distributed under the terms of
+  * the GNU General Public License Version 2. See the LICENSE.txt file
+  * at the top of the source tree.
+  */
+ 
+ #include "SipTelephonyEventSink.h"
+ 
+ namespace AsteriskSCF
+ {
+ 
+ namespace SipSessionManager
+ {
+ 
+ using namespace AsteriskSCF::System::WorkQueue::V1;
+ 
+ class WriteTelephonyEvent : public SuspendableWork
+ {
+ public:
+     WriteTelephonyEvent(
+             const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr& cb,
+             const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event,
+             pjsip_inv_session *inv)
+         : mCB(cb), mEvent(event), mInv(inv) { }
+ 
+     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+     {
+         AsteriskSCF::SessionCommunications::V1::BeginDTMFEventPtr beginDTMF;
+         AsteriskSCF::SessionCommunications::V1::EndDTMFEventPtr endDTMF;
+         AsteriskSCF::SessionCommunications::V1::FlashEventPtr flash;
+ 
+         if ((beginDTMF = AsteriskSCF::SessionCommunications::V1::BeginDTMFEventPtr::dynamicCast(mEvent)))
+         {
+             // XXX Since the only DTMF support we have is INFO, we won't get any beginDTMF indications. Sorry.
+         }
+         else if ((endDTMF = AsteriskSCF::SessionCommunications::V1::EndDTMFEventPtr::dynamicCast(mEvent)))
+         {
+             try
+             {
+                 sendDTMFINFO(endDTMF);
+             }
+             catch (const AsteriskSCF::SessionCommunications::V1::TelephonyEventException& ex)
+             {
+                 mCB->ice_exception(ex);
+             }
+         }
+         else if ((flash = AsteriskSCF::SessionCommunications::V1::FlashEventPtr::dynamicCast(mEvent)))
+         {
+             try
+             {
+                 sendFlashINFO();
+             }
+             catch (const AsteriskSCF::SessionCommunications::V1::TelephonyEventException& ex)
+             {
+                 mCB->ice_exception(ex);
+             }
+         }
+         mCB->ice_response();
+         return Complete;
+     }
+ private:
+ 
+     pjsip_tx_data *createINFORequest()
+     {
+         pjsip_method infoMethod;
+         pj_str_t infoStr;
+         pj_cstr(&infoStr, "INFO");
+         pjsip_method_init_np(&infoMethod, &infoStr);
+ 
+         pj_status_t status;
+         pjsip_tx_data *tdata;
+         status = pjsip_dlg_create_request(mInv->dlg, &infoMethod, -1, &tdata);
+         
+         if (status != PJ_SUCCESS)
+         {
+             throw AsteriskSCF::SessionCommunications::V1::TelephonyEventException();
+         }
+ 
+         return tdata;
+     }
+ 
+     void fillINFOBody(pjsip_tx_data *tdata, char signal, int duration)
+     {
+         pj_str_t type;
+         pj_cstr(&type, "application");
+         pj_str_t subtype;
+         pj_cstr(&subtype, "dtmf-relay");
+         std::stringstream bodyText;
+         bodyText << "Signal= " << signal 
+             << "\r\nDuration= " << duration << "\r\n\r\n";
+         pj_str_t bodyStr;
+         pj_cstr(&bodyStr, bodyText.str().c_str());
+ 
+         pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
+ 
+         if (!body)
+         {
+             throw AsteriskSCF::SessionCommunications::V1::TelephonyEventException();
+         }
+ 
+         tdata->msg->body = body;
+     }
+ 
+     void sendDTMFINFO(const AsteriskSCF::SessionCommunications::V1::EndDTMFEventPtr& endDTMF)
+     {
+         pjsip_tx_data *tdata = createINFORequest();
+ 
+         pj_str_t infoPackage;
+         pj_cstr(&infoPackage, "Info-Package");
+         pj_str_t infoPackageVal;
+         pj_cstr(&infoPackageVal, "dtmf");
+         pjsip_generic_string_hdr *infoPackageHdr = pjsip_generic_string_hdr_create(tdata->pool, &infoPackage, &infoPackageVal);
+ 
+         pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) infoPackageHdr);
+ 
 -        fillINFOBody(tdata, endDTMF->digit, endDTMF->duration);
++        fillINFOBody(tdata, endDTMF->signal, endDTMF->duration);
+ 
+         pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+     }
+ 
+     void sendFlashINFO()
+     {
+         pjsip_tx_data *tdata = createINFORequest();
+         fillINFOBody(tdata, '!', 100);
+         pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+     }
+ 
+     AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr mCB;
+     AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr mEvent;
+     pjsip_inv_session *mInv;
+ };
+ 
+ 
+ SipTelephonyEventSink::SipTelephonyEventSink(const SessionWorkPtr& sessionWork, pjsip_inv_session *inv)
+     : mSessionWork(sessionWork), mInv(inv)  { }
+ 
+ void SipTelephonyEventSink::write_async(
+         const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr& cb,
+         const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event,
+         const Ice::Current&)
+ {
+     mSessionWork->enqueueWork(new WriteTelephonyEvent(cb, event, mInv));
+ }
+ 
+ class SetTelephonyEventSource : public SuspendableWork
+ {
+ public:
+     SetTelephonyEventSource(
+             const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_setSourcePtr& cb,
+             const SipTelephonyEventSinkPtr& sink, 
+             const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source)
 -        : mSink(sink), mSource(source) { }
++        : mCB(cb), mSink(sink), mSource(source) { }
+ 
+     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+     {
+         mSink->setSource(mSource);
+         mCB->ice_response();
+         return Complete;
+     }
+ private:
+     AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_setSourcePtr mCB;
+     SipTelephonyEventSinkPtr mSink;
+     AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx mSource;
+ };
+ 
+ void SipTelephonyEventSink::setSource_async(
+         const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_setSourcePtr& cb,
+         const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source,
+         const Ice::Current&)
+ {
+     mSessionWork->enqueueWork(new SetTelephonyEventSource(cb, this, source));
+ }
+ 
+ void SipTelephonyEventSink::setSource(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source)
+ {
+     mSource = source;
+ }
+ 
+ class GetTelephonyEventSource : public SuspendableWork
+ {
+ public:
+     GetTelephonyEventSource(
+             const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr& cb,
+             const SipTelephonyEventSinkPtr& sink)
 -        : mSink(sink) { }
++        : mCB(cb), mSink(sink) { }
+ 
+     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+     {
+         mCB->ice_response(mSink->getSource());
+         return Complete;
+     }
+ private:
+     AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr mCB;
+     SipTelephonyEventSinkPtr mSink;
+ };
+ 
+ void SipTelephonyEventSink::getSource_async(
+         const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr& cb,
+         const Ice::Current&)
+ {
+     mSessionWork->enqueueWork(new GetTelephonyEventSource(cb, this));
+ }
+ 
+ AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx SipTelephonyEventSink::getSource()
+ {
+     return mSource;
+ }
+ 
+ };
+ };
diff --cc src/SipTelephonyEventSource.cpp
index 0000000,b7eab2c..b424dfa
mode 000000,100644..100644
--- a/src/SipTelephonyEventSource.cpp
+++ b/src/SipTelephonyEventSource.cpp
@@@ -1,0 -1,106 +1,108 @@@
+ /*
+  * Asterisk SCF -- An open-source communications framework.
+  *
+  * Copyright (C) 2010, Digium, Inc.
+  *
+  * See http://www.asterisk.org for more information about
+  * the Asterisk SCF project. Please do not directly contact
+  * any of the maintainers of this project for assistance;
+  * the project provides a web site, mailing lists and IRC
+  * channels for your use.
+  *
+  * This program is free software, distributed under the terms of
+  * the GNU General Public License Version 2. See the LICENSE.txt file
+  * at the top of the source tree.
+  */
+ 
+ #include "SipTelephonyEventSource.h"
+ #include <AsteriskSCF/System/WorkQueue/WorkQueueIf.h>
+ 
+ namespace AsteriskSCF
+ {
+ 
+ namespace SipSessionManager
+ {
+ 
+ using namespace AsteriskSCF::System::WorkQueue::V1;
+ 
+ void SipTelephonyEventSource::distributeToSinks(const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event)
+ {
+     for (AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq::const_iterator iter = mSinks.begin();
+             iter != mSinks.end(); ++iter)
+     {
+         (*iter)->write(event);
+     }
+ }
+ 
+ SipTelephonyEventSource::SipTelephonyEventSource(const SessionWorkPtr& sessionWork)
+     : mSessionWork(sessionWork) { }
+ 
+ class AddSink : public SuspendableWork
+ {
+ public:
+     AddSink(
+             const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr& cb,
+             const SipTelephonyEventSourcePtr& source,
+             const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink)
+         : mCB(cb), mSource(source), mSink(sink) { }
+ 
+     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+     {
+         mSource->addSink(mSink);
+         mCB->ice_response();
++        return Complete;
+     }
+ private:
... 4674 lines suppressed ...


-- 
asterisk-scf/release/sip.git



More information about the asterisk-scf-commits mailing list