Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include <iostream>
6 #include <map>
7 #include <algorithm>
8 #include <string>
9 #include <unistd.h>
11 #include "base/basictypes.h"
12 #include "logging.h"
14 #define GTEST_HAS_RTTI 0
15 #include "gtest/gtest.h"
16 #include "gtest_utils.h"
18 #include "nspr.h"
19 #include "nss.h"
20 #include "ssl.h"
21 #include "prthread.h"
23 #include "cpr_stdlib.h"
24 #include "FakePCObserver.h"
25 #include "FakeMediaStreams.h"
26 #include "FakeMediaStreamsImpl.h"
27 #include "PeerConnectionImpl.h"
28 #include "PeerConnectionCtx.h"
29 #include "PeerConnectionMedia.h"
30 #include "MediaPipeline.h"
31 #include "runnable_utils.h"
32 #include "nsServiceManagerUtils.h"
33 #include "mozilla/Services.h"
34 #include "nsIPrefService.h"
35 #include "nsIPrefBranch.h"
36 #include "nsNetUtil.h"
37 #include "nsIIOService.h"
38 #include "nsIDNSService.h"
39 #include "nsWeakReference.h"
40 #include "nricectx.h"
41 #include "rlogringbuffer.h"
42 #include "mozilla/SyncRunnable.h"
43 #include "logging.h"
44 #include "stunserver.h"
45 #include "stunserver.cpp"
46 #include "PeerConnectionImplEnumsBinding.cpp"
48 #include "mtransport_test_utils.h"
49 #include "gtest_ringbuffer_dumper.h"
50 MtransportTestUtils *test_utils;
51 nsCOMPtr<nsIThread> gMainThread;
52 nsCOMPtr<nsIThread> gGtestThread;
53 bool gTestsComplete = false;
55 #ifndef USE_FAKE_MEDIA_STREAMS
56 #error USE_FAKE_MEDIA_STREAMS undefined
57 #endif
58 #ifndef USE_FAKE_PCOBSERVER
59 #error USE_FAKE_PCOBSERVER undefined
60 #endif
62 static int kDefaultTimeout = 7000;
63 static bool fRtcpMux = true;
65 static std::string callerName = "caller";
66 static std::string calleeName = "callee";
68 #define ARRAY_TO_STL(container, type, array) \
69 (container<type>((array), (array) + PR_ARRAY_SIZE(array)))
71 #define ARRAY_TO_SET(type, array) ARRAY_TO_STL(std::set, type, array)
73 std::string g_stun_server_address((char *)"23.21.150.121");
74 uint16_t g_stun_server_port(3478);
75 std::string kBogusSrflxAddress((char *)"192.0.2.1");
76 uint16_t kBogusSrflxPort(1001);
78 namespace sipcc {
80 // We can't use mozilla/dom/MediaConstraintsBinding.h here because it uses
81 // nsString, so we pass constraints in using MediaConstraintsExternal instead
83 class MediaConstraints : public MediaConstraintsExternal {
84 public:
85 void setBooleanConstraint(const char *namePtr, bool value, bool mandatory) {
86 cc_boolean_constraint_t &member (getMember(namePtr));
87 member.was_passed = true;
88 member.value = value;
89 member.mandatory = mandatory;
90 }
91 private:
92 cc_boolean_constraint_t &getMember(const char *namePtr) {
93 if (strcmp(namePtr, "OfferToReceiveAudio") == 0) {
94 return mConstraints.offer_to_receive_audio;
95 }
96 if (strcmp(namePtr, "OfferToReceiveVideo") == 0) {
97 return mConstraints.offer_to_receive_video;
98 }
99 MOZ_ASSERT(false);
100 return mConstraints.moz_dont_offer_datachannel;
101 }
102 };
103 }
105 using namespace mozilla;
106 using namespace mozilla::dom;
108 namespace test {
109 std::string indent(const std::string &s, int width = 4) {
110 std::string prefix;
111 std::string out;
112 char previous = '\n';
113 prefix.assign(width, ' ');
114 for (std::string::const_iterator i = s.begin(); i != s.end(); i++) {
115 if (previous == '\n') {
116 out += prefix;
117 }
118 out += *i;
119 previous = *i;
120 }
121 return out;
122 }
124 static const std::string strSampleSdpAudioVideoNoIce =
125 "v=0\r\n"
126 "o=Mozilla-SIPUA 4949 0 IN IP4 10.86.255.143\r\n"
127 "s=SIP Call\r\n"
128 "t=0 0\r\n"
129 "a=ice-ufrag:qkEP\r\n"
130 "a=ice-pwd:ed6f9GuHjLcoCN6sC/Eh7fVl\r\n"
131 "m=audio 16384 RTP/AVP 0 8 9 101\r\n"
132 "c=IN IP4 10.86.255.143\r\n"
133 "a=rtpmap:0 PCMU/8000\r\n"
134 "a=rtpmap:8 PCMA/8000\r\n"
135 "a=rtpmap:9 G722/8000\r\n"
136 "a=rtpmap:101 telephone-event/8000\r\n"
137 "a=fmtp:101 0-15\r\n"
138 "a=sendrecv\r\n"
139 "a=candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host\r\n"
140 "a=candidate:2 2 UDP 2130706431 192.168.2.2 50006 typ host\r\n"
141 "m=video 1024 RTP/AVP 97\r\n"
142 "c=IN IP4 10.86.255.143\r\n"
143 "a=rtpmap:120 VP8/90000\r\n"
144 "a=fmtp:97 profile-level-id=42E00C\r\n"
145 "a=sendrecv\r\n"
146 "a=candidate:1 1 UDP 2130706431 192.168.2.3 50007 typ host\r\n"
147 "a=candidate:2 2 UDP 2130706431 192.168.2.4 50008 typ host\r\n";
149 static const std::string strSampleCandidate =
150 "a=candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host\r\n";
152 static const std::string strSampleMid = "";
154 static const unsigned short nSamplelevel = 2;
156 static const std::string strG711SdpOffer =
157 "v=0\r\n"
158 "o=- 1 1 IN IP4 148.147.200.251\r\n"
159 "s=-\r\n"
160 "b=AS:64\r\n"
161 "t=0 0\r\n"
162 "a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:"
163 "7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n"
164 "m=audio 9000 RTP/AVP 0 8 126\r\n"
165 "c=IN IP4 148.147.200.251\r\n"
166 "b=TIAS:64000\r\n"
167 "a=rtpmap:0 PCMU/8000\r\n"
168 "a=rtpmap:8 PCMA/8000\r\n"
169 "a=rtpmap:126 telephone-event/8000\r\n"
170 "a=candidate:0 1 udp 2130706432 148.147.200.251 9000 typ host\r\n"
171 "a=candidate:0 2 udp 2130706432 148.147.200.251 9005 typ host\r\n"
172 "a=ice-ufrag:cYuakxkEKH+RApYE\r\n"
173 "a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n"
174 "a=sendrecv\r\n";
177 enum sdpTestFlags
178 {
179 SHOULD_SEND_AUDIO = (1<<0),
180 SHOULD_RECV_AUDIO = (1<<1),
181 SHOULD_INACTIVE_AUDIO = (1<<2),
182 SHOULD_REJECT_AUDIO = (1<<3),
183 SHOULD_OMIT_AUDIO = (1<<4),
184 DONT_CHECK_AUDIO = (1<<5),
185 SHOULD_CHECK_AUDIO = (1<<6),
187 SHOULD_SEND_VIDEO = (1<<8),
188 SHOULD_RECV_VIDEO = (1<<9),
189 SHOULD_INACTIVE_VIDEO = (1<<10),
190 SHOULD_REJECT_VIDEO = (1<<11),
191 SHOULD_OMIT_VIDEO = (1<<12),
192 DONT_CHECK_VIDEO = (1<<13),
193 SHOULD_CHECK_VIDEO = (1<<14),
195 SHOULD_INCLUDE_DATA = (1 << 16),
196 DONT_CHECK_DATA = (1 << 17),
198 SHOULD_SENDRECV_AUDIO = SHOULD_SEND_AUDIO | SHOULD_RECV_AUDIO,
199 SHOULD_SENDRECV_VIDEO = SHOULD_SEND_VIDEO | SHOULD_RECV_VIDEO,
200 SHOULD_SENDRECV_AV = SHOULD_SENDRECV_AUDIO | SHOULD_SENDRECV_VIDEO,
201 SHOULD_CHECK_AV = SHOULD_CHECK_AUDIO | SHOULD_CHECK_VIDEO,
203 AUDIO_FLAGS = SHOULD_SEND_AUDIO | SHOULD_RECV_AUDIO
204 | SHOULD_INACTIVE_AUDIO | SHOULD_REJECT_AUDIO
205 | DONT_CHECK_AUDIO | SHOULD_OMIT_AUDIO
206 | SHOULD_CHECK_AUDIO,
208 VIDEO_FLAGS = SHOULD_SEND_VIDEO | SHOULD_RECV_VIDEO
209 | SHOULD_INACTIVE_VIDEO | SHOULD_REJECT_VIDEO
210 | DONT_CHECK_VIDEO | SHOULD_OMIT_VIDEO
211 | SHOULD_CHECK_VIDEO
212 };
214 enum offerAnswerFlags
215 {
216 OFFER_NONE = 0, // Sugar to make function calls clearer.
217 OFFER_AUDIO = (1<<0),
218 OFFER_VIDEO = (1<<1),
219 // Leaving some room here for other media types
220 ANSWER_NONE = 0, // Sugar to make function calls clearer.
221 ANSWER_AUDIO = (1<<8),
222 ANSWER_VIDEO = (1<<9),
224 OFFER_AV = OFFER_AUDIO | OFFER_VIDEO,
225 ANSWER_AV = ANSWER_AUDIO | ANSWER_VIDEO
226 };
228 enum mediaPipelineFlags
229 {
230 PIPELINE_LOCAL = (1<<0),
231 PIPELINE_RTCP_MUX = (1<<1),
232 PIPELINE_SEND = (1<<2),
233 PIPELINE_VIDEO = (1<<3),
234 PIPELINE_RTCP_NACK = (1<<4)
235 };
238 class TestObserver : public AFakePCObserver
239 {
240 public:
241 TestObserver(sipcc::PeerConnectionImpl *peerConnection,
242 const std::string &aName) :
243 AFakePCObserver(peerConnection, aName) {}
245 size_t MatchingCandidates(const std::string& cand) {
246 size_t count = 0;
248 for (size_t i=0; i<candidates.size(); ++i) {
249 if (candidates[i].find(cand) != std::string::npos)
250 ++count;
251 }
253 return count;
254 }
256 NS_DECL_THREADSAFE_ISUPPORTS
257 NS_IMETHODIMP OnCreateOfferSuccess(const char* offer, ER&);
258 NS_IMETHODIMP OnCreateOfferError(uint32_t code, const char *msg, ER&);
259 NS_IMETHODIMP OnCreateAnswerSuccess(const char* answer, ER&);
260 NS_IMETHODIMP OnCreateAnswerError(uint32_t code, const char *msg, ER&);
261 NS_IMETHODIMP OnSetLocalDescriptionSuccess(ER&);
262 NS_IMETHODIMP OnSetRemoteDescriptionSuccess(ER&);
263 NS_IMETHODIMP OnSetLocalDescriptionError(uint32_t code, const char *msg, ER&);
264 NS_IMETHODIMP OnSetRemoteDescriptionError(uint32_t code, const char *msg, ER&);
265 NS_IMETHODIMP NotifyConnection(ER&);
266 NS_IMETHODIMP NotifyClosedConnection(ER&);
267 NS_IMETHODIMP NotifyDataChannel(nsIDOMDataChannel *channel, ER&);
268 NS_IMETHODIMP OnStateChange(PCObserverStateType state_type, ER&, void*);
269 NS_IMETHODIMP OnAddStream(nsIDOMMediaStream *stream, ER&);
270 NS_IMETHODIMP OnRemoveStream(ER&);
271 NS_IMETHODIMP OnAddTrack(ER&);
272 NS_IMETHODIMP OnRemoveTrack(ER&);
273 NS_IMETHODIMP OnAddIceCandidateSuccess(ER&);
274 NS_IMETHODIMP OnAddIceCandidateError(uint32_t code, const char *msg, ER&);
275 NS_IMETHODIMP OnIceCandidate(uint16_t level, const char *mid, const char *cand, ER&);
276 };
278 NS_IMPL_ISUPPORTS(TestObserver, nsISupportsWeakReference)
280 NS_IMETHODIMP
281 TestObserver::OnCreateOfferSuccess(const char* offer, ER&)
282 {
283 lastString = strdup(offer);
284 state = stateSuccess;
285 std::cout << name << ": onCreateOfferSuccess = " << std::endl << indent(offer)
286 << std::endl;
287 return NS_OK;
288 }
290 NS_IMETHODIMP
291 TestObserver::OnCreateOfferError(uint32_t code, const char *message, ER&)
292 {
293 lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code);
294 state = stateError;
295 std::cout << name << ": onCreateOfferError = " << code
296 << " (" << message << ")" << std::endl;
297 return NS_OK;
298 }
300 NS_IMETHODIMP
301 TestObserver::OnCreateAnswerSuccess(const char* answer, ER&)
302 {
303 lastString = strdup(answer);
304 state = stateSuccess;
305 std::cout << name << ": onCreateAnswerSuccess =" << std::endl
306 << indent(answer) << std::endl;
307 return NS_OK;
308 }
310 NS_IMETHODIMP
311 TestObserver::OnCreateAnswerError(uint32_t code, const char *message, ER&)
312 {
313 lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code);
314 std::cout << name << ": onCreateAnswerError = " << code
315 << " (" << message << ")" << std::endl;
316 state = stateError;
317 return NS_OK;
318 }
320 NS_IMETHODIMP
321 TestObserver::OnSetLocalDescriptionSuccess(ER&)
322 {
323 lastStatusCode = sipcc::PeerConnectionImpl::kNoError;
324 state = stateSuccess;
325 std::cout << name << ": onSetLocalDescriptionSuccess" << std::endl;
326 return NS_OK;
327 }
329 NS_IMETHODIMP
330 TestObserver::OnSetRemoteDescriptionSuccess(ER&)
331 {
332 lastStatusCode = sipcc::PeerConnectionImpl::kNoError;
333 state = stateSuccess;
334 std::cout << name << ": onSetRemoteDescriptionSuccess" << std::endl;
335 return NS_OK;
336 }
338 NS_IMETHODIMP
339 TestObserver::OnSetLocalDescriptionError(uint32_t code, const char *message, ER&)
340 {
341 lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code);
342 state = stateError;
343 std::cout << name << ": onSetLocalDescriptionError = " << code
344 << " (" << message << ")" << std::endl;
345 return NS_OK;
346 }
348 NS_IMETHODIMP
349 TestObserver::OnSetRemoteDescriptionError(uint32_t code, const char *message, ER&)
350 {
351 lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code);
352 state = stateError;
353 std::cout << name << ": onSetRemoteDescriptionError = " << code
354 << " (" << message << ")" << std::endl;
355 return NS_OK;
356 }
358 NS_IMETHODIMP
359 TestObserver::NotifyConnection(ER&)
360 {
361 std::cout << name << ": NotifyConnection" << std::endl;
362 return NS_OK;
363 }
365 NS_IMETHODIMP
366 TestObserver::NotifyClosedConnection(ER&)
367 {
368 std::cout << name << ": NotifyClosedConnection" << std::endl;
369 return NS_OK;
370 }
372 NS_IMETHODIMP
373 TestObserver::NotifyDataChannel(nsIDOMDataChannel *channel, ER&)
374 {
375 std::cout << name << ": NotifyDataChannel" << std::endl;
376 return NS_OK;
377 }
379 NS_IMETHODIMP
380 TestObserver::OnStateChange(PCObserverStateType state_type, ER&, void*)
381 {
382 nsresult rv;
383 PCImplReadyState gotready;
384 PCImplIceConnectionState gotice;
385 PCImplIceGatheringState goticegathering;
386 PCImplSipccState gotsipcc;
387 PCImplSignalingState gotsignaling;
389 std::cout << name << ": ";
391 switch (state_type)
392 {
393 case PCObserverStateType::ReadyState:
394 rv = pc->ReadyState(&gotready);
395 NS_ENSURE_SUCCESS(rv, rv);
396 std::cout << "Ready State: "
397 << PCImplReadyStateValues::strings[int(gotready)].value
398 << std::endl;
399 break;
400 case PCObserverStateType::IceConnectionState:
401 rv = pc->IceConnectionState(&gotice);
402 NS_ENSURE_SUCCESS(rv, rv);
403 std::cout << "ICE Connection State: "
404 << PCImplIceConnectionStateValues::strings[int(gotice)].value
405 << std::endl;
406 break;
407 case PCObserverStateType::IceGatheringState:
408 rv = pc->IceGatheringState(&goticegathering);
409 NS_ENSURE_SUCCESS(rv, rv);
410 std::cout
411 << "ICE Gathering State: "
412 << PCImplIceGatheringStateValues::strings[int(goticegathering)].value
413 << std::endl;
414 break;
415 case PCObserverStateType::SdpState:
416 std::cout << "SDP State: " << std::endl;
417 // NS_ENSURE_SUCCESS(rv, rv);
418 break;
419 case PCObserverStateType::SipccState:
420 rv = pc->SipccState(&gotsipcc);
421 NS_ENSURE_SUCCESS(rv, rv);
422 std::cout << "SIPCC State: "
423 << PCImplSipccStateValues::strings[int(gotsipcc)].value
424 << std::endl;
425 break;
426 case PCObserverStateType::SignalingState:
427 rv = pc->SignalingState(&gotsignaling);
428 NS_ENSURE_SUCCESS(rv, rv);
429 std::cout << "Signaling State: "
430 << PCImplSignalingStateValues::strings[int(gotsignaling)].value
431 << std::endl;
432 break;
433 default:
434 // Unknown State
435 MOZ_CRASH("Unknown state change type.");
436 break;
437 }
439 lastStateType = state_type;
440 return NS_OK;
441 }
444 NS_IMETHODIMP
445 TestObserver::OnAddStream(nsIDOMMediaStream *stream, ER&)
446 {
447 PR_ASSERT(stream);
449 DOMMediaStream *ms = static_cast<DOMMediaStream *>(stream);
451 std::cout << name << ": OnAddStream called hints=" << ms->GetHintContents()
452 << " thread=" << PR_GetCurrentThread() << std::endl ;
454 onAddStreamCalled = true;
456 streams.push_back(ms);
458 // We know that the media stream is secretly a Fake_SourceMediaStream,
459 // so now we can start it pulling from us
460 Fake_SourceMediaStream *fs = static_cast<Fake_SourceMediaStream *>(ms->GetStream());
462 test_utils->sts_target()->Dispatch(
463 WrapRunnable(fs, &Fake_SourceMediaStream::Start),
464 NS_DISPATCH_NORMAL);
466 return NS_OK;
467 }
469 NS_IMETHODIMP
470 TestObserver::OnRemoveStream(ER&)
471 {
472 state = stateSuccess;
473 return NS_OK;
474 }
476 NS_IMETHODIMP
477 TestObserver::OnAddTrack(ER&)
478 {
479 state = stateSuccess;
480 return NS_OK;
481 }
483 NS_IMETHODIMP
484 TestObserver::OnRemoveTrack(ER&)
485 {
486 state = stateSuccess;
487 return NS_OK;
488 }
490 NS_IMETHODIMP
491 TestObserver::OnIceCandidate(uint16_t level,
492 const char * mid,
493 const char * candidate, ER&)
494 {
495 std::cout << name << ": onIceCandidate [" << level << "/"
496 << mid << "] " << candidate << std::endl;
497 candidates.push_back(candidate);
498 return NS_OK;
499 }
501 NS_IMETHODIMP
502 TestObserver::OnAddIceCandidateSuccess(ER&)
503 {
504 lastStatusCode = sipcc::PeerConnectionImpl::kNoError;
505 state = stateSuccess;
506 std::cout << name << ": onAddIceCandidateSuccess" << std::endl;
507 addIceSuccessCount++;
508 return NS_OK;
509 }
511 NS_IMETHODIMP
512 TestObserver::OnAddIceCandidateError(uint32_t code, const char *message, ER&)
513 {
514 lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code);
515 state = stateError;
516 std::cout << name << ": onAddIceCandidateError = " << code
517 << " (" << message << ")" << std::endl;
518 return NS_OK;
519 }
521 class ParsedSDP {
522 public:
523 //Line number with the corresponding SDP line.
524 typedef std::pair<int, std::string> SdpLine;
526 ParsedSDP(std::string sdp):
527 sdp_(),
528 sdp_without_ice_(),
529 ice_candidates_(),
530 levels_(0),
531 num_lines(0)
532 {
533 sdp_ = sdp;
534 Parse();
535 }
537 void DeleteAllLines(std::string objType)
538 {
539 int count = sdp_map_.count(objType);
540 std::cout << "Removing " << count << " lines from SDP (" << objType
541 << ")" << std::endl;
543 for (int i = 0; i < count; i++) {
544 DeleteLine(objType);
545 }
546 }
548 void DeleteLine(std::string objType)
549 {
550 ReplaceLine(objType, "");
551 }
553 // Replaces the first instance of objType in the SDP with
554 // a new string.
555 // If content is an empty string then the line will be removed
556 void ReplaceLine(std::string objType, std::string content)
557 {
558 std::multimap<std::string, SdpLine>::iterator it;
559 it = sdp_map_.find(objType);
560 if(it != sdp_map_.end()) {
561 SdpLine sdp_line_pair = (*it).second;
562 int line_no = sdp_line_pair.first;
563 sdp_map_.erase(it);
564 if(content.empty()) {
565 return;
566 }
567 std::string value = content.substr(objType.length() + 1);
568 sdp_map_.insert(std::pair<std::string, SdpLine>(objType,
569 std::make_pair(line_no,value)));
570 }
571 }
573 void AddLine(std::string content)
574 {
575 size_t whiteSpace = content.find(' ');
576 std::string key;
577 std::string value;
578 if(whiteSpace == std::string::npos) {
579 key = content.substr(0, content.size() - 2);
580 value = "";
581 } else {
582 key = content.substr(0, whiteSpace);
583 value = content.substr(whiteSpace+1);
584 }
585 sdp_map_.insert(std::pair<std::string, SdpLine>(key,
586 std::make_pair(num_lines,value)));
587 num_lines++;
588 }
590 // Returns the values for all lines of the indicated type
591 // Removes trailing "\r\n" from values.
592 std::vector<std::string> GetLines(std::string objType) const
593 {
594 std::multimap<std::string, SdpLine>::const_iterator it, end;
595 std::vector<std::string> values;
596 it = sdp_map_.lower_bound(objType);
597 end = sdp_map_.upper_bound(objType);
598 while (it != end) {
599 std::string value = it->second.second;
600 if (value.find("\r") != std::string::npos) {
601 value = value.substr(0, value.find("\r"));
602 } else {
603 ADD_FAILURE();
604 }
605 values.push_back(value);
606 ++it;
607 }
608 return values;
609 }
611 //Parse SDP as std::string into map that looks like:
612 // key: sdp content till first space
613 // value : <line_number, sdp content after the first space>
614 void Parse()
615 {
616 size_t prev = 0;
617 size_t found = 0;
618 num_lines = 0;
619 for(;;) {
620 found = sdp_.find('\n', found + 1);
621 if (found == std::string::npos)
622 break;
623 std::string line = sdp_.substr(prev, (found - prev) + 1);
624 size_t whiteSpace = line.find(' ');
625 std::string key;
626 std::string value;
627 if(whiteSpace == std::string::npos) {
628 //this is the line with no extra contents
629 //example, v=0, a=sendrecv
630 key = line.substr(0, line.size() - 2);
631 //<line_no>:<valeu>
632 value = "";
633 } else {
634 key = line.substr(0, whiteSpace);
635 //<line_no>:<value>
636 value = line.substr(whiteSpace+1);
637 }
638 SdpLine sdp_line_pair = std::make_pair(num_lines,value);
639 sdp_map_.insert(std::pair<std::string, SdpLine>(key, sdp_line_pair));
640 num_lines++;
641 //storing ice candidates separately for quick acesss as needed
642 //for the trickle unit tests
643 if (line.find("a=candidate") == 0) {
644 // This is a candidate, strip of a= and \r\n
645 std::string cand = line.substr(2, line.size() - 4);
646 ice_candidates_.insert(std::pair<int, std::string>(levels_, cand));
647 } else {
648 sdp_without_ice_ += line;
649 }
650 if (line.find("m=") == 0) {
651 // This is an m-line
652 ++levels_;
653 }
654 prev = found + 1;
655 }
656 }
658 //Convert Internal SDP representation into String representation
659 std::string getSdp()
660 {
661 std::vector<std::string> sdp_lines(num_lines);
662 for (std::multimap<std::string, SdpLine>::iterator it = sdp_map_.begin();
663 it != sdp_map_.end(); ++it) {
665 SdpLine sdp_line_pair = (*it).second;
666 std::string value;
667 if(sdp_line_pair.second.length() == 0) {
668 value = (*it).first + "\r\n";
669 sdp_lines[sdp_line_pair.first] = value;
670 } else {
671 value = (*it).first + ' ' + sdp_line_pair.second;
672 sdp_lines[sdp_line_pair.first] = value;
673 }
674 }
676 //generate our final sdp in std::string format
677 std::string sdp;
678 for (size_t i = 0; i < sdp_lines.size(); i++)
679 {
680 sdp += sdp_lines[i];
681 }
683 return sdp;
684 }
688 std::string sdp_;
689 std::string sdp_without_ice_;
690 std::multimap<int, std::string> ice_candidates_;
691 std::multimap<std::string, SdpLine> sdp_map_;
692 int levels_;
693 int num_lines;
694 };
696 class SignalingAgent {
697 public:
698 SignalingAgent(const std::string &aName) : pc(nullptr), name(aName) {
699 cfg_.addStunServer(g_stun_server_address, g_stun_server_port);
701 pc = sipcc::PeerConnectionImpl::CreatePeerConnection();
702 EXPECT_TRUE(pc);
703 }
705 SignalingAgent(const std::string &aName, const std::string stun_addr,
706 uint16_t stun_port) : pc(nullptr), name(aName) {
707 cfg_.addStunServer(stun_addr, stun_port);
709 pc = sipcc::PeerConnectionImpl::CreatePeerConnection();
710 EXPECT_TRUE(pc);
711 }
714 ~SignalingAgent() {
715 mozilla::SyncRunnable::DispatchToThread(gMainThread,
716 WrapRunnable(this, &SignalingAgent::Close));
717 }
719 void Init_m(nsCOMPtr<nsIThread> thread)
720 {
721 pObserver = new TestObserver(pc, name);
722 ASSERT_TRUE(pObserver);
724 ASSERT_EQ(pc->Initialize(*pObserver, nullptr, cfg_, thread), NS_OK);
725 }
727 void Init(nsCOMPtr<nsIThread> thread)
728 {
729 mozilla::SyncRunnable::DispatchToThread(thread,
730 WrapRunnable(this, &SignalingAgent::Init_m, thread));
732 ASSERT_TRUE_WAIT(sipcc_state() == PCImplSipccState::Started,
733 kDefaultTimeout);
734 }
736 void WaitForGather() {
737 ASSERT_TRUE_WAIT(ice_gathering_state() == PCImplIceGatheringState::Complete,
738 kDefaultTimeout);
740 std::cout << name << ": Init Complete" << std::endl;
741 }
743 bool WaitForGatherAllowFail() {
744 EXPECT_TRUE_WAIT(
745 ice_gathering_state() == PCImplIceGatheringState::Complete ||
746 ice_connection_state() == PCImplIceConnectionState::Failed,
747 kDefaultTimeout);
749 if (ice_connection_state() == PCImplIceConnectionState::Failed) {
750 std::cout << name << ": Init Failed" << std::endl;
751 return false;
752 }
754 std::cout << name << "Init Complete" << std::endl;
755 return true;
756 }
758 PCImplSipccState sipcc_state()
759 {
760 return pc->SipccState();
761 }
763 PCImplIceConnectionState ice_connection_state()
764 {
765 return pc->IceConnectionState();
766 }
768 PCImplIceGatheringState ice_gathering_state()
769 {
770 return pc->IceGatheringState();
771 }
773 PCImplSignalingState signaling_state()
774 {
775 return pc->SignalingState();
776 }
778 void Close()
779 {
780 if (pc) {
781 std::cout << name << ": Close" << std::endl;
783 pc->Close();
784 pc = nullptr;
785 }
787 // Shutdown is synchronous evidently.
788 // ASSERT_TRUE(pObserver->WaitForObserverCall());
789 // ASSERT_EQ(pc->sipcc_state(), sipcc::PeerConnectionInterface::kIdle);
790 }
792 bool OfferContains(const std::string& str) {
793 std::string o(offer());
795 return o.find(str) != std::string::npos;
796 }
798 bool AnswerContains(const std::string& str) {
799 std::string o(answer());
801 return o.find(str) != std::string::npos;
802 }
804 size_t MatchingCandidates(const std::string& cand) {
805 return pObserver->MatchingCandidates(cand);
806 }
808 char* offer() const { return offer_; }
809 char* answer() const { return answer_; }
811 std::string getLocalDescription() const {
812 char *sdp = nullptr;
813 pc->GetLocalDescription(&sdp);
814 if (!sdp) {
815 return "";
816 }
817 return sdp;
818 }
820 std::string getRemoteDescription() const {
821 char *sdp = 0;
822 pc->GetRemoteDescription(&sdp);
823 if (!sdp) {
824 return "";
825 }
826 return sdp;
827 }
829 // Adds a stream to the PeerConnection.
830 void AddStream(uint32_t hint =
831 DOMMediaStream::HINT_CONTENTS_AUDIO |
832 DOMMediaStream::HINT_CONTENTS_VIDEO,
833 MediaStream *stream = nullptr,
834 sipcc::MediaConstraints *constraints = nullptr
835 ) {
837 sipcc::MediaConstraints noConstraints;
838 if (!constraints) {
839 constraints = &noConstraints;
840 }
842 nsRefPtr<DOMMediaStream> domMediaStream;
843 if (stream) {
844 domMediaStream = new DOMMediaStream(stream);
845 } else {
846 domMediaStream = new DOMMediaStream();
847 }
849 domMediaStream->SetHintContents(hint);
850 ASSERT_EQ(pc->AddStream(*domMediaStream, *constraints), NS_OK);
851 domMediaStream_ = domMediaStream;
852 }
855 // Removes a stream from the PeerConnection. If the stream
856 // parameter is absent, removes the stream that was most
857 // recently added to the PeerConnection.
858 void RemoveLastStreamAdded() {
859 ASSERT_EQ(pc->RemoveStream(*domMediaStream_), NS_OK);
860 }
862 void CreateOffer(sipcc::MediaConstraints& constraints,
863 uint32_t offerFlags, uint32_t sdpCheck,
864 PCImplSignalingState endState =
865 PCImplSignalingState::SignalingStable) {
867 // Create a media stream as if it came from GUM
868 Fake_AudioStreamSource *audio_stream =
869 new Fake_AudioStreamSource();
871 nsresult ret;
872 mozilla::SyncRunnable::DispatchToThread(
873 test_utils->sts_target(),
874 WrapRunnableRet(audio_stream, &Fake_MediaStream::Start, &ret));
876 ASSERT_TRUE(NS_SUCCEEDED(ret));
878 uint32_t aHintContents = 0;
879 if (offerFlags & OFFER_AUDIO) {
880 aHintContents |= DOMMediaStream::HINT_CONTENTS_AUDIO;
881 }
882 if (offerFlags & OFFER_VIDEO) {
883 aHintContents |= DOMMediaStream::HINT_CONTENTS_VIDEO;
884 }
885 AddStream(aHintContents, audio_stream);
887 // Now call CreateOffer as JS would
888 pObserver->state = TestObserver::stateNoResponse;
889 ASSERT_EQ(pc->CreateOffer(constraints), NS_OK);
890 ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
891 kDefaultTimeout);
892 ASSERT_EQ(pObserver->state, TestObserver::stateSuccess);
893 SDPSanityCheck(pObserver->lastString, sdpCheck, true);
894 ASSERT_EQ(signaling_state(), endState);
895 offer_ = pObserver->lastString;
896 }
898 void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
899 uint32_t offerAnswerFlags,
900 uint32_t sdpCheck = DONT_CHECK_AUDIO|
901 DONT_CHECK_VIDEO|
902 DONT_CHECK_DATA,
903 PCImplSignalingState endState =
904 PCImplSignalingState::SignalingHaveRemoteOffer) {
906 uint32_t aHintContents = 0;
907 if (offerAnswerFlags & ANSWER_AUDIO) {
908 aHintContents |= DOMMediaStream::HINT_CONTENTS_AUDIO;
909 }
910 if (offerAnswerFlags & ANSWER_VIDEO) {
911 aHintContents |= DOMMediaStream::HINT_CONTENTS_VIDEO;
912 }
913 AddStream(aHintContents);
915 // Decide if streams are disabled for offer or answer
916 // then perform SDP checking based on which stream disabled
917 pObserver->state = TestObserver::stateNoResponse;
918 ASSERT_EQ(pc->CreateAnswer(constraints), NS_OK);
919 ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
920 kDefaultTimeout);
921 ASSERT_EQ(pObserver->state, TestObserver::stateSuccess);
922 SDPSanityCheck(pObserver->lastString, sdpCheck, false);
923 ASSERT_EQ(signaling_state(), endState);
925 answer_ = pObserver->lastString;
926 }
928 // At present, we use the hints field in a stream to find and
929 // remove it. This only works if the specified hints flags are
930 // unique among all streams in the PeerConnection. This is not
931 // generally true, and will need significant revision once
932 // multiple streams are supported.
933 void CreateOfferRemoveStream(sipcc::MediaConstraints& constraints,
934 uint32_t hints, uint32_t sdpCheck) {
936 domMediaStream_->SetHintContents(hints);
938 // This currently "removes" a stream that has the same audio/video
939 // hints as were passed in.
940 // When complete RemoveStream will remove and entire stream and its tracks
941 // not just disable a track as this is currently doing
942 ASSERT_EQ(pc->RemoveStream(*domMediaStream_), NS_OK);
944 // Now call CreateOffer as JS would
945 pObserver->state = TestObserver::stateNoResponse;
946 ASSERT_EQ(pc->CreateOffer(constraints), NS_OK);
947 ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
948 kDefaultTimeout);
949 ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
950 SDPSanityCheck(pObserver->lastString, sdpCheck, true);
951 offer_ = pObserver->lastString;
952 }
954 void SetRemote(TestObserver::Action action, std::string remote,
955 bool ignoreError = false,
956 PCImplSignalingState endState =
957 PCImplSignalingState::SignalingInvalid) {
959 if (endState == PCImplSignalingState::SignalingInvalid) {
960 endState = (action == TestObserver::OFFER ?
961 PCImplSignalingState::SignalingHaveRemoteOffer :
962 PCImplSignalingState::SignalingStable);
963 }
965 pObserver->state = TestObserver::stateNoResponse;
966 ASSERT_EQ(pc->SetRemoteDescription(action, remote.c_str()), NS_OK);
967 ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
968 kDefaultTimeout);
969 ASSERT_EQ(signaling_state(), endState);
970 if (!ignoreError) {
971 ASSERT_EQ(pObserver->state, TestObserver::stateSuccess);
972 }
973 }
975 void SetLocal(TestObserver::Action action, std::string local,
976 bool ignoreError = false,
977 PCImplSignalingState endState =
978 PCImplSignalingState::SignalingInvalid) {
980 if (endState == PCImplSignalingState::SignalingInvalid) {
981 endState = (action == TestObserver::OFFER ?
982 PCImplSignalingState::SignalingHaveLocalOffer :
983 PCImplSignalingState::SignalingStable);
984 }
986 pObserver->state = TestObserver::stateNoResponse;
987 ASSERT_EQ(pc->SetLocalDescription(action, local.c_str()), NS_OK);
988 ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
989 kDefaultTimeout);
990 ASSERT_EQ(signaling_state(), endState);
991 if (!ignoreError) {
992 ASSERT_EQ(pObserver->state, TestObserver::stateSuccess);
993 }
994 }
996 void DoTrickleIce(ParsedSDP &sdp) {
997 int expectAddIce = 0;
998 pObserver->addIceSuccessCount = 0;
999 for (std::multimap<int, std::string>::iterator it =
1000 sdp.ice_candidates_.begin();
1001 it != sdp.ice_candidates_.end(); ++it) {
1002 if ((*it).first != 0) {
1003 std::cerr << "Adding trickle ICE candidate " << (*it).second
1004 << std::endl;
1005 ASSERT_TRUE(NS_SUCCEEDED(pc->AddIceCandidate((*it).second.c_str(), "", (*it).first)));
1006 expectAddIce++;
1007 }
1008 }
1009 ASSERT_TRUE_WAIT(pObserver->addIceSuccessCount == expectAddIce,
1010 kDefaultTimeout);
1011 }
1014 void DoTrickleIceChrome(ParsedSDP &sdp) {
1015 int expectAddIce = 0;
1016 pObserver->addIceSuccessCount = 0;
1017 for (std::multimap<int, std::string>::iterator it =
1018 sdp.ice_candidates_.begin();
1019 it != sdp.ice_candidates_.end(); ++it) {
1020 if ((*it).first != 0) {
1021 std::string candidate = "a=" + (*it).second + "\r\n";
1022 std::cerr << "Adding trickle ICE candidate " << candidate << std::endl;
1024 ASSERT_TRUE(NS_SUCCEEDED(pc->AddIceCandidate(candidate.c_str(), "", (*it).first)));
1025 expectAddIce++;
1026 }
1027 }
1028 ASSERT_TRUE_WAIT(pObserver->addIceSuccessCount == expectAddIce,
1029 kDefaultTimeout);
1030 }
1033 bool IceCompleted() {
1034 return pc->IceConnectionState() == PCImplIceConnectionState::Connected;
1035 }
1037 void AddIceCandidate(const char* candidate, const char* mid, unsigned short level,
1038 bool expectSuccess) {
1039 PCImplSignalingState endState = signaling_state();
1040 pObserver->state = TestObserver::stateNoResponse;
1041 pc->AddIceCandidate(candidate, mid, level);
1042 ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
1043 kDefaultTimeout);
1044 ASSERT_TRUE(pObserver->state ==
1045 expectSuccess ? TestObserver::stateSuccess :
1046 TestObserver::stateError
1047 );
1049 // Verify that adding ICE candidates does not change the signaling state
1050 ASSERT_EQ(signaling_state(), endState);
1051 }
1053 int GetPacketsReceived(int stream) {
1054 std::vector<DOMMediaStream *> streams = pObserver->GetStreams();
1056 if ((int) streams.size() <= stream) {
1057 return 0;
1058 }
1060 return streams[stream]->GetStream()->AsSourceStream()->GetSegmentsAdded();
1061 }
1063 int GetPacketsSent(int stream) {
1064 return static_cast<Fake_MediaStreamBase *>(
1065 domMediaStream_->GetStream())->GetSegmentsAdded();
1066 }
1068 //Stops generating new audio data for transmission.
1069 //Should be called before Cleanup of the peer connection.
1070 void CloseSendStreams() {
1071 static_cast<Fake_MediaStream*>(
1072 domMediaStream_->GetStream())->StopStream();
1073 }
1075 //Stops pulling audio data off the receivers.
1076 //Should be called before Cleanup of the peer connection.
1077 void CloseReceiveStreams() {
1078 std::vector<DOMMediaStream *> streams =
1079 pObserver->GetStreams();
1080 for (size_t i = 0; i < streams.size(); i++) {
1081 streams[i]->GetStream()->AsSourceStream()->StopStream();
1082 }
1083 }
1085 mozilla::RefPtr<mozilla::MediaPipeline> GetMediaPipeline(
1086 bool local, int stream, int track) {
1087 sipcc::SourceStreamInfo *streamInfo;
1089 if (local) {
1090 streamInfo = pc->media()->GetLocalStream(stream);
1091 } else {
1092 streamInfo = pc->media()->GetRemoteStream(stream);
1093 }
1095 if (!streamInfo) {
1096 return nullptr;
1097 }
1099 const auto &pipelines = streamInfo->GetPipelines();
1100 auto it = pipelines.find(track);
1101 return (it == pipelines.end())? nullptr : it->second;
1102 }
1104 void CheckMediaPipeline(int stream, int track, uint32_t flags,
1105 VideoSessionConduit::FrameRequestType frameRequestMethod =
1106 VideoSessionConduit::FrameRequestNone) {
1108 std::cout << name << ": Checking media pipeline settings for "
1109 << ((flags & PIPELINE_LOCAL) ? "local " : "remote ")
1110 << ((flags & PIPELINE_SEND) ? "sending " : "receiving ")
1111 << ((flags & PIPELINE_VIDEO) ? "video" : "audio")
1112 << " pipeline (stream " << stream
1113 << ", track " << track << "); expect "
1114 << ((flags & PIPELINE_RTCP_MUX) ? "MUX, " : "no MUX, ")
1115 << ((flags & PIPELINE_RTCP_NACK) ? "NACK." : "no NACK.")
1116 << std::endl;
1118 mozilla::RefPtr<mozilla::MediaPipeline> pipeline =
1119 GetMediaPipeline((flags & PIPELINE_LOCAL), stream, track);
1120 ASSERT_TRUE(pipeline);
1121 ASSERT_EQ(pipeline->IsDoingRtcpMux(), !!(flags & PIPELINE_RTCP_MUX));
1122 // We cannot yet test send/recv with video.
1123 if (!(flags & PIPELINE_VIDEO)) {
1124 if (flags & PIPELINE_SEND) {
1125 ASSERT_TRUE_WAIT(pipeline->rtp_packets_sent() >= 40 &&
1126 pipeline->rtcp_packets_received() >= 1,
1127 kDefaultTimeout);
1128 ASSERT_GE(pipeline->rtp_packets_sent(), 40);
1129 ASSERT_GE(pipeline->rtcp_packets_received(), 1);
1130 } else {
1131 ASSERT_TRUE_WAIT(pipeline->rtp_packets_received() >= 40 &&
1132 pipeline->rtcp_packets_sent() >= 1,
1133 kDefaultTimeout);
1134 ASSERT_GE(pipeline->rtp_packets_received(), 40);
1135 ASSERT_GE(pipeline->rtcp_packets_sent(), 1);
1136 }
1137 }
1140 // Check feedback method for video
1141 if (flags & PIPELINE_VIDEO) {
1142 mozilla::MediaSessionConduit *conduit = pipeline->Conduit();
1143 ASSERT_TRUE(conduit);
1144 ASSERT_EQ(conduit->type(), mozilla::MediaSessionConduit::VIDEO);
1145 mozilla::VideoSessionConduit *video_conduit =
1146 static_cast<mozilla::VideoSessionConduit*>(conduit);
1147 ASSERT_EQ(!!(flags & PIPELINE_RTCP_NACK),
1148 video_conduit->UsingNackBasic());
1149 ASSERT_EQ(frameRequestMethod, video_conduit->FrameRequestMethod());
1150 }
1151 }
1153 public:
1154 mozilla::RefPtr<sipcc::PeerConnectionImpl> pc;
1155 nsRefPtr<TestObserver> pObserver;
1156 char* offer_;
1157 char* answer_;
1158 nsRefPtr<DOMMediaStream> domMediaStream_;
1159 sipcc::IceConfiguration cfg_;
1160 const std::string name;
1162 private:
1163 void SDPSanityCheck(std::string sdp, uint32_t flags, bool offer)
1164 {
1165 ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
1166 ASSERT_NE(sdp.find("v=0"), std::string::npos);
1167 ASSERT_NE(sdp.find("c=IN IP4"), std::string::npos);
1168 ASSERT_NE(sdp.find("a=fingerprint:sha-256"), std::string::npos);
1170 std::cout << name << ": SDPSanityCheck flags for "
1171 << (offer ? "offer" : "answer")
1172 << " = " << std::hex << std::showbase
1173 << flags << std::dec
1175 << ((flags & SHOULD_SEND_AUDIO)?" SHOULD_SEND_AUDIO":"")
1176 << ((flags & SHOULD_RECV_AUDIO)?" SHOULD_RECV_AUDIO":"")
1177 << ((flags & SHOULD_INACTIVE_AUDIO)?" SHOULD_INACTIVE_AUDIO":"")
1178 << ((flags & SHOULD_REJECT_AUDIO)?" SHOULD_REJECT_AUDIO":"")
1179 << ((flags & SHOULD_OMIT_AUDIO)?" SHOULD_OMIT_AUDIO":"")
1180 << ((flags & DONT_CHECK_AUDIO)?" DONT_CHECK_AUDIO":"")
1182 << ((flags & SHOULD_SEND_VIDEO)?" SHOULD_SEND_VIDEO":"")
1183 << ((flags & SHOULD_RECV_VIDEO)?" SHOULD_RECV_VIDEO":"")
1184 << ((flags & SHOULD_INACTIVE_VIDEO)?" SHOULD_INACTIVE_VIDEO":"")
1185 << ((flags & SHOULD_REJECT_VIDEO)?" SHOULD_REJECT_VIDEO":"")
1186 << ((flags & SHOULD_OMIT_VIDEO)?" SHOULD_OMIT_VIDEO":"")
1187 << ((flags & DONT_CHECK_VIDEO)?" DONT_CHECK_VIDEO":"")
1189 << ((flags & SHOULD_INCLUDE_DATA)?" SHOULD_INCLUDE_DATA":"")
1190 << ((flags & DONT_CHECK_DATA)?" DONT_CHECK_DATA":"")
1191 << std::endl;
1193 switch(flags & AUDIO_FLAGS) {
1194 case 0:
1195 ASSERT_EQ(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos);
1196 break;
1197 case SHOULD_CHECK_AUDIO:
1198 ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos);
1199 if (offer) {
1200 ASSERT_NE(sdp.find("a=rtpmap:0 PCMU/8000"), std::string::npos);
1201 }
1202 break;
1203 case SHOULD_SEND_AUDIO:
1204 ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos);
1205 ASSERT_NE(sdp.find(" 0-15\r\na=sendonly"), std::string::npos);
1206 if (offer) {
1207 ASSERT_NE(sdp.find("a=rtpmap:0 PCMU/8000"), std::string::npos);
1208 }
1209 break;
1210 case SHOULD_RECV_AUDIO:
1211 ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos);
1212 ASSERT_NE(sdp.find(" 0-15\r\na=recvonly"), std::string::npos);
1213 if (offer) {
1214 ASSERT_NE(sdp.find("a=rtpmap:0 PCMU/8000"), std::string::npos);
1215 }
1216 break;
1217 case SHOULD_SENDRECV_AUDIO:
1218 ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos);
1219 ASSERT_NE(sdp.find(" 0-15\r\na=sendrecv"), std::string::npos);
1220 if (offer) {
1221 ASSERT_NE(sdp.find("a=rtpmap:0 PCMU/8000"), std::string::npos);
1222 }
1223 break;
1224 case SHOULD_INACTIVE_AUDIO:
1225 ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos);
1226 ASSERT_NE(sdp.find(" 0-15\r\na=inactive"), std::string::npos);
1227 break;
1228 case SHOULD_REJECT_AUDIO:
1229 ASSERT_EQ(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos);
1230 ASSERT_NE(sdp.find("m=audio 0 "), std::string::npos);
1231 break;
1232 case SHOULD_OMIT_AUDIO:
1233 ASSERT_EQ(sdp.find("m=audio"), std::string::npos);
1234 break;
1235 case DONT_CHECK_AUDIO:
1236 break;
1237 default:
1238 ASSERT_FALSE("Missing case in switch statement");
1239 }
1241 switch(flags & VIDEO_FLAGS) {
1242 case 0:
1243 ASSERT_EQ(sdp.find("a=rtpmap:120 VP8/90000"), std::string::npos);
1244 break;
1245 case SHOULD_CHECK_VIDEO:
1246 ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000"), std::string::npos);
1247 break;
1248 case SHOULD_SEND_VIDEO:
1249 ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000\r\na=sendonly"),
1250 std::string::npos);
1251 break;
1252 case SHOULD_RECV_VIDEO:
1253 ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000\r\na=recvonly"),
1254 std::string::npos);
1255 break;
1256 case SHOULD_SENDRECV_VIDEO:
1257 ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000\r\na=sendrecv"),
1258 std::string::npos);
1259 break;
1260 case SHOULD_INACTIVE_VIDEO:
1261 ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000\r\na=inactive"),
1262 std::string::npos);
1263 break;
1264 case SHOULD_REJECT_VIDEO:
1265 ASSERT_NE(sdp.find("m=video 0 "), std::string::npos);
1266 break;
1267 case SHOULD_OMIT_VIDEO:
1268 ASSERT_EQ(sdp.find("m=video"), std::string::npos);
1269 break;
1270 case DONT_CHECK_VIDEO:
1271 break;
1272 default:
1273 ASSERT_FALSE("Missing case in switch statement");
1274 }
1276 if (flags & SHOULD_INCLUDE_DATA) {
1277 ASSERT_NE(sdp.find("m=application"), std::string::npos);
1278 } else if (!(flags & DONT_CHECK_DATA)) {
1279 ASSERT_EQ(sdp.find("m=application"), std::string::npos);
1280 }
1281 }
1282 };
1284 class SignalingEnvironment : public ::testing::Environment {
1285 public:
1286 void TearDown() {
1287 // Signaling is shut down in XPCOM shutdown
1288 }
1289 };
1291 class SignalingAgentTest : public ::testing::Test {
1292 public:
1293 static void SetUpTestCase() {
1294 }
1296 void TearDown() {
1297 // Delete all the agents.
1298 for (size_t i=0; i < agents_.size(); i++) {
1299 delete agents_[i];
1300 }
1301 }
1303 bool CreateAgent() {
1304 return CreateAgent(g_stun_server_address, g_stun_server_port);
1305 }
1307 bool CreateAgent(const std::string stun_addr, uint16_t stun_port,
1308 bool wait_for_gather = true) {
1309 ScopedDeletePtr<SignalingAgent> agent(
1310 new SignalingAgent("agent", stun_addr, stun_port));
1312 agent->Init(gMainThread);
1314 if (wait_for_gather) {
1315 if (!agent->WaitForGatherAllowFail())
1316 return false;
1317 }
1319 agents_.push_back(agent.forget());
1321 return true;
1322 }
1324 void CreateAgentNoInit() {
1325 ScopedDeletePtr<SignalingAgent> agent(new SignalingAgent("agent"));
1326 agents_.push_back(agent.forget());
1327 }
1329 SignalingAgent *agent(size_t i) {
1330 return agents_[i];
1331 }
1333 private:
1334 std::vector<SignalingAgent *> agents_;
1335 };
1338 class SignalingTest : public ::testing::Test {
1339 public:
1340 SignalingTest()
1341 : init_(false),
1342 a1_(nullptr),
1343 a2_(nullptr),
1344 wait_for_gather_(true),
1345 stun_addr_(g_stun_server_address),
1346 stun_port_(g_stun_server_port) {}
1348 SignalingTest(const std::string& stun_addr, uint16_t stun_port)
1349 : a1_(nullptr),
1350 a2_(nullptr),
1351 wait_for_gather_(true),
1352 stun_addr_(stun_addr),
1353 stun_port_(stun_port) {}
1355 static void SetUpTestCase() {
1356 }
1358 void EnsureInit() {
1360 if (init_)
1361 return;
1363 a1_ = new SignalingAgent(callerName, stun_addr_, stun_port_);
1364 a2_ = new SignalingAgent(calleeName, stun_addr_, stun_port_);
1366 a1_->Init(gMainThread);
1367 a2_->Init(gMainThread);
1369 if (wait_for_gather_) {
1370 WaitForGather();
1371 }
1372 }
1374 void WaitForGather() {
1375 a1_->WaitForGather();
1376 a2_->WaitForGather();
1377 }
1379 static void TearDownTestCase() {
1380 }
1382 void CreateOffer(sipcc::MediaConstraints& constraints,
1383 uint32_t offerFlags, uint32_t sdpCheck) {
1384 EnsureInit();
1385 a1_->CreateOffer(constraints, offerFlags, sdpCheck);
1386 }
1388 void CreateSetOffer(sipcc::MediaConstraints& constraints, uint32_t sdpCheck) {
1389 EnsureInit();
1390 a1_->CreateOffer(constraints, OFFER_AV, sdpCheck);
1391 a1_->SetLocal(TestObserver::OFFER, a1_->offer());
1392 }
1394 void OfferAnswer(sipcc::MediaConstraints& aconstraints,
1395 sipcc::MediaConstraints& bconstraints,
1396 uint32_t offerAnswerFlags,
1397 bool finishAfterAnswer, uint32_t offerSdpCheck,
1398 uint32_t answerSdpCheck) {
1399 EnsureInit();
1400 a1_->CreateOffer(aconstraints, offerAnswerFlags, offerSdpCheck);
1401 a1_->SetLocal(TestObserver::OFFER, a1_->offer());
1402 a2_->SetRemote(TestObserver::OFFER, a1_->offer());
1403 a2_->CreateAnswer(bconstraints, a1_->offer(),
1404 offerAnswerFlags, answerSdpCheck);
1405 if(true == finishAfterAnswer) {
1406 a2_->SetLocal(TestObserver::ANSWER, a2_->answer());
1407 a1_->SetRemote(TestObserver::ANSWER, a2_->answer());
1409 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
1410 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
1411 }
1412 }
1414 void OfferModifiedAnswer(sipcc::MediaConstraints& aconstraints,
1415 sipcc::MediaConstraints& bconstraints,
1416 uint32_t offerSdpCheck, uint32_t answerSdpCheck) {
1417 EnsureInit();
1418 a1_->CreateOffer(aconstraints, OFFER_AUDIO, offerSdpCheck);
1419 a1_->SetLocal(TestObserver::OFFER, a1_->offer());
1420 a2_->SetRemote(TestObserver::OFFER, a1_->offer());
1421 a2_->CreateAnswer(bconstraints, a1_->offer(), OFFER_AUDIO | ANSWER_AUDIO,
1422 answerSdpCheck);
1423 a2_->SetLocal(TestObserver::ANSWER, a2_->answer());
1424 ParsedSDP sdpWrapper(a2_->answer());
1425 sdpWrapper.ReplaceLine("m=audio", "m=audio 65375 RTP/SAVPF 109 8 101\r\n");
1426 sdpWrapper.AddLine("a=rtpmap:8 PCMA/8000\r\n");
1427 std::cout << "Modified SDP " << std::endl
1428 << indent(sdpWrapper.getSdp()) << std::endl;
1429 a1_->SetRemote(TestObserver::ANSWER, sdpWrapper.getSdp());
1430 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
1431 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
1432 }
1434 void OfferAnswerTrickle(sipcc::MediaConstraints& aconstraints,
1435 sipcc::MediaConstraints& bconstraints,
1436 uint32_t offerSdpCheck, uint32_t answerSdpCheck) {
1437 EnsureInit();
1438 a1_->CreateOffer(aconstraints, OFFER_AV, offerSdpCheck);
1439 a1_->SetLocal(TestObserver::OFFER, a1_->offer());
1440 ParsedSDP a1_offer(a1_->offer());
1441 a2_->SetRemote(TestObserver::OFFER, a1_offer.sdp_without_ice_);
1442 a2_->CreateAnswer(bconstraints, a1_offer.sdp_without_ice_,
1443 OFFER_AV|ANSWER_AV, answerSdpCheck);
1444 a2_->SetLocal(TestObserver::ANSWER, a2_->answer());
1445 ParsedSDP a2_answer(a2_->answer());
1446 a1_->SetRemote(TestObserver::ANSWER, a2_answer.sdp_without_ice_);
1447 // Now set the trickle ICE candidates
1448 a1_->DoTrickleIce(a2_answer);
1449 a2_->DoTrickleIce(a1_offer);
1450 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
1451 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
1452 }
1455 void OfferAnswerTrickleChrome(sipcc::MediaConstraints& aconstraints,
1456 sipcc::MediaConstraints& bconstraints,
1457 uint32_t offerSdpCheck, uint32_t answerSdpCheck) {
1458 EnsureInit();
1459 a1_->CreateOffer(aconstraints, OFFER_AV, offerSdpCheck);
1460 a1_->SetLocal(TestObserver::OFFER, a1_->offer());
1461 ParsedSDP a1_offer(a1_->offer());
1462 a2_->SetRemote(TestObserver::OFFER, a1_offer.sdp_without_ice_);
1463 a2_->CreateAnswer(bconstraints, a1_offer.sdp_without_ice_,
1464 OFFER_AV|ANSWER_AV, answerSdpCheck);
1465 a2_->SetLocal(TestObserver::ANSWER, a2_->answer());
1466 ParsedSDP a2_answer(a2_->answer());
1467 a1_->SetRemote(TestObserver::ANSWER, a2_answer.sdp_without_ice_);
1468 // Now set the trickle ICE candidates
1469 a1_->DoTrickleIceChrome(a2_answer);
1470 a2_->DoTrickleIceChrome(a1_offer);
1471 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
1472 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
1473 }
1475 void CreateOfferRemoveStream(sipcc::MediaConstraints& constraints,
1476 uint32_t hints, uint32_t sdpCheck) {
1477 EnsureInit();
1478 sipcc::MediaConstraints aconstraints;
1479 aconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1480 aconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1481 a1_->CreateOffer(aconstraints, OFFER_AV, SHOULD_SENDRECV_AV );
1482 a1_->CreateOfferRemoveStream(constraints, hints, sdpCheck);
1483 }
1485 void CreateOfferAudioOnly(sipcc::MediaConstraints& constraints,
1486 uint32_t sdpCheck) {
1487 EnsureInit();
1488 a1_->CreateOffer(constraints, OFFER_AUDIO, sdpCheck);
1489 }
1491 void CreateOfferAddCandidate(sipcc::MediaConstraints& constraints,
1492 const char * candidate, const char * mid,
1493 unsigned short level, uint32_t sdpCheck) {
1494 EnsureInit();
1495 a1_->CreateOffer(constraints, OFFER_AV, sdpCheck);
1496 a1_->AddIceCandidate(candidate, mid, level, true);
1497 }
1499 void AddIceCandidateEarly(const char * candidate, const char * mid,
1500 unsigned short level) {
1501 EnsureInit();
1502 a1_->AddIceCandidate(candidate, mid, level, false);
1503 }
1505 void CheckRtcpFbSdp(const std::string &sdp,
1506 const std::set<std::string>& expected) {
1508 std::set<std::string>::const_iterator it;
1510 // Iterate through the list of expected feedback types and ensure
1511 // that none of them are missing.
1512 for (it = expected.begin(); it != expected.end(); ++it) {
1513 std::string attr = std::string("\r\na=rtcp-fb:120 ") + (*it) + "\r\n";
1514 std::cout << " - Checking for a=rtcp-fb: '" << *it << "'" << std::endl;
1515 ASSERT_NE(sdp.find(attr), std::string::npos);
1516 }
1518 // Iterate through all of the rtcp-fb lines in the SDP and ensure
1519 // that all of them are expected.
1520 ParsedSDP sdpWrapper(sdp);
1521 std::vector<std::string> values = sdpWrapper.GetLines("a=rtcp-fb:120");
1522 std::vector<std::string>::iterator it2;
1523 for (it2 = values.begin(); it2 != values.end(); ++it2) {
1524 std::cout << " - Verifying that rtcp-fb is okay: '" << *it2
1525 << "'" << std::endl;
1526 ASSERT_NE(0U, expected.count(*it2));
1527 }
1528 }
1530 void TestRtcpFb(const std::set<std::string>& feedback,
1531 uint32_t rtcpFbFlags,
1532 VideoSessionConduit::FrameRequestType frameRequestMethod) {
1533 EnsureInit();
1534 sipcc::MediaConstraints constraints;
1536 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV);
1537 a1_->SetLocal(TestObserver::OFFER, a1_->offer());
1539 ParsedSDP sdpWrapper(a1_->offer());
1541 // Strip out any existing rtcp-fb lines
1542 sdpWrapper.DeleteAllLines("a=rtcp-fb:120");
1544 // Add rtcp-fb lines for the desired feedback types
1545 // We know that the video section is generated second (last),
1546 // so appending these to the end of the SDP has the desired effect.
1547 std::set<std::string>::const_iterator it;
1548 for (it = feedback.begin(); it != feedback.end(); ++it) {
1549 sdpWrapper.AddLine(std::string("a=rtcp-fb:120 ") + (*it) + "\r\n");
1550 }
1552 std::cout << "Modified SDP " << std::endl
1553 << indent(sdpWrapper.getSdp()) << std::endl;
1555 // Double-check that the offered SDP matches what we expect
1556 CheckRtcpFbSdp(sdpWrapper.getSdp(), feedback);
1558 a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp());
1559 a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), OFFER_AV | ANSWER_AV);
1561 CheckRtcpFbSdp(a2_->answer(), feedback);
1563 a2_->SetLocal(TestObserver::ANSWER, a2_->answer());
1564 a1_->SetRemote(TestObserver::ANSWER, a2_->answer());
1566 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
1567 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
1569 a1_->CloseSendStreams();
1570 a1_->CloseReceiveStreams();
1571 a2_->CloseSendStreams();
1572 a2_->CloseReceiveStreams();
1574 // Check caller video settings for remote pipeline
1575 a1_->CheckMediaPipeline(0, 2, (fRtcpMux ? PIPELINE_RTCP_MUX : 0) |
1576 PIPELINE_SEND | PIPELINE_VIDEO | rtcpFbFlags, frameRequestMethod);
1578 // Check callee video settings for remote pipeline
1579 a2_->CheckMediaPipeline(0, 2, (fRtcpMux ? PIPELINE_RTCP_MUX : 0) |
1580 PIPELINE_VIDEO | rtcpFbFlags, frameRequestMethod);
1581 }
1583 void SetTestStunServer() {
1584 stun_addr_ = TestStunServer::GetInstance()->addr();
1585 stun_port_ = TestStunServer::GetInstance()->port();
1587 TestStunServer::GetInstance()->SetActive(false);
1588 TestStunServer::GetInstance()->SetResponseAddr(
1589 kBogusSrflxAddress, kBogusSrflxPort);
1590 }
1592 // Check max-fs and max-fr in SDP
1593 void CheckMaxFsFrSdp(const std::string sdp,
1594 int format,
1595 int max_fs,
1596 int max_fr) {
1597 ParsedSDP sdpWrapper(sdp);
1598 std::stringstream ss;
1599 ss << "a=fmtp:" << format;
1600 std::vector<std::string> lines = sdpWrapper.GetLines(ss.str());
1602 // Both max-fs and max-fr not exist
1603 if (lines.empty()) {
1604 ASSERT_EQ(max_fs, 0);
1605 ASSERT_EQ(max_fr, 0);
1606 return;
1607 }
1609 // At most one instance allowed for each format
1610 ASSERT_EQ(lines.size(), 1U);
1612 std::string line = lines.front();
1614 // Make sure that max-fs doesn't exist
1615 if (max_fs == 0) {
1616 ASSERT_EQ(line.find("max-fs="), std::string::npos);
1617 }
1618 // Check max-fs value
1619 if (max_fs > 0) {
1620 std::stringstream ss;
1621 ss << "max-fs=" << max_fs;
1622 ASSERT_NE(line.find(ss.str()), std::string::npos);
1623 }
1624 // Make sure that max-fr doesn't exist
1625 if (max_fr == 0) {
1626 ASSERT_EQ(line.find("max-fr="), std::string::npos);
1627 }
1628 // Check max-fr value
1629 if (max_fr > 0) {
1630 std::stringstream ss;
1631 ss << "max-fr=" << max_fr;
1632 ASSERT_NE(line.find(ss.str()), std::string::npos);
1633 }
1634 }
1636 protected:
1637 bool init_;
1638 ScopedDeletePtr<SignalingAgent> a1_; // Canonically "caller"
1639 ScopedDeletePtr<SignalingAgent> a2_; // Canonically "callee"
1640 bool wait_for_gather_;
1641 std::string stun_addr_;
1642 uint16_t stun_port_;
1643 };
1645 static void SetIntPrefOnMainThread(nsCOMPtr<nsIPrefBranch> prefs,
1646 const char *pref_name,
1647 int new_value) {
1648 MOZ_ASSERT(NS_IsMainThread());
1649 prefs->SetIntPref(pref_name, new_value);
1650 }
1652 static void SetMaxFsFr(nsCOMPtr<nsIPrefBranch> prefs,
1653 int max_fs,
1654 int max_fr) {
1655 gMainThread->Dispatch(
1656 WrapRunnableNM(SetIntPrefOnMainThread,
1657 prefs,
1658 "media.navigator.video.max_fs",
1659 max_fs),
1660 NS_DISPATCH_SYNC);
1662 gMainThread->Dispatch(
1663 WrapRunnableNM(SetIntPrefOnMainThread,
1664 prefs,
1665 "media.navigator.video.max_fr",
1666 max_fr),
1667 NS_DISPATCH_SYNC);
1668 }
1670 class FsFrPrefClearer {
1671 public:
1672 FsFrPrefClearer(nsCOMPtr<nsIPrefBranch> prefs): mPrefs(prefs) {}
1673 ~FsFrPrefClearer() {
1674 gMainThread->Dispatch(
1675 WrapRunnableNM(FsFrPrefClearer::ClearUserPrefOnMainThread,
1676 mPrefs,
1677 "media.navigator.video.max_fs"),
1678 NS_DISPATCH_SYNC);
1679 gMainThread->Dispatch(
1680 WrapRunnableNM(FsFrPrefClearer::ClearUserPrefOnMainThread,
1681 mPrefs,
1682 "media.navigator.video.max_fr"),
1683 NS_DISPATCH_SYNC);
1684 }
1686 static void ClearUserPrefOnMainThread(nsCOMPtr<nsIPrefBranch> prefs,
1687 const char *pref_name) {
1688 MOZ_ASSERT(NS_IsMainThread());
1689 prefs->ClearUserPref(pref_name);
1690 }
1691 private:
1692 nsCOMPtr<nsIPrefBranch> mPrefs;
1693 };
1695 TEST_F(SignalingTest, JustInit)
1696 {
1697 }
1699 TEST_F(SignalingTest, CreateSetOffer)
1700 {
1701 sipcc::MediaConstraints constraints;
1702 CreateSetOffer(constraints, SHOULD_SENDRECV_AV);
1703 }
1705 TEST_F(SignalingTest, CreateOfferAudioVideoConstraintUndefined)
1706 {
1707 sipcc::MediaConstraints constraints;
1708 CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV);
1709 }
1711 TEST_F(SignalingTest, CreateOfferNoVideoStreamRecvVideo)
1712 {
1713 sipcc::MediaConstraints constraints;
1714 constraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1715 constraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1716 CreateOffer(constraints, OFFER_AUDIO,
1717 SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO);
1718 }
1720 TEST_F(SignalingTest, CreateOfferNoAudioStreamRecvAudio)
1721 {
1722 sipcc::MediaConstraints constraints;
1723 constraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1724 constraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1725 CreateOffer(constraints, OFFER_VIDEO,
1726 SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO);
1727 }
1729 TEST_F(SignalingTest, CreateOfferNoVideoStream)
1730 {
1731 sipcc::MediaConstraints constraints;
1732 constraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1733 constraints.setBooleanConstraint("OfferToReceiveVideo", false, false);
1734 CreateOffer(constraints, OFFER_AUDIO,
1735 SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO);
1736 }
1738 TEST_F(SignalingTest, CreateOfferNoAudioStream)
1739 {
1740 sipcc::MediaConstraints constraints;
1741 constraints.setBooleanConstraint("OfferToReceiveAudio", false, false);
1742 constraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1743 CreateOffer(constraints, OFFER_VIDEO,
1744 SHOULD_OMIT_AUDIO | SHOULD_SENDRECV_VIDEO);
1745 }
1747 TEST_F(SignalingTest, CreateOfferDontReceiveAudio)
1748 {
1749 sipcc::MediaConstraints constraints;
1750 constraints.setBooleanConstraint("OfferToReceiveAudio", false, false);
1751 constraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1752 CreateOffer(constraints, OFFER_AV,
1753 SHOULD_SEND_AUDIO | SHOULD_SENDRECV_VIDEO);
1754 }
1756 TEST_F(SignalingTest, CreateOfferDontReceiveVideo)
1757 {
1758 sipcc::MediaConstraints constraints;
1759 constraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1760 constraints.setBooleanConstraint("OfferToReceiveVideo", false, false);
1761 CreateOffer(constraints, OFFER_AV,
1762 SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO);
1763 }
1765 // XXX Disabled pending resolution of Bug 840728
1766 TEST_F(SignalingTest, DISABLED_CreateOfferRemoveAudioStream)
1767 {
1768 sipcc::MediaConstraints constraints;
1769 constraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1770 constraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1771 CreateOfferRemoveStream(constraints, DOMMediaStream::HINT_CONTENTS_AUDIO,
1772 SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO);
1773 }
1775 // XXX Disabled pending resolution of Bug 840728
1776 TEST_F(SignalingTest, DISABLED_CreateOfferDontReceiveAudioRemoveAudioStream)
1777 {
1778 sipcc::MediaConstraints constraints;
1779 constraints.setBooleanConstraint("OfferToReceiveAudio", false, false);
1780 constraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1781 CreateOfferRemoveStream(constraints, DOMMediaStream::HINT_CONTENTS_AUDIO,
1782 SHOULD_SENDRECV_VIDEO);
1783 }
1785 // XXX Disabled pending resolution of Bug 840728
1786 TEST_F(SignalingTest, DISABLED_CreateOfferDontReceiveVideoRemoveVideoStream)
1787 {
1788 sipcc::MediaConstraints constraints;
1789 constraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1790 constraints.setBooleanConstraint("OfferToReceiveVideo", false, false);
1791 CreateOfferRemoveStream(constraints, DOMMediaStream::HINT_CONTENTS_VIDEO,
1792 SHOULD_SENDRECV_AUDIO);
1793 }
1795 TEST_F(SignalingTest, OfferAnswerNothingDisabled)
1796 {
1797 sipcc::MediaConstraints constraints;
1798 OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, false,
1799 SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV);
1800 }
1802 TEST_F(SignalingTest, OfferAnswerDontReceiveAudioOnOffer)
1803 {
1804 sipcc::MediaConstraints offerconstraints;
1805 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false);
1806 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1807 sipcc::MediaConstraints answerconstraints;
1808 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1809 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1810 OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AV,
1811 false, SHOULD_SEND_AUDIO | SHOULD_SENDRECV_VIDEO,
1812 SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO);
1813 }
1815 TEST_F(SignalingTest, OfferAnswerDontReceiveVideoOnOffer)
1816 {
1817 sipcc::MediaConstraints offerconstraints;
1818 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1819 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false);
1820 sipcc::MediaConstraints answerconstraints;
1821 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1822 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1823 OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AV,
1824 false, SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO,
1825 SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO);
1826 }
1828 TEST_F(SignalingTest, OfferAnswerDontReceiveAudioOnAnswer)
1829 {
1830 sipcc::MediaConstraints offerconstraints;
1831 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1832 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1833 sipcc::MediaConstraints answerconstraints;
1834 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false);
1835 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1836 OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AV,
1837 false, SHOULD_SENDRECV_AV,
1838 SHOULD_SEND_AUDIO | SHOULD_SENDRECV_VIDEO);
1839 }
1841 TEST_F(SignalingTest, OfferAnswerDontReceiveVideoOnAnswer)
1842 {
1843 sipcc::MediaConstraints offerconstraints;
1844 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1845 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1846 sipcc::MediaConstraints answerconstraints;
1847 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1848 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false);
1849 OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AV,
1850 false, SHOULD_SENDRECV_AV,
1851 SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO);
1852 }
1854 TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnOfferRecvAudio)
1855 {
1856 sipcc::MediaConstraints offerconstraints;
1857 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1858 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1859 sipcc::MediaConstraints answerconstraints;
1860 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1861 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1862 OfferAnswer(offerconstraints, answerconstraints, OFFER_VIDEO | ANSWER_AV,
1863 false, SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO,
1864 SHOULD_SEND_AUDIO | SHOULD_SENDRECV_VIDEO);
1865 }
1867 TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnOffer)
1868 {
1869 sipcc::MediaConstraints offerconstraints;
1870 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false);
1871 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1872 sipcc::MediaConstraints answerconstraints;
1873 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1874 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1875 OfferAnswer(offerconstraints, answerconstraints, OFFER_VIDEO | ANSWER_AV,
1876 false, SHOULD_OMIT_AUDIO | SHOULD_SENDRECV_VIDEO,
1877 SHOULD_OMIT_AUDIO | SHOULD_SENDRECV_VIDEO);
1878 }
1880 TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnOfferRecvVideo)
1881 {
1882 sipcc::MediaConstraints offerconstraints;
1883 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1884 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1885 sipcc::MediaConstraints answerconstraints;
1886 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1887 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1888 OfferAnswer(offerconstraints, answerconstraints, OFFER_AUDIO | ANSWER_AV,
1889 false, SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO,
1890 SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO);
1891 }
1893 TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnOffer)
1894 {
1895 sipcc::MediaConstraints offerconstraints;
1896 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1897 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false);
1898 sipcc::MediaConstraints answerconstraints;
1899 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1900 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1901 OfferAnswer(offerconstraints, answerconstraints, OFFER_AUDIO | ANSWER_AV,
1902 false, SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO,
1903 SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO);
1904 }
1906 TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnAnswer)
1907 {
1908 sipcc::MediaConstraints offerconstraints;
1909 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1910 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1911 sipcc::MediaConstraints answerconstraints;
1912 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1913 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1914 OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_VIDEO,
1915 false, SHOULD_SENDRECV_AV,
1916 SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO);
1917 }
1919 TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnAnswer)
1920 {
1921 sipcc::MediaConstraints offerconstraints;
1922 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1923 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1924 sipcc::MediaConstraints answerconstraints;
1925 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1926 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1927 OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AUDIO,
1928 false, SHOULD_SENDRECV_AV,
1929 SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO);
1930 }
1932 TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnAnswerDontReceiveVideoOnAnswer)
1933 {
1934 sipcc::MediaConstraints offerconstraints;
1935 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1936 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1937 sipcc::MediaConstraints answerconstraints;
1938 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1939 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false);
1940 OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AUDIO,
1941 false, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AUDIO );
1942 }
1944 TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnAnswerDontReceiveAudioOnAnswer)
1945 {
1946 sipcc::MediaConstraints offerconstraints;
1947 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1948 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1949 sipcc::MediaConstraints answerconstraints;
1950 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false);
1951 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1952 OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_VIDEO,
1953 false, SHOULD_SENDRECV_AV,
1954 SHOULD_REJECT_AUDIO | SHOULD_SENDRECV_VIDEO);
1955 }
1957 TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnOfferDontReceiveAudioOnOffer)
1958 {
1959 sipcc::MediaConstraints offerconstraints;
1960 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false);
1961 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1962 sipcc::MediaConstraints answerconstraints;
1963 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1964 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1965 OfferAnswer(offerconstraints, answerconstraints, OFFER_VIDEO | ANSWER_AV,
1966 false, SHOULD_SENDRECV_VIDEO, SHOULD_SENDRECV_VIDEO);
1967 }
1969 TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnOfferDontReceiveVideoOnOffer)
1970 {
1971 sipcc::MediaConstraints offerconstraints;
1972 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1973 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false);
1974 sipcc::MediaConstraints answerconstraints;
1975 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1976 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1977 OfferAnswer(offerconstraints, answerconstraints, OFFER_AUDIO | ANSWER_AV,
1978 false, SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO,
1979 SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO);
1980 }
1982 TEST_F(SignalingTest, OfferAnswerDontReceiveAudioNoAudioStreamOnOfferDontReceiveVideoOnAnswer)
1983 {
1984 sipcc::MediaConstraints offerconstraints;
1985 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false);
1986 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
1987 sipcc::MediaConstraints answerconstraints;
1988 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
1989 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false);
1990 OfferAnswer(offerconstraints, answerconstraints, OFFER_VIDEO | ANSWER_AV,
1991 false, SHOULD_SENDRECV_VIDEO, SHOULD_SEND_VIDEO);
1992 }
1994 TEST_F(SignalingTest, CreateOfferAddCandidate)
1995 {
1996 sipcc::MediaConstraints constraints;
1997 CreateOfferAddCandidate(constraints, strSampleCandidate.c_str(),
1998 strSampleMid.c_str(), nSamplelevel,
1999 SHOULD_SENDRECV_AV);
2000 }
2002 TEST_F(SignalingTest, AddIceCandidateEarly)
2003 {
2004 sipcc::MediaConstraints constraints;
2005 AddIceCandidateEarly(strSampleCandidate.c_str(),
2006 strSampleMid.c_str(), nSamplelevel);
2007 }
2009 // XXX adam@nostrum.com -- This test seems questionable; we need to think
2010 // through what actually needs to be tested here.
2011 TEST_F(SignalingTest, DISABLED_OfferAnswerReNegotiateOfferAnswerDontReceiveVideoNoVideoStream)
2012 {
2013 sipcc::MediaConstraints aconstraints;
2014 aconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
2015 aconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
2017 sipcc::MediaConstraints bconstraints;
2018 bconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
2019 bconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false);
2021 OfferAnswer(aconstraints, aconstraints, OFFER_AV | ANSWER_AV,
2022 false, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV);
2023 OfferAnswer(bconstraints, bconstraints, OFFER_AUDIO | ANSWER_AV,
2024 false, SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO,
2025 SHOULD_SENDRECV_AUDIO | SHOULD_INACTIVE_VIDEO);
2026 }
2028 TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnAnswerNoConstraints)
2029 {
2030 sipcc::MediaConstraints offerconstraints;
2031 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
2032 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
2033 sipcc::MediaConstraints answerconstraints;
2034 OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_VIDEO,
2035 false, SHOULD_SENDRECV_AV,
2036 SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO);
2037 }
2039 TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnAnswerNoConstraints)
2040 {
2041 sipcc::MediaConstraints offerconstraints;
2042 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
2043 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
2044 sipcc::MediaConstraints answerconstraints;
2045 OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AUDIO,
2046 false, SHOULD_SENDRECV_AV,
2047 SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO);
2048 }
2050 TEST_F(SignalingTest, OfferAnswerDontAddAudioVideoStreamsOnAnswerNoConstraints)
2051 {
2052 sipcc::MediaConstraints offerconstraints;
2053 offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
2054 offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
2055 sipcc::MediaConstraints answerconstraints;
2056 OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_NONE,
2057 false, SHOULD_SENDRECV_AV,
2058 SHOULD_RECV_AUDIO | SHOULD_RECV_VIDEO);
2059 }
2061 TEST_F(SignalingTest, FullCall)
2062 {
2063 sipcc::MediaConstraints constraints;
2064 OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV,
2065 true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV);
2067 // Wait for some data to get written
2068 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
2069 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
2071 a1_->CloseSendStreams();
2072 a2_->CloseReceiveStreams();
2073 // Check that we wrote a bunch of data
2074 ASSERT_GE(a1_->GetPacketsSent(0), 40);
2075 //ASSERT_GE(a2_->GetPacketsSent(0), 40);
2076 //ASSERT_GE(a1_->GetPacketsReceived(0), 40);
2077 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
2079 // Check the low-level media pipeline
2080 // for RTP and RTCP flows
2081 // The first Local pipeline gets stored at 0
2082 a1_->CheckMediaPipeline(0, 0, fRtcpMux ?
2083 PIPELINE_LOCAL | PIPELINE_RTCP_MUX | PIPELINE_SEND :
2084 PIPELINE_LOCAL | PIPELINE_SEND);
2086 // The first Remote pipeline gets stored at 1
2087 a2_->CheckMediaPipeline(0, 1, (fRtcpMux ? PIPELINE_RTCP_MUX : 0));
2088 }
2090 TEST_F(SignalingTest, FullCallAudioOnly)
2091 {
2092 sipcc::MediaConstraints constraints;
2093 OfferAnswer(constraints, constraints, OFFER_AUDIO | ANSWER_AUDIO,
2094 true, SHOULD_SENDRECV_AUDIO, SHOULD_SENDRECV_AUDIO);
2096 // Wait for some data to get written
2097 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
2098 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
2100 a1_->CloseSendStreams();
2101 a2_->CloseReceiveStreams();
2102 // Check that we wrote a bunch of data
2103 ASSERT_GE(a1_->GetPacketsSent(0), 40);
2104 //ASSERT_GE(a2_->GetPacketsSent(0), 40);
2105 //ASSERT_GE(a1_->GetPacketsReceived(0), 40);
2106 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
2107 }
2109 TEST_F(SignalingTest, FullCallAnswererRejectsVideo)
2110 {
2111 sipcc::MediaConstraints offerconstraints;
2112 sipcc::MediaConstraints answerconstraints;
2113 answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
2114 answerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false);
2115 OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AUDIO,
2116 true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AUDIO);
2118 // Wait for some data to get written
2119 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
2120 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
2122 a1_->CloseSendStreams();
2123 a2_->CloseReceiveStreams();
2124 // Check that we wrote a bunch of data
2125 ASSERT_GE(a1_->GetPacketsSent(0), 40);
2126 //ASSERT_GE(a2_->GetPacketsSent(0), 40);
2127 //ASSERT_GE(a1_->GetPacketsReceived(0), 40);
2128 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
2129 }
2131 TEST_F(SignalingTest, FullCallVideoOnly)
2132 {
2133 sipcc::MediaConstraints constraints;
2134 OfferAnswer(constraints, constraints, OFFER_VIDEO | ANSWER_VIDEO,
2135 true, SHOULD_SENDRECV_VIDEO, SHOULD_SENDRECV_VIDEO);
2137 // If we could check for video packets, we would wait for some to be written
2138 // here. Since we can't, we don't.
2139 // ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
2140 // a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
2142 a1_->CloseSendStreams();
2143 a2_->CloseReceiveStreams();
2145 // FIXME -- Ideally we would check that packets were sent
2146 // and received; however, the test driver setup does not
2147 // currently support sending/receiving with Fake_VideoStreamSource.
2148 //
2149 // Check that we wrote a bunch of data
2150 // ASSERT_GE(a1_->GetPacketsSent(0), 40);
2151 //ASSERT_GE(a2_->GetPacketsSent(0), 40);
2152 //ASSERT_GE(a1_->GetPacketsReceived(0), 40);
2153 // ASSERT_GE(a2_->GetPacketsReceived(0), 40);
2154 }
2156 TEST_F(SignalingTest, OfferModifiedAnswer)
2157 {
2158 sipcc::MediaConstraints constraints;
2159 OfferModifiedAnswer(constraints, constraints, SHOULD_SENDRECV_AUDIO,
2160 SHOULD_SENDRECV_AUDIO);
2161 a1_->CloseSendStreams();
2162 a2_->CloseReceiveStreams();
2163 }
2165 TEST_F(SignalingTest, FullCallTrickle)
2166 {
2167 sipcc::MediaConstraints constraints;
2168 OfferAnswerTrickle(constraints, constraints,
2169 SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV);
2171 std::cerr << "ICE handshake completed" << std::endl;
2173 // Wait for some data to get written
2174 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
2175 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
2177 a1_->CloseSendStreams();
2178 a2_->CloseReceiveStreams();
2179 ASSERT_GE(a1_->GetPacketsSent(0), 40);
2180 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
2181 }
2183 // Offer answer with trickle but with chrome-style candidates
2184 TEST_F(SignalingTest, FullCallTrickleChrome)
2185 {
2186 sipcc::MediaConstraints constraints;
2187 OfferAnswerTrickleChrome(constraints, constraints,
2188 SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV);
2190 std::cerr << "ICE handshake completed" << std::endl;
2192 // Wait for some data to get written
2193 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
2194 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
2196 a1_->CloseSendStreams();
2197 a2_->CloseReceiveStreams();
2198 ASSERT_GE(a1_->GetPacketsSent(0), 40);
2199 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
2200 }
2202 // This test comes from Bug 810220
2203 TEST_F(SignalingTest, AudioOnlyG711Call)
2204 {
2205 EnsureInit();
2207 sipcc::MediaConstraints constraints;
2208 const std::string& offer(strG711SdpOffer);
2210 std::cout << "Setting offer to:" << std::endl << indent(offer) << std::endl;
2211 a2_->SetRemote(TestObserver::OFFER, offer);
2213 std::cout << "Creating answer:" << std::endl;
2214 a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO,
2215 DONT_CHECK_AUDIO | DONT_CHECK_VIDEO | DONT_CHECK_DATA);
2217 std::string answer = a2_->answer();
2219 // They didn't offer opus, so our answer shouldn't include it.
2220 ASSERT_EQ(answer.find(" opus/"), std::string::npos);
2222 // They also didn't offer video or application
2223 ASSERT_EQ(answer.find("video"), std::string::npos);
2224 ASSERT_EQ(answer.find("application"), std::string::npos);
2226 // We should answer with PCMU and telephone-event
2227 ASSERT_NE(answer.find(" PCMU/8000"), std::string::npos);
2228 ASSERT_NE(answer.find(" telephone-event/8000"), std::string::npos);
2230 // Double-check the directionality
2231 ASSERT_NE(answer.find("\r\na=sendrecv"), std::string::npos);
2233 }
2235 // This test comes from Bug814038
2236 TEST_F(SignalingTest, ChromeOfferAnswer)
2237 {
2238 EnsureInit();
2240 sipcc::MediaConstraints constraints;
2242 // This is captured SDP from an early interop attempt with Chrome.
2243 std::string offer =
2244 "v=0\r\n"
2245 "o=- 1713781661 2 IN IP4 127.0.0.1\r\n"
2246 "s=-\r\n"
2247 "t=0 0\r\n"
2248 "a=group:BUNDLE audio video\r\n"
2250 "m=audio 1 RTP/SAVPF 103 104 111 0 8 107 106 105 13 126\r\n"
2251 "a=fingerprint:sha-1 4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:"
2252 "5D:49:6B:19:E5:7C:AB\r\n"
2253 "c=IN IP4 0.0.0.0\r\n"
2254 "a=rtcp:1 IN IP4 0.0.0.0\r\n"
2255 "a=ice-ufrag:lBrbdDfrVBH1cldN\r\n"
2256 "a=ice-pwd:rzh23jet4QpCaEoj9Sl75pL3\r\n"
2257 "a=ice-options:google-ice\r\n"
2258 "a=sendrecv\r\n"
2259 "a=mid:audio\r\n"
2260 "a=rtcp-mux\r\n"
2261 "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:"
2262 "RzrYlzpkTsvgYFD1hQqNCzQ7y4emNLKI1tODsjim\r\n"
2263 "a=rtpmap:103 ISAC/16000\r\n"
2264 "a=rtpmap:104 ISAC/32000\r\n"
2265 // NOTE: the actual SDP that Chrome sends at the moment
2266 // doesn't indicate two channels. I've amended their SDP
2267 // here, under the assumption that the constraints
2268 // described in draft-spittka-payload-rtp-opus will
2269 // eventually be implemented by Google.
2270 "a=rtpmap:111 opus/48000/2\r\n"
2271 "a=rtpmap:0 PCMU/8000\r\n"
2272 "a=rtpmap:8 PCMA/8000\r\n"
2273 "a=rtpmap:107 CN/48000\r\n"
2274 "a=rtpmap:106 CN/32000\r\n"
2275 "a=rtpmap:105 CN/16000\r\n"
2276 "a=rtpmap:13 CN/8000\r\n"
2277 "a=rtpmap:126 telephone-event/8000\r\n"
2278 "a=ssrc:661333377 cname:KIXaNxUlU5DP3fVS\r\n"
2279 "a=ssrc:661333377 msid:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5 a0\r\n"
2280 "a=ssrc:661333377 mslabel:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5\r\n"
2281 "a=ssrc:661333377 label:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5a0\r\n"
2283 "m=video 1 RTP/SAVPF 100 101 102\r\n"
2284 "a=fingerprint:sha-1 4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:"
2285 "6B:19:E5:7C:AB\r\n"
2286 "c=IN IP4 0.0.0.0\r\n"
2287 "a=rtcp:1 IN IP4 0.0.0.0\r\n"
2288 "a=ice-ufrag:lBrbdDfrVBH1cldN\r\n"
2289 "a=ice-pwd:rzh23jet4QpCaEoj9Sl75pL3\r\n"
2290 "a=ice-options:google-ice\r\n"
2291 "a=sendrecv\r\n"
2292 "a=mid:video\r\n"
2293 "a=rtcp-mux\r\n"
2294 "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:"
2295 "RzrYlzpkTsvgYFD1hQqNCzQ7y4emNLKI1tODsjim\r\n"
2296 "a=rtpmap:100 VP8/90000\r\n"
2297 "a=rtpmap:101 red/90000\r\n"
2298 "a=rtpmap:102 ulpfec/90000\r\n"
2299 "a=rtcp-fb:100 nack\r\n"
2300 "a=rtcp-fb:100 ccm fir\r\n"
2301 "a=ssrc:3012607008 cname:KIXaNxUlU5DP3fVS\r\n"
2302 "a=ssrc:3012607008 msid:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5 v0\r\n"
2303 "a=ssrc:3012607008 mslabel:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5\r\n"
2304 "a=ssrc:3012607008 label:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5v0\r\n";
2307 std::cout << "Setting offer to:" << std::endl << indent(offer) << std::endl;
2308 a2_->SetRemote(TestObserver::OFFER, offer);
2310 std::cout << "Creating answer:" << std::endl;
2311 a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO);
2313 std::string answer = a2_->answer();
2314 }
2317 TEST_F(SignalingTest, FullChromeHandshake)
2318 {
2319 EnsureInit();
2321 sipcc::MediaConstraints constraints;
2322 constraints.setBooleanConstraint("OfferToReceiveAudio", true, false);
2323 constraints.setBooleanConstraint("OfferToReceiveVideo", true, false);
2325 std::string offer = "v=0\r\n"
2326 "o=- 3835809413 2 IN IP4 127.0.0.1\r\n"
2327 "s=-\r\n"
2328 "t=0 0\r\n"
2329 "a=group:BUNDLE audio video\r\n"
2330 "a=msid-semantic: WMS ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH\r\n"
2331 "m=audio 1 RTP/SAVPF 103 104 111 0 8 107 106 105 13 126\r\n"
2332 "c=IN IP4 1.1.1.1\r\n"
2333 "a=rtcp:1 IN IP4 1.1.1.1\r\n"
2334 "a=ice-ufrag:jz9UBk9RT8eCQXiL\r\n"
2335 "a=ice-pwd:iscXxsdU+0gracg0g5D45orx\r\n"
2336 "a=ice-options:google-ice\r\n"
2337 "a=fingerprint:sha-256 A8:76:8C:4C:FA:2E:67:D7:F8:1D:28:4E:90:24:04:"
2338 "12:EB:B4:A6:69:3D:05:92:E4:91:C3:EA:F9:B7:54:D3:09\r\n"
2339 "a=sendrecv\r\n"
2340 "a=mid:audio\r\n"
2341 "a=rtcp-mux\r\n"
2342 "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:/he/v44FKu/QvEhex86zV0pdn2V"
2343 "4Y7wB2xaZ8eUy\r\n"
2344 "a=rtpmap:103 ISAC/16000\r\n"
2345 "a=rtpmap:104 ISAC/32000\r\n"
2346 "a=rtpmap:111 opus/48000/2\r\n"
2347 "a=rtpmap:0 PCMU/8000\r\n"
2348 "a=rtpmap:8 PCMA/8000\r\n"
2349 "a=rtpmap:107 CN/48000\r\n"
2350 "a=rtpmap:106 CN/32000\r\n"
2351 "a=rtpmap:105 CN/16000\r\n"
2352 "a=rtpmap:13 CN/8000\r\n"
2353 "a=rtpmap:126 telephone-event/8000\r\n"
2354 "a=ssrc:3389377748 cname:G5I+Jxz4rcaq8IIK\r\n"
2355 "a=ssrc:3389377748 msid:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH a0\r\n"
2356 "a=ssrc:3389377748 mslabel:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH\r\n"
2357 "a=ssrc:3389377748 label:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOHa0\r\n"
2358 "m=video 1 RTP/SAVPF 100 116 117\r\n"
2359 "c=IN IP4 1.1.1.1\r\n"
2360 "a=rtcp:1 IN IP4 1.1.1.1\r\n"
2361 "a=ice-ufrag:jz9UBk9RT8eCQXiL\r\n"
2362 "a=ice-pwd:iscXxsdU+0gracg0g5D45orx\r\n"
2363 "a=ice-options:google-ice\r\n"
2364 "a=fingerprint:sha-256 A8:76:8C:4C:FA:2E:67:D7:F8:1D:28:4E:90:24:04:"
2365 "12:EB:B4:A6:69:3D:05:92:E4:91:C3:EA:F9:B7:54:D3:09\r\n"
2366 "a=sendrecv\r\n"
2367 "a=mid:video\r\n"
2368 "a=rtcp-mux\r\n"
2369 "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:/he/v44FKu/QvEhex86zV0pdn2V"
2370 "4Y7wB2xaZ8eUy\r\n"
2371 "a=rtpmap:100 VP8/90000\r\n"
2372 "a=rtpmap:116 red/90000\r\n"
2373 "a=rtpmap:117 ulpfec/90000\r\n"
2374 "a=ssrc:3613537198 cname:G5I+Jxz4rcaq8IIK\r\n"
2375 "a=ssrc:3613537198 msid:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH v0\r\n"
2376 "a=ssrc:3613537198 mslabel:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH\r\n"
2377 "a=ssrc:3613537198 label:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOHv0\r\n";
2379 std::cout << "Setting offer to:" << std::endl << indent(offer) << std::endl;
2380 a2_->SetRemote(TestObserver::OFFER, offer);
2382 std::cout << "Creating answer:" << std::endl;
2383 a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO);
2385 std::cout << "Setting answer" << std::endl;
2386 a2_->SetLocal(TestObserver::ANSWER, a2_->answer());
2388 std::string answer = a2_->answer();
2389 ASSERT_NE(answer.find("111 opus/"), std::string::npos);
2390 }
2392 // Disabled pending resolution of bug 818640.
2393 TEST_F(SignalingTest, DISABLED_OfferAllDynamicTypes)
2394 {
2395 EnsureInit();
2397 sipcc::MediaConstraints constraints;
2398 std::string offer;
2399 for (int i = 96; i < 128; i++)
2400 {
2401 std::stringstream ss;
2402 ss << i;
2403 std::cout << "Trying dynamic pt = " << i << std::endl;
2404 offer =
2405 "v=0\r\n"
2406 "o=- 1 1 IN IP4 148.147.200.251\r\n"
2407 "s=-\r\n"
2408 "b=AS:64\r\n"
2409 "t=0 0\r\n"
2410 "a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:"
2411 "7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n"
2412 "m=audio 9000 RTP/AVP " + ss.str() + "\r\n"
2413 "c=IN IP4 148.147.200.251\r\n"
2414 "b=TIAS:64000\r\n"
2415 "a=rtpmap:" + ss.str() +" opus/48000/2\r\n"
2416 "a=candidate:0 1 udp 2130706432 148.147.200.251 9000 typ host\r\n"
2417 "a=candidate:0 2 udp 2130706432 148.147.200.251 9005 typ host\r\n"
2418 "a=ice-ufrag:cYuakxkEKH+RApYE\r\n"
2419 "a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n"
2420 "a=sendrecv\r\n";
2422 /*
2423 std::cout << "Setting offer to:" << std::endl
2424 << indent(offer) << std::endl;
2425 */
2426 a2_->SetRemote(TestObserver::OFFER, offer);
2428 //std::cout << "Creating answer:" << std::endl;
2429 a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO);
2431 std::string answer = a2_->answer();
2433 ASSERT_NE(answer.find(ss.str() + " opus/"), std::string::npos);
2434 }
2436 }
2438 TEST_F(SignalingTest, OfferAnswerCheckDescriptions)
2439 {
2440 sipcc::MediaConstraints constraints;
2441 OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, true,
2442 SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV);
2444 std::cout << "Caller's Local Description: " << std::endl
2445 << indent(a1_->getLocalDescription()) << std::endl << std::endl;
2447 std::cout << "Caller's Remote Description: " << std::endl
2448 << indent(a1_->getRemoteDescription()) << std::endl << std::endl;
2450 std::cout << "Callee's Local Description: " << std::endl
2451 << indent(a2_->getLocalDescription()) << std::endl << std::endl;
2453 std::cout << "Callee's Remote Description: " << std::endl
2454 << indent(a2_->getRemoteDescription()) << std::endl << std::endl;
2456 ASSERT_EQ(a1_->getLocalDescription(),a2_->getRemoteDescription());
2457 ASSERT_EQ(a2_->getLocalDescription(),a1_->getRemoteDescription());
2458 }
2460 TEST_F(SignalingTest, CheckTrickleSdpChange)
2461 {
2462 sipcc::MediaConstraints constraints;
2463 OfferAnswerTrickle(constraints, constraints,
2464 SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV);
2465 std::cerr << "ICE handshake completed" << std::endl;
2467 a1_->CloseSendStreams();
2468 a2_->CloseReceiveStreams();
2470 std::cout << "Caller's Local Description: " << std::endl
2471 << indent(a1_->getLocalDescription()) << std::endl << std::endl;
2473 std::cout << "Caller's Remote Description: " << std::endl
2474 << indent(a1_->getRemoteDescription()) << std::endl << std::endl;
2476 std::cout << "Callee's Local Description: " << std::endl
2477 << indent(a2_->getLocalDescription()) << std::endl << std::endl;
2479 std::cout << "Callee's Remote Description: " << std::endl
2480 << indent(a2_->getRemoteDescription()) << std::endl << std::endl;
2482 ASSERT_NE(a1_->getLocalDescription().find("\r\na=candidate"),
2483 std::string::npos);
2484 ASSERT_NE(a1_->getRemoteDescription().find("\r\na=candidate"),
2485 std::string::npos);
2486 ASSERT_NE(a2_->getLocalDescription().find("\r\na=candidate"),
2487 std::string::npos);
2488 ASSERT_NE(a2_->getRemoteDescription().find("\r\na=candidate"),
2489 std::string::npos);
2490 /* TODO (abr): These checks aren't quite right, since trickle ICE
2491 * can easily result in SDP that is semantically identical but
2492 * varies syntactically (in particularly, the ordering of attributes
2493 * withing an m-line section can be different). This needs to be updated
2494 * to be a semantic comparision between the SDP. Currently, these checks
2495 * will fail whenever we add any other attributes to the SDP, such as
2496 * RTCP MUX or RTCP feedback.
2497 ASSERT_EQ(a1_->getLocalDescription(),a2_->getRemoteDescription());
2498 ASSERT_EQ(a2_->getLocalDescription(),a1_->getRemoteDescription());
2499 */
2500 }
2502 TEST_F(SignalingTest, ipAddrAnyOffer)
2503 {
2504 EnsureInit();
2506 sipcc::MediaConstraints constraints;
2507 std::string offer =
2508 "v=0\r\n"
2509 "o=- 1 1 IN IP4 127.0.0.1\r\n"
2510 "s=-\r\n"
2511 "b=AS:64\r\n"
2512 "t=0 0\r\n"
2513 "a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:"
2514 "7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n"
2515 "m=audio 9000 RTP/AVP 99\r\n"
2516 "c=IN IP4 0.0.0.0\r\n"
2517 "a=rtpmap:99 opus/48000/2\r\n"
2518 "a=ice-ufrag:cYuakxkEKH+RApYE\r\n"
2519 "a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n"
2520 "a=sendrecv\r\n";
2522 a2_->SetRemote(TestObserver::OFFER, offer);
2523 ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateSuccess);
2524 a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO);
2525 ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateSuccess);
2526 std::string answer = a2_->answer();
2527 ASSERT_NE(answer.find("a=sendrecv"), std::string::npos);
2528 }
2530 static void CreateSDPForBigOTests(std::string& offer, const char *number) {
2531 offer =
2532 "v=0\r\n"
2533 "o=- ";
2534 offer += number;
2535 offer += " ";
2536 offer += number;
2537 offer += " IN IP4 127.0.0.1\r\n"
2538 "s=-\r\n"
2539 "b=AS:64\r\n"
2540 "t=0 0\r\n"
2541 "a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:"
2542 "7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n"
2543 "m=audio 9000 RTP/AVP 99\r\n"
2544 "c=IN IP4 0.0.0.0\r\n"
2545 "a=rtpmap:99 opus/48000/2\r\n"
2546 "a=ice-ufrag:cYuakxkEKH+RApYE\r\n"
2547 "a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n"
2548 "a=sendrecv\r\n";
2549 }
2551 TEST_F(SignalingTest, BigOValues)
2552 {
2553 EnsureInit();
2555 std::string offer;
2557 CreateSDPForBigOTests(offer, "12345678901234567");
2559 a2_->SetRemote(TestObserver::OFFER, offer);
2560 ASSERT_EQ(a2_->pObserver->state, TestObserver::stateSuccess);
2561 }
2563 TEST_F(SignalingTest, BigOValuesExtraChars)
2564 {
2565 EnsureInit();
2567 std::string offer;
2569 CreateSDPForBigOTests(offer, "12345678901234567FOOBAR");
2571 // The signaling state will remain "stable" because the unparsable
2572 // SDP leads to a failure in SetRemoteDescription.
2573 a2_->SetRemote(TestObserver::OFFER, offer, true,
2574 PCImplSignalingState::SignalingStable);
2575 ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateError);
2576 }
2578 TEST_F(SignalingTest, BigOValuesTooBig)
2579 {
2580 EnsureInit();
2582 std::string offer;
2584 CreateSDPForBigOTests(offer, "18446744073709551615");
2586 // The signaling state will remain "stable" because the unparsable
2587 // SDP leads to a failure in SetRemoteDescription.
2588 a2_->SetRemote(TestObserver::OFFER, offer, true,
2589 PCImplSignalingState::SignalingStable);
2590 ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateError);
2591 }
2593 TEST_F(SignalingTest, SetLocalAnswerInStable)
2594 {
2595 EnsureInit();
2597 sipcc::MediaConstraints constraints;
2598 CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
2600 // The signaling state will remain "stable" because the
2601 // SetLocalDescription call fails.
2602 a1_->SetLocal(TestObserver::ANSWER, a1_->offer(), true,
2603 PCImplSignalingState::SignalingStable);
2604 ASSERT_EQ(a1_->pObserver->lastStatusCode,
2605 sipcc::PeerConnectionImpl::kInvalidState);
2606 }
2608 TEST_F(SignalingTest, SetRemoteAnswerInStable) {
2609 EnsureInit();
2611 // The signaling state will remain "stable" because the
2612 // SetRemoteDescription call fails.
2613 a1_->SetRemote(TestObserver::ANSWER, strSampleSdpAudioVideoNoIce, true,
2614 PCImplSignalingState::SignalingStable);
2615 ASSERT_EQ(a1_->pObserver->lastStatusCode,
2616 sipcc::PeerConnectionImpl::kInvalidState);
2617 }
2619 TEST_F(SignalingTest, SetLocalAnswerInHaveLocalOffer) {
2620 sipcc::MediaConstraints constraints;
2621 CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
2622 a1_->SetLocal(TestObserver::OFFER, a1_->offer());
2623 ASSERT_EQ(a1_->pObserver->lastStatusCode,
2624 sipcc::PeerConnectionImpl::kNoError);
2626 // The signaling state will remain "have-local-offer" because the
2627 // SetLocalDescription call fails.
2628 a1_->SetLocal(TestObserver::ANSWER, a1_->offer(), true,
2629 PCImplSignalingState::SignalingHaveLocalOffer);
2630 ASSERT_EQ(a1_->pObserver->lastStatusCode,
2631 sipcc::PeerConnectionImpl::kInvalidState);
2632 }
2634 TEST_F(SignalingTest, SetRemoteOfferInHaveLocalOffer) {
2635 sipcc::MediaConstraints constraints;
2636 CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
2637 a1_->SetLocal(TestObserver::OFFER, a1_->offer());
2638 ASSERT_EQ(a1_->pObserver->lastStatusCode,
2639 sipcc::PeerConnectionImpl::kNoError);
2641 // The signaling state will remain "have-local-offer" because the
2642 // SetRemoteDescription call fails.
2643 a1_->SetRemote(TestObserver::OFFER, a1_->offer(), true,
2644 PCImplSignalingState::SignalingHaveLocalOffer);
2645 ASSERT_EQ(a1_->pObserver->lastStatusCode,
2646 sipcc::PeerConnectionImpl::kInvalidState);
2647 }
2649 TEST_F(SignalingTest, SetLocalOfferInHaveRemoteOffer) {
2650 sipcc::MediaConstraints constraints;
2651 CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
2652 a2_->SetRemote(TestObserver::OFFER, a1_->offer());
2653 ASSERT_EQ(a2_->pObserver->lastStatusCode,
2654 sipcc::PeerConnectionImpl::kNoError);
2656 // The signaling state will remain "have-remote-offer" because the
2657 // SetLocalDescription call fails.
2658 a2_->SetLocal(TestObserver::OFFER, a1_->offer(), true,
2659 PCImplSignalingState::SignalingHaveRemoteOffer);
2660 ASSERT_EQ(a2_->pObserver->lastStatusCode,
2661 sipcc::PeerConnectionImpl::kInvalidState);
2662 }
2664 TEST_F(SignalingTest, SetRemoteAnswerInHaveRemoteOffer) {
2665 sipcc::MediaConstraints constraints;
2666 CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
2667 a2_->SetRemote(TestObserver::OFFER, a1_->offer());
2668 ASSERT_EQ(a2_->pObserver->lastStatusCode,
2669 sipcc::PeerConnectionImpl::kNoError);
2671 // The signaling state will remain "have-remote-offer" because the
2672 // SetRemoteDescription call fails.
2673 a2_->SetRemote(TestObserver::ANSWER, a1_->offer(), true,
2674 PCImplSignalingState::SignalingHaveRemoteOffer);
2675 ASSERT_EQ(a2_->pObserver->lastStatusCode,
2676 sipcc::PeerConnectionImpl::kInvalidState);
2677 }
2679 // Disabled until the spec adds a failure callback to addStream
2680 TEST_F(SignalingTest, DISABLED_AddStreamInHaveLocalOffer) {
2681 sipcc::MediaConstraints constraints;
2682 CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
2683 a1_->SetLocal(TestObserver::OFFER, a1_->offer());
2684 ASSERT_EQ(a1_->pObserver->lastStatusCode,
2685 sipcc::PeerConnectionImpl::kNoError);
2686 a1_->AddStream();
2687 ASSERT_EQ(a1_->pObserver->lastStatusCode,
2688 sipcc::PeerConnectionImpl::kInvalidState);
2689 }
2691 // Disabled until the spec adds a failure callback to removeStream
2692 TEST_F(SignalingTest, DISABLED_RemoveStreamInHaveLocalOffer) {
2693 sipcc::MediaConstraints constraints;
2694 CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
2695 a1_->SetLocal(TestObserver::OFFER, a1_->offer());
2696 ASSERT_EQ(a1_->pObserver->lastStatusCode,
2697 sipcc::PeerConnectionImpl::kNoError);
2698 a1_->RemoveLastStreamAdded();
2699 ASSERT_EQ(a1_->pObserver->lastStatusCode,
2700 sipcc::PeerConnectionImpl::kInvalidState);
2701 }
2703 TEST_F(SignalingTest, AddCandidateInHaveLocalOffer) {
2704 sipcc::MediaConstraints constraints;
2705 CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
2706 a1_->SetLocal(TestObserver::OFFER, a1_->offer());
2707 ASSERT_EQ(a1_->pObserver->lastStatusCode,
2708 sipcc::PeerConnectionImpl::kNoError);
2709 a1_->AddIceCandidate(strSampleCandidate.c_str(),
2710 strSampleMid.c_str(), nSamplelevel, false);
2711 ASSERT_EQ(a1_->pObserver->lastStatusCode,
2712 sipcc::PeerConnectionImpl::kInvalidState);
2713 }
2715 TEST_F(SignalingAgentTest, CreateOffer) {
2716 CreateAgent();
2717 sipcc::MediaConstraints constraints;
2718 agent(0)->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
2719 PR_Sleep(20000);
2720 }
2722 TEST_F(SignalingAgentTest, CreateOfferTrickleTestServer) {
2723 TestStunServer::GetInstance()->SetActive(false);
2724 TestStunServer::GetInstance()->SetResponseAddr(
2725 kBogusSrflxAddress, kBogusSrflxPort);
2727 CreateAgent(
2728 TestStunServer::GetInstance()->addr(),
2729 TestStunServer::GetInstance()->port(),
2730 false);
2732 sipcc::MediaConstraints constraints;
2733 agent(0)->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
2735 // Verify that the bogus addr is not there.
2736 ASSERT_FALSE(agent(0)->OfferContains(kBogusSrflxAddress));
2738 // Now enable the STUN server.
2739 TestStunServer::GetInstance()->SetActive(true);
2740 agent(0)->WaitForGather();
2742 // There shouldn't be any candidates until SetLocal.
2743 ASSERT_EQ(0U, agent(0)->MatchingCandidates(kBogusSrflxAddress));
2745 // Verify that the candidates appear in the offer.
2746 size_t match;
2747 match = agent(0)->getLocalDescription().find(kBogusSrflxAddress);
2748 ASSERT_LT(0U, match);
2749 }
2751 TEST_F(SignalingAgentTest, CreateOfferSetLocalTrickleTestServer) {
2752 TestStunServer::GetInstance()->SetActive(false);
2753 TestStunServer::GetInstance()->SetResponseAddr(
2754 kBogusSrflxAddress, kBogusSrflxPort);
2756 CreateAgent(
2757 TestStunServer::GetInstance()->addr(),
2758 TestStunServer::GetInstance()->port(),
2759 false);
2761 sipcc::MediaConstraints constraints;
2762 agent(0)->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
2764 // Verify that the bogus addr is not there.
2765 ASSERT_FALSE(agent(0)->OfferContains(kBogusSrflxAddress));
2767 // Now enable the STUN server.
2768 TestStunServer::GetInstance()->SetActive(true);
2769 agent(0)->WaitForGather();
2771 // There shouldn't be any candidates until SetLocal.
2772 ASSERT_EQ(0U, agent(0)->MatchingCandidates(kBogusSrflxAddress));
2774 agent(0)->SetLocal(TestObserver::OFFER, agent(0)->offer());
2775 PR_Sleep(1000); // Give time for the message queues.
2777 // Verify that we got our candidates.
2778 ASSERT_LE(2U, agent(0)->MatchingCandidates(kBogusSrflxAddress));
2780 // Verify that the candidates appear in the offer.
2781 size_t match;
2782 match = agent(0)->getLocalDescription().find(kBogusSrflxAddress);
2783 ASSERT_LT(0U, match);
2784 }
2787 TEST_F(SignalingAgentTest, CreateAnswerSetLocalTrickleTestServer) {
2788 TestStunServer::GetInstance()->SetActive(false);
2789 TestStunServer::GetInstance()->SetResponseAddr(
2790 kBogusSrflxAddress, kBogusSrflxPort);
2792 CreateAgent(
2793 TestStunServer::GetInstance()->addr(),
2794 TestStunServer::GetInstance()->port(),
2795 false);
2797 std::string offer(strG711SdpOffer);
2798 agent(0)->SetRemote(TestObserver::OFFER, offer, true,
2799 PCImplSignalingState::SignalingHaveRemoteOffer);
2800 ASSERT_EQ(agent(0)->pObserver->lastStatusCode,
2801 sipcc::PeerConnectionImpl::kNoError);
2803 sipcc::MediaConstraints constraints;
2804 agent(0)->CreateAnswer(constraints, offer, ANSWER_AUDIO, DONT_CHECK_AUDIO);
2806 // Verify that the bogus addr is not there.
2807 ASSERT_FALSE(agent(0)->AnswerContains(kBogusSrflxAddress));
2809 // Now enable the STUN server.
2810 TestStunServer::GetInstance()->SetActive(true);
2811 agent(0)->WaitForGather();
2813 // There shouldn't be any candidates until SetLocal.
2814 ASSERT_EQ(0U, agent(0)->MatchingCandidates(kBogusSrflxAddress));
2816 agent(0)->SetLocal(TestObserver::ANSWER, agent(0)->answer());
2817 PR_Sleep(1000); // Give time for the message queues.
2819 // Verify that we got our candidates.
2820 ASSERT_LE(2U, agent(0)->MatchingCandidates(kBogusSrflxAddress));
2822 // Verify that the candidates appear in the answer.
2823 size_t match;
2824 match = agent(0)->getLocalDescription().find(kBogusSrflxAddress);
2825 ASSERT_LT(0U, match);
2826 }
2830 TEST_F(SignalingAgentTest, CreateUntilFailThenWait) {
2831 int i;
2833 for (i=0; ; i++) {
2834 if (!CreateAgent())
2835 break;
2836 std::cerr << "Created agent " << i << std::endl;
2837 }
2838 std::cerr << "Failed after creating " << i << " PCs " << std::endl;
2839 PR_Sleep(10000); // Wait to see if we crash
2840 }
2842 // Test for bug 856433.
2843 TEST_F(SignalingAgentTest, CreateNoInit) {
2844 CreateAgentNoInit();
2845 }
2848 /*
2849 * Test for Bug 843595
2850 */
2851 TEST_F(SignalingTest, missingUfrag)
2852 {
2853 EnsureInit();
2855 sipcc::MediaConstraints constraints;
2856 std::string offer =
2857 "v=0\r\n"
2858 "o=Mozilla-SIPUA 2208 0 IN IP4 0.0.0.0\r\n"
2859 "s=SIP Call\r\n"
2860 "t=0 0\r\n"
2861 "a=ice-pwd:4450d5a4a5f097855c16fa079893be18\r\n"
2862 "a=fingerprint:sha-256 23:9A:2E:43:94:42:CF:46:68:FC:62:F9:F4:48:61:DB:"
2863 "2F:8C:C9:FF:6B:25:54:9D:41:09:EF:83:A8:19:FC:B6\r\n"
2864 "m=audio 56187 RTP/SAVPF 109 0 8 101\r\n"
2865 "c=IN IP4 77.9.79.167\r\n"
2866 "a=rtpmap:109 opus/48000/2\r\n"
2867 "a=ptime:20\r\n"
2868 "a=rtpmap:0 PCMU/8000\r\n"
2869 "a=rtpmap:8 PCMA/8000\r\n"
2870 "a=rtpmap:101 telephone-event/8000\r\n"
2871 "a=fmtp:101 0-15\r\n"
2872 "a=sendrecv\r\n"
2873 "a=candidate:0 1 UDP 2113601791 192.168.178.20 56187 typ host\r\n"
2874 "a=candidate:1 1 UDP 1694236671 77.9.79.167 56187 typ srflx raddr "
2875 "192.168.178.20 rport 56187\r\n"
2876 "a=candidate:0 2 UDP 2113601790 192.168.178.20 52955 typ host\r\n"
2877 "a=candidate:1 2 UDP 1694236670 77.9.79.167 52955 typ srflx raddr "
2878 "192.168.178.20 rport 52955\r\n"
2879 "m=video 49929 RTP/SAVPF 120\r\n"
2880 "c=IN IP4 77.9.79.167\r\n"
2881 "a=rtpmap:120 VP8/90000\r\n"
2882 "a=recvonly\r\n"
2883 "a=candidate:0 1 UDP 2113601791 192.168.178.20 49929 typ host\r\n"
2884 "a=candidate:1 1 UDP 1694236671 77.9.79.167 49929 typ srflx raddr "
2885 "192.168.178.20 rport 49929\r\n"
2886 "a=candidate:0 2 UDP 2113601790 192.168.178.20 50769 typ host\r\n"
2887 "a=candidate:1 2 UDP 1694236670 77.9.79.167 50769 typ srflx raddr "
2888 "192.168.178.20 rport 50769\r\n"
2889 "m=application 54054 DTLS/SCTP 5000\r\n"
2890 "c=IN IP4 77.9.79.167\r\n"
2891 "a=fmtp:HuRUu]Dtcl\\zM,7(OmEU%O$gU]x/z\tD protocol=webrtc-datachannel;"
2892 "streams=16\r\n"
2893 "a=sendrecv\r\n";
2895 // Need to create an offer, since that's currently required by our
2896 // FSM. This may change in the future.
2897 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV);
2898 a1_->SetLocal(TestObserver::OFFER, offer, true);
2899 // We now detect the missing ICE parameters at SetRemoteDescription
2900 a2_->SetRemote(TestObserver::OFFER, offer, true,
2901 PCImplSignalingState::SignalingStable);
2902 ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateError);
2903 }
2905 TEST_F(SignalingTest, AudioOnlyCalleeNoRtcpMux)
2906 {
2907 EnsureInit();
2909 sipcc::MediaConstraints constraints;
2911 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
2912 a1_->SetLocal(TestObserver::OFFER, a1_->offer(), false);
2913 ParsedSDP sdpWrapper(a1_->offer());
2914 sdpWrapper.DeleteLine("a=rtcp-mux");
2915 std::cout << "Modified SDP " << std::endl
2916 << indent(sdpWrapper.getSdp()) << std::endl;
2917 a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp(), false);
2918 a2_->CreateAnswer(constraints, sdpWrapper.getSdp(),
2919 OFFER_AUDIO | ANSWER_AUDIO);
2920 a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false);
2921 a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false);
2923 // Answer should not have a=rtcp-mux
2924 ASSERT_EQ(a2_->getLocalDescription().find("\r\na=rtcp-mux"),
2925 std::string::npos);
2927 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
2928 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
2930 // Wait for some data to get written
2931 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
2932 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
2934 a1_->CloseSendStreams();
2935 a2_->CloseReceiveStreams();
2937 ASSERT_GE(a1_->GetPacketsSent(0), 40);
2938 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
2940 // Check the low-level media pipeline
2941 // for RTP and RTCP flows
2942 // The first Local pipeline gets stored at 0
2943 a1_->CheckMediaPipeline(0, 0, PIPELINE_LOCAL | PIPELINE_SEND);
2945 // The first Remote pipeline gets stored at 1
2946 a2_->CheckMediaPipeline(0, 1, 0);
2947 }
2949 TEST_F(SignalingTest, FullCallAudioNoMuxVideoMux)
2950 {
2951 EnsureInit();
2953 sipcc::MediaConstraints constraints;
2955 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV);
2956 a1_->SetLocal(TestObserver::OFFER, a1_->offer(), false);
2957 ParsedSDP sdpWrapper(a1_->offer());
2958 sdpWrapper.DeleteLine("a=rtcp-mux");
2959 std::cout << "Modified SDP " << std::endl
2960 << indent(sdpWrapper.getSdp()) << std::endl;
2961 a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp(), false);
2962 a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), OFFER_AV | ANSWER_AV);
2963 a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false);
2964 a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false);
2966 // Answer should have only one a=rtcp-mux line
2967 size_t match = a2_->getLocalDescription().find("\r\na=rtcp-mux");
2968 if (fRtcpMux) {
2969 ASSERT_NE(match, std::string::npos);
2970 match = a2_->getLocalDescription().find("\r\na=rtcp-mux", match + 1);
2971 }
2972 ASSERT_EQ(match, std::string::npos);
2974 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
2975 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
2977 // Wait for some data to get written
2978 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
2979 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
2981 a1_->CloseSendStreams();
2982 a2_->CloseReceiveStreams();
2984 ASSERT_GE(a1_->GetPacketsSent(0), 40);
2985 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
2987 // Check the low-level media pipeline
2988 // for RTP and RTCP flows
2989 // The first Local pipeline gets stored at 0
2990 a1_->CheckMediaPipeline(0, 0, PIPELINE_LOCAL | PIPELINE_SEND);
2992 // Now check video mux.
2993 a1_->CheckMediaPipeline(0, 1,
2994 PIPELINE_LOCAL | (fRtcpMux ? PIPELINE_RTCP_MUX : 0) | PIPELINE_SEND |
2995 PIPELINE_VIDEO);
2997 // The first Remote pipeline gets stored at 1
2998 a2_->CheckMediaPipeline(0, 1, 0);
3000 // Now check video mux.
3001 a2_->CheckMediaPipeline(0, 2, (fRtcpMux ? PIPELINE_RTCP_MUX : 0) |
3002 PIPELINE_VIDEO | PIPELINE_RTCP_NACK, VideoSessionConduit::FrameRequestPli);
3003 }
3005 TEST_F(SignalingTest, RtcpFbInOffer)
3006 {
3007 EnsureInit();
3008 sipcc::MediaConstraints constraints;
3009 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV);
3010 const char *expected[] = { "nack", "nack pli", "ccm fir" };
3011 CheckRtcpFbSdp(a1_->offer(), ARRAY_TO_SET(std::string, expected));
3012 }
3014 TEST_F(SignalingTest, RtcpFbInAnswer)
3015 {
3016 const char *feedbackTypes[] = { "nack", "nack pli", "ccm fir" };
3017 TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes),
3018 PIPELINE_RTCP_NACK,
3019 VideoSessionConduit::FrameRequestPli);
3020 }
3022 TEST_F(SignalingTest, RtcpFbNoNackBasic)
3023 {
3024 const char *feedbackTypes[] = { "nack pli", "ccm fir" };
3025 TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes),
3026 0,
3027 VideoSessionConduit::FrameRequestPli);
3028 }
3030 TEST_F(SignalingTest, RtcpFbNoNackPli)
3031 {
3032 const char *feedbackTypes[] = { "nack", "ccm fir" };
3033 TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes),
3034 PIPELINE_RTCP_NACK,
3035 VideoSessionConduit::FrameRequestFir);
3036 }
3038 TEST_F(SignalingTest, RtcpFbNoCcmFir)
3039 {
3040 const char *feedbackTypes[] = { "nack", "nack pli" };
3041 TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes),
3042 PIPELINE_RTCP_NACK,
3043 VideoSessionConduit::FrameRequestPli);
3044 }
3046 TEST_F(SignalingTest, RtcpFbNoNack)
3047 {
3048 const char *feedbackTypes[] = { "ccm fir" };
3049 TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes),
3050 0,
3051 VideoSessionConduit::FrameRequestFir);
3052 }
3054 TEST_F(SignalingTest, RtcpFbNoFrameRequest)
3055 {
3056 const char *feedbackTypes[] = { "nack" };
3057 TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes),
3058 PIPELINE_RTCP_NACK,
3059 VideoSessionConduit::FrameRequestNone);
3060 }
3062 TEST_F(SignalingTest, RtcpFbPliOnly)
3063 {
3064 const char *feedbackTypes[] = { "nack pli" };
3065 TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes),
3066 0,
3067 VideoSessionConduit::FrameRequestPli);
3068 }
3070 TEST_F(SignalingTest, RtcpFbNoFeedback)
3071 {
3072 const char *feedbackTypes[] = { };
3073 TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes),
3074 0,
3075 VideoSessionConduit::FrameRequestNone);
3076 }
3078 // In this test we will change the offer SDP's a=setup value
3079 // from actpass to passive. This will make the answer do active.
3080 TEST_F(SignalingTest, AudioCallForceDtlsRoles)
3081 {
3082 EnsureInit();
3084 sipcc::MediaConstraints constraints;
3085 size_t match;
3087 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
3089 // By default the offer should give actpass
3090 std::string offer(a1_->offer());
3091 match = offer.find("\r\na=setup:actpass");
3092 ASSERT_NE(match, std::string::npos);
3093 // Now replace the actpass with passive so that the answer will
3094 // return active
3095 offer.replace(match, strlen("\r\na=setup:actpass"),
3096 "\r\na=setup:passive");
3097 std::cout << "Modified SDP " << std::endl
3098 << indent(offer) << std::endl;
3100 a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false);
3101 a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false);
3102 a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
3104 // Now the answer should contain a=setup:active
3105 std::string answer(a2_->answer());
3106 match = answer.find("\r\na=setup:active");
3107 ASSERT_NE(match, std::string::npos);
3109 // This should setup the DTLS with the same roles
3110 // as the regular tests above.
3111 a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false);
3112 a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false);
3114 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
3115 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
3117 // Wait for some data to get written
3118 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
3119 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
3121 a1_->CloseSendStreams();
3122 a2_->CloseReceiveStreams();
3124 ASSERT_GE(a1_->GetPacketsSent(0), 40);
3125 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
3126 }
3128 // In this test we will change the offer SDP's a=setup value
3129 // from actpass to active. This will make the answer do passive
3130 TEST_F(SignalingTest, AudioCallReverseDtlsRoles)
3131 {
3132 EnsureInit();
3134 sipcc::MediaConstraints constraints;
3135 size_t match;
3137 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
3139 // By default the offer should give actpass
3140 std::string offer(a1_->offer());
3141 match = offer.find("\r\na=setup:actpass");
3142 ASSERT_NE(match, std::string::npos);
3143 // Now replace the actpass with active so that the answer will
3144 // return passive
3145 offer.replace(match, strlen("\r\na=setup:actpass"),
3146 "\r\na=setup:active");
3147 std::cout << "Modified SDP " << std::endl
3148 << indent(offer) << std::endl;
3150 a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false);
3151 a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false);
3152 a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
3154 // Now the answer should contain a=setup:passive
3155 std::string answer(a2_->answer());
3156 match = answer.find("\r\na=setup:passive");
3157 ASSERT_NE(match, std::string::npos);
3159 // This should setup the DTLS with the opposite roles
3160 // than the regular tests above.
3161 a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false);
3162 a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false);
3164 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
3165 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
3167 // Wait for some data to get written
3168 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
3169 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
3171 a1_->CloseSendStreams();
3172 a2_->CloseReceiveStreams();
3174 ASSERT_GE(a1_->GetPacketsSent(0), 40);
3175 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
3176 }
3178 // In this test we will change the answer SDP's a=setup value
3179 // from active to passive. This will make both sides do
3180 // active and should not connect.
3181 TEST_F(SignalingTest, AudioCallMismatchDtlsRoles)
3182 {
3183 EnsureInit();
3185 sipcc::MediaConstraints constraints;
3186 size_t match;
3188 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
3190 // By default the offer should give actpass
3191 std::string offer(a1_->offer());
3192 match = offer.find("\r\na=setup:actpass");
3193 ASSERT_NE(match, std::string::npos);
3194 a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false);
3195 a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false);
3196 a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
3198 // Now the answer should contain a=setup:active
3199 std::string answer(a2_->answer());
3200 match = answer.find("\r\na=setup:active");
3201 ASSERT_NE(match, std::string::npos);
3203 // Now replace the active with passive so that the offerer will
3204 // also do active.
3205 answer.replace(match, strlen("\r\na=setup:active"),
3206 "\r\na=setup:passive");
3207 std::cout << "Modified SDP " << std::endl
3208 << indent(answer) << std::endl;
3210 // This should setup the DTLS with both sides playing active
3211 a2_->SetLocal(TestObserver::ANSWER, answer.c_str(), false);
3212 a1_->SetRemote(TestObserver::ANSWER, answer.c_str(), false);
3214 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
3215 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
3217 // Not using ASSERT_TRUE_WAIT here because we expect failure
3218 PR_Sleep(kDefaultTimeout * 2); // Wait for some data to get written
3220 a1_->CloseSendStreams();
3221 a2_->CloseReceiveStreams();
3223 ASSERT_GE(a1_->GetPacketsSent(0), 40);
3224 // In this case we should receive nothing.
3225 ASSERT_EQ(a2_->GetPacketsReceived(0), 0);
3226 }
3228 // In this test we will change the offer SDP's a=setup value
3229 // from actpass to garbage. It should ignore the garbage value
3230 // and respond with setup:active
3231 TEST_F(SignalingTest, AudioCallGarbageSetup)
3232 {
3233 EnsureInit();
3235 sipcc::MediaConstraints constraints;
3236 size_t match;
3238 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
3240 // By default the offer should give actpass
3241 std::string offer(a1_->offer());
3242 match = offer.find("\r\na=setup:actpass");
3243 ASSERT_NE(match, std::string::npos);
3244 // Now replace the actpass with a garbage value
3245 offer.replace(match, strlen("\r\na=setup:actpass"),
3246 "\r\na=setup:G4rb4g3V4lu3");
3247 std::cout << "Modified SDP " << std::endl
3248 << indent(offer) << std::endl;
3250 a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false);
3251 a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false);
3252 a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
3254 // Now the answer should contain a=setup:active
3255 std::string answer(a2_->answer());
3256 match = answer.find("\r\na=setup:active");
3257 ASSERT_NE(match, std::string::npos);
3259 // This should setup the DTLS with the same roles
3260 // as the regular tests above.
3261 a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false);
3262 a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false);
3264 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
3265 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
3267 // Wait for some data to get written
3268 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
3269 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
3271 a1_->CloseSendStreams();
3272 a2_->CloseReceiveStreams();
3274 ASSERT_GE(a1_->GetPacketsSent(0), 40);
3275 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
3276 }
3278 // In this test we will change the offer SDP to remove the
3279 // a=setup line. Answer should respond with a=setup:active.
3280 TEST_F(SignalingTest, AudioCallOfferNoSetupOrConnection)
3281 {
3282 EnsureInit();
3284 sipcc::MediaConstraints constraints;
3285 size_t match;
3287 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
3289 // By default the offer should give setup:actpass
3290 std::string offer(a1_->offer());
3291 match = offer.find("\r\na=setup:actpass");
3292 ASSERT_NE(match, std::string::npos);
3293 // Remove the a=setup line
3294 offer.replace(match, strlen("\r\na=setup:actpass"), "");
3295 std::cout << "Modified SDP " << std::endl
3296 << indent(offer) << std::endl;
3298 a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false);
3299 a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false);
3300 a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
3302 // Now the answer should contain a=setup:active
3303 std::string answer(a2_->answer());
3304 match = answer.find("\r\na=setup:active");
3305 ASSERT_NE(match, std::string::npos);
3307 // This should setup the DTLS with the same roles
3308 // as the regular tests above.
3309 a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false);
3310 a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false);
3312 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
3313 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
3315 // Wait for some data to get written
3316 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
3317 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
3319 a1_->CloseSendStreams();
3320 a2_->CloseReceiveStreams();
3322 ASSERT_GE(a1_->GetPacketsSent(0), 40);
3323 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
3324 }
3326 // In this test we will change the answer SDP to remove the
3327 // a=setup line. ICE should still connect since active will
3328 // be assumed.
3329 TEST_F(SignalingTest, AudioCallAnswerNoSetupOrConnection)
3330 {
3331 EnsureInit();
3333 sipcc::MediaConstraints constraints;
3334 size_t match;
3336 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
3338 // By default the offer should give setup:actpass
3339 std::string offer(a1_->offer());
3340 match = offer.find("\r\na=setup:actpass");
3341 ASSERT_NE(match, std::string::npos);
3343 a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false);
3344 a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false);
3345 a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
3347 // Now the answer should contain a=setup:active
3348 std::string answer(a2_->answer());
3349 match = answer.find("\r\na=setup:active");
3350 ASSERT_NE(match, std::string::npos);
3351 // Remove the a=setup line
3352 answer.replace(match, strlen("\r\na=setup:active"), "");
3353 std::cout << "Modified SDP " << std::endl
3354 << indent(answer) << std::endl;
3356 // This should setup the DTLS with the same roles
3357 // as the regular tests above.
3358 a2_->SetLocal(TestObserver::ANSWER, answer, false);
3359 a1_->SetRemote(TestObserver::ANSWER, answer, false);
3361 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
3362 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
3364 // Wait for some data to get written
3365 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
3366 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
3368 a1_->CloseSendStreams();
3369 a2_->CloseReceiveStreams();
3371 ASSERT_GE(a1_->GetPacketsSent(0), 40);
3372 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
3373 }
3376 TEST_F(SignalingTest, FullCallRealTrickle)
3377 {
3378 wait_for_gather_ = false;
3380 sipcc::MediaConstraints constraints;
3381 OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV,
3382 true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV);
3384 // Wait for some data to get written
3385 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
3386 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
3388 a1_->CloseSendStreams();
3389 a2_->CloseReceiveStreams();
3390 ASSERT_GE(a1_->GetPacketsSent(0), 40);
3391 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
3392 }
3394 TEST_F(SignalingTest, FullCallRealTrickleTestServer)
3395 {
3396 wait_for_gather_ = false;
3397 SetTestStunServer();
3399 sipcc::MediaConstraints constraints;
3400 OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV,
3401 true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV);
3403 TestStunServer::GetInstance()->SetActive(true);
3405 // Wait for some data to get written
3406 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 &&
3407 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
3409 a1_->CloseSendStreams();
3410 a2_->CloseReceiveStreams();
3411 ASSERT_GE(a1_->GetPacketsSent(0), 40);
3412 ASSERT_GE(a2_->GetPacketsReceived(0), 40);
3413 }
3415 TEST_F(SignalingTest, hugeSdp)
3416 {
3417 EnsureInit();
3419 sipcc::MediaConstraints constraints;
3420 std::string offer =
3421 "v=0\r\n"
3422 "o=- 1109973417102828257 2 IN IP4 127.0.0.1\r\n"
3423 "s=-\r\n"
3424 "t=0 0\r\n"
3425 "a=group:BUNDLE audio video\r\n"
3426 "a=msid-semantic: WMS 1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n"
3427 "m=audio 32952 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126\r\n"
3428 "c=IN IP4 128.64.32.16\r\n"
3429 "a=rtcp:32952 IN IP4 128.64.32.16\r\n"
3430 "a=candidate:77142221 1 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n"
3431 "a=candidate:77142221 2 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n"
3432 "a=candidate:983072742 1 udp 2113937151 172.22.0.56 54082 typ host generation 0\r\n"
3433 "a=candidate:983072742 2 udp 2113937151 172.22.0.56 54082 typ host generation 0\r\n"
3434 "a=candidate:2245074553 1 udp 1845501695 32.64.128.1 62397 typ srflx raddr 192.168.137.1 rport 54081 generation 0\r\n"
3435 "a=candidate:2245074553 2 udp 1845501695 32.64.128.1 62397 typ srflx raddr 192.168.137.1 rport 54081 generation 0\r\n"
3436 "a=candidate:2479353907 1 udp 1845501695 32.64.128.1 54082 typ srflx raddr 172.22.0.56 rport 54082 generation 0\r\n"
3437 "a=candidate:2479353907 2 udp 1845501695 32.64.128.1 54082 typ srflx raddr 172.22.0.56 rport 54082 generation 0\r\n"
3438 "a=candidate:1243276349 1 tcp 1509957375 192.168.137.1 0 typ host generation 0\r\n"
3439 "a=candidate:1243276349 2 tcp 1509957375 192.168.137.1 0 typ host generation 0\r\n"
3440 "a=candidate:1947960086 1 tcp 1509957375 172.22.0.56 0 typ host generation 0\r\n"
3441 "a=candidate:1947960086 2 tcp 1509957375 172.22.0.56 0 typ host generation 0\r\n"
3442 "a=candidate:1808221584 1 udp 33562367 128.64.32.16 32952 typ relay raddr 32.64.128.1 rport 62398 generation 0\r\n"
3443 "a=candidate:1808221584 2 udp 33562367 128.64.32.16 32952 typ relay raddr 32.64.128.1 rport 62398 generation 0\r\n"
3444 "a=candidate:507872740 1 udp 33562367 128.64.32.16 40975 typ relay raddr 32.64.128.1 rport 54085 generation 0\r\n"
3445 "a=candidate:507872740 2 udp 33562367 128.64.32.16 40975 typ relay raddr 32.64.128.1 rport 54085 generation 0\r\n"
3446 "a=ice-ufrag:xQuJwjX3V3eMA81k\r\n"
3447 "a=ice-pwd:ZUiRmjS2GDhG140p73dAsSVP\r\n"
3448 "a=ice-options:google-ice\r\n"
3449 "a=fingerprint:sha-256 59:4A:8B:73:A7:73:53:71:88:D7:4D:58:28:0C:79:72:31:29:9B:05:37:DD:58:43:C2:D4:85:A2:B3:66:38:7A\r\n"
3450 "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n"
3451 "a=sendrecv\r\n"
3452 "a=mid:audio\r\n"
3453 "a=rtcp-mux\r\n"
3454 "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:/U44g3ULdtapeiSg+T3n6dDLBKIjpOhb/NXAL/2b\r\n"
3455 "a=rtpmap:111 opus/48000/2\r\n"
3456 "a=fmtp:111 minptime=10\r\n"
3457 "a=rtpmap:103 ISAC/16000\r\n"
3458 "a=rtpmap:104 ISAC/32000\r\n"
3459 "a=rtpmap:0 PCMU/8000\r\n"
3460 "a=rtpmap:8 PCMA/8000\r\n"
3461 "a=rtpmap:107 CN/48000\r\n"
3462 "a=rtpmap:106 CN/32000\r\n"
3463 "a=rtpmap:105 CN/16000\r\n"
3464 "a=rtpmap:13 CN/8000\r\n"
3465 "a=rtpmap:126 telephone-event/8000\r\n"
3466 "a=maxptime:60\r\n"
3467 "a=ssrc:2271517329 cname:mKDNt7SQf6pwDlIn\r\n"
3468 "a=ssrc:2271517329 msid:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP 1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPa0\r\n"
3469 "a=ssrc:2271517329 mslabel:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n"
3470 "a=ssrc:2271517329 label:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPa0\r\n"
3471 "m=video 32952 RTP/SAVPF 100 116 117\r\n"
3472 "c=IN IP4 128.64.32.16\r\n"
3473 "a=rtcp:32952 IN IP4 128.64.32.16\r\n"
3474 "a=candidate:77142221 1 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n"
3475 "a=candidate:77142221 2 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n"
3476 "a=candidate:983072742 1 udp 2113937151 172.22.0.56 54082 typ host generation 0\r\n"
3477 "a=candidate:983072742 2 udp 2113937151 172.22.0.56 54082 typ host generation 0\r\n"
3478 "a=candidate:2245074553 1 udp 1845501695 32.64.128.1 62397 typ srflx raddr 192.168.137.1 rport 54081 generation 0\r\n"
3479 "a=candidate:2245074553 2 udp 1845501695 32.64.128.1 62397 typ srflx raddr 192.168.137.1 rport 54081 generation 0\r\n"
3480 "a=candidate:2479353907 1 udp 1845501695 32.64.128.1 54082 typ srflx raddr 172.22.0.56 rport 54082 generation 0\r\n"
3481 "a=candidate:2479353907 2 udp 1845501695 32.64.128.1 54082 typ srflx raddr 172.22.0.56 rport 54082 generation 0\r\n"
3482 "a=candidate:1243276349 1 tcp 1509957375 192.168.137.1 0 typ host generation 0\r\n"
3483 "a=candidate:1243276349 2 tcp 1509957375 192.168.137.1 0 typ host generation 0\r\n"
3484 "a=candidate:1947960086 1 tcp 1509957375 172.22.0.56 0 typ host generation 0\r\n"
3485 "a=candidate:1947960086 2 tcp 1509957375 172.22.0.56 0 typ host generation 0\r\n"
3486 "a=candidate:1808221584 1 udp 33562367 128.64.32.16 32952 typ relay raddr 32.64.128.1 rport 62398 generation 0\r\n"
3487 "a=candidate:1808221584 2 udp 33562367 128.64.32.16 32952 typ relay raddr 32.64.128.1 rport 62398 generation 0\r\n"
3488 "a=candidate:507872740 1 udp 33562367 128.64.32.16 40975 typ relay raddr 32.64.128.1 rport 54085 generation 0\r\n"
3489 "a=candidate:507872740 2 udp 33562367 128.64.32.16 40975 typ relay raddr 32.64.128.1 rport 54085 generation 0\r\n"
3490 "a=ice-ufrag:xQuJwjX3V3eMA81k\r\n"
3491 "a=ice-pwd:ZUiRmjS2GDhG140p73dAsSVP\r\n"
3492 "a=ice-options:google-ice\r\n"
3493 "a=fingerprint:sha-256 59:4A:8B:73:A7:73:53:71:88:D7:4D:58:28:0C:79:72:31:29:9B:05:37:DD:58:43:C2:D4:85:A2:B3:66:38:7A\r\n"
3494 "a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\n"
3495 "a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n"
3496 "a=sendrecv\r\n"
3497 "a=mid:video\r\n"
3498 "a=rtcp-mux\r\n"
3499 "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:/U44g3ULdtapeiSg+T3n6dDLBKIjpOhb/NXAL/2b\r\n"
3500 "a=rtpmap:100 VP8/90000\r\n"
3501 "a=rtcp-fb:100 ccm fir\r\n"
3502 "a=rtcp-fb:100 nack\r\n"
3503 "a=rtcp-fb:100 goog-remb\r\n"
3504 "a=rtpmap:116 red/90000\r\n"
3505 "a=rtpmap:117 ulpfec/90000\r\n"
3506 "a=ssrc:54724160 cname:mKDNt7SQf6pwDlIn\r\n"
3507 "a=ssrc:54724160 msid:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP 1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPv0\r\n"
3508 "a=ssrc:54724160 mslabel:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n"
3509 "a=ssrc:54724160 label:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPv0\r\n";
3511 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV);
3512 a1_->SetLocal(TestObserver::OFFER, offer, true);
3514 a2_->SetRemote(TestObserver::OFFER, offer, true);
3515 ASSERT_GE(a2_->getRemoteDescription().length(), 4096U);
3516 a2_->CreateAnswer(constraints, offer, OFFER_AV);
3517 }
3519 // Test max_fs and max_fr prefs have proper impact on SDP offer
3520 TEST_F(SignalingTest, MaxFsFrInOffer)
3521 {
3522 EnsureInit();
3524 sipcc::MediaConstraints constraints;
3526 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
3527 ASSERT_TRUE(prefs);
3528 FsFrPrefClearer prefClearer(prefs);
3530 SetMaxFsFr(prefs, 300, 30);
3532 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV);
3534 // Verify that SDP contains correct max-fs and max-fr
3535 CheckMaxFsFrSdp(a1_->offer(), 120, 300, 30);
3536 }
3538 // Test max_fs and max_fr prefs have proper impact on SDP answer
3539 TEST_F(SignalingTest, MaxFsFrInAnswer)
3540 {
3541 EnsureInit();
3543 sipcc::MediaConstraints constraints;
3545 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
3546 ASSERT_TRUE(prefs);
3547 FsFrPrefClearer prefClearer(prefs);
3549 // We don't want max_fs and max_fr prefs impact SDP at this moment
3550 SetMaxFsFr(prefs, 0, 0);
3552 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV);
3554 // SDP should not contain max-fs and max-fr here
3555 CheckMaxFsFrSdp(a1_->offer(), 120, 0, 0);
3557 a2_->SetRemote(TestObserver::OFFER, a1_->offer());
3559 SetMaxFsFr(prefs, 600, 60);
3561 a2_->CreateAnswer(constraints, a1_->offer(), OFFER_AV | ANSWER_AV);
3563 // Verify that SDP contains correct max-fs and max-fr
3564 CheckMaxFsFrSdp(a2_->answer(), 120, 600, 60);
3565 }
3567 // Test SDP offer has proper impact on callee's codec configuration
3568 TEST_F(SignalingTest, MaxFsFrCalleeCodec)
3569 {
3570 EnsureInit();
3572 sipcc::MediaConstraints constraints;
3574 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
3575 ASSERT_TRUE(prefs);
3576 FsFrPrefClearer prefClearer(prefs);
3578 // We don't want max_fs and max_fr prefs impact SDP at this moment
3579 SetMaxFsFr(prefs, 0, 0);
3581 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV);
3583 ParsedSDP sdpWrapper(a1_->offer());
3585 sdpWrapper.ReplaceLine("a=rtpmap:120",
3586 "a=rtpmap:120 VP8/90000\r\na=fmtp:120 max-fs=300;max-fr=30\r\n");
3588 std::cout << "Modified SDP " << std::endl
3589 << indent(sdpWrapper.getSdp()) << std::endl;
3591 // Double confirm that SDP offer contains correct max-fs and max-fr
3592 CheckMaxFsFrSdp(sdpWrapper.getSdp(), 120, 300, 30);
3594 a1_->SetLocal(TestObserver::OFFER, sdpWrapper.getSdp());
3595 a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp());
3597 a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), OFFER_AV | ANSWER_AV);
3599 // SDP should not contain max-fs and max-fr here
3600 CheckMaxFsFrSdp(a2_->answer(), 120, 0, 0);
3602 a2_->SetLocal(TestObserver::ANSWER, a2_->answer());
3603 a1_->SetRemote(TestObserver::ANSWER, a2_->answer());
3605 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
3606 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
3608 // Checking callee's video sending configuration does respect max-fs and
3609 // max-fr in SDP offer.
3610 mozilla::RefPtr<mozilla::MediaPipeline> pipeline =
3611 a2_->GetMediaPipeline(1, 0, 1);
3612 ASSERT_TRUE(pipeline);
3613 mozilla::MediaSessionConduit *conduit = pipeline->Conduit();
3614 ASSERT_TRUE(conduit);
3615 ASSERT_EQ(conduit->type(), mozilla::MediaSessionConduit::VIDEO);
3616 mozilla::VideoSessionConduit *video_conduit =
3617 static_cast<mozilla::VideoSessionConduit*>(conduit);
3619 ASSERT_EQ(video_conduit->SendingMaxFs(), (unsigned short) 300);
3620 ASSERT_EQ(video_conduit->SendingMaxFr(), (unsigned short) 30);
3621 }
3623 // Test SDP answer has proper impact on caller's codec configuration
3624 TEST_F(SignalingTest, MaxFsFrCallerCodec)
3625 {
3626 EnsureInit();
3628 sipcc::MediaConstraints constraints;
3630 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
3631 ASSERT_TRUE(prefs);
3632 FsFrPrefClearer prefClearer(prefs);
3634 // We don't want max_fs and max_fr prefs impact SDP at this moment
3635 SetMaxFsFr(prefs, 0, 0);
3637 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV);
3638 a1_->SetLocal(TestObserver::OFFER, a1_->offer());
3639 a2_->SetRemote(TestObserver::OFFER, a1_->offer());
3641 a2_->CreateAnswer(constraints, a1_->offer(), OFFER_AV | ANSWER_AV);
3643 ParsedSDP sdpWrapper(a2_->answer());
3645 sdpWrapper.ReplaceLine("a=rtpmap:120",
3646 "a=rtpmap:120 VP8/90000\r\na=fmtp:120 max-fs=600;max-fr=60\r\n");
3648 std::cout << "Modified SDP " << std::endl
3649 << indent(sdpWrapper.getSdp()) << std::endl;
3651 // Double confirm that SDP answer contains correct max-fs and max-fr
3652 CheckMaxFsFrSdp(sdpWrapper.getSdp(), 120, 600, 60);
3654 a2_->SetLocal(TestObserver::ANSWER, sdpWrapper.getSdp());
3655 a1_->SetRemote(TestObserver::ANSWER, sdpWrapper.getSdp());
3657 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout);
3658 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout);
3660 // Checking caller's video sending configuration does respect max-fs and
3661 // max-fr in SDP answer.
3662 mozilla::RefPtr<mozilla::MediaPipeline> pipeline =
3663 a1_->GetMediaPipeline(1, 0, 1);
3664 ASSERT_TRUE(pipeline);
3665 mozilla::MediaSessionConduit *conduit = pipeline->Conduit();
3666 ASSERT_TRUE(conduit);
3667 ASSERT_EQ(conduit->type(), mozilla::MediaSessionConduit::VIDEO);
3668 mozilla::VideoSessionConduit *video_conduit =
3669 static_cast<mozilla::VideoSessionConduit*>(conduit);
3671 ASSERT_EQ(video_conduit->SendingMaxFs(), (unsigned short) 600);
3672 ASSERT_EQ(video_conduit->SendingMaxFr(), (unsigned short) 60);
3673 }
3675 } // End namespace test.
3677 bool is_color_terminal(const char *terminal) {
3678 if (!terminal) {
3679 return false;
3680 }
3681 const char *color_terms[] = {
3682 "xterm",
3683 "xterm-color",
3684 "xterm-256color",
3685 "screen",
3686 "linux",
3687 "cygwin",
3688 0
3689 };
3690 const char **p = color_terms;
3691 while (*p) {
3692 if (!strcmp(terminal, *p)) {
3693 return true;
3694 }
3695 p++;
3696 }
3697 return false;
3698 }
3700 static std::string get_environment(const char *name) {
3701 char *value = getenv(name);
3703 if (!value)
3704 return "";
3706 return value;
3707 }
3709 // This exists to send as an event to trigger shutdown.
3710 static void tests_complete() {
3711 gTestsComplete = true;
3712 }
3714 // The GTest thread runs this instead of the main thread so it can
3715 // do things like ASSERT_TRUE_WAIT which you could not do on the main thread.
3716 static int gtest_main(int argc, char **argv) {
3717 MOZ_ASSERT(!NS_IsMainThread());
3719 ::testing::InitGoogleTest(&argc, argv);
3721 for(int i=0; i<argc; i++) {
3722 if (!strcmp(argv[i],"-t")) {
3723 kDefaultTimeout = 20000;
3724 }
3725 }
3727 ::testing::AddGlobalTestEnvironment(new test::SignalingEnvironment);
3728 int result = RUN_ALL_TESTS();
3730 test_utils->sts_target()->Dispatch(
3731 WrapRunnableNM(&TestStunServer::ShutdownInstance), NS_DISPATCH_SYNC);
3733 // Set the global shutdown flag and tickle the main thread
3734 // The main thread did not go through Init() so calling Shutdown()
3735 // on it will not work.
3736 gMainThread->Dispatch(WrapRunnableNM(tests_complete), NS_DISPATCH_SYNC);
3738 return result;
3739 }
3742 int main(int argc, char **argv) {
3744 // This test can cause intermittent oranges on the builders
3745 CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_TESTS")
3747 if (isatty(STDOUT_FILENO) && is_color_terminal(getenv("TERM"))) {
3748 std::string ansiMagenta = "\x1b[35m";
3749 std::string ansiCyan = "\x1b[36m";
3750 std::string ansiColorOff = "\x1b[0m";
3751 callerName = ansiCyan + callerName + ansiColorOff;
3752 calleeName = ansiMagenta + calleeName + ansiColorOff;
3753 }
3755 std::string tmp = get_environment("STUN_SERVER_ADDRESS");
3756 if (tmp != "")
3757 g_stun_server_address = tmp;
3759 tmp = get_environment("STUN_SERVER_PORT");
3760 if (tmp != "")
3761 g_stun_server_port = atoi(tmp.c_str());
3763 test_utils = new MtransportTestUtils();
3764 NSS_NoDB_Init(nullptr);
3765 NSS_SetDomesticPolicy();
3767 ::testing::TestEventListeners& listeners =
3768 ::testing::UnitTest::GetInstance()->listeners();
3769 // Adds a listener to the end. Google Test takes the ownership.
3770 listeners.Append(new test::RingbufferDumper(test_utils));
3771 test_utils->sts_target()->Dispatch(
3772 WrapRunnableNM(&TestStunServer::GetInstance), NS_DISPATCH_SYNC);
3774 // Set the main thread global which is this thread.
3775 nsIThread *thread;
3776 NS_GetMainThread(&thread);
3777 gMainThread = thread;
3778 MOZ_ASSERT(NS_IsMainThread());
3780 // Now create the GTest thread and run all of the tests on it
3781 // When it is complete it will set gTestsComplete
3782 NS_NewNamedThread("gtest_thread", &thread);
3783 gGtestThread = thread;
3785 int result;
3786 gGtestThread->Dispatch(
3787 WrapRunnableNMRet(gtest_main, argc, argv, &result), NS_DISPATCH_NORMAL);
3789 // Here we handle the event queue for dispatches to the main thread
3790 // When the GTest thread is complete it will send one more dispatch
3791 // with gTestsComplete == true.
3792 while (!gTestsComplete && NS_ProcessNextEvent());
3794 gGtestThread->Shutdown();
3796 sipcc::PeerConnectionCtx::Destroy();
3797 delete test_utils;
3799 return result;
3800 }