1/* 2 * libjingle 3 * Copyright 2004 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include <string> 29#include <vector> 30 31#include "talk/base/gunit.h" 32#include "talk/base/logging.h" 33#include "talk/base/scoped_ptr.h" 34#include "talk/media/base/fakemediaengine.h" 35#include "talk/media/devices/fakedevicemanager.h" 36#include "talk/p2p/base/constants.h" 37#include "talk/p2p/client/basicportallocator.h" 38#include "talk/session/media/mediasessionclient.h" 39#include "talk/xmllite/xmlbuilder.h" 40#include "talk/xmllite/xmlelement.h" 41#include "talk/xmllite/xmlprinter.h" 42#include "talk/xmpp/constants.h" 43 44using cricket::AudioCodec; 45using cricket::AudioContentDescription; 46using cricket::Codec; 47using cricket::DataCodec; 48using cricket::DataContentDescription; 49using cricket::FeedbackParam; 50using cricket::FeedbackParams; 51using cricket::VideoCodec; 52using cricket::VideoContentDescription; 53 54// The codecs that our FakeMediaEngine will support. Order is important, since 55// the tests check that our messages have codecs in the correct order. 56static const cricket::AudioCodec kAudioCodecs[] = { 57 cricket::AudioCodec(103, "ISAC", 16000, -1, 1, 18), 58 cricket::AudioCodec(104, "ISAC", 32000, -1, 1, 17), 59 cricket::AudioCodec(119, "ISACLC", 16000, 40000, 1, 16), 60 cricket::AudioCodec(99, "speex", 16000, 22000, 1, 15), 61 cricket::AudioCodec(97, "IPCMWB", 16000, 80000, 1, 14), 62 cricket::AudioCodec(9, "G722", 16000, 64000, 1, 13), 63 cricket::AudioCodec(102, "iLBC", 8000, 13300, 1, 12), 64 cricket::AudioCodec(98, "speex", 8000, 11000, 1, 11), 65 cricket::AudioCodec(3, "GSM", 8000, 13000, 1, 10), 66 cricket::AudioCodec(100, "EG711U", 8000, 64000, 1, 9), 67 cricket::AudioCodec(101, "EG711A", 8000, 64000, 1, 8), 68 cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 7), 69 cricket::AudioCodec(8, "PCMA", 8000, 64000, 1, 6), 70 cricket::AudioCodec(126, "CN", 32000, 0, 1, 5), 71 cricket::AudioCodec(105, "CN", 16000, 0, 1, 4), 72 cricket::AudioCodec(13, "CN", 8000, 0, 1, 3), 73 cricket::AudioCodec(117, "red", 8000, 0, 1, 2), 74 cricket::AudioCodec(106, "telephone-event", 8000, 0, 1, 1) 75}; 76 77static const cricket::VideoCodec kVideoCodecs[] = { 78 cricket::VideoCodec(96, "H264-SVC", 320, 200, 30, 1) 79}; 80 81static const cricket::DataCodec kDataCodecs[] = { 82 cricket::DataCodec(127, "google-data", 0) 83}; 84 85const std::string kGingleCryptoOffer = \ 86 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \ 87 " <usage/> " \ 88 " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \ 89 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \ 90 " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \ 91 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \ 92 "</rtp:encryption> "; 93 94// Jingle offer does not have any <usage> element. 95const std::string kJingleCryptoOffer = \ 96 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \ 97 " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \ 98 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \ 99 " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \ 100 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \ 101 "</rtp:encryption> "; 102 103 104const std::string kGingleRequiredCryptoOffer = \ 105 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'> "\ 106 " <usage/> " \ 107 " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \ 108 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \ 109 " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \ 110 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \ 111 "</rtp:encryption> "; 112 113const std::string kJingleRequiredCryptoOffer = \ 114 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'> "\ 115 " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \ 116 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \ 117 " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \ 118 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \ 119 "</rtp:encryption> "; 120 121 122const std::string kGingleUnsupportedCryptoOffer = \ 123 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \ 124 " <usage/> " \ 125 " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \ 126 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \ 127 " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \ 128 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \ 129 "</rtp:encryption> "; 130 131const std::string kJingleUnsupportedCryptoOffer = \ 132 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \ 133 " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \ 134 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \ 135 " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \ 136 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \ 137 "</rtp:encryption> "; 138 139 140// With unsupported but with required="true" 141const std::string kGingleRequiredUnsupportedCryptoOffer = \ 142 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'>" \ 143 " <usage/> " \ 144 " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \ 145 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \ 146 " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \ 147 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \ 148 "</rtp:encryption> "; 149 150const std::string kJingleRequiredUnsupportedCryptoOffer = \ 151 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'>" \ 152 " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1' " \ 153 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/> " \ 154 " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2' " \ 155 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \ 156 "</rtp:encryption> "; 157 158const std::string kGingleInitiate( 159 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 160 " to='user@domain.com/resource' type='set' id='123'> " \ 161 " <session xmlns='http://www.google.com/session' type='initiate'" \ 162 " id='abcdef' initiator='me@domain.com/resource'> " \ 163 " <description xmlns='http://www.google.com/session/phone'> " \ 164 " <payload-type xmlns='http://www.google.com/session/phone' " \ 165 " id='103' name='ISAC' clockrate='16000' /> " \ 166 " <payload-type xmlns='http://www.google.com/session/phone' " \ 167 " id='104' name='ISAC' clockrate='32000' /> " \ 168 " <payload-type xmlns='http://www.google.com/session/phone' " \ 169 " id='119' name='ISACLC' clockrate='16000' bitrate='40000' /> " \ 170 " <payload-type xmlns='http://www.google.com/session/phone' " \ 171 " id='99' name='speex' clockrate='16000' bitrate='22000' /> " \ 172 " <payload-type xmlns='http://www.google.com/session/phone' " \ 173 " id='97' name='IPCMWB' clockrate='16000' bitrate='80000' /> " \ 174 " <payload-type xmlns='http://www.google.com/session/phone' " \ 175 " id='9' name='G722' clockrate='16000' bitrate='64000' /> " \ 176 " <payload-type xmlns='http://www.google.com/session/phone' " \ 177 " id='102' name='iLBC' clockrate='8000' bitrate='13300' />" \ 178 " <payload-type xmlns='http://www.google.com/session/phone' " \ 179 " id='98' name='speex' clockrate='8000' bitrate='11000' />" \ 180 " <payload-type xmlns='http://www.google.com/session/phone' " \ 181 " id='3' name='GSM' clockrate='8000' bitrate='13000' /> " \ 182 " <payload-type xmlns='http://www.google.com/session/phone' " \ 183 " id='100' name='EG711U' clockrate='8000' bitrate='64000' /> " \ 184 " <payload-type xmlns='http://www.google.com/session/phone' " \ 185 " id='101' name='EG711A' clockrate='8000' bitrate='64000' /> " \ 186 " <payload-type xmlns='http://www.google.com/session/phone' " \ 187 " id='0' name='PCMU' clockrate='8000' bitrate='64000' /> " \ 188 " <payload-type xmlns='http://www.google.com/session/phone' " \ 189 " id='8' name='PCMA' clockrate='8000' bitrate='64000' /> " \ 190 " <payload-type xmlns='http://www.google.com/session/phone' " \ 191 " id='126' name='CN' clockrate='32000' /> " \ 192 " <payload-type xmlns='http://www.google.com/session/phone' " \ 193 " id='105' name='CN' clockrate='16000' /> " \ 194 " <payload-type xmlns='http://www.google.com/session/phone' " \ 195 " id='13' name='CN' clockrate='8000' /> " \ 196 " <payload-type xmlns='http://www.google.com/session/phone' " \ 197 " id='117' name='red' clockrate='8000' /> " \ 198 " <payload-type xmlns='http://www.google.com/session/phone' " \ 199 " id='106' name='telephone-event' clockrate='8000' /> " \ 200 " </description> " \ 201 " </session> " \ 202 "</iq> "); 203 204const std::string kJingleInitiate( 205 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 206 " to='user@domain.com/resource' type='set' id='123'> " \ 207 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 208 " sid='abcdef' initiator='me@domain.com/resource'> " \ 209 " <content name='test audio'> " \ 210 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \ 211 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \ 212 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \ 213 " <payload-type " \ 214 " id='119' name='ISACLC' clockrate='16000'> " \ 215 " <parameter name='bitrate' value='40000'/> " \ 216 " </payload-type> " \ 217 " <payload-type " \ 218 " id='99' name='speex' clockrate='16000'> " \ 219 " <parameter name='bitrate' value='22000'/> " \ 220 " </payload-type> " \ 221 " <payload-type " \ 222 " id='97' name='IPCMWB' clockrate='16000'> " \ 223 " <parameter name='bitrate' value='80000'/> " \ 224 " </payload-type> " \ 225 " <payload-type " \ 226 " id='9' name='G722' clockrate='16000'> " \ 227 " <parameter name='bitrate' value='64000'/> " \ 228 " </payload-type> " \ 229 " <payload-type " \ 230 " id='102' name='iLBC' clockrate='8000'> " \ 231 " <parameter name='bitrate' value='13300'/> " \ 232 " </payload-type> " \ 233 " <payload-type " \ 234 " id='98' name='speex' clockrate='8000'> " \ 235 " <parameter name='bitrate' value='11000'/> " \ 236 " </payload-type> " \ 237 " <payload-type " \ 238 " id='3' name='GSM' clockrate='8000'> " \ 239 " <parameter name='bitrate' value='13000'/> " \ 240 " </payload-type> " \ 241 " <payload-type " \ 242 " id='100' name='EG711U' clockrate='8000'> " \ 243 " <parameter name='bitrate' value='64000'/> " \ 244 " </payload-type> " \ 245 " <payload-type " \ 246 " id='101' name='EG711A' clockrate='8000'> " \ 247 " <parameter name='bitrate' value='64000'/> " \ 248 " </payload-type> " \ 249 " <payload-type " \ 250 " id='0' name='PCMU' clockrate='8000'> " \ 251 " <parameter name='bitrate' value='64000'/> " \ 252 " </payload-type> " \ 253 " <payload-type " \ 254 " id='8' name='PCMA' clockrate='8000'> " \ 255 " <parameter name='bitrate' value='64000'/> " \ 256 " </payload-type> " \ 257 " <payload-type " \ 258 " id='126' name='CN' clockrate='32000' /> " \ 259 " <payload-type " \ 260 " id='105' name='CN' clockrate='16000' /> " \ 261 " <payload-type " \ 262 " id='13' name='CN' clockrate='8000' /> " \ 263 " <payload-type " \ 264 " id='117' name='red' clockrate='8000' /> " \ 265 " <payload-type " \ 266 " id='106' name='telephone-event' clockrate='8000' /> " \ 267 " </description> " \ 268 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 269 " </content> " \ 270 " </jingle> " \ 271 "</iq> "); 272 273// Initiate string with a different order of supported codecs. 274// Should accept the supported ones, but with our desired order. 275const std::string kGingleInitiateDifferentPreference( 276 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 277 " to='user@domain.com/resource' type='set' id='123'> " \ 278 " <session xmlns='http://www.google.com/session' type='initiate'" \ 279 " id='abcdef' initiator='me@domain.com/resource'> " \ 280 " <description xmlns='http://www.google.com/session/phone'> " \ 281 " <payload-type xmlns='http://www.google.com/session/phone' " \ 282 " id='104' name='ISAC' clockrate='32000' /> " \ 283 " <payload-type xmlns='http://www.google.com/session/phone' " \ 284 " id='97' name='IPCMWB' clockrate='16000' bitrate='80000' /> " \ 285 " <payload-type xmlns='http://www.google.com/session/phone' " \ 286 " id='9' name='G722' clockrate='16000' bitrate='64000' /> " \ 287 " <payload-type xmlns='http://www.google.com/session/phone' " \ 288 " id='119' name='ISACLC' clockrate='16000' bitrate='40000' /> " \ 289 " <payload-type xmlns='http://www.google.com/session/phone' " \ 290 " id='103' name='ISAC' clockrate='16000' /> " \ 291 " <payload-type xmlns='http://www.google.com/session/phone' " \ 292 " id='99' name='speex' clockrate='16000' bitrate='22000' /> " \ 293 " <payload-type xmlns='http://www.google.com/session/phone' " \ 294 " id='100' name='EG711U' clockrate='8000' bitrate='64000' /> " \ 295 " <payload-type xmlns='http://www.google.com/session/phone' " \ 296 " id='101' name='EG711A' clockrate='8000' bitrate='64000' /> " \ 297 " <payload-type xmlns='http://www.google.com/session/phone' " \ 298 " id='0' name='PCMU' clockrate='8000' bitrate='64000' /> " \ 299 " <payload-type xmlns='http://www.google.com/session/phone' " \ 300 " id='8' name='PCMA' clockrate='8000' bitrate='64000' /> " \ 301 " <payload-type xmlns='http://www.google.com/session/phone' " \ 302 " id='102' name='iLBC' clockrate='8000' bitrate='13300' />" \ 303 " <payload-type xmlns='http://www.google.com/session/phone' " \ 304 " id='3' name='GSM' clockrate='8000' bitrate='13000' /> " \ 305 " <payload-type xmlns='http://www.google.com/session/phone' " \ 306 " id='98' name='speex' clockrate='8000' bitrate='11000' />" \ 307 " <payload-type xmlns='http://www.google.com/session/phone' " \ 308 " id='126' name='CN' clockrate='32000' /> " \ 309 " <payload-type xmlns='http://www.google.com/session/phone' " \ 310 " id='105' name='CN' clockrate='16000' /> " \ 311 " <payload-type xmlns='http://www.google.com/session/phone' " \ 312 " id='13' name='CN' clockrate='8000' /> " \ 313 " <payload-type xmlns='http://www.google.com/session/phone' " \ 314 " id='117' name='red' clockrate='8000' /> " \ 315 " <payload-type xmlns='http://www.google.com/session/phone' " \ 316 " id='106' name='telephone-event' clockrate='8000' /> " \ 317 " </description> " \ 318 " </session> " \ 319 "</iq> "); 320 321const std::string kJingleInitiateDifferentPreference( 322 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 323 " to='user@domain.com/resource' type='set' id='123'> " \ 324 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 325 " sid='abcdef' initiator='me@domain.com/resource'> " \ 326 " <content name='test audio'> " \ 327 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \ 328 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \ 329 " <payload-type " \ 330 " id='97' name='IPCMWB' clockrate='16000'> " \ 331 " <parameter name='bitrate' value='80000'/> " \ 332 " </payload-type> " \ 333 " <payload-type " \ 334 " id='9' name='G722' clockrate='16000'> " \ 335 " <parameter name='bitrate' value='64000'/> " \ 336 " </payload-type> " \ 337 " <payload-type " \ 338 " id='119' name='ISACLC' clockrate='16000'> " \ 339 " <parameter name='bitrate' value='40000'/> " \ 340 " </payload-type> " \ 341 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \ 342 " <payload-type " \ 343 " id='99' name='speex' clockrate='16000'> " \ 344 " <parameter name='bitrate' value='22000'/> " \ 345 " </payload-type> " \ 346 " <payload-type " \ 347 " id='100' name='EG711U' clockrate='8000'> " \ 348 " <parameter name='bitrate' value='64000'/> " \ 349 " </payload-type> " \ 350 " <payload-type " \ 351 " id='101' name='EG711A' clockrate='8000'> " \ 352 " <parameter name='bitrate' value='64000'/> " \ 353 " </payload-type> " \ 354 " <payload-type " \ 355 " id='0' name='PCMU' clockrate='8000'> " \ 356 " <parameter name='bitrate' value='64000'/> " \ 357 " </payload-type> " \ 358 " <payload-type " \ 359 " id='8' name='PCMA' clockrate='8000'> " \ 360 " <parameter name='bitrate' value='64000'/> " \ 361 " </payload-type> " \ 362 " <payload-type " \ 363 " id='102' name='iLBC' clockrate='8000'> " \ 364 " <parameter name='bitrate' value='13300'/> " \ 365 " </payload-type> " \ 366 " <payload-type " \ 367 " id='3' name='GSM' clockrate='8000'> " \ 368 " <parameter name='bitrate' value='13000'/> " \ 369 " </payload-type> " \ 370 " <payload-type " \ 371 " id='98' name='speex' clockrate='8000'> " \ 372 " <parameter name='bitrate' value='11000'/> " \ 373 " </payload-type> " \ 374 " <payload-type " \ 375 " id='126' name='CN' clockrate='32000' /> " \ 376 " <payload-type " \ 377 " id='105' name='CN' clockrate='16000' /> " \ 378 " <payload-type " \ 379 " id='13' name='CN' clockrate='8000' /> " \ 380 " <payload-type " \ 381 " id='117' name='red' clockrate='8000' /> " \ 382 " <payload-type " \ 383 " id='106' name='telephone-event' clockrate='8000' /> " \ 384 " </description> " \ 385 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 386 " </content> " \ 387 " </jingle> " \ 388 "</iq> "); 389 390const std::string kJingleInitiateWithRtcpFb( 391 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 392 " to='user@domain.com/resource' type='set' id='123'> " \ 393 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 394 " sid='abcdef' initiator='me@domain.com/resource'> " \ 395 " <content name='test audio'> " \ 396 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \ 397 " <payload-type id='103' name='ISAC' clockrate='16000'> " \ 398 " <rtcp-fb type='nack'/> " \ 399 " </payload-type> " \ 400 " </description> " \ 401 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 402 " </content> " \ 403 " <content name='test video'> " \ 404 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \ 405 " <rtcp-fb type='nack'/> " \ 406 " <payload-type id='99' name='H264-SVC'> " \ 407 " <rtcp-fb type='ccm' subtype='fir'/> " \ 408 " <parameter name='height' value='200'/> " \ 409 " <parameter name='width' value='320'/> " \ 410 " <parameter name='framerate' value='30'/> " \ 411 " </payload-type> " \ 412 " </description> " \ 413 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 414 " </content> " \ 415 " <content name='test data'> " \ 416 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='data'> " \ 417 " <rtcp-fb type='nack'/> " \ 418 " <payload-type id='127' name='google-data'> " \ 419 " </payload-type> " \ 420 " </description> " \ 421 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 422 " </content> " \ 423 " </jingle> " \ 424 "</iq> "); 425 426const std::string kGingleVideoInitiate( 427 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 428 " to='user@domain.com/resource' type='set' id='123'> " \ 429 " <session xmlns='http://www.google.com/session' type='initiate'" \ 430 " id='abcdef' initiator='me@domain.com/resource'> " \ 431 " <description xmlns='http://www.google.com/session/video'> " \ 432 " <payload-type xmlns='http://www.google.com/session/phone' " \ 433 " id='103' name='ISAC' clockrate='16000' /> " \ 434 " <payload-type xmlns='http://www.google.com/session/video' " \ 435 " id='99' name='H264-SVC' framerate='30' " \ 436 " height='200' width='320'/> " \ 437 " </description> " \ 438 " </session> " \ 439 "</iq> "); 440 441const std::string kJingleVideoInitiate( 442 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 443 " to='user@domain.com/resource' type='set' id='123'> " \ 444 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 445 " sid='abcdef' initiator='me@domain.com/resource'> " \ 446 " <content name='test audio'> " \ 447 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \ 448 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \ 449 " </description> " \ 450 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 451 " </content> " \ 452 " <content name='test video'> " \ 453 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \ 454 " <payload-type id='99' name='H264-SVC'> " \ 455 " <parameter name='height' value='200'/> " \ 456 " <parameter name='width' value='320'/> " \ 457 " <parameter name='framerate' value='30'/> " \ 458 " </payload-type> " \ 459 " </description> " \ 460 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 461 " </content> " \ 462 " </jingle> " \ 463 "</iq> "); 464 465const std::string kJingleVideoInitiateWithRtpData( 466 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 467 " to='user@domain.com/resource' type='set' id='123'> " \ 468 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 469 " sid='abcdef' initiator='me@domain.com/resource'> " \ 470 " <content name='test audio'> " \ 471 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \ 472 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \ 473 " </description> " \ 474 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 475 " </content> " \ 476 " <content name='test video'> " \ 477 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \ 478 " <payload-type id='99' name='H264-SVC'> " \ 479 " <parameter name='height' value='200'/> " \ 480 " <parameter name='width' value='320'/> " \ 481 " <parameter name='framerate' value='30'/> " \ 482 " </payload-type> " \ 483 " </description> " \ 484 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 485 " </content> " \ 486 " <content name='test data'> " \ 487 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='data'> " \ 488 " <payload-type id='127' name='google-data'/> " \ 489 " <rtcp-mux/> " \ 490 " </description> " \ 491 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 492 " </content> " \ 493 " </jingle> " \ 494 "</iq> "); 495 496const std::string kJingleVideoInitiateWithSctpData( 497 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 498 " to='user@domain.com/resource' type='set' id='123'> " \ 499 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 500 " sid='abcdef' initiator='me@domain.com/resource'> " \ 501 " <content name='test audio'> " \ 502 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \ 503 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \ 504 " </description> " \ 505 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 506 " </content> " \ 507 " <content name='test video'> " \ 508 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \ 509 " <payload-type id='99' name='H264-SVC'> " \ 510 " <parameter name='height' value='200'/> " \ 511 " <parameter name='width' value='320'/> " \ 512 " <parameter name='framerate' value='30'/> " \ 513 " </payload-type> " \ 514 " </description> " \ 515 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 516 " </content> " \ 517 " <content name='test data'> " \ 518 " <description xmlns='google:jingle:sctp' media='data'> " \ 519 " <stream sid='1'/> " \ 520 " </description> " \ 521 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 522 " </content> " \ 523 " </jingle> " \ 524 "</iq> "); 525 526const std::string kJingleVideoInitiateWithBandwidth( 527 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 528 " to='user@domain.com/resource' type='set' id='123'> " \ 529 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 530 " sid='abcdef' initiator='me@domain.com/resource'> " \ 531 " <content name='test audio'> " \ 532 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \ 533 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \ 534 " </description> " \ 535 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 536 " </content> " \ 537 " <content name='test video'> " \ 538 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \ 539 " <payload-type id='99' name='H264-SVC'> " \ 540 " <parameter name='height' value='200'/> " \ 541 " <parameter name='width' value='320'/> " \ 542 " <parameter name='framerate' value='30'/> " \ 543 " </payload-type> " \ 544 " <bandwidth type='AS'>42</bandwidth> " \ 545 " </description> " \ 546 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 547 " </content> " \ 548 " </jingle> " \ 549 "</iq> "); 550 551const std::string kJingleVideoInitiateWithRtcpMux( 552 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 553 " to='user@domain.com/resource' type='set' id='123'> " \ 554 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 555 " sid='abcdef' initiator='me@domain.com/resource'> " \ 556 " <content name='test audio'> " \ 557 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \ 558 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \ 559 " </description> " \ 560 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 561 " </content> " \ 562 " <content name='test video'> " \ 563 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \ 564 " <payload-type id='99' name='H264-SVC'> " \ 565 " <parameter name='height' value='200'/> " \ 566 " <parameter name='width' value='320'/> " \ 567 " <parameter name='framerate' value='30'/> " \ 568 " </payload-type> " \ 569 " <rtcp-mux/> " \ 570 " </description> " \ 571 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 572 " </content> " \ 573 " </jingle> " \ 574 "</iq> "); 575 576// Initiate string with a combination of supported and unsupported codecs 577// Should accept the supported ones 578const std::string kGingleInitiateSomeUnsupported( 579 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 580 " to='user@domain.com/resource' type='set' id='123'> " \ 581 " <session xmlns='http://www.google.com/session' type='initiate'" \ 582 " id='abcdef' initiator='me@domain.com/resource'> " \ 583 " <description xmlns='http://www.google.com/session/phone'> " \ 584 " <payload-type xmlns='http://www.google.com/session/phone' " \ 585 " id='103' name='ISAC' clockrate='16000' /> " \ 586 " <payload-type xmlns='http://www.google.com/session/phone' " \ 587 " id='97' name='ASDFDS' /> " \ 588 " <payload-type xmlns='http://www.google.com/session/phone' " \ 589 " id='102' name='1010' /> " \ 590 " <payload-type xmlns='http://www.google.com/session/phone' " \ 591 " id='107' name='DFAS' /> " \ 592 " <payload-type xmlns='http://www.google.com/session/phone' " \ 593 " id='100' name='EG711U' /> " \ 594 " <payload-type xmlns='http://www.google.com/session/phone' " \ 595 " id='101' name='EG711A' /> " \ 596 " <payload-type xmlns='http://www.google.com/session/phone' " \ 597 " id='0' name='PCMU' /> " \ 598 " <payload-type xmlns='http://www.google.com/session/phone' " \ 599 " id='110' name=':)' /> " \ 600 " <payload-type xmlns='http://www.google.com/session/phone' " \ 601 " id='13' name='CN' /> " \ 602 " </description> " \ 603 " </session> " \ 604 "</iq> "); 605 606const std::string kJingleInitiateSomeUnsupported( 607 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 608 " to='user@domain.com/resource' type='set' id='123'> " \ 609 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 610 " sid='abcdef' initiator='me@domain.com/resource'> " \ 611 " <content name='test audio'> " \ 612 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \ 613 " <payload-type " \ 614 " id='103' name='ISAC' clockrate='16000' /> " \ 615 " <payload-type " \ 616 " id='97' name='ASDFDS' /> " \ 617 " <payload-type " \ 618 " id='102' name='1010' /> " \ 619 " <payload-type " \ 620 " id='107' name='DFAS' /> " \ 621 " <payload-type " \ 622 " id='100' name='EG711U' /> " \ 623 " <payload-type " \ 624 " id='101' name='EG711A' /> " \ 625 " <payload-type " \ 626 " id='0' name='PCMU' /> " \ 627 " <payload-type " \ 628 " id='110' name=':)' /> " \ 629 " <payload-type " \ 630 " id='13' name='CN' /> " \ 631 " </description> " \ 632 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 633 " </content> " \ 634 " </jingle> " \ 635 "</iq> "); 636 637const std::string kGingleVideoInitiateWithBandwidth( 638 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 639 " to='user@domain.com/resource' type='set' id='123'> " \ 640 " <session xmlns='http://www.google.com/session' type='initiate'" \ 641 " id='abcdef' initiator='me@domain.com/resource'> " \ 642 " <description xmlns='http://www.google.com/session/video'> " \ 643 " <payload-type xmlns='http://www.google.com/session/phone' " \ 644 " id='103' name='ISAC' clockrate='16000' /> " \ 645 " <payload-type xmlns='http://www.google.com/session/video' " \ 646 " id='99' name='H264-SVC' framerate='30' " \ 647 " height='200' width='320'/> " \ 648 " <bandwidth type='AS'>42</bandwidth> " \ 649 " </description> " \ 650 " </session> " \ 651 "</iq> "); 652 653// Initiate string without any supported codecs. Should send a reject. 654const std::string kGingleInitiateNoSupportedAudioCodecs( 655 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 656 " to='user@domain.com/resource' type='set' id='123'> " \ 657 " <session xmlns='http://www.google.com/session' type='initiate'" \ 658 " id='abcdef' initiator='me@domain.com/resource'> " \ 659 " <description xmlns='http://www.google.com/session/phone'> " \ 660 " <payload-type xmlns='http://www.google.com/session/phone' " \ 661 " id='123' name='Supercodec6000' /> " \ 662 " </description> " \ 663 " </session> " \ 664 "</iq> "); 665 666const std::string kJingleInitiateNoSupportedAudioCodecs( 667 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 668 " to='user@domain.com/resource' type='set' id='123'> " \ 669 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 670 " sid='abcdef' initiator='me@domain.com/resource'> " \ 671 " <content name='test audio'> " \ 672 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \ 673 " <payload-type " \ 674 " id='123' name='Supercodec6000' /> " \ 675 " </description> " \ 676 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 677 " </content> " \ 678 " </jingle> " \ 679 "</iq> "); 680 681// Initiate string without any codecs. Assumes ancient version of Cricket 682// and tries a session with ISAC and PCMU 683const std::string kGingleInitiateNoAudioCodecs( 684 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 685 " to='user@domain.com/resource' type='set' id='123'> " \ 686 " <session xmlns='http://www.google.com/session' type='initiate'" \ 687 " id='abcdef' initiator='me@domain.com/resource'> " \ 688 " <description xmlns='http://www.google.com/session/phone'> " \ 689 " </description> " \ 690 " </session> " \ 691 "</iq> "); 692 693const std::string kJingleInitiateNoAudioCodecs( 694 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 695 " to='user@domain.com/resource' type='set' id='123'> " \ 696 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 697 " sid='abcdef' initiator='me@domain.com/resource'> " \ 698 " <content name='test audio'> " \ 699 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \ 700 " </description> " \ 701 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 702 " </content> " \ 703 " </jingle> " \ 704 "</iq> "); 705 706// The codecs are supported, but not at the given clockrates. Should send 707// a reject. 708const std::string kGingleInitiateWrongClockrates( 709 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 710 " to='user@domain.com/resource' type='set' id='123'> " \ 711 " <session xmlns='http://www.google.com/session' type='initiate'" \ 712 " id='abcdef' initiator='me@domain.com/resource'> " \ 713 " <description xmlns='http://www.google.com/session/phone'> " \ 714 " <payload-type xmlns='http://www.google.com/session/phone' " \ 715 " id='103' name='ISAC' clockrate='8000'/> " \ 716 " <payload-type xmlns='http://www.google.com/session/phone' " \ 717 " id='97' name='IPCMWB' clockrate='1337'/> " \ 718 " <payload-type xmlns='http://www.google.com/session/phone' " \ 719 " id='102' name='iLBC' clockrate='1982' /> " \ 720 " </description> " \ 721 " </session> " \ 722 "</iq> "); 723 724const std::string kJingleInitiateWrongClockrates( 725 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 726 " to='user@domain.com/resource' type='set' id='123'> " \ 727 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 728 " sid='abcdef' initiator='me@domain.com/resource'> " \ 729 " <content name='test audio'> " \ 730 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \ 731 " <payload-type " \ 732 " id='103' name='ISAC' clockrate='8000'/> " \ 733 " <payload-type " \ 734 " id='97' name='IPCMWB' clockrate='1337'/> " \ 735 " <payload-type " \ 736 " id='102' name='iLBC' clockrate='1982' /> " \ 737 " </description> " \ 738 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 739 " </content> " \ 740 " </jingle> " \ 741 "</iq> "); 742 743// The codecs are supported, but not with the given number of channels. 744// Should send a reject. 745const std::string kGingleInitiateWrongChannels( 746 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 747 " to='user@domain.com/resource' type='set' id='123'> " \ 748 " <session xmlns='http://www.google.com/session' type='initiate'" \ 749 " id='abcdef' initiator='me@domain.com/resource'> " \ 750 " <description xmlns='http://www.google.com/session/phone'> " \ 751 " <payload-type xmlns='http://www.google.com/session/phone' " \ 752 " id='103' name='ISAC' channels='2'/> " \ 753 " <payload-type xmlns='http://www.google.com/session/phone' " \ 754 " id='97' name='IPCMWB' channels='3'/> " \ 755 " </description> " \ 756 " </session> " \ 757 "</iq> "); 758 759const std::string kJingleInitiateWrongChannels( 760 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 761 " to='user@domain.com/resource' type='set' id='123'> " \ 762 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'> " \ 763 " <content name='test audio'> " \ 764 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \ 765 " <payload-type " \ 766 " id='103' name='ISAC' channels='2'/> " \ 767 " <payload-type " \ 768 " id='97' name='IPCMWB' channels='3'/> " \ 769 " </description> " \ 770 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 771 " </content> " \ 772 " </jingle> " \ 773 "</iq> "); 774 775// Initiate with a dynamic codec not using webrtc default payload id. Should 776// accept with provided payload id. 777const std::string kGingleInitiateDynamicAudioCodecs( 778 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 779 " to='user@domain.com/resource' type='set' id='123'> " \ 780 " <session xmlns='http://www.google.com/session' type='initiate'" \ 781 " id='abcdef' initiator='me@domain.com/resource'> " \ 782 " <description xmlns='http://www.google.com/session/phone'> " \ 783 " <payload-type xmlns='http://www.google.com/session/phone' " \ 784 " id='123' name='speex' clockrate='16000'/> " \ 785 " </description> " \ 786 " </session> " \ 787 "</iq> "); 788 789const std::string kJingleInitiateDynamicAudioCodecs( 790 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 791 " to='user@domain.com/resource' type='set' id='123'> " \ 792 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 793 " sid='abcdef' initiator='me@domain.com/resource'> " \ 794 " <content name='test audio'> " \ 795 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \ 796 " <payload-type " \ 797 " id='123' name='speex' clockrate='16000'/> " \ 798 " </description> " \ 799 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 800 " </content> " \ 801 " </jingle> " \ 802 "</iq> "); 803 804// Initiate string with nothing but static codec id's. Should accept. 805const std::string kGingleInitiateStaticAudioCodecs( 806 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 807 " to='user@domain.com/resource' type='set' id='123'> " \ 808 " <session xmlns='http://www.google.com/session' type='initiate'" \ 809 " id='abcdef' initiator='me@domain.com/resource'> " \ 810 " <description xmlns='http://www.google.com/session/phone'> " \ 811 " <payload-type xmlns='http://www.google.com/session/phone' " \ 812 " id='3' /> " \ 813 " <payload-type xmlns='http://www.google.com/session/phone' " \ 814 " id='0' /> " \ 815 " <payload-type xmlns='http://www.google.com/session/phone' " \ 816 " id='8' /> " \ 817 " </description> " \ 818 " </session> " \ 819 "</iq> "); 820 821const std::string kJingleInitiateStaticAudioCodecs( 822 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 823 " to='user@domain.com/resource' type='set' id='123'> " \ 824 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \ 825 " sid='abcdef' initiator='me@domain.com/resource'> " \ 826 " <content name='test audio'> " \ 827 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \ 828 " <payload-type id='3' /> " \ 829 " <payload-type id='0' /> " \ 830 " <payload-type id='8' /> " \ 831 " </description> " \ 832 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 833 " </content> " \ 834 " </jingle> " \ 835 "</iq> "); 836 837// Initiate with payload type-less codecs. Should reject. 838const std::string kGingleInitiateNoPayloadTypes( 839 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 840 " to='user@domain.com/resource' type='set' id='123'> " \ 841 " <session xmlns='http://www.google.com/session' type='initiate'" \ 842 " id='abcdef' initiator='me@domain.com/resource'> " \ 843 " <description xmlns='http://www.google.com/session/phone'> " \ 844 " <payload-type xmlns='http://www.google.com/session/phone' " \ 845 " name='ISAC' clockrate='16000'/> " \ 846 " </description> " \ 847 " </session> " \ 848 "</iq> "); 849 850const std::string kJingleInitiateNoPayloadTypes( 851 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 852 " to='user@domain.com/resource' type='set' id='123'> " \ 853 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'> " \ 854 " sid='abcdef' initiator='me@domain.com/resource'> " \ 855 " <content name='test audio'> " \ 856 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \ 857 " <payload-type name='ISAC' clockrate='16000'/> " \ 858 " </description> " \ 859 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 860 " </content> " \ 861 " </jingle> " \ 862 "</iq> "); 863 864// Initiate with unnamed dynamic codces. Should reject. 865const std::string kGingleInitiateDynamicWithoutNames( 866 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 867 " to='user@domain.com/resource' type='set' id='123'> " \ 868 " <session xmlns='http://www.google.com/session' type='initiate'" \ 869 " id='abcdef' initiator='me@domain.com/resource'> " \ 870 " <description xmlns='http://www.google.com/session/phone'> " \ 871 " <payload-type xmlns='http://www.google.com/session/phone' " \ 872 " id='100' clockrate='16000'/> " \ 873 " </description> " \ 874 " </session> " \ 875 "</iq> "); 876 877const std::string kJingleInitiateDynamicWithoutNames( 878 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \ 879 " to='user@domain.com/resource' type='set' id='123'> " \ 880 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'> " \ 881 " sid='abcdef' initiator='me@domain.com/resource'> " \ 882 " <content name='test audio'> " \ 883 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \ 884 " <payload-type id='100' clockrate='16000'/> " \ 885 " </description> " \ 886 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \ 887 " </content> " \ 888 " </jingle> " \ 889 "</iq> "); 890 891const uint32 kAudioSsrc = 4294967295U; 892const uint32 kVideoSsrc = 87654321; 893const uint32 kDataSsrc = 1010101; 894// Note that this message does not specify a session ID. It must be populated 895// before use. 896const std::string kGingleAcceptWithSsrcs( 897 "<iq xmlns='jabber:client' from='me@mydomain.com' " \ 898 " to='user@domain.com/resource' type='set' id='150'> " \ 899 " <session xmlns='http://www.google.com/session' type='accept' " \ 900 " initiator='me@domain.com/resource'> " \ 901 " <description xmlns='http://www.google.com/session/video'> " \ 902 " <payload-type xmlns='http://www.google.com/session/phone' " \ 903 " id='103' name='ISAC' clockrate='16000' /> " \ 904 " <payload-type xmlns='http://www.google.com/session/phone' " \ 905 " id='104' name='ISAC' clockrate='32000' /> " \ 906 " <src-id xmlns='http://www.google.com/session/phone'> " \ 907 " 4294967295</src-id> " \ 908 " <src-id>87654321</src-id> " \ 909 " </description> " \ 910 " </session> " \ 911 "</iq> "); 912 913const std::string kJingleAcceptWithSsrcs( 914 "<iq xmlns='jabber:client' from='me@mydomain.com' " \ 915 " to='user@domain.com/resource' type='set' id='150'> " \ 916 " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \ 917 " initiator='me@domain.com/resource'> " \ 918 " <content name='audio'> " \ 919 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \ 920 " media='audio' ssrc='4294967295'> " \ 921 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \ 922 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \ 923 " </description> " \ 924 " <transport xmlns='http://www.google.com/transport/p2p'/> " \ 925 " </content> " \ 926 " <content name='video'> " \ 927 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \ 928 " media='video' ssrc='87654321'> " \ 929 " </description> " \ 930 " <transport xmlns='http://www.google.com/transport/p2p'/> " \ 931 " </content> " \ 932 " </jingle> " \ 933 "</iq> "); 934 935const std::string kJingleAcceptWithRtpDataSsrcs( 936 "<iq xmlns='jabber:client' from='me@mydomain.com' " \ 937 " to='user@domain.com/resource' type='set' id='150'> " \ 938 " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \ 939 " initiator='me@domain.com/resource'> " \ 940 " <content name='audio'> " \ 941 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \ 942 " media='audio' ssrc='4294967295'> " \ 943 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \ 944 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \ 945 " </description> " \ 946 " <transport xmlns='http://www.google.com/transport/p2p'/> " \ 947 " </content> " \ 948 " <content name='video'> " \ 949 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \ 950 " media='video' ssrc='87654321'> " \ 951 " </description> " \ 952 " <transport xmlns='http://www.google.com/transport/p2p'/> " \ 953 " </content> " \ 954 " <content name='data'> " \ 955 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \ 956 " media='data' ssrc='1010101'> " \ 957 " </description> " \ 958 " <transport xmlns='http://www.google.com/transport/p2p'/> " \ 959 " </content> " \ 960 " </jingle> " \ 961 "</iq> "); 962 963const std::string kJingleAcceptWithSctpData( 964 "<iq xmlns='jabber:client' from='me@mydomain.com' " \ 965 " to='user@domain.com/resource' type='set' id='150'> " \ 966 " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \ 967 " initiator='me@domain.com/resource'> " \ 968 " <content name='audio'> " \ 969 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \ 970 " media='audio' ssrc='4294967295'> " \ 971 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \ 972 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \ 973 " </description> " \ 974 " <transport xmlns='http://www.google.com/transport/p2p'/> " \ 975 " </content> " \ 976 " <content name='video'> " \ 977 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \ 978 " media='video' ssrc='87654321'> " \ 979 " </description> " \ 980 " <transport xmlns='http://www.google.com/transport/p2p'/> " \ 981 " </content> " \ 982 " <content name='data'> " \ 983 " <description xmlns='google:jingle:sctp'> " \ 984 " <stream sid='1'/> " \ 985 " </description> " \ 986 " <transport xmlns='http://www.google.com/transport/p2p'/> " \ 987 " </content> " \ 988 " </jingle> " \ 989 "</iq> "); 990 991std::string JingleView(const std::string& ssrc, 992 const std::string& width, 993 const std::string& height, 994 const std::string& framerate) { 995 // We have some slightly weird whitespace formatting to make the 996 // actual XML generated match the expected XML here. 997 return \ 998 "<cli:iq" 999 " to='me@mydomain.com'" 1000 " type='set'" 1001 " xmlns:cli='jabber:client'>" 1002 "<jingle" 1003 " xmlns='urn:xmpp:jingle:1'" 1004 " action='session-info'" 1005 " sid=''>" 1006 "<view xmlns='google:jingle'" 1007 " name='video'" 1008 " type='static'" 1009 " ssrc='" + ssrc + "'>" 1010 "<params" 1011 " width='" + width + "'" 1012 " height='" + height + "'" 1013 " framerate='" + framerate + "'" 1014 " preference='0'/>" 1015 "</view>" 1016 "</jingle>" 1017 "</cli:iq>"; 1018} 1019 1020std::string JingleStreamAdd(const std::string& content_name, 1021 const std::string& nick, 1022 const std::string& name, 1023 const std::string& ssrc) { 1024 return \ 1025 "<iq" 1026 " xmlns='jabber:client'" 1027 " from='me@mydomain.com'" 1028 " to='user@domain.com/resource'" 1029 " type='set'" 1030 " id='150'>" 1031 " <jingle" 1032 " xmlns='urn:xmpp:jingle:1'" 1033 " action='description-info'>" 1034 " <content" 1035 " xmlns='urn:xmpp:jingle:1'" 1036 " name='" + content_name + "'>" 1037 " <description" 1038 " xmlns='urn:xmpp:jingle:apps:rtp:1'" 1039 " media='" + content_name + "'>" 1040 " <streams" 1041 " xmlns='google:jingle'>" 1042 " <stream" 1043 " nick='" + nick + "'" 1044 " name='" + name + "'>" 1045 " <ssrc>" + ssrc + "</ssrc>" 1046 " </stream>" 1047 " </streams>" 1048 " </description>" 1049 " </content>" 1050 " </jingle>" 1051 "</iq>"; 1052} 1053 1054std::string JingleOutboundStreamRemove(const std::string& sid, 1055 const std::string& content_name, 1056 const std::string& name) { 1057 return \ 1058 "<cli:iq" 1059 " to='me@mydomain.com'" 1060 " type='set'" 1061 " xmlns:cli='jabber:client'>" 1062 "<jingle" 1063 " xmlns='urn:xmpp:jingle:1'" 1064 " action='description-info'" 1065 " sid='" + sid + "'>" 1066 "<content" 1067 " name='" + content_name + "'" 1068 " creator='initiator'>" 1069 "<description" 1070 " xmlns='urn:xmpp:jingle:apps:rtp:1'" 1071 " media='" + content_name + "'>" 1072 "<streams" 1073 " xmlns='google:jingle'>" 1074 "<stream" 1075 " name='" + name + "'>" 1076 "</stream>" 1077 "</streams>" 1078 "</description>" 1079 "</content>" 1080 "</jingle>" 1081 "</cli:iq>"; 1082} 1083 1084std::string JingleOutboundStreamAdd(const std::string& sid, 1085 const std::string& content_name, 1086 const std::string& name, 1087 const std::string& ssrc) { 1088 return \ 1089 "<cli:iq" 1090 " to='me@mydomain.com'" 1091 " type='set'" 1092 " xmlns:cli='jabber:client'>" 1093 "<jingle" 1094 " xmlns='urn:xmpp:jingle:1'" 1095 " action='description-info'" 1096 " sid='" + sid + "'>" 1097 "<content" 1098 " name='" + content_name + "'" 1099 " creator='initiator'>" 1100 "<description" 1101 " xmlns='urn:xmpp:jingle:apps:rtp:1'" 1102 " media='" + content_name + "'>" 1103 "<streams" 1104 " xmlns='google:jingle'>" 1105 "<stream" 1106 " name='" + name + "'>" 1107 "<ssrc>" + ssrc + "</ssrc>" 1108 "</stream>" 1109 "</streams>" 1110 "</description>" 1111 "</content>" 1112 "</jingle>" 1113 "</cli:iq>"; 1114} 1115 1116std::string JingleStreamAddWithoutSsrc(const std::string& content_name, 1117 const std::string& nick, 1118 const std::string& name) { 1119 return \ 1120 "<iq" 1121 " xmlns='jabber:client'" 1122 " from='me@mydomain.com'" 1123 " to='user@domain.com/resource'" 1124 " type='set'" 1125 " id='150'>" 1126 " <jingle" 1127 " xmlns='urn:xmpp:jingle:1'" 1128 " action='description-info'>" 1129 " <content" 1130 " xmlns='urn:xmpp:jingle:1'" 1131 " name='" + content_name + "'>" 1132 " <description" 1133 " xmlns='urn:xmpp:jingle:apps:rtp:1'" 1134 " media='" + content_name + "'>" 1135 " <streams" 1136 " xmlns='google:jingle'>" 1137 " <stream" 1138 " nick='" + nick + "'" 1139 " name='" + name + "'>" 1140 " </stream>" 1141 " </streams>" 1142 " </description>" 1143 " </content>" 1144 " </jingle>" 1145 "</iq>"; 1146} 1147 1148std::string JingleStreamRemove(const std::string& content_name, 1149 const std::string& nick, 1150 const std::string& name) { 1151 return \ 1152 "<iq" 1153 " xmlns='jabber:client'" 1154 " from='me@mydomain.com'" 1155 " to='user@domain.com/resource'" 1156 " type='set'" 1157 " id='150'>" 1158 " <jingle" 1159 " xmlns='urn:xmpp:jingle:1'" 1160 " action='description-info'>" 1161 " <content" 1162 " xmlns='urn:xmpp:jingle:1'" 1163 " name='" + content_name + "'>" 1164 " <description" 1165 " xmlns='urn:xmpp:jingle:apps:rtp:1'" 1166 " media='" + content_name + "'>" 1167 " <streams" 1168 " xmlns='google:jingle'>" 1169 " <stream" 1170 " nick='" + nick + "'" 1171 " name='" + name + "'/>" 1172 " </streams>" 1173 " </description>" 1174 " </content>" 1175 " </jingle>" 1176 "</iq>"; 1177} 1178 1179// Convenience function to get CallOptions that have audio enabled, 1180// but not video or data. 1181static cricket::CallOptions AudioCallOptions() { 1182 cricket::CallOptions options; 1183 options.has_audio = true; 1184 options.has_video = false; 1185 options.data_channel_type = cricket::DCT_NONE; 1186 return options; 1187} 1188 1189// Convenience function to get CallOptions that have audio and video 1190// enabled, but not data. 1191static cricket::CallOptions VideoCallOptions() { 1192 cricket::CallOptions options; 1193 options.has_audio = true; 1194 options.has_video = true; 1195 options.data_channel_type = cricket::DCT_NONE; 1196 return options; 1197} 1198 1199static buzz::XmlElement* CopyElement(const buzz::XmlElement* elem) { 1200 return new buzz::XmlElement(*elem); 1201} 1202 1203static std::string AddEncryption(std::string stanza, std::string encryption) { 1204 std::string::size_type pos = stanza.find("</description>"); 1205 while (pos != std::string::npos) { 1206 stanza = stanza.insert(pos, encryption); 1207 pos = stanza.find("</description>", pos + encryption.length() + 1); 1208 } 1209 return stanza; 1210} 1211 1212static int IntFromJingleCodecParameter(const buzz::XmlElement* parameter, 1213 const std::string& expected_name) { 1214 if (parameter) { 1215 const std::string& actual_name = 1216 parameter->Attr(cricket::QN_PAYLOADTYPE_PARAMETER_NAME); 1217 1218 EXPECT_EQ(expected_name, actual_name) 1219 << "wrong parameter name. Expected '" 1220 << expected_name << "'. Actually '" 1221 << actual_name << "'."; 1222 1223 return atoi(parameter->Attr( 1224 cricket::QN_PAYLOADTYPE_PARAMETER_VALUE).c_str()); 1225 } 1226 return 0; 1227} 1228 1229template <class CodecClass, class DescriptionClass> 1230static void VerifyCodecFbParams(const FeedbackParams& expected, 1231 const DescriptionClass* desc) { 1232 if (!expected.params().empty()) { 1233 ASSERT_TRUE(desc != NULL); 1234 const std::vector<CodecClass> codecs = desc->codecs(); 1235 for (size_t i = 0; i < codecs.size(); ++i) { 1236 EXPECT_EQ(expected, codecs[i].feedback_params); 1237 } 1238 } 1239} 1240 1241// Parses and extracts payload and codec info from test XML. Since 1242// that XML will be in various contents (Gingle and Jingle), we need an 1243// abstract parser with one concrete implementation per XML content. 1244class MediaSessionTestParser { 1245 public: 1246 virtual buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) = 0; 1247 virtual buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) = 0; 1248 virtual buzz::XmlElement* NextContent(buzz::XmlElement* content) = 0; 1249 virtual buzz::XmlElement* PayloadTypeFromContent( 1250 buzz::XmlElement* content) = 0; 1251 virtual buzz::XmlElement* NextFromPayloadType( 1252 buzz::XmlElement* payload_type) = 0; 1253 virtual cricket::AudioCodec AudioCodecFromPayloadType( 1254 const buzz::XmlElement* payload_type) = 0; 1255 virtual cricket::VideoCodec VideoCodecFromPayloadType( 1256 const buzz::XmlElement* payload_type) = 0; 1257 virtual cricket::DataCodec DataCodecFromPayloadType( 1258 const buzz::XmlElement* payload_type) = 0; 1259 virtual buzz::XmlElement* EncryptionFromContent( 1260 buzz::XmlElement* content) = 0; 1261 virtual buzz::XmlElement* NextFromEncryption( 1262 buzz::XmlElement* encryption) = 0; 1263 virtual const buzz::XmlElement* BandwidthFromContent( 1264 buzz::XmlElement* content) = 0; 1265 virtual const buzz::XmlElement* RtcpMuxFromContent( 1266 buzz::XmlElement* content) = 0; 1267 virtual bool ActionIsTerminate(const buzz::XmlElement* action) = 0; 1268 virtual ~MediaSessionTestParser() {} 1269}; 1270 1271class JingleSessionTestParser : public MediaSessionTestParser { 1272 public: 1273 JingleSessionTestParser() {} 1274 1275 ~JingleSessionTestParser() { 1276 } 1277 1278 buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) { 1279 return stanza->FirstNamed(cricket::QN_JINGLE); 1280 } 1281 1282 buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) { 1283 // We need to be able to use multiple contents, but the action 1284 // gets deleted before we can call NextContent, so we need to 1285 // stash away a copy. 1286 action_.reset(CopyElement(action)); 1287 return action_->FirstNamed(cricket::QN_JINGLE_CONTENT); 1288 } 1289 1290 buzz::XmlElement* NextContent(buzz::XmlElement* content) { 1291 // For some reason, content->NextNamed(cricket::QN_JINGLE_CONTENT) 1292 // doesn't work. 1293 return action_->FirstNamed(cricket::QN_JINGLE_CONTENT) 1294 ->NextNamed(cricket::QN_JINGLE_CONTENT); 1295 } 1296 1297 buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) { 1298 buzz::XmlElement* content_desc = 1299 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT); 1300 if (!content_desc) 1301 return NULL; 1302 1303 return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE); 1304 } 1305 1306 buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) { 1307 return payload_type->NextNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE); 1308 } 1309 1310 void ParsePayloadTypeFeedbackParameters(const buzz::XmlElement* element, 1311 FeedbackParams* params) { 1312 const buzz::XmlElement* param = 1313 element->FirstNamed(cricket::QN_JINGLE_RTCP_FB); 1314 for (; param != NULL; 1315 param = param->NextNamed(cricket::QN_JINGLE_RTCP_FB)) { 1316 std::string type = param->Attr(cricket::QN_TYPE); 1317 std::string subtype = param->Attr(cricket::QN_SUBTYPE); 1318 if (!type.empty()) { 1319 params->Add(FeedbackParam(type, subtype)); 1320 } 1321 } 1322 } 1323 1324 cricket::AudioCodec AudioCodecFromPayloadType( 1325 const buzz::XmlElement* payload_type) { 1326 int id = 0; 1327 if (payload_type->HasAttr(cricket::QN_ID)) 1328 id = atoi(payload_type->Attr(cricket::QN_ID).c_str()); 1329 1330 std::string name; 1331 if (payload_type->HasAttr(cricket::QN_NAME)) 1332 name = payload_type->Attr(cricket::QN_NAME); 1333 1334 int clockrate = 0; 1335 if (payload_type->HasAttr(cricket::QN_CLOCKRATE)) 1336 clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str()); 1337 1338 int bitrate = IntFromJingleCodecParameter( 1339 payload_type->FirstNamed(cricket::QN_PARAMETER), "bitrate"); 1340 1341 int channels = 1; 1342 if (payload_type->HasAttr(cricket::QN_CHANNELS)) 1343 channels = atoi(payload_type->Attr( 1344 cricket::QN_CHANNELS).c_str()); 1345 1346 AudioCodec codec = AudioCodec(id, name, clockrate, bitrate, channels, 0); 1347 ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params); 1348 return codec; 1349 } 1350 1351 cricket::VideoCodec VideoCodecFromPayloadType( 1352 const buzz::XmlElement* payload_type) { 1353 int id = 0; 1354 if (payload_type->HasAttr(cricket::QN_ID)) 1355 id = atoi(payload_type->Attr(cricket::QN_ID).c_str()); 1356 1357 std::string name; 1358 if (payload_type->HasAttr(cricket::QN_NAME)) 1359 name = payload_type->Attr(cricket::QN_NAME); 1360 1361 int width = 0; 1362 int height = 0; 1363 int framerate = 0; 1364 const buzz::XmlElement* param = 1365 payload_type->FirstNamed(cricket::QN_PARAMETER); 1366 if (param) { 1367 width = IntFromJingleCodecParameter(param, "width"); 1368 param = param->NextNamed(cricket::QN_PARAMETER); 1369 if (param) { 1370 height = IntFromJingleCodecParameter(param, "height"); 1371 param = param->NextNamed(cricket::QN_PARAMETER); 1372 if (param) { 1373 framerate = IntFromJingleCodecParameter(param, "framerate"); 1374 } 1375 } 1376 } 1377 VideoCodec codec = VideoCodec(id, name, width, height, framerate, 0); 1378 ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params); 1379 return codec; 1380 } 1381 1382 cricket::DataCodec DataCodecFromPayloadType( 1383 const buzz::XmlElement* payload_type) { 1384 int id = 0; 1385 if (payload_type->HasAttr(cricket::QN_ID)) 1386 id = atoi(payload_type->Attr(cricket::QN_ID).c_str()); 1387 1388 std::string name; 1389 if (payload_type->HasAttr(cricket::QN_NAME)) 1390 name = payload_type->Attr(cricket::QN_NAME); 1391 1392 DataCodec codec = DataCodec(id, name, 0); 1393 ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params); 1394 return codec; 1395 } 1396 1397 bool ActionIsTerminate(const buzz::XmlElement* action) { 1398 return (action->HasAttr(cricket::QN_ACTION) && 1399 action->Attr(cricket::QN_ACTION) == "session-terminate"); 1400 } 1401 1402 buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) { 1403 buzz::XmlElement* content_desc = 1404 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT); 1405 if (!content_desc) 1406 return NULL; 1407 1408 return content_desc->FirstNamed(cricket::QN_ENCRYPTION); 1409 } 1410 1411 buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) { 1412 return encryption->NextNamed(cricket::QN_ENCRYPTION); 1413 } 1414 1415 const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) { 1416 buzz::XmlElement* content_desc = 1417 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT); 1418 if (!content_desc) 1419 return NULL; 1420 1421 return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_BANDWIDTH); 1422 } 1423 1424 const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) { 1425 return content->FirstNamed(cricket::QN_JINGLE_RTCP_MUX); 1426 } 1427 1428 private: 1429 talk_base::scoped_ptr<buzz::XmlElement> action_; 1430}; 1431 1432class GingleSessionTestParser : public MediaSessionTestParser { 1433 public: 1434 GingleSessionTestParser() : found_content_count_(0) {} 1435 1436 buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) { 1437 return stanza->FirstNamed(cricket::QN_GINGLE_SESSION); 1438 } 1439 1440 buzz::XmlElement* ContentFromAction(buzz::XmlElement* session) { 1441 buzz::XmlElement* content = 1442 session->FirstNamed(cricket::QN_GINGLE_AUDIO_CONTENT); 1443 if (content == NULL) 1444 content = session->FirstNamed(cricket::QN_GINGLE_VIDEO_CONTENT); 1445 return content; 1446 } 1447 1448 // Assumes contents are in order of audio, and then video. 1449 buzz::XmlElement* NextContent(buzz::XmlElement* content) { 1450 found_content_count_++; 1451 return content; 1452 } 1453 1454 buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) { 1455 if (found_content_count_ > 0) { 1456 return content->FirstNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE); 1457 } else { 1458 return content->FirstNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE); 1459 } 1460 } 1461 1462 buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) { 1463 if (found_content_count_ > 0) { 1464 return payload_type->NextNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE); 1465 } else { 1466 return payload_type->NextNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE); 1467 } 1468 } 1469 1470 cricket::AudioCodec AudioCodecFromPayloadType( 1471 const buzz::XmlElement* payload_type) { 1472 int id = 0; 1473 if (payload_type->HasAttr(cricket::QN_ID)) 1474 id = atoi(payload_type->Attr(cricket::QN_ID).c_str()); 1475 1476 std::string name; 1477 if (payload_type->HasAttr(cricket::QN_NAME)) 1478 name = payload_type->Attr(cricket::QN_NAME); 1479 1480 int clockrate = 0; 1481 if (payload_type->HasAttr(cricket::QN_CLOCKRATE)) 1482 clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str()); 1483 1484 int bitrate = 0; 1485 if (payload_type->HasAttr(cricket::QN_BITRATE)) 1486 bitrate = atoi(payload_type->Attr(cricket::QN_BITRATE).c_str()); 1487 1488 int channels = 1; 1489 if (payload_type->HasAttr(cricket::QN_CHANNELS)) 1490 channels = atoi(payload_type->Attr(cricket::QN_CHANNELS).c_str()); 1491 1492 return cricket::AudioCodec(id, name, clockrate, bitrate, channels, 0); 1493 } 1494 1495 cricket::VideoCodec VideoCodecFromPayloadType( 1496 const buzz::XmlElement* payload_type) { 1497 int id = 0; 1498 if (payload_type->HasAttr(cricket::QN_ID)) 1499 id = atoi(payload_type->Attr(cricket::QN_ID).c_str()); 1500 1501 std::string name; 1502 if (payload_type->HasAttr(cricket::QN_NAME)) 1503 name = payload_type->Attr(cricket::QN_NAME); 1504 1505 int width = 0; 1506 if (payload_type->HasAttr(cricket::QN_WIDTH)) 1507 width = atoi(payload_type->Attr(cricket::QN_WIDTH).c_str()); 1508 1509 int height = 0; 1510 if (payload_type->HasAttr(cricket::QN_HEIGHT)) 1511 height = atoi(payload_type->Attr(cricket::QN_HEIGHT).c_str()); 1512 1513 int framerate = 1; 1514 if (payload_type->HasAttr(cricket::QN_FRAMERATE)) 1515 framerate = atoi(payload_type->Attr(cricket::QN_FRAMERATE).c_str()); 1516 1517 return cricket::VideoCodec(id, name, width, height, framerate, 0); 1518 } 1519 1520 cricket::DataCodec DataCodecFromPayloadType( 1521 const buzz::XmlElement* payload_type) { 1522 // Gingle can't do data codecs. 1523 return cricket::DataCodec(0, "", 0); 1524 } 1525 1526 buzz::XmlElement* EncryptionFromContent( 1527 buzz::XmlElement* content) { 1528 return content->FirstNamed(cricket::QN_ENCRYPTION); 1529 } 1530 1531 buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) { 1532 return encryption->NextNamed(cricket::QN_ENCRYPTION); 1533 } 1534 1535 const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) { 1536 return content->FirstNamed(cricket::QN_GINGLE_VIDEO_BANDWIDTH); 1537 } 1538 1539 const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) { 1540 return NULL; 1541 } 1542 1543 bool ActionIsTerminate(const buzz::XmlElement* session) { 1544 return (session->HasAttr(buzz::QN_TYPE) && 1545 session->Attr(buzz::QN_TYPE) == "terminate"); 1546 } 1547 1548 int found_content_count_; 1549}; 1550 1551class MediaSessionClientTest : public sigslot::has_slots<> { 1552 public: 1553 explicit MediaSessionClientTest(MediaSessionTestParser* parser, 1554 cricket::SignalingProtocol initial_protocol) { 1555 nm_ = new talk_base::BasicNetworkManager(); 1556 pa_ = new cricket::BasicPortAllocator(nm_); 1557 sm_ = new cricket::SessionManager(pa_, NULL); 1558 fme_ = new cricket::FakeMediaEngine(); 1559 fdme_ = new cricket::FakeDataEngine(); 1560 1561 FeedbackParams params_nack_fir; 1562 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm, 1563 cricket::kRtcpFbCcmParamFir)); 1564 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack)); 1565 FeedbackParams params_nack; 1566 params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack)); 1567 1568 std::vector<cricket::AudioCodec> 1569 audio_codecs(kAudioCodecs, kAudioCodecs + ARRAY_SIZE(kAudioCodecs)); 1570 SetCodecFeedbackParams(&audio_codecs, params_nack); 1571 fme_->SetAudioCodecs(audio_codecs); 1572 std::vector<cricket::VideoCodec> 1573 video_codecs(kVideoCodecs, kVideoCodecs + ARRAY_SIZE(kVideoCodecs)); 1574 SetCodecFeedbackParams(&video_codecs, params_nack_fir); 1575 fme_->SetVideoCodecs(video_codecs); 1576 std::vector<cricket::DataCodec> 1577 data_codecs(kDataCodecs, kDataCodecs + ARRAY_SIZE(kDataCodecs)); 1578 SetCodecFeedbackParams(&data_codecs, params_nack); 1579 fdme_->SetDataCodecs(data_codecs); 1580 1581 client_ = new cricket::MediaSessionClient( 1582 buzz::Jid("user@domain.com/resource"), sm_, 1583 fme_, fdme_, new cricket::FakeDeviceManager()); 1584 client_->session_manager()->SignalOutgoingMessage.connect( 1585 this, &MediaSessionClientTest::OnSendStanza); 1586 client_->session_manager()->SignalSessionCreate.connect( 1587 this, &MediaSessionClientTest::OnSessionCreate); 1588 client_->SignalCallCreate.connect( 1589 this, &MediaSessionClientTest::OnCallCreate); 1590 client_->SignalCallDestroy.connect( 1591 this, &MediaSessionClientTest::OnCallDestroy); 1592 1593 call_ = NULL; 1594 parser_ = parser; 1595 initial_protocol_ = initial_protocol; 1596 expect_incoming_crypto_ = false; 1597 expect_outgoing_crypto_ = false; 1598 expected_video_bandwidth_ = cricket::kAutoBandwidth; 1599 expected_video_rtcp_mux_ = false; 1600 } 1601 1602 ~MediaSessionClientTest() { 1603 delete client_; 1604 delete sm_; 1605 delete pa_; 1606 delete nm_; 1607 delete parser_; 1608 ClearStanzas(); 1609 } 1610 1611 buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) { 1612 return parser_->ActionFromStanza(stanza); 1613 } 1614 1615 buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) { 1616 return parser_->ContentFromAction(action); 1617 } 1618 1619 buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* payload) { 1620 return parser_->PayloadTypeFromContent(payload); 1621 } 1622 1623 buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) { 1624 return parser_->NextFromPayloadType(payload_type); 1625 } 1626 1627 buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) { 1628 return parser_->EncryptionFromContent(content); 1629 } 1630 1631 buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) { 1632 return parser_->NextFromEncryption(encryption); 1633 } 1634 1635 cricket::AudioCodec AudioCodecFromPayloadType( 1636 const buzz::XmlElement* payload_type) { 1637 return parser_->AudioCodecFromPayloadType(payload_type); 1638 } 1639 1640 cricket::VideoCodec VideoCodecFromPayloadType( 1641 const buzz::XmlElement* payload_type) { 1642 return parser_->VideoCodecFromPayloadType(payload_type); 1643 } 1644 1645 cricket::DataCodec DataCodecFromPayloadType( 1646 const buzz::XmlElement* payload_type) { 1647 return parser_->DataCodecFromPayloadType(payload_type); 1648 } 1649 1650 const AudioContentDescription* GetFirstAudioContentDescription( 1651 const cricket::SessionDescription* sdesc) { 1652 const cricket::ContentInfo* content = 1653 cricket::GetFirstAudioContent(sdesc); 1654 if (content == NULL) 1655 return NULL; 1656 return static_cast<const AudioContentDescription*>(content->description); 1657 } 1658 1659 const cricket::VideoContentDescription* GetFirstVideoContentDescription( 1660 const cricket::SessionDescription* sdesc) { 1661 const cricket::ContentInfo* content = 1662 cricket::GetFirstVideoContent(sdesc); 1663 if (content == NULL) 1664 return NULL; 1665 return static_cast<const cricket::VideoContentDescription*>( 1666 content->description); 1667 } 1668 1669 void CheckCryptoFromGoodIncomingInitiate(const cricket::Session* session) { 1670 ASSERT_TRUE(session != NULL); 1671 const AudioContentDescription* content = 1672 GetFirstAudioContentDescription(session->remote_description()); 1673 ASSERT_TRUE(content != NULL); 1674 ASSERT_EQ(2U, content->cryptos().size()); 1675 ASSERT_EQ(145, content->cryptos()[0].tag); 1676 ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite); 1677 ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9", 1678 content->cryptos()[0].key_params); 1679 ASSERT_EQ(51, content->cryptos()[1].tag); 1680 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", content->cryptos()[1].cipher_suite); 1681 ASSERT_EQ("inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy", 1682 content->cryptos()[1].key_params); 1683 } 1684 1685 void CheckCryptoForGoodOutgoingAccept(const cricket::Session* session) { 1686 const AudioContentDescription* content = 1687 GetFirstAudioContentDescription(session->local_description()); 1688 ASSERT_EQ(1U, content->cryptos().size()); 1689 ASSERT_EQ(145, content->cryptos()[0].tag); 1690 ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite); 1691 ASSERT_EQ(47U, content->cryptos()[0].key_params.size()); 1692 } 1693 1694 void CheckBadCryptoFromIncomingInitiate(const cricket::Session* session) { 1695 const AudioContentDescription* content = 1696 GetFirstAudioContentDescription(session->remote_description()); 1697 ASSERT_EQ(1U, content->cryptos().size()); 1698 ASSERT_EQ(145, content->cryptos()[0].tag); 1699 ASSERT_EQ("NOT_SUPPORTED", content->cryptos()[0].cipher_suite); 1700 ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9", 1701 content->cryptos()[0].key_params); 1702 } 1703 1704 void CheckNoCryptoForOutgoingAccept(const cricket::Session* session) { 1705 const AudioContentDescription* content = 1706 GetFirstAudioContentDescription(session->local_description()); 1707 ASSERT_TRUE(content->cryptos().empty()); 1708 } 1709 1710 void CheckRtcpFb(const cricket::SessionDescription* sdesc) { 1711 VerifyCodecFbParams<AudioCodec>(expected_audio_fb_params_, 1712 GetFirstAudioContentDescription(sdesc)); 1713 1714 VerifyCodecFbParams<VideoCodec>(expected_video_fb_params_, 1715 GetFirstVideoContentDescription(sdesc)); 1716 1717 VerifyCodecFbParams<DataCodec>(expected_data_fb_params_, 1718 GetFirstDataContentDescription(sdesc)); 1719 } 1720 1721 void CheckVideoBandwidth(int expected_bandwidth, 1722 const cricket::SessionDescription* sdesc) { 1723 const cricket::VideoContentDescription* video = 1724 GetFirstVideoContentDescription(sdesc); 1725 if (video != NULL) { 1726 ASSERT_EQ(expected_bandwidth, video->bandwidth()); 1727 } 1728 } 1729 1730 void CheckVideoRtcpMux(bool expected_video_rtcp_mux, 1731 const cricket::SessionDescription* sdesc) { 1732 const cricket::VideoContentDescription* video = 1733 GetFirstVideoContentDescription(sdesc); 1734 if (video != NULL) { 1735 ASSERT_EQ(expected_video_rtcp_mux, video->rtcp_mux()); 1736 } 1737 } 1738 1739 virtual void CheckRtpDataContent(buzz::XmlElement* content) { 1740 if (initial_protocol_) { 1741 // Gingle can not write out data content. 1742 return; 1743 } 1744 1745 buzz::XmlElement* e = PayloadTypeFromContent(content); 1746 ASSERT_TRUE(e != NULL); 1747 cricket::DataCodec codec = DataCodecFromPayloadType(e); 1748 EXPECT_EQ(127, codec.id); 1749 EXPECT_EQ("google-data", codec.name); 1750 EXPECT_EQ(expected_data_fb_params_, codec.feedback_params); 1751 1752 CheckDataRtcpMux(true, call_->sessions()[0]->local_description()); 1753 CheckDataRtcpMux(true, call_->sessions()[0]->remote_description()); 1754 if (expect_outgoing_crypto_) { 1755 content = parser_->NextContent(content); 1756 buzz::XmlElement* encryption = EncryptionFromContent(content); 1757 ASSERT_TRUE(encryption != NULL); 1758 // TODO(pthatcher): Check encryption parameters? 1759 } 1760 } 1761 1762 virtual void CheckSctpDataContent(buzz::XmlElement* content) { 1763 if (initial_protocol_) { 1764 // Gingle can not write out data content. 1765 return; 1766 } 1767 1768 buzz::XmlElement* payload_type = PayloadTypeFromContent(content); 1769 ASSERT_TRUE(payload_type == NULL); 1770 buzz::XmlElement* encryption = EncryptionFromContent(content); 1771 ASSERT_TRUE(encryption == NULL); 1772 // TODO(pthatcher): Check for <streams>. 1773 } 1774 1775 void CheckDataRtcpMux(bool expected_data_rtcp_mux, 1776 const cricket::SessionDescription* sdesc) { 1777 const cricket::DataContentDescription* data = 1778 GetFirstDataContentDescription(sdesc); 1779 if (data != NULL) { 1780 ASSERT_EQ(expected_data_rtcp_mux, data->rtcp_mux()); 1781 } 1782 } 1783 1784 void CheckAudioSsrcForIncomingAccept(const cricket::Session* session) { 1785 const AudioContentDescription* audio = 1786 GetFirstAudioContentDescription(session->remote_description()); 1787 ASSERT_TRUE(audio != NULL); 1788 ASSERT_EQ(kAudioSsrc, audio->first_ssrc()); 1789 } 1790 1791 void CheckVideoSsrcForIncomingAccept(const cricket::Session* session) { 1792 const cricket::VideoContentDescription* video = 1793 GetFirstVideoContentDescription(session->remote_description()); 1794 ASSERT_TRUE(video != NULL); 1795 ASSERT_EQ(kVideoSsrc, video->first_ssrc()); 1796 } 1797 1798 void CheckDataSsrcForIncomingAccept(const cricket::Session* session) { 1799 const cricket::DataContentDescription* data = 1800 GetFirstDataContentDescription(session->remote_description()); 1801 ASSERT_TRUE(data != NULL); 1802 ASSERT_EQ(kDataSsrc, data->first_ssrc()); 1803 } 1804 1805 void TestGoodIncomingInitiate(const std::string& initiate_string, 1806 const cricket::CallOptions& options, 1807 buzz::XmlElement** element) { 1808 *element = NULL; 1809 1810 talk_base::scoped_ptr<buzz::XmlElement> el( 1811 buzz::XmlElement::ForStr(initiate_string)); 1812 client_->session_manager()->OnIncomingMessage(el.get()); 1813 ASSERT_TRUE(call_ != NULL); 1814 ASSERT_TRUE(call_->sessions()[0] != NULL); 1815 ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE, 1816 call_->sessions()[0]->state()); 1817 ASSERT_EQ(1U, stanzas_.size()); 1818 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name()); 1819 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE)); 1820 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE)); 1821 ClearStanzas(); 1822 CheckVideoBandwidth(expected_video_bandwidth_, 1823 call_->sessions()[0]->remote_description()); 1824 CheckVideoRtcpMux(expected_video_rtcp_mux_, 1825 call_->sessions()[0]->remote_description()); 1826 CheckRtcpFb(call_->sessions()[0]->remote_description()); 1827 if (expect_incoming_crypto_) { 1828 CheckCryptoFromGoodIncomingInitiate(call_->sessions()[0]); 1829 } 1830 1831 // TODO(pthatcher): Add tests for sending <bandwidth> in accept. 1832 call_->AcceptSession(call_->sessions()[0], options); 1833 ASSERT_EQ(cricket::Session::STATE_SENTACCEPT, 1834 call_->sessions()[0]->state()); 1835 ASSERT_EQ(1U, stanzas_.size()); 1836 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name()); 1837 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE)); 1838 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE)); 1839 1840 buzz::XmlElement* e = ActionFromStanza(stanzas_[0]); 1841 ASSERT_TRUE(e != NULL); 1842 ASSERT_TRUE(ContentFromAction(e) != NULL); 1843 *element = CopyElement(ContentFromAction(e)); 1844 ASSERT_TRUE(*element != NULL); 1845 ClearStanzas(); 1846 if (expect_outgoing_crypto_) { 1847 CheckCryptoForGoodOutgoingAccept(call_->sessions()[0]); 1848 } 1849 1850 if (options.data_channel_type == cricket::DCT_RTP) { 1851 CheckDataRtcpMux(true, call_->sessions()[0]->local_description()); 1852 CheckDataRtcpMux(true, call_->sessions()[0]->remote_description()); 1853 // TODO(pthatcher): Check rtcpmux and crypto? 1854 } 1855 1856 call_->Terminate(); 1857 ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE, 1858 call_->sessions()[0]->state()); 1859 ASSERT_EQ(1U, stanzas_.size()); 1860 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name()); 1861 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE)); 1862 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE)); 1863 e = ActionFromStanza(stanzas_[0]); 1864 ASSERT_TRUE(e != NULL); 1865 ASSERT_TRUE(parser_->ActionIsTerminate(e)); 1866 ClearStanzas(); 1867 } 1868 1869 void TestRejectOffer(const std::string &initiate_string, 1870 const cricket::CallOptions& options, 1871 buzz::XmlElement** element) { 1872 *element = NULL; 1873 1874 talk_base::scoped_ptr<buzz::XmlElement> el( 1875 buzz::XmlElement::ForStr(initiate_string)); 1876 client_->session_manager()->OnIncomingMessage(el.get()); 1877 ASSERT_TRUE(call_ != NULL); 1878 ASSERT_TRUE(call_->sessions()[0] != NULL); 1879 ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE, 1880 call_->sessions()[0]->state()); 1881 ASSERT_EQ(1U, stanzas_.size()); 1882 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name()); 1883 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE)); 1884 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE)); 1885 ClearStanzas(); 1886 1887 call_->AcceptSession(call_->sessions()[0], options); 1888 ASSERT_EQ(cricket::Session::STATE_SENTACCEPT, 1889 call_->sessions()[0]->state()); 1890 ASSERT_EQ(1U, stanzas_.size()); 1891 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name()); 1892 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE)); 1893 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE)); 1894 1895 buzz::XmlElement* e = ActionFromStanza(stanzas_[0]); 1896 ASSERT_TRUE(e != NULL); 1897 ASSERT_TRUE(ContentFromAction(e) != NULL); 1898 *element = CopyElement(ContentFromAction(e)); 1899 ASSERT_TRUE(*element != NULL); 1900 ClearStanzas(); 1901 1902 buzz::XmlElement* content = *element; 1903 // The NextContent method actually returns the second content. So we 1904 // can't handle the case when audio, video and data are all enabled. But 1905 // since we are testing rejection, it won't be the case. 1906 if (options.has_audio) { 1907 ASSERT_TRUE(content != NULL); 1908 ASSERT_EQ("test audio", content->Attr(buzz::QName("", "name"))); 1909 content = parser_->NextContent(content); 1910 } 1911 1912 if (options.has_video) { 1913 ASSERT_TRUE(content != NULL); 1914 ASSERT_EQ("test video", content->Attr(buzz::QName("", "name"))); 1915 content = parser_->NextContent(content); 1916 } 1917 1918 if (options.has_data()) { 1919 ASSERT_TRUE(content != NULL); 1920 ASSERT_EQ("test data", content->Attr(buzz::QName("", "name"))); 1921 content = parser_->NextContent(content); 1922 } 1923 1924 call_->Terminate(); 1925 ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE, 1926 call_->sessions()[0]->state()); 1927 ASSERT_EQ(1U, stanzas_.size()); 1928 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name()); 1929 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE)); 1930 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE)); 1931 e = ActionFromStanza(stanzas_[0]); 1932 ASSERT_TRUE(e != NULL); 1933 ASSERT_TRUE(parser_->ActionIsTerminate(e)); 1934 ClearStanzas(); 1935 } 1936 1937 void TestBadIncomingInitiate(const std::string& initiate_string) { 1938 talk_base::scoped_ptr<buzz::XmlElement> el( 1939 buzz::XmlElement::ForStr(initiate_string)); 1940 client_->session_manager()->OnIncomingMessage(el.get()); 1941 ASSERT_TRUE(call_ != NULL); 1942 ASSERT_TRUE(call_->sessions()[0] != NULL); 1943 ASSERT_EQ(cricket::Session::STATE_SENTREJECT, 1944 call_->sessions()[0]->state()); 1945 ASSERT_EQ(2U, stanzas_.size()); 1946 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name()); 1947 ASSERT_TRUE(stanzas_[1]->HasAttr(buzz::QN_TYPE)); 1948 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[1]->Attr(buzz::QN_TYPE)); 1949 ClearStanzas(); 1950 } 1951 1952 void VerifyAudioCodec(const AudioCodec& codec, int id, 1953 const std::string& name, int clockrate, 1954 int bitrate, int channels) { 1955 ASSERT_EQ(id, codec.id); 1956 ASSERT_EQ(name, codec.name); 1957 ASSERT_EQ(clockrate, codec.clockrate); 1958 ASSERT_EQ(bitrate, codec.bitrate); 1959 ASSERT_EQ(channels, codec.channels); 1960 ASSERT_EQ(expected_audio_fb_params_, codec.feedback_params); 1961 } 1962 1963 void TestGoodOutgoingInitiate(const cricket::CallOptions& options) { 1964 if (initial_protocol_ == cricket::PROTOCOL_JINGLE) { 1965 // rtcp fb is only implemented for jingle. 1966 ExpectRtcpFb(); 1967 } 1968 1969 client_->CreateCall(); 1970 ASSERT_TRUE(call_ != NULL); 1971 call_->InitiateSession(buzz::Jid("me@mydomain.com"), 1972 buzz::Jid("me@mydomain.com"), options); 1973 ASSERT_TRUE(call_->sessions()[0] != NULL); 1974 ASSERT_EQ(cricket::Session::STATE_SENTINITIATE, 1975 call_->sessions()[0]->state()); 1976 ASSERT_EQ(1U, stanzas_.size()); 1977 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name()); 1978 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE)); 1979 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE)); 1980 buzz::XmlElement* action = ActionFromStanza(stanzas_[0]); 1981 ASSERT_TRUE(action != NULL); 1982 buzz::XmlElement* content = ContentFromAction(action); 1983 ASSERT_TRUE(content != NULL); 1984 1985 buzz::XmlElement* e = PayloadTypeFromContent(content); 1986 ASSERT_TRUE(e != NULL); 1987 cricket::AudioCodec codec = AudioCodecFromPayloadType(e); 1988 VerifyAudioCodec(codec, 103, "ISAC", 16000, 0, 1); 1989 1990 e = NextFromPayloadType(e); 1991 ASSERT_TRUE(e != NULL); 1992 codec = AudioCodecFromPayloadType(e); 1993 VerifyAudioCodec(codec, 104, "ISAC", 32000, 0, 1); 1994 1995 e = NextFromPayloadType(e); 1996 ASSERT_TRUE(e != NULL); 1997 codec = AudioCodecFromPayloadType(e); 1998 VerifyAudioCodec(codec, 119, "ISACLC", 16000, 40000, 1); 1999 2000 e = NextFromPayloadType(e); 2001 ASSERT_TRUE(e != NULL); 2002 codec = AudioCodecFromPayloadType(e); 2003 VerifyAudioCodec(codec, 99, "speex", 16000, 22000, 1); 2004 2005 e = NextFromPayloadType(e); 2006 ASSERT_TRUE(e != NULL); 2007 codec = AudioCodecFromPayloadType(e); 2008 VerifyAudioCodec(codec, 97, "IPCMWB", 16000, 80000, 1); 2009 2010 e = NextFromPayloadType(e); 2011 ASSERT_TRUE(e != NULL); 2012 codec = AudioCodecFromPayloadType(e); 2013 VerifyAudioCodec(codec, 9, "G722", 16000, 64000, 1); 2014 2015 e = NextFromPayloadType(e); 2016 ASSERT_TRUE(e != NULL); 2017 codec = AudioCodecFromPayloadType(e); 2018 VerifyAudioCodec(codec, 102, "iLBC", 8000, 13300, 1); 2019 2020 e = NextFromPayloadType(e); 2021 ASSERT_TRUE(e != NULL); 2022 codec = AudioCodecFromPayloadType(e); 2023 VerifyAudioCodec(codec, 98, "speex", 8000, 11000, 1); 2024 2025 e = NextFromPayloadType(e); 2026 ASSERT_TRUE(e != NULL); 2027 codec = AudioCodecFromPayloadType(e); 2028 VerifyAudioCodec(codec, 3, "GSM", 8000, 13000, 1); 2029 2030 e = NextFromPayloadType(e); 2031 ASSERT_TRUE(e != NULL); 2032 codec = AudioCodecFromPayloadType(e); 2033 VerifyAudioCodec(codec, 100, "EG711U", 8000, 64000, 1); 2034 2035 e = NextFromPayloadType(e); 2036 ASSERT_TRUE(e != NULL); 2037 codec = AudioCodecFromPayloadType(e); 2038 VerifyAudioCodec(codec, 101, "EG711A", 8000, 64000, 1); 2039 2040 e = NextFromPayloadType(e); 2041 ASSERT_TRUE(e != NULL); 2042 codec = AudioCodecFromPayloadType(e); 2043 VerifyAudioCodec(codec, 0, "PCMU", 8000, 64000, 1); 2044 2045 e = NextFromPayloadType(e); 2046 ASSERT_TRUE(e != NULL); 2047 codec = AudioCodecFromPayloadType(e); 2048 VerifyAudioCodec(codec, 8, "PCMA", 8000, 64000, 1); 2049 2050 e = NextFromPayloadType(e); 2051 ASSERT_TRUE(e != NULL); 2052 codec = AudioCodecFromPayloadType(e); 2053 VerifyAudioCodec(codec, 126, "CN", 32000, 0, 1); 2054 2055 e = NextFromPayloadType(e); 2056 ASSERT_TRUE(e != NULL); 2057 codec = AudioCodecFromPayloadType(e); 2058 VerifyAudioCodec(codec, 105, "CN", 16000, 0, 1); 2059 2060 e = NextFromPayloadType(e); 2061 ASSERT_TRUE(e != NULL); 2062 codec = AudioCodecFromPayloadType(e); 2063 VerifyAudioCodec(codec, 13, "CN", 8000, 0, 1); 2064 2065 e = NextFromPayloadType(e); 2066 ASSERT_TRUE(e != NULL); 2067 codec = AudioCodecFromPayloadType(e); 2068 VerifyAudioCodec(codec, 117, "red", 8000, 0, 1); 2069 2070 e = NextFromPayloadType(e); 2071 ASSERT_TRUE(e != NULL); 2072 codec = AudioCodecFromPayloadType(e); 2073 VerifyAudioCodec(codec, 106, "telephone-event", 8000, 0, 1); 2074 2075 e = NextFromPayloadType(e); 2076 ASSERT_TRUE(e == NULL); 2077 2078 if (expect_outgoing_crypto_) { 2079 buzz::XmlElement* encryption = EncryptionFromContent(content); 2080 ASSERT_TRUE(encryption != NULL); 2081 2082 if (client_->secure() == cricket::SEC_REQUIRED) { 2083 ASSERT_TRUE(cricket::GetXmlAttr( 2084 encryption, cricket::QN_ENCRYPTION_REQUIRED, false)); 2085 } 2086 2087 if (content->Name().Namespace() == cricket::NS_GINGLE_AUDIO) { 2088 e = encryption->FirstNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE); 2089 ASSERT_TRUE(e != NULL); 2090 ASSERT_TRUE( 2091 e->NextNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE) == NULL); 2092 ASSERT_TRUE( 2093 e->FirstNamed(cricket::QN_GINGLE_VIDEO_CRYPTO_USAGE) == NULL); 2094 } 2095 2096 e = encryption->FirstNamed(cricket::QN_CRYPTO); 2097 ASSERT_TRUE(e != NULL); 2098 ASSERT_EQ("0", e->Attr(cricket::QN_CRYPTO_TAG)); 2099 ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", e->Attr(cricket::QN_CRYPTO_SUITE)); 2100 std::string key_0 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS); 2101 ASSERT_EQ(47U, key_0.length()); 2102 ASSERT_EQ("inline:", key_0.substr(0, 7)); 2103 2104 e = e->NextNamed(cricket::QN_CRYPTO); 2105 ASSERT_TRUE(e != NULL); 2106 ASSERT_EQ("1", e->Attr(cricket::QN_CRYPTO_TAG)); 2107 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", e->Attr(cricket::QN_CRYPTO_SUITE)); 2108 std::string key_1 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS); 2109 ASSERT_EQ(47U, key_1.length()); 2110 ASSERT_EQ("inline:", key_1.substr(0, 7)); 2111 ASSERT_NE(key_0, key_1); 2112 2113 encryption = NextFromEncryption(encryption); 2114 ASSERT_TRUE(encryption == NULL); 2115 } 2116 2117 if (options.has_video) { 2118 CheckVideoBandwidth(options.video_bandwidth, 2119 call_->sessions()[0]->local_description()); 2120 CheckVideoRtcpMux(expected_video_rtcp_mux_, 2121 call_->sessions()[0]->remote_description()); 2122 content = parser_->NextContent(content); 2123 const buzz::XmlElement* bandwidth = 2124 parser_->BandwidthFromContent(content); 2125 if (options.video_bandwidth == cricket::kAutoBandwidth) { 2126 ASSERT_TRUE(bandwidth == NULL); 2127 } else { 2128 ASSERT_TRUE(bandwidth != NULL); 2129 ASSERT_EQ("AS", bandwidth->Attr(buzz::QName("", "type"))); 2130 ASSERT_EQ(talk_base::ToString(options.video_bandwidth / 1000), 2131 bandwidth->BodyText()); 2132 } 2133 2134 buzz::XmlElement* e = PayloadTypeFromContent(content); 2135 ASSERT_TRUE(e != NULL); 2136 VideoCodec codec = VideoCodecFromPayloadType(e); 2137 VideoCodec expected_codec = kVideoCodecs[0]; 2138 expected_codec.preference = codec.preference; 2139 expected_codec.feedback_params = expected_video_fb_params_; 2140 EXPECT_EQ(expected_codec, codec); 2141 } 2142 2143 if (options.data_channel_type == cricket::DCT_RTP) { 2144 content = parser_->NextContent(content); 2145 CheckRtpDataContent(content); 2146 } 2147 2148 if (options.data_channel_type == cricket::DCT_SCTP) { 2149 content = parser_->NextContent(content); 2150 CheckSctpDataContent(content); 2151 } 2152 2153 ClearStanzas(); 2154 } 2155 2156 void TestHasAllSupportedAudioCodecs(buzz::XmlElement* e) { 2157 ASSERT_TRUE(e != NULL); 2158 2159 e = PayloadTypeFromContent(e); 2160 ASSERT_TRUE(e != NULL); 2161 cricket::AudioCodec codec = AudioCodecFromPayloadType(e); 2162 ASSERT_EQ(103, codec.id); 2163 ASSERT_EQ("ISAC", codec.name); 2164 ASSERT_EQ(16000, codec.clockrate); 2165 ASSERT_EQ(1, codec.channels); 2166 2167 e = NextFromPayloadType(e); 2168 ASSERT_TRUE(e != NULL); 2169 codec = AudioCodecFromPayloadType(e); 2170 ASSERT_EQ(104, codec.id); 2171 ASSERT_EQ("ISAC", codec.name); 2172 ASSERT_EQ(32000, codec.clockrate); 2173 ASSERT_EQ(1, codec.channels); 2174 2175 e = NextFromPayloadType(e); 2176 ASSERT_TRUE(e != NULL); 2177 codec = AudioCodecFromPayloadType(e); 2178 ASSERT_EQ(119, codec.id); 2179 ASSERT_EQ("ISACLC", codec.name); 2180 ASSERT_EQ(16000, codec.clockrate); 2181 ASSERT_EQ(40000, codec.bitrate); 2182 ASSERT_EQ(1, codec.channels); 2183 2184 e = NextFromPayloadType(e); 2185 ASSERT_TRUE(e != NULL); 2186 codec = AudioCodecFromPayloadType(e); 2187 ASSERT_EQ(99, codec.id); 2188 ASSERT_EQ("speex", codec.name); 2189 ASSERT_EQ(16000, codec.clockrate); 2190 ASSERT_EQ(22000, codec.bitrate); 2191 ASSERT_EQ(1, codec.channels); 2192 2193 e = NextFromPayloadType(e); 2194 ASSERT_TRUE(e != NULL); 2195 codec = AudioCodecFromPayloadType(e); 2196 ASSERT_EQ(97, codec.id); 2197 ASSERT_EQ("IPCMWB", codec.name); 2198 ASSERT_EQ(16000, codec.clockrate); 2199 ASSERT_EQ(80000, codec.bitrate); 2200 ASSERT_EQ(1, codec.channels); 2201 2202 e = NextFromPayloadType(e); 2203 ASSERT_TRUE(e != NULL); 2204 codec = AudioCodecFromPayloadType(e); 2205 ASSERT_EQ(9, codec.id); 2206 ASSERT_EQ("G722", codec.name); 2207 ASSERT_EQ(16000, codec.clockrate); 2208 ASSERT_EQ(64000, codec.bitrate); 2209 ASSERT_EQ(1, codec.channels); 2210 2211 e = NextFromPayloadType(e); 2212 ASSERT_TRUE(e != NULL); 2213 codec = AudioCodecFromPayloadType(e); 2214 ASSERT_EQ(102, codec.id); 2215 ASSERT_EQ("iLBC", codec.name); 2216 ASSERT_EQ(8000, codec.clockrate); 2217 ASSERT_EQ(13300, codec.bitrate); 2218 ASSERT_EQ(1, codec.channels); 2219 2220 e = NextFromPayloadType(e); 2221 ASSERT_TRUE(e != NULL); 2222 codec = AudioCodecFromPayloadType(e); 2223 ASSERT_EQ(98, codec.id); 2224 ASSERT_EQ("speex", codec.name); 2225 ASSERT_EQ(8000, codec.clockrate); 2226 ASSERT_EQ(11000, codec.bitrate); 2227 ASSERT_EQ(1, codec.channels); 2228 2229 e = NextFromPayloadType(e); 2230 ASSERT_TRUE(e != NULL); 2231 codec = AudioCodecFromPayloadType(e); 2232 ASSERT_EQ(3, codec.id); 2233 ASSERT_EQ("GSM", codec.name); 2234 ASSERT_EQ(8000, codec.clockrate); 2235 ASSERT_EQ(13000, codec.bitrate); 2236 ASSERT_EQ(1, codec.channels); 2237 2238 e = NextFromPayloadType(e); 2239 ASSERT_TRUE(e != NULL); 2240 codec = AudioCodecFromPayloadType(e); 2241 ASSERT_EQ(100, codec.id); 2242 ASSERT_EQ("EG711U", codec.name); 2243 ASSERT_EQ(8000, codec.clockrate); 2244 ASSERT_EQ(64000, codec.bitrate); 2245 ASSERT_EQ(1, codec.channels); 2246 2247 e = NextFromPayloadType(e); 2248 ASSERT_TRUE(e != NULL); 2249 codec = AudioCodecFromPayloadType(e); 2250 ASSERT_EQ(101, codec.id); 2251 ASSERT_EQ("EG711A", codec.name); 2252 ASSERT_EQ(8000, codec.clockrate); 2253 ASSERT_EQ(64000, codec.bitrate); 2254 ASSERT_EQ(1, codec.channels); 2255 2256 e = NextFromPayloadType(e); 2257 ASSERT_TRUE(e != NULL); 2258 codec = AudioCodecFromPayloadType(e); 2259 ASSERT_EQ(0, codec.id); 2260 ASSERT_EQ("PCMU", codec.name); 2261 ASSERT_EQ(8000, codec.clockrate); 2262 ASSERT_EQ(64000, codec.bitrate); 2263 ASSERT_EQ(1, codec.channels); 2264 2265 e = NextFromPayloadType(e); 2266 ASSERT_TRUE(e != NULL); 2267 codec = AudioCodecFromPayloadType(e); 2268 ASSERT_EQ(8, codec.id); 2269 ASSERT_EQ("PCMA", codec.name); 2270 ASSERT_EQ(8000, codec.clockrate); 2271 ASSERT_EQ(64000, codec.bitrate); 2272 ASSERT_EQ(1, codec.channels); 2273 2274 e = NextFromPayloadType(e); 2275 ASSERT_TRUE(e != NULL); 2276 codec = AudioCodecFromPayloadType(e); 2277 ASSERT_EQ(126, codec.id); 2278 ASSERT_EQ("CN", codec.name); 2279 ASSERT_EQ(32000, codec.clockrate); 2280 ASSERT_EQ(1, codec.channels); 2281 2282 e = NextFromPayloadType(e); 2283 ASSERT_TRUE(e != NULL); 2284 codec = AudioCodecFromPayloadType(e); 2285 ASSERT_EQ(105, codec.id); 2286 ASSERT_EQ("CN", codec.name); 2287 ASSERT_EQ(16000, codec.clockrate); 2288 ASSERT_EQ(1, codec.channels); 2289 2290 e = NextFromPayloadType(e); 2291 ASSERT_TRUE(e != NULL); 2292 codec = AudioCodecFromPayloadType(e); 2293 ASSERT_EQ(13, codec.id); 2294 ASSERT_EQ("CN", codec.name); 2295 ASSERT_EQ(8000, codec.clockrate); 2296 ASSERT_EQ(1, codec.channels); 2297 2298 e = NextFromPayloadType(e); 2299 ASSERT_TRUE(e != NULL); 2300 codec = AudioCodecFromPayloadType(e); 2301 ASSERT_EQ(117, codec.id); 2302 ASSERT_EQ("red", codec.name); 2303 ASSERT_EQ(8000, codec.clockrate); 2304 ASSERT_EQ(1, codec.channels); 2305 2306 e = NextFromPayloadType(e); 2307 ASSERT_TRUE(e != NULL); 2308 codec = AudioCodecFromPayloadType(e); 2309 ASSERT_EQ(106, codec.id); 2310 ASSERT_EQ("telephone-event", codec.name); 2311 ASSERT_EQ(8000, codec.clockrate); 2312 ASSERT_EQ(1, codec.channels); 2313 2314 e = NextFromPayloadType(e); 2315 ASSERT_TRUE(e == NULL); 2316 } 2317 2318 void TestCodecsOfVideoInitiate(buzz::XmlElement* content) { 2319 ASSERT_TRUE(content != NULL); 2320 buzz::XmlElement* payload_type = PayloadTypeFromContent(content); 2321 ASSERT_TRUE(payload_type != NULL); 2322 cricket::AudioCodec codec = AudioCodecFromPayloadType(payload_type); 2323 ASSERT_EQ(103, codec.id); 2324 ASSERT_EQ("ISAC", codec.name); 2325 ASSERT_EQ(16000, codec.clockrate); 2326 ASSERT_EQ(1, codec.channels); 2327 2328 content = parser_->NextContent(content); 2329 ASSERT_TRUE(content != NULL); 2330 payload_type = PayloadTypeFromContent(content); 2331 ASSERT_TRUE(payload_type != NULL); 2332 cricket::VideoCodec vcodec = 2333 parser_->VideoCodecFromPayloadType(payload_type); 2334 ASSERT_EQ(99, vcodec.id); 2335 ASSERT_EQ("H264-SVC", vcodec.name); 2336 ASSERT_EQ(320, vcodec.width); 2337 ASSERT_EQ(200, vcodec.height); 2338 ASSERT_EQ(30, vcodec.framerate); 2339 } 2340 2341 void TestHasAudioCodecsFromInitiateSomeUnsupported(buzz::XmlElement* e) { 2342 ASSERT_TRUE(e != NULL); 2343 e = PayloadTypeFromContent(e); 2344 ASSERT_TRUE(e != NULL); 2345 2346 cricket::AudioCodec codec = AudioCodecFromPayloadType(e); 2347 ASSERT_EQ(103, codec.id); 2348 ASSERT_EQ("ISAC", codec.name); 2349 ASSERT_EQ(16000, codec.clockrate); 2350 ASSERT_EQ(1, codec.channels); 2351 2352 e = NextFromPayloadType(e); 2353 ASSERT_TRUE(e != NULL); 2354 codec = AudioCodecFromPayloadType(e); 2355 ASSERT_EQ(100, codec.id); 2356 ASSERT_EQ("EG711U", codec.name); 2357 2358 e = NextFromPayloadType(e); 2359 ASSERT_TRUE(e != NULL); 2360 codec = AudioCodecFromPayloadType(e); 2361 ASSERT_EQ(101, codec.id); 2362 ASSERT_EQ("EG711A", codec.name); 2363 2364 e = NextFromPayloadType(e); 2365 ASSERT_TRUE(e != NULL); 2366 codec = AudioCodecFromPayloadType(e); 2367 ASSERT_EQ(0, codec.id); 2368 ASSERT_EQ("PCMU", codec.name); 2369 2370 e = NextFromPayloadType(e); 2371 ASSERT_TRUE(e != NULL); 2372 codec = AudioCodecFromPayloadType(e); 2373 ASSERT_EQ(13, codec.id); 2374 ASSERT_EQ("CN", codec.name); 2375 2376 e = NextFromPayloadType(e); 2377 ASSERT_TRUE(e == NULL); 2378 } 2379 2380 void TestHasAudioCodecsFromInitiateDynamicAudioCodecs( 2381 buzz::XmlElement* e) { 2382 ASSERT_TRUE(e != NULL); 2383 e = PayloadTypeFromContent(e); 2384 ASSERT_TRUE(e != NULL); 2385 2386 cricket::AudioCodec codec = AudioCodecFromPayloadType(e); 2387 ASSERT_EQ(123, codec.id); 2388 ASSERT_EQ(16000, codec.clockrate); 2389 ASSERT_EQ(1, codec.channels); 2390 2391 e = NextFromPayloadType(e); 2392 ASSERT_TRUE(e == NULL); 2393 } 2394 2395 void TestHasDefaultAudioCodecs(buzz::XmlElement* e) { 2396 ASSERT_TRUE(e != NULL); 2397 e = PayloadTypeFromContent(e); 2398 ASSERT_TRUE(e != NULL); 2399 2400 cricket::AudioCodec codec = AudioCodecFromPayloadType(e); 2401 ASSERT_EQ(103, codec.id); 2402 ASSERT_EQ("ISAC", codec.name); 2403 2404 e = NextFromPayloadType(e); 2405 ASSERT_TRUE(e != NULL); 2406 codec = AudioCodecFromPayloadType(e); 2407 ASSERT_EQ(0, codec.id); 2408 ASSERT_EQ("PCMU", codec.name); 2409 2410 e = NextFromPayloadType(e); 2411 ASSERT_TRUE(e == NULL); 2412 } 2413 2414 void TestHasAudioCodecsFromInitiateStaticAudioCodecs( 2415 buzz::XmlElement* e) { 2416 ASSERT_TRUE(e != NULL); 2417 e = PayloadTypeFromContent(e); 2418 ASSERT_TRUE(e != NULL); 2419 2420 cricket::AudioCodec codec = AudioCodecFromPayloadType(e); 2421 ASSERT_EQ(3, codec.id); 2422 2423 e = NextFromPayloadType(e); 2424 ASSERT_TRUE(e != NULL); 2425 codec = AudioCodecFromPayloadType(e); 2426 ASSERT_EQ(0, codec.id); 2427 2428 e = NextFromPayloadType(e); 2429 ASSERT_TRUE(e != NULL); 2430 codec = AudioCodecFromPayloadType(e); 2431 ASSERT_EQ(8, codec.id); 2432 2433 e = NextFromPayloadType(e); 2434 ASSERT_TRUE(e == NULL); 2435 } 2436 2437 void TestGingleInitiateWithUnsupportedCrypto( 2438 const std::string &initiate_string, 2439 buzz::XmlElement** element) { 2440 *element = NULL; 2441 2442 talk_base::scoped_ptr<buzz::XmlElement> el( 2443 buzz::XmlElement::ForStr(initiate_string)); 2444 client_->session_manager()->OnIncomingMessage(el.get()); 2445 2446 ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE, 2447 call_->sessions()[0]->state()); 2448 ClearStanzas(); 2449 CheckBadCryptoFromIncomingInitiate(call_->sessions()[0]); 2450 2451 call_->AcceptSession(call_->sessions()[0], cricket::CallOptions()); 2452 ClearStanzas(); 2453 CheckNoCryptoForOutgoingAccept(call_->sessions()[0]); 2454 2455 call_->Terminate(); 2456 ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE, 2457 call_->sessions()[0]->state()); 2458 ClearStanzas(); 2459 } 2460 2461 void TestIncomingAcceptWithSsrcs( 2462 const std::string& accept_string, 2463 cricket::CallOptions& options) { 2464 client_->CreateCall(); 2465 ASSERT_TRUE(call_ != NULL); 2466 2467 call_->InitiateSession(buzz::Jid("me@mydomain.com"), 2468 buzz::Jid("me@mydomain.com"), options); 2469 ASSERT_TRUE(call_->sessions()[0] != NULL); 2470 ASSERT_EQ(cricket::Session::STATE_SENTINITIATE, 2471 call_->sessions()[0]->state()); 2472 ASSERT_EQ(1U, stanzas_.size()); 2473 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name()); 2474 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE)); 2475 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE)); 2476 buzz::XmlElement* action = ActionFromStanza(stanzas_[0]); 2477 ASSERT_TRUE(action != NULL); 2478 buzz::XmlElement* content = ContentFromAction(action); 2479 ASSERT_TRUE(content != NULL); 2480 if (initial_protocol_ == cricket::PROTOCOL_JINGLE) { 2481 buzz::XmlElement* content_desc = 2482 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT); 2483 ASSERT_TRUE(content_desc != NULL); 2484 ASSERT_EQ("", content_desc->Attr(cricket::QN_SSRC)); 2485 } 2486 ClearStanzas(); 2487 2488 // We need to insert the session ID into the session accept message. 2489 talk_base::scoped_ptr<buzz::XmlElement> el( 2490 buzz::XmlElement::ForStr(accept_string)); 2491 const std::string sid = call_->sessions()[0]->id(); 2492 if (initial_protocol_ == cricket::PROTOCOL_JINGLE) { 2493 buzz::XmlElement* jingle = el->FirstNamed(cricket::QN_JINGLE); 2494 jingle->SetAttr(cricket::QN_SID, sid); 2495 } else { 2496 buzz::XmlElement* session = el->FirstNamed(cricket::QN_GINGLE_SESSION); 2497 session->SetAttr(cricket::QN_ID, sid); 2498 } 2499 2500 client_->session_manager()->OnIncomingMessage(el.get()); 2501 2502 ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT, 2503 call_->sessions()[0]->state()); 2504 ASSERT_EQ(1U, stanzas_.size()); 2505 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name()); 2506 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE)); 2507 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE)); 2508 ClearStanzas(); 2509 2510 CheckAudioSsrcForIncomingAccept(call_->sessions()[0]); 2511 CheckVideoSsrcForIncomingAccept(call_->sessions()[0]); 2512 if (options.data_channel_type == cricket::DCT_RTP) { 2513 CheckDataSsrcForIncomingAccept(call_->sessions()[0]); 2514 } 2515 // TODO(pthatcher): Check kDataSid if DCT_SCTP. 2516 // const uint32 kDataSid = 0; 2517 } 2518 2519 size_t ClearStanzas() { 2520 size_t size = stanzas_.size(); 2521 for (size_t i = 0; i < size; i++) { 2522 delete stanzas_[i]; 2523 } 2524 stanzas_.clear(); 2525 return size; 2526 } 2527 2528 buzz::XmlElement* SetJingleSid(buzz::XmlElement* stanza) { 2529 buzz::XmlElement* jingle = 2530 stanza->FirstNamed(cricket::QN_JINGLE); 2531 jingle->SetAttr(cricket::QN_SID, call_->sessions()[0]->id()); 2532 return stanza; 2533 } 2534 2535 void TestSendVideoStreamUpdate() { 2536 cricket::CallOptions options = VideoCallOptions(); 2537 options.is_muc = true; 2538 2539 client_->CreateCall(); 2540 call_->InitiateSession(buzz::Jid("me@mydomain.com"), 2541 buzz::Jid("me@mydomain.com"), options); 2542 ClearStanzas(); 2543 2544 cricket::StreamParams stream; 2545 stream.id = "test-stream"; 2546 stream.ssrcs.push_back(1001); 2547 talk_base::scoped_ptr<buzz::XmlElement> expected_stream_add( 2548 buzz::XmlElement::ForStr( 2549 JingleOutboundStreamAdd( 2550 call_->sessions()[0]->id(), 2551 "video", stream.id, "1001"))); 2552 talk_base::scoped_ptr<buzz::XmlElement> expected_stream_remove( 2553 buzz::XmlElement::ForStr( 2554 JingleOutboundStreamRemove( 2555 call_->sessions()[0]->id(), 2556 "video", stream.id))); 2557 2558 call_->SendVideoStreamUpdate(call_->sessions()[0], 2559 call_->CreateVideoStreamUpdate(stream)); 2560 ASSERT_EQ(1U, stanzas_.size()); 2561 EXPECT_EQ(expected_stream_add->Str(), stanzas_[0]->Str()); 2562 ClearStanzas(); 2563 2564 stream.ssrcs.clear(); 2565 call_->SendVideoStreamUpdate(call_->sessions()[0], 2566 call_->CreateVideoStreamUpdate(stream)); 2567 ASSERT_EQ(1U, stanzas_.size()); 2568 EXPECT_EQ(expected_stream_remove->Str(), stanzas_[0]->Str()); 2569 ClearStanzas(); 2570 } 2571 2572 void TestStreamsUpdateAndViewRequests() { 2573 cricket::CallOptions options = VideoCallOptions(); 2574 options.is_muc = true; 2575 2576 client_->CreateCall(); 2577 call_->InitiateSession(buzz::Jid("me@mydomain.com"), 2578 buzz::Jid("me@mydomain.com"), options); 2579 ASSERT_EQ(1U, ClearStanzas()); 2580 ASSERT_EQ(0U, last_streams_added_.audio().size()); 2581 ASSERT_EQ(0U, last_streams_added_.video().size()); 2582 ASSERT_EQ(0U, last_streams_removed_.audio().size()); 2583 ASSERT_EQ(0U, last_streams_removed_.video().size()); 2584 2585 talk_base::scoped_ptr<buzz::XmlElement> accept_stanza( 2586 buzz::XmlElement::ForStr(kJingleAcceptWithSsrcs)); 2587 SetJingleSid(accept_stanza.get()); 2588 client_->session_manager()->OnIncomingMessage(accept_stanza.get()); 2589 ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT, 2590 call_->sessions()[0]->state()); 2591 ASSERT_EQ(1U, stanzas_.size()); 2592 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE)); 2593 ClearStanzas(); 2594 // Need to clear the added streams, because they are populated when 2595 // receiving an accept message now. 2596 last_streams_added_.mutable_video()->clear(); 2597 last_streams_added_.mutable_audio()->clear(); 2598 2599 call_->sessions()[0]->SetState(cricket::Session::STATE_INPROGRESS); 2600 2601 talk_base::scoped_ptr<buzz::XmlElement> streams_stanza( 2602 buzz::XmlElement::ForStr( 2603 JingleStreamAdd("video", "Bob", "video1", "ABC"))); 2604 SetJingleSid(streams_stanza.get()); 2605 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2606 // First one is ignored because of bad syntax. 2607 ASSERT_EQ(1U, stanzas_.size()); 2608 // TODO(pthatcher): Figure out how to make this an ERROR rather than RESULT. 2609 ASSERT_EQ(std::string(buzz::STR_ERROR), stanzas_[0]->Attr(buzz::QN_TYPE)); 2610 ClearStanzas(); 2611 ASSERT_EQ(0U, last_streams_added_.audio().size()); 2612 ASSERT_EQ(0U, last_streams_added_.video().size()); 2613 ASSERT_EQ(0U, last_streams_removed_.audio().size()); 2614 ASSERT_EQ(0U, last_streams_removed_.video().size()); 2615 2616 streams_stanza.reset(buzz::XmlElement::ForStr( 2617 JingleStreamAdd("audio", "Bob", "audio1", "1234"))); 2618 SetJingleSid(streams_stanza.get()); 2619 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2620 ASSERT_EQ(1U, last_streams_added_.audio().size()); 2621 ASSERT_EQ("Bob", last_streams_added_.audio()[0].groupid); 2622 ASSERT_EQ(1U, last_streams_added_.audio()[0].ssrcs.size()); 2623 ASSERT_EQ(1234U, last_streams_added_.audio()[0].first_ssrc()); 2624 2625 // Ignores adds without ssrcs. 2626 streams_stanza.reset(buzz::XmlElement::ForStr( 2627 JingleStreamAddWithoutSsrc("audio", "Bob", "audioX"))); 2628 SetJingleSid(streams_stanza.get()); 2629 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2630 ASSERT_EQ(1U, last_streams_added_.audio().size()); 2631 ASSERT_EQ(1234U, last_streams_added_.audio()[0].first_ssrc()); 2632 2633 // Ignores stream updates with unknown content names. (Don't terminate). 2634 streams_stanza.reset(buzz::XmlElement::ForStr( 2635 JingleStreamAddWithoutSsrc("foo", "Bob", "foo"))); 2636 SetJingleSid(streams_stanza.get()); 2637 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2638 2639 streams_stanza.reset(buzz::XmlElement::ForStr( 2640 JingleStreamAdd("audio", "Joe", "audio1", "2468"))); 2641 SetJingleSid(streams_stanza.get()); 2642 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2643 ASSERT_EQ(1U, last_streams_added_.audio().size()); 2644 ASSERT_EQ("Joe", last_streams_added_.audio()[0].groupid); 2645 ASSERT_EQ(1U, last_streams_added_.audio()[0].ssrcs.size()); 2646 ASSERT_EQ(2468U, last_streams_added_.audio()[0].first_ssrc()); 2647 2648 streams_stanza.reset(buzz::XmlElement::ForStr( 2649 JingleStreamAdd("video", "Bob", "video1", "5678"))); 2650 SetJingleSid(streams_stanza.get()); 2651 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2652 ASSERT_EQ(1U, last_streams_added_.video().size()); 2653 ASSERT_EQ("Bob", last_streams_added_.video()[0].groupid); 2654 ASSERT_EQ(1U, last_streams_added_.video()[0].ssrcs.size()); 2655 ASSERT_EQ(5678U, last_streams_added_.video()[0].first_ssrc()); 2656 2657 // We're testing that a "duplicate" is effectively ignored. 2658 last_streams_added_.mutable_video()->clear(); 2659 last_streams_removed_.mutable_video()->clear(); 2660 streams_stanza.reset(buzz::XmlElement::ForStr( 2661 JingleStreamAdd("video", "Bob", "video1", "5678"))); 2662 SetJingleSid(streams_stanza.get()); 2663 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2664 ASSERT_EQ(0U, last_streams_added_.video().size()); 2665 ASSERT_EQ(0U, last_streams_removed_.video().size()); 2666 2667 streams_stanza.reset(buzz::XmlElement::ForStr( 2668 JingleStreamAdd("video", "Bob", "video2", "5679"))); 2669 SetJingleSid(streams_stanza.get()); 2670 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2671 ASSERT_EQ(1U, last_streams_added_.video().size()); 2672 ASSERT_EQ("Bob", last_streams_added_.video()[0].groupid); 2673 ASSERT_EQ(1U, last_streams_added_.video()[0].ssrcs.size()); 2674 ASSERT_EQ(5679U, last_streams_added_.video()[0].first_ssrc()); 2675 2676 cricket::FakeVoiceMediaChannel* voice_channel = fme_->GetVoiceChannel(0); 2677 ASSERT_TRUE(voice_channel != NULL); 2678 ASSERT_TRUE(voice_channel->HasRecvStream(1234U)); 2679 ASSERT_TRUE(voice_channel->HasRecvStream(2468U)); 2680 cricket::FakeVideoMediaChannel* video_channel = fme_->GetVideoChannel(0); 2681 ASSERT_TRUE(video_channel != NULL); 2682 ASSERT_TRUE(video_channel->HasRecvStream(5678U)); 2683 ClearStanzas(); 2684 2685 cricket::ViewRequest viewRequest; 2686 cricket::StaticVideoView staticVideoView( 2687 cricket::StreamSelector(5678U), 640, 480, 30); 2688 viewRequest.static_video_views.push_back(staticVideoView); 2689 talk_base::scoped_ptr<buzz::XmlElement> expected_view_elem( 2690 buzz::XmlElement::ForStr(JingleView("5678", "640", "480", "30"))); 2691 SetJingleSid(expected_view_elem.get()); 2692 2693 ASSERT_TRUE( 2694 call_->SendViewRequest(call_->sessions()[0], viewRequest)); 2695 ASSERT_EQ(1U, stanzas_.size()); 2696 ASSERT_EQ(expected_view_elem->Str(), stanzas_[0]->Str()); 2697 ClearStanzas(); 2698 2699 streams_stanza.reset(buzz::XmlElement::ForStr( 2700 JingleStreamRemove("audio", "Bob", "audio1"))); 2701 SetJingleSid(streams_stanza.get()); 2702 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2703 ASSERT_EQ(1U, last_streams_removed_.audio().size()); 2704 ASSERT_EQ(1U, last_streams_removed_.audio()[0].ssrcs.size()); 2705 EXPECT_EQ(1234U, last_streams_removed_.audio()[0].first_ssrc()); 2706 2707 streams_stanza.reset(buzz::XmlElement::ForStr( 2708 JingleStreamRemove("video", "Bob", "video1"))); 2709 SetJingleSid(streams_stanza.get()); 2710 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2711 ASSERT_EQ(1U, last_streams_removed_.video().size()); 2712 ASSERT_EQ(1U, last_streams_removed_.video()[0].ssrcs.size()); 2713 EXPECT_EQ(5678U, last_streams_removed_.video()[0].first_ssrc()); 2714 2715 streams_stanza.reset(buzz::XmlElement::ForStr( 2716 JingleStreamRemove("video", "Bob", "video2"))); 2717 SetJingleSid(streams_stanza.get()); 2718 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2719 ASSERT_EQ(1U, last_streams_removed_.video().size()); 2720 ASSERT_EQ(1U, last_streams_removed_.video()[0].ssrcs.size()); 2721 EXPECT_EQ(5679U, last_streams_removed_.video()[0].first_ssrc()); 2722 2723 // Duplicate removal: should be ignored. 2724 last_streams_removed_.mutable_audio()->clear(); 2725 streams_stanza.reset(buzz::XmlElement::ForStr( 2726 JingleStreamRemove("audio", "Bob", "audio1"))); 2727 SetJingleSid(streams_stanza.get()); 2728 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2729 ASSERT_EQ(0U, last_streams_removed_.audio().size()); 2730 2731 // Duplicate removal: should be ignored. 2732 last_streams_removed_.mutable_video()->clear(); 2733 streams_stanza.reset(buzz::XmlElement::ForStr( 2734 JingleStreamRemove("video", "Bob", "video1"))); 2735 SetJingleSid(streams_stanza.get()); 2736 client_->session_manager()->OnIncomingMessage(streams_stanza.get()); 2737 ASSERT_EQ(0U, last_streams_removed_.video().size()); 2738 2739 voice_channel = fme_->GetVoiceChannel(0); 2740 ASSERT_TRUE(voice_channel != NULL); 2741 ASSERT_FALSE(voice_channel->HasRecvStream(1234U)); 2742 ASSERT_TRUE(voice_channel->HasRecvStream(2468U)); 2743 video_channel = fme_->GetVideoChannel(0); 2744 ASSERT_TRUE(video_channel != NULL); 2745 ASSERT_FALSE(video_channel->HasRecvStream(5678U)); 2746 2747 // Fails because ssrc is now invalid. 2748 ASSERT_FALSE( 2749 call_->SendViewRequest(call_->sessions()[0], viewRequest)); 2750 2751 ClearStanzas(); 2752 } 2753 2754 void MakeSignalingSecure(cricket::SecurePolicy secure) { 2755 client_->set_secure(secure); 2756 } 2757 2758 void ExpectCrypto(cricket::SecurePolicy secure) { 2759 MakeSignalingSecure(secure); 2760 expect_incoming_crypto_ = true; 2761#ifdef HAVE_SRTP 2762 expect_outgoing_crypto_ = true; 2763#endif 2764 } 2765 2766 void ExpectVideoBandwidth(int bandwidth) { 2767 expected_video_bandwidth_ = bandwidth; 2768 } 2769 2770 void ExpectVideoRtcpMux(bool rtcp_mux) { 2771 expected_video_rtcp_mux_ = rtcp_mux; 2772 } 2773 2774 template <class C> 2775 void SetCodecFeedbackParams(std::vector<C>* codecs, 2776 const FeedbackParams& fb_params) { 2777 for (size_t i = 0; i < codecs->size(); ++i) { 2778 codecs->at(i).feedback_params = fb_params; 2779 } 2780 } 2781 2782 void ExpectRtcpFb() { 2783 FeedbackParams params_nack_fir; 2784 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm, 2785 cricket::kRtcpFbCcmParamFir)); 2786 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack)); 2787 2788 FeedbackParams params_nack; 2789 params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack)); 2790 2791 expected_audio_fb_params_ = params_nack; 2792 expected_video_fb_params_ = params_nack_fir; 2793 expected_data_fb_params_ = params_nack; 2794 } 2795 2796 private: 2797 void OnSendStanza(cricket::SessionManager* manager, 2798 const buzz::XmlElement* stanza) { 2799 LOG(LS_INFO) << stanza->Str(); 2800 stanzas_.push_back(new buzz::XmlElement(*stanza)); 2801 } 2802 2803 void OnSessionCreate(cricket::Session* session, bool initiate) { 2804 session->set_current_protocol(initial_protocol_); 2805 } 2806 2807 void OnCallCreate(cricket::Call *call) { 2808 call_ = call; 2809 call->SignalMediaStreamsUpdate.connect( 2810 this, &MediaSessionClientTest::OnMediaStreamsUpdate); 2811 } 2812 2813 void OnCallDestroy(cricket::Call *call) { 2814 call_ = NULL; 2815 } 2816 2817 void OnMediaStreamsUpdate(cricket::Call *call, 2818 cricket::Session *session, 2819 const cricket::MediaStreams& added, 2820 const cricket::MediaStreams& removed) { 2821 last_streams_added_.CopyFrom(added); 2822 last_streams_removed_.CopyFrom(removed); 2823 } 2824 2825 talk_base::NetworkManager* nm_; 2826 cricket::PortAllocator* pa_; 2827 cricket::SessionManager* sm_; 2828 cricket::FakeMediaEngine* fme_; 2829 cricket::FakeDataEngine* fdme_; 2830 cricket::MediaSessionClient* client_; 2831 2832 cricket::Call* call_; 2833 std::vector<buzz::XmlElement* > stanzas_; 2834 MediaSessionTestParser* parser_; 2835 cricket::SignalingProtocol initial_protocol_; 2836 bool expect_incoming_crypto_; 2837 bool expect_outgoing_crypto_; 2838 int expected_video_bandwidth_; 2839 bool expected_video_rtcp_mux_; 2840 FeedbackParams expected_audio_fb_params_; 2841 FeedbackParams expected_video_fb_params_; 2842 FeedbackParams expected_data_fb_params_; 2843 cricket::MediaStreams last_streams_added_; 2844 cricket::MediaStreams last_streams_removed_; 2845}; 2846 2847MediaSessionClientTest* GingleTest() { 2848 return new MediaSessionClientTest(new GingleSessionTestParser(), 2849 cricket::PROTOCOL_GINGLE); 2850} 2851 2852MediaSessionClientTest* JingleTest() { 2853 return new MediaSessionClientTest(new JingleSessionTestParser(), 2854 cricket::PROTOCOL_JINGLE); 2855} 2856 2857TEST(MediaSessionTest, JingleGoodInitiateWithRtcpFb) { 2858 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2859 talk_base::scoped_ptr<buzz::XmlElement> elem; 2860 2861 cricket::CallOptions options = VideoCallOptions(); 2862 options.data_channel_type = cricket::DCT_SCTP; 2863 test->ExpectRtcpFb(); 2864 test->TestGoodIncomingInitiate( 2865 kJingleInitiateWithRtcpFb, options, elem.use()); 2866} 2867 2868TEST(MediaSessionTest, JingleGoodVideoInitiate) { 2869 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2870 talk_base::scoped_ptr<buzz::XmlElement> elem; 2871 test->TestGoodIncomingInitiate( 2872 kJingleVideoInitiate, VideoCallOptions(), elem.use()); 2873 test->TestCodecsOfVideoInitiate(elem.get()); 2874} 2875 2876TEST(MediaSessionTest, JingleGoodVideoInitiateWithBandwidth) { 2877 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2878 talk_base::scoped_ptr<buzz::XmlElement> elem; 2879 test->ExpectVideoBandwidth(42000); 2880 test->TestGoodIncomingInitiate( 2881 kJingleVideoInitiateWithBandwidth, VideoCallOptions(), elem.use()); 2882} 2883 2884TEST(MediaSessionTest, JingleGoodVideoInitiateWithRtcpMux) { 2885 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2886 talk_base::scoped_ptr<buzz::XmlElement> elem; 2887 test->ExpectVideoRtcpMux(true); 2888 test->TestGoodIncomingInitiate( 2889 kJingleVideoInitiateWithRtcpMux, VideoCallOptions(), elem.use()); 2890} 2891 2892TEST(MediaSessionTest, JingleGoodVideoInitiateWithRtpData) { 2893 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2894 talk_base::scoped_ptr<buzz::XmlElement> elem; 2895 cricket::CallOptions options = VideoCallOptions(); 2896 options.data_channel_type = cricket::DCT_RTP; 2897 test->TestGoodIncomingInitiate( 2898 AddEncryption(kJingleVideoInitiateWithRtpData, kJingleCryptoOffer), 2899 options, 2900 elem.use()); 2901} 2902 2903TEST(MediaSessionTest, JingleGoodVideoInitiateWithSctpData) { 2904 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2905 talk_base::scoped_ptr<buzz::XmlElement> elem; 2906 cricket::CallOptions options = VideoCallOptions(); 2907 options.data_channel_type = cricket::DCT_SCTP; 2908 test->TestGoodIncomingInitiate(kJingleVideoInitiateWithSctpData, 2909 options, 2910 elem.use()); 2911} 2912 2913TEST(MediaSessionTest, JingleRejectAudio) { 2914 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2915 talk_base::scoped_ptr<buzz::XmlElement> elem; 2916 cricket::CallOptions options = VideoCallOptions(); 2917 options.has_audio = false; 2918 options.data_channel_type = cricket::DCT_RTP; 2919 test->TestRejectOffer(kJingleVideoInitiateWithRtpData, options, elem.use()); 2920} 2921 2922TEST(MediaSessionTest, JingleRejectVideo) { 2923 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2924 talk_base::scoped_ptr<buzz::XmlElement> elem; 2925 cricket::CallOptions options = AudioCallOptions(); 2926 options.data_channel_type = cricket::DCT_RTP; 2927 test->TestRejectOffer(kJingleVideoInitiateWithRtpData, options, elem.use()); 2928} 2929 2930TEST(MediaSessionTest, JingleRejectData) { 2931 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2932 talk_base::scoped_ptr<buzz::XmlElement> elem; 2933 test->TestRejectOffer( 2934 kJingleVideoInitiateWithRtpData, VideoCallOptions(), elem.use()); 2935} 2936 2937TEST(MediaSessionTest, JingleRejectVideoAndData) { 2938 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2939 talk_base::scoped_ptr<buzz::XmlElement> elem; 2940 test->TestRejectOffer( 2941 kJingleVideoInitiateWithRtpData, AudioCallOptions(), elem.use()); 2942} 2943 2944TEST(MediaSessionTest, JingleGoodInitiateAllSupportedAudioCodecs) { 2945 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2946 talk_base::scoped_ptr<buzz::XmlElement> elem; 2947 test->TestGoodIncomingInitiate( 2948 kJingleInitiate, AudioCallOptions(), elem.use()); 2949 test->TestHasAllSupportedAudioCodecs(elem.get()); 2950} 2951 2952TEST(MediaSessionTest, JingleGoodInitiateDifferentPreferenceAudioCodecs) { 2953 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2954 talk_base::scoped_ptr<buzz::XmlElement> elem; 2955 test->TestGoodIncomingInitiate( 2956 kJingleInitiateDifferentPreference, AudioCallOptions(), elem.use()); 2957 test->TestHasAllSupportedAudioCodecs(elem.get()); 2958} 2959 2960TEST(MediaSessionTest, JingleGoodInitiateSomeUnsupportedAudioCodecs) { 2961 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2962 talk_base::scoped_ptr<buzz::XmlElement> elem; 2963 test->TestGoodIncomingInitiate( 2964 kJingleInitiateSomeUnsupported, AudioCallOptions(), elem.use()); 2965 test->TestHasAudioCodecsFromInitiateSomeUnsupported(elem.get()); 2966} 2967 2968TEST(MediaSessionTest, JingleGoodInitiateDynamicAudioCodecs) { 2969 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2970 talk_base::scoped_ptr<buzz::XmlElement> elem; 2971 test->TestGoodIncomingInitiate( 2972 kJingleInitiateDynamicAudioCodecs, AudioCallOptions(), elem.use()); 2973 test->TestHasAudioCodecsFromInitiateDynamicAudioCodecs(elem.get()); 2974} 2975 2976TEST(MediaSessionTest, JingleGoodInitiateStaticAudioCodecs) { 2977 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2978 talk_base::scoped_ptr<buzz::XmlElement> elem; 2979 test->TestGoodIncomingInitiate( 2980 kJingleInitiateStaticAudioCodecs, AudioCallOptions(), elem.use()); 2981 test->TestHasAudioCodecsFromInitiateStaticAudioCodecs(elem.get()); 2982} 2983 2984TEST(MediaSessionTest, JingleBadInitiateNoAudioCodecs) { 2985 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2986 test->TestBadIncomingInitiate(kJingleInitiateNoAudioCodecs); 2987} 2988 2989TEST(MediaSessionTest, JingleBadInitiateNoSupportedAudioCodecs) { 2990 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2991 test->TestBadIncomingInitiate(kJingleInitiateNoSupportedAudioCodecs); 2992} 2993 2994TEST(MediaSessionTest, JingleBadInitiateWrongClockrates) { 2995 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 2996 test->TestBadIncomingInitiate(kJingleInitiateWrongClockrates); 2997} 2998 2999TEST(MediaSessionTest, JingleBadInitiateWrongChannels) { 3000 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3001 test->TestBadIncomingInitiate(kJingleInitiateWrongChannels); 3002} 3003 3004TEST(MediaSessionTest, JingleBadInitiateNoPayloadTypes) { 3005 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3006 test->TestBadIncomingInitiate(kJingleInitiateNoPayloadTypes); 3007} 3008 3009TEST(MediaSessionTest, JingleBadInitiateDynamicWithoutNames) { 3010 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3011 test->TestBadIncomingInitiate(kJingleInitiateDynamicWithoutNames); 3012} 3013 3014TEST(MediaSessionTest, JingleGoodOutgoingInitiate) { 3015 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3016 test->TestGoodOutgoingInitiate(AudioCallOptions()); 3017} 3018 3019TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithBandwidth) { 3020 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3021 cricket::CallOptions options = VideoCallOptions(); 3022 options.video_bandwidth = 42000; 3023 test->TestGoodOutgoingInitiate(options); 3024} 3025 3026TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithRtcpMux) { 3027 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3028 cricket::CallOptions options = VideoCallOptions(); 3029 options.rtcp_mux_enabled = true; 3030 test->TestGoodOutgoingInitiate(options); 3031} 3032 3033TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithRtpData) { 3034 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3035 cricket::CallOptions options; 3036 options.data_channel_type = cricket::DCT_RTP; 3037 test->ExpectCrypto(cricket::SEC_ENABLED); 3038 test->TestGoodOutgoingInitiate(options); 3039} 3040 3041TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithSctpData) { 3042 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3043 cricket::CallOptions options; 3044 options.data_channel_type = cricket::DCT_SCTP; 3045 test->TestGoodOutgoingInitiate(options); 3046} 3047 3048// Crypto related tests. 3049 3050// Offer has crypto but the session is not secured, just ignore it. 3051TEST(MediaSessionTest, JingleInitiateWithCryptoIsIgnoredWhenNotSecured) { 3052 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3053 talk_base::scoped_ptr<buzz::XmlElement> elem; 3054 test->TestGoodIncomingInitiate( 3055 AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer), 3056 VideoCallOptions(), 3057 elem.use()); 3058} 3059 3060// Offer has crypto required but the session is not secure, fail. 3061TEST(MediaSessionTest, JingleInitiateWithCryptoRequiredWhenNotSecured) { 3062 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3063 test->TestBadIncomingInitiate(AddEncryption(kJingleVideoInitiate, 3064 kJingleRequiredCryptoOffer)); 3065} 3066 3067// Offer has no crypto but the session is secure required, fail. 3068TEST(MediaSessionTest, JingleInitiateWithNoCryptoFailsWhenSecureRequired) { 3069 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3070 test->ExpectCrypto(cricket::SEC_REQUIRED); 3071 test->TestBadIncomingInitiate(kJingleInitiate); 3072} 3073 3074// Offer has crypto and session is secure, expect crypto in the answer. 3075TEST(MediaSessionTest, JingleInitiateWithCryptoWhenSecureEnabled) { 3076 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3077 talk_base::scoped_ptr<buzz::XmlElement> elem; 3078 test->ExpectCrypto(cricket::SEC_ENABLED); 3079 test->TestGoodIncomingInitiate( 3080 AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer), 3081 VideoCallOptions(), 3082 elem.use()); 3083} 3084 3085// Offer has crypto and session is secure required, expect crypto in 3086// the answer. 3087TEST(MediaSessionTest, JingleInitiateWithCryptoWhenSecureRequired) { 3088 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3089 talk_base::scoped_ptr<buzz::XmlElement> elem; 3090 test->ExpectCrypto(cricket::SEC_REQUIRED); 3091 test->TestGoodIncomingInitiate( 3092 AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer), 3093 VideoCallOptions(), 3094 elem.use()); 3095} 3096 3097// Offer has unsupported crypto and session is secure, no crypto in 3098// the answer. 3099TEST(MediaSessionTest, JingleInitiateWithUnsupportedCrypto) { 3100 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3101 talk_base::scoped_ptr<buzz::XmlElement> elem; 3102 test->MakeSignalingSecure(cricket::SEC_ENABLED); 3103 test->TestGoodIncomingInitiate( 3104 AddEncryption(kJingleInitiate, kJingleUnsupportedCryptoOffer), 3105 VideoCallOptions(), 3106 elem.use()); 3107} 3108 3109// Offer has unsupported REQUIRED crypto and session is not secure, fail. 3110TEST(MediaSessionTest, JingleInitiateWithRequiredUnsupportedCrypto) { 3111 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3112 test->TestBadIncomingInitiate( 3113 AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer)); 3114} 3115 3116// Offer has unsupported REQUIRED crypto and session is secure, fail. 3117TEST(MediaSessionTest, JingleInitiateWithRequiredUnsupportedCryptoWhenSecure) { 3118 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3119 test->MakeSignalingSecure(cricket::SEC_ENABLED); 3120 test->TestBadIncomingInitiate( 3121 AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer)); 3122} 3123 3124// Offer has unsupported REQUIRED crypto and session is required secure, fail. 3125TEST(MediaSessionTest, 3126 JingleInitiateWithRequiredUnsupportedCryptoWhenSecureRequired) { 3127 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3128 test->MakeSignalingSecure(cricket::SEC_REQUIRED); 3129 test->TestBadIncomingInitiate( 3130 AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer)); 3131} 3132 3133 3134TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithCrypto) { 3135 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3136 test->ExpectCrypto(cricket::SEC_ENABLED); 3137 test->TestGoodOutgoingInitiate(AudioCallOptions()); 3138} 3139 3140TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithCryptoRequired) { 3141 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3142 test->ExpectCrypto(cricket::SEC_REQUIRED); 3143 test->TestGoodOutgoingInitiate(AudioCallOptions()); 3144} 3145 3146TEST(MediaSessionTest, JingleIncomingAcceptWithSsrcs) { 3147 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3148 cricket::CallOptions options = VideoCallOptions(); 3149 options.is_muc = true; 3150 test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithSsrcs, options); 3151} 3152 3153TEST(MediaSessionTest, JingleIncomingAcceptWithRtpDataSsrcs) { 3154 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3155 cricket::CallOptions options = VideoCallOptions(); 3156 options.is_muc = true; 3157 options.data_channel_type = cricket::DCT_RTP; 3158 test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithRtpDataSsrcs, options); 3159} 3160 3161TEST(MediaSessionTest, JingleIncomingAcceptWithSctpData) { 3162 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3163 cricket::CallOptions options = VideoCallOptions(); 3164 options.is_muc = true; 3165 options.data_channel_type = cricket::DCT_SCTP; 3166 test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithSctpData, options); 3167} 3168 3169TEST(MediaSessionTest, JingleStreamsUpdateAndView) { 3170 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3171 test->TestStreamsUpdateAndViewRequests(); 3172} 3173 3174TEST(MediaSessionTest, JingleSendVideoStreamUpdate) { 3175 talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest()); 3176 test->TestSendVideoStreamUpdate(); 3177} 3178 3179// Gingle tests 3180 3181TEST(MediaSessionTest, GingleGoodVideoInitiate) { 3182 talk_base::scoped_ptr<buzz::XmlElement> elem; 3183 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3184 test->TestGoodIncomingInitiate( 3185 kGingleVideoInitiate, VideoCallOptions(), elem.use()); 3186 test->TestCodecsOfVideoInitiate(elem.get()); 3187} 3188 3189TEST(MediaSessionTest, GingleGoodVideoInitiateWithBandwidth) { 3190 talk_base::scoped_ptr<buzz::XmlElement> elem; 3191 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3192 test->ExpectVideoBandwidth(42000); 3193 test->TestGoodIncomingInitiate( 3194 kGingleVideoInitiateWithBandwidth, VideoCallOptions(), elem.use()); 3195} 3196 3197TEST(MediaSessionTest, GingleGoodInitiateAllSupportedAudioCodecs) { 3198 talk_base::scoped_ptr<buzz::XmlElement> elem; 3199 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3200 test->TestGoodIncomingInitiate( 3201 kGingleInitiate, AudioCallOptions(), elem.use()); 3202 test->TestHasAllSupportedAudioCodecs(elem.get()); 3203} 3204 3205TEST(MediaSessionTest, GingleGoodInitiateAllSupportedAudioCodecsWithCrypto) { 3206 talk_base::scoped_ptr<buzz::XmlElement> elem; 3207 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3208 test->ExpectCrypto(cricket::SEC_ENABLED); 3209 test->TestGoodIncomingInitiate( 3210 AddEncryption(kGingleInitiate, kGingleCryptoOffer), 3211 AudioCallOptions(), 3212 elem.use()); 3213 test->TestHasAllSupportedAudioCodecs(elem.get()); 3214} 3215 3216TEST(MediaSessionTest, GingleGoodInitiateDifferentPreferenceAudioCodecs) { 3217 talk_base::scoped_ptr<buzz::XmlElement> elem; 3218 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3219 test->TestGoodIncomingInitiate( 3220 kGingleInitiateDifferentPreference, AudioCallOptions(), elem.use()); 3221 test->TestHasAllSupportedAudioCodecs(elem.get()); 3222} 3223 3224TEST(MediaSessionTest, GingleGoodInitiateSomeUnsupportedAudioCodecs) { 3225 talk_base::scoped_ptr<buzz::XmlElement> elem; 3226 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3227 test->TestGoodIncomingInitiate( 3228 kGingleInitiateSomeUnsupported, AudioCallOptions(), elem.use()); 3229 test->TestHasAudioCodecsFromInitiateSomeUnsupported(elem.get()); 3230} 3231 3232TEST(MediaSessionTest, GingleGoodInitiateDynamicAudioCodecs) { 3233 talk_base::scoped_ptr<buzz::XmlElement> elem; 3234 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3235 test->TestGoodIncomingInitiate( 3236 kGingleInitiateDynamicAudioCodecs, AudioCallOptions(), elem.use()); 3237 test->TestHasAudioCodecsFromInitiateDynamicAudioCodecs(elem.get()); 3238} 3239 3240TEST(MediaSessionTest, GingleGoodInitiateStaticAudioCodecs) { 3241 talk_base::scoped_ptr<buzz::XmlElement> elem; 3242 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3243 test->TestGoodIncomingInitiate( 3244 kGingleInitiateStaticAudioCodecs, AudioCallOptions(), elem.use()); 3245 test->TestHasAudioCodecsFromInitiateStaticAudioCodecs(elem.get()); 3246} 3247 3248TEST(MediaSessionTest, GingleGoodInitiateNoAudioCodecs) { 3249 talk_base::scoped_ptr<buzz::XmlElement> elem; 3250 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3251 test->TestGoodIncomingInitiate( 3252 kGingleInitiateNoAudioCodecs, AudioCallOptions(), elem.use()); 3253 test->TestHasDefaultAudioCodecs(elem.get()); 3254} 3255 3256TEST(MediaSessionTest, GingleBadInitiateNoSupportedAudioCodecs) { 3257 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3258 test->TestBadIncomingInitiate(kGingleInitiateNoSupportedAudioCodecs); 3259} 3260 3261TEST(MediaSessionTest, GingleBadInitiateWrongClockrates) { 3262 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3263 test->TestBadIncomingInitiate(kGingleInitiateWrongClockrates); 3264} 3265 3266TEST(MediaSessionTest, GingleBadInitiateWrongChannels) { 3267 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3268 test->TestBadIncomingInitiate(kGingleInitiateWrongChannels); 3269} 3270 3271 3272TEST(MediaSessionTest, GingleBadInitiateNoPayloadTypes) { 3273 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3274 test->TestBadIncomingInitiate(kGingleInitiateNoPayloadTypes); 3275} 3276 3277TEST(MediaSessionTest, GingleBadInitiateDynamicWithoutNames) { 3278 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3279 test->TestBadIncomingInitiate(kGingleInitiateDynamicWithoutNames); 3280} 3281 3282TEST(MediaSessionTest, GingleGoodOutgoingInitiate) { 3283 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3284 test->TestGoodOutgoingInitiate(AudioCallOptions()); 3285} 3286 3287TEST(MediaSessionTest, GingleGoodOutgoingInitiateWithBandwidth) { 3288 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3289 cricket::CallOptions options = VideoCallOptions(); 3290 options.video_bandwidth = 42000; 3291 test->TestGoodOutgoingInitiate(options); 3292} 3293 3294// Crypto related tests. 3295 3296// Offer has crypto but the session is not secured, just ignore it. 3297TEST(MediaSessionTest, GingleInitiateWithCryptoIsIgnoredWhenNotSecured) { 3298 talk_base::scoped_ptr<buzz::XmlElement> elem; 3299 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3300 test->TestGoodIncomingInitiate( 3301 AddEncryption(kGingleInitiate, kGingleCryptoOffer), 3302 VideoCallOptions(), 3303 elem.use()); 3304} 3305 3306// Offer has crypto required but the session is not secure, fail. 3307TEST(MediaSessionTest, GingleInitiateWithCryptoRequiredWhenNotSecured) { 3308 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3309 test->TestBadIncomingInitiate(AddEncryption(kGingleInitiate, 3310 kGingleRequiredCryptoOffer)); 3311} 3312 3313// Offer has no crypto but the session is secure required, fail. 3314TEST(MediaSessionTest, GingleInitiateWithNoCryptoFailsWhenSecureRequired) { 3315 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3316 test->ExpectCrypto(cricket::SEC_REQUIRED); 3317 test->TestBadIncomingInitiate(kGingleInitiate); 3318} 3319 3320// Offer has crypto and session is secure, expect crypto in the answer. 3321TEST(MediaSessionTest, GingleInitiateWithCryptoWhenSecureEnabled) { 3322 talk_base::scoped_ptr<buzz::XmlElement> elem; 3323 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3324 test->ExpectCrypto(cricket::SEC_ENABLED); 3325 test->TestGoodIncomingInitiate( 3326 AddEncryption(kGingleInitiate, kGingleCryptoOffer), 3327 VideoCallOptions(), 3328 elem.use()); 3329} 3330 3331// Offer has crypto and session is secure required, expect crypto in 3332// the answer. 3333TEST(MediaSessionTest, GingleInitiateWithCryptoWhenSecureRequired) { 3334 talk_base::scoped_ptr<buzz::XmlElement> elem; 3335 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3336 test->ExpectCrypto(cricket::SEC_REQUIRED); 3337 test->TestGoodIncomingInitiate( 3338 AddEncryption(kGingleInitiate, kGingleCryptoOffer), 3339 VideoCallOptions(), 3340 elem.use()); 3341} 3342 3343// Offer has unsupported crypto and session is secure, no crypto in 3344// the answer. 3345TEST(MediaSessionTest, GingleInitiateWithUnsupportedCrypto) { 3346 talk_base::scoped_ptr<buzz::XmlElement> elem; 3347 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3348 test->MakeSignalingSecure(cricket::SEC_ENABLED); 3349 test->TestGoodIncomingInitiate( 3350 AddEncryption(kGingleInitiate, kGingleUnsupportedCryptoOffer), 3351 VideoCallOptions(), 3352 elem.use()); 3353} 3354 3355// Offer has unsupported REQUIRED crypto and session is not secure, fail. 3356TEST(MediaSessionTest, GingleInitiateWithRequiredUnsupportedCrypto) { 3357 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3358 test->TestBadIncomingInitiate( 3359 AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer)); 3360} 3361 3362// Offer has unsupported REQUIRED crypto and session is secure, fail. 3363TEST(MediaSessionTest, GingleInitiateWithRequiredUnsupportedCryptoWhenSecure) { 3364 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3365 test->MakeSignalingSecure(cricket::SEC_ENABLED); 3366 test->TestBadIncomingInitiate( 3367 AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer)); 3368} 3369 3370// Offer has unsupported REQUIRED crypto and session is required secure, fail. 3371TEST(MediaSessionTest, 3372 GingleInitiateWithRequiredUnsupportedCryptoWhenSecureRequired) { 3373 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3374 test->MakeSignalingSecure(cricket::SEC_REQUIRED); 3375 test->TestBadIncomingInitiate( 3376 AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer)); 3377} 3378 3379TEST(MediaSessionTest, GingleGoodOutgoingInitiateWithCrypto) { 3380 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3381 test->ExpectCrypto(cricket::SEC_ENABLED); 3382 test->TestGoodOutgoingInitiate(AudioCallOptions()); 3383} 3384 3385TEST(MediaSessionTest, GingleGoodOutgoingInitiateWithCryptoRequired) { 3386 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3387 test->ExpectCrypto(cricket::SEC_REQUIRED); 3388 test->TestGoodOutgoingInitiate(AudioCallOptions()); 3389} 3390 3391TEST(MediaSessionTest, GingleIncomingAcceptWithSsrcs) { 3392 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3393 cricket::CallOptions options = VideoCallOptions(); 3394 options.is_muc = true; 3395 test->TestIncomingAcceptWithSsrcs(kGingleAcceptWithSsrcs, options); 3396} 3397 3398TEST(MediaSessionTest, GingleGoodOutgoingInitiateWithRtpData) { 3399 talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest()); 3400 cricket::CallOptions options; 3401 options.data_channel_type = cricket::DCT_RTP; 3402 test->ExpectCrypto(cricket::SEC_ENABLED); 3403 test->TestGoodOutgoingInitiate(options); 3404} 3405