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