Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: webrtc/libjingle/session/media/mediasessionclient_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698