~ubuntu-branches/debian/experimental/kopete/experimental

« back to all changes in this revision

Viewing changes to protocols/jabber/libjingle/talk/p2p/base/session_unittest.cc

  • Committer: Package Import Robot
  • Author(s): Maximiliano Curia
  • Date: 2015-02-24 11:32:57 UTC
  • mfrom: (1.1.41 vivid)
  • Revision ID: package-import@ubuntu.com-20150224113257-gnupg4v7lzz18ij0
Tags: 4:14.12.2-1
* New upstream release (14.12.2).
* Bump Standards-Version to 3.9.6, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <cstring>
 
29
#include <sstream>
 
30
#include <deque>
 
31
#include <map>
 
32
 
 
33
#include "talk/base/basicpacketsocketfactory.h"
 
34
#include "talk/base/common.h"
 
35
#include "talk/base/gunit.h"
 
36
#include "talk/base/helpers.h"
 
37
#include "talk/base/host.h"
 
38
#include "talk/base/logging.h"
 
39
#include "talk/base/natserver.h"
 
40
#include "talk/base/natsocketfactory.h"
 
41
#include "talk/base/stringencode.h"
 
42
#include "talk/p2p/base/constants.h"
 
43
#include "talk/p2p/base/parsing.h"
 
44
#include "talk/p2p/base/portallocator.h"
 
45
#include "talk/p2p/base/p2ptransport.h"
 
46
#include "talk/p2p/base/relayport.h"
 
47
#include "talk/p2p/base/relayserver.h"
 
48
#include "talk/p2p/base/session.h"
 
49
#include "talk/p2p/base/sessionclient.h"
 
50
#include "talk/p2p/base/sessionmanager.h"
 
51
#include "talk/p2p/base/stunport.h"
 
52
#include "talk/p2p/base/stunserver.h"
 
53
#include "talk/p2p/base/transportchannel.h"
 
54
#include "talk/p2p/base/transportchannelproxy.h"
 
55
#include "talk/p2p/base/udpport.h"
 
56
#include "talk/xmpp/constants.h"
 
57
 
 
58
using cricket::SignalingProtocol;
 
59
using cricket::PROTOCOL_HYBRID;
 
60
using cricket::PROTOCOL_JINGLE;
 
61
using cricket::PROTOCOL_GINGLE;
 
62
 
 
63
static const std::string kInitiator = "init@init.com";
 
64
static const std::string kResponder = "resp@resp.com";
 
65
// Expected from test random number generator.
 
66
static const std::string kSessionId = "2154761789";
 
67
// TODO: When we need to test more than one transport type,
 
68
// allow this to be injected like the content types are.
 
69
static const std::string kTransportType = "http://www.google.com/transport/p2p";
 
70
 
 
71
// Controls how long we wait for a session to send messages that we
 
72
// expect, in milliseconds.  We put it high to avoid flaky tests.
 
73
static const int kEventTimeout = 5000;
 
74
 
 
75
static const int kNumPorts = 2;
 
76
static const int kPort0 = 28653;
 
77
static const int kPortStep = 5;
 
78
 
 
79
static const std::string kNotifyNick1 = "derekcheng_google.com^59422C27";
 
80
static const std::string kNotifyNick2 = "someoneelses_google.com^7abd6a7a20";
 
81
static const uint32 kNotifyAudioSsrc1 = 2625839801U;
 
82
static const uint32 kNotifyAudioSsrc2 = 2529430427U;
 
83
static const uint32 kNotifyVideoSsrc1 = 3;
 
84
static const uint32 kNotifyVideoSsrc2 = 2;
 
85
 
 
86
static const std::string kViewRequestNick = "param_google.com^16A3CDBE";
 
87
static const uint32 kViewRequestSsrc = 4;
 
88
static const int kViewRequestWidth = 320;
 
89
static const int kViewRequestHeight = 200;
 
90
static const int kViewRequestFrameRate = 15;
 
91
 
 
92
int GetPort(int port_index) {
 
93
  return kPort0 + (port_index * kPortStep);
 
94
}
 
95
 
 
96
std::string GetPortString(int port_index) {
 
97
  return talk_base::ToString(GetPort(port_index));
 
98
}
 
99
 
 
100
// Only works for port_index < 10, which is fine for our purposes.
 
101
std::string GetUsername(int port_index) {
 
102
  return "username" + std::string(8, talk_base::ToString(port_index)[0]);
 
103
}
 
104
 
 
105
// Only works for port_index < 10, which is fine for our purposes.
 
106
std::string GetPassword(int port_index) {
 
107
  return "password" + std::string(8, talk_base::ToString(port_index)[0]);
 
108
}
 
109
 
 
110
std::string IqAck(const std::string& id,
 
111
                  const std::string& from,
 
112
                  const std::string& to) {
 
113
  return "<cli:iq"
 
114
      " to=\"" + to + "\""
 
115
      " id=\"" + id + "\""
 
116
      " type=\"result\""
 
117
      " from=\"" + from + "\""
 
118
      " xmlns:cli=\"jabber:client\""
 
119
      "/>";
 
120
}
 
121
 
 
122
std::string IqSet(const std::string& id,
 
123
                  const std::string& from,
 
124
                  const std::string& to,
 
125
                  const std::string& content) {
 
126
  return "<cli:iq"
 
127
      " to=\"" + to + "\""
 
128
      " type=\"set\""
 
129
      " from=\"" + from + "\""
 
130
      " id=\"" + id + "\""
 
131
      " xmlns:cli=\"jabber:client\""
 
132
      ">"
 
133
      + content +
 
134
      "</cli:iq>";
 
135
}
 
136
 
 
137
std::string IqError(const std::string& id,
 
138
                    const std::string& from,
 
139
                    const std::string& to,
 
140
                    const std::string& content) {
 
141
  return "<cli:error"
 
142
      " to=\"" + to + "\""
 
143
      " type=\"error\""
 
144
      " from=\"" + from + "\""
 
145
      " id=\"" + id + "\""
 
146
      " xmlns:cli=\"jabber:client\""
 
147
      ">"
 
148
      + content +
 
149
      "</cli:error>";
 
150
}
 
151
 
 
152
std::string GingleSessionXml(const std::string& type,
 
153
                             const std::string& content) {
 
154
  return "<session"
 
155
      " xmlns=\"http://www.google.com/session\""
 
156
      " type=\"" + type + "\""
 
157
      " id=\"" + kSessionId + "\""
 
158
      " initiator=\"" + kInitiator + "\""
 
159
      ">"
 
160
      + content +
 
161
      "</session>";
 
162
}
 
163
 
 
164
std::string GingleDescriptionXml(const std::string& content_type) {
 
165
  return "<description"
 
166
      " xmlns=\"" + content_type + "\""
 
167
      "/>";
 
168
}
 
169
 
 
170
std::string P2pCandidateXml(const std::string& name, int port_index) {
 
171
  return "<candidate"
 
172
      " name=\"" + name + "\""
 
173
      " address=\"127.0.0.1\""
 
174
      " port=\"" + GetPortString(port_index) + "\""
 
175
      " preference=\"1\""
 
176
      " username=\"" + GetUsername(port_index) + "\""
 
177
      " protocol=\"udp\""
 
178
      " generation=\"0\""
 
179
      " password=\"" + GetPassword(port_index) + "\""
 
180
      " type=\"local\""
 
181
      " network=\"network\""
 
182
      "/>";
 
183
}
 
184
 
 
185
std::string JingleActionXml(const std::string& action,
 
186
                            const std::string& content) {
 
187
  return "<jingle"
 
188
      " xmlns=\"urn:xmpp:jingle:1\""
 
189
      " action=\"" + action + "\""
 
190
      " sid=\"" + kSessionId + "\""
 
191
      ">"
 
192
      + content +
 
193
      "</jingle>";
 
194
}
 
195
 
 
196
std::string JingleInitiateActionXml(const std::string& content) {
 
197
  return "<jingle"
 
198
      " xmlns=\"urn:xmpp:jingle:1\""
 
199
      " action=\"session-initiate\""
 
200
      " sid=\"" + kSessionId + "\""
 
201
      " initiator=\"" + kInitiator + "\""
 
202
      ">"
 
203
      + content +
 
204
      "</jingle>";
 
205
}
 
206
 
 
207
std::string JingleGroupInfoXml(const std::string& content_name_a,
 
208
                               const std::string& content_name_b) {
 
209
  std::string group_info = "<jin:group"
 
210
      " type=\"BUNDLE\""
 
211
      " xmlns:jin=\"google:jingle\""
 
212
      ">";
 
213
  if (!content_name_a.empty())
 
214
    group_info += "<content name=\"" + content_name_a + "\""
 
215
    "/>";
 
216
  if (!content_name_b.empty())
 
217
    group_info += "<content name=\"" + content_name_b + "\""
 
218
    "/>";
 
219
  group_info += "</jin:group>";
 
220
  return group_info;
 
221
}
 
222
 
 
223
 
 
224
std::string JingleEmptyContentXml(const std::string& content_name,
 
225
                                  const std::string& content_type,
 
226
                                  const std::string& transport_type) {
 
227
  return "<content"
 
228
      " name=\"" + content_name + "\""
 
229
      " creator=\"initiator\""
 
230
      ">"
 
231
      "<description"
 
232
      " xmlns=\"" + content_type + "\""
 
233
      "/>"
 
234
      "<transport"
 
235
      " xmlns=\"" + transport_type + "\""
 
236
      "/>"
 
237
      "</content>";
 
238
}
 
239
 
 
240
std::string JingleContentXml(const std::string& content_name,
 
241
                             const std::string& content_type,
 
242
                             const std::string& transport_type,
 
243
                             const std::string& transport_main) {
 
244
  std::string transport = transport_type.empty() ? "" :
 
245
      "<transport"
 
246
      " xmlns=\"" + transport_type + "\""
 
247
      ">"
 
248
      + transport_main +
 
249
      "</transport>";
 
250
 
 
251
  return"<content"
 
252
      " name=\"" + content_name + "\""
 
253
      " creator=\"initiator\""
 
254
      ">"
 
255
      "<description"
 
256
      " xmlns=\"" + content_type + "\""
 
257
      "/>"
 
258
      + transport +
 
259
      "</content>";
 
260
}
 
261
 
 
262
std::string JingleTransportContentXml(const std::string& content_name,
 
263
                                      const std::string& transport_type,
 
264
                                      const std::string& content) {
 
265
  return "<content"
 
266
      " name=\"" + content_name + "\""
 
267
      " creator=\"initiator\""
 
268
      ">"
 
269
      "<transport"
 
270
      " xmlns=\"" + transport_type + "\""
 
271
      ">"
 
272
      + content +
 
273
      "</transport>"
 
274
      "</content>";
 
275
}
 
276
 
 
277
std::string GingleInitiateXml(const std::string& content_type) {
 
278
  return GingleSessionXml(
 
279
      "initiate",
 
280
      GingleDescriptionXml(content_type));
 
281
}
 
282
 
 
283
std::string JingleInitiateXml(const std::string& content_name_a,
 
284
                              const std::string& content_type_a,
 
285
                              const std::string& content_name_b,
 
286
                              const std::string& content_type_b,
 
287
                              bool bundle = false) {
 
288
  std::string content_xml;
 
289
  if (content_name_b.empty()) {
 
290
    content_xml = JingleEmptyContentXml(
 
291
        content_name_a, content_type_a, kTransportType);
 
292
  } else {
 
293
    content_xml = JingleEmptyContentXml(
 
294
           content_name_a, content_type_a, kTransportType) +
 
295
       JingleEmptyContentXml(
 
296
           content_name_b, content_type_b, kTransportType);
 
297
    if (bundle) {
 
298
      content_xml += JingleGroupInfoXml(content_name_a, content_name_b);
 
299
    }
 
300
  }
 
301
  return JingleInitiateActionXml(content_xml);
 
302
}
 
303
 
 
304
std::string GingleAcceptXml(const std::string& content_type) {
 
305
  return GingleSessionXml(
 
306
      "accept",
 
307
      GingleDescriptionXml(content_type));
 
308
}
 
309
 
 
310
std::string JingleAcceptXml(const std::string& content_name_a,
 
311
                            const std::string& content_type_a,
 
312
                            const std::string& content_name_b,
 
313
                            const std::string& content_type_b,
 
314
                            bool bundle = false) {
 
315
  std::string content_xml;
 
316
  if (content_name_b.empty()) {
 
317
    content_xml = JingleEmptyContentXml(
 
318
        content_name_a, content_type_a, kTransportType);
 
319
  } else {
 
320
    content_xml = JingleEmptyContentXml(
 
321
        content_name_a, content_type_a, kTransportType) +
 
322
        JingleEmptyContentXml(
 
323
            content_name_b, content_type_b, kTransportType);
 
324
  }
 
325
  if (bundle) {
 
326
    content_xml += JingleGroupInfoXml(content_name_a, content_name_b);
 
327
  }
 
328
 
 
329
  return JingleActionXml("session-accept", content_xml);
 
330
}
 
331
 
 
332
std::string Gingle2CandidatesXml(const std::string& channel_name,
 
333
                                 int port_index0,
 
334
                                 int port_index1) {
 
335
  return GingleSessionXml(
 
336
      "candidates",
 
337
      P2pCandidateXml(channel_name, port_index0) +
 
338
      P2pCandidateXml(channel_name, port_index1));
 
339
}
 
340
 
 
341
std::string Gingle4CandidatesXml(const std::string& channel_name_a,
 
342
                                 int port_index0,
 
343
                                 int port_index1,
 
344
                                 const std::string& channel_name_b,
 
345
                                 int port_index2,
 
346
                                 int port_index3) {
 
347
  return GingleSessionXml(
 
348
      "candidates",
 
349
      P2pCandidateXml(channel_name_a, port_index0) +
 
350
      P2pCandidateXml(channel_name_a, port_index1) +
 
351
      P2pCandidateXml(channel_name_b, port_index2) +
 
352
      P2pCandidateXml(channel_name_b, port_index3));
 
353
}
 
354
 
 
355
std::string Jingle2TransportInfoXml(const std::string& content_name,
 
356
                                    const std::string& channel_name,
 
357
                                    int port_index0,
 
358
                                    int port_index1) {
 
359
  return JingleActionXml(
 
360
      "transport-info",
 
361
      JingleTransportContentXml(
 
362
          content_name, kTransportType,
 
363
          P2pCandidateXml(channel_name, port_index0) +
 
364
          P2pCandidateXml(channel_name, port_index1)));
 
365
}
 
366
 
 
367
std::string Jingle4TransportInfoXml(const std::string& content_name,
 
368
                                    const std::string& channel_name_a,
 
369
                                    int port_index0,
 
370
                                    int port_index1,
 
371
                                    const std::string& channel_name_b,
 
372
                                    int port_index2,
 
373
                                    int port_index3) {
 
374
  return JingleActionXml(
 
375
      "transport-info",
 
376
      JingleTransportContentXml(
 
377
          content_name, kTransportType,
 
378
          P2pCandidateXml(channel_name_a, port_index0) +
 
379
          P2pCandidateXml(channel_name_a, port_index1) +
 
380
          P2pCandidateXml(channel_name_b, port_index2) +
 
381
          P2pCandidateXml(channel_name_b, port_index3)));
 
382
}
 
383
 
 
384
std::string JingleDescriptionInfoXml(const std::string& content_name,
 
385
                                     const std::string& content_type) {
 
386
  return JingleActionXml(
 
387
      "description-info",
 
388
      JingleContentXml(content_name, content_type, "", ""));
 
389
}
 
390
 
 
391
std::string GingleRejectXml(const std::string& reason) {
 
392
  return GingleSessionXml(
 
393
      "reject",
 
394
      "<" + reason + "/>");
 
395
}
 
396
 
 
397
std::string JingleTerminateXml(const std::string& reason) {
 
398
    return JingleActionXml(
 
399
        "session-terminate",
 
400
        "<reason><" + reason + "/></reason>");
 
401
}
 
402
 
 
403
std::string GingleTerminateXml(const std::string& reason) {
 
404
  return GingleSessionXml(
 
405
      "terminate",
 
406
      "<" + reason + "/>");
 
407
}
 
408
 
 
409
std::string GingleRedirectXml(const std::string& intitiate,
 
410
                              const std::string& target) {
 
411
  return intitiate +
 
412
    "<error code=\"302\" type=\"modify\">"
 
413
    "<redirect xmlns=\"http://www.google.com/session\">"
 
414
    "xmpp:" + target +
 
415
    "</redirect>"
 
416
    "</error>";
 
417
}
 
418
 
 
419
std::string JingleRedirectXml(const std::string& intitiate,
 
420
                              const std::string& target) {
 
421
  return intitiate +
 
422
    "<error code=\"302\" type=\"modify\">"
 
423
    "<redirect xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">"
 
424
    "xmpp:" + target +
 
425
    "</redirect>"
 
426
    "</error>";
 
427
}
 
428
 
 
429
std::string InitiateXml(SignalingProtocol protocol,
 
430
                        const std::string& gingle_content_type,
 
431
                        const std::string& content_name_a,
 
432
                        const std::string& content_type_a,
 
433
                        const std::string& content_name_b,
 
434
                        const std::string& content_type_b,
 
435
                        bool bundle = false) {
 
436
  switch (protocol) {
 
437
    case PROTOCOL_JINGLE:
 
438
      return JingleInitiateXml(content_name_a, content_type_a,
 
439
                               content_name_b, content_type_b,
 
440
                               bundle);
 
441
    case PROTOCOL_GINGLE:
 
442
      return GingleInitiateXml(gingle_content_type);
 
443
    case PROTOCOL_HYBRID:
 
444
      return JingleInitiateXml(content_name_a, content_type_a,
 
445
                               content_name_b, content_type_b) +
 
446
          GingleInitiateXml(gingle_content_type);
 
447
  }
 
448
  return "";
 
449
}
 
450
 
 
451
std::string InitiateXml(SignalingProtocol protocol,
 
452
                        const std::string& content_name,
 
453
                        const std::string& content_type) {
 
454
  return InitiateXml(protocol,
 
455
                     content_type,
 
456
                     content_name, content_type,
 
457
                     "", "");
 
458
}
 
459
 
 
460
std::string AcceptXml(SignalingProtocol protocol,
 
461
                      const std::string& gingle_content_type,
 
462
                      const std::string& content_name_a,
 
463
                      const std::string& content_type_a,
 
464
                      const std::string& content_name_b,
 
465
                      const std::string& content_type_b,
 
466
                      bool bundle = false) {
 
467
  switch (protocol) {
 
468
    case PROTOCOL_JINGLE:
 
469
      return JingleAcceptXml(content_name_a, content_type_a,
 
470
                             content_name_b, content_type_b, bundle);
 
471
    case PROTOCOL_GINGLE:
 
472
      return GingleAcceptXml(gingle_content_type);
 
473
    case PROTOCOL_HYBRID:
 
474
      return
 
475
          JingleAcceptXml(content_name_a, content_type_a,
 
476
                          content_name_b, content_type_b) +
 
477
          GingleAcceptXml(gingle_content_type);
 
478
  }
 
479
  return "";
 
480
}
 
481
 
 
482
 
 
483
std::string AcceptXml(SignalingProtocol protocol,
 
484
                      const std::string& content_name,
 
485
                      const std::string& content_type,
 
486
                      bool bundle = false) {
 
487
  return AcceptXml(protocol,
 
488
                   content_type,
 
489
                   content_name, content_type,
 
490
                   "", "");
 
491
}
 
492
 
 
493
std::string TransportInfo2Xml(SignalingProtocol protocol,
 
494
                              const std::string& content_name,
 
495
                              const std::string& channel_name,
 
496
                              int port_index0,
 
497
                              int port_index1) {
 
498
  switch (protocol) {
 
499
    case PROTOCOL_JINGLE:
 
500
      return Jingle2TransportInfoXml(
 
501
          content_name,
 
502
          channel_name, port_index0, port_index1);
 
503
    case PROTOCOL_GINGLE:
 
504
      return Gingle2CandidatesXml(
 
505
          channel_name, port_index0, port_index1);
 
506
    case PROTOCOL_HYBRID:
 
507
      return
 
508
          Jingle2TransportInfoXml(
 
509
              content_name,
 
510
              channel_name, port_index0, port_index1) +
 
511
          Gingle2CandidatesXml(
 
512
              channel_name, port_index0, port_index1);
 
513
  }
 
514
  return "";
 
515
}
 
516
 
 
517
std::string TransportInfo4Xml(SignalingProtocol protocol,
 
518
                              const std::string& content_name,
 
519
                              const std::string& channel_name_a,
 
520
                              int port_index0,
 
521
                              int port_index1,
 
522
                              const std::string& channel_name_b,
 
523
                              int port_index2,
 
524
                              int port_index3) {
 
525
  switch (protocol) {
 
526
    case PROTOCOL_JINGLE:
 
527
      return Jingle4TransportInfoXml(
 
528
          content_name,
 
529
          channel_name_a, port_index0, port_index1,
 
530
          channel_name_b, port_index2, port_index3);
 
531
    case PROTOCOL_GINGLE:
 
532
      return Gingle4CandidatesXml(
 
533
          channel_name_a, port_index0, port_index1,
 
534
          channel_name_b, port_index2, port_index3);
 
535
    case PROTOCOL_HYBRID:
 
536
      return
 
537
          Jingle4TransportInfoXml(
 
538
              content_name,
 
539
              channel_name_a, port_index0, port_index1,
 
540
              channel_name_b, port_index2, port_index3) +
 
541
          Gingle4CandidatesXml(
 
542
              channel_name_a, port_index0, port_index1,
 
543
              channel_name_b, port_index2, port_index3);
 
544
  }
 
545
  return "";
 
546
}
 
547
 
 
548
std::string RejectXml(SignalingProtocol protocol,
 
549
                      const std::string& reason) {
 
550
  switch (protocol) {
 
551
    case PROTOCOL_JINGLE:
 
552
      return JingleTerminateXml(reason);
 
553
    case PROTOCOL_GINGLE:
 
554
      return GingleRejectXml(reason);
 
555
    case PROTOCOL_HYBRID:
 
556
      return JingleTerminateXml(reason) +
 
557
          GingleRejectXml(reason);
 
558
  }
 
559
  return "";
 
560
}
 
561
 
 
562
std::string TerminateXml(SignalingProtocol protocol,
 
563
                         const std::string& reason) {
 
564
  switch (protocol) {
 
565
    case PROTOCOL_JINGLE:
 
566
      return JingleTerminateXml(reason);
 
567
    case PROTOCOL_GINGLE:
 
568
      return GingleTerminateXml(reason);
 
569
    case PROTOCOL_HYBRID:
 
570
      return JingleTerminateXml(reason) +
 
571
          GingleTerminateXml(reason);
 
572
  }
 
573
  return "";
 
574
}
 
575
 
 
576
std::string RedirectXml(SignalingProtocol protocol,
 
577
                        const std::string& initiate,
 
578
                        const std::string& target) {
 
579
  switch (protocol) {
 
580
    case PROTOCOL_JINGLE:
 
581
      return JingleRedirectXml(initiate, target);
 
582
    case PROTOCOL_GINGLE:
 
583
      return GingleRedirectXml(initiate, target);
 
584
  }
 
585
  return "";
 
586
}
 
587
 
 
588
// TODO: Break out and join with fakeportallocator.h
 
589
class TestPortAllocatorSession : public cricket::PortAllocatorSession {
 
590
 public:
 
591
  TestPortAllocatorSession(const std::string& name,
 
592
                           const std::string& session_type,
 
593
                           const int port_offset)
 
594
      : PortAllocatorSession(name, session_type, 0),
 
595
        port_offset_(port_offset),
 
596
        ports_(kNumPorts),
 
597
        address_("127.0.0.1", 0),
 
598
        network_("network", "unittest",
 
599
                 talk_base::IPAddress(INADDR_LOOPBACK), 8),
 
600
        socket_factory_(talk_base::Thread::Current()),
 
601
        running_(false),
 
602
        port_(28653) {
 
603
    network_.AddIP(address_.ipaddr());
 
604
  }
 
605
 
 
606
  ~TestPortAllocatorSession() {
 
607
    for (size_t i = 0; i < ports_.size(); i++)
 
608
      delete ports_[i];
 
609
  }
 
610
 
 
611
  virtual void GetInitialPorts() {
 
612
    for (int i = 0; i < kNumPorts; i++) {
 
613
      int index = port_offset_ + i;
 
614
      ports_[i] = cricket::UDPPort::Create(
 
615
          talk_base::Thread::Current(), &socket_factory_,
 
616
          &network_, address_.ipaddr(), GetPort(index), GetPort(index));
 
617
      ports_[i]->set_username_fragment(GetUsername(index));
 
618
      ports_[i]->set_password(GetPassword(index));
 
619
      AddPort(ports_[i]);
 
620
    }
 
621
  }
 
622
 
 
623
  virtual void StartGetAllPorts() { running_ = true; }
 
624
  virtual void StopGetAllPorts() { running_ = false; }
 
625
  virtual bool IsGettingAllPorts() { return running_; }
 
626
 
 
627
  void AddPort(cricket::Port* port) {
 
628
    port->set_name(name_);
 
629
    port->set_preference(1.0);
 
630
    port->set_generation(0);
 
631
    port->SignalDestroyed.connect(
 
632
        this, &TestPortAllocatorSession::OnPortDestroyed);
 
633
    port->SignalAddressReady.connect(
 
634
        this, &TestPortAllocatorSession::OnAddressReady);
 
635
    port->PrepareAddress();
 
636
    SignalPortReady(this, port);
 
637
  }
 
638
 
 
639
  void OnPortDestroyed(cricket::Port* port) {
 
640
    for (size_t i = 0; i < ports_.size(); i++) {
 
641
      if (ports_[i] == port)
 
642
        ports_[i] = NULL;
 
643
    }
 
644
  }
 
645
 
 
646
  void OnAddressReady(cricket::Port* port) {
 
647
    SignalCandidatesReady(this, port->candidates());
 
648
  }
 
649
 
 
650
 private:
 
651
  int port_offset_;
 
652
  std::vector<cricket::Port*> ports_;
 
653
  talk_base::SocketAddress address_;
 
654
  talk_base::Network network_;
 
655
  talk_base::BasicPacketSocketFactory socket_factory_;
 
656
  bool running_;
 
657
  int port_;
 
658
};
 
659
 
 
660
class TestPortAllocator : public cricket::PortAllocator {
 
661
 public:
 
662
  TestPortAllocator() : port_offset_(0) {}
 
663
 
 
664
  virtual cricket::PortAllocatorSession*
 
665
  CreateSession(const std::string &name,
 
666
                const std::string &content_type) {
 
667
    port_offset_ += 2;
 
668
    return new TestPortAllocatorSession(name, content_type, port_offset_ - 2);
 
669
  }
 
670
 
 
671
  int port_offset_;
 
672
};
 
673
 
 
674
class TestContentDescription : public cricket::ContentDescription {
 
675
 public:
 
676
  explicit TestContentDescription(const std::string& gingle_content_type,
 
677
                                  const std::string& content_type)
 
678
      : gingle_content_type(gingle_content_type),
 
679
        content_type(content_type) {
 
680
  }
 
681
  virtual ContentDescription* Copy() const {
 
682
    return new TestContentDescription(*this);
 
683
  }
 
684
 
 
685
  std::string gingle_content_type;
 
686
  std::string content_type;
 
687
};
 
688
 
 
689
cricket::SessionDescription* NewTestSessionDescription(
 
690
    const std::string gingle_content_type,
 
691
    const std::string& content_name_a, const std::string& content_type_a,
 
692
    const std::string& content_name_b, const std::string& content_type_b) {
 
693
 
 
694
  cricket::SessionDescription* offer = new cricket::SessionDescription();
 
695
  offer->AddContent(content_name_a, content_type_a,
 
696
                    new TestContentDescription(gingle_content_type,
 
697
                                               content_type_a));
 
698
  if (content_name_a != content_name_b) {
 
699
    offer->AddContent(content_name_b, content_type_b,
 
700
                      new TestContentDescription(gingle_content_type,
 
701
                                                 content_type_b));
 
702
  }
 
703
  return offer;
 
704
}
 
705
 
 
706
cricket::SessionDescription* NewTestSessionDescription(
 
707
    const std::string& content_name, const std::string& content_type) {
 
708
 
 
709
  cricket::SessionDescription* offer = new cricket::SessionDescription();
 
710
  offer->AddContent(content_name, content_type,
 
711
                    new TestContentDescription(content_type,
 
712
                                               content_type));
 
713
  return offer;
 
714
}
 
715
 
 
716
struct TestSessionClient: public cricket::SessionClient,
 
717
                          public sigslot::has_slots<> {
 
718
 public:
 
719
  TestSessionClient() {
 
720
  }
 
721
 
 
722
  ~TestSessionClient() {
 
723
  }
 
724
 
 
725
  virtual bool ParseContent(SignalingProtocol protocol,
 
726
                            const buzz::XmlElement* elem,
 
727
                            const cricket::ContentDescription** content,
 
728
                            cricket::ParseError* error) {
 
729
    std::string content_type;
 
730
    std::string gingle_content_type;
 
731
    if (protocol == PROTOCOL_GINGLE) {
 
732
      gingle_content_type = elem->Name().Namespace();
 
733
    } else {
 
734
      content_type = elem->Name().Namespace();
 
735
    }
 
736
 
 
737
    *content = new TestContentDescription(gingle_content_type, content_type);
 
738
    return true;
 
739
  }
 
740
 
 
741
  virtual bool WriteContent(SignalingProtocol protocol,
 
742
                            const cricket::ContentDescription* untyped_content,
 
743
                            buzz::XmlElement** elem,
 
744
                            cricket::WriteError* error) {
 
745
    const TestContentDescription* content =
 
746
        static_cast<const TestContentDescription*>(untyped_content);
 
747
    std::string content_type = (protocol == PROTOCOL_GINGLE ?
 
748
                                content->gingle_content_type :
 
749
                                content->content_type);
 
750
     *elem = new buzz::XmlElement(
 
751
        buzz::QName(content_type, "description"), true);
 
752
    return true;
 
753
  }
 
754
 
 
755
  void OnSessionCreate(cricket::Session* session, bool initiate) {
 
756
  }
 
757
 
 
758
  void OnSessionDestroy(cricket::Session* session) {
 
759
  }
 
760
};
 
761
 
 
762
struct ChannelHandler : sigslot::has_slots<> {
 
763
  explicit ChannelHandler(cricket::TransportChannel* p, const std::string& name)
 
764
    : channel(p), last_readable(false), last_writable(false), data_count(0),
 
765
      last_size(0), name(name) {
 
766
    p->SignalReadableState.connect(this, &ChannelHandler::OnReadableState);
 
767
    p->SignalWritableState.connect(this, &ChannelHandler::OnWritableState);
 
768
    p->SignalReadPacket.connect(this, &ChannelHandler::OnReadPacket);
 
769
  }
 
770
 
 
771
  bool writable() const {
 
772
    return last_writable && channel->writable();
 
773
  }
 
774
 
 
775
  bool readable() const {
 
776
    return last_readable && channel->readable();
 
777
  }
 
778
 
 
779
  void OnReadableState(cricket::TransportChannel* p) {
 
780
    EXPECT_EQ(channel, p);
 
781
    last_readable = channel->readable();
 
782
  }
 
783
 
 
784
  void OnWritableState(cricket::TransportChannel* p) {
 
785
    EXPECT_EQ(channel, p);
 
786
    last_writable = channel->writable();
 
787
  }
 
788
 
 
789
  void OnReadPacket(cricket::TransportChannel* p, const char* buf,
 
790
                    size_t size) {
 
791
    if (memcmp(buf, name.c_str(), name.size()) != 0)
 
792
      return;  // drop packet if packet doesn't belong to this channel. This
 
793
               // can happen when transport channels are muxed together.
 
794
    buf += name.size();  // Remove channel name from the message.
 
795
    size -= name.size();  // Decrement size by channel name string size.
 
796
    EXPECT_EQ(channel, p);
 
797
    EXPECT_LE(size, sizeof(last_data));
 
798
    data_count += 1;
 
799
    last_size = size;
 
800
    std::memcpy(last_data, buf, size);
 
801
  }
 
802
 
 
803
  void Send(const char* data, size_t size) {
 
804
    std::string data_with_id(name);
 
805
    data_with_id += data;
 
806
    int result = channel->SendPacket(data_with_id.c_str(), data_with_id.size());
 
807
    EXPECT_EQ(static_cast<int>(data_with_id.size()), result);
 
808
  }
 
809
 
 
810
  cricket::TransportChannel* channel;
 
811
  bool last_readable, last_writable;
 
812
  int data_count;
 
813
  char last_data[4096];
 
814
  size_t last_size;
 
815
  std::string name;
 
816
};
 
817
 
 
818
void PrintStanza(const std::string& message,
 
819
                 const buzz::XmlElement* stanza) {
 
820
  printf("%s: %s\n", message.c_str(), stanza->Str().c_str());
 
821
}
 
822
 
 
823
class TestClient : public sigslot::has_slots<> {
 
824
 public:
 
825
  TestClient(cricket::PortAllocator* port_allocator,
 
826
             int* next_message_id,
 
827
             const std::string& local_name,
 
828
             SignalingProtocol start_protocol,
 
829
             const std::string& content_type,
 
830
             const std::string& content_name_a,
 
831
             const std::string& channel_name_a,
 
832
             const std::string& content_name_b,
 
833
             const std::string& channel_name_b) {
 
834
    Construct(port_allocator, next_message_id, local_name, start_protocol,
 
835
              content_type, content_name_a, channel_name_a,
 
836
              content_name_b, channel_name_b);
 
837
  }
 
838
 
 
839
  ~TestClient() {
 
840
    if (session) {
 
841
      session_manager->DestroySession(session);
 
842
      EXPECT_EQ(1U, session_destroyed_count);
 
843
    }
 
844
    delete session_manager;
 
845
    delete client;
 
846
  }
 
847
 
 
848
  void Construct(cricket::PortAllocator* pa,
 
849
                 int* message_id,
 
850
                 const std::string& lname,
 
851
                 SignalingProtocol protocol,
 
852
                 const std::string& cont_type,
 
853
                 const std::string& cont_name_a,
 
854
                 const std::string& chan_name_a,
 
855
                 const std::string& cont_name_b,
 
856
                 const std::string& chan_name_b) {
 
857
    port_allocator_ = pa;
 
858
    next_message_id = message_id;
 
859
    local_name = lname;
 
860
    start_protocol = protocol;
 
861
    content_type = cont_type;
 
862
    content_name_a = cont_name_a;
 
863
    channel_name_a = chan_name_a;
 
864
    content_name_b = cont_name_b;
 
865
    channel_name_b = chan_name_b;
 
866
    session_created_count = 0;
 
867
    session_destroyed_count = 0;
 
868
    session_remote_description_update_count = 0;
 
869
    last_expected_sent_stanza = NULL;
 
870
    session = NULL;
 
871
    last_session_state = cricket::BaseSession::STATE_INIT;
 
872
    chan_a = NULL;
 
873
    chan_b = NULL;
 
874
    blow_up_on_error = true;
 
875
    error_count = 0;
 
876
 
 
877
    session_manager = new cricket::SessionManager(port_allocator_);
 
878
    session_manager->SignalSessionCreate.connect(
 
879
        this, &TestClient::OnSessionCreate);
 
880
    session_manager->SignalSessionDestroy.connect(
 
881
        this, &TestClient::OnSessionDestroy);
 
882
    session_manager->SignalOutgoingMessage.connect(
 
883
        this, &TestClient::OnOutgoingMessage);
 
884
 
 
885
    client = new TestSessionClient();
 
886
    session_manager->AddClient(content_type, client);
 
887
    EXPECT_EQ(client, session_manager->GetClient(content_type));
 
888
  }
 
889
 
 
890
  uint32 sent_stanza_count() const {
 
891
    return sent_stanzas.size();
 
892
  }
 
893
 
 
894
  const buzz::XmlElement* stanza() const {
 
895
    return last_expected_sent_stanza;
 
896
  }
 
897
 
 
898
  cricket::BaseSession::State session_state() const {
 
899
    EXPECT_EQ(last_session_state, session->state());
 
900
    return session->state();
 
901
  }
 
902
 
 
903
  void SetSessionState(cricket::BaseSession::State state) {
 
904
    session->SetState(state);
 
905
    EXPECT_EQ_WAIT(last_session_state, session->state(), kEventTimeout);
 
906
  }
 
907
 
 
908
  void CreateSession() {
 
909
    session_manager->CreateSession(local_name, content_type);
 
910
  }
 
911
 
 
912
  void DeliverStanza(const buzz::XmlElement* stanza) {
 
913
    session_manager->OnIncomingMessage(stanza);
 
914
  }
 
915
 
 
916
  void DeliverStanza(const std::string& str) {
 
917
    buzz::XmlElement* stanza = buzz::XmlElement::ForStr(str);
 
918
    session_manager->OnIncomingMessage(stanza);
 
919
    delete stanza;
 
920
  }
 
921
 
 
922
  void DeliverAckToLastStanza() {
 
923
    const buzz::XmlElement* orig_stanza = stanza();
 
924
    const buzz::XmlElement* response_stanza =
 
925
        buzz::XmlElement::ForStr(IqAck(orig_stanza->Attr(buzz::QN_IQ), "", ""));
 
926
    session_manager->OnIncomingResponse(orig_stanza, response_stanza);
 
927
    delete response_stanza;
 
928
  }
 
929
 
 
930
  void ExpectSentStanza(const std::string& expected) {
 
931
    EXPECT_TRUE(!sent_stanzas.empty()) <<
 
932
        "Found no stanza when expected " << expected;
 
933
 
 
934
    last_expected_sent_stanza = sent_stanzas.front();
 
935
    sent_stanzas.pop_front();
 
936
 
 
937
    std::string actual = last_expected_sent_stanza->Str();
 
938
    EXPECT_EQ(expected, actual);
 
939
  }
 
940
 
 
941
  void SkipUnsentStanza() {
 
942
    GetNextOutgoingMessageID();
 
943
  }
 
944
 
 
945
  bool HasTransport(const std::string& content_name) const {
 
946
    ASSERT(session != NULL);
 
947
    const cricket::Transport* transport = session->GetTransport(content_name);
 
948
    return transport != NULL && (kTransportType == transport->type());
 
949
  }
 
950
 
 
951
  bool HasChannel(const std::string& content_name,
 
952
                  const std::string& channel_name) const {
 
953
    ASSERT(session != NULL);
 
954
    const cricket::TransportChannel* channel =
 
955
        session->GetChannel(content_name, channel_name);
 
956
    return channel != NULL && (channel_name == channel->name());
 
957
  }
 
958
 
 
959
  cricket::TransportChannel* GetChannel(const std::string& content_name,
 
960
                                        const std::string& channel_name) const {
 
961
    ASSERT(session != NULL);
 
962
    return session->GetChannel(content_name, channel_name);
 
963
  }
 
964
 
 
965
  void OnSessionCreate(cricket::Session* created_session, bool initiate) {
 
966
    session_created_count += 1;
 
967
 
 
968
    session = created_session;
 
969
    session->set_current_protocol(start_protocol);
 
970
    session->set_allow_local_ips(true);
 
971
    session->SignalState.connect(this, &TestClient::OnSessionState);
 
972
    session->SignalError.connect(this, &TestClient::OnSessionError);
 
973
    session->SignalRemoteDescriptionUpdate.connect(
 
974
        this, &TestClient::OnSessionRemoteDescriptionUpdate);
 
975
 
 
976
    CreateChannels();
 
977
  }
 
978
 
 
979
  void OnSessionDestroy(cricket::Session *session) {
 
980
    session_destroyed_count += 1;
 
981
  }
 
982
 
 
983
  void OnSessionState(cricket::BaseSession* session,
 
984
                      cricket::BaseSession::State state) {
 
985
    // EXPECT_EQ does not allow use of this, hence the tmp variable.
 
986
    cricket::BaseSession* tmp = this->session;
 
987
    EXPECT_EQ(tmp, session);
 
988
    last_session_state = state;
 
989
  }
 
990
 
 
991
  void OnSessionError(cricket::BaseSession* session,
 
992
                      cricket::BaseSession::Error error) {
 
993
    // EXPECT_EQ does not allow use of this, hence the tmp variable.
 
994
    cricket::BaseSession* tmp = this->session;
 
995
    EXPECT_EQ(tmp, session);
 
996
    if (blow_up_on_error) {
 
997
      EXPECT_TRUE(false);
 
998
    } else {
 
999
      error_count++;
 
1000
    }
 
1001
  }
 
1002
 
 
1003
  void OnSessionRemoteDescriptionUpdate(cricket::BaseSession* session,
 
1004
      const cricket::ContentInfos& contents) {
 
1005
    session_remote_description_update_count++;
 
1006
  }
 
1007
 
 
1008
  void PrepareCandidates() {
 
1009
    session_manager->OnSignalingReady();
 
1010
  }
 
1011
 
 
1012
  void OnOutgoingMessage(cricket::SessionManager* manager,
 
1013
                         const buzz::XmlElement* stanza) {
 
1014
    buzz::XmlElement* elem = new buzz::XmlElement(*stanza);
 
1015
    EXPECT_TRUE(elem->Name() == buzz::QN_IQ);
 
1016
    EXPECT_TRUE(elem->HasAttr(buzz::QN_TO));
 
1017
    EXPECT_FALSE(elem->HasAttr(buzz::QN_FROM));
 
1018
    EXPECT_TRUE(elem->HasAttr(buzz::QN_TYPE));
 
1019
    EXPECT_TRUE((elem->Attr(buzz::QN_TYPE) == "set") ||
 
1020
                (elem->Attr(buzz::QN_TYPE) == "result") ||
 
1021
                (elem->Attr(buzz::QN_TYPE) == "error"));
 
1022
 
 
1023
    elem->SetAttr(buzz::QN_FROM, local_name);
 
1024
    if (elem->Attr(buzz::QN_TYPE) == "set") {
 
1025
      EXPECT_FALSE(elem->HasAttr(buzz::QN_ID));
 
1026
      elem->SetAttr(buzz::QN_ID, GetNextOutgoingMessageID());
 
1027
    }
 
1028
 
 
1029
    // Uncommenting this is useful for debugging.
 
1030
    // PrintStanza("OutgoingMessage", elem);
 
1031
    sent_stanzas.push_back(elem);
 
1032
  }
 
1033
 
 
1034
  std::string GetNextOutgoingMessageID() {
 
1035
    int message_id = (*next_message_id)++;
 
1036
    std::ostringstream ost;
 
1037
    ost << message_id;
 
1038
    return ost.str();
 
1039
  }
 
1040
 
 
1041
  void CreateChannels() {
 
1042
    ASSERT(session != NULL);
 
1043
    chan_a = new ChannelHandler(
 
1044
        session->CreateChannel(content_name_a, channel_name_a), channel_name_a);
 
1045
    chan_b = new ChannelHandler(
 
1046
        session->CreateChannel(content_name_b, channel_name_b), channel_name_b);
 
1047
  }
 
1048
 
 
1049
  int* next_message_id;
 
1050
  std::string local_name;
 
1051
  SignalingProtocol start_protocol;
 
1052
  std::string content_type;
 
1053
  std::string content_name_a;
 
1054
  std::string channel_name_a;
 
1055
  std::string content_name_b;
 
1056
  std::string channel_name_b;
 
1057
 
 
1058
  uint32 session_created_count;
 
1059
  uint32 session_destroyed_count;
 
1060
  uint32 session_remote_description_update_count;
 
1061
  std::deque<buzz::XmlElement*> sent_stanzas;
 
1062
  buzz::XmlElement* last_expected_sent_stanza;
 
1063
 
 
1064
  cricket::SessionManager* session_manager;
 
1065
  TestSessionClient* client;
 
1066
  cricket::PortAllocator* port_allocator_;
 
1067
  cricket::Session* session;
 
1068
  cricket::BaseSession::State last_session_state;
 
1069
  ChannelHandler* chan_a;
 
1070
  ChannelHandler* chan_b;
 
1071
  bool blow_up_on_error;
 
1072
  int error_count;
 
1073
};
 
1074
 
 
1075
class SessionTest : public testing::Test {
 
1076
 protected:
 
1077
  virtual void SetUp() {
 
1078
    // Seed needed for each test to satisfy expectations.
 
1079
    talk_base::SetRandomTestMode(true);
 
1080
  }
 
1081
 
 
1082
  virtual void TearDown() {
 
1083
    talk_base::SetRandomTestMode(false);
 
1084
  }
 
1085
 
 
1086
  // Tests sending data between two clients, over two channels.
 
1087
  void TestSendRecv(ChannelHandler* chan1a,
 
1088
                    ChannelHandler* chan1b,
 
1089
                    ChannelHandler* chan2a,
 
1090
                    ChannelHandler* chan2b) {
 
1091
    const char* dat1a = "spamspamspamspamspamspamspambakedbeansspam";
 
1092
    const char* dat2a = "mapssnaebdekabmapsmapsmapsmapsmapsmapsmaps";
 
1093
    const char* dat1b = "Lobster Thermidor a Crevette with a mornay sauce...";
 
1094
    const char* dat2b = "...ecuas yanrom a htiw etteverC a rodimrehT retsboL";
 
1095
 
 
1096
    for (int i = 0; i < 20; i++) {
 
1097
      chan1a->Send(dat1a, strlen(dat1a));
 
1098
      chan1b->Send(dat1b, strlen(dat1b));
 
1099
      chan2a->Send(dat2a, strlen(dat2a));
 
1100
      chan2b->Send(dat2b, strlen(dat2b));
 
1101
 
 
1102
      EXPECT_EQ_WAIT(i + 1, chan1a->data_count, kEventTimeout);
 
1103
      EXPECT_EQ_WAIT(i + 1, chan1b->data_count, kEventTimeout);
 
1104
      EXPECT_EQ_WAIT(i + 1, chan2a->data_count, kEventTimeout);
 
1105
      EXPECT_EQ_WAIT(i + 1, chan2b->data_count, kEventTimeout);
 
1106
 
 
1107
      EXPECT_EQ(strlen(dat2a), chan1a->last_size);
 
1108
      EXPECT_EQ(strlen(dat2b), chan1b->last_size);
 
1109
      EXPECT_EQ(strlen(dat1a), chan2a->last_size);
 
1110
      EXPECT_EQ(strlen(dat1b), chan2b->last_size);
 
1111
 
 
1112
      EXPECT_EQ(0, std::memcmp(chan1a->last_data, dat2a,
 
1113
                               strlen(dat2a)));
 
1114
      EXPECT_EQ(0, std::memcmp(chan1b->last_data, dat2b,
 
1115
                               strlen(dat2b)));
 
1116
      EXPECT_EQ(0, std::memcmp(chan2a->last_data, dat1a,
 
1117
                               strlen(dat1a)));
 
1118
      EXPECT_EQ(0, std::memcmp(chan2b->last_data, dat1b,
 
1119
                               strlen(dat1b)));
 
1120
    }
 
1121
  }
 
1122
 
 
1123
  // Test an initiate from one client to another, each with
 
1124
  // independent initial protocols.  Checks for the correct initiates,
 
1125
  // candidates, and accept messages, and tests that working network
 
1126
  // channels are established.
 
1127
  void TestSession(SignalingProtocol initiator_protocol,
 
1128
                   SignalingProtocol responder_protocol,
 
1129
                   SignalingProtocol resulting_protocol,
 
1130
                   const std::string& gingle_content_type,
 
1131
                   const std::string& content_type,
 
1132
                   const std::string& content_name_a,
 
1133
                   const std::string& channel_name_a,
 
1134
                   const std::string& content_name_b,
 
1135
                   const std::string& channel_name_b,
 
1136
                   const std::string& initiate_xml,
 
1137
                   const std::string& transport_info_a_xml,
 
1138
                   const std::string& transport_info_b_xml,
 
1139
                   const std::string& transport_info_reply_a_xml,
 
1140
                   const std::string& transport_info_reply_b_xml,
 
1141
                   const std::string& accept_xml,
 
1142
                   bool bundle = false) {
 
1143
    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
 
1144
        new TestPortAllocator());
 
1145
    int next_message_id = 0;
 
1146
 
 
1147
    talk_base::scoped_ptr<TestClient> initiator(
 
1148
        new TestClient(allocator.get(), &next_message_id,
 
1149
                       kInitiator, initiator_protocol,
 
1150
                       content_type,
 
1151
                       content_name_a,  channel_name_a,
 
1152
                       content_name_b,  channel_name_b));
 
1153
    talk_base::scoped_ptr<TestClient> responder(
 
1154
        new TestClient(allocator.get(), &next_message_id,
 
1155
                       kResponder, responder_protocol,
 
1156
                       content_type,
 
1157
                       content_name_a,  channel_name_a,
 
1158
                       content_name_b,  channel_name_b));
 
1159
 
 
1160
    // Create Session and check channels and state.
 
1161
    initiator->CreateSession();
 
1162
    EXPECT_EQ(1U, initiator->session_created_count);
 
1163
    EXPECT_EQ(kSessionId, initiator->session->id());
 
1164
    EXPECT_EQ(initiator->session->local_name(), kInitiator);
 
1165
    EXPECT_EQ(cricket::BaseSession::STATE_INIT,
 
1166
              initiator->session_state());
 
1167
 
 
1168
    EXPECT_TRUE(initiator->HasTransport(content_name_a));
 
1169
    EXPECT_TRUE(initiator->HasChannel(content_name_a, channel_name_a));
 
1170
    EXPECT_TRUE(initiator->HasTransport(content_name_b));
 
1171
    EXPECT_TRUE(initiator->HasChannel(content_name_b, channel_name_b));
 
1172
 
 
1173
    // Initiate and expect initiate message sent.
 
1174
    cricket::SessionDescription* offer = NewTestSessionDescription(
 
1175
        gingle_content_type,
 
1176
        content_name_a, content_type,
 
1177
        content_name_b, content_type);
 
1178
    if (bundle) {
 
1179
      cricket::ContentGroup group(cricket::GROUP_TYPE_BUNDLE);
 
1180
      group.AddContentName(content_name_a);
 
1181
      group.AddContentName(content_name_b);
 
1182
      EXPECT_TRUE(group.HasContentName(content_name_a));
 
1183
      EXPECT_TRUE(group.HasContentName(content_name_b));
 
1184
      offer->AddGroup(group);
 
1185
    }
 
1186
    EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
 
1187
    EXPECT_EQ(initiator->session->remote_name(), kResponder);
 
1188
    EXPECT_EQ(initiator->session->local_description(), offer);
 
1189
 
 
1190
    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1191
    EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
 
1192
              initiator->session_state());
 
1193
 
 
1194
    initiator->ExpectSentStanza(
 
1195
        IqSet("0", kInitiator, kResponder, initiate_xml));
 
1196
 
 
1197
    // Deliver the initiate. Expect ack and session created with
 
1198
    // transports.
 
1199
    responder->DeliverStanza(initiator->stanza());
 
1200
    responder->ExpectSentStanza(
 
1201
        IqAck("0", kResponder, kInitiator));
 
1202
    EXPECT_EQ(0U, responder->sent_stanza_count());
 
1203
 
 
1204
    EXPECT_EQ(1U, responder->session_created_count);
 
1205
    EXPECT_EQ(kSessionId, responder->session->id());
 
1206
    EXPECT_EQ(responder->session->local_name(), kResponder);
 
1207
    EXPECT_EQ(responder->session->remote_name(), kInitiator);
 
1208
    EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
 
1209
              responder->session_state());
 
1210
 
 
1211
    EXPECT_TRUE(responder->HasTransport(content_name_a));
 
1212
    EXPECT_TRUE(responder->HasChannel(content_name_a, channel_name_a));
 
1213
    EXPECT_TRUE(responder->HasTransport(content_name_b));
 
1214
    EXPECT_TRUE(responder->HasChannel(content_name_b, channel_name_b));
 
1215
 
 
1216
    // Expect transport-info message from initiator.
 
1217
    // But don't send candidates until initiate ack is received.
 
1218
    initiator->PrepareCandidates();
 
1219
    WAIT(initiator->sent_stanza_count() > 0, 100);
 
1220
    EXPECT_EQ(0U, initiator->sent_stanza_count());
 
1221
    initiator->DeliverAckToLastStanza();
 
1222
    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1223
    initiator->ExpectSentStanza(
 
1224
        IqSet("1", kInitiator, kResponder, transport_info_a_xml));
 
1225
 
 
1226
    // Deliver transport-info and expect ack.
 
1227
    responder->DeliverStanza(initiator->stanza());
 
1228
    responder->ExpectSentStanza(
 
1229
        IqAck("1", kResponder, kInitiator));
 
1230
 
 
1231
    if (!transport_info_b_xml.empty()) {
 
1232
      // Expect second transport-info message from initiator.
 
1233
      EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1234
      initiator->ExpectSentStanza(
 
1235
          IqSet("2", kInitiator, kResponder, transport_info_b_xml));
 
1236
      EXPECT_EQ(0U, initiator->sent_stanza_count());
 
1237
 
 
1238
      // Deliver second transport-info message and expect ack.
 
1239
      responder->DeliverStanza(initiator->stanza());
 
1240
      responder->ExpectSentStanza(
 
1241
          IqAck("2", kResponder, kInitiator));
 
1242
    } else {
 
1243
      EXPECT_EQ(0U, initiator->sent_stanza_count());
 
1244
      EXPECT_EQ(0U, responder->sent_stanza_count());
 
1245
      initiator->SkipUnsentStanza();
 
1246
    }
 
1247
 
 
1248
    // Expect reply transport-info message from responder.
 
1249
    responder->PrepareCandidates();
 
1250
    EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
 
1251
    responder->ExpectSentStanza(
 
1252
        IqSet("3", kResponder, kInitiator, transport_info_reply_a_xml));
 
1253
 
 
1254
    // Deliver reply transport-info and expect ack.
 
1255
    initiator->DeliverStanza(responder->stanza());
 
1256
    initiator->ExpectSentStanza(
 
1257
        IqAck("3", kInitiator, kResponder));
 
1258
 
 
1259
    if (!transport_info_reply_b_xml.empty()) {
 
1260
      // Expect second reply transport-info message from responder.
 
1261
      EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
 
1262
      responder->ExpectSentStanza(
 
1263
          IqSet("4", kResponder, kInitiator, transport_info_reply_b_xml));
 
1264
      EXPECT_EQ(0U, responder->sent_stanza_count());
 
1265
 
 
1266
      // Deliver second reply transport-info message and expect ack.
 
1267
      initiator->DeliverStanza(responder->stanza());
 
1268
      initiator->ExpectSentStanza(
 
1269
          IqAck("4", kInitiator, kResponder));
 
1270
      EXPECT_EQ(0U, initiator->sent_stanza_count());
 
1271
    } else {
 
1272
      EXPECT_EQ(0U, initiator->sent_stanza_count());
 
1273
      EXPECT_EQ(0U, responder->sent_stanza_count());
 
1274
      responder->SkipUnsentStanza();
 
1275
    }
 
1276
 
 
1277
    // The channels should be able to become writable at this point.  This
 
1278
    // requires pinging, so it may take a little while.
 
1279
    EXPECT_TRUE_WAIT(initiator->chan_a->writable() &&
 
1280
                     initiator->chan_a->readable(), kEventTimeout);
 
1281
    EXPECT_TRUE_WAIT(initiator->chan_b->writable() &&
 
1282
                     initiator->chan_b->readable(), kEventTimeout);
 
1283
    EXPECT_TRUE_WAIT(responder->chan_a->writable() &&
 
1284
                     responder->chan_a->readable(), kEventTimeout);
 
1285
    EXPECT_TRUE_WAIT(responder->chan_b->writable() &&
 
1286
                     responder->chan_b->readable(), kEventTimeout);
 
1287
 
 
1288
    // Accept the session and expect accept stanza.
 
1289
    cricket::SessionDescription* answer = NewTestSessionDescription(
 
1290
        gingle_content_type,
 
1291
        content_name_a, content_type,
 
1292
        content_name_b, content_type);
 
1293
    if (bundle) {
 
1294
      cricket::ContentGroup group(cricket::GROUP_TYPE_BUNDLE);
 
1295
      group.AddContentName(content_name_a);
 
1296
      group.AddContentName(content_name_b);
 
1297
      EXPECT_TRUE(group.HasContentName(content_name_a));
 
1298
      EXPECT_TRUE(group.HasContentName(content_name_b));
 
1299
      answer->AddGroup(group);
 
1300
    }
 
1301
    EXPECT_TRUE(responder->session->Accept(answer));
 
1302
    EXPECT_EQ(responder->session->local_description(), answer);
 
1303
 
 
1304
    responder->ExpectSentStanza(
 
1305
        IqSet("5", kResponder, kInitiator, accept_xml));
 
1306
 
 
1307
    EXPECT_EQ(0U, responder->sent_stanza_count());
 
1308
 
 
1309
    // Deliver the accept message and expect an ack.
 
1310
    initiator->DeliverStanza(responder->stanza());
 
1311
    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1312
    initiator->ExpectSentStanza(
 
1313
        IqAck("5", kInitiator, kResponder));
 
1314
    EXPECT_EQ(0U, initiator->sent_stanza_count());
 
1315
 
 
1316
    // Both sessions should be in progress and have functioning
 
1317
    // channels.
 
1318
    EXPECT_EQ(resulting_protocol, initiator->session->current_protocol());
 
1319
    EXPECT_EQ(resulting_protocol, responder->session->current_protocol());
 
1320
    EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
 
1321
                   initiator->session_state(), kEventTimeout);
 
1322
    EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
 
1323
                   responder->session_state(), kEventTimeout);
 
1324
    if (bundle) {
 
1325
      cricket::TransportChannel* initiator_chan_a = initiator->chan_a->channel;
 
1326
      cricket::TransportChannel* initiator_chan_b = initiator->chan_b->channel;
 
1327
 
 
1328
      // Since we know these are TransportChannelProxy, type cast it.
 
1329
      cricket::TransportChannelProxy* initiator_proxy_chan_a =
 
1330
          static_cast<cricket::TransportChannelProxy*>(initiator_chan_a);
 
1331
      cricket::TransportChannelProxy* initiator_proxy_chan_b =
 
1332
              static_cast<cricket::TransportChannelProxy*>(initiator_chan_b);
 
1333
      EXPECT_TRUE(initiator_proxy_chan_a->impl() != NULL);
 
1334
      EXPECT_TRUE(initiator_proxy_chan_b->impl() != NULL);
 
1335
      EXPECT_EQ(initiator_proxy_chan_a->impl(), initiator_proxy_chan_b->impl());
 
1336
 
 
1337
      cricket::TransportChannel* responder_chan_a = responder->chan_a->channel;
 
1338
      cricket::TransportChannel* responder_chan_b = responder->chan_b->channel;
 
1339
 
 
1340
      // Since we know these are TransportChannelProxy, type cast it.
 
1341
      cricket::TransportChannelProxy* responder_proxy_chan_a =
 
1342
          static_cast<cricket::TransportChannelProxy*>(responder_chan_a);
 
1343
      cricket::TransportChannelProxy* responder_proxy_chan_b =
 
1344
              static_cast<cricket::TransportChannelProxy*>(responder_chan_b);
 
1345
      EXPECT_TRUE(responder_proxy_chan_a->impl() != NULL);
 
1346
      EXPECT_TRUE(responder_proxy_chan_b->impl() != NULL);
 
1347
      EXPECT_EQ(responder_proxy_chan_a->impl(), responder_proxy_chan_b->impl());
 
1348
    }
 
1349
    TestSendRecv(initiator->chan_a, initiator->chan_b,
 
1350
                 responder->chan_a, responder->chan_b);
 
1351
 
 
1352
    if (resulting_protocol == PROTOCOL_JINGLE) {
 
1353
      // Deliver a description-info message to the initiator and check if the
 
1354
      // content description changes.
 
1355
      EXPECT_EQ(0U, initiator->session_remote_description_update_count);
 
1356
 
 
1357
      const cricket::SessionDescription* old_session_desc =
 
1358
          initiator->session->remote_description();
 
1359
      const cricket::ContentInfo* old_content_a =
 
1360
          old_session_desc->GetContentByName(content_name_a);
 
1361
      const cricket::ContentDescription* old_content_desc_a =
 
1362
          old_content_a->description;
 
1363
      const cricket::ContentInfo* old_content_b =
 
1364
          old_session_desc->GetContentByName(content_name_b);
 
1365
      const cricket::ContentDescription* old_content_desc_b =
 
1366
          old_content_b->description;
 
1367
      EXPECT_TRUE(old_content_desc_a != NULL);
 
1368
      EXPECT_TRUE(old_content_desc_b != NULL);
 
1369
 
 
1370
      LOG(LS_INFO) << "A " << old_content_a->name;
 
1371
      LOG(LS_INFO) << "B " << old_content_b->name;
 
1372
 
 
1373
      std::string description_info_xml =
 
1374
          JingleDescriptionInfoXml(content_name_a, content_type);
 
1375
      initiator->DeliverStanza(
 
1376
          IqSet("6", kResponder, kInitiator, description_info_xml));
 
1377
      responder->SkipUnsentStanza();
 
1378
      EXPECT_EQ(1U, initiator->session_remote_description_update_count);
 
1379
 
 
1380
      const cricket::SessionDescription* new_session_desc =
 
1381
          initiator->session->remote_description();
 
1382
      const cricket::ContentInfo* new_content_a =
 
1383
          new_session_desc->GetContentByName(content_name_a);
 
1384
      const cricket::ContentDescription* new_content_desc_a =
 
1385
          new_content_a->description;
 
1386
      const cricket::ContentInfo* new_content_b =
 
1387
          new_session_desc->GetContentByName(content_name_b);
 
1388
      const cricket::ContentDescription* new_content_desc_b =
 
1389
          new_content_b->description;
 
1390
      EXPECT_TRUE(new_content_desc_a != NULL);
 
1391
      EXPECT_TRUE(new_content_desc_b != NULL);
 
1392
 
 
1393
      // TODO: We used to replace contents from an update, but
 
1394
      // that no longer works with partial updates.  We need to figure out
 
1395
      // a way to merge patial updates into contents.  For now, users of
 
1396
      // Session should listen to SignalRemoteDescriptionUpdate and handle
 
1397
      // updates.  They should not expect remote_description to be the
 
1398
      // latest value.
 
1399
      // See session.cc OnDescriptionInfoMessage.
 
1400
 
 
1401
      // EXPECT_NE(old_content_desc_a, new_content_desc_a);
 
1402
 
 
1403
      // if (content_name_a != content_name_b) {
 
1404
      //   // If content_name_a != content_name_b, then b's content description
 
1405
      //   // should not have changed since the description-info message only
 
1406
      //   // contained an update for content_name_a.
 
1407
      //   EXPECT_EQ(old_content_desc_b, new_content_desc_b);
 
1408
      // }
 
1409
 
 
1410
      EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1411
      initiator->ExpectSentStanza(
 
1412
          IqAck("6", kInitiator, kResponder));
 
1413
      EXPECT_EQ(0U, initiator->sent_stanza_count());
 
1414
    } else {
 
1415
      responder->SkipUnsentStanza();
 
1416
    }
 
1417
 
 
1418
    initiator->session->Terminate();
 
1419
    initiator->ExpectSentStanza(
 
1420
        IqSet("7", kInitiator, kResponder,
 
1421
              TerminateXml(resulting_protocol,
 
1422
                           cricket::STR_TERMINATE_SUCCESS)));
 
1423
 
 
1424
    responder->DeliverStanza(initiator->stanza());
 
1425
    responder->ExpectSentStanza(
 
1426
        IqAck("7", kResponder, kInitiator));
 
1427
    EXPECT_EQ(cricket::BaseSession::STATE_SENTTERMINATE,
 
1428
              initiator->session_state());
 
1429
    EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE,
 
1430
              responder->session_state());
 
1431
  }
 
1432
 
 
1433
  // Test an initiate with other content, called "main".
 
1434
  void TestOtherContent(SignalingProtocol initiator_protocol,
 
1435
                        SignalingProtocol responder_protocol,
 
1436
                        SignalingProtocol resulting_protocol) {
 
1437
    std::string content_name = "main";
 
1438
    std::string content_type = "http://oink.splat/session";
 
1439
    std::string content_name_a = content_name;
 
1440
    std::string channel_name_a = "rtcp";
 
1441
    std::string content_name_b = content_name;
 
1442
    std::string channel_name_b = "rtp";
 
1443
    std::string initiate_xml = InitiateXml(
 
1444
        initiator_protocol,
 
1445
        content_name_a, content_type);
 
1446
    std::string transport_info_a_xml = TransportInfo4Xml(
 
1447
        initiator_protocol, content_name,
 
1448
        channel_name_a, 0, 1,
 
1449
        channel_name_b, 2, 3);
 
1450
    std::string transport_info_b_xml = "";
 
1451
    std::string transport_info_reply_a_xml = TransportInfo4Xml(
 
1452
        resulting_protocol, content_name,
 
1453
        channel_name_a, 4, 5,
 
1454
        channel_name_b, 6, 7);
 
1455
    std::string transport_info_reply_b_xml = "";
 
1456
    std::string accept_xml = AcceptXml(
 
1457
        resulting_protocol,
 
1458
        content_name_a, content_type);
 
1459
 
 
1460
 
 
1461
    TestSession(initiator_protocol, responder_protocol, resulting_protocol,
 
1462
                content_type,
 
1463
                content_type,
 
1464
                content_name_a, channel_name_a,
 
1465
                content_name_b, channel_name_b,
 
1466
                initiate_xml,
 
1467
                transport_info_a_xml, transport_info_b_xml,
 
1468
                transport_info_reply_a_xml, transport_info_reply_b_xml,
 
1469
                accept_xml);
 
1470
  }
 
1471
 
 
1472
  // Test an initiate with audio content.
 
1473
  void TestAudioContent(SignalingProtocol initiator_protocol,
 
1474
                        SignalingProtocol responder_protocol,
 
1475
                        SignalingProtocol resulting_protocol) {
 
1476
    std::string gingle_content_type = cricket::NS_GINGLE_AUDIO;
 
1477
    std::string content_name = cricket::CN_AUDIO;
 
1478
    std::string content_type = cricket::NS_JINGLE_RTP;
 
1479
    std::string channel_name_a = "rtcp";
 
1480
    std::string channel_name_b = "rtp";
 
1481
    std::string initiate_xml = InitiateXml(
 
1482
        initiator_protocol,
 
1483
        gingle_content_type,
 
1484
        content_name, content_type,
 
1485
        "", "");
 
1486
    std::string transport_info_a_xml = TransportInfo4Xml(
 
1487
        initiator_protocol, content_name,
 
1488
        channel_name_a, 0, 1,
 
1489
        channel_name_b, 2, 3);
 
1490
    std::string transport_info_b_xml = "";
 
1491
    std::string transport_info_reply_a_xml = TransportInfo4Xml(
 
1492
        resulting_protocol, content_name,
 
1493
        channel_name_a, 4, 5,
 
1494
        channel_name_b, 6, 7);
 
1495
    std::string transport_info_reply_b_xml = "";
 
1496
    std::string accept_xml = AcceptXml(
 
1497
        resulting_protocol,
 
1498
        gingle_content_type,
 
1499
        content_name, content_type,
 
1500
        "", "");
 
1501
 
 
1502
 
 
1503
    TestSession(initiator_protocol, responder_protocol, resulting_protocol,
 
1504
                gingle_content_type,
 
1505
                content_type,
 
1506
                content_name, channel_name_a,
 
1507
                content_name, channel_name_b,
 
1508
                initiate_xml,
 
1509
                transport_info_a_xml, transport_info_b_xml,
 
1510
                transport_info_reply_a_xml, transport_info_reply_b_xml,
 
1511
                accept_xml);
 
1512
  }
 
1513
 
 
1514
  // Since media content is "split" into two contents (audio and
 
1515
  // video), we need to treat it special.
 
1516
  void TestVideoContents(SignalingProtocol initiator_protocol,
 
1517
                         SignalingProtocol responder_protocol,
 
1518
                         SignalingProtocol resulting_protocol) {
 
1519
    std::string content_type = cricket::NS_JINGLE_RTP;
 
1520
    std::string gingle_content_type = cricket::NS_GINGLE_VIDEO;
 
1521
    std::string content_name_a = cricket::CN_AUDIO;
 
1522
    std::string channel_name_a = "rtcp";
 
1523
    std::string content_name_b = cricket::CN_VIDEO;
 
1524
    std::string channel_name_b = "video_rtp";
 
1525
 
 
1526
    std::string initiate_xml = InitiateXml(
 
1527
        initiator_protocol,
 
1528
        gingle_content_type,
 
1529
        content_name_a, content_type,
 
1530
        content_name_b, content_type);
 
1531
    std::string transport_info_a_xml = TransportInfo2Xml(
 
1532
        initiator_protocol, content_name_a,
 
1533
        channel_name_a, 0, 1);
 
1534
    std::string transport_info_b_xml = TransportInfo2Xml(
 
1535
        initiator_protocol, content_name_b,
 
1536
        channel_name_b, 2, 3);
 
1537
    std::string transport_info_reply_a_xml = TransportInfo2Xml(
 
1538
        resulting_protocol, content_name_a,
 
1539
        channel_name_a, 4, 5);
 
1540
    std::string transport_info_reply_b_xml = TransportInfo2Xml(
 
1541
        resulting_protocol, content_name_b,
 
1542
        channel_name_b, 6, 7);
 
1543
    std::string accept_xml = AcceptXml(
 
1544
        resulting_protocol,
 
1545
        gingle_content_type,
 
1546
        content_name_a, content_type,
 
1547
        content_name_b, content_type);
 
1548
 
 
1549
    TestSession(initiator_protocol, responder_protocol, resulting_protocol,
 
1550
                gingle_content_type,
 
1551
                content_type,
 
1552
                content_name_a, channel_name_a,
 
1553
                content_name_b, channel_name_b,
 
1554
                initiate_xml,
 
1555
                transport_info_a_xml, transport_info_b_xml,
 
1556
                transport_info_reply_a_xml, transport_info_reply_b_xml,
 
1557
                accept_xml);
 
1558
  }
 
1559
 
 
1560
  void TestBadRedirect(SignalingProtocol protocol) {
 
1561
    std::string content_name = "main";
 
1562
    std::string content_type = "http://oink.splat/session";
 
1563
    std::string channel_name_a = "chana";
 
1564
    std::string channel_name_b = "chanb";
 
1565
    std::string initiate_xml = InitiateXml(
 
1566
        protocol, content_name, content_type);
 
1567
    std::string transport_info_xml = TransportInfo4Xml(
 
1568
        protocol, content_name,
 
1569
        channel_name_a, 0, 1,
 
1570
        channel_name_b, 2, 3);
 
1571
    std::string transport_info_reply_xml = TransportInfo4Xml(
 
1572
        protocol, content_name,
 
1573
        channel_name_a, 4, 5,
 
1574
        channel_name_b, 6, 7);
 
1575
    std::string accept_xml = AcceptXml(
 
1576
        protocol, content_name, content_type);
 
1577
    std::string responder_full = kResponder + "/full";
 
1578
 
 
1579
    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
 
1580
        new TestPortAllocator());
 
1581
    int next_message_id = 0;
 
1582
 
 
1583
    talk_base::scoped_ptr<TestClient> initiator(
 
1584
        new TestClient(allocator.get(), &next_message_id,
 
1585
                       kInitiator, protocol,
 
1586
                       content_type,
 
1587
                       content_name, channel_name_a,
 
1588
                       content_name, channel_name_b));
 
1589
 
 
1590
    talk_base::scoped_ptr<TestClient> responder(
 
1591
        new TestClient(allocator.get(), &next_message_id,
 
1592
                       responder_full, protocol,
 
1593
                       content_type,
 
1594
                       content_name,  channel_name_a,
 
1595
                       content_name,  channel_name_b));
 
1596
 
 
1597
    // Create Session and check channels and state.
 
1598
    initiator->CreateSession();
 
1599
    EXPECT_EQ(1U, initiator->session_created_count);
 
1600
    EXPECT_EQ(kSessionId, initiator->session->id());
 
1601
    EXPECT_EQ(initiator->session->local_name(), kInitiator);
 
1602
    EXPECT_EQ(cricket::BaseSession::STATE_INIT,
 
1603
              initiator->session_state());
 
1604
 
 
1605
    EXPECT_TRUE(initiator->HasChannel(content_name, channel_name_a));
 
1606
    EXPECT_TRUE(initiator->HasChannel(content_name, channel_name_b));
 
1607
 
 
1608
    // Initiate and expect initiate message sent.
 
1609
    cricket::SessionDescription* offer = NewTestSessionDescription(
 
1610
        content_name, content_type);
 
1611
    EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
 
1612
    EXPECT_EQ(initiator->session->remote_name(), kResponder);
 
1613
    EXPECT_EQ(initiator->session->local_description(), offer);
 
1614
 
 
1615
    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1616
    EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
 
1617
              initiator->session_state());
 
1618
    initiator->ExpectSentStanza(
 
1619
        IqSet("0", kInitiator, kResponder, initiate_xml));
 
1620
 
 
1621
    // Expect transport-info message from initiator.
 
1622
    initiator->DeliverAckToLastStanza();
 
1623
    initiator->PrepareCandidates();
 
1624
    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1625
    initiator->ExpectSentStanza(
 
1626
        IqSet("1", kInitiator, kResponder, transport_info_xml));
 
1627
 
 
1628
    // Send an unauthorized redirect to the initiator and expect it be ignored.
 
1629
    initiator->blow_up_on_error = false;
 
1630
    const buzz::XmlElement* initiate_stanza = initiator->stanza();
 
1631
    talk_base::scoped_ptr<buzz::XmlElement> redirect_stanza(
 
1632
        buzz::XmlElement::ForStr(
 
1633
            IqError("ER", kResponder, kInitiator,
 
1634
                    RedirectXml(protocol, initiate_xml, "not@allowed.com"))));
 
1635
    initiator->session_manager->OnFailedSend(
 
1636
        initiate_stanza, redirect_stanza.get());
 
1637
    EXPECT_EQ(initiator->session->remote_name(), kResponder);
 
1638
    initiator->blow_up_on_error = true;
 
1639
    EXPECT_EQ(initiator->error_count, 1);
 
1640
  }
 
1641
 
 
1642
  void TestGoodRedirect(SignalingProtocol protocol) {
 
1643
    std::string content_name = "main";
 
1644
    std::string content_type = "http://oink.splat/session";
 
1645
    std::string channel_name_a = "chana";
 
1646
    std::string channel_name_b = "chanb";
 
1647
    std::string initiate_xml = InitiateXml(
 
1648
        protocol, content_name, content_type);
 
1649
    std::string transport_info_xml = TransportInfo4Xml(
 
1650
        protocol, content_name,
 
1651
        channel_name_a, 0, 1,
 
1652
        channel_name_b, 2, 3);
 
1653
    std::string transport_info_reply_xml = TransportInfo4Xml(
 
1654
        protocol, content_name,
 
1655
        channel_name_a, 4, 5,
 
1656
        channel_name_b, 6, 7);
 
1657
    std::string accept_xml = AcceptXml(
 
1658
        protocol, content_name, content_type);
 
1659
    std::string responder_full = kResponder + "/full";
 
1660
 
 
1661
    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
 
1662
        new TestPortAllocator());
 
1663
    int next_message_id = 0;
 
1664
 
 
1665
    talk_base::scoped_ptr<TestClient> initiator(
 
1666
        new TestClient(allocator.get(), &next_message_id,
 
1667
                       kInitiator, protocol,
 
1668
                       content_type,
 
1669
                       content_name, channel_name_a,
 
1670
                       content_name, channel_name_b));
 
1671
 
 
1672
    talk_base::scoped_ptr<TestClient> responder(
 
1673
        new TestClient(allocator.get(), &next_message_id,
 
1674
                       responder_full, protocol,
 
1675
                       content_type,
 
1676
                       content_name,  channel_name_a,
 
1677
                       content_name,  channel_name_b));
 
1678
 
 
1679
    // Create Session and check channels and state.
 
1680
    initiator->CreateSession();
 
1681
    EXPECT_EQ(1U, initiator->session_created_count);
 
1682
    EXPECT_EQ(kSessionId, initiator->session->id());
 
1683
    EXPECT_EQ(initiator->session->local_name(), kInitiator);
 
1684
    EXPECT_EQ(cricket::BaseSession::STATE_INIT,
 
1685
              initiator->session_state());
 
1686
 
 
1687
    EXPECT_TRUE(initiator->HasChannel(content_name, channel_name_a));
 
1688
    EXPECT_TRUE(initiator->HasChannel(content_name, channel_name_b));
 
1689
 
 
1690
    // Initiate and expect initiate message sent.
 
1691
    cricket::SessionDescription* offer = NewTestSessionDescription(
 
1692
        content_name, content_type);
 
1693
    EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
 
1694
    EXPECT_EQ(initiator->session->remote_name(), kResponder);
 
1695
    EXPECT_EQ(initiator->session->local_description(), offer);
 
1696
 
 
1697
    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1698
    EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
 
1699
              initiator->session_state());
 
1700
    initiator->ExpectSentStanza(
 
1701
        IqSet("0", kInitiator, kResponder, initiate_xml));
 
1702
 
 
1703
    // Expect transport-info message from initiator.
 
1704
    initiator->DeliverAckToLastStanza();
 
1705
    initiator->PrepareCandidates();
 
1706
    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1707
    initiator->ExpectSentStanza(
 
1708
        IqSet("1", kInitiator, kResponder, transport_info_xml));
 
1709
 
 
1710
    // Send a redirect to the initiator and expect all of the message
 
1711
    // to be resent.
 
1712
    const buzz::XmlElement* initiate_stanza = initiator->stanza();
 
1713
    talk_base::scoped_ptr<buzz::XmlElement> redirect_stanza(
 
1714
        buzz::XmlElement::ForStr(
 
1715
            IqError("ER2", kResponder, kInitiator,
 
1716
                    RedirectXml(protocol, initiate_xml, responder_full))));
 
1717
    initiator->session_manager->OnFailedSend(
 
1718
        initiate_stanza, redirect_stanza.get());
 
1719
    EXPECT_EQ(initiator->session->remote_name(), responder_full);
 
1720
 
 
1721
    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1722
    initiator->ExpectSentStanza(
 
1723
        IqSet("2", kInitiator, responder_full, initiate_xml));
 
1724
    initiator->ExpectSentStanza(
 
1725
        IqSet("3", kInitiator, responder_full, transport_info_xml));
 
1726
 
 
1727
    // Deliver the initiate. Expect ack and session created with
 
1728
    // transports.
 
1729
    responder->DeliverStanza(
 
1730
        IqSet("2", kInitiator, responder_full, initiate_xml));
 
1731
    responder->ExpectSentStanza(
 
1732
        IqAck("2", responder_full, kInitiator));
 
1733
    EXPECT_EQ(0U, responder->sent_stanza_count());
 
1734
 
 
1735
    EXPECT_EQ(1U, responder->session_created_count);
 
1736
    EXPECT_EQ(kSessionId, responder->session->id());
 
1737
    EXPECT_EQ(responder->session->local_name(), responder_full);
 
1738
    EXPECT_EQ(responder->session->remote_name(), kInitiator);
 
1739
    EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
 
1740
              responder->session_state());
 
1741
 
 
1742
    EXPECT_TRUE(responder->HasChannel(content_name, channel_name_a));
 
1743
    EXPECT_TRUE(responder->HasChannel(content_name, channel_name_b));
 
1744
 
 
1745
    // Deliver transport-info and expect ack.
 
1746
    responder->DeliverStanza(
 
1747
        IqSet("3", kInitiator, responder_full, transport_info_xml));
 
1748
    responder->ExpectSentStanza(
 
1749
        IqAck("3", responder_full, kInitiator));
 
1750
 
 
1751
    // Expect reply transport-infos sent to new remote JID
 
1752
    responder->PrepareCandidates();
 
1753
    EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
 
1754
    responder->ExpectSentStanza(
 
1755
        IqSet("4", responder_full, kInitiator, transport_info_reply_xml));
 
1756
 
 
1757
    initiator->DeliverStanza(responder->stanza());
 
1758
    initiator->ExpectSentStanza(
 
1759
        IqAck("4", kInitiator, responder_full));
 
1760
 
 
1761
    // The channels should be able to become writable at this point.  This
 
1762
    // requires pinging, so it may take a little while.
 
1763
    EXPECT_TRUE_WAIT(initiator->chan_a->writable() &&
 
1764
                     initiator->chan_a->readable(), kEventTimeout);
 
1765
    EXPECT_TRUE_WAIT(initiator->chan_b->writable() &&
 
1766
                     initiator->chan_b->readable(), kEventTimeout);
 
1767
    EXPECT_TRUE_WAIT(responder->chan_a->writable() &&
 
1768
                     responder->chan_a->readable(), kEventTimeout);
 
1769
    EXPECT_TRUE_WAIT(responder->chan_b->writable() &&
 
1770
                     responder->chan_b->readable(), kEventTimeout);
 
1771
 
 
1772
    // Accept the session and expect accept stanza.
 
1773
    cricket::SessionDescription* answer = NewTestSessionDescription(
 
1774
        content_name, content_type);
 
1775
    EXPECT_TRUE(responder->session->Accept(answer));
 
1776
    EXPECT_EQ(responder->session->local_description(), answer);
 
1777
 
 
1778
    responder->ExpectSentStanza(
 
1779
        IqSet("5", responder_full, kInitiator, accept_xml));
 
1780
    EXPECT_EQ(0U, responder->sent_stanza_count());
 
1781
 
 
1782
    // Deliver the accept message and expect an ack.
 
1783
    initiator->DeliverStanza(responder->stanza());
 
1784
    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1785
    initiator->ExpectSentStanza(
 
1786
        IqAck("5", kInitiator, responder_full));
 
1787
    EXPECT_EQ(0U, initiator->sent_stanza_count());
 
1788
 
 
1789
    // Both sessions should be in progress and have functioning
 
1790
    // channels.
 
1791
    EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
 
1792
                   initiator->session_state(), kEventTimeout);
 
1793
    EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
 
1794
                   responder->session_state(), kEventTimeout);
 
1795
    TestSendRecv(initiator->chan_a, initiator->chan_b,
 
1796
                 responder->chan_a, responder->chan_b);
 
1797
  }
 
1798
 
 
1799
  void TestCandidatesInInitiateAndAccept(const std::string& test_name) {
 
1800
    std::string content_name = "main";
 
1801
    std::string content_type = "http://oink.splat/session";
 
1802
    std::string channel_name_a = "rtcp";
 
1803
    std::string channel_name_b = "rtp";
 
1804
    cricket::SignalingProtocol protocol = PROTOCOL_JINGLE;
 
1805
 
 
1806
    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
 
1807
        new TestPortAllocator());
 
1808
    int next_message_id = 0;
 
1809
 
 
1810
    talk_base::scoped_ptr<TestClient> initiator(
 
1811
        new TestClient(allocator.get(), &next_message_id,
 
1812
                       kInitiator, protocol,
 
1813
                       content_type,
 
1814
                       content_name,  channel_name_a,
 
1815
                       content_name,  channel_name_b));
 
1816
 
 
1817
    talk_base::scoped_ptr<TestClient> responder(
 
1818
        new TestClient(allocator.get(), &next_message_id,
 
1819
                       kResponder, protocol,
 
1820
                       content_type,
 
1821
                       content_name,  channel_name_a,
 
1822
                       content_name,  channel_name_b));
 
1823
 
 
1824
    // Create Session and check channels and state.
 
1825
    initiator->CreateSession();
 
1826
    EXPECT_TRUE(initiator->HasTransport(content_name));
 
1827
    EXPECT_TRUE(initiator->HasChannel(content_name, channel_name_a));
 
1828
    EXPECT_TRUE(initiator->HasTransport(content_name));
 
1829
    EXPECT_TRUE(initiator->HasChannel(content_name, channel_name_b));
 
1830
 
 
1831
    // Initiate and expect initiate message sent.
 
1832
    cricket::SessionDescription* offer = NewTestSessionDescription(
 
1833
        content_name, content_type);
 
1834
    EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
 
1835
 
 
1836
    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1837
    EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
 
1838
              initiator->session_state());
 
1839
    initiator->ExpectSentStanza(
 
1840
        IqSet("0", kInitiator, kResponder,
 
1841
              InitiateXml(protocol, content_name, content_type)));
 
1842
 
 
1843
    // Fake the delivery the initiate and candidates together.
 
1844
    responder->DeliverStanza(
 
1845
        IqSet("A", kInitiator, kResponder,
 
1846
            JingleInitiateActionXml(
 
1847
                JingleContentXml(
 
1848
                    content_name, content_type, kTransportType,
 
1849
                    P2pCandidateXml(channel_name_a, 0) +
 
1850
                    P2pCandidateXml(channel_name_a, 1) +
 
1851
                    P2pCandidateXml(channel_name_b, 2) +
 
1852
                    P2pCandidateXml(channel_name_b, 3)))));
 
1853
    responder->ExpectSentStanza(
 
1854
        IqAck("A", kResponder, kInitiator));
 
1855
    EXPECT_EQ(0U, responder->sent_stanza_count());
 
1856
 
 
1857
    EXPECT_EQ(1U, responder->session_created_count);
 
1858
    EXPECT_EQ(kSessionId, responder->session->id());
 
1859
    EXPECT_EQ(responder->session->local_name(), kResponder);
 
1860
    EXPECT_EQ(responder->session->remote_name(), kInitiator);
 
1861
    EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
 
1862
              responder->session_state());
 
1863
 
 
1864
    EXPECT_TRUE(responder->HasTransport(content_name));
 
1865
    EXPECT_TRUE(responder->HasChannel(content_name, channel_name_a));
 
1866
    EXPECT_TRUE(responder->HasTransport(content_name));
 
1867
    EXPECT_TRUE(responder->HasChannel(content_name, channel_name_b));
 
1868
 
 
1869
    // Expect transport-info message from initiator.
 
1870
    // But don't send candidates until initiate ack is received.
 
1871
    initiator->DeliverAckToLastStanza();
 
1872
    initiator->PrepareCandidates();
 
1873
    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1874
    initiator->ExpectSentStanza(
 
1875
        IqSet("1", kInitiator, kResponder,
 
1876
              TransportInfo4Xml(protocol, content_name,
 
1877
                                channel_name_a, 0, 1,
 
1878
                                channel_name_b, 2, 3)));
 
1879
 
 
1880
    responder->PrepareCandidates();
 
1881
    EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
 
1882
    responder->ExpectSentStanza(
 
1883
        IqSet("2", kResponder, kInitiator,
 
1884
              TransportInfo4Xml(protocol, content_name,
 
1885
                                channel_name_a, 4, 5,
 
1886
                                channel_name_b, 6, 7)));
 
1887
 
 
1888
    // Accept the session and expect accept stanza.
 
1889
    cricket::SessionDescription* answer = NewTestSessionDescription(
 
1890
        content_name, content_type);
 
1891
    EXPECT_TRUE(responder->session->Accept(answer));
 
1892
 
 
1893
    responder->ExpectSentStanza(
 
1894
        IqSet("3", kResponder, kInitiator,
 
1895
              AcceptXml(protocol, content_name, content_type)));
 
1896
    EXPECT_EQ(0U, responder->sent_stanza_count());
 
1897
 
 
1898
    // Fake the delivery the accept and candidates together.
 
1899
    initiator->DeliverStanza(
 
1900
        IqSet("B", kResponder, kInitiator,
 
1901
            JingleActionXml("session-accept",
 
1902
                JingleContentXml(
 
1903
                    content_name, content_type, kTransportType,
 
1904
                    P2pCandidateXml(channel_name_a, 4) +
 
1905
                    P2pCandidateXml(channel_name_a, 5) +
 
1906
                    P2pCandidateXml(channel_name_b, 6) +
 
1907
                    P2pCandidateXml(channel_name_b, 7)))));
 
1908
    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
 
1909
    initiator->ExpectSentStanza(
 
1910
        IqAck("B", kInitiator, kResponder));
 
1911
    EXPECT_EQ(0U, initiator->sent_stanza_count());
 
1912
 
 
1913
    // The channels should be able to become writable at this point.  This
 
1914
    // requires pinging, so it may take a little while.
 
1915
    EXPECT_TRUE_WAIT(initiator->chan_a->writable() &&
 
1916
                     initiator->chan_a->readable(), kEventTimeout);
 
1917
    EXPECT_TRUE_WAIT(initiator->chan_b->writable() &&
 
1918
                     initiator->chan_b->readable(), kEventTimeout);
 
1919
    EXPECT_TRUE_WAIT(responder->chan_a->writable() &&
 
1920
                     responder->chan_a->readable(), kEventTimeout);
 
1921
    EXPECT_TRUE_WAIT(responder->chan_b->writable() &&
 
1922
                     responder->chan_b->readable(), kEventTimeout);
 
1923
 
 
1924
 
 
1925
    // Both sessions should be in progress and have functioning
 
1926
    // channels.
 
1927
    EXPECT_EQ(protocol, initiator->session->current_protocol());
 
1928
    EXPECT_EQ(protocol, responder->session->current_protocol());
 
1929
    EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
 
1930
                   initiator->session_state(), kEventTimeout);
 
1931
    EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
 
1932
                   responder->session_state(), kEventTimeout);
 
1933
    TestSendRecv(initiator->chan_a, initiator->chan_b,
 
1934
                 responder->chan_a, responder->chan_b);
 
1935
  }
 
1936
 
 
1937
  // Tests that when an initiator terminates right after initiate,
 
1938
  // everything behaves correctly.
 
1939
  void TestEarlyTerminationFromInitiator(SignalingProtocol protocol) {
 
1940
    std::string content_name = "main";
 
1941
    std::string content_type = "http://oink.splat/session";
 
1942
 
 
1943
    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
 
1944
        new TestPortAllocator());
 
1945
    int next_message_id = 0;
 
1946
 
 
1947
    talk_base::scoped_ptr<TestClient> initiator(
 
1948
        new TestClient(allocator.get(), &next_message_id,
 
1949
                       kInitiator, protocol,
 
1950
                       content_type,
 
1951
                       content_name, "a",
 
1952
                       content_name, "b"));
 
1953
 
 
1954
    talk_base::scoped_ptr<TestClient> responder(
 
1955
        new TestClient(allocator.get(), &next_message_id,
 
1956
                       kResponder, protocol,
 
1957
                       content_type,
 
1958
                       content_name,  "a",
 
1959
                       content_name,  "b"));
 
1960
 
 
1961
    // Send initiate
 
1962
    initiator->CreateSession();
 
1963
    EXPECT_TRUE(initiator->session->Initiate(
 
1964
        kResponder, NewTestSessionDescription(content_name, content_type)));
 
1965
    initiator->ExpectSentStanza(
 
1966
        IqSet("0", kInitiator, kResponder,
 
1967
              InitiateXml(protocol, content_name, content_type)));
 
1968
    EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
 
1969
              initiator->session_state());
 
1970
 
 
1971
    responder->DeliverStanza(initiator->stanza());
 
1972
    responder->ExpectSentStanza(
 
1973
        IqAck("0", kResponder, kInitiator));
 
1974
    EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
 
1975
              responder->session_state());
 
1976
 
 
1977
    initiator->session->TerminateWithReason(cricket::STR_TERMINATE_ERROR);
 
1978
    initiator->ExpectSentStanza(
 
1979
        IqSet("1", kInitiator, kResponder,
 
1980
              TerminateXml(protocol, cricket::STR_TERMINATE_ERROR)));
 
1981
    EXPECT_EQ(cricket::BaseSession::STATE_SENTTERMINATE,
 
1982
              initiator->session_state());
 
1983
 
 
1984
    responder->DeliverStanza(initiator->stanza());
 
1985
    responder->ExpectSentStanza(
 
1986
        IqAck("1", kResponder, kInitiator));
 
1987
    EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE,
 
1988
              responder->session_state());
 
1989
  }
 
1990
 
 
1991
  // Tests that when the responder rejects, everything behaves
 
1992
  // correctly.
 
1993
  void TestRejection(SignalingProtocol protocol) {
 
1994
    std::string content_name = "main";
 
1995
    std::string content_type = "http://oink.splat/session";
 
1996
 
 
1997
    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
 
1998
        new TestPortAllocator());
 
1999
    int next_message_id = 0;
 
2000
 
 
2001
    talk_base::scoped_ptr<TestClient> initiator(
 
2002
        new TestClient(allocator.get(), &next_message_id,
 
2003
                       kInitiator, protocol,
 
2004
                       content_type,
 
2005
                       content_name, "a",
 
2006
                       content_name, "b"));
 
2007
 
 
2008
    // Send initiate
 
2009
    initiator->CreateSession();
 
2010
    EXPECT_TRUE(initiator->session->Initiate(
 
2011
        kResponder, NewTestSessionDescription(content_name, content_type)));
 
2012
    initiator->ExpectSentStanza(
 
2013
        IqSet("0", kInitiator, kResponder,
 
2014
              InitiateXml(protocol, content_name, content_type)));
 
2015
    EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
 
2016
              initiator->session_state());
 
2017
 
 
2018
    initiator->DeliverStanza(
 
2019
        IqSet("1", kResponder, kInitiator,
 
2020
              RejectXml(protocol, cricket::STR_TERMINATE_ERROR)));
 
2021
    initiator->ExpectSentStanza(
 
2022
        IqAck("1", kInitiator, kResponder));
 
2023
    if (protocol == PROTOCOL_JINGLE) {
 
2024
      EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE,
 
2025
                initiator->session_state());
 
2026
    } else {
 
2027
      EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDREJECT,
 
2028
                initiator->session_state());
 
2029
    }
 
2030
  }
 
2031
 
 
2032
  void TestTransportMux() {
 
2033
    SignalingProtocol initiator_protocol = PROTOCOL_JINGLE;
 
2034
    SignalingProtocol responder_protocol = PROTOCOL_JINGLE;
 
2035
    SignalingProtocol resulting_protocol = PROTOCOL_JINGLE;
 
2036
    std::string content_type = cricket::NS_JINGLE_RTP;
 
2037
    std::string gingle_content_type = cricket::NS_GINGLE_VIDEO;
 
2038
    std::string content_name_a = cricket::CN_AUDIO;
 
2039
    std::string channel_name_a = "rtcp";
 
2040
    std::string content_name_b = cricket::CN_VIDEO;
 
2041
    std::string channel_name_b = "video_rtp";
 
2042
 
 
2043
    std::string initiate_xml = InitiateXml(
 
2044
        initiator_protocol,
 
2045
        gingle_content_type,
 
2046
        content_name_a, content_type,
 
2047
        content_name_b, content_type, true);
 
2048
    std::string transport_info_a_xml = TransportInfo2Xml(
 
2049
        initiator_protocol, content_name_a,
 
2050
        channel_name_a, 0, 1);
 
2051
    std::string transport_info_b_xml = TransportInfo2Xml(
 
2052
        initiator_protocol, content_name_b,
 
2053
        channel_name_b, 2, 3);
 
2054
    std::string transport_info_reply_a_xml = TransportInfo2Xml(
 
2055
        resulting_protocol, content_name_a,
 
2056
        channel_name_a, 4, 5);
 
2057
    std::string transport_info_reply_b_xml = TransportInfo2Xml(
 
2058
        resulting_protocol, content_name_b,
 
2059
        channel_name_b, 6, 7);
 
2060
    std::string accept_xml = AcceptXml(
 
2061
        resulting_protocol,
 
2062
        gingle_content_type,
 
2063
        content_name_a, content_type,
 
2064
        content_name_b, content_type, true);
 
2065
 
 
2066
    TestSession(initiator_protocol, responder_protocol, resulting_protocol,
 
2067
                gingle_content_type,
 
2068
                content_type,
 
2069
                content_name_a, channel_name_a,
 
2070
                content_name_b, channel_name_b,
 
2071
                initiate_xml,
 
2072
                transport_info_a_xml, transport_info_b_xml,
 
2073
                transport_info_reply_a_xml, transport_info_reply_b_xml,
 
2074
                accept_xml,
 
2075
                true);
 
2076
  }
 
2077
};
 
2078
 
 
2079
// For each of these, "X => Y = Z" means "if a client with protocol X
 
2080
// initiates to a client with protocol Y, they end up speaking protocol Z.
 
2081
 
 
2082
// Gingle => Gingle = Gingle (with other content)
 
2083
TEST_F(SessionTest, GingleToGingleOtherContent) {
 
2084
  TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
 
2085
}
 
2086
 
 
2087
// Gingle => Gingle = Gingle (with audio content)
 
2088
TEST_F(SessionTest, GingleToGingleAudioContent) {
 
2089
  TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
 
2090
}
 
2091
 
 
2092
// Gingle => Gingle = Gingle (with video contents)
 
2093
TEST_F(SessionTest, GingleToGingleVideoContents) {
 
2094
  TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
 
2095
}
 
2096
 
 
2097
 
 
2098
// Jingle => Jingle = Jingle (with other content)
 
2099
TEST_F(SessionTest, JingleToJingleOtherContent) {
 
2100
  TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
 
2101
}
 
2102
 
 
2103
// Jingle => Jingle = Jingle (with audio content)
 
2104
TEST_F(SessionTest, JingleToJingleAudioContent) {
 
2105
  TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
 
2106
}
 
2107
 
 
2108
// Jingle => Jingle = Jingle (with video contents)
 
2109
TEST_F(SessionTest, JingleToJingleVideoContents) {
 
2110
  TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
 
2111
}
 
2112
 
 
2113
 
 
2114
// Hybrid => Hybrid = Jingle (with other content)
 
2115
TEST_F(SessionTest, HybridToHybridOtherContent) {
 
2116
  TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
 
2117
}
 
2118
 
 
2119
// Hybrid => Hybrid = Jingle (with audio content)
 
2120
TEST_F(SessionTest, HybridToHybridAudioContent) {
 
2121
  TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
 
2122
}
 
2123
 
 
2124
// Hybrid => Hybrid = Jingle (with video contents)
 
2125
TEST_F(SessionTest, HybridToHybridVideoContents) {
 
2126
  TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
 
2127
}
 
2128
 
 
2129
 
 
2130
// Gingle => Hybrid = Gingle (with other content)
 
2131
TEST_F(SessionTest, GingleToHybridOtherContent) {
 
2132
  TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
 
2133
}
 
2134
 
 
2135
// Gingle => Hybrid = Gingle (with audio content)
 
2136
TEST_F(SessionTest, GingleToHybridAudioContent) {
 
2137
  TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
 
2138
}
 
2139
 
 
2140
// Gingle => Hybrid = Gingle (with video contents)
 
2141
TEST_F(SessionTest, GingleToHybridVideoContents) {
 
2142
  TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
 
2143
}
 
2144
 
 
2145
 
 
2146
// Jingle => Hybrid = Jingle (with other content)
 
2147
TEST_F(SessionTest, JingleToHybridOtherContent) {
 
2148
  TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
 
2149
}
 
2150
 
 
2151
// Jingle => Hybrid = Jingle (with audio content)
 
2152
TEST_F(SessionTest, JingleToHybridAudioContent) {
 
2153
  TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
 
2154
}
 
2155
 
 
2156
// Jingle => Hybrid = Jingle (with video contents)
 
2157
TEST_F(SessionTest, JingleToHybridVideoContents) {
 
2158
  TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
 
2159
}
 
2160
 
 
2161
 
 
2162
// Hybrid => Gingle = Gingle (with other content)
 
2163
TEST_F(SessionTest, HybridToGingleOtherContent) {
 
2164
  TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
 
2165
}
 
2166
 
 
2167
// Hybrid => Gingle = Gingle (with audio content)
 
2168
TEST_F(SessionTest, HybridToGingleAudioContent) {
 
2169
  TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
 
2170
}
 
2171
 
 
2172
// Hybrid => Gingle = Gingle (with video contents)
 
2173
TEST_F(SessionTest, HybridToGingleVideoContents) {
 
2174
  TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
 
2175
}
 
2176
 
 
2177
 
 
2178
// Hybrid => Jingle = Jingle (with other content)
 
2179
TEST_F(SessionTest, HybridToJingleOtherContent) {
 
2180
  TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
 
2181
}
 
2182
 
 
2183
// Hybrid => Jingle = Jingle (with audio content)
 
2184
TEST_F(SessionTest, HybridToJingleAudioContent) {
 
2185
  TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
 
2186
}
 
2187
 
 
2188
// Hybrid => Jingle = Jingle (with video contents)
 
2189
TEST_F(SessionTest, HybridToJingleVideoContents) {
 
2190
  TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
 
2191
}
 
2192
 
 
2193
 
 
2194
TEST_F(SessionTest, GingleEarlyTerminationFromInitiator) {
 
2195
  TestEarlyTerminationFromInitiator(PROTOCOL_GINGLE);
 
2196
}
 
2197
 
 
2198
TEST_F(SessionTest, JingleEarlyTerminationFromInitiator) {
 
2199
  TestEarlyTerminationFromInitiator(PROTOCOL_JINGLE);
 
2200
}
 
2201
 
 
2202
TEST_F(SessionTest, HybridEarlyTerminationFromInitiator) {
 
2203
  TestEarlyTerminationFromInitiator(PROTOCOL_HYBRID);
 
2204
}
 
2205
 
 
2206
TEST_F(SessionTest, GingleRejection) {
 
2207
  TestRejection(PROTOCOL_GINGLE);
 
2208
}
 
2209
 
 
2210
TEST_F(SessionTest, JingleRejection) {
 
2211
  TestRejection(PROTOCOL_JINGLE);
 
2212
}
 
2213
 
 
2214
TEST_F(SessionTest, GingleGoodRedirect) {
 
2215
  TestGoodRedirect(PROTOCOL_GINGLE);
 
2216
}
 
2217
 
 
2218
TEST_F(SessionTest, JingleGoodRedirect) {
 
2219
  TestGoodRedirect(PROTOCOL_JINGLE);
 
2220
}
 
2221
 
 
2222
TEST_F(SessionTest, GingleBadRedirect) {
 
2223
  TestBadRedirect(PROTOCOL_GINGLE);
 
2224
}
 
2225
 
 
2226
TEST_F(SessionTest, JingleBadRedirect) {
 
2227
  TestBadRedirect(PROTOCOL_JINGLE);
 
2228
}
 
2229
 
 
2230
TEST_F(SessionTest, TestCandidatesInInitiateAndAccept) {
 
2231
  TestCandidatesInInitiateAndAccept("Candidates in initiate/accept");
 
2232
}
 
2233
 
 
2234
TEST_F(SessionTest, TestTransportMux) {
 
2235
  TestTransportMux();
 
2236
}