1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/* 2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle 3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc. 4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without 6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met: 7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 1. Redistributions of source code must retain the above copyright notice, 9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer. 10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright notice, 11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer in the documentation 12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * and/or other materials provided with the distribution. 13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 3. The name of the author may not be used to endorse or promote products 14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * derived from this software without specific prior written permission. 15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */ 27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <string> 294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/session/phone/mediasessionclient.h" 31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "talk/base/helpers.h" 33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h" 34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/stringutils.h" 354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "talk/base/stringencode.h" 36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/p2p/base/constants.h" 37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/p2p/base/parsing.h" 384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "talk/session/phone/cryptoparams.h" 394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "talk/session/phone/srtpfilter.h" 40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/xmpp/constants.h" 41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/xmllite/qname.h" 424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "talk/xmllite/xmlconstants.h" 43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochusing namespace talk_base; 45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochnamespace { 474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst std::string kInline = "inline:"; 484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace cricket { 51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochtypedef std::vector<CryptoParams> CryptoParamsVec; 534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochMediaSessionClient::MediaSessionClient( 55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const buzz::Jid& jid, SessionManager *manager) 56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch : jid_(jid), session_manager_(manager), focus_call_(NULL), 574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch channel_manager_(new ChannelManager(session_manager_->worker_thread())), 584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch secure_(SEC_DISABLED) { 59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Construct(); 60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochMediaSessionClient::MediaSessionClient( 63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const buzz::Jid& jid, SessionManager *manager, 64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch MediaEngine* media_engine, DeviceManager* device_manager) 65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch : jid_(jid), session_manager_(manager), focus_call_(NULL), 66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch channel_manager_(new ChannelManager( 674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch media_engine, device_manager, session_manager_->worker_thread())), 684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch secure_(SEC_DISABLED) { 69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Construct(); 70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid MediaSessionClient::Construct() { 74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Register ourselves as the handler of phone and video sessions. 75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick session_manager_->AddClient(NS_JINGLE_RTP, this); 76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Forward device notifications. 77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SignalDevicesChange.repeat(channel_manager_->SignalDevicesChange); 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Bring up the channel manager. 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // In previous versions of ChannelManager, this was done automatically 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // in the constructor. 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick channel_manager_->Init(); 82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochMediaSessionClient::~MediaSessionClient() { 85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Destroy all calls 86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::map<uint32, Call *>::iterator it; 87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (calls_.begin() != calls_.end()) { 88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::map<uint32, Call *>::iterator it = calls_.begin(); 89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch DestroyCall((*it).second); 90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Delete channel manager. This will wait for the channels to exit 93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete channel_manager_; 94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Remove ourselves from the client map. 96731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick session_manager_->RemoveClient(NS_JINGLE_RTP); 97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool CreateCryptoParams(int tag, const std::string& cipher, CryptoParams *out) { 1004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string key; 1014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch key.reserve(SRTP_MASTER_KEY_BASE64_LEN); 1024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!CreateRandomString(SRTP_MASTER_KEY_BASE64_LEN, &key)) { 1044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 1054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch out->tag = tag; 1074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch out->cipher_suite = cipher; 1084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch out->key_params = kInline + key; 1094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return true; 1104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 1114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool AddCryptoParams(const std::string& cipher_suite, CryptoParamsVec *out) { 1134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int size = out->size(); 1144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch out->resize(size + 1); 1164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return CreateCryptoParams(size, cipher_suite, &out->at(size)); 1174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 1184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// For audio, HMAC 32 is prefered because of the low overhead. 1204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool GetSupportedAudioCryptos(CryptoParamsVec* cryptos) { 1214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#ifdef HAVE_SRTP 1224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return AddCryptoParams(CS_AES_CM_128_HMAC_SHA1_32, cryptos) && 1234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch AddCryptoParams(CS_AES_CM_128_HMAC_SHA1_80, cryptos); 1244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#else 1254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 1264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif 1274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 1284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool GetSupportedVideoCryptos(CryptoParamsVec* cryptos) { 1304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#ifdef HAVE_SRTP 1314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return AddCryptoParams(CS_AES_CM_128_HMAC_SHA1_80, cryptos); 1324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#else 1334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 1344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif 1354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 1364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochSessionDescription* MediaSessionClient::CreateOffer( 1384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const CallOptions& options) { 1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SessionDescription* offer = new SessionDescription(); 1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick AudioContentDescription* audio = new AudioContentDescription(); 141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick AudioCodecs audio_codecs; 1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick channel_manager_->GetSupportedAudioCodecs(&audio_codecs); 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (AudioCodecs::const_iterator codec = audio_codecs.begin(); 146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick codec != audio_codecs.end(); ++codec) { 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick audio->AddCodec(*codec); 1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (options.is_muc) { 1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick audio->set_ssrc(0); 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick audio->SortCodecs(); 1534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (secure() != SEC_DISABLED) { 1554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch CryptoParamsVec audio_cryptos; 1564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (GetSupportedAudioCryptos(&audio_cryptos)) { 1574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch for (CryptoParamsVec::const_iterator crypto = audio_cryptos.begin(); 1584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch crypto != audio_cryptos.end(); ++crypto) { 1594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch audio->AddCrypto(*crypto); 1604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (secure() == SEC_REQUIRED) { 1634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (audio->cryptos().empty()) { 1644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return NULL; // Abort, crypto required but none found. 1654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch audio->set_crypto_required(true); 1674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick offer->AddContent(CN_AUDIO, NS_JINGLE_RTP, audio); 171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // add video codecs, if this is a video call 1734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (options.is_video) { 1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick VideoContentDescription* video = new VideoContentDescription(); 1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick VideoCodecs video_codecs; 176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch channel_manager_->GetSupportedVideoCodecs(&video_codecs); 1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (VideoCodecs::const_iterator codec = video_codecs.begin(); 178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick codec != video_codecs.end(); ++codec) { 1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick video->AddCodec(*codec); 1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (options.is_muc) { 1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick video->set_ssrc(0); 1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch video->set_bandwidth(options.video_bandwidth); 1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick video->SortCodecs(); 1864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (secure() != SEC_DISABLED) { 1884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch CryptoParamsVec video_cryptos; 1894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (GetSupportedVideoCryptos(&video_cryptos)) { 1904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch for (CryptoParamsVec::const_iterator crypto = video_cryptos.begin(); 1914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch crypto != video_cryptos.end(); ++crypto) { 1924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch video->AddCrypto(*crypto); 1934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (secure() == SEC_REQUIRED) { 1964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (video->cryptos().empty()) { 1974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return NULL; // Abort, crypto required but none found. 1984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch video->set_crypto_required(true); 2004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 2014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 2024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick offer->AddContent(CN_VIDEO, NS_JINGLE_RTP, video); 204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return offer; 2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst ContentInfo* GetFirstMediaContent(const SessionDescription* sdesc, 210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick MediaType media_type) { 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (sdesc == NULL) 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return NULL; 2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 214731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ContentInfos& contents = sdesc->contents(); 215731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (ContentInfos::const_iterator content = contents.begin(); 216731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick content != contents.end(); content++) { 217731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (content->type == NS_JINGLE_RTP) { 218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const MediaContentDescription* media = 219731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick static_cast<const MediaContentDescription*>(content->description); 220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (media->type() == media_type) { 221731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return &*content; 222731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 223731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 224731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 225731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return NULL; 226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst ContentInfo* GetFirstAudioContent(const SessionDescription* sdesc) { 229731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return GetFirstMediaContent(sdesc, MEDIA_TYPE_AUDIO); 2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst ContentInfo* GetFirstVideoContent(const SessionDescription* sdesc) { 233731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return GetFirstMediaContent(sdesc, MEDIA_TYPE_VIDEO); 2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// For video support only 80-bit SHA1 HMAC. For audio 32-bit HMAC is 2374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// tolerated because it is low overhead. Pick the crypto in the list 2384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// that is supported. 2394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool SelectCrypto(const MediaContentDescription* offer, CryptoParams *crypto) { 2404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch bool audio = offer->type() == MEDIA_TYPE_AUDIO; 2414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const CryptoParamsVec& cryptos = offer->cryptos(); 2424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 2434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch for (CryptoParamsVec::const_iterator i = cryptos.begin(); 2444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch i != cryptos.end(); ++i) { 2454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (CS_AES_CM_128_HMAC_SHA1_80 == i->cipher_suite || 2464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch (CS_AES_CM_128_HMAC_SHA1_32 == i->cipher_suite && audio)) { 2474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return CreateCryptoParams(i->tag, i->cipher_suite, crypto); 2484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 2494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 2504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 2514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 2524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickSessionDescription* MediaSessionClient::CreateAnswer( 2544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const SessionDescription* offer, const CallOptions& options) { 255731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // The answer contains the intersection of the codecs in the offer with the 256731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // codecs we support, ordered by our local preference. As indicated by 257731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // XEP-0167, we retain the same payload ids from the offer in the answer. 2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SessionDescription* accept = new SessionDescription(); 2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const ContentInfo* audio_content = GetFirstAudioContent(offer); 2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (audio_content) { 2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const AudioContentDescription* audio_offer = 2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static_cast<const AudioContentDescription*>(audio_content->description); 2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick AudioContentDescription* audio_accept = new AudioContentDescription(); 265731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AudioCodecs audio_codecs; 266731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick channel_manager_->GetSupportedAudioCodecs(&audio_codecs); 267731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (AudioCodecs::const_iterator ours = audio_codecs.begin(); 268731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ours != audio_codecs.end(); ++ours) { 269731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (AudioCodecs::const_iterator theirs = audio_offer->codecs().begin(); 270731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick theirs != audio_offer->codecs().end(); ++theirs) { 271731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (ours->Matches(*theirs)) { 272731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AudioCodec negotiated(*ours); 273731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick negotiated.id = theirs->id; 274731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick audio_accept->AddCodec(negotiated); 275731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 278731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick audio_accept->SortCodecs(); 2804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 2814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (secure() != SEC_DISABLED) { 2824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch CryptoParams crypto; 2834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 2844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (SelectCrypto(audio_offer, &crypto)) { 2854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch audio_accept->AddCrypto(crypto); 2864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 2874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 2884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 2894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (audio_accept->cryptos().empty() && 2904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch (audio_offer->crypto_required() || secure() == SEC_REQUIRED)) { 2914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return NULL; // Fails the session setup. 2924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick accept->AddContent(audio_content->name, audio_content->type, audio_accept); 294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 2963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const ContentInfo* video_content = GetFirstVideoContent(offer); 2973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (video_content) { 2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const VideoContentDescription* video_offer = 2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static_cast<const VideoContentDescription*>(video_content->description); 3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick VideoContentDescription* video_accept = new VideoContentDescription(); 301731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VideoCodecs video_codecs; 302731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick channel_manager_->GetSupportedVideoCodecs(&video_codecs); 303731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (VideoCodecs::const_iterator ours = video_codecs.begin(); 304731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ours != video_codecs.end(); ++ours) { 305731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (VideoCodecs::const_iterator theirs = video_offer->codecs().begin(); 306731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick theirs != video_offer->codecs().end(); ++theirs) { 307731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (ours->Matches(*theirs)) { 308731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VideoCodec negotiated(*ours); 309731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick negotiated.id = theirs->id; 310731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick video_accept->AddCodec(negotiated); 311731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 314731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 3154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch video_accept->set_bandwidth(options.video_bandwidth); 3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick video_accept->SortCodecs(); 3174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 3184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (secure() != SEC_DISABLED) { 3194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch CryptoParams crypto; 3204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 3214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (SelectCrypto(video_offer, &crypto)) { 3224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch video_accept->AddCrypto(crypto); 3234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 3244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 3254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 3264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (video_accept->cryptos().empty() && 3274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch (video_offer->crypto_required() || secure() == SEC_REQUIRED)) { 3284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return NULL; // Fails the session setup. 3294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 3303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick accept->AddContent(video_content->name, video_content->type, video_accept); 331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 332f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 3333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return accept; 334f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 3364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochCall *MediaSessionClient::CreateCall() { 3374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch Call *call = new Call(this); 338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch calls_[call->id()] = call; 339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SignalCallCreate(call); 340f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return call; 341f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 342f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid MediaSessionClient::OnSessionCreate(Session *session, 344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool received_initiate) { 345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (received_initiate) { 346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session->SignalState.connect(this, &MediaSessionClient::OnSessionState); 347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 348f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 349f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 350731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid MediaSessionClient::OnSessionState(BaseSession* base_session, 351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BaseSession::State state) { 352731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // MediaSessionClient can only be used with a Session*, so it's 353731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // safe to cast here. 354731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Session* session = static_cast<Session*>(base_session); 355731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (state == Session::STATE_RECEIVEDINITIATE) { 357731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // The creation of the call must happen after the session has 358731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // processed the initiate message because we need the 359731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // remote_description to know what content names to use in the 360731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // call. 361731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 362f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // If our accept would have no codecs, then we must reject this call. 363731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const SessionDescription* offer = session->remote_description(); 3644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const SessionDescription* accept = CreateAnswer(offer, CallOptions()); 3653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const ContentInfo* audio_content = GetFirstAudioContent(accept); 3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const AudioContentDescription* audio_accept = (!audio_content) ? NULL : 3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static_cast<const AudioContentDescription*>(audio_content->description); 3683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 369731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // For some reason, we need to create the call even when we 370731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // reject. 3714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch Call *call = CreateCall(); 372731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick session_map_[session->id()] = call; 373731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick call->IncomingSession(session, offer); 374731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 3753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!audio_accept || audio_accept->codecs().size() == 0) { 376731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick session->Reject(STR_TERMINATE_INCOMPATIBLE_PARAMETERS); 377f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete accept; 379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 380f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 381f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid MediaSessionClient::DestroyCall(Call *call) { 383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Change focus away, signal destruction 384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (call == focus_call_) 386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetFocus(NULL); 387f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SignalCallDestroy(call); 388f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 389f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Remove it from calls_ map and delete 390f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 391f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::map<uint32, Call *>::iterator it = calls_.find(call->id()); 392f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (it != calls_.end()) 393f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch calls_.erase(it); 394f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 395f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete call; 396f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 397f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 398f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid MediaSessionClient::OnSessionDestroy(Session *session) { 399f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Find the call this session is in, remove it 400f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 401731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::map<std::string, Call *>::iterator it = session_map_.find(session->id()); 4023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT(it != session_map_.end()); 403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (it != session_map_.end()) { 404f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Call *call = (*it).second; 405f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_map_.erase(it); 406f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call->RemoveSession(session); 407f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 408f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 409f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 410f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochCall *MediaSessionClient::GetFocus() { 411f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return focus_call_; 412f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 413f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 414f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid MediaSessionClient::SetFocus(Call *call) { 415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Call *old_focus_call = focus_call_; 416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (focus_call_ != call) { 417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (focus_call_ != NULL) 418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch focus_call_->EnableChannels(false); 419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch focus_call_ = call; 420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (focus_call_ != NULL) 421f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch focus_call_->EnableChannels(true); 422f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SignalFocus(focus_call_, old_focus_call); 423f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 424f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 425f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 426f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid MediaSessionClient::JoinCalls(Call *call_to_join, Call *call) { 427f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Move all sessions from call to call_to_join, delete call. 428f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // If call_to_join has focus, added sessions should have enabled channels. 429f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 430f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (focus_call_ == call) 431f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetFocus(NULL); 432f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_to_join->Join(call, focus_call_ == call_to_join); 433f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch DestroyCall(call); 434f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 435f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 436f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSession *MediaSessionClient::CreateSession(Call *call) { 437731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& type = NS_JINGLE_RTP; 438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Session *session = session_manager_->CreateSession(jid().Str(), type); 439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_map_[session->id()] = call; 440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return session; 441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 443731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ParseGingleAudioCodec(const buzz::XmlElement* element, AudioCodec* out) { 444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int id = GetXmlAttr(element, QN_ID, -1); 445f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (id < 0) 446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::string name = GetXmlAttr(element, QN_NAME, buzz::STR_EMPTY); 449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int clockrate = GetXmlAttr(element, QN_CLOCKRATE, 0); 450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int bitrate = GetXmlAttr(element, QN_BITRATE, 0); 451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int channels = GetXmlAttr(element, QN_CHANNELS, 1); 4523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *out = AudioCodec(id, name, clockrate, bitrate, channels, 0); 453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 456731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ParseGingleVideoCodec(const buzz::XmlElement* element, VideoCodec* out) { 457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int id = GetXmlAttr(element, QN_ID, -1); 458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (id < 0) 459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 460f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 461f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::string name = GetXmlAttr(element, QN_NAME, buzz::STR_EMPTY); 462f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int width = GetXmlAttr(element, QN_WIDTH, 0); 463f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int height = GetXmlAttr(element, QN_HEIGHT, 0); 464f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int framerate = GetXmlAttr(element, QN_FRAMERATE, 0); 465731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 466f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *out = VideoCodec(id, name, width, height, framerate, 0); 467f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 470731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParseGingleSsrc(const buzz::XmlElement* parent_elem, 471731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const buzz::QName& name, 472731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick MediaContentDescription* content) { 473731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const buzz::XmlElement* ssrc_elem = parent_elem->FirstNamed(name); 474731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (ssrc_elem) { 475731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick content->set_ssrc(strtoul(ssrc_elem->BodyText().c_str(), NULL, 10)); 476731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 477731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 478731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 4794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool ParseCryptoParams(const buzz::XmlElement* element, 4804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch CryptoParams* out, 4814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ParseError* error) { 4824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!element->HasAttr(QN_CRYPTO_SUITE)) { 4834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return BadParse("crypto: crypto-suite attribute missing ", error); 4844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (!element->HasAttr(QN_CRYPTO_KEY_PARAMS)) { 4854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return BadParse("crypto: key-params attribute missing ", error); 4864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (!element->HasAttr(QN_CRYPTO_TAG)) { 4874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return BadParse("crypto: tag attribute missing ", error); 4884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 4894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 4904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const std::string& crypto_suite = element->Attr(QN_CRYPTO_SUITE); 4914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const std::string& key_params = element->Attr(QN_CRYPTO_KEY_PARAMS); 4924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const int tag = GetXmlAttr(element, QN_CRYPTO_TAG, 0); 4934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const std::string& session_params = 4944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch element->Attr(QN_CRYPTO_SESSION_PARAMS); // Optional. 4954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 4964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch *out = CryptoParams(tag, crypto_suite, key_params, session_params); 4974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return true; 4984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 4994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 5004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 5014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Parse the first encryption element found with a matching 'usage' 5024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// element. 5034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// <usage/> is specific to Gingle. In Jingle, <crypto/> is already 5044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// scoped to a content. 5054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Return false if there was an encryption element and it could not be 5064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// parsed. 5074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool ParseGingleEncryption(const buzz::XmlElement* desc, 5084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const buzz::QName& usage, 5094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch MediaContentDescription* media, 5104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ParseError* error) { 5114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch for (const buzz::XmlElement* encryption = desc->FirstNamed(QN_ENCRYPTION); 5124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch encryption != NULL; 5134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch encryption = encryption->NextNamed(QN_ENCRYPTION)) { 5144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (encryption->FirstNamed(usage) != NULL) { 5154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch media->set_crypto_required( 5164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch GetXmlAttr(encryption, QN_ENCRYPTION_REQUIRED, false)); 5174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch for (const buzz::XmlElement* crypto = encryption->FirstNamed(QN_CRYPTO); 5184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch crypto != NULL; 5194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch crypto = crypto->NextNamed(QN_CRYPTO)) { 5204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch CryptoParams params; 5214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!ParseCryptoParams(crypto, ¶ms, error)) { 5224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 5234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 5244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch media->AddCrypto(params); 5254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 5264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch break; 5274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 5284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 5294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return true; 5304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 5314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 5324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid ParseBandwidth(const buzz::XmlElement* parent_elem, 5334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch MediaContentDescription* media) { 5344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const buzz::XmlElement* bw_elem = GetXmlChild(parent_elem, LN_BANDWIDTH); 5354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int bandwidth_kbps; 5364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (bw_elem && FromString(bw_elem->BodyText(), &bandwidth_kbps)) { 5374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (bandwidth_kbps >= 0) { 5384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch media->set_bandwidth(bandwidth_kbps * 1000); 5394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 5404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 5414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 5424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 543731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ParseGingleAudioContent(const buzz::XmlElement* content_elem, 544731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ContentDescription** content, 545731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ParseError* error) { 546731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AudioContentDescription* audio = new AudioContentDescription(); 547731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 548731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (content_elem->FirstElement()) { 549731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (const buzz::XmlElement* codec_elem = 550731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick content_elem->FirstNamed(QN_GINGLE_AUDIO_PAYLOADTYPE); 551731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick codec_elem != NULL; 552731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick codec_elem = codec_elem->NextNamed(QN_GINGLE_AUDIO_PAYLOADTYPE)) { 553731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AudioCodec codec; 554731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (ParseGingleAudioCodec(codec_elem, &codec)) { 555731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick audio->AddCodec(codec); 556f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 557f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 558731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 559731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // For backward compatibility, we can assume the other client is 560731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // an old version of Talk if it has no audio payload types at all. 561731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick audio->AddCodec(AudioCodec(103, "ISAC", 16000, -1, 1, 1)); 562731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick audio->AddCodec(AudioCodec(0, "PCMU", 8000, 64000, 1, 0)); 563731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 564731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 565dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ParseGingleSsrc(content_elem, QN_GINGLE_AUDIO_SRCID, audio); 566731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 5674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!ParseGingleEncryption(content_elem, QN_GINGLE_AUDIO_CRYPTO_USAGE, 5684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch audio, error)) { 5694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 5704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 5714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 572731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick *content = audio; 573731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 574731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 575731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 576731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ParseGingleVideoContent(const buzz::XmlElement* content_elem, 577731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ContentDescription** content, 578731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ParseError* error) { 579731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VideoContentDescription* video = new VideoContentDescription(); 580731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 581731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (const buzz::XmlElement* codec_elem = 582731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick content_elem->FirstNamed(QN_GINGLE_VIDEO_PAYLOADTYPE); 583731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick codec_elem != NULL; 584731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick codec_elem = codec_elem->NextNamed(QN_GINGLE_VIDEO_PAYLOADTYPE)) { 585731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VideoCodec codec; 586731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (ParseGingleVideoCodec(codec_elem, &codec)) { 587731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick video->AddCodec(codec); 5883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 589731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 590f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 591731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ParseGingleSsrc(content_elem, QN_GINGLE_VIDEO_SRCID, video); 5924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ParseBandwidth(content_elem, video); 5934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 5944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!ParseGingleEncryption(content_elem, QN_GINGLE_VIDEO_CRYPTO_USAGE, 5954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch video, error)) { 5964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 5974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 5983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 599731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick *content = video; 600731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 601731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 602731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 603731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParsePayloadTypeParameters(const buzz::XmlElement* element, 604731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::map<std::string, std::string>* paramap) { 605731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (const buzz::XmlElement* param = element->FirstNamed(QN_PARAMETER); 606731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick param != NULL; param = param->NextNamed(QN_PARAMETER)) { 6074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string name = GetXmlAttr(param, QN_PAYLOADTYPE_PARAMETER_NAME, 6084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch buzz::STR_EMPTY); 6094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string value = GetXmlAttr(param, QN_PAYLOADTYPE_PARAMETER_VALUE, 6104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch buzz::STR_EMPTY); 611731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!name.empty() && !value.empty()) { 612731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick paramap->insert(make_pair(name, value)); 6133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 614731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 615731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 6163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 617731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint FindWithDefault(const std::map<std::string, std::string>& map, 618731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& key, const int def) { 619731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::map<std::string, std::string>::const_iterator iter = map.find(key); 620731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return (iter == map.end()) ? def : atoi(iter->second.c_str()); 621731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 622731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 6234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 6244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Parse the first encryption element found. 6254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Return false if there was an encryption element and it could not be 6264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// parsed. 6274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool ParseJingleEncryption(const buzz::XmlElement* content_elem, 6284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch MediaContentDescription* media, 6294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ParseError* error) { 6304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const buzz::XmlElement* encryption = 6314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch content_elem->FirstNamed(QN_ENCRYPTION); 6324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (encryption == NULL) { 6334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return true; 6344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 6354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 6364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch media->set_crypto_required( 6374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch GetXmlAttr(encryption, QN_ENCRYPTION_REQUIRED, false)); 6384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 6394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch for (const buzz::XmlElement* crypto = encryption->FirstNamed(QN_CRYPTO); 6404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch crypto != NULL; 6414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch crypto = crypto->NextNamed(QN_CRYPTO)) { 6424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch CryptoParams params; 6434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!ParseCryptoParams(crypto, ¶ms, error)) { 6444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 6454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 6464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch media->AddCrypto(params); 6474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 6484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return true; 6494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 6504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 651731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ParseJingleAudioCodec(const buzz::XmlElement* elem, AudioCodec* codec) { 652731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int id = GetXmlAttr(elem, QN_ID, -1); 653731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (id < 0) 654731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return false; 655731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 6564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string name = GetXmlAttr(elem, QN_NAME, buzz::STR_EMPTY); 657731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int clockrate = GetXmlAttr(elem, QN_CLOCKRATE, 0); 658731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int channels = GetXmlAttr(elem, QN_CHANNELS, 1); 659731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 660731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::map<std::string, std::string> paramap; 661731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ParsePayloadTypeParameters(elem, ¶map); 662731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int bitrate = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_BITRATE, 0); 663731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 664731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick *codec = AudioCodec(id, name, clockrate, bitrate, channels, 0); 665731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 666731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 667731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 668731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ParseJingleVideoCodec(const buzz::XmlElement* elem, VideoCodec* codec) { 669731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int id = GetXmlAttr(elem, QN_ID, -1); 670731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (id < 0) 671731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return false; 672731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 6734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string name = GetXmlAttr(elem, QN_NAME, buzz::STR_EMPTY); 674731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 675731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::map<std::string, std::string> paramap; 676731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ParsePayloadTypeParameters(elem, ¶map); 677731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int width = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_WIDTH, 0); 678731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int height = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_HEIGHT, 0); 679731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int framerate = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_FRAMERATE, 0); 680731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 681731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick *codec = VideoCodec(id, name, width, height, framerate, 0); 682731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 683731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 684731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 685731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ParseJingleAudioContent(const buzz::XmlElement* content_elem, 686731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ContentDescription** content, 687731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ParseError* error) { 688731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AudioContentDescription* audio = new AudioContentDescription(); 689731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 690731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (const buzz::XmlElement* payload_elem = 691731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick content_elem->FirstNamed(QN_JINGLE_RTP_PAYLOADTYPE); 692731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick payload_elem != NULL; 693731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick payload_elem = payload_elem->NextNamed(QN_JINGLE_RTP_PAYLOADTYPE)) { 694731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AudioCodec codec; 695731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (ParseJingleAudioCodec(payload_elem, &codec)) { 696731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick audio->AddCodec(codec); 6973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 698731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 6993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!ParseJingleEncryption(content_elem, audio, error)) { 7014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 7024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 703731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO: Figure out how to integrate SSRC into Jingle. 704731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick *content = audio; 705731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 706731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 707731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 708731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ParseJingleVideoContent(const buzz::XmlElement* content_elem, 709731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ContentDescription** content, 710731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ParseError* error) { 711731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VideoContentDescription* video = new VideoContentDescription(); 712731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 713731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (const buzz::XmlElement* payload_elem = 714731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick content_elem->FirstNamed(QN_JINGLE_RTP_PAYLOADTYPE); 715731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick payload_elem != NULL; 716731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick payload_elem = payload_elem->NextNamed(QN_JINGLE_RTP_PAYLOADTYPE)) { 717731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VideoCodec codec; 718731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (ParseJingleVideoCodec(payload_elem, &codec)) { 719731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick video->AddCodec(codec); 720731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 721f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 722f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 7234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ParseBandwidth(content_elem, video); 7244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 7254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!ParseJingleEncryption(content_elem, video, error)) { 7264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 7274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 728731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO: Figure out how to integrate SSRC into Jingle. 729731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick *content = video; 7303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 731f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 732f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 733731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool MediaSessionClient::ParseContent(SignalingProtocol protocol, 734731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const buzz::XmlElement* content_elem, 735731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ContentDescription** content, 736731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ParseError* error) { 737731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (protocol == PROTOCOL_GINGLE) { 738731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& content_type = content_elem->Name().Namespace(); 739731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (NS_GINGLE_AUDIO == content_type) { 740731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ParseGingleAudioContent(content_elem, content, error); 741731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else if (NS_GINGLE_VIDEO == content_type) { 742731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ParseGingleVideoContent(content_elem, content, error); 743731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 744731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return BadParse("Unknown content type: " + content_type, error); 745731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 746731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 747731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string media; 748731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!RequireXmlAttr(content_elem, QN_JINGLE_CONTENT_MEDIA, &media, error)) 749731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return false; 750731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 751731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (media == JINGLE_CONTENT_MEDIA_AUDIO) { 752731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ParseJingleAudioContent(content_elem, content, error); 753731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else if (media == JINGLE_CONTENT_MEDIA_VIDEO) { 754731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ParseJingleVideoContent(content_elem, content, error); 755731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 756731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return BadParse("Unknown media: " + media, error); 757731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 758731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 759731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 760731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 761731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbuzz::XmlElement* CreateGingleAudioCodecElem(const AudioCodec& codec) { 762f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::XmlElement* payload_type = 763f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch new buzz::XmlElement(QN_GINGLE_AUDIO_PAYLOADTYPE, true); 764f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AddXmlAttr(payload_type, QN_ID, codec.id); 765f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch payload_type->AddAttr(QN_NAME, codec.name); 766f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (codec.clockrate > 0) 767f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AddXmlAttr(payload_type, QN_CLOCKRATE, codec.clockrate); 768f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (codec.bitrate > 0) 769f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AddXmlAttr(payload_type, QN_BITRATE, codec.bitrate); 770f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (codec.channels > 1) 771f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AddXmlAttr(payload_type, QN_CHANNELS, codec.channels); 772f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return payload_type; 773f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 774f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 775731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbuzz::XmlElement* CreateGingleVideoCodecElem(const VideoCodec& codec) { 776f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::XmlElement* payload_type = 777f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch new buzz::XmlElement(QN_GINGLE_VIDEO_PAYLOADTYPE, true); 778f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AddXmlAttr(payload_type, QN_ID, codec.id); 779f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch payload_type->AddAttr(QN_NAME, codec.name); 780f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AddXmlAttr(payload_type, QN_WIDTH, codec.width); 781f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AddXmlAttr(payload_type, QN_HEIGHT, codec.height); 782f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AddXmlAttr(payload_type, QN_FRAMERATE, codec.framerate); 783f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return payload_type; 784f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 785f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 786731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbuzz::XmlElement* CreateGingleSsrcElem(const buzz::QName& name, uint32 ssrc) { 787731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick buzz::XmlElement* elem = new buzz::XmlElement(name, true); 788731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (ssrc) { 789731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SetXmlBody(elem, ssrc); 790731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 791731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return elem; 792731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 793731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 7944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbuzz::XmlElement* CreateBandwidthElem(const buzz::QName& name, int bps) { 7954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int kbps = bps / 1000; 7964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch buzz::XmlElement* elem = new buzz::XmlElement(name); 7974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch elem->AddAttr(buzz::QN_TYPE, "AS"); 7984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch SetXmlBody(elem, kbps); 7994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return elem; 8004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 8014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 8024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// For Jingle, usage_qname is empty. 8034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbuzz::XmlElement* CreateJingleEncryptionElem(const CryptoParamsVec& cryptos, 8044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch bool required) { 8054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch buzz::XmlElement* encryption_elem = new buzz::XmlElement(QN_ENCRYPTION); 8064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 8074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (required) { 8084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch encryption_elem->SetAttr(QN_ENCRYPTION_REQUIRED, "true"); 8094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 8104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 8114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch for (CryptoParamsVec::const_iterator i = cryptos.begin(); 8124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch i != cryptos.end(); 8134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ++i) { 8144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch buzz::XmlElement* crypto_elem = new buzz::XmlElement(QN_CRYPTO); 8154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 8164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch AddXmlAttr(crypto_elem, QN_CRYPTO_TAG, i->tag); 8174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch crypto_elem->AddAttr(QN_CRYPTO_SUITE, i->cipher_suite); 8184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch crypto_elem->AddAttr(QN_CRYPTO_KEY_PARAMS, i->key_params); 8194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!i->session_params.empty()) { 8204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch crypto_elem->AddAttr(QN_CRYPTO_SESSION_PARAMS, i->session_params); 8214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 8224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch encryption_elem->AddElement(crypto_elem); 8234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 8244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return encryption_elem; 8254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 8264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 8274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbuzz::XmlElement* CreateGingleEncryptionElem(const CryptoParamsVec& cryptos, 8284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const buzz::QName& usage_qname, 8294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch bool required) { 8304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch buzz::XmlElement* encryption_elem = 8314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch CreateJingleEncryptionElem(cryptos, required); 8324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 8334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (required) { 8344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch encryption_elem->SetAttr(QN_ENCRYPTION_REQUIRED, "true"); 8354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 8364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 8374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch buzz::XmlElement* usage_elem = new buzz::XmlElement(usage_qname); 8384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch encryption_elem->AddElement(usage_elem); 8394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 8404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return encryption_elem; 8414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 8424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 843731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbuzz::XmlElement* CreateGingleAudioContentElem( 8444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const AudioContentDescription* audio, 8454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch bool crypto_required) { 846731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick buzz::XmlElement* elem = 847731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new buzz::XmlElement(QN_GINGLE_AUDIO_CONTENT, true); 848731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 849731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (AudioCodecs::const_iterator codec = audio->codecs().begin(); 850731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick codec != audio->codecs().end(); ++codec) { 851731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddElement(CreateGingleAudioCodecElem(*codec)); 852731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 853731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (audio->ssrc_set()) { 854731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddElement(CreateGingleSsrcElem( 855731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick QN_GINGLE_AUDIO_SRCID, audio->ssrc())); 856731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 857731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 8584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const CryptoParamsVec& cryptos = audio->cryptos(); 8594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!cryptos.empty()) { 8604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch elem->AddElement(CreateGingleEncryptionElem(cryptos, 8614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch QN_GINGLE_AUDIO_CRYPTO_USAGE, 8624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch crypto_required)); 8634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 8644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 865731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 866731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return elem; 867731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 868731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 869731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbuzz::XmlElement* CreateGingleVideoContentElem( 8704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const VideoContentDescription* video, 8714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch bool crypto_required) { 872731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick buzz::XmlElement* elem = 873731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new buzz::XmlElement(QN_GINGLE_VIDEO_CONTENT, true); 874731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 875731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (VideoCodecs::const_iterator codec = video->codecs().begin(); 876731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick codec != video->codecs().end(); ++codec) { 877731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddElement(CreateGingleVideoCodecElem(*codec)); 878731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 879731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (video->ssrc_set()) { 880731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddElement(CreateGingleSsrcElem( 881731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick QN_GINGLE_VIDEO_SRCID, video->ssrc())); 882731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 8834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (video->bandwidth() != kAutoBandwidth) { 8844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch elem->AddElement(CreateBandwidthElem(QN_GINGLE_VIDEO_BANDWIDTH, 8854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch video->bandwidth())); 8864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 8874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 8884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const CryptoParamsVec& cryptos = video->cryptos(); 8894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!cryptos.empty()) { 8904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch elem->AddElement(CreateGingleEncryptionElem(cryptos, 8914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch QN_GINGLE_VIDEO_CRYPTO_USAGE, 8924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch crypto_required)); 8934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 894731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 895731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return elem; 896731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 897731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 898731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbuzz::XmlElement* CreatePayloadTypeParameterElem( 899731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& name, int value) { 900731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick buzz::XmlElement* elem = new buzz::XmlElement(QN_PARAMETER); 901731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 902731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddAttr(QN_PAYLOADTYPE_PARAMETER_NAME, name); 903731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AddXmlAttr(elem, QN_PAYLOADTYPE_PARAMETER_VALUE, value); 904731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 905731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return elem; 906731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 907731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 908731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbuzz::XmlElement* CreateJingleAudioCodecElem(const AudioCodec& codec) { 909731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick buzz::XmlElement* elem = new buzz::XmlElement(QN_JINGLE_RTP_PAYLOADTYPE); 910731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 911731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AddXmlAttr(elem, QN_ID, codec.id); 912731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddAttr(QN_NAME, codec.name); 913731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (codec.clockrate > 0) { 914731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AddXmlAttr(elem, QN_CLOCKRATE, codec.clockrate); 915731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 916731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (codec.bitrate > 0) { 917731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddElement(CreatePayloadTypeParameterElem( 918731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick PAYLOADTYPE_PARAMETER_BITRATE, codec.bitrate)); 919731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 920731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (codec.channels > 1) { 921731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AddXmlAttr(elem, QN_CHANNELS, codec.channels); 922731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 923731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 924731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return elem; 925731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 926731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 927731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbuzz::XmlElement* CreateJingleVideoCodecElem(const VideoCodec& codec) { 928731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick buzz::XmlElement* elem = new buzz::XmlElement(QN_JINGLE_RTP_PAYLOADTYPE); 929731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 930731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AddXmlAttr(elem, QN_ID, codec.id); 931731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddAttr(QN_NAME, codec.name); 932731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddElement(CreatePayloadTypeParameterElem( 933731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick PAYLOADTYPE_PARAMETER_WIDTH, codec.width)); 934731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddElement(CreatePayloadTypeParameterElem( 935731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick PAYLOADTYPE_PARAMETER_HEIGHT, codec.height)); 936731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddElement(CreatePayloadTypeParameterElem( 937731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick PAYLOADTYPE_PARAMETER_FRAMERATE, codec.framerate)); 938731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 939731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return elem; 940731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 941731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 942731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbuzz::XmlElement* CreateJingleAudioContentElem( 9434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const AudioContentDescription* audio, bool crypto_required) { 944731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick buzz::XmlElement* elem = 945731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new buzz::XmlElement(QN_JINGLE_RTP_CONTENT, true); 946731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 947731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->SetAttr(QN_JINGLE_CONTENT_MEDIA, JINGLE_CONTENT_MEDIA_AUDIO); 948731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 949731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (AudioCodecs::const_iterator codec = audio->codecs().begin(); 950731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick codec != audio->codecs().end(); ++codec) { 951731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddElement(CreateJingleAudioCodecElem(*codec)); 952731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 953731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 9544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const CryptoParamsVec& cryptos = audio->cryptos(); 9554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!cryptos.empty()) { 9564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch elem->AddElement(CreateJingleEncryptionElem(cryptos, crypto_required)); 9574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 9584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 959731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO: Figure out how to integrate SSRC into Jingle. 960731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return elem; 961731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 962731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 963731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbuzz::XmlElement* CreateJingleVideoContentElem( 9644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const VideoContentDescription* video, bool crypto_required) { 965731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick buzz::XmlElement* elem = 966731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new buzz::XmlElement(QN_JINGLE_RTP_CONTENT, true); 967731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 968731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->SetAttr(QN_JINGLE_CONTENT_MEDIA, JINGLE_CONTENT_MEDIA_VIDEO); 969731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 970731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (VideoCodecs::const_iterator codec = video->codecs().begin(); 971731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick codec != video->codecs().end(); ++codec) { 972731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick elem->AddElement(CreateJingleVideoCodecElem(*codec)); 973731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 974731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 9754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const CryptoParamsVec& cryptos = video->cryptos(); 9764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!cryptos.empty()) { 9774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch elem->AddElement(CreateJingleEncryptionElem(cryptos, crypto_required)); 9784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 9794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 9804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (video->bandwidth() != kAutoBandwidth) { 9814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch elem->AddElement(CreateBandwidthElem(QN_JINGLE_RTP_BANDWIDTH, 9824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch video->bandwidth())); 9834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 9844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 985731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO: Figure out how to integrate SSRC into Jingle. 986731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return elem; 987731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 988731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 989731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool MediaSessionClient::WriteContent(SignalingProtocol protocol, 990731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ContentDescription* content, 9913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick buzz::XmlElement** elem, 9923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick WriteError* error) { 9933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const MediaContentDescription* media = 994731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick static_cast<const MediaContentDescription*>(content); 9954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch bool crypto_required = secure() == SEC_REQUIRED; 9963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 9973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (media->type() == MEDIA_TYPE_AUDIO) { 9983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const AudioContentDescription* audio = 999731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick static_cast<const AudioContentDescription*>(media); 1000731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (protocol == PROTOCOL_GINGLE) { 10014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch *elem = CreateGingleAudioContentElem(audio, crypto_required); 1002731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 10034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch *elem = CreateJingleAudioContentElem(audio, crypto_required); 10043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 10053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else if (media->type() == MEDIA_TYPE_VIDEO) { 10063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const VideoContentDescription* video = 1007731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick static_cast<const VideoContentDescription*>(media); 1008731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (protocol == PROTOCOL_GINGLE) { 10094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch *elem = CreateGingleVideoContentElem(video, crypto_required); 1010731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 10114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch *elem = CreateJingleVideoContentElem(video, crypto_required); 1012f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 1013731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 1014731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return BadWrite("Unknown content type: " + media->type(), error); 10153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1016731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 10173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 1018f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 1019f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 1020f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // namespace cricket 1021