[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(¤tMedia->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