|
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/. */ |
|
4 |
|
5 #include <iostream> |
|
6 #include <map> |
|
7 #include <algorithm> |
|
8 #include <string> |
|
9 #include <unistd.h> |
|
10 |
|
11 #include "base/basictypes.h" |
|
12 #include "logging.h" |
|
13 |
|
14 #define GTEST_HAS_RTTI 0 |
|
15 #include "gtest/gtest.h" |
|
16 #include "gtest_utils.h" |
|
17 |
|
18 #include "nspr.h" |
|
19 #include "nss.h" |
|
20 #include "ssl.h" |
|
21 #include "prthread.h" |
|
22 |
|
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" |
|
47 |
|
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; |
|
54 |
|
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 |
|
61 |
|
62 static int kDefaultTimeout = 7000; |
|
63 static bool fRtcpMux = true; |
|
64 |
|
65 static std::string callerName = "caller"; |
|
66 static std::string calleeName = "callee"; |
|
67 |
|
68 #define ARRAY_TO_STL(container, type, array) \ |
|
69 (container<type>((array), (array) + PR_ARRAY_SIZE(array))) |
|
70 |
|
71 #define ARRAY_TO_SET(type, array) ARRAY_TO_STL(std::set, type, array) |
|
72 |
|
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); |
|
77 |
|
78 namespace sipcc { |
|
79 |
|
80 // We can't use mozilla/dom/MediaConstraintsBinding.h here because it uses |
|
81 // nsString, so we pass constraints in using MediaConstraintsExternal instead |
|
82 |
|
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 } |
|
104 |
|
105 using namespace mozilla; |
|
106 using namespace mozilla::dom; |
|
107 |
|
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 } |
|
123 |
|
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"; |
|
148 |
|
149 static const std::string strSampleCandidate = |
|
150 "a=candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host\r\n"; |
|
151 |
|
152 static const std::string strSampleMid = ""; |
|
153 |
|
154 static const unsigned short nSamplelevel = 2; |
|
155 |
|
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"; |
|
175 |
|
176 |
|
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), |
|
186 |
|
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), |
|
194 |
|
195 SHOULD_INCLUDE_DATA = (1 << 16), |
|
196 DONT_CHECK_DATA = (1 << 17), |
|
197 |
|
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, |
|
202 |
|
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, |
|
207 |
|
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 }; |
|
213 |
|
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), |
|
223 |
|
224 OFFER_AV = OFFER_AUDIO | OFFER_VIDEO, |
|
225 ANSWER_AV = ANSWER_AUDIO | ANSWER_VIDEO |
|
226 }; |
|
227 |
|
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 }; |
|
236 |
|
237 |
|
238 class TestObserver : public AFakePCObserver |
|
239 { |
|
240 public: |
|
241 TestObserver(sipcc::PeerConnectionImpl *peerConnection, |
|
242 const std::string &aName) : |
|
243 AFakePCObserver(peerConnection, aName) {} |
|
244 |
|
245 size_t MatchingCandidates(const std::string& cand) { |
|
246 size_t count = 0; |
|
247 |
|
248 for (size_t i=0; i<candidates.size(); ++i) { |
|
249 if (candidates[i].find(cand) != std::string::npos) |
|
250 ++count; |
|
251 } |
|
252 |
|
253 return count; |
|
254 } |
|
255 |
|
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 }; |
|
277 |
|
278 NS_IMPL_ISUPPORTS(TestObserver, nsISupportsWeakReference) |
|
279 |
|
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 } |
|
289 |
|
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 } |
|
299 |
|
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 } |
|
309 |
|
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 } |
|
319 |
|
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 } |
|
328 |
|
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 } |
|
337 |
|
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 } |
|
347 |
|
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 } |
|
357 |
|
358 NS_IMETHODIMP |
|
359 TestObserver::NotifyConnection(ER&) |
|
360 { |
|
361 std::cout << name << ": NotifyConnection" << std::endl; |
|
362 return NS_OK; |
|
363 } |
|
364 |
|
365 NS_IMETHODIMP |
|
366 TestObserver::NotifyClosedConnection(ER&) |
|
367 { |
|
368 std::cout << name << ": NotifyClosedConnection" << std::endl; |
|
369 return NS_OK; |
|
370 } |
|
371 |
|
372 NS_IMETHODIMP |
|
373 TestObserver::NotifyDataChannel(nsIDOMDataChannel *channel, ER&) |
|
374 { |
|
375 std::cout << name << ": NotifyDataChannel" << std::endl; |
|
376 return NS_OK; |
|
377 } |
|
378 |
|
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; |
|
388 |
|
389 std::cout << name << ": "; |
|
390 |
|
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 } |
|
438 |
|
439 lastStateType = state_type; |
|
440 return NS_OK; |
|
441 } |
|
442 |
|
443 |
|
444 NS_IMETHODIMP |
|
445 TestObserver::OnAddStream(nsIDOMMediaStream *stream, ER&) |
|
446 { |
|
447 PR_ASSERT(stream); |
|
448 |
|
449 DOMMediaStream *ms = static_cast<DOMMediaStream *>(stream); |
|
450 |
|
451 std::cout << name << ": OnAddStream called hints=" << ms->GetHintContents() |
|
452 << " thread=" << PR_GetCurrentThread() << std::endl ; |
|
453 |
|
454 onAddStreamCalled = true; |
|
455 |
|
456 streams.push_back(ms); |
|
457 |
|
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()); |
|
461 |
|
462 test_utils->sts_target()->Dispatch( |
|
463 WrapRunnable(fs, &Fake_SourceMediaStream::Start), |
|
464 NS_DISPATCH_NORMAL); |
|
465 |
|
466 return NS_OK; |
|
467 } |
|
468 |
|
469 NS_IMETHODIMP |
|
470 TestObserver::OnRemoveStream(ER&) |
|
471 { |
|
472 state = stateSuccess; |
|
473 return NS_OK; |
|
474 } |
|
475 |
|
476 NS_IMETHODIMP |
|
477 TestObserver::OnAddTrack(ER&) |
|
478 { |
|
479 state = stateSuccess; |
|
480 return NS_OK; |
|
481 } |
|
482 |
|
483 NS_IMETHODIMP |
|
484 TestObserver::OnRemoveTrack(ER&) |
|
485 { |
|
486 state = stateSuccess; |
|
487 return NS_OK; |
|
488 } |
|
489 |
|
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 } |
|
500 |
|
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 } |
|
510 |
|
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 } |
|
520 |
|
521 class ParsedSDP { |
|
522 public: |
|
523 //Line number with the corresponding SDP line. |
|
524 typedef std::pair<int, std::string> SdpLine; |
|
525 |
|
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 } |
|
536 |
|
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; |
|
542 |
|
543 for (int i = 0; i < count; i++) { |
|
544 DeleteLine(objType); |
|
545 } |
|
546 } |
|
547 |
|
548 void DeleteLine(std::string objType) |
|
549 { |
|
550 ReplaceLine(objType, ""); |
|
551 } |
|
552 |
|
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 } |
|
572 |
|
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 } |
|
589 |
|
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 } |
|
610 |
|
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 } |
|
657 |
|
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) { |
|
664 |
|
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 } |
|
675 |
|
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 } |
|
682 |
|
683 return sdp; |
|
684 } |
|
685 |
|
686 |
|
687 |
|
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 }; |
|
695 |
|
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); |
|
700 |
|
701 pc = sipcc::PeerConnectionImpl::CreatePeerConnection(); |
|
702 EXPECT_TRUE(pc); |
|
703 } |
|
704 |
|
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); |
|
708 |
|
709 pc = sipcc::PeerConnectionImpl::CreatePeerConnection(); |
|
710 EXPECT_TRUE(pc); |
|
711 } |
|
712 |
|
713 |
|
714 ~SignalingAgent() { |
|
715 mozilla::SyncRunnable::DispatchToThread(gMainThread, |
|
716 WrapRunnable(this, &SignalingAgent::Close)); |
|
717 } |
|
718 |
|
719 void Init_m(nsCOMPtr<nsIThread> thread) |
|
720 { |
|
721 pObserver = new TestObserver(pc, name); |
|
722 ASSERT_TRUE(pObserver); |
|
723 |
|
724 ASSERT_EQ(pc->Initialize(*pObserver, nullptr, cfg_, thread), NS_OK); |
|
725 } |
|
726 |
|
727 void Init(nsCOMPtr<nsIThread> thread) |
|
728 { |
|
729 mozilla::SyncRunnable::DispatchToThread(thread, |
|
730 WrapRunnable(this, &SignalingAgent::Init_m, thread)); |
|
731 |
|
732 ASSERT_TRUE_WAIT(sipcc_state() == PCImplSipccState::Started, |
|
733 kDefaultTimeout); |
|
734 } |
|
735 |
|
736 void WaitForGather() { |
|
737 ASSERT_TRUE_WAIT(ice_gathering_state() == PCImplIceGatheringState::Complete, |
|
738 kDefaultTimeout); |
|
739 |
|
740 std::cout << name << ": Init Complete" << std::endl; |
|
741 } |
|
742 |
|
743 bool WaitForGatherAllowFail() { |
|
744 EXPECT_TRUE_WAIT( |
|
745 ice_gathering_state() == PCImplIceGatheringState::Complete || |
|
746 ice_connection_state() == PCImplIceConnectionState::Failed, |
|
747 kDefaultTimeout); |
|
748 |
|
749 if (ice_connection_state() == PCImplIceConnectionState::Failed) { |
|
750 std::cout << name << ": Init Failed" << std::endl; |
|
751 return false; |
|
752 } |
|
753 |
|
754 std::cout << name << "Init Complete" << std::endl; |
|
755 return true; |
|
756 } |
|
757 |
|
758 PCImplSipccState sipcc_state() |
|
759 { |
|
760 return pc->SipccState(); |
|
761 } |
|
762 |
|
763 PCImplIceConnectionState ice_connection_state() |
|
764 { |
|
765 return pc->IceConnectionState(); |
|
766 } |
|
767 |
|
768 PCImplIceGatheringState ice_gathering_state() |
|
769 { |
|
770 return pc->IceGatheringState(); |
|
771 } |
|
772 |
|
773 PCImplSignalingState signaling_state() |
|
774 { |
|
775 return pc->SignalingState(); |
|
776 } |
|
777 |
|
778 void Close() |
|
779 { |
|
780 if (pc) { |
|
781 std::cout << name << ": Close" << std::endl; |
|
782 |
|
783 pc->Close(); |
|
784 pc = nullptr; |
|
785 } |
|
786 |
|
787 // Shutdown is synchronous evidently. |
|
788 // ASSERT_TRUE(pObserver->WaitForObserverCall()); |
|
789 // ASSERT_EQ(pc->sipcc_state(), sipcc::PeerConnectionInterface::kIdle); |
|
790 } |
|
791 |
|
792 bool OfferContains(const std::string& str) { |
|
793 std::string o(offer()); |
|
794 |
|
795 return o.find(str) != std::string::npos; |
|
796 } |
|
797 |
|
798 bool AnswerContains(const std::string& str) { |
|
799 std::string o(answer()); |
|
800 |
|
801 return o.find(str) != std::string::npos; |
|
802 } |
|
803 |
|
804 size_t MatchingCandidates(const std::string& cand) { |
|
805 return pObserver->MatchingCandidates(cand); |
|
806 } |
|
807 |
|
808 char* offer() const { return offer_; } |
|
809 char* answer() const { return answer_; } |
|
810 |
|
811 std::string getLocalDescription() const { |
|
812 char *sdp = nullptr; |
|
813 pc->GetLocalDescription(&sdp); |
|
814 if (!sdp) { |
|
815 return ""; |
|
816 } |
|
817 return sdp; |
|
818 } |
|
819 |
|
820 std::string getRemoteDescription() const { |
|
821 char *sdp = 0; |
|
822 pc->GetRemoteDescription(&sdp); |
|
823 if (!sdp) { |
|
824 return ""; |
|
825 } |
|
826 return sdp; |
|
827 } |
|
828 |
|
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 ) { |
|
836 |
|
837 sipcc::MediaConstraints noConstraints; |
|
838 if (!constraints) { |
|
839 constraints = &noConstraints; |
|
840 } |
|
841 |
|
842 nsRefPtr<DOMMediaStream> domMediaStream; |
|
843 if (stream) { |
|
844 domMediaStream = new DOMMediaStream(stream); |
|
845 } else { |
|
846 domMediaStream = new DOMMediaStream(); |
|
847 } |
|
848 |
|
849 domMediaStream->SetHintContents(hint); |
|
850 ASSERT_EQ(pc->AddStream(*domMediaStream, *constraints), NS_OK); |
|
851 domMediaStream_ = domMediaStream; |
|
852 } |
|
853 |
|
854 |
|
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 } |
|
861 |
|
862 void CreateOffer(sipcc::MediaConstraints& constraints, |
|
863 uint32_t offerFlags, uint32_t sdpCheck, |
|
864 PCImplSignalingState endState = |
|
865 PCImplSignalingState::SignalingStable) { |
|
866 |
|
867 // Create a media stream as if it came from GUM |
|
868 Fake_AudioStreamSource *audio_stream = |
|
869 new Fake_AudioStreamSource(); |
|
870 |
|
871 nsresult ret; |
|
872 mozilla::SyncRunnable::DispatchToThread( |
|
873 test_utils->sts_target(), |
|
874 WrapRunnableRet(audio_stream, &Fake_MediaStream::Start, &ret)); |
|
875 |
|
876 ASSERT_TRUE(NS_SUCCEEDED(ret)); |
|
877 |
|
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); |
|
886 |
|
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 } |
|
897 |
|
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) { |
|
905 |
|
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); |
|
914 |
|
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); |
|
924 |
|
925 answer_ = pObserver->lastString; |
|
926 } |
|
927 |
|
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) { |
|
935 |
|
936 domMediaStream_->SetHintContents(hints); |
|
937 |
|
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); |
|
943 |
|
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 } |
|
953 |
|
954 void SetRemote(TestObserver::Action action, std::string remote, |
|
955 bool ignoreError = false, |
|
956 PCImplSignalingState endState = |
|
957 PCImplSignalingState::SignalingInvalid) { |
|
958 |
|
959 if (endState == PCImplSignalingState::SignalingInvalid) { |
|
960 endState = (action == TestObserver::OFFER ? |
|
961 PCImplSignalingState::SignalingHaveRemoteOffer : |
|
962 PCImplSignalingState::SignalingStable); |
|
963 } |
|
964 |
|
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 } |
|
974 |
|
975 void SetLocal(TestObserver::Action action, std::string local, |
|
976 bool ignoreError = false, |
|
977 PCImplSignalingState endState = |
|
978 PCImplSignalingState::SignalingInvalid) { |
|
979 |
|
980 if (endState == PCImplSignalingState::SignalingInvalid) { |
|
981 endState = (action == TestObserver::OFFER ? |
|
982 PCImplSignalingState::SignalingHaveLocalOffer : |
|
983 PCImplSignalingState::SignalingStable); |
|
984 } |
|
985 |
|
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 } |
|
995 |
|
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 } |
|
1012 |
|
1013 |
|
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; |
|
1023 |
|
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 } |
|
1031 |
|
1032 |
|
1033 bool IceCompleted() { |
|
1034 return pc->IceConnectionState() == PCImplIceConnectionState::Connected; |
|
1035 } |
|
1036 |
|
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 ); |
|
1048 |
|
1049 // Verify that adding ICE candidates does not change the signaling state |
|
1050 ASSERT_EQ(signaling_state(), endState); |
|
1051 } |
|
1052 |
|
1053 int GetPacketsReceived(int stream) { |
|
1054 std::vector<DOMMediaStream *> streams = pObserver->GetStreams(); |
|
1055 |
|
1056 if ((int) streams.size() <= stream) { |
|
1057 return 0; |
|
1058 } |
|
1059 |
|
1060 return streams[stream]->GetStream()->AsSourceStream()->GetSegmentsAdded(); |
|
1061 } |
|
1062 |
|
1063 int GetPacketsSent(int stream) { |
|
1064 return static_cast<Fake_MediaStreamBase *>( |
|
1065 domMediaStream_->GetStream())->GetSegmentsAdded(); |
|
1066 } |
|
1067 |
|
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 } |
|
1074 |
|
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 } |
|
1084 |
|
1085 mozilla::RefPtr<mozilla::MediaPipeline> GetMediaPipeline( |
|
1086 bool local, int stream, int track) { |
|
1087 sipcc::SourceStreamInfo *streamInfo; |
|
1088 |
|
1089 if (local) { |
|
1090 streamInfo = pc->media()->GetLocalStream(stream); |
|
1091 } else { |
|
1092 streamInfo = pc->media()->GetRemoteStream(stream); |
|
1093 } |
|
1094 |
|
1095 if (!streamInfo) { |
|
1096 return nullptr; |
|
1097 } |
|
1098 |
|
1099 const auto &pipelines = streamInfo->GetPipelines(); |
|
1100 auto it = pipelines.find(track); |
|
1101 return (it == pipelines.end())? nullptr : it->second; |
|
1102 } |
|
1103 |
|
1104 void CheckMediaPipeline(int stream, int track, uint32_t flags, |
|
1105 VideoSessionConduit::FrameRequestType frameRequestMethod = |
|
1106 VideoSessionConduit::FrameRequestNone) { |
|
1107 |
|
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; |
|
1117 |
|
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 } |
|
1138 |
|
1139 |
|
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 } |
|
1152 |
|
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; |
|
1161 |
|
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); |
|
1169 |
|
1170 std::cout << name << ": SDPSanityCheck flags for " |
|
1171 << (offer ? "offer" : "answer") |
|
1172 << " = " << std::hex << std::showbase |
|
1173 << flags << std::dec |
|
1174 |
|
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":"") |
|
1181 |
|
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":"") |
|
1188 |
|
1189 << ((flags & SHOULD_INCLUDE_DATA)?" SHOULD_INCLUDE_DATA":"") |
|
1190 << ((flags & DONT_CHECK_DATA)?" DONT_CHECK_DATA":"") |
|
1191 << std::endl; |
|
1192 |
|
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 } |
|
1240 |
|
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 } |
|
1275 |
|
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 }; |
|
1283 |
|
1284 class SignalingEnvironment : public ::testing::Environment { |
|
1285 public: |
|
1286 void TearDown() { |
|
1287 // Signaling is shut down in XPCOM shutdown |
|
1288 } |
|
1289 }; |
|
1290 |
|
1291 class SignalingAgentTest : public ::testing::Test { |
|
1292 public: |
|
1293 static void SetUpTestCase() { |
|
1294 } |
|
1295 |
|
1296 void TearDown() { |
|
1297 // Delete all the agents. |
|
1298 for (size_t i=0; i < agents_.size(); i++) { |
|
1299 delete agents_[i]; |
|
1300 } |
|
1301 } |
|
1302 |
|
1303 bool CreateAgent() { |
|
1304 return CreateAgent(g_stun_server_address, g_stun_server_port); |
|
1305 } |
|
1306 |
|
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)); |
|
1311 |
|
1312 agent->Init(gMainThread); |
|
1313 |
|
1314 if (wait_for_gather) { |
|
1315 if (!agent->WaitForGatherAllowFail()) |
|
1316 return false; |
|
1317 } |
|
1318 |
|
1319 agents_.push_back(agent.forget()); |
|
1320 |
|
1321 return true; |
|
1322 } |
|
1323 |
|
1324 void CreateAgentNoInit() { |
|
1325 ScopedDeletePtr<SignalingAgent> agent(new SignalingAgent("agent")); |
|
1326 agents_.push_back(agent.forget()); |
|
1327 } |
|
1328 |
|
1329 SignalingAgent *agent(size_t i) { |
|
1330 return agents_[i]; |
|
1331 } |
|
1332 |
|
1333 private: |
|
1334 std::vector<SignalingAgent *> agents_; |
|
1335 }; |
|
1336 |
|
1337 |
|
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) {} |
|
1347 |
|
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) {} |
|
1354 |
|
1355 static void SetUpTestCase() { |
|
1356 } |
|
1357 |
|
1358 void EnsureInit() { |
|
1359 |
|
1360 if (init_) |
|
1361 return; |
|
1362 |
|
1363 a1_ = new SignalingAgent(callerName, stun_addr_, stun_port_); |
|
1364 a2_ = new SignalingAgent(calleeName, stun_addr_, stun_port_); |
|
1365 |
|
1366 a1_->Init(gMainThread); |
|
1367 a2_->Init(gMainThread); |
|
1368 |
|
1369 if (wait_for_gather_) { |
|
1370 WaitForGather(); |
|
1371 } |
|
1372 } |
|
1373 |
|
1374 void WaitForGather() { |
|
1375 a1_->WaitForGather(); |
|
1376 a2_->WaitForGather(); |
|
1377 } |
|
1378 |
|
1379 static void TearDownTestCase() { |
|
1380 } |
|
1381 |
|
1382 void CreateOffer(sipcc::MediaConstraints& constraints, |
|
1383 uint32_t offerFlags, uint32_t sdpCheck) { |
|
1384 EnsureInit(); |
|
1385 a1_->CreateOffer(constraints, offerFlags, sdpCheck); |
|
1386 } |
|
1387 |
|
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 } |
|
1393 |
|
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()); |
|
1408 |
|
1409 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
|
1410 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
|
1411 } |
|
1412 } |
|
1413 |
|
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 } |
|
1433 |
|
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 } |
|
1453 |
|
1454 |
|
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 } |
|
1474 |
|
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 } |
|
1484 |
|
1485 void CreateOfferAudioOnly(sipcc::MediaConstraints& constraints, |
|
1486 uint32_t sdpCheck) { |
|
1487 EnsureInit(); |
|
1488 a1_->CreateOffer(constraints, OFFER_AUDIO, sdpCheck); |
|
1489 } |
|
1490 |
|
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 } |
|
1498 |
|
1499 void AddIceCandidateEarly(const char * candidate, const char * mid, |
|
1500 unsigned short level) { |
|
1501 EnsureInit(); |
|
1502 a1_->AddIceCandidate(candidate, mid, level, false); |
|
1503 } |
|
1504 |
|
1505 void CheckRtcpFbSdp(const std::string &sdp, |
|
1506 const std::set<std::string>& expected) { |
|
1507 |
|
1508 std::set<std::string>::const_iterator it; |
|
1509 |
|
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 } |
|
1517 |
|
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 } |
|
1529 |
|
1530 void TestRtcpFb(const std::set<std::string>& feedback, |
|
1531 uint32_t rtcpFbFlags, |
|
1532 VideoSessionConduit::FrameRequestType frameRequestMethod) { |
|
1533 EnsureInit(); |
|
1534 sipcc::MediaConstraints constraints; |
|
1535 |
|
1536 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); |
|
1537 a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
|
1538 |
|
1539 ParsedSDP sdpWrapper(a1_->offer()); |
|
1540 |
|
1541 // Strip out any existing rtcp-fb lines |
|
1542 sdpWrapper.DeleteAllLines("a=rtcp-fb:120"); |
|
1543 |
|
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 } |
|
1551 |
|
1552 std::cout << "Modified SDP " << std::endl |
|
1553 << indent(sdpWrapper.getSdp()) << std::endl; |
|
1554 |
|
1555 // Double-check that the offered SDP matches what we expect |
|
1556 CheckRtcpFbSdp(sdpWrapper.getSdp(), feedback); |
|
1557 |
|
1558 a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp()); |
|
1559 a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), OFFER_AV | ANSWER_AV); |
|
1560 |
|
1561 CheckRtcpFbSdp(a2_->answer(), feedback); |
|
1562 |
|
1563 a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); |
|
1564 a1_->SetRemote(TestObserver::ANSWER, a2_->answer()); |
|
1565 |
|
1566 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
|
1567 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
|
1568 |
|
1569 a1_->CloseSendStreams(); |
|
1570 a1_->CloseReceiveStreams(); |
|
1571 a2_->CloseSendStreams(); |
|
1572 a2_->CloseReceiveStreams(); |
|
1573 |
|
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); |
|
1577 |
|
1578 // Check callee video settings for remote pipeline |
|
1579 a2_->CheckMediaPipeline(0, 2, (fRtcpMux ? PIPELINE_RTCP_MUX : 0) | |
|
1580 PIPELINE_VIDEO | rtcpFbFlags, frameRequestMethod); |
|
1581 } |
|
1582 |
|
1583 void SetTestStunServer() { |
|
1584 stun_addr_ = TestStunServer::GetInstance()->addr(); |
|
1585 stun_port_ = TestStunServer::GetInstance()->port(); |
|
1586 |
|
1587 TestStunServer::GetInstance()->SetActive(false); |
|
1588 TestStunServer::GetInstance()->SetResponseAddr( |
|
1589 kBogusSrflxAddress, kBogusSrflxPort); |
|
1590 } |
|
1591 |
|
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()); |
|
1601 |
|
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 } |
|
1608 |
|
1609 // At most one instance allowed for each format |
|
1610 ASSERT_EQ(lines.size(), 1U); |
|
1611 |
|
1612 std::string line = lines.front(); |
|
1613 |
|
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 } |
|
1635 |
|
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 }; |
|
1644 |
|
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 } |
|
1651 |
|
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); |
|
1661 |
|
1662 gMainThread->Dispatch( |
|
1663 WrapRunnableNM(SetIntPrefOnMainThread, |
|
1664 prefs, |
|
1665 "media.navigator.video.max_fr", |
|
1666 max_fr), |
|
1667 NS_DISPATCH_SYNC); |
|
1668 } |
|
1669 |
|
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 } |
|
1685 |
|
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 }; |
|
1694 |
|
1695 TEST_F(SignalingTest, JustInit) |
|
1696 { |
|
1697 } |
|
1698 |
|
1699 TEST_F(SignalingTest, CreateSetOffer) |
|
1700 { |
|
1701 sipcc::MediaConstraints constraints; |
|
1702 CreateSetOffer(constraints, SHOULD_SENDRECV_AV); |
|
1703 } |
|
1704 |
|
1705 TEST_F(SignalingTest, CreateOfferAudioVideoConstraintUndefined) |
|
1706 { |
|
1707 sipcc::MediaConstraints constraints; |
|
1708 CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); |
|
1709 } |
|
1710 |
|
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 } |
|
1719 |
|
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 } |
|
1728 |
|
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 } |
|
1737 |
|
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 } |
|
1746 |
|
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 } |
|
1755 |
|
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 } |
|
1764 |
|
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 } |
|
1774 |
|
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 } |
|
1784 |
|
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 } |
|
1794 |
|
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 } |
|
1801 |
|
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 } |
|
1814 |
|
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 } |
|
1827 |
|
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 } |
|
1840 |
|
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 } |
|
1853 |
|
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 } |
|
1866 |
|
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 } |
|
1879 |
|
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 } |
|
1892 |
|
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 } |
|
1905 |
|
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 } |
|
1918 |
|
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 } |
|
1931 |
|
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 } |
|
1943 |
|
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 } |
|
1956 |
|
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 } |
|
1968 |
|
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 } |
|
1981 |
|
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 } |
|
1993 |
|
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 } |
|
2001 |
|
2002 TEST_F(SignalingTest, AddIceCandidateEarly) |
|
2003 { |
|
2004 sipcc::MediaConstraints constraints; |
|
2005 AddIceCandidateEarly(strSampleCandidate.c_str(), |
|
2006 strSampleMid.c_str(), nSamplelevel); |
|
2007 } |
|
2008 |
|
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); |
|
2016 |
|
2017 sipcc::MediaConstraints bconstraints; |
|
2018 bconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
|
2019 bconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); |
|
2020 |
|
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 } |
|
2027 |
|
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 } |
|
2038 |
|
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 } |
|
2049 |
|
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 } |
|
2060 |
|
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); |
|
2066 |
|
2067 // Wait for some data to get written |
|
2068 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
2069 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
2070 |
|
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); |
|
2078 |
|
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); |
|
2085 |
|
2086 // The first Remote pipeline gets stored at 1 |
|
2087 a2_->CheckMediaPipeline(0, 1, (fRtcpMux ? PIPELINE_RTCP_MUX : 0)); |
|
2088 } |
|
2089 |
|
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); |
|
2095 |
|
2096 // Wait for some data to get written |
|
2097 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
2098 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
2099 |
|
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 } |
|
2108 |
|
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); |
|
2117 |
|
2118 // Wait for some data to get written |
|
2119 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
2120 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
2121 |
|
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 } |
|
2130 |
|
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); |
|
2136 |
|
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); |
|
2141 |
|
2142 a1_->CloseSendStreams(); |
|
2143 a2_->CloseReceiveStreams(); |
|
2144 |
|
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 } |
|
2155 |
|
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 } |
|
2164 |
|
2165 TEST_F(SignalingTest, FullCallTrickle) |
|
2166 { |
|
2167 sipcc::MediaConstraints constraints; |
|
2168 OfferAnswerTrickle(constraints, constraints, |
|
2169 SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); |
|
2170 |
|
2171 std::cerr << "ICE handshake completed" << std::endl; |
|
2172 |
|
2173 // Wait for some data to get written |
|
2174 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
2175 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
2176 |
|
2177 a1_->CloseSendStreams(); |
|
2178 a2_->CloseReceiveStreams(); |
|
2179 ASSERT_GE(a1_->GetPacketsSent(0), 40); |
|
2180 ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
|
2181 } |
|
2182 |
|
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); |
|
2189 |
|
2190 std::cerr << "ICE handshake completed" << std::endl; |
|
2191 |
|
2192 // Wait for some data to get written |
|
2193 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
2194 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
2195 |
|
2196 a1_->CloseSendStreams(); |
|
2197 a2_->CloseReceiveStreams(); |
|
2198 ASSERT_GE(a1_->GetPacketsSent(0), 40); |
|
2199 ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
|
2200 } |
|
2201 |
|
2202 // This test comes from Bug 810220 |
|
2203 TEST_F(SignalingTest, AudioOnlyG711Call) |
|
2204 { |
|
2205 EnsureInit(); |
|
2206 |
|
2207 sipcc::MediaConstraints constraints; |
|
2208 const std::string& offer(strG711SdpOffer); |
|
2209 |
|
2210 std::cout << "Setting offer to:" << std::endl << indent(offer) << std::endl; |
|
2211 a2_->SetRemote(TestObserver::OFFER, offer); |
|
2212 |
|
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); |
|
2216 |
|
2217 std::string answer = a2_->answer(); |
|
2218 |
|
2219 // They didn't offer opus, so our answer shouldn't include it. |
|
2220 ASSERT_EQ(answer.find(" opus/"), std::string::npos); |
|
2221 |
|
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); |
|
2225 |
|
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); |
|
2229 |
|
2230 // Double-check the directionality |
|
2231 ASSERT_NE(answer.find("\r\na=sendrecv"), std::string::npos); |
|
2232 |
|
2233 } |
|
2234 |
|
2235 // This test comes from Bug814038 |
|
2236 TEST_F(SignalingTest, ChromeOfferAnswer) |
|
2237 { |
|
2238 EnsureInit(); |
|
2239 |
|
2240 sipcc::MediaConstraints constraints; |
|
2241 |
|
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" |
|
2249 |
|
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" |
|
2282 |
|
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"; |
|
2305 |
|
2306 |
|
2307 std::cout << "Setting offer to:" << std::endl << indent(offer) << std::endl; |
|
2308 a2_->SetRemote(TestObserver::OFFER, offer); |
|
2309 |
|
2310 std::cout << "Creating answer:" << std::endl; |
|
2311 a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO); |
|
2312 |
|
2313 std::string answer = a2_->answer(); |
|
2314 } |
|
2315 |
|
2316 |
|
2317 TEST_F(SignalingTest, FullChromeHandshake) |
|
2318 { |
|
2319 EnsureInit(); |
|
2320 |
|
2321 sipcc::MediaConstraints constraints; |
|
2322 constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
|
2323 constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
|
2324 |
|
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"; |
|
2378 |
|
2379 std::cout << "Setting offer to:" << std::endl << indent(offer) << std::endl; |
|
2380 a2_->SetRemote(TestObserver::OFFER, offer); |
|
2381 |
|
2382 std::cout << "Creating answer:" << std::endl; |
|
2383 a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO); |
|
2384 |
|
2385 std::cout << "Setting answer" << std::endl; |
|
2386 a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); |
|
2387 |
|
2388 std::string answer = a2_->answer(); |
|
2389 ASSERT_NE(answer.find("111 opus/"), std::string::npos); |
|
2390 } |
|
2391 |
|
2392 // Disabled pending resolution of bug 818640. |
|
2393 TEST_F(SignalingTest, DISABLED_OfferAllDynamicTypes) |
|
2394 { |
|
2395 EnsureInit(); |
|
2396 |
|
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"; |
|
2421 |
|
2422 /* |
|
2423 std::cout << "Setting offer to:" << std::endl |
|
2424 << indent(offer) << std::endl; |
|
2425 */ |
|
2426 a2_->SetRemote(TestObserver::OFFER, offer); |
|
2427 |
|
2428 //std::cout << "Creating answer:" << std::endl; |
|
2429 a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO); |
|
2430 |
|
2431 std::string answer = a2_->answer(); |
|
2432 |
|
2433 ASSERT_NE(answer.find(ss.str() + " opus/"), std::string::npos); |
|
2434 } |
|
2435 |
|
2436 } |
|
2437 |
|
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); |
|
2443 |
|
2444 std::cout << "Caller's Local Description: " << std::endl |
|
2445 << indent(a1_->getLocalDescription()) << std::endl << std::endl; |
|
2446 |
|
2447 std::cout << "Caller's Remote Description: " << std::endl |
|
2448 << indent(a1_->getRemoteDescription()) << std::endl << std::endl; |
|
2449 |
|
2450 std::cout << "Callee's Local Description: " << std::endl |
|
2451 << indent(a2_->getLocalDescription()) << std::endl << std::endl; |
|
2452 |
|
2453 std::cout << "Callee's Remote Description: " << std::endl |
|
2454 << indent(a2_->getRemoteDescription()) << std::endl << std::endl; |
|
2455 |
|
2456 ASSERT_EQ(a1_->getLocalDescription(),a2_->getRemoteDescription()); |
|
2457 ASSERT_EQ(a2_->getLocalDescription(),a1_->getRemoteDescription()); |
|
2458 } |
|
2459 |
|
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; |
|
2466 |
|
2467 a1_->CloseSendStreams(); |
|
2468 a2_->CloseReceiveStreams(); |
|
2469 |
|
2470 std::cout << "Caller's Local Description: " << std::endl |
|
2471 << indent(a1_->getLocalDescription()) << std::endl << std::endl; |
|
2472 |
|
2473 std::cout << "Caller's Remote Description: " << std::endl |
|
2474 << indent(a1_->getRemoteDescription()) << std::endl << std::endl; |
|
2475 |
|
2476 std::cout << "Callee's Local Description: " << std::endl |
|
2477 << indent(a2_->getLocalDescription()) << std::endl << std::endl; |
|
2478 |
|
2479 std::cout << "Callee's Remote Description: " << std::endl |
|
2480 << indent(a2_->getRemoteDescription()) << std::endl << std::endl; |
|
2481 |
|
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 } |
|
2501 |
|
2502 TEST_F(SignalingTest, ipAddrAnyOffer) |
|
2503 { |
|
2504 EnsureInit(); |
|
2505 |
|
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"; |
|
2521 |
|
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 } |
|
2529 |
|
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 } |
|
2550 |
|
2551 TEST_F(SignalingTest, BigOValues) |
|
2552 { |
|
2553 EnsureInit(); |
|
2554 |
|
2555 std::string offer; |
|
2556 |
|
2557 CreateSDPForBigOTests(offer, "12345678901234567"); |
|
2558 |
|
2559 a2_->SetRemote(TestObserver::OFFER, offer); |
|
2560 ASSERT_EQ(a2_->pObserver->state, TestObserver::stateSuccess); |
|
2561 } |
|
2562 |
|
2563 TEST_F(SignalingTest, BigOValuesExtraChars) |
|
2564 { |
|
2565 EnsureInit(); |
|
2566 |
|
2567 std::string offer; |
|
2568 |
|
2569 CreateSDPForBigOTests(offer, "12345678901234567FOOBAR"); |
|
2570 |
|
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 } |
|
2577 |
|
2578 TEST_F(SignalingTest, BigOValuesTooBig) |
|
2579 { |
|
2580 EnsureInit(); |
|
2581 |
|
2582 std::string offer; |
|
2583 |
|
2584 CreateSDPForBigOTests(offer, "18446744073709551615"); |
|
2585 |
|
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 } |
|
2592 |
|
2593 TEST_F(SignalingTest, SetLocalAnswerInStable) |
|
2594 { |
|
2595 EnsureInit(); |
|
2596 |
|
2597 sipcc::MediaConstraints constraints; |
|
2598 CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
|
2599 |
|
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 } |
|
2607 |
|
2608 TEST_F(SignalingTest, SetRemoteAnswerInStable) { |
|
2609 EnsureInit(); |
|
2610 |
|
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 } |
|
2618 |
|
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); |
|
2625 |
|
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 } |
|
2633 |
|
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); |
|
2640 |
|
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 } |
|
2648 |
|
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); |
|
2655 |
|
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 } |
|
2663 |
|
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); |
|
2670 |
|
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 } |
|
2678 |
|
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 } |
|
2690 |
|
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 } |
|
2702 |
|
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 } |
|
2714 |
|
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 } |
|
2721 |
|
2722 TEST_F(SignalingAgentTest, CreateOfferTrickleTestServer) { |
|
2723 TestStunServer::GetInstance()->SetActive(false); |
|
2724 TestStunServer::GetInstance()->SetResponseAddr( |
|
2725 kBogusSrflxAddress, kBogusSrflxPort); |
|
2726 |
|
2727 CreateAgent( |
|
2728 TestStunServer::GetInstance()->addr(), |
|
2729 TestStunServer::GetInstance()->port(), |
|
2730 false); |
|
2731 |
|
2732 sipcc::MediaConstraints constraints; |
|
2733 agent(0)->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
|
2734 |
|
2735 // Verify that the bogus addr is not there. |
|
2736 ASSERT_FALSE(agent(0)->OfferContains(kBogusSrflxAddress)); |
|
2737 |
|
2738 // Now enable the STUN server. |
|
2739 TestStunServer::GetInstance()->SetActive(true); |
|
2740 agent(0)->WaitForGather(); |
|
2741 |
|
2742 // There shouldn't be any candidates until SetLocal. |
|
2743 ASSERT_EQ(0U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); |
|
2744 |
|
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 } |
|
2750 |
|
2751 TEST_F(SignalingAgentTest, CreateOfferSetLocalTrickleTestServer) { |
|
2752 TestStunServer::GetInstance()->SetActive(false); |
|
2753 TestStunServer::GetInstance()->SetResponseAddr( |
|
2754 kBogusSrflxAddress, kBogusSrflxPort); |
|
2755 |
|
2756 CreateAgent( |
|
2757 TestStunServer::GetInstance()->addr(), |
|
2758 TestStunServer::GetInstance()->port(), |
|
2759 false); |
|
2760 |
|
2761 sipcc::MediaConstraints constraints; |
|
2762 agent(0)->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
|
2763 |
|
2764 // Verify that the bogus addr is not there. |
|
2765 ASSERT_FALSE(agent(0)->OfferContains(kBogusSrflxAddress)); |
|
2766 |
|
2767 // Now enable the STUN server. |
|
2768 TestStunServer::GetInstance()->SetActive(true); |
|
2769 agent(0)->WaitForGather(); |
|
2770 |
|
2771 // There shouldn't be any candidates until SetLocal. |
|
2772 ASSERT_EQ(0U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); |
|
2773 |
|
2774 agent(0)->SetLocal(TestObserver::OFFER, agent(0)->offer()); |
|
2775 PR_Sleep(1000); // Give time for the message queues. |
|
2776 |
|
2777 // Verify that we got our candidates. |
|
2778 ASSERT_LE(2U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); |
|
2779 |
|
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 } |
|
2785 |
|
2786 |
|
2787 TEST_F(SignalingAgentTest, CreateAnswerSetLocalTrickleTestServer) { |
|
2788 TestStunServer::GetInstance()->SetActive(false); |
|
2789 TestStunServer::GetInstance()->SetResponseAddr( |
|
2790 kBogusSrflxAddress, kBogusSrflxPort); |
|
2791 |
|
2792 CreateAgent( |
|
2793 TestStunServer::GetInstance()->addr(), |
|
2794 TestStunServer::GetInstance()->port(), |
|
2795 false); |
|
2796 |
|
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); |
|
2802 |
|
2803 sipcc::MediaConstraints constraints; |
|
2804 agent(0)->CreateAnswer(constraints, offer, ANSWER_AUDIO, DONT_CHECK_AUDIO); |
|
2805 |
|
2806 // Verify that the bogus addr is not there. |
|
2807 ASSERT_FALSE(agent(0)->AnswerContains(kBogusSrflxAddress)); |
|
2808 |
|
2809 // Now enable the STUN server. |
|
2810 TestStunServer::GetInstance()->SetActive(true); |
|
2811 agent(0)->WaitForGather(); |
|
2812 |
|
2813 // There shouldn't be any candidates until SetLocal. |
|
2814 ASSERT_EQ(0U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); |
|
2815 |
|
2816 agent(0)->SetLocal(TestObserver::ANSWER, agent(0)->answer()); |
|
2817 PR_Sleep(1000); // Give time for the message queues. |
|
2818 |
|
2819 // Verify that we got our candidates. |
|
2820 ASSERT_LE(2U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); |
|
2821 |
|
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 } |
|
2827 |
|
2828 |
|
2829 |
|
2830 TEST_F(SignalingAgentTest, CreateUntilFailThenWait) { |
|
2831 int i; |
|
2832 |
|
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 } |
|
2841 |
|
2842 // Test for bug 856433. |
|
2843 TEST_F(SignalingAgentTest, CreateNoInit) { |
|
2844 CreateAgentNoInit(); |
|
2845 } |
|
2846 |
|
2847 |
|
2848 /* |
|
2849 * Test for Bug 843595 |
|
2850 */ |
|
2851 TEST_F(SignalingTest, missingUfrag) |
|
2852 { |
|
2853 EnsureInit(); |
|
2854 |
|
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"; |
|
2894 |
|
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 } |
|
2904 |
|
2905 TEST_F(SignalingTest, AudioOnlyCalleeNoRtcpMux) |
|
2906 { |
|
2907 EnsureInit(); |
|
2908 |
|
2909 sipcc::MediaConstraints constraints; |
|
2910 |
|
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); |
|
2922 |
|
2923 // Answer should not have a=rtcp-mux |
|
2924 ASSERT_EQ(a2_->getLocalDescription().find("\r\na=rtcp-mux"), |
|
2925 std::string::npos); |
|
2926 |
|
2927 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
|
2928 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
|
2929 |
|
2930 // Wait for some data to get written |
|
2931 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
2932 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
2933 |
|
2934 a1_->CloseSendStreams(); |
|
2935 a2_->CloseReceiveStreams(); |
|
2936 |
|
2937 ASSERT_GE(a1_->GetPacketsSent(0), 40); |
|
2938 ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
|
2939 |
|
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); |
|
2944 |
|
2945 // The first Remote pipeline gets stored at 1 |
|
2946 a2_->CheckMediaPipeline(0, 1, 0); |
|
2947 } |
|
2948 |
|
2949 TEST_F(SignalingTest, FullCallAudioNoMuxVideoMux) |
|
2950 { |
|
2951 EnsureInit(); |
|
2952 |
|
2953 sipcc::MediaConstraints constraints; |
|
2954 |
|
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); |
|
2965 |
|
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); |
|
2973 |
|
2974 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
|
2975 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
|
2976 |
|
2977 // Wait for some data to get written |
|
2978 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
2979 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
2980 |
|
2981 a1_->CloseSendStreams(); |
|
2982 a2_->CloseReceiveStreams(); |
|
2983 |
|
2984 ASSERT_GE(a1_->GetPacketsSent(0), 40); |
|
2985 ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
|
2986 |
|
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); |
|
2991 |
|
2992 // Now check video mux. |
|
2993 a1_->CheckMediaPipeline(0, 1, |
|
2994 PIPELINE_LOCAL | (fRtcpMux ? PIPELINE_RTCP_MUX : 0) | PIPELINE_SEND | |
|
2995 PIPELINE_VIDEO); |
|
2996 |
|
2997 // The first Remote pipeline gets stored at 1 |
|
2998 a2_->CheckMediaPipeline(0, 1, 0); |
|
2999 |
|
3000 // Now check video mux. |
|
3001 a2_->CheckMediaPipeline(0, 2, (fRtcpMux ? PIPELINE_RTCP_MUX : 0) | |
|
3002 PIPELINE_VIDEO | PIPELINE_RTCP_NACK, VideoSessionConduit::FrameRequestPli); |
|
3003 } |
|
3004 |
|
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 } |
|
3013 |
|
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 } |
|
3021 |
|
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 } |
|
3029 |
|
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 } |
|
3037 |
|
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 } |
|
3045 |
|
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 } |
|
3053 |
|
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 } |
|
3061 |
|
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 } |
|
3069 |
|
3070 TEST_F(SignalingTest, RtcpFbNoFeedback) |
|
3071 { |
|
3072 const char *feedbackTypes[] = { }; |
|
3073 TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), |
|
3074 0, |
|
3075 VideoSessionConduit::FrameRequestNone); |
|
3076 } |
|
3077 |
|
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(); |
|
3083 |
|
3084 sipcc::MediaConstraints constraints; |
|
3085 size_t match; |
|
3086 |
|
3087 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
|
3088 |
|
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; |
|
3099 |
|
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); |
|
3103 |
|
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); |
|
3108 |
|
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); |
|
3113 |
|
3114 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
|
3115 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
|
3116 |
|
3117 // Wait for some data to get written |
|
3118 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
3119 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
3120 |
|
3121 a1_->CloseSendStreams(); |
|
3122 a2_->CloseReceiveStreams(); |
|
3123 |
|
3124 ASSERT_GE(a1_->GetPacketsSent(0), 40); |
|
3125 ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
|
3126 } |
|
3127 |
|
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(); |
|
3133 |
|
3134 sipcc::MediaConstraints constraints; |
|
3135 size_t match; |
|
3136 |
|
3137 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
|
3138 |
|
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; |
|
3149 |
|
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); |
|
3153 |
|
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); |
|
3158 |
|
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); |
|
3163 |
|
3164 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
|
3165 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
|
3166 |
|
3167 // Wait for some data to get written |
|
3168 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
3169 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
3170 |
|
3171 a1_->CloseSendStreams(); |
|
3172 a2_->CloseReceiveStreams(); |
|
3173 |
|
3174 ASSERT_GE(a1_->GetPacketsSent(0), 40); |
|
3175 ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
|
3176 } |
|
3177 |
|
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(); |
|
3184 |
|
3185 sipcc::MediaConstraints constraints; |
|
3186 size_t match; |
|
3187 |
|
3188 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
|
3189 |
|
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); |
|
3197 |
|
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); |
|
3202 |
|
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; |
|
3209 |
|
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); |
|
3213 |
|
3214 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
|
3215 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
|
3216 |
|
3217 // Not using ASSERT_TRUE_WAIT here because we expect failure |
|
3218 PR_Sleep(kDefaultTimeout * 2); // Wait for some data to get written |
|
3219 |
|
3220 a1_->CloseSendStreams(); |
|
3221 a2_->CloseReceiveStreams(); |
|
3222 |
|
3223 ASSERT_GE(a1_->GetPacketsSent(0), 40); |
|
3224 // In this case we should receive nothing. |
|
3225 ASSERT_EQ(a2_->GetPacketsReceived(0), 0); |
|
3226 } |
|
3227 |
|
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(); |
|
3234 |
|
3235 sipcc::MediaConstraints constraints; |
|
3236 size_t match; |
|
3237 |
|
3238 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
|
3239 |
|
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; |
|
3249 |
|
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); |
|
3253 |
|
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); |
|
3258 |
|
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); |
|
3263 |
|
3264 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
|
3265 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
|
3266 |
|
3267 // Wait for some data to get written |
|
3268 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
3269 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
3270 |
|
3271 a1_->CloseSendStreams(); |
|
3272 a2_->CloseReceiveStreams(); |
|
3273 |
|
3274 ASSERT_GE(a1_->GetPacketsSent(0), 40); |
|
3275 ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
|
3276 } |
|
3277 |
|
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(); |
|
3283 |
|
3284 sipcc::MediaConstraints constraints; |
|
3285 size_t match; |
|
3286 |
|
3287 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
|
3288 |
|
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; |
|
3297 |
|
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); |
|
3301 |
|
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); |
|
3306 |
|
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); |
|
3311 |
|
3312 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
|
3313 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
|
3314 |
|
3315 // Wait for some data to get written |
|
3316 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
3317 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
3318 |
|
3319 a1_->CloseSendStreams(); |
|
3320 a2_->CloseReceiveStreams(); |
|
3321 |
|
3322 ASSERT_GE(a1_->GetPacketsSent(0), 40); |
|
3323 ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
|
3324 } |
|
3325 |
|
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(); |
|
3332 |
|
3333 sipcc::MediaConstraints constraints; |
|
3334 size_t match; |
|
3335 |
|
3336 a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
|
3337 |
|
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); |
|
3342 |
|
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); |
|
3346 |
|
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; |
|
3355 |
|
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); |
|
3360 |
|
3361 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
|
3362 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
|
3363 |
|
3364 // Wait for some data to get written |
|
3365 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
3366 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
3367 |
|
3368 a1_->CloseSendStreams(); |
|
3369 a2_->CloseReceiveStreams(); |
|
3370 |
|
3371 ASSERT_GE(a1_->GetPacketsSent(0), 40); |
|
3372 ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
|
3373 } |
|
3374 |
|
3375 |
|
3376 TEST_F(SignalingTest, FullCallRealTrickle) |
|
3377 { |
|
3378 wait_for_gather_ = false; |
|
3379 |
|
3380 sipcc::MediaConstraints constraints; |
|
3381 OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, |
|
3382 true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); |
|
3383 |
|
3384 // Wait for some data to get written |
|
3385 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
3386 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
3387 |
|
3388 a1_->CloseSendStreams(); |
|
3389 a2_->CloseReceiveStreams(); |
|
3390 ASSERT_GE(a1_->GetPacketsSent(0), 40); |
|
3391 ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
|
3392 } |
|
3393 |
|
3394 TEST_F(SignalingTest, FullCallRealTrickleTestServer) |
|
3395 { |
|
3396 wait_for_gather_ = false; |
|
3397 SetTestStunServer(); |
|
3398 |
|
3399 sipcc::MediaConstraints constraints; |
|
3400 OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, |
|
3401 true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); |
|
3402 |
|
3403 TestStunServer::GetInstance()->SetActive(true); |
|
3404 |
|
3405 // Wait for some data to get written |
|
3406 ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
|
3407 a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
|
3408 |
|
3409 a1_->CloseSendStreams(); |
|
3410 a2_->CloseReceiveStreams(); |
|
3411 ASSERT_GE(a1_->GetPacketsSent(0), 40); |
|
3412 ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
|
3413 } |
|
3414 |
|
3415 TEST_F(SignalingTest, hugeSdp) |
|
3416 { |
|
3417 EnsureInit(); |
|
3418 |
|
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"; |
|
3510 |
|
3511 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); |
|
3512 a1_->SetLocal(TestObserver::OFFER, offer, true); |
|
3513 |
|
3514 a2_->SetRemote(TestObserver::OFFER, offer, true); |
|
3515 ASSERT_GE(a2_->getRemoteDescription().length(), 4096U); |
|
3516 a2_->CreateAnswer(constraints, offer, OFFER_AV); |
|
3517 } |
|
3518 |
|
3519 // Test max_fs and max_fr prefs have proper impact on SDP offer |
|
3520 TEST_F(SignalingTest, MaxFsFrInOffer) |
|
3521 { |
|
3522 EnsureInit(); |
|
3523 |
|
3524 sipcc::MediaConstraints constraints; |
|
3525 |
|
3526 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); |
|
3527 ASSERT_TRUE(prefs); |
|
3528 FsFrPrefClearer prefClearer(prefs); |
|
3529 |
|
3530 SetMaxFsFr(prefs, 300, 30); |
|
3531 |
|
3532 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); |
|
3533 |
|
3534 // Verify that SDP contains correct max-fs and max-fr |
|
3535 CheckMaxFsFrSdp(a1_->offer(), 120, 300, 30); |
|
3536 } |
|
3537 |
|
3538 // Test max_fs and max_fr prefs have proper impact on SDP answer |
|
3539 TEST_F(SignalingTest, MaxFsFrInAnswer) |
|
3540 { |
|
3541 EnsureInit(); |
|
3542 |
|
3543 sipcc::MediaConstraints constraints; |
|
3544 |
|
3545 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); |
|
3546 ASSERT_TRUE(prefs); |
|
3547 FsFrPrefClearer prefClearer(prefs); |
|
3548 |
|
3549 // We don't want max_fs and max_fr prefs impact SDP at this moment |
|
3550 SetMaxFsFr(prefs, 0, 0); |
|
3551 |
|
3552 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); |
|
3553 |
|
3554 // SDP should not contain max-fs and max-fr here |
|
3555 CheckMaxFsFrSdp(a1_->offer(), 120, 0, 0); |
|
3556 |
|
3557 a2_->SetRemote(TestObserver::OFFER, a1_->offer()); |
|
3558 |
|
3559 SetMaxFsFr(prefs, 600, 60); |
|
3560 |
|
3561 a2_->CreateAnswer(constraints, a1_->offer(), OFFER_AV | ANSWER_AV); |
|
3562 |
|
3563 // Verify that SDP contains correct max-fs and max-fr |
|
3564 CheckMaxFsFrSdp(a2_->answer(), 120, 600, 60); |
|
3565 } |
|
3566 |
|
3567 // Test SDP offer has proper impact on callee's codec configuration |
|
3568 TEST_F(SignalingTest, MaxFsFrCalleeCodec) |
|
3569 { |
|
3570 EnsureInit(); |
|
3571 |
|
3572 sipcc::MediaConstraints constraints; |
|
3573 |
|
3574 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); |
|
3575 ASSERT_TRUE(prefs); |
|
3576 FsFrPrefClearer prefClearer(prefs); |
|
3577 |
|
3578 // We don't want max_fs and max_fr prefs impact SDP at this moment |
|
3579 SetMaxFsFr(prefs, 0, 0); |
|
3580 |
|
3581 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); |
|
3582 |
|
3583 ParsedSDP sdpWrapper(a1_->offer()); |
|
3584 |
|
3585 sdpWrapper.ReplaceLine("a=rtpmap:120", |
|
3586 "a=rtpmap:120 VP8/90000\r\na=fmtp:120 max-fs=300;max-fr=30\r\n"); |
|
3587 |
|
3588 std::cout << "Modified SDP " << std::endl |
|
3589 << indent(sdpWrapper.getSdp()) << std::endl; |
|
3590 |
|
3591 // Double confirm that SDP offer contains correct max-fs and max-fr |
|
3592 CheckMaxFsFrSdp(sdpWrapper.getSdp(), 120, 300, 30); |
|
3593 |
|
3594 a1_->SetLocal(TestObserver::OFFER, sdpWrapper.getSdp()); |
|
3595 a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp()); |
|
3596 |
|
3597 a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), OFFER_AV | ANSWER_AV); |
|
3598 |
|
3599 // SDP should not contain max-fs and max-fr here |
|
3600 CheckMaxFsFrSdp(a2_->answer(), 120, 0, 0); |
|
3601 |
|
3602 a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); |
|
3603 a1_->SetRemote(TestObserver::ANSWER, a2_->answer()); |
|
3604 |
|
3605 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
|
3606 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
|
3607 |
|
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); |
|
3618 |
|
3619 ASSERT_EQ(video_conduit->SendingMaxFs(), (unsigned short) 300); |
|
3620 ASSERT_EQ(video_conduit->SendingMaxFr(), (unsigned short) 30); |
|
3621 } |
|
3622 |
|
3623 // Test SDP answer has proper impact on caller's codec configuration |
|
3624 TEST_F(SignalingTest, MaxFsFrCallerCodec) |
|
3625 { |
|
3626 EnsureInit(); |
|
3627 |
|
3628 sipcc::MediaConstraints constraints; |
|
3629 |
|
3630 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); |
|
3631 ASSERT_TRUE(prefs); |
|
3632 FsFrPrefClearer prefClearer(prefs); |
|
3633 |
|
3634 // We don't want max_fs and max_fr prefs impact SDP at this moment |
|
3635 SetMaxFsFr(prefs, 0, 0); |
|
3636 |
|
3637 a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); |
|
3638 a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
|
3639 a2_->SetRemote(TestObserver::OFFER, a1_->offer()); |
|
3640 |
|
3641 a2_->CreateAnswer(constraints, a1_->offer(), OFFER_AV | ANSWER_AV); |
|
3642 |
|
3643 ParsedSDP sdpWrapper(a2_->answer()); |
|
3644 |
|
3645 sdpWrapper.ReplaceLine("a=rtpmap:120", |
|
3646 "a=rtpmap:120 VP8/90000\r\na=fmtp:120 max-fs=600;max-fr=60\r\n"); |
|
3647 |
|
3648 std::cout << "Modified SDP " << std::endl |
|
3649 << indent(sdpWrapper.getSdp()) << std::endl; |
|
3650 |
|
3651 // Double confirm that SDP answer contains correct max-fs and max-fr |
|
3652 CheckMaxFsFrSdp(sdpWrapper.getSdp(), 120, 600, 60); |
|
3653 |
|
3654 a2_->SetLocal(TestObserver::ANSWER, sdpWrapper.getSdp()); |
|
3655 a1_->SetRemote(TestObserver::ANSWER, sdpWrapper.getSdp()); |
|
3656 |
|
3657 ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
|
3658 ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
|
3659 |
|
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); |
|
3670 |
|
3671 ASSERT_EQ(video_conduit->SendingMaxFs(), (unsigned short) 600); |
|
3672 ASSERT_EQ(video_conduit->SendingMaxFr(), (unsigned short) 60); |
|
3673 } |
|
3674 |
|
3675 } // End namespace test. |
|
3676 |
|
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 } |
|
3699 |
|
3700 static std::string get_environment(const char *name) { |
|
3701 char *value = getenv(name); |
|
3702 |
|
3703 if (!value) |
|
3704 return ""; |
|
3705 |
|
3706 return value; |
|
3707 } |
|
3708 |
|
3709 // This exists to send as an event to trigger shutdown. |
|
3710 static void tests_complete() { |
|
3711 gTestsComplete = true; |
|
3712 } |
|
3713 |
|
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()); |
|
3718 |
|
3719 ::testing::InitGoogleTest(&argc, argv); |
|
3720 |
|
3721 for(int i=0; i<argc; i++) { |
|
3722 if (!strcmp(argv[i],"-t")) { |
|
3723 kDefaultTimeout = 20000; |
|
3724 } |
|
3725 } |
|
3726 |
|
3727 ::testing::AddGlobalTestEnvironment(new test::SignalingEnvironment); |
|
3728 int result = RUN_ALL_TESTS(); |
|
3729 |
|
3730 test_utils->sts_target()->Dispatch( |
|
3731 WrapRunnableNM(&TestStunServer::ShutdownInstance), NS_DISPATCH_SYNC); |
|
3732 |
|
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); |
|
3737 |
|
3738 return result; |
|
3739 } |
|
3740 |
|
3741 |
|
3742 int main(int argc, char **argv) { |
|
3743 |
|
3744 // This test can cause intermittent oranges on the builders |
|
3745 CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_TESTS") |
|
3746 |
|
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 } |
|
3754 |
|
3755 std::string tmp = get_environment("STUN_SERVER_ADDRESS"); |
|
3756 if (tmp != "") |
|
3757 g_stun_server_address = tmp; |
|
3758 |
|
3759 tmp = get_environment("STUN_SERVER_PORT"); |
|
3760 if (tmp != "") |
|
3761 g_stun_server_port = atoi(tmp.c_str()); |
|
3762 |
|
3763 test_utils = new MtransportTestUtils(); |
|
3764 NSS_NoDB_Init(nullptr); |
|
3765 NSS_SetDomesticPolicy(); |
|
3766 |
|
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); |
|
3773 |
|
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()); |
|
3779 |
|
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; |
|
3784 |
|
3785 int result; |
|
3786 gGtestThread->Dispatch( |
|
3787 WrapRunnableNMRet(gtest_main, argc, argv, &result), NS_DISPATCH_NORMAL); |
|
3788 |
|
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()); |
|
3793 |
|
3794 gGtestThread->Shutdown(); |
|
3795 |
|
3796 sipcc::PeerConnectionCtx::Destroy(); |
|
3797 delete test_utils; |
|
3798 |
|
3799 return result; |
|
3800 } |