blob: 1ad93722bda5f3682727d43a8f9d984e17699604 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
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
wu@webrtc.org91053e72013-08-10 07:18:04 +000044using 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
henrike@webrtc.org28e20752013-07-10 00:45:36 +000054// 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
wu@webrtc.org91053e72013-08-10 07:18:04 +0000390const 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
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000426const 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;
894const uint32 kDataSid = 0;
895// Note that this message does not specify a session ID. It must be populated
896// before use.
897const std::string kGingleAcceptWithSsrcs(
898 "<iq xmlns='jabber:client' from='me@mydomain.com' " \
899 " to='user@domain.com/resource' type='set' id='150'> " \
900 " <session xmlns='http://www.google.com/session' type='accept' " \
901 " initiator='me@domain.com/resource'> " \
902 " <description xmlns='http://www.google.com/session/video'> " \
903 " <payload-type xmlns='http://www.google.com/session/phone' " \
904 " id='103' name='ISAC' clockrate='16000' /> " \
905 " <payload-type xmlns='http://www.google.com/session/phone' " \
906 " id='104' name='ISAC' clockrate='32000' /> " \
907 " <src-id xmlns='http://www.google.com/session/phone'> " \
908 " 4294967295</src-id> " \
909 " <src-id>87654321</src-id> " \
910 " </description> " \
911 " </session> " \
912 "</iq> ");
913
914const std::string kJingleAcceptWithSsrcs(
915 "<iq xmlns='jabber:client' from='me@mydomain.com' " \
916 " to='user@domain.com/resource' type='set' id='150'> " \
917 " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \
918 " initiator='me@domain.com/resource'> " \
919 " <content name='audio'> " \
920 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
921 " media='audio' ssrc='4294967295'> " \
922 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
923 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
924 " </description> " \
925 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
926 " </content> " \
927 " <content name='video'> " \
928 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
929 " media='video' ssrc='87654321'> " \
930 " </description> " \
931 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
932 " </content> " \
933 " </jingle> " \
934 "</iq> ");
935
936const std::string kJingleAcceptWithRtpDataSsrcs(
937 "<iq xmlns='jabber:client' from='me@mydomain.com' " \
938 " to='user@domain.com/resource' type='set' id='150'> " \
939 " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \
940 " initiator='me@domain.com/resource'> " \
941 " <content name='audio'> " \
942 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
943 " media='audio' ssrc='4294967295'> " \
944 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
945 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
946 " </description> " \
947 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
948 " </content> " \
949 " <content name='video'> " \
950 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
951 " media='video' ssrc='87654321'> " \
952 " </description> " \
953 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
954 " </content> " \
955 " <content name='data'> " \
956 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
957 " media='data' ssrc='1010101'> " \
958 " </description> " \
959 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
960 " </content> " \
961 " </jingle> " \
962 "</iq> ");
963
964const std::string kJingleAcceptWithSctpData(
965 "<iq xmlns='jabber:client' from='me@mydomain.com' " \
966 " to='user@domain.com/resource' type='set' id='150'> " \
967 " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \
968 " initiator='me@domain.com/resource'> " \
969 " <content name='audio'> " \
970 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
971 " media='audio' ssrc='4294967295'> " \
972 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
973 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
974 " </description> " \
975 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
976 " </content> " \
977 " <content name='video'> " \
978 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
979 " media='video' ssrc='87654321'> " \
980 " </description> " \
981 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
982 " </content> " \
983 " <content name='data'> " \
984 " <description xmlns='google:jingle:sctp'> " \
985 " <stream sid='1'/> " \
986 " </description> " \
987 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
988 " </content> " \
989 " </jingle> " \
990 "</iq> ");
991
992std::string JingleView(const std::string& ssrc,
993 const std::string& width,
994 const std::string& height,
995 const std::string& framerate) {
996 // We have some slightly weird whitespace formatting to make the
997 // actual XML generated match the expected XML here.
998 return \
999 "<cli:iq"
1000 " to='me@mydomain.com'"
1001 " type='set'"
1002 " xmlns:cli='jabber:client'>"
1003 "<jingle"
1004 " xmlns='urn:xmpp:jingle:1'"
1005 " action='session-info'"
1006 " sid=''>"
1007 "<view xmlns='google:jingle'"
1008 " name='video'"
1009 " type='static'"
1010 " ssrc='" + ssrc + "'>"
1011 "<params"
1012 " width='" + width + "'"
1013 " height='" + height + "'"
1014 " framerate='" + framerate + "'"
1015 " preference='0'/>"
1016 "</view>"
1017 "</jingle>"
1018 "</cli:iq>";
1019}
1020
1021std::string JingleStreamAdd(const std::string& content_name,
1022 const std::string& nick,
1023 const std::string& name,
1024 const std::string& ssrc) {
1025 return \
1026 "<iq"
1027 " xmlns='jabber:client'"
1028 " from='me@mydomain.com'"
1029 " to='user@domain.com/resource'"
1030 " type='set'"
1031 " id='150'>"
1032 " <jingle"
1033 " xmlns='urn:xmpp:jingle:1'"
1034 " action='description-info'>"
1035 " <content"
1036 " xmlns='urn:xmpp:jingle:1'"
1037 " name='" + content_name + "'>"
1038 " <description"
1039 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
1040 " media='" + content_name + "'>"
1041 " <streams"
1042 " xmlns='google:jingle'>"
1043 " <stream"
1044 " nick='" + nick + "'"
1045 " name='" + name + "'>"
1046 " <ssrc>" + ssrc + "</ssrc>"
1047 " </stream>"
1048 " </streams>"
1049 " </description>"
1050 " </content>"
1051 " </jingle>"
1052 "</iq>";
1053}
1054
1055std::string JingleOutboundStreamRemove(const std::string& sid,
1056 const std::string& content_name,
1057 const std::string& name) {
1058 return \
1059 "<cli:iq"
1060 " to='me@mydomain.com'"
1061 " type='set'"
1062 " xmlns:cli='jabber:client'>"
1063 "<jingle"
1064 " xmlns='urn:xmpp:jingle:1'"
1065 " action='description-info'"
1066 " sid='" + sid + "'>"
1067 "<content"
1068 " name='" + content_name + "'"
1069 " creator='initiator'>"
1070 "<description"
1071 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
1072 " media='" + content_name + "'>"
1073 "<streams"
1074 " xmlns='google:jingle'>"
1075 "<stream"
1076 " name='" + name + "'>"
1077 "</stream>"
1078 "</streams>"
1079 "</description>"
1080 "</content>"
1081 "</jingle>"
1082 "</cli:iq>";
1083}
1084
1085std::string JingleOutboundStreamAdd(const std::string& sid,
1086 const std::string& content_name,
1087 const std::string& name,
1088 const std::string& ssrc) {
1089 return \
1090 "<cli:iq"
1091 " to='me@mydomain.com'"
1092 " type='set'"
1093 " xmlns:cli='jabber:client'>"
1094 "<jingle"
1095 " xmlns='urn:xmpp:jingle:1'"
1096 " action='description-info'"
1097 " sid='" + sid + "'>"
1098 "<content"
1099 " name='" + content_name + "'"
1100 " creator='initiator'>"
1101 "<description"
1102 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
1103 " media='" + content_name + "'>"
1104 "<streams"
1105 " xmlns='google:jingle'>"
1106 "<stream"
1107 " name='" + name + "'>"
1108 "<ssrc>" + ssrc + "</ssrc>"
1109 "</stream>"
1110 "</streams>"
1111 "</description>"
1112 "</content>"
1113 "</jingle>"
1114 "</cli:iq>";
1115}
1116
1117std::string JingleStreamAddWithoutSsrc(const std::string& content_name,
1118 const std::string& nick,
1119 const std::string& name) {
1120 return \
1121 "<iq"
1122 " xmlns='jabber:client'"
1123 " from='me@mydomain.com'"
1124 " to='user@domain.com/resource'"
1125 " type='set'"
1126 " id='150'>"
1127 " <jingle"
1128 " xmlns='urn:xmpp:jingle:1'"
1129 " action='description-info'>"
1130 " <content"
1131 " xmlns='urn:xmpp:jingle:1'"
1132 " name='" + content_name + "'>"
1133 " <description"
1134 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
1135 " media='" + content_name + "'>"
1136 " <streams"
1137 " xmlns='google:jingle'>"
1138 " <stream"
1139 " nick='" + nick + "'"
1140 " name='" + name + "'>"
1141 " </stream>"
1142 " </streams>"
1143 " </description>"
1144 " </content>"
1145 " </jingle>"
1146 "</iq>";
1147}
1148
1149std::string JingleStreamRemove(const std::string& content_name,
1150 const std::string& nick,
1151 const std::string& name) {
1152 return \
1153 "<iq"
1154 " xmlns='jabber:client'"
1155 " from='me@mydomain.com'"
1156 " to='user@domain.com/resource'"
1157 " type='set'"
1158 " id='150'>"
1159 " <jingle"
1160 " xmlns='urn:xmpp:jingle:1'"
1161 " action='description-info'>"
1162 " <content"
1163 " xmlns='urn:xmpp:jingle:1'"
1164 " name='" + content_name + "'>"
1165 " <description"
1166 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
1167 " media='" + content_name + "'>"
1168 " <streams"
1169 " xmlns='google:jingle'>"
1170 " <stream"
1171 " nick='" + nick + "'"
1172 " name='" + name + "'/>"
1173 " </streams>"
1174 " </description>"
1175 " </content>"
1176 " </jingle>"
1177 "</iq>";
1178}
1179
1180// Convenience function to get CallOptions that have audio enabled,
1181// but not video or data.
1182static cricket::CallOptions AudioCallOptions() {
1183 cricket::CallOptions options;
1184 options.has_audio = true;
1185 options.has_video = false;
1186 options.data_channel_type = cricket::DCT_NONE;
1187 return options;
1188}
1189
1190// Convenience function to get CallOptions that have audio and video
1191// enabled, but not data.
1192static cricket::CallOptions VideoCallOptions() {
1193 cricket::CallOptions options;
1194 options.has_audio = true;
1195 options.has_video = true;
1196 options.data_channel_type = cricket::DCT_NONE;
1197 return options;
1198}
1199
wu@webrtc.org91053e72013-08-10 07:18:04 +00001200static buzz::XmlElement* CopyElement(const buzz::XmlElement* elem) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001201 return new buzz::XmlElement(*elem);
1202}
1203
1204static std::string AddEncryption(std::string stanza, std::string encryption) {
1205 std::string::size_type pos = stanza.find("</description>");
1206 while (pos != std::string::npos) {
1207 stanza = stanza.insert(pos, encryption);
1208 pos = stanza.find("</description>", pos + encryption.length() + 1);
1209 }
1210 return stanza;
1211}
1212
wu@webrtc.org91053e72013-08-10 07:18:04 +00001213static int IntFromJingleCodecParameter(const buzz::XmlElement* parameter,
1214 const std::string& expected_name) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001215 if (parameter) {
1216 const std::string& actual_name =
1217 parameter->Attr(cricket::QN_PAYLOADTYPE_PARAMETER_NAME);
1218
1219 EXPECT_EQ(expected_name, actual_name)
1220 << "wrong parameter name. Expected '"
1221 << expected_name << "'. Actually '"
1222 << actual_name << "'.";
1223
1224 return atoi(parameter->Attr(
1225 cricket::QN_PAYLOADTYPE_PARAMETER_VALUE).c_str());
1226 }
1227 return 0;
1228}
1229
wu@webrtc.org91053e72013-08-10 07:18:04 +00001230template <class CodecClass, class DescriptionClass>
1231static void VerifyCodecFbParams(const FeedbackParams& expected,
1232 const DescriptionClass* desc) {
1233 if (!expected.params().empty()) {
1234 ASSERT_TRUE(desc != NULL);
1235 const std::vector<CodecClass> codecs = desc->codecs();
1236 for (size_t i = 0; i < codecs.size(); ++i) {
1237 EXPECT_EQ(expected, codecs[i].feedback_params);
1238 }
1239 }
1240}
1241
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001242// Parses and extracts payload and codec info from test XML. Since
1243// that XML will be in various contents (Gingle and Jingle), we need an
1244// abstract parser with one concrete implementation per XML content.
1245class MediaSessionTestParser {
1246 public:
1247 virtual buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) = 0;
1248 virtual buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) = 0;
1249 virtual buzz::XmlElement* NextContent(buzz::XmlElement* content) = 0;
1250 virtual buzz::XmlElement* PayloadTypeFromContent(
1251 buzz::XmlElement* content) = 0;
1252 virtual buzz::XmlElement* NextFromPayloadType(
1253 buzz::XmlElement* payload_type) = 0;
1254 virtual cricket::AudioCodec AudioCodecFromPayloadType(
1255 const buzz::XmlElement* payload_type) = 0;
1256 virtual cricket::VideoCodec VideoCodecFromPayloadType(
1257 const buzz::XmlElement* payload_type) = 0;
1258 virtual cricket::DataCodec DataCodecFromPayloadType(
1259 const buzz::XmlElement* payload_type) = 0;
1260 virtual buzz::XmlElement* EncryptionFromContent(
1261 buzz::XmlElement* content) = 0;
1262 virtual buzz::XmlElement* NextFromEncryption(
1263 buzz::XmlElement* encryption) = 0;
1264 virtual const buzz::XmlElement* BandwidthFromContent(
1265 buzz::XmlElement* content) = 0;
1266 virtual const buzz::XmlElement* RtcpMuxFromContent(
1267 buzz::XmlElement* content) = 0;
1268 virtual bool ActionIsTerminate(const buzz::XmlElement* action) = 0;
1269 virtual ~MediaSessionTestParser() {}
1270};
1271
1272class JingleSessionTestParser : public MediaSessionTestParser {
1273 public:
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001274 JingleSessionTestParser() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001275
1276 ~JingleSessionTestParser() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001277 }
1278
1279 buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1280 return stanza->FirstNamed(cricket::QN_JINGLE);
1281 }
1282
1283 buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
1284 // We need to be able to use multiple contents, but the action
1285 // gets deleted before we can call NextContent, so we need to
1286 // stash away a copy.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001287 action_.reset(CopyElement(action));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001288 return action_->FirstNamed(cricket::QN_JINGLE_CONTENT);
1289 }
1290
1291 buzz::XmlElement* NextContent(buzz::XmlElement* content) {
1292 // For some reason, content->NextNamed(cricket::QN_JINGLE_CONTENT)
1293 // doesn't work.
1294 return action_->FirstNamed(cricket::QN_JINGLE_CONTENT)
1295 ->NextNamed(cricket::QN_JINGLE_CONTENT);
1296 }
1297
1298 buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) {
1299 buzz::XmlElement* content_desc =
1300 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
1301 if (!content_desc)
1302 return NULL;
1303
1304 return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
1305 }
1306
1307 buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1308 return payload_type->NextNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
1309 }
1310
wu@webrtc.org91053e72013-08-10 07:18:04 +00001311 void ParsePayloadTypeFeedbackParameters(const buzz::XmlElement* element,
1312 FeedbackParams* params) {
1313 const buzz::XmlElement* param =
1314 element->FirstNamed(cricket::QN_JINGLE_RTCP_FB);
1315 for (; param != NULL;
1316 param = param->NextNamed(cricket::QN_JINGLE_RTCP_FB)) {
1317 std::string type = param->Attr(cricket::QN_TYPE);
1318 std::string subtype = param->Attr(cricket::QN_SUBTYPE);
1319 if (!type.empty()) {
1320 params->Add(FeedbackParam(type, subtype));
1321 }
1322 }
1323 }
1324
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001325 cricket::AudioCodec AudioCodecFromPayloadType(
1326 const buzz::XmlElement* payload_type) {
1327 int id = 0;
1328 if (payload_type->HasAttr(cricket::QN_ID))
1329 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1330
1331 std::string name;
1332 if (payload_type->HasAttr(cricket::QN_NAME))
1333 name = payload_type->Attr(cricket::QN_NAME);
1334
1335 int clockrate = 0;
1336 if (payload_type->HasAttr(cricket::QN_CLOCKRATE))
1337 clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str());
1338
1339 int bitrate = IntFromJingleCodecParameter(
1340 payload_type->FirstNamed(cricket::QN_PARAMETER), "bitrate");
1341
1342 int channels = 1;
1343 if (payload_type->HasAttr(cricket::QN_CHANNELS))
1344 channels = atoi(payload_type->Attr(
1345 cricket::QN_CHANNELS).c_str());
1346
wu@webrtc.org91053e72013-08-10 07:18:04 +00001347 AudioCodec codec = AudioCodec(id, name, clockrate, bitrate, channels, 0);
1348 ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
1349 return codec;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001350 }
1351
1352 cricket::VideoCodec VideoCodecFromPayloadType(
1353 const buzz::XmlElement* payload_type) {
1354 int id = 0;
1355 if (payload_type->HasAttr(cricket::QN_ID))
1356 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1357
1358 std::string name;
1359 if (payload_type->HasAttr(cricket::QN_NAME))
1360 name = payload_type->Attr(cricket::QN_NAME);
1361
1362 int width = 0;
1363 int height = 0;
1364 int framerate = 0;
1365 const buzz::XmlElement* param =
1366 payload_type->FirstNamed(cricket::QN_PARAMETER);
1367 if (param) {
1368 width = IntFromJingleCodecParameter(param, "width");
1369 param = param->NextNamed(cricket::QN_PARAMETER);
1370 if (param) {
1371 height = IntFromJingleCodecParameter(param, "height");
1372 param = param->NextNamed(cricket::QN_PARAMETER);
1373 if (param) {
1374 framerate = IntFromJingleCodecParameter(param, "framerate");
1375 }
1376 }
1377 }
wu@webrtc.org91053e72013-08-10 07:18:04 +00001378 VideoCodec codec = VideoCodec(id, name, width, height, framerate, 0);
1379 ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
1380 return codec;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001381 }
1382
1383 cricket::DataCodec DataCodecFromPayloadType(
1384 const buzz::XmlElement* payload_type) {
1385 int id = 0;
1386 if (payload_type->HasAttr(cricket::QN_ID))
1387 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1388
1389 std::string name;
1390 if (payload_type->HasAttr(cricket::QN_NAME))
1391 name = payload_type->Attr(cricket::QN_NAME);
1392
wu@webrtc.org91053e72013-08-10 07:18:04 +00001393 DataCodec codec = DataCodec(id, name, 0);
1394 ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
1395 return codec;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001396 }
1397
1398 bool ActionIsTerminate(const buzz::XmlElement* action) {
1399 return (action->HasAttr(cricket::QN_ACTION) &&
1400 action->Attr(cricket::QN_ACTION) == "session-terminate");
1401 }
1402
1403 buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
1404 buzz::XmlElement* content_desc =
1405 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
1406 if (!content_desc)
1407 return NULL;
1408
1409 return content_desc->FirstNamed(cricket::QN_ENCRYPTION);
1410 }
1411
1412 buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1413 return encryption->NextNamed(cricket::QN_ENCRYPTION);
1414 }
1415
1416 const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
1417 buzz::XmlElement* content_desc =
1418 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
1419 if (!content_desc)
1420 return NULL;
1421
1422 return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_BANDWIDTH);
1423 }
1424
1425 const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
1426 return content->FirstNamed(cricket::QN_JINGLE_RTCP_MUX);
1427 }
1428
1429 private:
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001430 talk_base::scoped_ptr<buzz::XmlElement> action_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001431};
1432
1433class GingleSessionTestParser : public MediaSessionTestParser {
1434 public:
1435 GingleSessionTestParser() : found_content_count_(0) {}
1436
1437 buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1438 return stanza->FirstNamed(cricket::QN_GINGLE_SESSION);
1439 }
1440
1441 buzz::XmlElement* ContentFromAction(buzz::XmlElement* session) {
1442 buzz::XmlElement* content =
1443 session->FirstNamed(cricket::QN_GINGLE_AUDIO_CONTENT);
1444 if (content == NULL)
1445 content = session->FirstNamed(cricket::QN_GINGLE_VIDEO_CONTENT);
1446 return content;
1447 }
1448
1449 // Assumes contents are in order of audio, and then video.
1450 buzz::XmlElement* NextContent(buzz::XmlElement* content) {
1451 found_content_count_++;
1452 return content;
1453 }
1454
1455 buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) {
1456 if (found_content_count_ > 0) {
1457 return content->FirstNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE);
1458 } else {
1459 return content->FirstNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE);
1460 }
1461 }
1462
1463 buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1464 if (found_content_count_ > 0) {
1465 return payload_type->NextNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE);
1466 } else {
1467 return payload_type->NextNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE);
1468 }
1469 }
1470
1471 cricket::AudioCodec AudioCodecFromPayloadType(
1472 const buzz::XmlElement* payload_type) {
1473 int id = 0;
1474 if (payload_type->HasAttr(cricket::QN_ID))
1475 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1476
1477 std::string name;
1478 if (payload_type->HasAttr(cricket::QN_NAME))
1479 name = payload_type->Attr(cricket::QN_NAME);
1480
1481 int clockrate = 0;
1482 if (payload_type->HasAttr(cricket::QN_CLOCKRATE))
1483 clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str());
1484
1485 int bitrate = 0;
1486 if (payload_type->HasAttr(cricket::QN_BITRATE))
1487 bitrate = atoi(payload_type->Attr(cricket::QN_BITRATE).c_str());
1488
1489 int channels = 1;
1490 if (payload_type->HasAttr(cricket::QN_CHANNELS))
1491 channels = atoi(payload_type->Attr(cricket::QN_CHANNELS).c_str());
1492
1493 return cricket::AudioCodec(id, name, clockrate, bitrate, channels, 0);
1494 }
1495
1496 cricket::VideoCodec VideoCodecFromPayloadType(
1497 const buzz::XmlElement* payload_type) {
1498 int id = 0;
1499 if (payload_type->HasAttr(cricket::QN_ID))
1500 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1501
1502 std::string name;
1503 if (payload_type->HasAttr(cricket::QN_NAME))
1504 name = payload_type->Attr(cricket::QN_NAME);
1505
1506 int width = 0;
1507 if (payload_type->HasAttr(cricket::QN_WIDTH))
1508 width = atoi(payload_type->Attr(cricket::QN_WIDTH).c_str());
1509
1510 int height = 0;
1511 if (payload_type->HasAttr(cricket::QN_HEIGHT))
1512 height = atoi(payload_type->Attr(cricket::QN_HEIGHT).c_str());
1513
1514 int framerate = 1;
1515 if (payload_type->HasAttr(cricket::QN_FRAMERATE))
1516 framerate = atoi(payload_type->Attr(cricket::QN_FRAMERATE).c_str());
1517
1518 return cricket::VideoCodec(id, name, width, height, framerate, 0);
1519 }
1520
1521 cricket::DataCodec DataCodecFromPayloadType(
1522 const buzz::XmlElement* payload_type) {
1523 // Gingle can't do data codecs.
1524 return cricket::DataCodec(0, "", 0);
1525 }
1526
1527 buzz::XmlElement* EncryptionFromContent(
1528 buzz::XmlElement* content) {
1529 return content->FirstNamed(cricket::QN_ENCRYPTION);
1530 }
1531
1532 buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1533 return encryption->NextNamed(cricket::QN_ENCRYPTION);
1534 }
1535
1536 const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
1537 return content->FirstNamed(cricket::QN_GINGLE_VIDEO_BANDWIDTH);
1538 }
1539
1540 const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
1541 return NULL;
1542 }
1543
1544 bool ActionIsTerminate(const buzz::XmlElement* session) {
1545 return (session->HasAttr(buzz::QN_TYPE) &&
1546 session->Attr(buzz::QN_TYPE) == "terminate");
1547 }
1548
1549 int found_content_count_;
1550};
1551
1552class MediaSessionClientTest : public sigslot::has_slots<> {
1553 public:
1554 explicit MediaSessionClientTest(MediaSessionTestParser* parser,
1555 cricket::SignalingProtocol initial_protocol) {
1556 nm_ = new talk_base::BasicNetworkManager();
1557 pa_ = new cricket::BasicPortAllocator(nm_);
1558 sm_ = new cricket::SessionManager(pa_, NULL);
1559 fme_ = new cricket::FakeMediaEngine();
1560 fdme_ = new cricket::FakeDataEngine();
1561
wu@webrtc.org91053e72013-08-10 07:18:04 +00001562 FeedbackParams params_nack_fir;
1563 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm,
1564 cricket::kRtcpFbCcmParamFir));
1565 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack));
1566 FeedbackParams params_nack;
1567 params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack));
1568
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001569 std::vector<cricket::AudioCodec>
1570 audio_codecs(kAudioCodecs, kAudioCodecs + ARRAY_SIZE(kAudioCodecs));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001571 SetCodecFeedbackParams(&audio_codecs, params_nack);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001572 fme_->SetAudioCodecs(audio_codecs);
1573 std::vector<cricket::VideoCodec>
1574 video_codecs(kVideoCodecs, kVideoCodecs + ARRAY_SIZE(kVideoCodecs));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001575 SetCodecFeedbackParams(&video_codecs, params_nack_fir);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001576 fme_->SetVideoCodecs(video_codecs);
1577 std::vector<cricket::DataCodec>
1578 data_codecs(kDataCodecs, kDataCodecs + ARRAY_SIZE(kDataCodecs));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001579 SetCodecFeedbackParams(&data_codecs, params_nack);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001580 fdme_->SetDataCodecs(data_codecs);
1581
1582 client_ = new cricket::MediaSessionClient(
1583 buzz::Jid("user@domain.com/resource"), sm_,
1584 fme_, fdme_, new cricket::FakeDeviceManager());
1585 client_->session_manager()->SignalOutgoingMessage.connect(
1586 this, &MediaSessionClientTest::OnSendStanza);
1587 client_->session_manager()->SignalSessionCreate.connect(
1588 this, &MediaSessionClientTest::OnSessionCreate);
1589 client_->SignalCallCreate.connect(
1590 this, &MediaSessionClientTest::OnCallCreate);
1591 client_->SignalCallDestroy.connect(
1592 this, &MediaSessionClientTest::OnCallDestroy);
1593
1594 call_ = NULL;
1595 parser_ = parser;
1596 initial_protocol_ = initial_protocol;
1597 expect_incoming_crypto_ = false;
1598 expect_outgoing_crypto_ = false;
1599 expected_video_bandwidth_ = cricket::kAutoBandwidth;
1600 expected_video_rtcp_mux_ = false;
1601 }
1602
1603 ~MediaSessionClientTest() {
1604 delete client_;
1605 delete sm_;
1606 delete pa_;
1607 delete nm_;
1608 delete parser_;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001609 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001610 }
1611
1612 buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1613 return parser_->ActionFromStanza(stanza);
1614 }
1615
1616 buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
1617 return parser_->ContentFromAction(action);
1618 }
1619
1620 buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* payload) {
1621 return parser_->PayloadTypeFromContent(payload);
1622 }
1623
1624 buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1625 return parser_->NextFromPayloadType(payload_type);
1626 }
1627
1628 buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
1629 return parser_->EncryptionFromContent(content);
1630 }
1631
1632 buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1633 return parser_->NextFromEncryption(encryption);
1634 }
1635
1636 cricket::AudioCodec AudioCodecFromPayloadType(
1637 const buzz::XmlElement* payload_type) {
1638 return parser_->AudioCodecFromPayloadType(payload_type);
1639 }
1640
wu@webrtc.org91053e72013-08-10 07:18:04 +00001641 cricket::VideoCodec VideoCodecFromPayloadType(
1642 const buzz::XmlElement* payload_type) {
1643 return parser_->VideoCodecFromPayloadType(payload_type);
1644 }
1645
1646 cricket::DataCodec DataCodecFromPayloadType(
1647 const buzz::XmlElement* payload_type) {
1648 return parser_->DataCodecFromPayloadType(payload_type);
1649 }
1650
1651 const AudioContentDescription* GetFirstAudioContentDescription(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001652 const cricket::SessionDescription* sdesc) {
1653 const cricket::ContentInfo* content =
1654 cricket::GetFirstAudioContent(sdesc);
1655 if (content == NULL)
1656 return NULL;
wu@webrtc.org91053e72013-08-10 07:18:04 +00001657 return static_cast<const AudioContentDescription*>(content->description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001658 }
1659
1660 const cricket::VideoContentDescription* GetFirstVideoContentDescription(
1661 const cricket::SessionDescription* sdesc) {
1662 const cricket::ContentInfo* content =
1663 cricket::GetFirstVideoContent(sdesc);
1664 if (content == NULL)
1665 return NULL;
1666 return static_cast<const cricket::VideoContentDescription*>(
1667 content->description);
1668 }
1669
1670 void CheckCryptoFromGoodIncomingInitiate(const cricket::Session* session) {
1671 ASSERT_TRUE(session != NULL);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001672 const AudioContentDescription* content =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001673 GetFirstAudioContentDescription(session->remote_description());
1674 ASSERT_TRUE(content != NULL);
1675 ASSERT_EQ(2U, content->cryptos().size());
1676 ASSERT_EQ(145, content->cryptos()[0].tag);
1677 ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite);
1678 ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9",
1679 content->cryptos()[0].key_params);
1680 ASSERT_EQ(51, content->cryptos()[1].tag);
1681 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", content->cryptos()[1].cipher_suite);
1682 ASSERT_EQ("inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy",
1683 content->cryptos()[1].key_params);
1684 }
1685
1686 void CheckCryptoForGoodOutgoingAccept(const cricket::Session* session) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001687 const AudioContentDescription* content =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001688 GetFirstAudioContentDescription(session->local_description());
1689 ASSERT_EQ(1U, content->cryptos().size());
1690 ASSERT_EQ(145, content->cryptos()[0].tag);
1691 ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite);
1692 ASSERT_EQ(47U, content->cryptos()[0].key_params.size());
1693 }
1694
1695 void CheckBadCryptoFromIncomingInitiate(const cricket::Session* session) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001696 const AudioContentDescription* content =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001697 GetFirstAudioContentDescription(session->remote_description());
1698 ASSERT_EQ(1U, content->cryptos().size());
1699 ASSERT_EQ(145, content->cryptos()[0].tag);
1700 ASSERT_EQ("NOT_SUPPORTED", content->cryptos()[0].cipher_suite);
1701 ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9",
1702 content->cryptos()[0].key_params);
1703 }
1704
1705 void CheckNoCryptoForOutgoingAccept(const cricket::Session* session) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001706 const AudioContentDescription* content =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001707 GetFirstAudioContentDescription(session->local_description());
1708 ASSERT_TRUE(content->cryptos().empty());
1709 }
1710
wu@webrtc.org91053e72013-08-10 07:18:04 +00001711 void CheckRtcpFb(const cricket::SessionDescription* sdesc) {
1712 VerifyCodecFbParams<AudioCodec>(expected_audio_fb_params_,
1713 GetFirstAudioContentDescription(sdesc));
1714
1715 VerifyCodecFbParams<VideoCodec>(expected_video_fb_params_,
1716 GetFirstVideoContentDescription(sdesc));
1717
1718 VerifyCodecFbParams<DataCodec>(expected_data_fb_params_,
1719 GetFirstDataContentDescription(sdesc));
1720 }
1721
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001722 void CheckVideoBandwidth(int expected_bandwidth,
1723 const cricket::SessionDescription* sdesc) {
1724 const cricket::VideoContentDescription* video =
1725 GetFirstVideoContentDescription(sdesc);
1726 if (video != NULL) {
1727 ASSERT_EQ(expected_bandwidth, video->bandwidth());
1728 }
1729 }
1730
1731 void CheckVideoRtcpMux(bool expected_video_rtcp_mux,
1732 const cricket::SessionDescription* sdesc) {
1733 const cricket::VideoContentDescription* video =
1734 GetFirstVideoContentDescription(sdesc);
1735 if (video != NULL) {
1736 ASSERT_EQ(expected_video_rtcp_mux, video->rtcp_mux());
1737 }
1738 }
1739
1740 virtual void CheckRtpDataContent(buzz::XmlElement* content) {
1741 if (initial_protocol_) {
1742 // Gingle can not write out data content.
1743 return;
1744 }
1745
1746 buzz::XmlElement* e = PayloadTypeFromContent(content);
1747 ASSERT_TRUE(e != NULL);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001748 cricket::DataCodec codec = DataCodecFromPayloadType(e);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001749 EXPECT_EQ(127, codec.id);
1750 EXPECT_EQ("google-data", codec.name);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001751 EXPECT_EQ(expected_data_fb_params_, codec.feedback_params);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001752
1753 CheckDataRtcpMux(true, call_->sessions()[0]->local_description());
1754 CheckDataRtcpMux(true, call_->sessions()[0]->remote_description());
1755 if (expect_outgoing_crypto_) {
1756 content = parser_->NextContent(content);
1757 buzz::XmlElement* encryption = EncryptionFromContent(content);
1758 ASSERT_TRUE(encryption != NULL);
1759 // TODO(pthatcher): Check encryption parameters?
1760 }
1761 }
1762
1763 virtual void CheckSctpDataContent(buzz::XmlElement* content) {
1764 if (initial_protocol_) {
1765 // Gingle can not write out data content.
1766 return;
1767 }
1768
1769 buzz::XmlElement* payload_type = PayloadTypeFromContent(content);
1770 ASSERT_TRUE(payload_type == NULL);
1771 buzz::XmlElement* encryption = EncryptionFromContent(content);
1772 ASSERT_TRUE(encryption == NULL);
1773 // TODO(pthatcher): Check for <streams>.
1774 }
1775
1776 void CheckDataRtcpMux(bool expected_data_rtcp_mux,
1777 const cricket::SessionDescription* sdesc) {
1778 const cricket::DataContentDescription* data =
1779 GetFirstDataContentDescription(sdesc);
1780 if (data != NULL) {
1781 ASSERT_EQ(expected_data_rtcp_mux, data->rtcp_mux());
1782 }
1783 }
1784
1785 void CheckAudioSsrcForIncomingAccept(const cricket::Session* session) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001786 const AudioContentDescription* audio =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001787 GetFirstAudioContentDescription(session->remote_description());
1788 ASSERT_TRUE(audio != NULL);
1789 ASSERT_EQ(kAudioSsrc, audio->first_ssrc());
1790 }
1791
1792 void CheckVideoSsrcForIncomingAccept(const cricket::Session* session) {
1793 const cricket::VideoContentDescription* video =
1794 GetFirstVideoContentDescription(session->remote_description());
1795 ASSERT_TRUE(video != NULL);
1796 ASSERT_EQ(kVideoSsrc, video->first_ssrc());
1797 }
1798
1799 void CheckDataSsrcForIncomingAccept(const cricket::Session* session) {
1800 const cricket::DataContentDescription* data =
1801 GetFirstDataContentDescription(session->remote_description());
1802 ASSERT_TRUE(data != NULL);
1803 ASSERT_EQ(kDataSsrc, data->first_ssrc());
1804 }
1805
1806 void TestGoodIncomingInitiate(const std::string& initiate_string,
1807 const cricket::CallOptions& options,
1808 buzz::XmlElement** element) {
1809 *element = NULL;
1810
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001811 talk_base::scoped_ptr<buzz::XmlElement> el(
1812 buzz::XmlElement::ForStr(initiate_string));
1813 client_->session_manager()->OnIncomingMessage(el.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001814 ASSERT_TRUE(call_ != NULL);
1815 ASSERT_TRUE(call_->sessions()[0] != NULL);
1816 ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
1817 call_->sessions()[0]->state());
1818 ASSERT_EQ(1U, stanzas_.size());
1819 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1820 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1821 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001822 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001823 CheckVideoBandwidth(expected_video_bandwidth_,
1824 call_->sessions()[0]->remote_description());
1825 CheckVideoRtcpMux(expected_video_rtcp_mux_,
1826 call_->sessions()[0]->remote_description());
wu@webrtc.org91053e72013-08-10 07:18:04 +00001827 CheckRtcpFb(call_->sessions()[0]->remote_description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001828 if (expect_incoming_crypto_) {
1829 CheckCryptoFromGoodIncomingInitiate(call_->sessions()[0]);
1830 }
1831
1832 // TODO(pthatcher): Add tests for sending <bandwidth> in accept.
1833 call_->AcceptSession(call_->sessions()[0], options);
1834 ASSERT_EQ(cricket::Session::STATE_SENTACCEPT,
1835 call_->sessions()[0]->state());
1836 ASSERT_EQ(1U, stanzas_.size());
1837 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1838 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1839 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1840
1841 buzz::XmlElement* e = ActionFromStanza(stanzas_[0]);
1842 ASSERT_TRUE(e != NULL);
1843 ASSERT_TRUE(ContentFromAction(e) != NULL);
1844 *element = CopyElement(ContentFromAction(e));
1845 ASSERT_TRUE(*element != NULL);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001846 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001847 if (expect_outgoing_crypto_) {
1848 CheckCryptoForGoodOutgoingAccept(call_->sessions()[0]);
1849 }
1850
wu@webrtc.org91053e72013-08-10 07:18:04 +00001851 if (options.data_channel_type == cricket::DCT_RTP) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001852 CheckDataRtcpMux(true, call_->sessions()[0]->local_description());
1853 CheckDataRtcpMux(true, call_->sessions()[0]->remote_description());
1854 // TODO(pthatcher): Check rtcpmux and crypto?
1855 }
1856
1857 call_->Terminate();
1858 ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
1859 call_->sessions()[0]->state());
1860 ASSERT_EQ(1U, stanzas_.size());
1861 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1862 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1863 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1864 e = ActionFromStanza(stanzas_[0]);
1865 ASSERT_TRUE(e != NULL);
1866 ASSERT_TRUE(parser_->ActionIsTerminate(e));
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001867 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001868 }
1869
1870 void TestRejectOffer(const std::string &initiate_string,
1871 const cricket::CallOptions& options,
1872 buzz::XmlElement** element) {
1873 *element = NULL;
1874
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001875 talk_base::scoped_ptr<buzz::XmlElement> el(
1876 buzz::XmlElement::ForStr(initiate_string));
1877 client_->session_manager()->OnIncomingMessage(el.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001878 ASSERT_TRUE(call_ != NULL);
1879 ASSERT_TRUE(call_->sessions()[0] != NULL);
1880 ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
1881 call_->sessions()[0]->state());
1882 ASSERT_EQ(1U, stanzas_.size());
1883 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1884 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1885 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001886 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001887
1888 call_->AcceptSession(call_->sessions()[0], options);
1889 ASSERT_EQ(cricket::Session::STATE_SENTACCEPT,
1890 call_->sessions()[0]->state());
1891 ASSERT_EQ(1U, stanzas_.size());
1892 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1893 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1894 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1895
1896 buzz::XmlElement* e = ActionFromStanza(stanzas_[0]);
1897 ASSERT_TRUE(e != NULL);
1898 ASSERT_TRUE(ContentFromAction(e) != NULL);
1899 *element = CopyElement(ContentFromAction(e));
1900 ASSERT_TRUE(*element != NULL);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001901 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001902
1903 buzz::XmlElement* content = *element;
1904 // The NextContent method actually returns the second content. So we
1905 // can't handle the case when audio, video and data are all enabled. But
1906 // since we are testing rejection, it won't be the case.
1907 if (options.has_audio) {
1908 ASSERT_TRUE(content != NULL);
1909 ASSERT_EQ("test audio", content->Attr(buzz::QName("", "name")));
1910 content = parser_->NextContent(content);
1911 }
1912
1913 if (options.has_video) {
1914 ASSERT_TRUE(content != NULL);
1915 ASSERT_EQ("test video", content->Attr(buzz::QName("", "name")));
1916 content = parser_->NextContent(content);
1917 }
1918
1919 if (options.has_data()) {
1920 ASSERT_TRUE(content != NULL);
1921 ASSERT_EQ("test data", content->Attr(buzz::QName("", "name")));
1922 content = parser_->NextContent(content);
1923 }
1924
1925 call_->Terminate();
1926 ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
1927 call_->sessions()[0]->state());
1928 ASSERT_EQ(1U, stanzas_.size());
1929 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1930 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1931 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1932 e = ActionFromStanza(stanzas_[0]);
1933 ASSERT_TRUE(e != NULL);
1934 ASSERT_TRUE(parser_->ActionIsTerminate(e));
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001935 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001936 }
1937
1938 void TestBadIncomingInitiate(const std::string& initiate_string) {
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001939 talk_base::scoped_ptr<buzz::XmlElement> el(
1940 buzz::XmlElement::ForStr(initiate_string));
1941 client_->session_manager()->OnIncomingMessage(el.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001942 ASSERT_TRUE(call_ != NULL);
1943 ASSERT_TRUE(call_->sessions()[0] != NULL);
1944 ASSERT_EQ(cricket::Session::STATE_SENTREJECT,
1945 call_->sessions()[0]->state());
1946 ASSERT_EQ(2U, stanzas_.size());
1947 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1948 ASSERT_TRUE(stanzas_[1]->HasAttr(buzz::QN_TYPE));
1949 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[1]->Attr(buzz::QN_TYPE));
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001950 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001951 }
1952
wu@webrtc.org91053e72013-08-10 07:18:04 +00001953 void VerifyAudioCodec(const AudioCodec& codec, int id,
1954 const std::string& name, int clockrate,
1955 int bitrate, int channels) {
1956 ASSERT_EQ(id, codec.id);
1957 ASSERT_EQ(name, codec.name);
1958 ASSERT_EQ(clockrate, codec.clockrate);
1959 ASSERT_EQ(bitrate, codec.bitrate);
1960 ASSERT_EQ(channels, codec.channels);
1961 ASSERT_EQ(expected_audio_fb_params_, codec.feedback_params);
1962 }
1963
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001964 void TestGoodOutgoingInitiate(const cricket::CallOptions& options) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001965 if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
1966 // rtcp fb is only implemented for jingle.
1967 ExpectRtcpFb();
1968 }
1969
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001970 client_->CreateCall();
1971 ASSERT_TRUE(call_ != NULL);
1972 call_->InitiateSession(buzz::Jid("me@mydomain.com"),
1973 buzz::Jid("me@mydomain.com"), options);
1974 ASSERT_TRUE(call_->sessions()[0] != NULL);
1975 ASSERT_EQ(cricket::Session::STATE_SENTINITIATE,
1976 call_->sessions()[0]->state());
1977 ASSERT_EQ(1U, stanzas_.size());
1978 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1979 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1980 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1981 buzz::XmlElement* action = ActionFromStanza(stanzas_[0]);
1982 ASSERT_TRUE(action != NULL);
1983 buzz::XmlElement* content = ContentFromAction(action);
1984 ASSERT_TRUE(content != NULL);
1985
1986 buzz::XmlElement* e = PayloadTypeFromContent(content);
1987 ASSERT_TRUE(e != NULL);
1988 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001989 VerifyAudioCodec(codec, 103, "ISAC", 16000, 0, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001990
1991 e = NextFromPayloadType(e);
1992 ASSERT_TRUE(e != NULL);
1993 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001994 VerifyAudioCodec(codec, 104, "ISAC", 32000, 0, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001995
1996 e = NextFromPayloadType(e);
1997 ASSERT_TRUE(e != NULL);
1998 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001999 VerifyAudioCodec(codec, 119, "ISACLC", 16000, 40000, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002000
2001 e = NextFromPayloadType(e);
2002 ASSERT_TRUE(e != NULL);
2003 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002004 VerifyAudioCodec(codec, 99, "speex", 16000, 22000, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002005
2006 e = NextFromPayloadType(e);
2007 ASSERT_TRUE(e != NULL);
2008 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002009 VerifyAudioCodec(codec, 97, "IPCMWB", 16000, 80000, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002010
2011 e = NextFromPayloadType(e);
2012 ASSERT_TRUE(e != NULL);
2013 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002014 VerifyAudioCodec(codec, 9, "G722", 16000, 64000, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002015
2016 e = NextFromPayloadType(e);
2017 ASSERT_TRUE(e != NULL);
2018 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002019 VerifyAudioCodec(codec, 102, "iLBC", 8000, 13300, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002020
2021 e = NextFromPayloadType(e);
2022 ASSERT_TRUE(e != NULL);
2023 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002024 VerifyAudioCodec(codec, 98, "speex", 8000, 11000, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002025
2026 e = NextFromPayloadType(e);
2027 ASSERT_TRUE(e != NULL);
2028 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002029 VerifyAudioCodec(codec, 3, "GSM", 8000, 13000, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002030
2031 e = NextFromPayloadType(e);
2032 ASSERT_TRUE(e != NULL);
2033 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002034 VerifyAudioCodec(codec, 100, "EG711U", 8000, 64000, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002035
2036 e = NextFromPayloadType(e);
2037 ASSERT_TRUE(e != NULL);
2038 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002039 VerifyAudioCodec(codec, 101, "EG711A", 8000, 64000, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002040
2041 e = NextFromPayloadType(e);
2042 ASSERT_TRUE(e != NULL);
2043 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002044 VerifyAudioCodec(codec, 0, "PCMU", 8000, 64000, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002045
2046 e = NextFromPayloadType(e);
2047 ASSERT_TRUE(e != NULL);
2048 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002049 VerifyAudioCodec(codec, 8, "PCMA", 8000, 64000, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002050
2051 e = NextFromPayloadType(e);
2052 ASSERT_TRUE(e != NULL);
2053 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002054 VerifyAudioCodec(codec, 126, "CN", 32000, 0, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002055
2056 e = NextFromPayloadType(e);
2057 ASSERT_TRUE(e != NULL);
2058 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002059 VerifyAudioCodec(codec, 105, "CN", 16000, 0, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002060
2061 e = NextFromPayloadType(e);
2062 ASSERT_TRUE(e != NULL);
2063 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002064 VerifyAudioCodec(codec, 13, "CN", 8000, 0, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002065
2066 e = NextFromPayloadType(e);
2067 ASSERT_TRUE(e != NULL);
2068 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002069 VerifyAudioCodec(codec, 117, "red", 8000, 0, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002070
2071 e = NextFromPayloadType(e);
2072 ASSERT_TRUE(e != NULL);
2073 codec = AudioCodecFromPayloadType(e);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002074 VerifyAudioCodec(codec, 106, "telephone-event", 8000, 0, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002075
2076 e = NextFromPayloadType(e);
2077 ASSERT_TRUE(e == NULL);
2078
2079 if (expect_outgoing_crypto_) {
2080 buzz::XmlElement* encryption = EncryptionFromContent(content);
2081 ASSERT_TRUE(encryption != NULL);
2082
2083 if (client_->secure() == cricket::SEC_REQUIRED) {
2084 ASSERT_TRUE(cricket::GetXmlAttr(
2085 encryption, cricket::QN_ENCRYPTION_REQUIRED, false));
2086 }
2087
2088 if (content->Name().Namespace() == cricket::NS_GINGLE_AUDIO) {
2089 e = encryption->FirstNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE);
2090 ASSERT_TRUE(e != NULL);
2091 ASSERT_TRUE(
2092 e->NextNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE) == NULL);
2093 ASSERT_TRUE(
2094 e->FirstNamed(cricket::QN_GINGLE_VIDEO_CRYPTO_USAGE) == NULL);
2095 }
2096
2097 e = encryption->FirstNamed(cricket::QN_CRYPTO);
2098 ASSERT_TRUE(e != NULL);
2099 ASSERT_EQ("0", e->Attr(cricket::QN_CRYPTO_TAG));
2100 ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", e->Attr(cricket::QN_CRYPTO_SUITE));
2101 std::string key_0 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS);
2102 ASSERT_EQ(47U, key_0.length());
2103 ASSERT_EQ("inline:", key_0.substr(0, 7));
2104
2105 e = e->NextNamed(cricket::QN_CRYPTO);
2106 ASSERT_TRUE(e != NULL);
2107 ASSERT_EQ("1", e->Attr(cricket::QN_CRYPTO_TAG));
2108 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", e->Attr(cricket::QN_CRYPTO_SUITE));
2109 std::string key_1 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS);
2110 ASSERT_EQ(47U, key_1.length());
2111 ASSERT_EQ("inline:", key_1.substr(0, 7));
2112 ASSERT_NE(key_0, key_1);
2113
2114 encryption = NextFromEncryption(encryption);
2115 ASSERT_TRUE(encryption == NULL);
2116 }
2117
2118 if (options.has_video) {
2119 CheckVideoBandwidth(options.video_bandwidth,
2120 call_->sessions()[0]->local_description());
2121 CheckVideoRtcpMux(expected_video_rtcp_mux_,
2122 call_->sessions()[0]->remote_description());
2123 content = parser_->NextContent(content);
2124 const buzz::XmlElement* bandwidth =
2125 parser_->BandwidthFromContent(content);
2126 if (options.video_bandwidth == cricket::kAutoBandwidth) {
2127 ASSERT_TRUE(bandwidth == NULL);
2128 } else {
2129 ASSERT_TRUE(bandwidth != NULL);
2130 ASSERT_EQ("AS", bandwidth->Attr(buzz::QName("", "type")));
2131 ASSERT_EQ(talk_base::ToString(options.video_bandwidth / 1000),
2132 bandwidth->BodyText());
2133 }
wu@webrtc.org91053e72013-08-10 07:18:04 +00002134
2135 buzz::XmlElement* e = PayloadTypeFromContent(content);
2136 ASSERT_TRUE(e != NULL);
2137 VideoCodec codec = VideoCodecFromPayloadType(e);
2138 VideoCodec expected_codec = kVideoCodecs[0];
2139 expected_codec.preference = codec.preference;
2140 expected_codec.feedback_params = expected_video_fb_params_;
2141 EXPECT_EQ(expected_codec, codec);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002142 }
2143
2144 if (options.data_channel_type == cricket::DCT_RTP) {
2145 content = parser_->NextContent(content);
2146 CheckRtpDataContent(content);
2147 }
2148
2149 if (options.data_channel_type == cricket::DCT_SCTP) {
2150 content = parser_->NextContent(content);
2151 CheckSctpDataContent(content);
2152 }
2153
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002154 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002155 }
2156
2157 void TestHasAllSupportedAudioCodecs(buzz::XmlElement* e) {
2158 ASSERT_TRUE(e != NULL);
2159
2160 e = PayloadTypeFromContent(e);
2161 ASSERT_TRUE(e != NULL);
2162 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2163 ASSERT_EQ(103, codec.id);
2164 ASSERT_EQ("ISAC", codec.name);
2165 ASSERT_EQ(16000, codec.clockrate);
2166 ASSERT_EQ(1, codec.channels);
2167
2168 e = NextFromPayloadType(e);
2169 ASSERT_TRUE(e != NULL);
2170 codec = AudioCodecFromPayloadType(e);
2171 ASSERT_EQ(104, codec.id);
2172 ASSERT_EQ("ISAC", codec.name);
2173 ASSERT_EQ(32000, codec.clockrate);
2174 ASSERT_EQ(1, codec.channels);
2175
2176 e = NextFromPayloadType(e);
2177 ASSERT_TRUE(e != NULL);
2178 codec = AudioCodecFromPayloadType(e);
2179 ASSERT_EQ(119, codec.id);
2180 ASSERT_EQ("ISACLC", codec.name);
2181 ASSERT_EQ(16000, codec.clockrate);
2182 ASSERT_EQ(40000, codec.bitrate);
2183 ASSERT_EQ(1, codec.channels);
2184
2185 e = NextFromPayloadType(e);
2186 ASSERT_TRUE(e != NULL);
2187 codec = AudioCodecFromPayloadType(e);
2188 ASSERT_EQ(99, codec.id);
2189 ASSERT_EQ("speex", codec.name);
2190 ASSERT_EQ(16000, codec.clockrate);
2191 ASSERT_EQ(22000, codec.bitrate);
2192 ASSERT_EQ(1, codec.channels);
2193
2194 e = NextFromPayloadType(e);
2195 ASSERT_TRUE(e != NULL);
2196 codec = AudioCodecFromPayloadType(e);
2197 ASSERT_EQ(97, codec.id);
2198 ASSERT_EQ("IPCMWB", codec.name);
2199 ASSERT_EQ(16000, codec.clockrate);
2200 ASSERT_EQ(80000, codec.bitrate);
2201 ASSERT_EQ(1, codec.channels);
2202
2203 e = NextFromPayloadType(e);
2204 ASSERT_TRUE(e != NULL);
2205 codec = AudioCodecFromPayloadType(e);
2206 ASSERT_EQ(9, codec.id);
2207 ASSERT_EQ("G722", codec.name);
2208 ASSERT_EQ(16000, codec.clockrate);
2209 ASSERT_EQ(64000, codec.bitrate);
2210 ASSERT_EQ(1, codec.channels);
2211
2212 e = NextFromPayloadType(e);
2213 ASSERT_TRUE(e != NULL);
2214 codec = AudioCodecFromPayloadType(e);
2215 ASSERT_EQ(102, codec.id);
2216 ASSERT_EQ("iLBC", codec.name);
2217 ASSERT_EQ(8000, codec.clockrate);
2218 ASSERT_EQ(13300, codec.bitrate);
2219 ASSERT_EQ(1, codec.channels);
2220
2221 e = NextFromPayloadType(e);
2222 ASSERT_TRUE(e != NULL);
2223 codec = AudioCodecFromPayloadType(e);
2224 ASSERT_EQ(98, codec.id);
2225 ASSERT_EQ("speex", codec.name);
2226 ASSERT_EQ(8000, codec.clockrate);
2227 ASSERT_EQ(11000, codec.bitrate);
2228 ASSERT_EQ(1, codec.channels);
2229
2230 e = NextFromPayloadType(e);
2231 ASSERT_TRUE(e != NULL);
2232 codec = AudioCodecFromPayloadType(e);
2233 ASSERT_EQ(3, codec.id);
2234 ASSERT_EQ("GSM", codec.name);
2235 ASSERT_EQ(8000, codec.clockrate);
2236 ASSERT_EQ(13000, codec.bitrate);
2237 ASSERT_EQ(1, codec.channels);
2238
2239 e = NextFromPayloadType(e);
2240 ASSERT_TRUE(e != NULL);
2241 codec = AudioCodecFromPayloadType(e);
2242 ASSERT_EQ(100, codec.id);
2243 ASSERT_EQ("EG711U", codec.name);
2244 ASSERT_EQ(8000, codec.clockrate);
2245 ASSERT_EQ(64000, codec.bitrate);
2246 ASSERT_EQ(1, codec.channels);
2247
2248 e = NextFromPayloadType(e);
2249 ASSERT_TRUE(e != NULL);
2250 codec = AudioCodecFromPayloadType(e);
2251 ASSERT_EQ(101, codec.id);
2252 ASSERT_EQ("EG711A", codec.name);
2253 ASSERT_EQ(8000, codec.clockrate);
2254 ASSERT_EQ(64000, codec.bitrate);
2255 ASSERT_EQ(1, codec.channels);
2256
2257 e = NextFromPayloadType(e);
2258 ASSERT_TRUE(e != NULL);
2259 codec = AudioCodecFromPayloadType(e);
2260 ASSERT_EQ(0, codec.id);
2261 ASSERT_EQ("PCMU", codec.name);
2262 ASSERT_EQ(8000, codec.clockrate);
2263 ASSERT_EQ(64000, codec.bitrate);
2264 ASSERT_EQ(1, codec.channels);
2265
2266 e = NextFromPayloadType(e);
2267 ASSERT_TRUE(e != NULL);
2268 codec = AudioCodecFromPayloadType(e);
2269 ASSERT_EQ(8, codec.id);
2270 ASSERT_EQ("PCMA", codec.name);
2271 ASSERT_EQ(8000, codec.clockrate);
2272 ASSERT_EQ(64000, codec.bitrate);
2273 ASSERT_EQ(1, codec.channels);
2274
2275 e = NextFromPayloadType(e);
2276 ASSERT_TRUE(e != NULL);
2277 codec = AudioCodecFromPayloadType(e);
2278 ASSERT_EQ(126, codec.id);
2279 ASSERT_EQ("CN", codec.name);
2280 ASSERT_EQ(32000, codec.clockrate);
2281 ASSERT_EQ(1, codec.channels);
2282
2283 e = NextFromPayloadType(e);
2284 ASSERT_TRUE(e != NULL);
2285 codec = AudioCodecFromPayloadType(e);
2286 ASSERT_EQ(105, codec.id);
2287 ASSERT_EQ("CN", codec.name);
2288 ASSERT_EQ(16000, codec.clockrate);
2289 ASSERT_EQ(1, codec.channels);
2290
2291 e = NextFromPayloadType(e);
2292 ASSERT_TRUE(e != NULL);
2293 codec = AudioCodecFromPayloadType(e);
2294 ASSERT_EQ(13, codec.id);
2295 ASSERT_EQ("CN", codec.name);
2296 ASSERT_EQ(8000, codec.clockrate);
2297 ASSERT_EQ(1, codec.channels);
2298
2299 e = NextFromPayloadType(e);
2300 ASSERT_TRUE(e != NULL);
2301 codec = AudioCodecFromPayloadType(e);
2302 ASSERT_EQ(117, codec.id);
2303 ASSERT_EQ("red", codec.name);
2304 ASSERT_EQ(8000, codec.clockrate);
2305 ASSERT_EQ(1, codec.channels);
2306
2307 e = NextFromPayloadType(e);
2308 ASSERT_TRUE(e != NULL);
2309 codec = AudioCodecFromPayloadType(e);
2310 ASSERT_EQ(106, codec.id);
2311 ASSERT_EQ("telephone-event", codec.name);
2312 ASSERT_EQ(8000, codec.clockrate);
2313 ASSERT_EQ(1, codec.channels);
2314
2315 e = NextFromPayloadType(e);
2316 ASSERT_TRUE(e == NULL);
2317 }
2318
2319 void TestCodecsOfVideoInitiate(buzz::XmlElement* content) {
2320 ASSERT_TRUE(content != NULL);
2321 buzz::XmlElement* payload_type = PayloadTypeFromContent(content);
2322 ASSERT_TRUE(payload_type != NULL);
2323 cricket::AudioCodec codec = AudioCodecFromPayloadType(payload_type);
2324 ASSERT_EQ(103, codec.id);
2325 ASSERT_EQ("ISAC", codec.name);
2326 ASSERT_EQ(16000, codec.clockrate);
2327 ASSERT_EQ(1, codec.channels);
2328
2329 content = parser_->NextContent(content);
2330 ASSERT_TRUE(content != NULL);
2331 payload_type = PayloadTypeFromContent(content);
2332 ASSERT_TRUE(payload_type != NULL);
2333 cricket::VideoCodec vcodec =
2334 parser_->VideoCodecFromPayloadType(payload_type);
2335 ASSERT_EQ(99, vcodec.id);
2336 ASSERT_EQ("H264-SVC", vcodec.name);
2337 ASSERT_EQ(320, vcodec.width);
2338 ASSERT_EQ(200, vcodec.height);
2339 ASSERT_EQ(30, vcodec.framerate);
2340 }
2341
2342 void TestHasAudioCodecsFromInitiateSomeUnsupported(buzz::XmlElement* e) {
2343 ASSERT_TRUE(e != NULL);
2344 e = PayloadTypeFromContent(e);
2345 ASSERT_TRUE(e != NULL);
2346
2347 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2348 ASSERT_EQ(103, codec.id);
2349 ASSERT_EQ("ISAC", codec.name);
2350 ASSERT_EQ(16000, codec.clockrate);
2351 ASSERT_EQ(1, codec.channels);
2352
2353 e = NextFromPayloadType(e);
2354 ASSERT_TRUE(e != NULL);
2355 codec = AudioCodecFromPayloadType(e);
2356 ASSERT_EQ(100, codec.id);
2357 ASSERT_EQ("EG711U", codec.name);
2358
2359 e = NextFromPayloadType(e);
2360 ASSERT_TRUE(e != NULL);
2361 codec = AudioCodecFromPayloadType(e);
2362 ASSERT_EQ(101, codec.id);
2363 ASSERT_EQ("EG711A", codec.name);
2364
2365 e = NextFromPayloadType(e);
2366 ASSERT_TRUE(e != NULL);
2367 codec = AudioCodecFromPayloadType(e);
2368 ASSERT_EQ(0, codec.id);
2369 ASSERT_EQ("PCMU", codec.name);
2370
2371 e = NextFromPayloadType(e);
2372 ASSERT_TRUE(e != NULL);
2373 codec = AudioCodecFromPayloadType(e);
2374 ASSERT_EQ(13, codec.id);
2375 ASSERT_EQ("CN", codec.name);
2376
2377 e = NextFromPayloadType(e);
2378 ASSERT_TRUE(e == NULL);
2379 }
2380
2381 void TestHasAudioCodecsFromInitiateDynamicAudioCodecs(
2382 buzz::XmlElement* e) {
2383 ASSERT_TRUE(e != NULL);
2384 e = PayloadTypeFromContent(e);
2385 ASSERT_TRUE(e != NULL);
2386
2387 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2388 ASSERT_EQ(123, codec.id);
2389 ASSERT_EQ(16000, codec.clockrate);
2390 ASSERT_EQ(1, codec.channels);
2391
2392 e = NextFromPayloadType(e);
2393 ASSERT_TRUE(e == NULL);
2394 }
2395
2396 void TestHasDefaultAudioCodecs(buzz::XmlElement* e) {
2397 ASSERT_TRUE(e != NULL);
2398 e = PayloadTypeFromContent(e);
2399 ASSERT_TRUE(e != NULL);
2400
2401 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2402 ASSERT_EQ(103, codec.id);
2403 ASSERT_EQ("ISAC", codec.name);
2404
2405 e = NextFromPayloadType(e);
2406 ASSERT_TRUE(e != NULL);
2407 codec = AudioCodecFromPayloadType(e);
2408 ASSERT_EQ(0, codec.id);
2409 ASSERT_EQ("PCMU", codec.name);
2410
2411 e = NextFromPayloadType(e);
2412 ASSERT_TRUE(e == NULL);
2413 }
2414
2415 void TestHasAudioCodecsFromInitiateStaticAudioCodecs(
2416 buzz::XmlElement* e) {
2417 ASSERT_TRUE(e != NULL);
2418 e = PayloadTypeFromContent(e);
2419 ASSERT_TRUE(e != NULL);
2420
2421 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2422 ASSERT_EQ(3, codec.id);
2423
2424 e = NextFromPayloadType(e);
2425 ASSERT_TRUE(e != NULL);
2426 codec = AudioCodecFromPayloadType(e);
2427 ASSERT_EQ(0, codec.id);
2428
2429 e = NextFromPayloadType(e);
2430 ASSERT_TRUE(e != NULL);
2431 codec = AudioCodecFromPayloadType(e);
2432 ASSERT_EQ(8, codec.id);
2433
2434 e = NextFromPayloadType(e);
2435 ASSERT_TRUE(e == NULL);
2436 }
2437
2438 void TestGingleInitiateWithUnsupportedCrypto(
2439 const std::string &initiate_string,
2440 buzz::XmlElement** element) {
2441 *element = NULL;
2442
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002443 talk_base::scoped_ptr<buzz::XmlElement> el(
2444 buzz::XmlElement::ForStr(initiate_string));
2445 client_->session_manager()->OnIncomingMessage(el.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002446
2447 ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
2448 call_->sessions()[0]->state());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002449 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002450 CheckBadCryptoFromIncomingInitiate(call_->sessions()[0]);
2451
2452 call_->AcceptSession(call_->sessions()[0], cricket::CallOptions());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002453 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002454 CheckNoCryptoForOutgoingAccept(call_->sessions()[0]);
2455
2456 call_->Terminate();
2457 ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
2458 call_->sessions()[0]->state());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002459 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002460 }
2461
2462 void TestIncomingAcceptWithSsrcs(
2463 const std::string& accept_string,
2464 cricket::CallOptions& options) {
2465 client_->CreateCall();
2466 ASSERT_TRUE(call_ != NULL);
2467
2468 call_->InitiateSession(buzz::Jid("me@mydomain.com"),
2469 buzz::Jid("me@mydomain.com"), options);
2470 ASSERT_TRUE(call_->sessions()[0] != NULL);
2471 ASSERT_EQ(cricket::Session::STATE_SENTINITIATE,
2472 call_->sessions()[0]->state());
2473 ASSERT_EQ(1U, stanzas_.size());
2474 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
2475 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
2476 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
2477 buzz::XmlElement* action = ActionFromStanza(stanzas_[0]);
2478 ASSERT_TRUE(action != NULL);
2479 buzz::XmlElement* content = ContentFromAction(action);
2480 ASSERT_TRUE(content != NULL);
2481 if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
2482 buzz::XmlElement* content_desc =
2483 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
2484 ASSERT_TRUE(content_desc != NULL);
2485 ASSERT_EQ("", content_desc->Attr(cricket::QN_SSRC));
2486 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002487 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002488
2489 // We need to insert the session ID into the session accept message.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002490 talk_base::scoped_ptr<buzz::XmlElement> el(
2491 buzz::XmlElement::ForStr(accept_string));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002492 const std::string sid = call_->sessions()[0]->id();
2493 if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
2494 buzz::XmlElement* jingle = el->FirstNamed(cricket::QN_JINGLE);
2495 jingle->SetAttr(cricket::QN_SID, sid);
2496 } else {
2497 buzz::XmlElement* session = el->FirstNamed(cricket::QN_GINGLE_SESSION);
2498 session->SetAttr(cricket::QN_ID, sid);
2499 }
2500
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002501 client_->session_manager()->OnIncomingMessage(el.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002502
2503 ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT,
2504 call_->sessions()[0]->state());
2505 ASSERT_EQ(1U, stanzas_.size());
2506 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
2507 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
2508 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002509 ClearStanzas();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002510
2511 CheckAudioSsrcForIncomingAccept(call_->sessions()[0]);
2512 CheckVideoSsrcForIncomingAccept(call_->sessions()[0]);
2513 if (options.data_channel_type == cricket::DCT_RTP) {
2514 CheckDataSsrcForIncomingAccept(call_->sessions()[0]);
2515 }
2516 // TODO(pthatcher): Check kDataSid if DCT_SCTP.
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::SecureMediaPolicy secure) {
2755 client_->set_secure(secure);
2756 }
2757
2758 void ExpectCrypto(cricket::SecureMediaPolicy 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
wu@webrtc.org91053e72013-08-10 07:18:04 +00002774 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
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002796 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_;
wu@webrtc.org91053e72013-08-10 07:18:04 +00002840 FeedbackParams expected_audio_fb_params_;
2841 FeedbackParams expected_video_fb_params_;
2842 FeedbackParams expected_data_fb_params_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002843 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
wu@webrtc.org91053e72013-08-10 07:18:04 +00002857TEST(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
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002868TEST(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}