1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/webrtc/signaling/test/signaling_unittests.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,3800 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include <iostream> 1.9 +#include <map> 1.10 +#include <algorithm> 1.11 +#include <string> 1.12 +#include <unistd.h> 1.13 + 1.14 +#include "base/basictypes.h" 1.15 +#include "logging.h" 1.16 + 1.17 +#define GTEST_HAS_RTTI 0 1.18 +#include "gtest/gtest.h" 1.19 +#include "gtest_utils.h" 1.20 + 1.21 +#include "nspr.h" 1.22 +#include "nss.h" 1.23 +#include "ssl.h" 1.24 +#include "prthread.h" 1.25 + 1.26 +#include "cpr_stdlib.h" 1.27 +#include "FakePCObserver.h" 1.28 +#include "FakeMediaStreams.h" 1.29 +#include "FakeMediaStreamsImpl.h" 1.30 +#include "PeerConnectionImpl.h" 1.31 +#include "PeerConnectionCtx.h" 1.32 +#include "PeerConnectionMedia.h" 1.33 +#include "MediaPipeline.h" 1.34 +#include "runnable_utils.h" 1.35 +#include "nsServiceManagerUtils.h" 1.36 +#include "mozilla/Services.h" 1.37 +#include "nsIPrefService.h" 1.38 +#include "nsIPrefBranch.h" 1.39 +#include "nsNetUtil.h" 1.40 +#include "nsIIOService.h" 1.41 +#include "nsIDNSService.h" 1.42 +#include "nsWeakReference.h" 1.43 +#include "nricectx.h" 1.44 +#include "rlogringbuffer.h" 1.45 +#include "mozilla/SyncRunnable.h" 1.46 +#include "logging.h" 1.47 +#include "stunserver.h" 1.48 +#include "stunserver.cpp" 1.49 +#include "PeerConnectionImplEnumsBinding.cpp" 1.50 + 1.51 +#include "mtransport_test_utils.h" 1.52 +#include "gtest_ringbuffer_dumper.h" 1.53 +MtransportTestUtils *test_utils; 1.54 +nsCOMPtr<nsIThread> gMainThread; 1.55 +nsCOMPtr<nsIThread> gGtestThread; 1.56 +bool gTestsComplete = false; 1.57 + 1.58 +#ifndef USE_FAKE_MEDIA_STREAMS 1.59 +#error USE_FAKE_MEDIA_STREAMS undefined 1.60 +#endif 1.61 +#ifndef USE_FAKE_PCOBSERVER 1.62 +#error USE_FAKE_PCOBSERVER undefined 1.63 +#endif 1.64 + 1.65 +static int kDefaultTimeout = 7000; 1.66 +static bool fRtcpMux = true; 1.67 + 1.68 +static std::string callerName = "caller"; 1.69 +static std::string calleeName = "callee"; 1.70 + 1.71 +#define ARRAY_TO_STL(container, type, array) \ 1.72 + (container<type>((array), (array) + PR_ARRAY_SIZE(array))) 1.73 + 1.74 +#define ARRAY_TO_SET(type, array) ARRAY_TO_STL(std::set, type, array) 1.75 + 1.76 +std::string g_stun_server_address((char *)"23.21.150.121"); 1.77 +uint16_t g_stun_server_port(3478); 1.78 +std::string kBogusSrflxAddress((char *)"192.0.2.1"); 1.79 +uint16_t kBogusSrflxPort(1001); 1.80 + 1.81 +namespace sipcc { 1.82 + 1.83 +// We can't use mozilla/dom/MediaConstraintsBinding.h here because it uses 1.84 +// nsString, so we pass constraints in using MediaConstraintsExternal instead 1.85 + 1.86 +class MediaConstraints : public MediaConstraintsExternal { 1.87 +public: 1.88 + void setBooleanConstraint(const char *namePtr, bool value, bool mandatory) { 1.89 + cc_boolean_constraint_t &member (getMember(namePtr)); 1.90 + member.was_passed = true; 1.91 + member.value = value; 1.92 + member.mandatory = mandatory; 1.93 + } 1.94 +private: 1.95 + cc_boolean_constraint_t &getMember(const char *namePtr) { 1.96 + if (strcmp(namePtr, "OfferToReceiveAudio") == 0) { 1.97 + return mConstraints.offer_to_receive_audio; 1.98 + } 1.99 + if (strcmp(namePtr, "OfferToReceiveVideo") == 0) { 1.100 + return mConstraints.offer_to_receive_video; 1.101 + } 1.102 + MOZ_ASSERT(false); 1.103 + return mConstraints.moz_dont_offer_datachannel; 1.104 + } 1.105 +}; 1.106 +} 1.107 + 1.108 +using namespace mozilla; 1.109 +using namespace mozilla::dom; 1.110 + 1.111 +namespace test { 1.112 +std::string indent(const std::string &s, int width = 4) { 1.113 + std::string prefix; 1.114 + std::string out; 1.115 + char previous = '\n'; 1.116 + prefix.assign(width, ' '); 1.117 + for (std::string::const_iterator i = s.begin(); i != s.end(); i++) { 1.118 + if (previous == '\n') { 1.119 + out += prefix; 1.120 + } 1.121 + out += *i; 1.122 + previous = *i; 1.123 + } 1.124 + return out; 1.125 +} 1.126 + 1.127 +static const std::string strSampleSdpAudioVideoNoIce = 1.128 + "v=0\r\n" 1.129 + "o=Mozilla-SIPUA 4949 0 IN IP4 10.86.255.143\r\n" 1.130 + "s=SIP Call\r\n" 1.131 + "t=0 0\r\n" 1.132 + "a=ice-ufrag:qkEP\r\n" 1.133 + "a=ice-pwd:ed6f9GuHjLcoCN6sC/Eh7fVl\r\n" 1.134 + "m=audio 16384 RTP/AVP 0 8 9 101\r\n" 1.135 + "c=IN IP4 10.86.255.143\r\n" 1.136 + "a=rtpmap:0 PCMU/8000\r\n" 1.137 + "a=rtpmap:8 PCMA/8000\r\n" 1.138 + "a=rtpmap:9 G722/8000\r\n" 1.139 + "a=rtpmap:101 telephone-event/8000\r\n" 1.140 + "a=fmtp:101 0-15\r\n" 1.141 + "a=sendrecv\r\n" 1.142 + "a=candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host\r\n" 1.143 + "a=candidate:2 2 UDP 2130706431 192.168.2.2 50006 typ host\r\n" 1.144 + "m=video 1024 RTP/AVP 97\r\n" 1.145 + "c=IN IP4 10.86.255.143\r\n" 1.146 + "a=rtpmap:120 VP8/90000\r\n" 1.147 + "a=fmtp:97 profile-level-id=42E00C\r\n" 1.148 + "a=sendrecv\r\n" 1.149 + "a=candidate:1 1 UDP 2130706431 192.168.2.3 50007 typ host\r\n" 1.150 + "a=candidate:2 2 UDP 2130706431 192.168.2.4 50008 typ host\r\n"; 1.151 + 1.152 +static const std::string strSampleCandidate = 1.153 + "a=candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host\r\n"; 1.154 + 1.155 +static const std::string strSampleMid = ""; 1.156 + 1.157 +static const unsigned short nSamplelevel = 2; 1.158 + 1.159 +static const std::string strG711SdpOffer = 1.160 + "v=0\r\n" 1.161 + "o=- 1 1 IN IP4 148.147.200.251\r\n" 1.162 + "s=-\r\n" 1.163 + "b=AS:64\r\n" 1.164 + "t=0 0\r\n" 1.165 + "a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:" 1.166 + "7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n" 1.167 + "m=audio 9000 RTP/AVP 0 8 126\r\n" 1.168 + "c=IN IP4 148.147.200.251\r\n" 1.169 + "b=TIAS:64000\r\n" 1.170 + "a=rtpmap:0 PCMU/8000\r\n" 1.171 + "a=rtpmap:8 PCMA/8000\r\n" 1.172 + "a=rtpmap:126 telephone-event/8000\r\n" 1.173 + "a=candidate:0 1 udp 2130706432 148.147.200.251 9000 typ host\r\n" 1.174 + "a=candidate:0 2 udp 2130706432 148.147.200.251 9005 typ host\r\n" 1.175 + "a=ice-ufrag:cYuakxkEKH+RApYE\r\n" 1.176 + "a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n" 1.177 + "a=sendrecv\r\n"; 1.178 + 1.179 + 1.180 +enum sdpTestFlags 1.181 +{ 1.182 + SHOULD_SEND_AUDIO = (1<<0), 1.183 + SHOULD_RECV_AUDIO = (1<<1), 1.184 + SHOULD_INACTIVE_AUDIO = (1<<2), 1.185 + SHOULD_REJECT_AUDIO = (1<<3), 1.186 + SHOULD_OMIT_AUDIO = (1<<4), 1.187 + DONT_CHECK_AUDIO = (1<<5), 1.188 + SHOULD_CHECK_AUDIO = (1<<6), 1.189 + 1.190 + SHOULD_SEND_VIDEO = (1<<8), 1.191 + SHOULD_RECV_VIDEO = (1<<9), 1.192 + SHOULD_INACTIVE_VIDEO = (1<<10), 1.193 + SHOULD_REJECT_VIDEO = (1<<11), 1.194 + SHOULD_OMIT_VIDEO = (1<<12), 1.195 + DONT_CHECK_VIDEO = (1<<13), 1.196 + SHOULD_CHECK_VIDEO = (1<<14), 1.197 + 1.198 + SHOULD_INCLUDE_DATA = (1 << 16), 1.199 + DONT_CHECK_DATA = (1 << 17), 1.200 + 1.201 + SHOULD_SENDRECV_AUDIO = SHOULD_SEND_AUDIO | SHOULD_RECV_AUDIO, 1.202 + SHOULD_SENDRECV_VIDEO = SHOULD_SEND_VIDEO | SHOULD_RECV_VIDEO, 1.203 + SHOULD_SENDRECV_AV = SHOULD_SENDRECV_AUDIO | SHOULD_SENDRECV_VIDEO, 1.204 + SHOULD_CHECK_AV = SHOULD_CHECK_AUDIO | SHOULD_CHECK_VIDEO, 1.205 + 1.206 + AUDIO_FLAGS = SHOULD_SEND_AUDIO | SHOULD_RECV_AUDIO 1.207 + | SHOULD_INACTIVE_AUDIO | SHOULD_REJECT_AUDIO 1.208 + | DONT_CHECK_AUDIO | SHOULD_OMIT_AUDIO 1.209 + | SHOULD_CHECK_AUDIO, 1.210 + 1.211 + VIDEO_FLAGS = SHOULD_SEND_VIDEO | SHOULD_RECV_VIDEO 1.212 + | SHOULD_INACTIVE_VIDEO | SHOULD_REJECT_VIDEO 1.213 + | DONT_CHECK_VIDEO | SHOULD_OMIT_VIDEO 1.214 + | SHOULD_CHECK_VIDEO 1.215 +}; 1.216 + 1.217 +enum offerAnswerFlags 1.218 +{ 1.219 + OFFER_NONE = 0, // Sugar to make function calls clearer. 1.220 + OFFER_AUDIO = (1<<0), 1.221 + OFFER_VIDEO = (1<<1), 1.222 + // Leaving some room here for other media types 1.223 + ANSWER_NONE = 0, // Sugar to make function calls clearer. 1.224 + ANSWER_AUDIO = (1<<8), 1.225 + ANSWER_VIDEO = (1<<9), 1.226 + 1.227 + OFFER_AV = OFFER_AUDIO | OFFER_VIDEO, 1.228 + ANSWER_AV = ANSWER_AUDIO | ANSWER_VIDEO 1.229 +}; 1.230 + 1.231 +enum mediaPipelineFlags 1.232 +{ 1.233 + PIPELINE_LOCAL = (1<<0), 1.234 + PIPELINE_RTCP_MUX = (1<<1), 1.235 + PIPELINE_SEND = (1<<2), 1.236 + PIPELINE_VIDEO = (1<<3), 1.237 + PIPELINE_RTCP_NACK = (1<<4) 1.238 +}; 1.239 + 1.240 + 1.241 +class TestObserver : public AFakePCObserver 1.242 +{ 1.243 +public: 1.244 + TestObserver(sipcc::PeerConnectionImpl *peerConnection, 1.245 + const std::string &aName) : 1.246 + AFakePCObserver(peerConnection, aName) {} 1.247 + 1.248 + size_t MatchingCandidates(const std::string& cand) { 1.249 + size_t count = 0; 1.250 + 1.251 + for (size_t i=0; i<candidates.size(); ++i) { 1.252 + if (candidates[i].find(cand) != std::string::npos) 1.253 + ++count; 1.254 + } 1.255 + 1.256 + return count; 1.257 + } 1.258 + 1.259 + NS_DECL_THREADSAFE_ISUPPORTS 1.260 + NS_IMETHODIMP OnCreateOfferSuccess(const char* offer, ER&); 1.261 + NS_IMETHODIMP OnCreateOfferError(uint32_t code, const char *msg, ER&); 1.262 + NS_IMETHODIMP OnCreateAnswerSuccess(const char* answer, ER&); 1.263 + NS_IMETHODIMP OnCreateAnswerError(uint32_t code, const char *msg, ER&); 1.264 + NS_IMETHODIMP OnSetLocalDescriptionSuccess(ER&); 1.265 + NS_IMETHODIMP OnSetRemoteDescriptionSuccess(ER&); 1.266 + NS_IMETHODIMP OnSetLocalDescriptionError(uint32_t code, const char *msg, ER&); 1.267 + NS_IMETHODIMP OnSetRemoteDescriptionError(uint32_t code, const char *msg, ER&); 1.268 + NS_IMETHODIMP NotifyConnection(ER&); 1.269 + NS_IMETHODIMP NotifyClosedConnection(ER&); 1.270 + NS_IMETHODIMP NotifyDataChannel(nsIDOMDataChannel *channel, ER&); 1.271 + NS_IMETHODIMP OnStateChange(PCObserverStateType state_type, ER&, void*); 1.272 + NS_IMETHODIMP OnAddStream(nsIDOMMediaStream *stream, ER&); 1.273 + NS_IMETHODIMP OnRemoveStream(ER&); 1.274 + NS_IMETHODIMP OnAddTrack(ER&); 1.275 + NS_IMETHODIMP OnRemoveTrack(ER&); 1.276 + NS_IMETHODIMP OnAddIceCandidateSuccess(ER&); 1.277 + NS_IMETHODIMP OnAddIceCandidateError(uint32_t code, const char *msg, ER&); 1.278 + NS_IMETHODIMP OnIceCandidate(uint16_t level, const char *mid, const char *cand, ER&); 1.279 +}; 1.280 + 1.281 +NS_IMPL_ISUPPORTS(TestObserver, nsISupportsWeakReference) 1.282 + 1.283 +NS_IMETHODIMP 1.284 +TestObserver::OnCreateOfferSuccess(const char* offer, ER&) 1.285 +{ 1.286 + lastString = strdup(offer); 1.287 + state = stateSuccess; 1.288 + std::cout << name << ": onCreateOfferSuccess = " << std::endl << indent(offer) 1.289 + << std::endl; 1.290 + return NS_OK; 1.291 +} 1.292 + 1.293 +NS_IMETHODIMP 1.294 +TestObserver::OnCreateOfferError(uint32_t code, const char *message, ER&) 1.295 +{ 1.296 + lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code); 1.297 + state = stateError; 1.298 + std::cout << name << ": onCreateOfferError = " << code 1.299 + << " (" << message << ")" << std::endl; 1.300 + return NS_OK; 1.301 +} 1.302 + 1.303 +NS_IMETHODIMP 1.304 +TestObserver::OnCreateAnswerSuccess(const char* answer, ER&) 1.305 +{ 1.306 + lastString = strdup(answer); 1.307 + state = stateSuccess; 1.308 + std::cout << name << ": onCreateAnswerSuccess =" << std::endl 1.309 + << indent(answer) << std::endl; 1.310 + return NS_OK; 1.311 +} 1.312 + 1.313 +NS_IMETHODIMP 1.314 +TestObserver::OnCreateAnswerError(uint32_t code, const char *message, ER&) 1.315 +{ 1.316 + lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code); 1.317 + std::cout << name << ": onCreateAnswerError = " << code 1.318 + << " (" << message << ")" << std::endl; 1.319 + state = stateError; 1.320 + return NS_OK; 1.321 +} 1.322 + 1.323 +NS_IMETHODIMP 1.324 +TestObserver::OnSetLocalDescriptionSuccess(ER&) 1.325 +{ 1.326 + lastStatusCode = sipcc::PeerConnectionImpl::kNoError; 1.327 + state = stateSuccess; 1.328 + std::cout << name << ": onSetLocalDescriptionSuccess" << std::endl; 1.329 + return NS_OK; 1.330 +} 1.331 + 1.332 +NS_IMETHODIMP 1.333 +TestObserver::OnSetRemoteDescriptionSuccess(ER&) 1.334 +{ 1.335 + lastStatusCode = sipcc::PeerConnectionImpl::kNoError; 1.336 + state = stateSuccess; 1.337 + std::cout << name << ": onSetRemoteDescriptionSuccess" << std::endl; 1.338 + return NS_OK; 1.339 +} 1.340 + 1.341 +NS_IMETHODIMP 1.342 +TestObserver::OnSetLocalDescriptionError(uint32_t code, const char *message, ER&) 1.343 +{ 1.344 + lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code); 1.345 + state = stateError; 1.346 + std::cout << name << ": onSetLocalDescriptionError = " << code 1.347 + << " (" << message << ")" << std::endl; 1.348 + return NS_OK; 1.349 +} 1.350 + 1.351 +NS_IMETHODIMP 1.352 +TestObserver::OnSetRemoteDescriptionError(uint32_t code, const char *message, ER&) 1.353 +{ 1.354 + lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code); 1.355 + state = stateError; 1.356 + std::cout << name << ": onSetRemoteDescriptionError = " << code 1.357 + << " (" << message << ")" << std::endl; 1.358 + return NS_OK; 1.359 +} 1.360 + 1.361 +NS_IMETHODIMP 1.362 +TestObserver::NotifyConnection(ER&) 1.363 +{ 1.364 + std::cout << name << ": NotifyConnection" << std::endl; 1.365 + return NS_OK; 1.366 +} 1.367 + 1.368 +NS_IMETHODIMP 1.369 +TestObserver::NotifyClosedConnection(ER&) 1.370 +{ 1.371 + std::cout << name << ": NotifyClosedConnection" << std::endl; 1.372 + return NS_OK; 1.373 +} 1.374 + 1.375 +NS_IMETHODIMP 1.376 +TestObserver::NotifyDataChannel(nsIDOMDataChannel *channel, ER&) 1.377 +{ 1.378 + std::cout << name << ": NotifyDataChannel" << std::endl; 1.379 + return NS_OK; 1.380 +} 1.381 + 1.382 +NS_IMETHODIMP 1.383 +TestObserver::OnStateChange(PCObserverStateType state_type, ER&, void*) 1.384 +{ 1.385 + nsresult rv; 1.386 + PCImplReadyState gotready; 1.387 + PCImplIceConnectionState gotice; 1.388 + PCImplIceGatheringState goticegathering; 1.389 + PCImplSipccState gotsipcc; 1.390 + PCImplSignalingState gotsignaling; 1.391 + 1.392 + std::cout << name << ": "; 1.393 + 1.394 + switch (state_type) 1.395 + { 1.396 + case PCObserverStateType::ReadyState: 1.397 + rv = pc->ReadyState(&gotready); 1.398 + NS_ENSURE_SUCCESS(rv, rv); 1.399 + std::cout << "Ready State: " 1.400 + << PCImplReadyStateValues::strings[int(gotready)].value 1.401 + << std::endl; 1.402 + break; 1.403 + case PCObserverStateType::IceConnectionState: 1.404 + rv = pc->IceConnectionState(&gotice); 1.405 + NS_ENSURE_SUCCESS(rv, rv); 1.406 + std::cout << "ICE Connection State: " 1.407 + << PCImplIceConnectionStateValues::strings[int(gotice)].value 1.408 + << std::endl; 1.409 + break; 1.410 + case PCObserverStateType::IceGatheringState: 1.411 + rv = pc->IceGatheringState(&goticegathering); 1.412 + NS_ENSURE_SUCCESS(rv, rv); 1.413 + std::cout 1.414 + << "ICE Gathering State: " 1.415 + << PCImplIceGatheringStateValues::strings[int(goticegathering)].value 1.416 + << std::endl; 1.417 + break; 1.418 + case PCObserverStateType::SdpState: 1.419 + std::cout << "SDP State: " << std::endl; 1.420 + // NS_ENSURE_SUCCESS(rv, rv); 1.421 + break; 1.422 + case PCObserverStateType::SipccState: 1.423 + rv = pc->SipccState(&gotsipcc); 1.424 + NS_ENSURE_SUCCESS(rv, rv); 1.425 + std::cout << "SIPCC State: " 1.426 + << PCImplSipccStateValues::strings[int(gotsipcc)].value 1.427 + << std::endl; 1.428 + break; 1.429 + case PCObserverStateType::SignalingState: 1.430 + rv = pc->SignalingState(&gotsignaling); 1.431 + NS_ENSURE_SUCCESS(rv, rv); 1.432 + std::cout << "Signaling State: " 1.433 + << PCImplSignalingStateValues::strings[int(gotsignaling)].value 1.434 + << std::endl; 1.435 + break; 1.436 + default: 1.437 + // Unknown State 1.438 + MOZ_CRASH("Unknown state change type."); 1.439 + break; 1.440 + } 1.441 + 1.442 + lastStateType = state_type; 1.443 + return NS_OK; 1.444 +} 1.445 + 1.446 + 1.447 +NS_IMETHODIMP 1.448 +TestObserver::OnAddStream(nsIDOMMediaStream *stream, ER&) 1.449 +{ 1.450 + PR_ASSERT(stream); 1.451 + 1.452 + DOMMediaStream *ms = static_cast<DOMMediaStream *>(stream); 1.453 + 1.454 + std::cout << name << ": OnAddStream called hints=" << ms->GetHintContents() 1.455 + << " thread=" << PR_GetCurrentThread() << std::endl ; 1.456 + 1.457 + onAddStreamCalled = true; 1.458 + 1.459 + streams.push_back(ms); 1.460 + 1.461 + // We know that the media stream is secretly a Fake_SourceMediaStream, 1.462 + // so now we can start it pulling from us 1.463 + Fake_SourceMediaStream *fs = static_cast<Fake_SourceMediaStream *>(ms->GetStream()); 1.464 + 1.465 + test_utils->sts_target()->Dispatch( 1.466 + WrapRunnable(fs, &Fake_SourceMediaStream::Start), 1.467 + NS_DISPATCH_NORMAL); 1.468 + 1.469 + return NS_OK; 1.470 +} 1.471 + 1.472 +NS_IMETHODIMP 1.473 +TestObserver::OnRemoveStream(ER&) 1.474 +{ 1.475 + state = stateSuccess; 1.476 + return NS_OK; 1.477 +} 1.478 + 1.479 +NS_IMETHODIMP 1.480 +TestObserver::OnAddTrack(ER&) 1.481 +{ 1.482 + state = stateSuccess; 1.483 + return NS_OK; 1.484 +} 1.485 + 1.486 +NS_IMETHODIMP 1.487 +TestObserver::OnRemoveTrack(ER&) 1.488 +{ 1.489 + state = stateSuccess; 1.490 + return NS_OK; 1.491 +} 1.492 + 1.493 +NS_IMETHODIMP 1.494 +TestObserver::OnIceCandidate(uint16_t level, 1.495 + const char * mid, 1.496 + const char * candidate, ER&) 1.497 +{ 1.498 + std::cout << name << ": onIceCandidate [" << level << "/" 1.499 + << mid << "] " << candidate << std::endl; 1.500 + candidates.push_back(candidate); 1.501 + return NS_OK; 1.502 +} 1.503 + 1.504 +NS_IMETHODIMP 1.505 +TestObserver::OnAddIceCandidateSuccess(ER&) 1.506 +{ 1.507 + lastStatusCode = sipcc::PeerConnectionImpl::kNoError; 1.508 + state = stateSuccess; 1.509 + std::cout << name << ": onAddIceCandidateSuccess" << std::endl; 1.510 + addIceSuccessCount++; 1.511 + return NS_OK; 1.512 +} 1.513 + 1.514 +NS_IMETHODIMP 1.515 +TestObserver::OnAddIceCandidateError(uint32_t code, const char *message, ER&) 1.516 +{ 1.517 + lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code); 1.518 + state = stateError; 1.519 + std::cout << name << ": onAddIceCandidateError = " << code 1.520 + << " (" << message << ")" << std::endl; 1.521 + return NS_OK; 1.522 +} 1.523 + 1.524 +class ParsedSDP { 1.525 + public: 1.526 + //Line number with the corresponding SDP line. 1.527 + typedef std::pair<int, std::string> SdpLine; 1.528 + 1.529 + ParsedSDP(std::string sdp): 1.530 + sdp_(), 1.531 + sdp_without_ice_(), 1.532 + ice_candidates_(), 1.533 + levels_(0), 1.534 + num_lines(0) 1.535 + { 1.536 + sdp_ = sdp; 1.537 + Parse(); 1.538 + } 1.539 + 1.540 + void DeleteAllLines(std::string objType) 1.541 + { 1.542 + int count = sdp_map_.count(objType); 1.543 + std::cout << "Removing " << count << " lines from SDP (" << objType 1.544 + << ")" << std::endl; 1.545 + 1.546 + for (int i = 0; i < count; i++) { 1.547 + DeleteLine(objType); 1.548 + } 1.549 + } 1.550 + 1.551 + void DeleteLine(std::string objType) 1.552 + { 1.553 + ReplaceLine(objType, ""); 1.554 + } 1.555 + 1.556 + // Replaces the first instance of objType in the SDP with 1.557 + // a new string. 1.558 + // If content is an empty string then the line will be removed 1.559 + void ReplaceLine(std::string objType, std::string content) 1.560 + { 1.561 + std::multimap<std::string, SdpLine>::iterator it; 1.562 + it = sdp_map_.find(objType); 1.563 + if(it != sdp_map_.end()) { 1.564 + SdpLine sdp_line_pair = (*it).second; 1.565 + int line_no = sdp_line_pair.first; 1.566 + sdp_map_.erase(it); 1.567 + if(content.empty()) { 1.568 + return; 1.569 + } 1.570 + std::string value = content.substr(objType.length() + 1); 1.571 + sdp_map_.insert(std::pair<std::string, SdpLine>(objType, 1.572 + std::make_pair(line_no,value))); 1.573 + } 1.574 + } 1.575 + 1.576 + void AddLine(std::string content) 1.577 + { 1.578 + size_t whiteSpace = content.find(' '); 1.579 + std::string key; 1.580 + std::string value; 1.581 + if(whiteSpace == std::string::npos) { 1.582 + key = content.substr(0, content.size() - 2); 1.583 + value = ""; 1.584 + } else { 1.585 + key = content.substr(0, whiteSpace); 1.586 + value = content.substr(whiteSpace+1); 1.587 + } 1.588 + sdp_map_.insert(std::pair<std::string, SdpLine>(key, 1.589 + std::make_pair(num_lines,value))); 1.590 + num_lines++; 1.591 + } 1.592 + 1.593 + // Returns the values for all lines of the indicated type 1.594 + // Removes trailing "\r\n" from values. 1.595 + std::vector<std::string> GetLines(std::string objType) const 1.596 + { 1.597 + std::multimap<std::string, SdpLine>::const_iterator it, end; 1.598 + std::vector<std::string> values; 1.599 + it = sdp_map_.lower_bound(objType); 1.600 + end = sdp_map_.upper_bound(objType); 1.601 + while (it != end) { 1.602 + std::string value = it->second.second; 1.603 + if (value.find("\r") != std::string::npos) { 1.604 + value = value.substr(0, value.find("\r")); 1.605 + } else { 1.606 + ADD_FAILURE(); 1.607 + } 1.608 + values.push_back(value); 1.609 + ++it; 1.610 + } 1.611 + return values; 1.612 + } 1.613 + 1.614 + //Parse SDP as std::string into map that looks like: 1.615 + // key: sdp content till first space 1.616 + // value : <line_number, sdp content after the first space> 1.617 + void Parse() 1.618 + { 1.619 + size_t prev = 0; 1.620 + size_t found = 0; 1.621 + num_lines = 0; 1.622 + for(;;) { 1.623 + found = sdp_.find('\n', found + 1); 1.624 + if (found == std::string::npos) 1.625 + break; 1.626 + std::string line = sdp_.substr(prev, (found - prev) + 1); 1.627 + size_t whiteSpace = line.find(' '); 1.628 + std::string key; 1.629 + std::string value; 1.630 + if(whiteSpace == std::string::npos) { 1.631 + //this is the line with no extra contents 1.632 + //example, v=0, a=sendrecv 1.633 + key = line.substr(0, line.size() - 2); 1.634 + //<line_no>:<valeu> 1.635 + value = ""; 1.636 + } else { 1.637 + key = line.substr(0, whiteSpace); 1.638 + //<line_no>:<value> 1.639 + value = line.substr(whiteSpace+1); 1.640 + } 1.641 + SdpLine sdp_line_pair = std::make_pair(num_lines,value); 1.642 + sdp_map_.insert(std::pair<std::string, SdpLine>(key, sdp_line_pair)); 1.643 + num_lines++; 1.644 + //storing ice candidates separately for quick acesss as needed 1.645 + //for the trickle unit tests 1.646 + if (line.find("a=candidate") == 0) { 1.647 + // This is a candidate, strip of a= and \r\n 1.648 + std::string cand = line.substr(2, line.size() - 4); 1.649 + ice_candidates_.insert(std::pair<int, std::string>(levels_, cand)); 1.650 + } else { 1.651 + sdp_without_ice_ += line; 1.652 + } 1.653 + if (line.find("m=") == 0) { 1.654 + // This is an m-line 1.655 + ++levels_; 1.656 + } 1.657 + prev = found + 1; 1.658 + } 1.659 + } 1.660 + 1.661 + //Convert Internal SDP representation into String representation 1.662 + std::string getSdp() 1.663 + { 1.664 + std::vector<std::string> sdp_lines(num_lines); 1.665 + for (std::multimap<std::string, SdpLine>::iterator it = sdp_map_.begin(); 1.666 + it != sdp_map_.end(); ++it) { 1.667 + 1.668 + SdpLine sdp_line_pair = (*it).second; 1.669 + std::string value; 1.670 + if(sdp_line_pair.second.length() == 0) { 1.671 + value = (*it).first + "\r\n"; 1.672 + sdp_lines[sdp_line_pair.first] = value; 1.673 + } else { 1.674 + value = (*it).first + ' ' + sdp_line_pair.second; 1.675 + sdp_lines[sdp_line_pair.first] = value; 1.676 + } 1.677 + } 1.678 + 1.679 + //generate our final sdp in std::string format 1.680 + std::string sdp; 1.681 + for (size_t i = 0; i < sdp_lines.size(); i++) 1.682 + { 1.683 + sdp += sdp_lines[i]; 1.684 + } 1.685 + 1.686 + return sdp; 1.687 + } 1.688 + 1.689 + 1.690 + 1.691 + std::string sdp_; 1.692 + std::string sdp_without_ice_; 1.693 + std::multimap<int, std::string> ice_candidates_; 1.694 + std::multimap<std::string, SdpLine> sdp_map_; 1.695 + int levels_; 1.696 + int num_lines; 1.697 +}; 1.698 + 1.699 +class SignalingAgent { 1.700 + public: 1.701 + SignalingAgent(const std::string &aName) : pc(nullptr), name(aName) { 1.702 + cfg_.addStunServer(g_stun_server_address, g_stun_server_port); 1.703 + 1.704 + pc = sipcc::PeerConnectionImpl::CreatePeerConnection(); 1.705 + EXPECT_TRUE(pc); 1.706 + } 1.707 + 1.708 + SignalingAgent(const std::string &aName, const std::string stun_addr, 1.709 + uint16_t stun_port) : pc(nullptr), name(aName) { 1.710 + cfg_.addStunServer(stun_addr, stun_port); 1.711 + 1.712 + pc = sipcc::PeerConnectionImpl::CreatePeerConnection(); 1.713 + EXPECT_TRUE(pc); 1.714 + } 1.715 + 1.716 + 1.717 + ~SignalingAgent() { 1.718 + mozilla::SyncRunnable::DispatchToThread(gMainThread, 1.719 + WrapRunnable(this, &SignalingAgent::Close)); 1.720 + } 1.721 + 1.722 + void Init_m(nsCOMPtr<nsIThread> thread) 1.723 + { 1.724 + pObserver = new TestObserver(pc, name); 1.725 + ASSERT_TRUE(pObserver); 1.726 + 1.727 + ASSERT_EQ(pc->Initialize(*pObserver, nullptr, cfg_, thread), NS_OK); 1.728 + } 1.729 + 1.730 + void Init(nsCOMPtr<nsIThread> thread) 1.731 + { 1.732 + mozilla::SyncRunnable::DispatchToThread(thread, 1.733 + WrapRunnable(this, &SignalingAgent::Init_m, thread)); 1.734 + 1.735 + ASSERT_TRUE_WAIT(sipcc_state() == PCImplSipccState::Started, 1.736 + kDefaultTimeout); 1.737 + } 1.738 + 1.739 + void WaitForGather() { 1.740 + ASSERT_TRUE_WAIT(ice_gathering_state() == PCImplIceGatheringState::Complete, 1.741 + kDefaultTimeout); 1.742 + 1.743 + std::cout << name << ": Init Complete" << std::endl; 1.744 + } 1.745 + 1.746 + bool WaitForGatherAllowFail() { 1.747 + EXPECT_TRUE_WAIT( 1.748 + ice_gathering_state() == PCImplIceGatheringState::Complete || 1.749 + ice_connection_state() == PCImplIceConnectionState::Failed, 1.750 + kDefaultTimeout); 1.751 + 1.752 + if (ice_connection_state() == PCImplIceConnectionState::Failed) { 1.753 + std::cout << name << ": Init Failed" << std::endl; 1.754 + return false; 1.755 + } 1.756 + 1.757 + std::cout << name << "Init Complete" << std::endl; 1.758 + return true; 1.759 + } 1.760 + 1.761 + PCImplSipccState sipcc_state() 1.762 + { 1.763 + return pc->SipccState(); 1.764 + } 1.765 + 1.766 + PCImplIceConnectionState ice_connection_state() 1.767 + { 1.768 + return pc->IceConnectionState(); 1.769 + } 1.770 + 1.771 + PCImplIceGatheringState ice_gathering_state() 1.772 + { 1.773 + return pc->IceGatheringState(); 1.774 + } 1.775 + 1.776 + PCImplSignalingState signaling_state() 1.777 + { 1.778 + return pc->SignalingState(); 1.779 + } 1.780 + 1.781 + void Close() 1.782 + { 1.783 + if (pc) { 1.784 + std::cout << name << ": Close" << std::endl; 1.785 + 1.786 + pc->Close(); 1.787 + pc = nullptr; 1.788 + } 1.789 + 1.790 + // Shutdown is synchronous evidently. 1.791 + // ASSERT_TRUE(pObserver->WaitForObserverCall()); 1.792 + // ASSERT_EQ(pc->sipcc_state(), sipcc::PeerConnectionInterface::kIdle); 1.793 + } 1.794 + 1.795 + bool OfferContains(const std::string& str) { 1.796 + std::string o(offer()); 1.797 + 1.798 + return o.find(str) != std::string::npos; 1.799 + } 1.800 + 1.801 + bool AnswerContains(const std::string& str) { 1.802 + std::string o(answer()); 1.803 + 1.804 + return o.find(str) != std::string::npos; 1.805 + } 1.806 + 1.807 + size_t MatchingCandidates(const std::string& cand) { 1.808 + return pObserver->MatchingCandidates(cand); 1.809 + } 1.810 + 1.811 + char* offer() const { return offer_; } 1.812 + char* answer() const { return answer_; } 1.813 + 1.814 + std::string getLocalDescription() const { 1.815 + char *sdp = nullptr; 1.816 + pc->GetLocalDescription(&sdp); 1.817 + if (!sdp) { 1.818 + return ""; 1.819 + } 1.820 + return sdp; 1.821 + } 1.822 + 1.823 + std::string getRemoteDescription() const { 1.824 + char *sdp = 0; 1.825 + pc->GetRemoteDescription(&sdp); 1.826 + if (!sdp) { 1.827 + return ""; 1.828 + } 1.829 + return sdp; 1.830 + } 1.831 + 1.832 + // Adds a stream to the PeerConnection. 1.833 + void AddStream(uint32_t hint = 1.834 + DOMMediaStream::HINT_CONTENTS_AUDIO | 1.835 + DOMMediaStream::HINT_CONTENTS_VIDEO, 1.836 + MediaStream *stream = nullptr, 1.837 + sipcc::MediaConstraints *constraints = nullptr 1.838 + ) { 1.839 + 1.840 + sipcc::MediaConstraints noConstraints; 1.841 + if (!constraints) { 1.842 + constraints = &noConstraints; 1.843 + } 1.844 + 1.845 + nsRefPtr<DOMMediaStream> domMediaStream; 1.846 + if (stream) { 1.847 + domMediaStream = new DOMMediaStream(stream); 1.848 + } else { 1.849 + domMediaStream = new DOMMediaStream(); 1.850 + } 1.851 + 1.852 + domMediaStream->SetHintContents(hint); 1.853 + ASSERT_EQ(pc->AddStream(*domMediaStream, *constraints), NS_OK); 1.854 + domMediaStream_ = domMediaStream; 1.855 + } 1.856 + 1.857 + 1.858 + // Removes a stream from the PeerConnection. If the stream 1.859 + // parameter is absent, removes the stream that was most 1.860 + // recently added to the PeerConnection. 1.861 + void RemoveLastStreamAdded() { 1.862 + ASSERT_EQ(pc->RemoveStream(*domMediaStream_), NS_OK); 1.863 + } 1.864 + 1.865 + void CreateOffer(sipcc::MediaConstraints& constraints, 1.866 + uint32_t offerFlags, uint32_t sdpCheck, 1.867 + PCImplSignalingState endState = 1.868 + PCImplSignalingState::SignalingStable) { 1.869 + 1.870 + // Create a media stream as if it came from GUM 1.871 + Fake_AudioStreamSource *audio_stream = 1.872 + new Fake_AudioStreamSource(); 1.873 + 1.874 + nsresult ret; 1.875 + mozilla::SyncRunnable::DispatchToThread( 1.876 + test_utils->sts_target(), 1.877 + WrapRunnableRet(audio_stream, &Fake_MediaStream::Start, &ret)); 1.878 + 1.879 + ASSERT_TRUE(NS_SUCCEEDED(ret)); 1.880 + 1.881 + uint32_t aHintContents = 0; 1.882 + if (offerFlags & OFFER_AUDIO) { 1.883 + aHintContents |= DOMMediaStream::HINT_CONTENTS_AUDIO; 1.884 + } 1.885 + if (offerFlags & OFFER_VIDEO) { 1.886 + aHintContents |= DOMMediaStream::HINT_CONTENTS_VIDEO; 1.887 + } 1.888 + AddStream(aHintContents, audio_stream); 1.889 + 1.890 + // Now call CreateOffer as JS would 1.891 + pObserver->state = TestObserver::stateNoResponse; 1.892 + ASSERT_EQ(pc->CreateOffer(constraints), NS_OK); 1.893 + ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse, 1.894 + kDefaultTimeout); 1.895 + ASSERT_EQ(pObserver->state, TestObserver::stateSuccess); 1.896 + SDPSanityCheck(pObserver->lastString, sdpCheck, true); 1.897 + ASSERT_EQ(signaling_state(), endState); 1.898 + offer_ = pObserver->lastString; 1.899 + } 1.900 + 1.901 +void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer, 1.902 + uint32_t offerAnswerFlags, 1.903 + uint32_t sdpCheck = DONT_CHECK_AUDIO| 1.904 + DONT_CHECK_VIDEO| 1.905 + DONT_CHECK_DATA, 1.906 + PCImplSignalingState endState = 1.907 + PCImplSignalingState::SignalingHaveRemoteOffer) { 1.908 + 1.909 + uint32_t aHintContents = 0; 1.910 + if (offerAnswerFlags & ANSWER_AUDIO) { 1.911 + aHintContents |= DOMMediaStream::HINT_CONTENTS_AUDIO; 1.912 + } 1.913 + if (offerAnswerFlags & ANSWER_VIDEO) { 1.914 + aHintContents |= DOMMediaStream::HINT_CONTENTS_VIDEO; 1.915 + } 1.916 + AddStream(aHintContents); 1.917 + 1.918 + // Decide if streams are disabled for offer or answer 1.919 + // then perform SDP checking based on which stream disabled 1.920 + pObserver->state = TestObserver::stateNoResponse; 1.921 + ASSERT_EQ(pc->CreateAnswer(constraints), NS_OK); 1.922 + ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse, 1.923 + kDefaultTimeout); 1.924 + ASSERT_EQ(pObserver->state, TestObserver::stateSuccess); 1.925 + SDPSanityCheck(pObserver->lastString, sdpCheck, false); 1.926 + ASSERT_EQ(signaling_state(), endState); 1.927 + 1.928 + answer_ = pObserver->lastString; 1.929 + } 1.930 + 1.931 + // At present, we use the hints field in a stream to find and 1.932 + // remove it. This only works if the specified hints flags are 1.933 + // unique among all streams in the PeerConnection. This is not 1.934 + // generally true, and will need significant revision once 1.935 + // multiple streams are supported. 1.936 + void CreateOfferRemoveStream(sipcc::MediaConstraints& constraints, 1.937 + uint32_t hints, uint32_t sdpCheck) { 1.938 + 1.939 + domMediaStream_->SetHintContents(hints); 1.940 + 1.941 + // This currently "removes" a stream that has the same audio/video 1.942 + // hints as were passed in. 1.943 + // When complete RemoveStream will remove and entire stream and its tracks 1.944 + // not just disable a track as this is currently doing 1.945 + ASSERT_EQ(pc->RemoveStream(*domMediaStream_), NS_OK); 1.946 + 1.947 + // Now call CreateOffer as JS would 1.948 + pObserver->state = TestObserver::stateNoResponse; 1.949 + ASSERT_EQ(pc->CreateOffer(constraints), NS_OK); 1.950 + ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse, 1.951 + kDefaultTimeout); 1.952 + ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess); 1.953 + SDPSanityCheck(pObserver->lastString, sdpCheck, true); 1.954 + offer_ = pObserver->lastString; 1.955 + } 1.956 + 1.957 + void SetRemote(TestObserver::Action action, std::string remote, 1.958 + bool ignoreError = false, 1.959 + PCImplSignalingState endState = 1.960 + PCImplSignalingState::SignalingInvalid) { 1.961 + 1.962 + if (endState == PCImplSignalingState::SignalingInvalid) { 1.963 + endState = (action == TestObserver::OFFER ? 1.964 + PCImplSignalingState::SignalingHaveRemoteOffer : 1.965 + PCImplSignalingState::SignalingStable); 1.966 + } 1.967 + 1.968 + pObserver->state = TestObserver::stateNoResponse; 1.969 + ASSERT_EQ(pc->SetRemoteDescription(action, remote.c_str()), NS_OK); 1.970 + ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse, 1.971 + kDefaultTimeout); 1.972 + ASSERT_EQ(signaling_state(), endState); 1.973 + if (!ignoreError) { 1.974 + ASSERT_EQ(pObserver->state, TestObserver::stateSuccess); 1.975 + } 1.976 + } 1.977 + 1.978 + void SetLocal(TestObserver::Action action, std::string local, 1.979 + bool ignoreError = false, 1.980 + PCImplSignalingState endState = 1.981 + PCImplSignalingState::SignalingInvalid) { 1.982 + 1.983 + if (endState == PCImplSignalingState::SignalingInvalid) { 1.984 + endState = (action == TestObserver::OFFER ? 1.985 + PCImplSignalingState::SignalingHaveLocalOffer : 1.986 + PCImplSignalingState::SignalingStable); 1.987 + } 1.988 + 1.989 + pObserver->state = TestObserver::stateNoResponse; 1.990 + ASSERT_EQ(pc->SetLocalDescription(action, local.c_str()), NS_OK); 1.991 + ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse, 1.992 + kDefaultTimeout); 1.993 + ASSERT_EQ(signaling_state(), endState); 1.994 + if (!ignoreError) { 1.995 + ASSERT_EQ(pObserver->state, TestObserver::stateSuccess); 1.996 + } 1.997 + } 1.998 + 1.999 + void DoTrickleIce(ParsedSDP &sdp) { 1.1000 + int expectAddIce = 0; 1.1001 + pObserver->addIceSuccessCount = 0; 1.1002 + for (std::multimap<int, std::string>::iterator it = 1.1003 + sdp.ice_candidates_.begin(); 1.1004 + it != sdp.ice_candidates_.end(); ++it) { 1.1005 + if ((*it).first != 0) { 1.1006 + std::cerr << "Adding trickle ICE candidate " << (*it).second 1.1007 + << std::endl; 1.1008 + ASSERT_TRUE(NS_SUCCEEDED(pc->AddIceCandidate((*it).second.c_str(), "", (*it).first))); 1.1009 + expectAddIce++; 1.1010 + } 1.1011 + } 1.1012 + ASSERT_TRUE_WAIT(pObserver->addIceSuccessCount == expectAddIce, 1.1013 + kDefaultTimeout); 1.1014 + } 1.1015 + 1.1016 + 1.1017 + void DoTrickleIceChrome(ParsedSDP &sdp) { 1.1018 + int expectAddIce = 0; 1.1019 + pObserver->addIceSuccessCount = 0; 1.1020 + for (std::multimap<int, std::string>::iterator it = 1.1021 + sdp.ice_candidates_.begin(); 1.1022 + it != sdp.ice_candidates_.end(); ++it) { 1.1023 + if ((*it).first != 0) { 1.1024 + std::string candidate = "a=" + (*it).second + "\r\n"; 1.1025 + std::cerr << "Adding trickle ICE candidate " << candidate << std::endl; 1.1026 + 1.1027 + ASSERT_TRUE(NS_SUCCEEDED(pc->AddIceCandidate(candidate.c_str(), "", (*it).first))); 1.1028 + expectAddIce++; 1.1029 + } 1.1030 + } 1.1031 + ASSERT_TRUE_WAIT(pObserver->addIceSuccessCount == expectAddIce, 1.1032 + kDefaultTimeout); 1.1033 + } 1.1034 + 1.1035 + 1.1036 + bool IceCompleted() { 1.1037 + return pc->IceConnectionState() == PCImplIceConnectionState::Connected; 1.1038 + } 1.1039 + 1.1040 + void AddIceCandidate(const char* candidate, const char* mid, unsigned short level, 1.1041 + bool expectSuccess) { 1.1042 + PCImplSignalingState endState = signaling_state(); 1.1043 + pObserver->state = TestObserver::stateNoResponse; 1.1044 + pc->AddIceCandidate(candidate, mid, level); 1.1045 + ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse, 1.1046 + kDefaultTimeout); 1.1047 + ASSERT_TRUE(pObserver->state == 1.1048 + expectSuccess ? TestObserver::stateSuccess : 1.1049 + TestObserver::stateError 1.1050 + ); 1.1051 + 1.1052 + // Verify that adding ICE candidates does not change the signaling state 1.1053 + ASSERT_EQ(signaling_state(), endState); 1.1054 + } 1.1055 + 1.1056 + int GetPacketsReceived(int stream) { 1.1057 + std::vector<DOMMediaStream *> streams = pObserver->GetStreams(); 1.1058 + 1.1059 + if ((int) streams.size() <= stream) { 1.1060 + return 0; 1.1061 + } 1.1062 + 1.1063 + return streams[stream]->GetStream()->AsSourceStream()->GetSegmentsAdded(); 1.1064 + } 1.1065 + 1.1066 + int GetPacketsSent(int stream) { 1.1067 + return static_cast<Fake_MediaStreamBase *>( 1.1068 + domMediaStream_->GetStream())->GetSegmentsAdded(); 1.1069 + } 1.1070 + 1.1071 + //Stops generating new audio data for transmission. 1.1072 + //Should be called before Cleanup of the peer connection. 1.1073 + void CloseSendStreams() { 1.1074 + static_cast<Fake_MediaStream*>( 1.1075 + domMediaStream_->GetStream())->StopStream(); 1.1076 + } 1.1077 + 1.1078 + //Stops pulling audio data off the receivers. 1.1079 + //Should be called before Cleanup of the peer connection. 1.1080 + void CloseReceiveStreams() { 1.1081 + std::vector<DOMMediaStream *> streams = 1.1082 + pObserver->GetStreams(); 1.1083 + for (size_t i = 0; i < streams.size(); i++) { 1.1084 + streams[i]->GetStream()->AsSourceStream()->StopStream(); 1.1085 + } 1.1086 + } 1.1087 + 1.1088 + mozilla::RefPtr<mozilla::MediaPipeline> GetMediaPipeline( 1.1089 + bool local, int stream, int track) { 1.1090 + sipcc::SourceStreamInfo *streamInfo; 1.1091 + 1.1092 + if (local) { 1.1093 + streamInfo = pc->media()->GetLocalStream(stream); 1.1094 + } else { 1.1095 + streamInfo = pc->media()->GetRemoteStream(stream); 1.1096 + } 1.1097 + 1.1098 + if (!streamInfo) { 1.1099 + return nullptr; 1.1100 + } 1.1101 + 1.1102 + const auto &pipelines = streamInfo->GetPipelines(); 1.1103 + auto it = pipelines.find(track); 1.1104 + return (it == pipelines.end())? nullptr : it->second; 1.1105 + } 1.1106 + 1.1107 + void CheckMediaPipeline(int stream, int track, uint32_t flags, 1.1108 + VideoSessionConduit::FrameRequestType frameRequestMethod = 1.1109 + VideoSessionConduit::FrameRequestNone) { 1.1110 + 1.1111 + std::cout << name << ": Checking media pipeline settings for " 1.1112 + << ((flags & PIPELINE_LOCAL) ? "local " : "remote ") 1.1113 + << ((flags & PIPELINE_SEND) ? "sending " : "receiving ") 1.1114 + << ((flags & PIPELINE_VIDEO) ? "video" : "audio") 1.1115 + << " pipeline (stream " << stream 1.1116 + << ", track " << track << "); expect " 1.1117 + << ((flags & PIPELINE_RTCP_MUX) ? "MUX, " : "no MUX, ") 1.1118 + << ((flags & PIPELINE_RTCP_NACK) ? "NACK." : "no NACK.") 1.1119 + << std::endl; 1.1120 + 1.1121 + mozilla::RefPtr<mozilla::MediaPipeline> pipeline = 1.1122 + GetMediaPipeline((flags & PIPELINE_LOCAL), stream, track); 1.1123 + ASSERT_TRUE(pipeline); 1.1124 + ASSERT_EQ(pipeline->IsDoingRtcpMux(), !!(flags & PIPELINE_RTCP_MUX)); 1.1125 + // We cannot yet test send/recv with video. 1.1126 + if (!(flags & PIPELINE_VIDEO)) { 1.1127 + if (flags & PIPELINE_SEND) { 1.1128 + ASSERT_TRUE_WAIT(pipeline->rtp_packets_sent() >= 40 && 1.1129 + pipeline->rtcp_packets_received() >= 1, 1.1130 + kDefaultTimeout); 1.1131 + ASSERT_GE(pipeline->rtp_packets_sent(), 40); 1.1132 + ASSERT_GE(pipeline->rtcp_packets_received(), 1); 1.1133 + } else { 1.1134 + ASSERT_TRUE_WAIT(pipeline->rtp_packets_received() >= 40 && 1.1135 + pipeline->rtcp_packets_sent() >= 1, 1.1136 + kDefaultTimeout); 1.1137 + ASSERT_GE(pipeline->rtp_packets_received(), 40); 1.1138 + ASSERT_GE(pipeline->rtcp_packets_sent(), 1); 1.1139 + } 1.1140 + } 1.1141 + 1.1142 + 1.1143 + // Check feedback method for video 1.1144 + if (flags & PIPELINE_VIDEO) { 1.1145 + mozilla::MediaSessionConduit *conduit = pipeline->Conduit(); 1.1146 + ASSERT_TRUE(conduit); 1.1147 + ASSERT_EQ(conduit->type(), mozilla::MediaSessionConduit::VIDEO); 1.1148 + mozilla::VideoSessionConduit *video_conduit = 1.1149 + static_cast<mozilla::VideoSessionConduit*>(conduit); 1.1150 + ASSERT_EQ(!!(flags & PIPELINE_RTCP_NACK), 1.1151 + video_conduit->UsingNackBasic()); 1.1152 + ASSERT_EQ(frameRequestMethod, video_conduit->FrameRequestMethod()); 1.1153 + } 1.1154 + } 1.1155 + 1.1156 +public: 1.1157 + mozilla::RefPtr<sipcc::PeerConnectionImpl> pc; 1.1158 + nsRefPtr<TestObserver> pObserver; 1.1159 + char* offer_; 1.1160 + char* answer_; 1.1161 + nsRefPtr<DOMMediaStream> domMediaStream_; 1.1162 + sipcc::IceConfiguration cfg_; 1.1163 + const std::string name; 1.1164 + 1.1165 +private: 1.1166 + void SDPSanityCheck(std::string sdp, uint32_t flags, bool offer) 1.1167 + { 1.1168 + ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess); 1.1169 + ASSERT_NE(sdp.find("v=0"), std::string::npos); 1.1170 + ASSERT_NE(sdp.find("c=IN IP4"), std::string::npos); 1.1171 + ASSERT_NE(sdp.find("a=fingerprint:sha-256"), std::string::npos); 1.1172 + 1.1173 + std::cout << name << ": SDPSanityCheck flags for " 1.1174 + << (offer ? "offer" : "answer") 1.1175 + << " = " << std::hex << std::showbase 1.1176 + << flags << std::dec 1.1177 + 1.1178 + << ((flags & SHOULD_SEND_AUDIO)?" SHOULD_SEND_AUDIO":"") 1.1179 + << ((flags & SHOULD_RECV_AUDIO)?" SHOULD_RECV_AUDIO":"") 1.1180 + << ((flags & SHOULD_INACTIVE_AUDIO)?" SHOULD_INACTIVE_AUDIO":"") 1.1181 + << ((flags & SHOULD_REJECT_AUDIO)?" SHOULD_REJECT_AUDIO":"") 1.1182 + << ((flags & SHOULD_OMIT_AUDIO)?" SHOULD_OMIT_AUDIO":"") 1.1183 + << ((flags & DONT_CHECK_AUDIO)?" DONT_CHECK_AUDIO":"") 1.1184 + 1.1185 + << ((flags & SHOULD_SEND_VIDEO)?" SHOULD_SEND_VIDEO":"") 1.1186 + << ((flags & SHOULD_RECV_VIDEO)?" SHOULD_RECV_VIDEO":"") 1.1187 + << ((flags & SHOULD_INACTIVE_VIDEO)?" SHOULD_INACTIVE_VIDEO":"") 1.1188 + << ((flags & SHOULD_REJECT_VIDEO)?" SHOULD_REJECT_VIDEO":"") 1.1189 + << ((flags & SHOULD_OMIT_VIDEO)?" SHOULD_OMIT_VIDEO":"") 1.1190 + << ((flags & DONT_CHECK_VIDEO)?" DONT_CHECK_VIDEO":"") 1.1191 + 1.1192 + << ((flags & SHOULD_INCLUDE_DATA)?" SHOULD_INCLUDE_DATA":"") 1.1193 + << ((flags & DONT_CHECK_DATA)?" DONT_CHECK_DATA":"") 1.1194 + << std::endl; 1.1195 + 1.1196 + switch(flags & AUDIO_FLAGS) { 1.1197 + case 0: 1.1198 + ASSERT_EQ(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); 1.1199 + break; 1.1200 + case SHOULD_CHECK_AUDIO: 1.1201 + ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); 1.1202 + if (offer) { 1.1203 + ASSERT_NE(sdp.find("a=rtpmap:0 PCMU/8000"), std::string::npos); 1.1204 + } 1.1205 + break; 1.1206 + case SHOULD_SEND_AUDIO: 1.1207 + ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); 1.1208 + ASSERT_NE(sdp.find(" 0-15\r\na=sendonly"), std::string::npos); 1.1209 + if (offer) { 1.1210 + ASSERT_NE(sdp.find("a=rtpmap:0 PCMU/8000"), std::string::npos); 1.1211 + } 1.1212 + break; 1.1213 + case SHOULD_RECV_AUDIO: 1.1214 + ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); 1.1215 + ASSERT_NE(sdp.find(" 0-15\r\na=recvonly"), std::string::npos); 1.1216 + if (offer) { 1.1217 + ASSERT_NE(sdp.find("a=rtpmap:0 PCMU/8000"), std::string::npos); 1.1218 + } 1.1219 + break; 1.1220 + case SHOULD_SENDRECV_AUDIO: 1.1221 + ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); 1.1222 + ASSERT_NE(sdp.find(" 0-15\r\na=sendrecv"), std::string::npos); 1.1223 + if (offer) { 1.1224 + ASSERT_NE(sdp.find("a=rtpmap:0 PCMU/8000"), std::string::npos); 1.1225 + } 1.1226 + break; 1.1227 + case SHOULD_INACTIVE_AUDIO: 1.1228 + ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); 1.1229 + ASSERT_NE(sdp.find(" 0-15\r\na=inactive"), std::string::npos); 1.1230 + break; 1.1231 + case SHOULD_REJECT_AUDIO: 1.1232 + ASSERT_EQ(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); 1.1233 + ASSERT_NE(sdp.find("m=audio 0 "), std::string::npos); 1.1234 + break; 1.1235 + case SHOULD_OMIT_AUDIO: 1.1236 + ASSERT_EQ(sdp.find("m=audio"), std::string::npos); 1.1237 + break; 1.1238 + case DONT_CHECK_AUDIO: 1.1239 + break; 1.1240 + default: 1.1241 + ASSERT_FALSE("Missing case in switch statement"); 1.1242 + } 1.1243 + 1.1244 + switch(flags & VIDEO_FLAGS) { 1.1245 + case 0: 1.1246 + ASSERT_EQ(sdp.find("a=rtpmap:120 VP8/90000"), std::string::npos); 1.1247 + break; 1.1248 + case SHOULD_CHECK_VIDEO: 1.1249 + ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000"), std::string::npos); 1.1250 + break; 1.1251 + case SHOULD_SEND_VIDEO: 1.1252 + ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000\r\na=sendonly"), 1.1253 + std::string::npos); 1.1254 + break; 1.1255 + case SHOULD_RECV_VIDEO: 1.1256 + ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000\r\na=recvonly"), 1.1257 + std::string::npos); 1.1258 + break; 1.1259 + case SHOULD_SENDRECV_VIDEO: 1.1260 + ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000\r\na=sendrecv"), 1.1261 + std::string::npos); 1.1262 + break; 1.1263 + case SHOULD_INACTIVE_VIDEO: 1.1264 + ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000\r\na=inactive"), 1.1265 + std::string::npos); 1.1266 + break; 1.1267 + case SHOULD_REJECT_VIDEO: 1.1268 + ASSERT_NE(sdp.find("m=video 0 "), std::string::npos); 1.1269 + break; 1.1270 + case SHOULD_OMIT_VIDEO: 1.1271 + ASSERT_EQ(sdp.find("m=video"), std::string::npos); 1.1272 + break; 1.1273 + case DONT_CHECK_VIDEO: 1.1274 + break; 1.1275 + default: 1.1276 + ASSERT_FALSE("Missing case in switch statement"); 1.1277 + } 1.1278 + 1.1279 + if (flags & SHOULD_INCLUDE_DATA) { 1.1280 + ASSERT_NE(sdp.find("m=application"), std::string::npos); 1.1281 + } else if (!(flags & DONT_CHECK_DATA)) { 1.1282 + ASSERT_EQ(sdp.find("m=application"), std::string::npos); 1.1283 + } 1.1284 + } 1.1285 +}; 1.1286 + 1.1287 +class SignalingEnvironment : public ::testing::Environment { 1.1288 + public: 1.1289 + void TearDown() { 1.1290 + // Signaling is shut down in XPCOM shutdown 1.1291 + } 1.1292 +}; 1.1293 + 1.1294 +class SignalingAgentTest : public ::testing::Test { 1.1295 + public: 1.1296 + static void SetUpTestCase() { 1.1297 + } 1.1298 + 1.1299 + void TearDown() { 1.1300 + // Delete all the agents. 1.1301 + for (size_t i=0; i < agents_.size(); i++) { 1.1302 + delete agents_[i]; 1.1303 + } 1.1304 + } 1.1305 + 1.1306 + bool CreateAgent() { 1.1307 + return CreateAgent(g_stun_server_address, g_stun_server_port); 1.1308 + } 1.1309 + 1.1310 + bool CreateAgent(const std::string stun_addr, uint16_t stun_port, 1.1311 + bool wait_for_gather = true) { 1.1312 + ScopedDeletePtr<SignalingAgent> agent( 1.1313 + new SignalingAgent("agent", stun_addr, stun_port)); 1.1314 + 1.1315 + agent->Init(gMainThread); 1.1316 + 1.1317 + if (wait_for_gather) { 1.1318 + if (!agent->WaitForGatherAllowFail()) 1.1319 + return false; 1.1320 + } 1.1321 + 1.1322 + agents_.push_back(agent.forget()); 1.1323 + 1.1324 + return true; 1.1325 + } 1.1326 + 1.1327 + void CreateAgentNoInit() { 1.1328 + ScopedDeletePtr<SignalingAgent> agent(new SignalingAgent("agent")); 1.1329 + agents_.push_back(agent.forget()); 1.1330 + } 1.1331 + 1.1332 + SignalingAgent *agent(size_t i) { 1.1333 + return agents_[i]; 1.1334 + } 1.1335 + 1.1336 + private: 1.1337 + std::vector<SignalingAgent *> agents_; 1.1338 +}; 1.1339 + 1.1340 + 1.1341 +class SignalingTest : public ::testing::Test { 1.1342 +public: 1.1343 + SignalingTest() 1.1344 + : init_(false), 1.1345 + a1_(nullptr), 1.1346 + a2_(nullptr), 1.1347 + wait_for_gather_(true), 1.1348 + stun_addr_(g_stun_server_address), 1.1349 + stun_port_(g_stun_server_port) {} 1.1350 + 1.1351 + SignalingTest(const std::string& stun_addr, uint16_t stun_port) 1.1352 + : a1_(nullptr), 1.1353 + a2_(nullptr), 1.1354 + wait_for_gather_(true), 1.1355 + stun_addr_(stun_addr), 1.1356 + stun_port_(stun_port) {} 1.1357 + 1.1358 + static void SetUpTestCase() { 1.1359 + } 1.1360 + 1.1361 + void EnsureInit() { 1.1362 + 1.1363 + if (init_) 1.1364 + return; 1.1365 + 1.1366 + a1_ = new SignalingAgent(callerName, stun_addr_, stun_port_); 1.1367 + a2_ = new SignalingAgent(calleeName, stun_addr_, stun_port_); 1.1368 + 1.1369 + a1_->Init(gMainThread); 1.1370 + a2_->Init(gMainThread); 1.1371 + 1.1372 + if (wait_for_gather_) { 1.1373 + WaitForGather(); 1.1374 + } 1.1375 + } 1.1376 + 1.1377 + void WaitForGather() { 1.1378 + a1_->WaitForGather(); 1.1379 + a2_->WaitForGather(); 1.1380 + } 1.1381 + 1.1382 + static void TearDownTestCase() { 1.1383 + } 1.1384 + 1.1385 + void CreateOffer(sipcc::MediaConstraints& constraints, 1.1386 + uint32_t offerFlags, uint32_t sdpCheck) { 1.1387 + EnsureInit(); 1.1388 + a1_->CreateOffer(constraints, offerFlags, sdpCheck); 1.1389 + } 1.1390 + 1.1391 + void CreateSetOffer(sipcc::MediaConstraints& constraints, uint32_t sdpCheck) { 1.1392 + EnsureInit(); 1.1393 + a1_->CreateOffer(constraints, OFFER_AV, sdpCheck); 1.1394 + a1_->SetLocal(TestObserver::OFFER, a1_->offer()); 1.1395 + } 1.1396 + 1.1397 + void OfferAnswer(sipcc::MediaConstraints& aconstraints, 1.1398 + sipcc::MediaConstraints& bconstraints, 1.1399 + uint32_t offerAnswerFlags, 1.1400 + bool finishAfterAnswer, uint32_t offerSdpCheck, 1.1401 + uint32_t answerSdpCheck) { 1.1402 + EnsureInit(); 1.1403 + a1_->CreateOffer(aconstraints, offerAnswerFlags, offerSdpCheck); 1.1404 + a1_->SetLocal(TestObserver::OFFER, a1_->offer()); 1.1405 + a2_->SetRemote(TestObserver::OFFER, a1_->offer()); 1.1406 + a2_->CreateAnswer(bconstraints, a1_->offer(), 1.1407 + offerAnswerFlags, answerSdpCheck); 1.1408 + if(true == finishAfterAnswer) { 1.1409 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); 1.1410 + a1_->SetRemote(TestObserver::ANSWER, a2_->answer()); 1.1411 + 1.1412 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.1413 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.1414 + } 1.1415 + } 1.1416 + 1.1417 + void OfferModifiedAnswer(sipcc::MediaConstraints& aconstraints, 1.1418 + sipcc::MediaConstraints& bconstraints, 1.1419 + uint32_t offerSdpCheck, uint32_t answerSdpCheck) { 1.1420 + EnsureInit(); 1.1421 + a1_->CreateOffer(aconstraints, OFFER_AUDIO, offerSdpCheck); 1.1422 + a1_->SetLocal(TestObserver::OFFER, a1_->offer()); 1.1423 + a2_->SetRemote(TestObserver::OFFER, a1_->offer()); 1.1424 + a2_->CreateAnswer(bconstraints, a1_->offer(), OFFER_AUDIO | ANSWER_AUDIO, 1.1425 + answerSdpCheck); 1.1426 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); 1.1427 + ParsedSDP sdpWrapper(a2_->answer()); 1.1428 + sdpWrapper.ReplaceLine("m=audio", "m=audio 65375 RTP/SAVPF 109 8 101\r\n"); 1.1429 + sdpWrapper.AddLine("a=rtpmap:8 PCMA/8000\r\n"); 1.1430 + std::cout << "Modified SDP " << std::endl 1.1431 + << indent(sdpWrapper.getSdp()) << std::endl; 1.1432 + a1_->SetRemote(TestObserver::ANSWER, sdpWrapper.getSdp()); 1.1433 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.1434 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.1435 + } 1.1436 + 1.1437 + void OfferAnswerTrickle(sipcc::MediaConstraints& aconstraints, 1.1438 + sipcc::MediaConstraints& bconstraints, 1.1439 + uint32_t offerSdpCheck, uint32_t answerSdpCheck) { 1.1440 + EnsureInit(); 1.1441 + a1_->CreateOffer(aconstraints, OFFER_AV, offerSdpCheck); 1.1442 + a1_->SetLocal(TestObserver::OFFER, a1_->offer()); 1.1443 + ParsedSDP a1_offer(a1_->offer()); 1.1444 + a2_->SetRemote(TestObserver::OFFER, a1_offer.sdp_without_ice_); 1.1445 + a2_->CreateAnswer(bconstraints, a1_offer.sdp_without_ice_, 1.1446 + OFFER_AV|ANSWER_AV, answerSdpCheck); 1.1447 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); 1.1448 + ParsedSDP a2_answer(a2_->answer()); 1.1449 + a1_->SetRemote(TestObserver::ANSWER, a2_answer.sdp_without_ice_); 1.1450 + // Now set the trickle ICE candidates 1.1451 + a1_->DoTrickleIce(a2_answer); 1.1452 + a2_->DoTrickleIce(a1_offer); 1.1453 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.1454 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.1455 + } 1.1456 + 1.1457 + 1.1458 + void OfferAnswerTrickleChrome(sipcc::MediaConstraints& aconstraints, 1.1459 + sipcc::MediaConstraints& bconstraints, 1.1460 + uint32_t offerSdpCheck, uint32_t answerSdpCheck) { 1.1461 + EnsureInit(); 1.1462 + a1_->CreateOffer(aconstraints, OFFER_AV, offerSdpCheck); 1.1463 + a1_->SetLocal(TestObserver::OFFER, a1_->offer()); 1.1464 + ParsedSDP a1_offer(a1_->offer()); 1.1465 + a2_->SetRemote(TestObserver::OFFER, a1_offer.sdp_without_ice_); 1.1466 + a2_->CreateAnswer(bconstraints, a1_offer.sdp_without_ice_, 1.1467 + OFFER_AV|ANSWER_AV, answerSdpCheck); 1.1468 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); 1.1469 + ParsedSDP a2_answer(a2_->answer()); 1.1470 + a1_->SetRemote(TestObserver::ANSWER, a2_answer.sdp_without_ice_); 1.1471 + // Now set the trickle ICE candidates 1.1472 + a1_->DoTrickleIceChrome(a2_answer); 1.1473 + a2_->DoTrickleIceChrome(a1_offer); 1.1474 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.1475 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.1476 + } 1.1477 + 1.1478 + void CreateOfferRemoveStream(sipcc::MediaConstraints& constraints, 1.1479 + uint32_t hints, uint32_t sdpCheck) { 1.1480 + EnsureInit(); 1.1481 + sipcc::MediaConstraints aconstraints; 1.1482 + aconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1483 + aconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1484 + a1_->CreateOffer(aconstraints, OFFER_AV, SHOULD_SENDRECV_AV ); 1.1485 + a1_->CreateOfferRemoveStream(constraints, hints, sdpCheck); 1.1486 + } 1.1487 + 1.1488 + void CreateOfferAudioOnly(sipcc::MediaConstraints& constraints, 1.1489 + uint32_t sdpCheck) { 1.1490 + EnsureInit(); 1.1491 + a1_->CreateOffer(constraints, OFFER_AUDIO, sdpCheck); 1.1492 + } 1.1493 + 1.1494 + void CreateOfferAddCandidate(sipcc::MediaConstraints& constraints, 1.1495 + const char * candidate, const char * mid, 1.1496 + unsigned short level, uint32_t sdpCheck) { 1.1497 + EnsureInit(); 1.1498 + a1_->CreateOffer(constraints, OFFER_AV, sdpCheck); 1.1499 + a1_->AddIceCandidate(candidate, mid, level, true); 1.1500 + } 1.1501 + 1.1502 + void AddIceCandidateEarly(const char * candidate, const char * mid, 1.1503 + unsigned short level) { 1.1504 + EnsureInit(); 1.1505 + a1_->AddIceCandidate(candidate, mid, level, false); 1.1506 + } 1.1507 + 1.1508 + void CheckRtcpFbSdp(const std::string &sdp, 1.1509 + const std::set<std::string>& expected) { 1.1510 + 1.1511 + std::set<std::string>::const_iterator it; 1.1512 + 1.1513 + // Iterate through the list of expected feedback types and ensure 1.1514 + // that none of them are missing. 1.1515 + for (it = expected.begin(); it != expected.end(); ++it) { 1.1516 + std::string attr = std::string("\r\na=rtcp-fb:120 ") + (*it) + "\r\n"; 1.1517 + std::cout << " - Checking for a=rtcp-fb: '" << *it << "'" << std::endl; 1.1518 + ASSERT_NE(sdp.find(attr), std::string::npos); 1.1519 + } 1.1520 + 1.1521 + // Iterate through all of the rtcp-fb lines in the SDP and ensure 1.1522 + // that all of them are expected. 1.1523 + ParsedSDP sdpWrapper(sdp); 1.1524 + std::vector<std::string> values = sdpWrapper.GetLines("a=rtcp-fb:120"); 1.1525 + std::vector<std::string>::iterator it2; 1.1526 + for (it2 = values.begin(); it2 != values.end(); ++it2) { 1.1527 + std::cout << " - Verifying that rtcp-fb is okay: '" << *it2 1.1528 + << "'" << std::endl; 1.1529 + ASSERT_NE(0U, expected.count(*it2)); 1.1530 + } 1.1531 + } 1.1532 + 1.1533 + void TestRtcpFb(const std::set<std::string>& feedback, 1.1534 + uint32_t rtcpFbFlags, 1.1535 + VideoSessionConduit::FrameRequestType frameRequestMethod) { 1.1536 + EnsureInit(); 1.1537 + sipcc::MediaConstraints constraints; 1.1538 + 1.1539 + a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); 1.1540 + a1_->SetLocal(TestObserver::OFFER, a1_->offer()); 1.1541 + 1.1542 + ParsedSDP sdpWrapper(a1_->offer()); 1.1543 + 1.1544 + // Strip out any existing rtcp-fb lines 1.1545 + sdpWrapper.DeleteAllLines("a=rtcp-fb:120"); 1.1546 + 1.1547 + // Add rtcp-fb lines for the desired feedback types 1.1548 + // We know that the video section is generated second (last), 1.1549 + // so appending these to the end of the SDP has the desired effect. 1.1550 + std::set<std::string>::const_iterator it; 1.1551 + for (it = feedback.begin(); it != feedback.end(); ++it) { 1.1552 + sdpWrapper.AddLine(std::string("a=rtcp-fb:120 ") + (*it) + "\r\n"); 1.1553 + } 1.1554 + 1.1555 + std::cout << "Modified SDP " << std::endl 1.1556 + << indent(sdpWrapper.getSdp()) << std::endl; 1.1557 + 1.1558 + // Double-check that the offered SDP matches what we expect 1.1559 + CheckRtcpFbSdp(sdpWrapper.getSdp(), feedback); 1.1560 + 1.1561 + a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp()); 1.1562 + a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), OFFER_AV | ANSWER_AV); 1.1563 + 1.1564 + CheckRtcpFbSdp(a2_->answer(), feedback); 1.1565 + 1.1566 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); 1.1567 + a1_->SetRemote(TestObserver::ANSWER, a2_->answer()); 1.1568 + 1.1569 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.1570 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.1571 + 1.1572 + a1_->CloseSendStreams(); 1.1573 + a1_->CloseReceiveStreams(); 1.1574 + a2_->CloseSendStreams(); 1.1575 + a2_->CloseReceiveStreams(); 1.1576 + 1.1577 + // Check caller video settings for remote pipeline 1.1578 + a1_->CheckMediaPipeline(0, 2, (fRtcpMux ? PIPELINE_RTCP_MUX : 0) | 1.1579 + PIPELINE_SEND | PIPELINE_VIDEO | rtcpFbFlags, frameRequestMethod); 1.1580 + 1.1581 + // Check callee video settings for remote pipeline 1.1582 + a2_->CheckMediaPipeline(0, 2, (fRtcpMux ? PIPELINE_RTCP_MUX : 0) | 1.1583 + PIPELINE_VIDEO | rtcpFbFlags, frameRequestMethod); 1.1584 + } 1.1585 + 1.1586 + void SetTestStunServer() { 1.1587 + stun_addr_ = TestStunServer::GetInstance()->addr(); 1.1588 + stun_port_ = TestStunServer::GetInstance()->port(); 1.1589 + 1.1590 + TestStunServer::GetInstance()->SetActive(false); 1.1591 + TestStunServer::GetInstance()->SetResponseAddr( 1.1592 + kBogusSrflxAddress, kBogusSrflxPort); 1.1593 + } 1.1594 + 1.1595 + // Check max-fs and max-fr in SDP 1.1596 + void CheckMaxFsFrSdp(const std::string sdp, 1.1597 + int format, 1.1598 + int max_fs, 1.1599 + int max_fr) { 1.1600 + ParsedSDP sdpWrapper(sdp); 1.1601 + std::stringstream ss; 1.1602 + ss << "a=fmtp:" << format; 1.1603 + std::vector<std::string> lines = sdpWrapper.GetLines(ss.str()); 1.1604 + 1.1605 + // Both max-fs and max-fr not exist 1.1606 + if (lines.empty()) { 1.1607 + ASSERT_EQ(max_fs, 0); 1.1608 + ASSERT_EQ(max_fr, 0); 1.1609 + return; 1.1610 + } 1.1611 + 1.1612 + // At most one instance allowed for each format 1.1613 + ASSERT_EQ(lines.size(), 1U); 1.1614 + 1.1615 + std::string line = lines.front(); 1.1616 + 1.1617 + // Make sure that max-fs doesn't exist 1.1618 + if (max_fs == 0) { 1.1619 + ASSERT_EQ(line.find("max-fs="), std::string::npos); 1.1620 + } 1.1621 + // Check max-fs value 1.1622 + if (max_fs > 0) { 1.1623 + std::stringstream ss; 1.1624 + ss << "max-fs=" << max_fs; 1.1625 + ASSERT_NE(line.find(ss.str()), std::string::npos); 1.1626 + } 1.1627 + // Make sure that max-fr doesn't exist 1.1628 + if (max_fr == 0) { 1.1629 + ASSERT_EQ(line.find("max-fr="), std::string::npos); 1.1630 + } 1.1631 + // Check max-fr value 1.1632 + if (max_fr > 0) { 1.1633 + std::stringstream ss; 1.1634 + ss << "max-fr=" << max_fr; 1.1635 + ASSERT_NE(line.find(ss.str()), std::string::npos); 1.1636 + } 1.1637 + } 1.1638 + 1.1639 + protected: 1.1640 + bool init_; 1.1641 + ScopedDeletePtr<SignalingAgent> a1_; // Canonically "caller" 1.1642 + ScopedDeletePtr<SignalingAgent> a2_; // Canonically "callee" 1.1643 + bool wait_for_gather_; 1.1644 + std::string stun_addr_; 1.1645 + uint16_t stun_port_; 1.1646 +}; 1.1647 + 1.1648 +static void SetIntPrefOnMainThread(nsCOMPtr<nsIPrefBranch> prefs, 1.1649 + const char *pref_name, 1.1650 + int new_value) { 1.1651 + MOZ_ASSERT(NS_IsMainThread()); 1.1652 + prefs->SetIntPref(pref_name, new_value); 1.1653 +} 1.1654 + 1.1655 +static void SetMaxFsFr(nsCOMPtr<nsIPrefBranch> prefs, 1.1656 + int max_fs, 1.1657 + int max_fr) { 1.1658 + gMainThread->Dispatch( 1.1659 + WrapRunnableNM(SetIntPrefOnMainThread, 1.1660 + prefs, 1.1661 + "media.navigator.video.max_fs", 1.1662 + max_fs), 1.1663 + NS_DISPATCH_SYNC); 1.1664 + 1.1665 + gMainThread->Dispatch( 1.1666 + WrapRunnableNM(SetIntPrefOnMainThread, 1.1667 + prefs, 1.1668 + "media.navigator.video.max_fr", 1.1669 + max_fr), 1.1670 + NS_DISPATCH_SYNC); 1.1671 +} 1.1672 + 1.1673 +class FsFrPrefClearer { 1.1674 + public: 1.1675 + FsFrPrefClearer(nsCOMPtr<nsIPrefBranch> prefs): mPrefs(prefs) {} 1.1676 + ~FsFrPrefClearer() { 1.1677 + gMainThread->Dispatch( 1.1678 + WrapRunnableNM(FsFrPrefClearer::ClearUserPrefOnMainThread, 1.1679 + mPrefs, 1.1680 + "media.navigator.video.max_fs"), 1.1681 + NS_DISPATCH_SYNC); 1.1682 + gMainThread->Dispatch( 1.1683 + WrapRunnableNM(FsFrPrefClearer::ClearUserPrefOnMainThread, 1.1684 + mPrefs, 1.1685 + "media.navigator.video.max_fr"), 1.1686 + NS_DISPATCH_SYNC); 1.1687 + } 1.1688 + 1.1689 + static void ClearUserPrefOnMainThread(nsCOMPtr<nsIPrefBranch> prefs, 1.1690 + const char *pref_name) { 1.1691 + MOZ_ASSERT(NS_IsMainThread()); 1.1692 + prefs->ClearUserPref(pref_name); 1.1693 + } 1.1694 + private: 1.1695 + nsCOMPtr<nsIPrefBranch> mPrefs; 1.1696 +}; 1.1697 + 1.1698 +TEST_F(SignalingTest, JustInit) 1.1699 +{ 1.1700 +} 1.1701 + 1.1702 +TEST_F(SignalingTest, CreateSetOffer) 1.1703 +{ 1.1704 + sipcc::MediaConstraints constraints; 1.1705 + CreateSetOffer(constraints, SHOULD_SENDRECV_AV); 1.1706 +} 1.1707 + 1.1708 +TEST_F(SignalingTest, CreateOfferAudioVideoConstraintUndefined) 1.1709 +{ 1.1710 + sipcc::MediaConstraints constraints; 1.1711 + CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); 1.1712 +} 1.1713 + 1.1714 +TEST_F(SignalingTest, CreateOfferNoVideoStreamRecvVideo) 1.1715 +{ 1.1716 + sipcc::MediaConstraints constraints; 1.1717 + constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1718 + constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1719 + CreateOffer(constraints, OFFER_AUDIO, 1.1720 + SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO); 1.1721 +} 1.1722 + 1.1723 +TEST_F(SignalingTest, CreateOfferNoAudioStreamRecvAudio) 1.1724 +{ 1.1725 + sipcc::MediaConstraints constraints; 1.1726 + constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1727 + constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1728 + CreateOffer(constraints, OFFER_VIDEO, 1.1729 + SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO); 1.1730 +} 1.1731 + 1.1732 +TEST_F(SignalingTest, CreateOfferNoVideoStream) 1.1733 +{ 1.1734 + sipcc::MediaConstraints constraints; 1.1735 + constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1736 + constraints.setBooleanConstraint("OfferToReceiveVideo", false, false); 1.1737 + CreateOffer(constraints, OFFER_AUDIO, 1.1738 + SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO); 1.1739 +} 1.1740 + 1.1741 +TEST_F(SignalingTest, CreateOfferNoAudioStream) 1.1742 +{ 1.1743 + sipcc::MediaConstraints constraints; 1.1744 + constraints.setBooleanConstraint("OfferToReceiveAudio", false, false); 1.1745 + constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1746 + CreateOffer(constraints, OFFER_VIDEO, 1.1747 + SHOULD_OMIT_AUDIO | SHOULD_SENDRECV_VIDEO); 1.1748 +} 1.1749 + 1.1750 +TEST_F(SignalingTest, CreateOfferDontReceiveAudio) 1.1751 +{ 1.1752 + sipcc::MediaConstraints constraints; 1.1753 + constraints.setBooleanConstraint("OfferToReceiveAudio", false, false); 1.1754 + constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1755 + CreateOffer(constraints, OFFER_AV, 1.1756 + SHOULD_SEND_AUDIO | SHOULD_SENDRECV_VIDEO); 1.1757 +} 1.1758 + 1.1759 +TEST_F(SignalingTest, CreateOfferDontReceiveVideo) 1.1760 +{ 1.1761 + sipcc::MediaConstraints constraints; 1.1762 + constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1763 + constraints.setBooleanConstraint("OfferToReceiveVideo", false, false); 1.1764 + CreateOffer(constraints, OFFER_AV, 1.1765 + SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO); 1.1766 +} 1.1767 + 1.1768 +// XXX Disabled pending resolution of Bug 840728 1.1769 +TEST_F(SignalingTest, DISABLED_CreateOfferRemoveAudioStream) 1.1770 +{ 1.1771 + sipcc::MediaConstraints constraints; 1.1772 + constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1773 + constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1774 + CreateOfferRemoveStream(constraints, DOMMediaStream::HINT_CONTENTS_AUDIO, 1.1775 + SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO); 1.1776 +} 1.1777 + 1.1778 +// XXX Disabled pending resolution of Bug 840728 1.1779 +TEST_F(SignalingTest, DISABLED_CreateOfferDontReceiveAudioRemoveAudioStream) 1.1780 +{ 1.1781 + sipcc::MediaConstraints constraints; 1.1782 + constraints.setBooleanConstraint("OfferToReceiveAudio", false, false); 1.1783 + constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1784 + CreateOfferRemoveStream(constraints, DOMMediaStream::HINT_CONTENTS_AUDIO, 1.1785 + SHOULD_SENDRECV_VIDEO); 1.1786 +} 1.1787 + 1.1788 +// XXX Disabled pending resolution of Bug 840728 1.1789 +TEST_F(SignalingTest, DISABLED_CreateOfferDontReceiveVideoRemoveVideoStream) 1.1790 +{ 1.1791 + sipcc::MediaConstraints constraints; 1.1792 + constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1793 + constraints.setBooleanConstraint("OfferToReceiveVideo", false, false); 1.1794 + CreateOfferRemoveStream(constraints, DOMMediaStream::HINT_CONTENTS_VIDEO, 1.1795 + SHOULD_SENDRECV_AUDIO); 1.1796 +} 1.1797 + 1.1798 +TEST_F(SignalingTest, OfferAnswerNothingDisabled) 1.1799 +{ 1.1800 + sipcc::MediaConstraints constraints; 1.1801 + OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, false, 1.1802 + SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); 1.1803 +} 1.1804 + 1.1805 +TEST_F(SignalingTest, OfferAnswerDontReceiveAudioOnOffer) 1.1806 +{ 1.1807 + sipcc::MediaConstraints offerconstraints; 1.1808 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false); 1.1809 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1810 + sipcc::MediaConstraints answerconstraints; 1.1811 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1812 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1813 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AV, 1.1814 + false, SHOULD_SEND_AUDIO | SHOULD_SENDRECV_VIDEO, 1.1815 + SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO); 1.1816 +} 1.1817 + 1.1818 +TEST_F(SignalingTest, OfferAnswerDontReceiveVideoOnOffer) 1.1819 +{ 1.1820 + sipcc::MediaConstraints offerconstraints; 1.1821 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1822 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); 1.1823 + sipcc::MediaConstraints answerconstraints; 1.1824 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1825 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1826 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AV, 1.1827 + false, SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO, 1.1828 + SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO); 1.1829 +} 1.1830 + 1.1831 +TEST_F(SignalingTest, OfferAnswerDontReceiveAudioOnAnswer) 1.1832 +{ 1.1833 + sipcc::MediaConstraints offerconstraints; 1.1834 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1835 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1836 + sipcc::MediaConstraints answerconstraints; 1.1837 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false); 1.1838 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1839 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AV, 1.1840 + false, SHOULD_SENDRECV_AV, 1.1841 + SHOULD_SEND_AUDIO | SHOULD_SENDRECV_VIDEO); 1.1842 +} 1.1843 + 1.1844 +TEST_F(SignalingTest, OfferAnswerDontReceiveVideoOnAnswer) 1.1845 +{ 1.1846 + sipcc::MediaConstraints offerconstraints; 1.1847 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1848 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1849 + sipcc::MediaConstraints answerconstraints; 1.1850 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1851 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); 1.1852 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AV, 1.1853 + false, SHOULD_SENDRECV_AV, 1.1854 + SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO); 1.1855 +} 1.1856 + 1.1857 +TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnOfferRecvAudio) 1.1858 +{ 1.1859 + sipcc::MediaConstraints offerconstraints; 1.1860 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1861 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1862 + sipcc::MediaConstraints answerconstraints; 1.1863 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1864 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1865 + OfferAnswer(offerconstraints, answerconstraints, OFFER_VIDEO | ANSWER_AV, 1.1866 + false, SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO, 1.1867 + SHOULD_SEND_AUDIO | SHOULD_SENDRECV_VIDEO); 1.1868 +} 1.1869 + 1.1870 +TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnOffer) 1.1871 +{ 1.1872 + sipcc::MediaConstraints offerconstraints; 1.1873 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false); 1.1874 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1875 + sipcc::MediaConstraints answerconstraints; 1.1876 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1877 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1878 + OfferAnswer(offerconstraints, answerconstraints, OFFER_VIDEO | ANSWER_AV, 1.1879 + false, SHOULD_OMIT_AUDIO | SHOULD_SENDRECV_VIDEO, 1.1880 + SHOULD_OMIT_AUDIO | SHOULD_SENDRECV_VIDEO); 1.1881 +} 1.1882 + 1.1883 +TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnOfferRecvVideo) 1.1884 +{ 1.1885 + sipcc::MediaConstraints offerconstraints; 1.1886 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1887 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1888 + sipcc::MediaConstraints answerconstraints; 1.1889 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1890 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1891 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AUDIO | ANSWER_AV, 1.1892 + false, SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO, 1.1893 + SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO); 1.1894 +} 1.1895 + 1.1896 +TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnOffer) 1.1897 +{ 1.1898 + sipcc::MediaConstraints offerconstraints; 1.1899 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1900 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); 1.1901 + sipcc::MediaConstraints answerconstraints; 1.1902 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1903 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1904 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AUDIO | ANSWER_AV, 1.1905 + false, SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO, 1.1906 + SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO); 1.1907 +} 1.1908 + 1.1909 +TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnAnswer) 1.1910 +{ 1.1911 + sipcc::MediaConstraints offerconstraints; 1.1912 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1913 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1914 + sipcc::MediaConstraints answerconstraints; 1.1915 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1916 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1917 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_VIDEO, 1.1918 + false, SHOULD_SENDRECV_AV, 1.1919 + SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO); 1.1920 +} 1.1921 + 1.1922 +TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnAnswer) 1.1923 +{ 1.1924 + sipcc::MediaConstraints offerconstraints; 1.1925 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1926 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1927 + sipcc::MediaConstraints answerconstraints; 1.1928 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1929 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1930 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AUDIO, 1.1931 + false, SHOULD_SENDRECV_AV, 1.1932 + SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO); 1.1933 +} 1.1934 + 1.1935 +TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnAnswerDontReceiveVideoOnAnswer) 1.1936 +{ 1.1937 + sipcc::MediaConstraints offerconstraints; 1.1938 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1939 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1940 + sipcc::MediaConstraints answerconstraints; 1.1941 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1942 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); 1.1943 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AUDIO, 1.1944 + false, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AUDIO ); 1.1945 +} 1.1946 + 1.1947 +TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnAnswerDontReceiveAudioOnAnswer) 1.1948 +{ 1.1949 + sipcc::MediaConstraints offerconstraints; 1.1950 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1951 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1952 + sipcc::MediaConstraints answerconstraints; 1.1953 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false); 1.1954 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1955 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_VIDEO, 1.1956 + false, SHOULD_SENDRECV_AV, 1.1957 + SHOULD_REJECT_AUDIO | SHOULD_SENDRECV_VIDEO); 1.1958 +} 1.1959 + 1.1960 +TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnOfferDontReceiveAudioOnOffer) 1.1961 +{ 1.1962 + sipcc::MediaConstraints offerconstraints; 1.1963 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false); 1.1964 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1965 + sipcc::MediaConstraints answerconstraints; 1.1966 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1967 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1968 + OfferAnswer(offerconstraints, answerconstraints, OFFER_VIDEO | ANSWER_AV, 1.1969 + false, SHOULD_SENDRECV_VIDEO, SHOULD_SENDRECV_VIDEO); 1.1970 +} 1.1971 + 1.1972 +TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnOfferDontReceiveVideoOnOffer) 1.1973 +{ 1.1974 + sipcc::MediaConstraints offerconstraints; 1.1975 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1976 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); 1.1977 + sipcc::MediaConstraints answerconstraints; 1.1978 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1979 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1980 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AUDIO | ANSWER_AV, 1.1981 + false, SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO, 1.1982 + SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO); 1.1983 +} 1.1984 + 1.1985 +TEST_F(SignalingTest, OfferAnswerDontReceiveAudioNoAudioStreamOnOfferDontReceiveVideoOnAnswer) 1.1986 +{ 1.1987 + sipcc::MediaConstraints offerconstraints; 1.1988 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false); 1.1989 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.1990 + sipcc::MediaConstraints answerconstraints; 1.1991 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.1992 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); 1.1993 + OfferAnswer(offerconstraints, answerconstraints, OFFER_VIDEO | ANSWER_AV, 1.1994 + false, SHOULD_SENDRECV_VIDEO, SHOULD_SEND_VIDEO); 1.1995 +} 1.1996 + 1.1997 +TEST_F(SignalingTest, CreateOfferAddCandidate) 1.1998 +{ 1.1999 + sipcc::MediaConstraints constraints; 1.2000 + CreateOfferAddCandidate(constraints, strSampleCandidate.c_str(), 1.2001 + strSampleMid.c_str(), nSamplelevel, 1.2002 + SHOULD_SENDRECV_AV); 1.2003 +} 1.2004 + 1.2005 +TEST_F(SignalingTest, AddIceCandidateEarly) 1.2006 +{ 1.2007 + sipcc::MediaConstraints constraints; 1.2008 + AddIceCandidateEarly(strSampleCandidate.c_str(), 1.2009 + strSampleMid.c_str(), nSamplelevel); 1.2010 +} 1.2011 + 1.2012 +// XXX adam@nostrum.com -- This test seems questionable; we need to think 1.2013 +// through what actually needs to be tested here. 1.2014 +TEST_F(SignalingTest, DISABLED_OfferAnswerReNegotiateOfferAnswerDontReceiveVideoNoVideoStream) 1.2015 +{ 1.2016 + sipcc::MediaConstraints aconstraints; 1.2017 + aconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.2018 + aconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.2019 + 1.2020 + sipcc::MediaConstraints bconstraints; 1.2021 + bconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.2022 + bconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); 1.2023 + 1.2024 + OfferAnswer(aconstraints, aconstraints, OFFER_AV | ANSWER_AV, 1.2025 + false, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); 1.2026 + OfferAnswer(bconstraints, bconstraints, OFFER_AUDIO | ANSWER_AV, 1.2027 + false, SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO, 1.2028 + SHOULD_SENDRECV_AUDIO | SHOULD_INACTIVE_VIDEO); 1.2029 +} 1.2030 + 1.2031 +TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnAnswerNoConstraints) 1.2032 +{ 1.2033 + sipcc::MediaConstraints offerconstraints; 1.2034 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.2035 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.2036 + sipcc::MediaConstraints answerconstraints; 1.2037 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_VIDEO, 1.2038 + false, SHOULD_SENDRECV_AV, 1.2039 + SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO); 1.2040 +} 1.2041 + 1.2042 +TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnAnswerNoConstraints) 1.2043 +{ 1.2044 + sipcc::MediaConstraints offerconstraints; 1.2045 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.2046 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.2047 + sipcc::MediaConstraints answerconstraints; 1.2048 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AUDIO, 1.2049 + false, SHOULD_SENDRECV_AV, 1.2050 + SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO); 1.2051 +} 1.2052 + 1.2053 +TEST_F(SignalingTest, OfferAnswerDontAddAudioVideoStreamsOnAnswerNoConstraints) 1.2054 +{ 1.2055 + sipcc::MediaConstraints offerconstraints; 1.2056 + offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.2057 + offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.2058 + sipcc::MediaConstraints answerconstraints; 1.2059 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_NONE, 1.2060 + false, SHOULD_SENDRECV_AV, 1.2061 + SHOULD_RECV_AUDIO | SHOULD_RECV_VIDEO); 1.2062 +} 1.2063 + 1.2064 +TEST_F(SignalingTest, FullCall) 1.2065 +{ 1.2066 + sipcc::MediaConstraints constraints; 1.2067 + OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, 1.2068 + true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); 1.2069 + 1.2070 + // Wait for some data to get written 1.2071 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.2072 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.2073 + 1.2074 + a1_->CloseSendStreams(); 1.2075 + a2_->CloseReceiveStreams(); 1.2076 + // Check that we wrote a bunch of data 1.2077 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.2078 + //ASSERT_GE(a2_->GetPacketsSent(0), 40); 1.2079 + //ASSERT_GE(a1_->GetPacketsReceived(0), 40); 1.2080 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.2081 + 1.2082 + // Check the low-level media pipeline 1.2083 + // for RTP and RTCP flows 1.2084 + // The first Local pipeline gets stored at 0 1.2085 + a1_->CheckMediaPipeline(0, 0, fRtcpMux ? 1.2086 + PIPELINE_LOCAL | PIPELINE_RTCP_MUX | PIPELINE_SEND : 1.2087 + PIPELINE_LOCAL | PIPELINE_SEND); 1.2088 + 1.2089 + // The first Remote pipeline gets stored at 1 1.2090 + a2_->CheckMediaPipeline(0, 1, (fRtcpMux ? PIPELINE_RTCP_MUX : 0)); 1.2091 +} 1.2092 + 1.2093 +TEST_F(SignalingTest, FullCallAudioOnly) 1.2094 +{ 1.2095 + sipcc::MediaConstraints constraints; 1.2096 + OfferAnswer(constraints, constraints, OFFER_AUDIO | ANSWER_AUDIO, 1.2097 + true, SHOULD_SENDRECV_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2098 + 1.2099 + // Wait for some data to get written 1.2100 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.2101 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.2102 + 1.2103 + a1_->CloseSendStreams(); 1.2104 + a2_->CloseReceiveStreams(); 1.2105 + // Check that we wrote a bunch of data 1.2106 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.2107 + //ASSERT_GE(a2_->GetPacketsSent(0), 40); 1.2108 + //ASSERT_GE(a1_->GetPacketsReceived(0), 40); 1.2109 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.2110 +} 1.2111 + 1.2112 +TEST_F(SignalingTest, FullCallAnswererRejectsVideo) 1.2113 +{ 1.2114 + sipcc::MediaConstraints offerconstraints; 1.2115 + sipcc::MediaConstraints answerconstraints; 1.2116 + answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.2117 + answerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); 1.2118 + OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AUDIO, 1.2119 + true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AUDIO); 1.2120 + 1.2121 + // Wait for some data to get written 1.2122 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.2123 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.2124 + 1.2125 + a1_->CloseSendStreams(); 1.2126 + a2_->CloseReceiveStreams(); 1.2127 + // Check that we wrote a bunch of data 1.2128 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.2129 + //ASSERT_GE(a2_->GetPacketsSent(0), 40); 1.2130 + //ASSERT_GE(a1_->GetPacketsReceived(0), 40); 1.2131 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.2132 +} 1.2133 + 1.2134 +TEST_F(SignalingTest, FullCallVideoOnly) 1.2135 +{ 1.2136 + sipcc::MediaConstraints constraints; 1.2137 + OfferAnswer(constraints, constraints, OFFER_VIDEO | ANSWER_VIDEO, 1.2138 + true, SHOULD_SENDRECV_VIDEO, SHOULD_SENDRECV_VIDEO); 1.2139 + 1.2140 + // If we could check for video packets, we would wait for some to be written 1.2141 + // here. Since we can't, we don't. 1.2142 + // ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.2143 + // a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.2144 + 1.2145 + a1_->CloseSendStreams(); 1.2146 + a2_->CloseReceiveStreams(); 1.2147 + 1.2148 + // FIXME -- Ideally we would check that packets were sent 1.2149 + // and received; however, the test driver setup does not 1.2150 + // currently support sending/receiving with Fake_VideoStreamSource. 1.2151 + // 1.2152 + // Check that we wrote a bunch of data 1.2153 + // ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.2154 + //ASSERT_GE(a2_->GetPacketsSent(0), 40); 1.2155 + //ASSERT_GE(a1_->GetPacketsReceived(0), 40); 1.2156 + // ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.2157 +} 1.2158 + 1.2159 +TEST_F(SignalingTest, OfferModifiedAnswer) 1.2160 +{ 1.2161 + sipcc::MediaConstraints constraints; 1.2162 + OfferModifiedAnswer(constraints, constraints, SHOULD_SENDRECV_AUDIO, 1.2163 + SHOULD_SENDRECV_AUDIO); 1.2164 + a1_->CloseSendStreams(); 1.2165 + a2_->CloseReceiveStreams(); 1.2166 +} 1.2167 + 1.2168 +TEST_F(SignalingTest, FullCallTrickle) 1.2169 +{ 1.2170 + sipcc::MediaConstraints constraints; 1.2171 + OfferAnswerTrickle(constraints, constraints, 1.2172 + SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); 1.2173 + 1.2174 + std::cerr << "ICE handshake completed" << std::endl; 1.2175 + 1.2176 + // Wait for some data to get written 1.2177 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.2178 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.2179 + 1.2180 + a1_->CloseSendStreams(); 1.2181 + a2_->CloseReceiveStreams(); 1.2182 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.2183 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.2184 +} 1.2185 + 1.2186 +// Offer answer with trickle but with chrome-style candidates 1.2187 +TEST_F(SignalingTest, FullCallTrickleChrome) 1.2188 +{ 1.2189 + sipcc::MediaConstraints constraints; 1.2190 + OfferAnswerTrickleChrome(constraints, constraints, 1.2191 + SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); 1.2192 + 1.2193 + std::cerr << "ICE handshake completed" << std::endl; 1.2194 + 1.2195 + // Wait for some data to get written 1.2196 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.2197 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.2198 + 1.2199 + a1_->CloseSendStreams(); 1.2200 + a2_->CloseReceiveStreams(); 1.2201 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.2202 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.2203 +} 1.2204 + 1.2205 +// This test comes from Bug 810220 1.2206 +TEST_F(SignalingTest, AudioOnlyG711Call) 1.2207 +{ 1.2208 + EnsureInit(); 1.2209 + 1.2210 + sipcc::MediaConstraints constraints; 1.2211 + const std::string& offer(strG711SdpOffer); 1.2212 + 1.2213 + std::cout << "Setting offer to:" << std::endl << indent(offer) << std::endl; 1.2214 + a2_->SetRemote(TestObserver::OFFER, offer); 1.2215 + 1.2216 + std::cout << "Creating answer:" << std::endl; 1.2217 + a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO, 1.2218 + DONT_CHECK_AUDIO | DONT_CHECK_VIDEO | DONT_CHECK_DATA); 1.2219 + 1.2220 + std::string answer = a2_->answer(); 1.2221 + 1.2222 + // They didn't offer opus, so our answer shouldn't include it. 1.2223 + ASSERT_EQ(answer.find(" opus/"), std::string::npos); 1.2224 + 1.2225 + // They also didn't offer video or application 1.2226 + ASSERT_EQ(answer.find("video"), std::string::npos); 1.2227 + ASSERT_EQ(answer.find("application"), std::string::npos); 1.2228 + 1.2229 + // We should answer with PCMU and telephone-event 1.2230 + ASSERT_NE(answer.find(" PCMU/8000"), std::string::npos); 1.2231 + ASSERT_NE(answer.find(" telephone-event/8000"), std::string::npos); 1.2232 + 1.2233 + // Double-check the directionality 1.2234 + ASSERT_NE(answer.find("\r\na=sendrecv"), std::string::npos); 1.2235 + 1.2236 +} 1.2237 + 1.2238 +// This test comes from Bug814038 1.2239 +TEST_F(SignalingTest, ChromeOfferAnswer) 1.2240 +{ 1.2241 + EnsureInit(); 1.2242 + 1.2243 + sipcc::MediaConstraints constraints; 1.2244 + 1.2245 + // This is captured SDP from an early interop attempt with Chrome. 1.2246 + std::string offer = 1.2247 + "v=0\r\n" 1.2248 + "o=- 1713781661 2 IN IP4 127.0.0.1\r\n" 1.2249 + "s=-\r\n" 1.2250 + "t=0 0\r\n" 1.2251 + "a=group:BUNDLE audio video\r\n" 1.2252 + 1.2253 + "m=audio 1 RTP/SAVPF 103 104 111 0 8 107 106 105 13 126\r\n" 1.2254 + "a=fingerprint:sha-1 4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:" 1.2255 + "5D:49:6B:19:E5:7C:AB\r\n" 1.2256 + "c=IN IP4 0.0.0.0\r\n" 1.2257 + "a=rtcp:1 IN IP4 0.0.0.0\r\n" 1.2258 + "a=ice-ufrag:lBrbdDfrVBH1cldN\r\n" 1.2259 + "a=ice-pwd:rzh23jet4QpCaEoj9Sl75pL3\r\n" 1.2260 + "a=ice-options:google-ice\r\n" 1.2261 + "a=sendrecv\r\n" 1.2262 + "a=mid:audio\r\n" 1.2263 + "a=rtcp-mux\r\n" 1.2264 + "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:" 1.2265 + "RzrYlzpkTsvgYFD1hQqNCzQ7y4emNLKI1tODsjim\r\n" 1.2266 + "a=rtpmap:103 ISAC/16000\r\n" 1.2267 + "a=rtpmap:104 ISAC/32000\r\n" 1.2268 + // NOTE: the actual SDP that Chrome sends at the moment 1.2269 + // doesn't indicate two channels. I've amended their SDP 1.2270 + // here, under the assumption that the constraints 1.2271 + // described in draft-spittka-payload-rtp-opus will 1.2272 + // eventually be implemented by Google. 1.2273 + "a=rtpmap:111 opus/48000/2\r\n" 1.2274 + "a=rtpmap:0 PCMU/8000\r\n" 1.2275 + "a=rtpmap:8 PCMA/8000\r\n" 1.2276 + "a=rtpmap:107 CN/48000\r\n" 1.2277 + "a=rtpmap:106 CN/32000\r\n" 1.2278 + "a=rtpmap:105 CN/16000\r\n" 1.2279 + "a=rtpmap:13 CN/8000\r\n" 1.2280 + "a=rtpmap:126 telephone-event/8000\r\n" 1.2281 + "a=ssrc:661333377 cname:KIXaNxUlU5DP3fVS\r\n" 1.2282 + "a=ssrc:661333377 msid:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5 a0\r\n" 1.2283 + "a=ssrc:661333377 mslabel:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5\r\n" 1.2284 + "a=ssrc:661333377 label:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5a0\r\n" 1.2285 + 1.2286 + "m=video 1 RTP/SAVPF 100 101 102\r\n" 1.2287 + "a=fingerprint:sha-1 4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:" 1.2288 + "6B:19:E5:7C:AB\r\n" 1.2289 + "c=IN IP4 0.0.0.0\r\n" 1.2290 + "a=rtcp:1 IN IP4 0.0.0.0\r\n" 1.2291 + "a=ice-ufrag:lBrbdDfrVBH1cldN\r\n" 1.2292 + "a=ice-pwd:rzh23jet4QpCaEoj9Sl75pL3\r\n" 1.2293 + "a=ice-options:google-ice\r\n" 1.2294 + "a=sendrecv\r\n" 1.2295 + "a=mid:video\r\n" 1.2296 + "a=rtcp-mux\r\n" 1.2297 + "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:" 1.2298 + "RzrYlzpkTsvgYFD1hQqNCzQ7y4emNLKI1tODsjim\r\n" 1.2299 + "a=rtpmap:100 VP8/90000\r\n" 1.2300 + "a=rtpmap:101 red/90000\r\n" 1.2301 + "a=rtpmap:102 ulpfec/90000\r\n" 1.2302 + "a=rtcp-fb:100 nack\r\n" 1.2303 + "a=rtcp-fb:100 ccm fir\r\n" 1.2304 + "a=ssrc:3012607008 cname:KIXaNxUlU5DP3fVS\r\n" 1.2305 + "a=ssrc:3012607008 msid:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5 v0\r\n" 1.2306 + "a=ssrc:3012607008 mslabel:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5\r\n" 1.2307 + "a=ssrc:3012607008 label:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5v0\r\n"; 1.2308 + 1.2309 + 1.2310 + std::cout << "Setting offer to:" << std::endl << indent(offer) << std::endl; 1.2311 + a2_->SetRemote(TestObserver::OFFER, offer); 1.2312 + 1.2313 + std::cout << "Creating answer:" << std::endl; 1.2314 + a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO); 1.2315 + 1.2316 + std::string answer = a2_->answer(); 1.2317 +} 1.2318 + 1.2319 + 1.2320 +TEST_F(SignalingTest, FullChromeHandshake) 1.2321 +{ 1.2322 + EnsureInit(); 1.2323 + 1.2324 + sipcc::MediaConstraints constraints; 1.2325 + constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); 1.2326 + constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); 1.2327 + 1.2328 + std::string offer = "v=0\r\n" 1.2329 + "o=- 3835809413 2 IN IP4 127.0.0.1\r\n" 1.2330 + "s=-\r\n" 1.2331 + "t=0 0\r\n" 1.2332 + "a=group:BUNDLE audio video\r\n" 1.2333 + "a=msid-semantic: WMS ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH\r\n" 1.2334 + "m=audio 1 RTP/SAVPF 103 104 111 0 8 107 106 105 13 126\r\n" 1.2335 + "c=IN IP4 1.1.1.1\r\n" 1.2336 + "a=rtcp:1 IN IP4 1.1.1.1\r\n" 1.2337 + "a=ice-ufrag:jz9UBk9RT8eCQXiL\r\n" 1.2338 + "a=ice-pwd:iscXxsdU+0gracg0g5D45orx\r\n" 1.2339 + "a=ice-options:google-ice\r\n" 1.2340 + "a=fingerprint:sha-256 A8:76:8C:4C:FA:2E:67:D7:F8:1D:28:4E:90:24:04:" 1.2341 + "12:EB:B4:A6:69:3D:05:92:E4:91:C3:EA:F9:B7:54:D3:09\r\n" 1.2342 + "a=sendrecv\r\n" 1.2343 + "a=mid:audio\r\n" 1.2344 + "a=rtcp-mux\r\n" 1.2345 + "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:/he/v44FKu/QvEhex86zV0pdn2V" 1.2346 + "4Y7wB2xaZ8eUy\r\n" 1.2347 + "a=rtpmap:103 ISAC/16000\r\n" 1.2348 + "a=rtpmap:104 ISAC/32000\r\n" 1.2349 + "a=rtpmap:111 opus/48000/2\r\n" 1.2350 + "a=rtpmap:0 PCMU/8000\r\n" 1.2351 + "a=rtpmap:8 PCMA/8000\r\n" 1.2352 + "a=rtpmap:107 CN/48000\r\n" 1.2353 + "a=rtpmap:106 CN/32000\r\n" 1.2354 + "a=rtpmap:105 CN/16000\r\n" 1.2355 + "a=rtpmap:13 CN/8000\r\n" 1.2356 + "a=rtpmap:126 telephone-event/8000\r\n" 1.2357 + "a=ssrc:3389377748 cname:G5I+Jxz4rcaq8IIK\r\n" 1.2358 + "a=ssrc:3389377748 msid:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH a0\r\n" 1.2359 + "a=ssrc:3389377748 mslabel:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH\r\n" 1.2360 + "a=ssrc:3389377748 label:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOHa0\r\n" 1.2361 + "m=video 1 RTP/SAVPF 100 116 117\r\n" 1.2362 + "c=IN IP4 1.1.1.1\r\n" 1.2363 + "a=rtcp:1 IN IP4 1.1.1.1\r\n" 1.2364 + "a=ice-ufrag:jz9UBk9RT8eCQXiL\r\n" 1.2365 + "a=ice-pwd:iscXxsdU+0gracg0g5D45orx\r\n" 1.2366 + "a=ice-options:google-ice\r\n" 1.2367 + "a=fingerprint:sha-256 A8:76:8C:4C:FA:2E:67:D7:F8:1D:28:4E:90:24:04:" 1.2368 + "12:EB:B4:A6:69:3D:05:92:E4:91:C3:EA:F9:B7:54:D3:09\r\n" 1.2369 + "a=sendrecv\r\n" 1.2370 + "a=mid:video\r\n" 1.2371 + "a=rtcp-mux\r\n" 1.2372 + "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:/he/v44FKu/QvEhex86zV0pdn2V" 1.2373 + "4Y7wB2xaZ8eUy\r\n" 1.2374 + "a=rtpmap:100 VP8/90000\r\n" 1.2375 + "a=rtpmap:116 red/90000\r\n" 1.2376 + "a=rtpmap:117 ulpfec/90000\r\n" 1.2377 + "a=ssrc:3613537198 cname:G5I+Jxz4rcaq8IIK\r\n" 1.2378 + "a=ssrc:3613537198 msid:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH v0\r\n" 1.2379 + "a=ssrc:3613537198 mslabel:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH\r\n" 1.2380 + "a=ssrc:3613537198 label:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOHv0\r\n"; 1.2381 + 1.2382 + std::cout << "Setting offer to:" << std::endl << indent(offer) << std::endl; 1.2383 + a2_->SetRemote(TestObserver::OFFER, offer); 1.2384 + 1.2385 + std::cout << "Creating answer:" << std::endl; 1.2386 + a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO); 1.2387 + 1.2388 + std::cout << "Setting answer" << std::endl; 1.2389 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); 1.2390 + 1.2391 + std::string answer = a2_->answer(); 1.2392 + ASSERT_NE(answer.find("111 opus/"), std::string::npos); 1.2393 +} 1.2394 + 1.2395 +// Disabled pending resolution of bug 818640. 1.2396 +TEST_F(SignalingTest, DISABLED_OfferAllDynamicTypes) 1.2397 +{ 1.2398 + EnsureInit(); 1.2399 + 1.2400 + sipcc::MediaConstraints constraints; 1.2401 + std::string offer; 1.2402 + for (int i = 96; i < 128; i++) 1.2403 + { 1.2404 + std::stringstream ss; 1.2405 + ss << i; 1.2406 + std::cout << "Trying dynamic pt = " << i << std::endl; 1.2407 + offer = 1.2408 + "v=0\r\n" 1.2409 + "o=- 1 1 IN IP4 148.147.200.251\r\n" 1.2410 + "s=-\r\n" 1.2411 + "b=AS:64\r\n" 1.2412 + "t=0 0\r\n" 1.2413 + "a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:" 1.2414 + "7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n" 1.2415 + "m=audio 9000 RTP/AVP " + ss.str() + "\r\n" 1.2416 + "c=IN IP4 148.147.200.251\r\n" 1.2417 + "b=TIAS:64000\r\n" 1.2418 + "a=rtpmap:" + ss.str() +" opus/48000/2\r\n" 1.2419 + "a=candidate:0 1 udp 2130706432 148.147.200.251 9000 typ host\r\n" 1.2420 + "a=candidate:0 2 udp 2130706432 148.147.200.251 9005 typ host\r\n" 1.2421 + "a=ice-ufrag:cYuakxkEKH+RApYE\r\n" 1.2422 + "a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n" 1.2423 + "a=sendrecv\r\n"; 1.2424 + 1.2425 + /* 1.2426 + std::cout << "Setting offer to:" << std::endl 1.2427 + << indent(offer) << std::endl; 1.2428 + */ 1.2429 + a2_->SetRemote(TestObserver::OFFER, offer); 1.2430 + 1.2431 + //std::cout << "Creating answer:" << std::endl; 1.2432 + a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO); 1.2433 + 1.2434 + std::string answer = a2_->answer(); 1.2435 + 1.2436 + ASSERT_NE(answer.find(ss.str() + " opus/"), std::string::npos); 1.2437 + } 1.2438 + 1.2439 +} 1.2440 + 1.2441 +TEST_F(SignalingTest, OfferAnswerCheckDescriptions) 1.2442 +{ 1.2443 + sipcc::MediaConstraints constraints; 1.2444 + OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, true, 1.2445 + SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); 1.2446 + 1.2447 + std::cout << "Caller's Local Description: " << std::endl 1.2448 + << indent(a1_->getLocalDescription()) << std::endl << std::endl; 1.2449 + 1.2450 + std::cout << "Caller's Remote Description: " << std::endl 1.2451 + << indent(a1_->getRemoteDescription()) << std::endl << std::endl; 1.2452 + 1.2453 + std::cout << "Callee's Local Description: " << std::endl 1.2454 + << indent(a2_->getLocalDescription()) << std::endl << std::endl; 1.2455 + 1.2456 + std::cout << "Callee's Remote Description: " << std::endl 1.2457 + << indent(a2_->getRemoteDescription()) << std::endl << std::endl; 1.2458 + 1.2459 + ASSERT_EQ(a1_->getLocalDescription(),a2_->getRemoteDescription()); 1.2460 + ASSERT_EQ(a2_->getLocalDescription(),a1_->getRemoteDescription()); 1.2461 +} 1.2462 + 1.2463 +TEST_F(SignalingTest, CheckTrickleSdpChange) 1.2464 +{ 1.2465 + sipcc::MediaConstraints constraints; 1.2466 + OfferAnswerTrickle(constraints, constraints, 1.2467 + SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); 1.2468 + std::cerr << "ICE handshake completed" << std::endl; 1.2469 + 1.2470 + a1_->CloseSendStreams(); 1.2471 + a2_->CloseReceiveStreams(); 1.2472 + 1.2473 + std::cout << "Caller's Local Description: " << std::endl 1.2474 + << indent(a1_->getLocalDescription()) << std::endl << std::endl; 1.2475 + 1.2476 + std::cout << "Caller's Remote Description: " << std::endl 1.2477 + << indent(a1_->getRemoteDescription()) << std::endl << std::endl; 1.2478 + 1.2479 + std::cout << "Callee's Local Description: " << std::endl 1.2480 + << indent(a2_->getLocalDescription()) << std::endl << std::endl; 1.2481 + 1.2482 + std::cout << "Callee's Remote Description: " << std::endl 1.2483 + << indent(a2_->getRemoteDescription()) << std::endl << std::endl; 1.2484 + 1.2485 + ASSERT_NE(a1_->getLocalDescription().find("\r\na=candidate"), 1.2486 + std::string::npos); 1.2487 + ASSERT_NE(a1_->getRemoteDescription().find("\r\na=candidate"), 1.2488 + std::string::npos); 1.2489 + ASSERT_NE(a2_->getLocalDescription().find("\r\na=candidate"), 1.2490 + std::string::npos); 1.2491 + ASSERT_NE(a2_->getRemoteDescription().find("\r\na=candidate"), 1.2492 + std::string::npos); 1.2493 + /* TODO (abr): These checks aren't quite right, since trickle ICE 1.2494 + * can easily result in SDP that is semantically identical but 1.2495 + * varies syntactically (in particularly, the ordering of attributes 1.2496 + * withing an m-line section can be different). This needs to be updated 1.2497 + * to be a semantic comparision between the SDP. Currently, these checks 1.2498 + * will fail whenever we add any other attributes to the SDP, such as 1.2499 + * RTCP MUX or RTCP feedback. 1.2500 + ASSERT_EQ(a1_->getLocalDescription(),a2_->getRemoteDescription()); 1.2501 + ASSERT_EQ(a2_->getLocalDescription(),a1_->getRemoteDescription()); 1.2502 + */ 1.2503 +} 1.2504 + 1.2505 +TEST_F(SignalingTest, ipAddrAnyOffer) 1.2506 +{ 1.2507 + EnsureInit(); 1.2508 + 1.2509 + sipcc::MediaConstraints constraints; 1.2510 + std::string offer = 1.2511 + "v=0\r\n" 1.2512 + "o=- 1 1 IN IP4 127.0.0.1\r\n" 1.2513 + "s=-\r\n" 1.2514 + "b=AS:64\r\n" 1.2515 + "t=0 0\r\n" 1.2516 + "a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:" 1.2517 + "7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n" 1.2518 + "m=audio 9000 RTP/AVP 99\r\n" 1.2519 + "c=IN IP4 0.0.0.0\r\n" 1.2520 + "a=rtpmap:99 opus/48000/2\r\n" 1.2521 + "a=ice-ufrag:cYuakxkEKH+RApYE\r\n" 1.2522 + "a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n" 1.2523 + "a=sendrecv\r\n"; 1.2524 + 1.2525 + a2_->SetRemote(TestObserver::OFFER, offer); 1.2526 + ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateSuccess); 1.2527 + a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO); 1.2528 + ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateSuccess); 1.2529 + std::string answer = a2_->answer(); 1.2530 + ASSERT_NE(answer.find("a=sendrecv"), std::string::npos); 1.2531 +} 1.2532 + 1.2533 +static void CreateSDPForBigOTests(std::string& offer, const char *number) { 1.2534 + offer = 1.2535 + "v=0\r\n" 1.2536 + "o=- "; 1.2537 + offer += number; 1.2538 + offer += " "; 1.2539 + offer += number; 1.2540 + offer += " IN IP4 127.0.0.1\r\n" 1.2541 + "s=-\r\n" 1.2542 + "b=AS:64\r\n" 1.2543 + "t=0 0\r\n" 1.2544 + "a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:" 1.2545 + "7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n" 1.2546 + "m=audio 9000 RTP/AVP 99\r\n" 1.2547 + "c=IN IP4 0.0.0.0\r\n" 1.2548 + "a=rtpmap:99 opus/48000/2\r\n" 1.2549 + "a=ice-ufrag:cYuakxkEKH+RApYE\r\n" 1.2550 + "a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n" 1.2551 + "a=sendrecv\r\n"; 1.2552 +} 1.2553 + 1.2554 +TEST_F(SignalingTest, BigOValues) 1.2555 +{ 1.2556 + EnsureInit(); 1.2557 + 1.2558 + std::string offer; 1.2559 + 1.2560 + CreateSDPForBigOTests(offer, "12345678901234567"); 1.2561 + 1.2562 + a2_->SetRemote(TestObserver::OFFER, offer); 1.2563 + ASSERT_EQ(a2_->pObserver->state, TestObserver::stateSuccess); 1.2564 +} 1.2565 + 1.2566 +TEST_F(SignalingTest, BigOValuesExtraChars) 1.2567 +{ 1.2568 + EnsureInit(); 1.2569 + 1.2570 + std::string offer; 1.2571 + 1.2572 + CreateSDPForBigOTests(offer, "12345678901234567FOOBAR"); 1.2573 + 1.2574 + // The signaling state will remain "stable" because the unparsable 1.2575 + // SDP leads to a failure in SetRemoteDescription. 1.2576 + a2_->SetRemote(TestObserver::OFFER, offer, true, 1.2577 + PCImplSignalingState::SignalingStable); 1.2578 + ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateError); 1.2579 +} 1.2580 + 1.2581 +TEST_F(SignalingTest, BigOValuesTooBig) 1.2582 +{ 1.2583 + EnsureInit(); 1.2584 + 1.2585 + std::string offer; 1.2586 + 1.2587 + CreateSDPForBigOTests(offer, "18446744073709551615"); 1.2588 + 1.2589 + // The signaling state will remain "stable" because the unparsable 1.2590 + // SDP leads to a failure in SetRemoteDescription. 1.2591 + a2_->SetRemote(TestObserver::OFFER, offer, true, 1.2592 + PCImplSignalingState::SignalingStable); 1.2593 + ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateError); 1.2594 +} 1.2595 + 1.2596 +TEST_F(SignalingTest, SetLocalAnswerInStable) 1.2597 +{ 1.2598 + EnsureInit(); 1.2599 + 1.2600 + sipcc::MediaConstraints constraints; 1.2601 + CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2602 + 1.2603 + // The signaling state will remain "stable" because the 1.2604 + // SetLocalDescription call fails. 1.2605 + a1_->SetLocal(TestObserver::ANSWER, a1_->offer(), true, 1.2606 + PCImplSignalingState::SignalingStable); 1.2607 + ASSERT_EQ(a1_->pObserver->lastStatusCode, 1.2608 + sipcc::PeerConnectionImpl::kInvalidState); 1.2609 +} 1.2610 + 1.2611 +TEST_F(SignalingTest, SetRemoteAnswerInStable) { 1.2612 + EnsureInit(); 1.2613 + 1.2614 + // The signaling state will remain "stable" because the 1.2615 + // SetRemoteDescription call fails. 1.2616 + a1_->SetRemote(TestObserver::ANSWER, strSampleSdpAudioVideoNoIce, true, 1.2617 + PCImplSignalingState::SignalingStable); 1.2618 + ASSERT_EQ(a1_->pObserver->lastStatusCode, 1.2619 + sipcc::PeerConnectionImpl::kInvalidState); 1.2620 +} 1.2621 + 1.2622 +TEST_F(SignalingTest, SetLocalAnswerInHaveLocalOffer) { 1.2623 + sipcc::MediaConstraints constraints; 1.2624 + CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2625 + a1_->SetLocal(TestObserver::OFFER, a1_->offer()); 1.2626 + ASSERT_EQ(a1_->pObserver->lastStatusCode, 1.2627 + sipcc::PeerConnectionImpl::kNoError); 1.2628 + 1.2629 + // The signaling state will remain "have-local-offer" because the 1.2630 + // SetLocalDescription call fails. 1.2631 + a1_->SetLocal(TestObserver::ANSWER, a1_->offer(), true, 1.2632 + PCImplSignalingState::SignalingHaveLocalOffer); 1.2633 + ASSERT_EQ(a1_->pObserver->lastStatusCode, 1.2634 + sipcc::PeerConnectionImpl::kInvalidState); 1.2635 +} 1.2636 + 1.2637 +TEST_F(SignalingTest, SetRemoteOfferInHaveLocalOffer) { 1.2638 + sipcc::MediaConstraints constraints; 1.2639 + CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2640 + a1_->SetLocal(TestObserver::OFFER, a1_->offer()); 1.2641 + ASSERT_EQ(a1_->pObserver->lastStatusCode, 1.2642 + sipcc::PeerConnectionImpl::kNoError); 1.2643 + 1.2644 + // The signaling state will remain "have-local-offer" because the 1.2645 + // SetRemoteDescription call fails. 1.2646 + a1_->SetRemote(TestObserver::OFFER, a1_->offer(), true, 1.2647 + PCImplSignalingState::SignalingHaveLocalOffer); 1.2648 + ASSERT_EQ(a1_->pObserver->lastStatusCode, 1.2649 + sipcc::PeerConnectionImpl::kInvalidState); 1.2650 +} 1.2651 + 1.2652 +TEST_F(SignalingTest, SetLocalOfferInHaveRemoteOffer) { 1.2653 + sipcc::MediaConstraints constraints; 1.2654 + CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2655 + a2_->SetRemote(TestObserver::OFFER, a1_->offer()); 1.2656 + ASSERT_EQ(a2_->pObserver->lastStatusCode, 1.2657 + sipcc::PeerConnectionImpl::kNoError); 1.2658 + 1.2659 + // The signaling state will remain "have-remote-offer" because the 1.2660 + // SetLocalDescription call fails. 1.2661 + a2_->SetLocal(TestObserver::OFFER, a1_->offer(), true, 1.2662 + PCImplSignalingState::SignalingHaveRemoteOffer); 1.2663 + ASSERT_EQ(a2_->pObserver->lastStatusCode, 1.2664 + sipcc::PeerConnectionImpl::kInvalidState); 1.2665 +} 1.2666 + 1.2667 +TEST_F(SignalingTest, SetRemoteAnswerInHaveRemoteOffer) { 1.2668 + sipcc::MediaConstraints constraints; 1.2669 + CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2670 + a2_->SetRemote(TestObserver::OFFER, a1_->offer()); 1.2671 + ASSERT_EQ(a2_->pObserver->lastStatusCode, 1.2672 + sipcc::PeerConnectionImpl::kNoError); 1.2673 + 1.2674 + // The signaling state will remain "have-remote-offer" because the 1.2675 + // SetRemoteDescription call fails. 1.2676 + a2_->SetRemote(TestObserver::ANSWER, a1_->offer(), true, 1.2677 + PCImplSignalingState::SignalingHaveRemoteOffer); 1.2678 + ASSERT_EQ(a2_->pObserver->lastStatusCode, 1.2679 + sipcc::PeerConnectionImpl::kInvalidState); 1.2680 +} 1.2681 + 1.2682 +// Disabled until the spec adds a failure callback to addStream 1.2683 +TEST_F(SignalingTest, DISABLED_AddStreamInHaveLocalOffer) { 1.2684 + sipcc::MediaConstraints constraints; 1.2685 + CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2686 + a1_->SetLocal(TestObserver::OFFER, a1_->offer()); 1.2687 + ASSERT_EQ(a1_->pObserver->lastStatusCode, 1.2688 + sipcc::PeerConnectionImpl::kNoError); 1.2689 + a1_->AddStream(); 1.2690 + ASSERT_EQ(a1_->pObserver->lastStatusCode, 1.2691 + sipcc::PeerConnectionImpl::kInvalidState); 1.2692 +} 1.2693 + 1.2694 +// Disabled until the spec adds a failure callback to removeStream 1.2695 +TEST_F(SignalingTest, DISABLED_RemoveStreamInHaveLocalOffer) { 1.2696 + sipcc::MediaConstraints constraints; 1.2697 + CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2698 + a1_->SetLocal(TestObserver::OFFER, a1_->offer()); 1.2699 + ASSERT_EQ(a1_->pObserver->lastStatusCode, 1.2700 + sipcc::PeerConnectionImpl::kNoError); 1.2701 + a1_->RemoveLastStreamAdded(); 1.2702 + ASSERT_EQ(a1_->pObserver->lastStatusCode, 1.2703 + sipcc::PeerConnectionImpl::kInvalidState); 1.2704 +} 1.2705 + 1.2706 +TEST_F(SignalingTest, AddCandidateInHaveLocalOffer) { 1.2707 + sipcc::MediaConstraints constraints; 1.2708 + CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2709 + a1_->SetLocal(TestObserver::OFFER, a1_->offer()); 1.2710 + ASSERT_EQ(a1_->pObserver->lastStatusCode, 1.2711 + sipcc::PeerConnectionImpl::kNoError); 1.2712 + a1_->AddIceCandidate(strSampleCandidate.c_str(), 1.2713 + strSampleMid.c_str(), nSamplelevel, false); 1.2714 + ASSERT_EQ(a1_->pObserver->lastStatusCode, 1.2715 + sipcc::PeerConnectionImpl::kInvalidState); 1.2716 +} 1.2717 + 1.2718 +TEST_F(SignalingAgentTest, CreateOffer) { 1.2719 + CreateAgent(); 1.2720 + sipcc::MediaConstraints constraints; 1.2721 + agent(0)->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2722 + PR_Sleep(20000); 1.2723 +} 1.2724 + 1.2725 +TEST_F(SignalingAgentTest, CreateOfferTrickleTestServer) { 1.2726 + TestStunServer::GetInstance()->SetActive(false); 1.2727 + TestStunServer::GetInstance()->SetResponseAddr( 1.2728 + kBogusSrflxAddress, kBogusSrflxPort); 1.2729 + 1.2730 + CreateAgent( 1.2731 + TestStunServer::GetInstance()->addr(), 1.2732 + TestStunServer::GetInstance()->port(), 1.2733 + false); 1.2734 + 1.2735 + sipcc::MediaConstraints constraints; 1.2736 + agent(0)->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2737 + 1.2738 + // Verify that the bogus addr is not there. 1.2739 + ASSERT_FALSE(agent(0)->OfferContains(kBogusSrflxAddress)); 1.2740 + 1.2741 + // Now enable the STUN server. 1.2742 + TestStunServer::GetInstance()->SetActive(true); 1.2743 + agent(0)->WaitForGather(); 1.2744 + 1.2745 + // There shouldn't be any candidates until SetLocal. 1.2746 + ASSERT_EQ(0U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); 1.2747 + 1.2748 + // Verify that the candidates appear in the offer. 1.2749 + size_t match; 1.2750 + match = agent(0)->getLocalDescription().find(kBogusSrflxAddress); 1.2751 + ASSERT_LT(0U, match); 1.2752 +} 1.2753 + 1.2754 +TEST_F(SignalingAgentTest, CreateOfferSetLocalTrickleTestServer) { 1.2755 + TestStunServer::GetInstance()->SetActive(false); 1.2756 + TestStunServer::GetInstance()->SetResponseAddr( 1.2757 + kBogusSrflxAddress, kBogusSrflxPort); 1.2758 + 1.2759 + CreateAgent( 1.2760 + TestStunServer::GetInstance()->addr(), 1.2761 + TestStunServer::GetInstance()->port(), 1.2762 + false); 1.2763 + 1.2764 + sipcc::MediaConstraints constraints; 1.2765 + agent(0)->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2766 + 1.2767 + // Verify that the bogus addr is not there. 1.2768 + ASSERT_FALSE(agent(0)->OfferContains(kBogusSrflxAddress)); 1.2769 + 1.2770 + // Now enable the STUN server. 1.2771 + TestStunServer::GetInstance()->SetActive(true); 1.2772 + agent(0)->WaitForGather(); 1.2773 + 1.2774 + // There shouldn't be any candidates until SetLocal. 1.2775 + ASSERT_EQ(0U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); 1.2776 + 1.2777 + agent(0)->SetLocal(TestObserver::OFFER, agent(0)->offer()); 1.2778 + PR_Sleep(1000); // Give time for the message queues. 1.2779 + 1.2780 + // Verify that we got our candidates. 1.2781 + ASSERT_LE(2U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); 1.2782 + 1.2783 + // Verify that the candidates appear in the offer. 1.2784 + size_t match; 1.2785 + match = agent(0)->getLocalDescription().find(kBogusSrflxAddress); 1.2786 + ASSERT_LT(0U, match); 1.2787 +} 1.2788 + 1.2789 + 1.2790 +TEST_F(SignalingAgentTest, CreateAnswerSetLocalTrickleTestServer) { 1.2791 + TestStunServer::GetInstance()->SetActive(false); 1.2792 + TestStunServer::GetInstance()->SetResponseAddr( 1.2793 + kBogusSrflxAddress, kBogusSrflxPort); 1.2794 + 1.2795 + CreateAgent( 1.2796 + TestStunServer::GetInstance()->addr(), 1.2797 + TestStunServer::GetInstance()->port(), 1.2798 + false); 1.2799 + 1.2800 + std::string offer(strG711SdpOffer); 1.2801 + agent(0)->SetRemote(TestObserver::OFFER, offer, true, 1.2802 + PCImplSignalingState::SignalingHaveRemoteOffer); 1.2803 + ASSERT_EQ(agent(0)->pObserver->lastStatusCode, 1.2804 + sipcc::PeerConnectionImpl::kNoError); 1.2805 + 1.2806 + sipcc::MediaConstraints constraints; 1.2807 + agent(0)->CreateAnswer(constraints, offer, ANSWER_AUDIO, DONT_CHECK_AUDIO); 1.2808 + 1.2809 + // Verify that the bogus addr is not there. 1.2810 + ASSERT_FALSE(agent(0)->AnswerContains(kBogusSrflxAddress)); 1.2811 + 1.2812 + // Now enable the STUN server. 1.2813 + TestStunServer::GetInstance()->SetActive(true); 1.2814 + agent(0)->WaitForGather(); 1.2815 + 1.2816 + // There shouldn't be any candidates until SetLocal. 1.2817 + ASSERT_EQ(0U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); 1.2818 + 1.2819 + agent(0)->SetLocal(TestObserver::ANSWER, agent(0)->answer()); 1.2820 + PR_Sleep(1000); // Give time for the message queues. 1.2821 + 1.2822 + // Verify that we got our candidates. 1.2823 + ASSERT_LE(2U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); 1.2824 + 1.2825 + // Verify that the candidates appear in the answer. 1.2826 + size_t match; 1.2827 + match = agent(0)->getLocalDescription().find(kBogusSrflxAddress); 1.2828 + ASSERT_LT(0U, match); 1.2829 +} 1.2830 + 1.2831 + 1.2832 + 1.2833 +TEST_F(SignalingAgentTest, CreateUntilFailThenWait) { 1.2834 + int i; 1.2835 + 1.2836 + for (i=0; ; i++) { 1.2837 + if (!CreateAgent()) 1.2838 + break; 1.2839 + std::cerr << "Created agent " << i << std::endl; 1.2840 + } 1.2841 + std::cerr << "Failed after creating " << i << " PCs " << std::endl; 1.2842 + PR_Sleep(10000); // Wait to see if we crash 1.2843 +} 1.2844 + 1.2845 +// Test for bug 856433. 1.2846 +TEST_F(SignalingAgentTest, CreateNoInit) { 1.2847 + CreateAgentNoInit(); 1.2848 +} 1.2849 + 1.2850 + 1.2851 +/* 1.2852 + * Test for Bug 843595 1.2853 + */ 1.2854 +TEST_F(SignalingTest, missingUfrag) 1.2855 +{ 1.2856 + EnsureInit(); 1.2857 + 1.2858 + sipcc::MediaConstraints constraints; 1.2859 + std::string offer = 1.2860 + "v=0\r\n" 1.2861 + "o=Mozilla-SIPUA 2208 0 IN IP4 0.0.0.0\r\n" 1.2862 + "s=SIP Call\r\n" 1.2863 + "t=0 0\r\n" 1.2864 + "a=ice-pwd:4450d5a4a5f097855c16fa079893be18\r\n" 1.2865 + "a=fingerprint:sha-256 23:9A:2E:43:94:42:CF:46:68:FC:62:F9:F4:48:61:DB:" 1.2866 + "2F:8C:C9:FF:6B:25:54:9D:41:09:EF:83:A8:19:FC:B6\r\n" 1.2867 + "m=audio 56187 RTP/SAVPF 109 0 8 101\r\n" 1.2868 + "c=IN IP4 77.9.79.167\r\n" 1.2869 + "a=rtpmap:109 opus/48000/2\r\n" 1.2870 + "a=ptime:20\r\n" 1.2871 + "a=rtpmap:0 PCMU/8000\r\n" 1.2872 + "a=rtpmap:8 PCMA/8000\r\n" 1.2873 + "a=rtpmap:101 telephone-event/8000\r\n" 1.2874 + "a=fmtp:101 0-15\r\n" 1.2875 + "a=sendrecv\r\n" 1.2876 + "a=candidate:0 1 UDP 2113601791 192.168.178.20 56187 typ host\r\n" 1.2877 + "a=candidate:1 1 UDP 1694236671 77.9.79.167 56187 typ srflx raddr " 1.2878 + "192.168.178.20 rport 56187\r\n" 1.2879 + "a=candidate:0 2 UDP 2113601790 192.168.178.20 52955 typ host\r\n" 1.2880 + "a=candidate:1 2 UDP 1694236670 77.9.79.167 52955 typ srflx raddr " 1.2881 + "192.168.178.20 rport 52955\r\n" 1.2882 + "m=video 49929 RTP/SAVPF 120\r\n" 1.2883 + "c=IN IP4 77.9.79.167\r\n" 1.2884 + "a=rtpmap:120 VP8/90000\r\n" 1.2885 + "a=recvonly\r\n" 1.2886 + "a=candidate:0 1 UDP 2113601791 192.168.178.20 49929 typ host\r\n" 1.2887 + "a=candidate:1 1 UDP 1694236671 77.9.79.167 49929 typ srflx raddr " 1.2888 + "192.168.178.20 rport 49929\r\n" 1.2889 + "a=candidate:0 2 UDP 2113601790 192.168.178.20 50769 typ host\r\n" 1.2890 + "a=candidate:1 2 UDP 1694236670 77.9.79.167 50769 typ srflx raddr " 1.2891 + "192.168.178.20 rport 50769\r\n" 1.2892 + "m=application 54054 DTLS/SCTP 5000\r\n" 1.2893 + "c=IN IP4 77.9.79.167\r\n" 1.2894 + "a=fmtp:HuRUu]Dtcl\\zM,7(OmEU%O$gU]x/z\tD protocol=webrtc-datachannel;" 1.2895 + "streams=16\r\n" 1.2896 + "a=sendrecv\r\n"; 1.2897 + 1.2898 + // Need to create an offer, since that's currently required by our 1.2899 + // FSM. This may change in the future. 1.2900 + a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); 1.2901 + a1_->SetLocal(TestObserver::OFFER, offer, true); 1.2902 + // We now detect the missing ICE parameters at SetRemoteDescription 1.2903 + a2_->SetRemote(TestObserver::OFFER, offer, true, 1.2904 + PCImplSignalingState::SignalingStable); 1.2905 + ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateError); 1.2906 +} 1.2907 + 1.2908 +TEST_F(SignalingTest, AudioOnlyCalleeNoRtcpMux) 1.2909 +{ 1.2910 + EnsureInit(); 1.2911 + 1.2912 + sipcc::MediaConstraints constraints; 1.2913 + 1.2914 + a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.2915 + a1_->SetLocal(TestObserver::OFFER, a1_->offer(), false); 1.2916 + ParsedSDP sdpWrapper(a1_->offer()); 1.2917 + sdpWrapper.DeleteLine("a=rtcp-mux"); 1.2918 + std::cout << "Modified SDP " << std::endl 1.2919 + << indent(sdpWrapper.getSdp()) << std::endl; 1.2920 + a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp(), false); 1.2921 + a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), 1.2922 + OFFER_AUDIO | ANSWER_AUDIO); 1.2923 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false); 1.2924 + a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false); 1.2925 + 1.2926 + // Answer should not have a=rtcp-mux 1.2927 + ASSERT_EQ(a2_->getLocalDescription().find("\r\na=rtcp-mux"), 1.2928 + std::string::npos); 1.2929 + 1.2930 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.2931 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.2932 + 1.2933 + // Wait for some data to get written 1.2934 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.2935 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.2936 + 1.2937 + a1_->CloseSendStreams(); 1.2938 + a2_->CloseReceiveStreams(); 1.2939 + 1.2940 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.2941 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.2942 + 1.2943 + // Check the low-level media pipeline 1.2944 + // for RTP and RTCP flows 1.2945 + // The first Local pipeline gets stored at 0 1.2946 + a1_->CheckMediaPipeline(0, 0, PIPELINE_LOCAL | PIPELINE_SEND); 1.2947 + 1.2948 + // The first Remote pipeline gets stored at 1 1.2949 + a2_->CheckMediaPipeline(0, 1, 0); 1.2950 +} 1.2951 + 1.2952 +TEST_F(SignalingTest, FullCallAudioNoMuxVideoMux) 1.2953 +{ 1.2954 + EnsureInit(); 1.2955 + 1.2956 + sipcc::MediaConstraints constraints; 1.2957 + 1.2958 + a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); 1.2959 + a1_->SetLocal(TestObserver::OFFER, a1_->offer(), false); 1.2960 + ParsedSDP sdpWrapper(a1_->offer()); 1.2961 + sdpWrapper.DeleteLine("a=rtcp-mux"); 1.2962 + std::cout << "Modified SDP " << std::endl 1.2963 + << indent(sdpWrapper.getSdp()) << std::endl; 1.2964 + a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp(), false); 1.2965 + a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), OFFER_AV | ANSWER_AV); 1.2966 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false); 1.2967 + a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false); 1.2968 + 1.2969 + // Answer should have only one a=rtcp-mux line 1.2970 + size_t match = a2_->getLocalDescription().find("\r\na=rtcp-mux"); 1.2971 + if (fRtcpMux) { 1.2972 + ASSERT_NE(match, std::string::npos); 1.2973 + match = a2_->getLocalDescription().find("\r\na=rtcp-mux", match + 1); 1.2974 + } 1.2975 + ASSERT_EQ(match, std::string::npos); 1.2976 + 1.2977 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.2978 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.2979 + 1.2980 + // Wait for some data to get written 1.2981 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.2982 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.2983 + 1.2984 + a1_->CloseSendStreams(); 1.2985 + a2_->CloseReceiveStreams(); 1.2986 + 1.2987 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.2988 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.2989 + 1.2990 + // Check the low-level media pipeline 1.2991 + // for RTP and RTCP flows 1.2992 + // The first Local pipeline gets stored at 0 1.2993 + a1_->CheckMediaPipeline(0, 0, PIPELINE_LOCAL | PIPELINE_SEND); 1.2994 + 1.2995 + // Now check video mux. 1.2996 + a1_->CheckMediaPipeline(0, 1, 1.2997 + PIPELINE_LOCAL | (fRtcpMux ? PIPELINE_RTCP_MUX : 0) | PIPELINE_SEND | 1.2998 + PIPELINE_VIDEO); 1.2999 + 1.3000 + // The first Remote pipeline gets stored at 1 1.3001 + a2_->CheckMediaPipeline(0, 1, 0); 1.3002 + 1.3003 + // Now check video mux. 1.3004 + a2_->CheckMediaPipeline(0, 2, (fRtcpMux ? PIPELINE_RTCP_MUX : 0) | 1.3005 + PIPELINE_VIDEO | PIPELINE_RTCP_NACK, VideoSessionConduit::FrameRequestPli); 1.3006 +} 1.3007 + 1.3008 +TEST_F(SignalingTest, RtcpFbInOffer) 1.3009 +{ 1.3010 + EnsureInit(); 1.3011 + sipcc::MediaConstraints constraints; 1.3012 + a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); 1.3013 + const char *expected[] = { "nack", "nack pli", "ccm fir" }; 1.3014 + CheckRtcpFbSdp(a1_->offer(), ARRAY_TO_SET(std::string, expected)); 1.3015 +} 1.3016 + 1.3017 +TEST_F(SignalingTest, RtcpFbInAnswer) 1.3018 +{ 1.3019 + const char *feedbackTypes[] = { "nack", "nack pli", "ccm fir" }; 1.3020 + TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), 1.3021 + PIPELINE_RTCP_NACK, 1.3022 + VideoSessionConduit::FrameRequestPli); 1.3023 +} 1.3024 + 1.3025 +TEST_F(SignalingTest, RtcpFbNoNackBasic) 1.3026 +{ 1.3027 + const char *feedbackTypes[] = { "nack pli", "ccm fir" }; 1.3028 + TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), 1.3029 + 0, 1.3030 + VideoSessionConduit::FrameRequestPli); 1.3031 +} 1.3032 + 1.3033 +TEST_F(SignalingTest, RtcpFbNoNackPli) 1.3034 +{ 1.3035 + const char *feedbackTypes[] = { "nack", "ccm fir" }; 1.3036 + TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), 1.3037 + PIPELINE_RTCP_NACK, 1.3038 + VideoSessionConduit::FrameRequestFir); 1.3039 +} 1.3040 + 1.3041 +TEST_F(SignalingTest, RtcpFbNoCcmFir) 1.3042 +{ 1.3043 + const char *feedbackTypes[] = { "nack", "nack pli" }; 1.3044 + TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), 1.3045 + PIPELINE_RTCP_NACK, 1.3046 + VideoSessionConduit::FrameRequestPli); 1.3047 +} 1.3048 + 1.3049 +TEST_F(SignalingTest, RtcpFbNoNack) 1.3050 +{ 1.3051 + const char *feedbackTypes[] = { "ccm fir" }; 1.3052 + TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), 1.3053 + 0, 1.3054 + VideoSessionConduit::FrameRequestFir); 1.3055 +} 1.3056 + 1.3057 +TEST_F(SignalingTest, RtcpFbNoFrameRequest) 1.3058 +{ 1.3059 + const char *feedbackTypes[] = { "nack" }; 1.3060 + TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), 1.3061 + PIPELINE_RTCP_NACK, 1.3062 + VideoSessionConduit::FrameRequestNone); 1.3063 +} 1.3064 + 1.3065 +TEST_F(SignalingTest, RtcpFbPliOnly) 1.3066 +{ 1.3067 + const char *feedbackTypes[] = { "nack pli" }; 1.3068 + TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), 1.3069 + 0, 1.3070 + VideoSessionConduit::FrameRequestPli); 1.3071 +} 1.3072 + 1.3073 +TEST_F(SignalingTest, RtcpFbNoFeedback) 1.3074 +{ 1.3075 + const char *feedbackTypes[] = { }; 1.3076 + TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), 1.3077 + 0, 1.3078 + VideoSessionConduit::FrameRequestNone); 1.3079 +} 1.3080 + 1.3081 +// In this test we will change the offer SDP's a=setup value 1.3082 +// from actpass to passive. This will make the answer do active. 1.3083 +TEST_F(SignalingTest, AudioCallForceDtlsRoles) 1.3084 +{ 1.3085 + EnsureInit(); 1.3086 + 1.3087 + sipcc::MediaConstraints constraints; 1.3088 + size_t match; 1.3089 + 1.3090 + a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.3091 + 1.3092 + // By default the offer should give actpass 1.3093 + std::string offer(a1_->offer()); 1.3094 + match = offer.find("\r\na=setup:actpass"); 1.3095 + ASSERT_NE(match, std::string::npos); 1.3096 + // Now replace the actpass with passive so that the answer will 1.3097 + // return active 1.3098 + offer.replace(match, strlen("\r\na=setup:actpass"), 1.3099 + "\r\na=setup:passive"); 1.3100 + std::cout << "Modified SDP " << std::endl 1.3101 + << indent(offer) << std::endl; 1.3102 + 1.3103 + a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false); 1.3104 + a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false); 1.3105 + a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO); 1.3106 + 1.3107 + // Now the answer should contain a=setup:active 1.3108 + std::string answer(a2_->answer()); 1.3109 + match = answer.find("\r\na=setup:active"); 1.3110 + ASSERT_NE(match, std::string::npos); 1.3111 + 1.3112 + // This should setup the DTLS with the same roles 1.3113 + // as the regular tests above. 1.3114 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false); 1.3115 + a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false); 1.3116 + 1.3117 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.3118 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.3119 + 1.3120 + // Wait for some data to get written 1.3121 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.3122 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.3123 + 1.3124 + a1_->CloseSendStreams(); 1.3125 + a2_->CloseReceiveStreams(); 1.3126 + 1.3127 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.3128 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.3129 +} 1.3130 + 1.3131 +// In this test we will change the offer SDP's a=setup value 1.3132 +// from actpass to active. This will make the answer do passive 1.3133 +TEST_F(SignalingTest, AudioCallReverseDtlsRoles) 1.3134 +{ 1.3135 + EnsureInit(); 1.3136 + 1.3137 + sipcc::MediaConstraints constraints; 1.3138 + size_t match; 1.3139 + 1.3140 + a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.3141 + 1.3142 + // By default the offer should give actpass 1.3143 + std::string offer(a1_->offer()); 1.3144 + match = offer.find("\r\na=setup:actpass"); 1.3145 + ASSERT_NE(match, std::string::npos); 1.3146 + // Now replace the actpass with active so that the answer will 1.3147 + // return passive 1.3148 + offer.replace(match, strlen("\r\na=setup:actpass"), 1.3149 + "\r\na=setup:active"); 1.3150 + std::cout << "Modified SDP " << std::endl 1.3151 + << indent(offer) << std::endl; 1.3152 + 1.3153 + a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false); 1.3154 + a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false); 1.3155 + a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO); 1.3156 + 1.3157 + // Now the answer should contain a=setup:passive 1.3158 + std::string answer(a2_->answer()); 1.3159 + match = answer.find("\r\na=setup:passive"); 1.3160 + ASSERT_NE(match, std::string::npos); 1.3161 + 1.3162 + // This should setup the DTLS with the opposite roles 1.3163 + // than the regular tests above. 1.3164 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false); 1.3165 + a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false); 1.3166 + 1.3167 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.3168 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.3169 + 1.3170 + // Wait for some data to get written 1.3171 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.3172 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.3173 + 1.3174 + a1_->CloseSendStreams(); 1.3175 + a2_->CloseReceiveStreams(); 1.3176 + 1.3177 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.3178 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.3179 +} 1.3180 + 1.3181 +// In this test we will change the answer SDP's a=setup value 1.3182 +// from active to passive. This will make both sides do 1.3183 +// active and should not connect. 1.3184 +TEST_F(SignalingTest, AudioCallMismatchDtlsRoles) 1.3185 +{ 1.3186 + EnsureInit(); 1.3187 + 1.3188 + sipcc::MediaConstraints constraints; 1.3189 + size_t match; 1.3190 + 1.3191 + a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.3192 + 1.3193 + // By default the offer should give actpass 1.3194 + std::string offer(a1_->offer()); 1.3195 + match = offer.find("\r\na=setup:actpass"); 1.3196 + ASSERT_NE(match, std::string::npos); 1.3197 + a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false); 1.3198 + a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false); 1.3199 + a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO); 1.3200 + 1.3201 + // Now the answer should contain a=setup:active 1.3202 + std::string answer(a2_->answer()); 1.3203 + match = answer.find("\r\na=setup:active"); 1.3204 + ASSERT_NE(match, std::string::npos); 1.3205 + 1.3206 + // Now replace the active with passive so that the offerer will 1.3207 + // also do active. 1.3208 + answer.replace(match, strlen("\r\na=setup:active"), 1.3209 + "\r\na=setup:passive"); 1.3210 + std::cout << "Modified SDP " << std::endl 1.3211 + << indent(answer) << std::endl; 1.3212 + 1.3213 + // This should setup the DTLS with both sides playing active 1.3214 + a2_->SetLocal(TestObserver::ANSWER, answer.c_str(), false); 1.3215 + a1_->SetRemote(TestObserver::ANSWER, answer.c_str(), false); 1.3216 + 1.3217 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.3218 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.3219 + 1.3220 + // Not using ASSERT_TRUE_WAIT here because we expect failure 1.3221 + PR_Sleep(kDefaultTimeout * 2); // Wait for some data to get written 1.3222 + 1.3223 + a1_->CloseSendStreams(); 1.3224 + a2_->CloseReceiveStreams(); 1.3225 + 1.3226 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.3227 + // In this case we should receive nothing. 1.3228 + ASSERT_EQ(a2_->GetPacketsReceived(0), 0); 1.3229 +} 1.3230 + 1.3231 +// In this test we will change the offer SDP's a=setup value 1.3232 +// from actpass to garbage. It should ignore the garbage value 1.3233 +// and respond with setup:active 1.3234 +TEST_F(SignalingTest, AudioCallGarbageSetup) 1.3235 +{ 1.3236 + EnsureInit(); 1.3237 + 1.3238 + sipcc::MediaConstraints constraints; 1.3239 + size_t match; 1.3240 + 1.3241 + a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.3242 + 1.3243 + // By default the offer should give actpass 1.3244 + std::string offer(a1_->offer()); 1.3245 + match = offer.find("\r\na=setup:actpass"); 1.3246 + ASSERT_NE(match, std::string::npos); 1.3247 + // Now replace the actpass with a garbage value 1.3248 + offer.replace(match, strlen("\r\na=setup:actpass"), 1.3249 + "\r\na=setup:G4rb4g3V4lu3"); 1.3250 + std::cout << "Modified SDP " << std::endl 1.3251 + << indent(offer) << std::endl; 1.3252 + 1.3253 + a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false); 1.3254 + a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false); 1.3255 + a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO); 1.3256 + 1.3257 + // Now the answer should contain a=setup:active 1.3258 + std::string answer(a2_->answer()); 1.3259 + match = answer.find("\r\na=setup:active"); 1.3260 + ASSERT_NE(match, std::string::npos); 1.3261 + 1.3262 + // This should setup the DTLS with the same roles 1.3263 + // as the regular tests above. 1.3264 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false); 1.3265 + a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false); 1.3266 + 1.3267 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.3268 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.3269 + 1.3270 + // Wait for some data to get written 1.3271 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.3272 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.3273 + 1.3274 + a1_->CloseSendStreams(); 1.3275 + a2_->CloseReceiveStreams(); 1.3276 + 1.3277 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.3278 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.3279 +} 1.3280 + 1.3281 +// In this test we will change the offer SDP to remove the 1.3282 +// a=setup line. Answer should respond with a=setup:active. 1.3283 +TEST_F(SignalingTest, AudioCallOfferNoSetupOrConnection) 1.3284 +{ 1.3285 + EnsureInit(); 1.3286 + 1.3287 + sipcc::MediaConstraints constraints; 1.3288 + size_t match; 1.3289 + 1.3290 + a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.3291 + 1.3292 + // By default the offer should give setup:actpass 1.3293 + std::string offer(a1_->offer()); 1.3294 + match = offer.find("\r\na=setup:actpass"); 1.3295 + ASSERT_NE(match, std::string::npos); 1.3296 + // Remove the a=setup line 1.3297 + offer.replace(match, strlen("\r\na=setup:actpass"), ""); 1.3298 + std::cout << "Modified SDP " << std::endl 1.3299 + << indent(offer) << std::endl; 1.3300 + 1.3301 + a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false); 1.3302 + a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false); 1.3303 + a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO); 1.3304 + 1.3305 + // Now the answer should contain a=setup:active 1.3306 + std::string answer(a2_->answer()); 1.3307 + match = answer.find("\r\na=setup:active"); 1.3308 + ASSERT_NE(match, std::string::npos); 1.3309 + 1.3310 + // This should setup the DTLS with the same roles 1.3311 + // as the regular tests above. 1.3312 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false); 1.3313 + a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false); 1.3314 + 1.3315 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.3316 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.3317 + 1.3318 + // Wait for some data to get written 1.3319 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.3320 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.3321 + 1.3322 + a1_->CloseSendStreams(); 1.3323 + a2_->CloseReceiveStreams(); 1.3324 + 1.3325 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.3326 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.3327 +} 1.3328 + 1.3329 +// In this test we will change the answer SDP to remove the 1.3330 +// a=setup line. ICE should still connect since active will 1.3331 +// be assumed. 1.3332 +TEST_F(SignalingTest, AudioCallAnswerNoSetupOrConnection) 1.3333 +{ 1.3334 + EnsureInit(); 1.3335 + 1.3336 + sipcc::MediaConstraints constraints; 1.3337 + size_t match; 1.3338 + 1.3339 + a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); 1.3340 + 1.3341 + // By default the offer should give setup:actpass 1.3342 + std::string offer(a1_->offer()); 1.3343 + match = offer.find("\r\na=setup:actpass"); 1.3344 + ASSERT_NE(match, std::string::npos); 1.3345 + 1.3346 + a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false); 1.3347 + a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false); 1.3348 + a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO); 1.3349 + 1.3350 + // Now the answer should contain a=setup:active 1.3351 + std::string answer(a2_->answer()); 1.3352 + match = answer.find("\r\na=setup:active"); 1.3353 + ASSERT_NE(match, std::string::npos); 1.3354 + // Remove the a=setup line 1.3355 + answer.replace(match, strlen("\r\na=setup:active"), ""); 1.3356 + std::cout << "Modified SDP " << std::endl 1.3357 + << indent(answer) << std::endl; 1.3358 + 1.3359 + // This should setup the DTLS with the same roles 1.3360 + // as the regular tests above. 1.3361 + a2_->SetLocal(TestObserver::ANSWER, answer, false); 1.3362 + a1_->SetRemote(TestObserver::ANSWER, answer, false); 1.3363 + 1.3364 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.3365 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.3366 + 1.3367 + // Wait for some data to get written 1.3368 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.3369 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.3370 + 1.3371 + a1_->CloseSendStreams(); 1.3372 + a2_->CloseReceiveStreams(); 1.3373 + 1.3374 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.3375 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.3376 +} 1.3377 + 1.3378 + 1.3379 +TEST_F(SignalingTest, FullCallRealTrickle) 1.3380 +{ 1.3381 + wait_for_gather_ = false; 1.3382 + 1.3383 + sipcc::MediaConstraints constraints; 1.3384 + OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, 1.3385 + true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); 1.3386 + 1.3387 + // Wait for some data to get written 1.3388 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.3389 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.3390 + 1.3391 + a1_->CloseSendStreams(); 1.3392 + a2_->CloseReceiveStreams(); 1.3393 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.3394 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.3395 +} 1.3396 + 1.3397 +TEST_F(SignalingTest, FullCallRealTrickleTestServer) 1.3398 +{ 1.3399 + wait_for_gather_ = false; 1.3400 + SetTestStunServer(); 1.3401 + 1.3402 + sipcc::MediaConstraints constraints; 1.3403 + OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, 1.3404 + true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); 1.3405 + 1.3406 + TestStunServer::GetInstance()->SetActive(true); 1.3407 + 1.3408 + // Wait for some data to get written 1.3409 + ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && 1.3410 + a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); 1.3411 + 1.3412 + a1_->CloseSendStreams(); 1.3413 + a2_->CloseReceiveStreams(); 1.3414 + ASSERT_GE(a1_->GetPacketsSent(0), 40); 1.3415 + ASSERT_GE(a2_->GetPacketsReceived(0), 40); 1.3416 +} 1.3417 + 1.3418 +TEST_F(SignalingTest, hugeSdp) 1.3419 +{ 1.3420 + EnsureInit(); 1.3421 + 1.3422 + sipcc::MediaConstraints constraints; 1.3423 + std::string offer = 1.3424 + "v=0\r\n" 1.3425 + "o=- 1109973417102828257 2 IN IP4 127.0.0.1\r\n" 1.3426 + "s=-\r\n" 1.3427 + "t=0 0\r\n" 1.3428 + "a=group:BUNDLE audio video\r\n" 1.3429 + "a=msid-semantic: WMS 1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n" 1.3430 + "m=audio 32952 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126\r\n" 1.3431 + "c=IN IP4 128.64.32.16\r\n" 1.3432 + "a=rtcp:32952 IN IP4 128.64.32.16\r\n" 1.3433 + "a=candidate:77142221 1 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n" 1.3434 + "a=candidate:77142221 2 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n" 1.3435 + "a=candidate:983072742 1 udp 2113937151 172.22.0.56 54082 typ host generation 0\r\n" 1.3436 + "a=candidate:983072742 2 udp 2113937151 172.22.0.56 54082 typ host generation 0\r\n" 1.3437 + "a=candidate:2245074553 1 udp 1845501695 32.64.128.1 62397 typ srflx raddr 192.168.137.1 rport 54081 generation 0\r\n" 1.3438 + "a=candidate:2245074553 2 udp 1845501695 32.64.128.1 62397 typ srflx raddr 192.168.137.1 rport 54081 generation 0\r\n" 1.3439 + "a=candidate:2479353907 1 udp 1845501695 32.64.128.1 54082 typ srflx raddr 172.22.0.56 rport 54082 generation 0\r\n" 1.3440 + "a=candidate:2479353907 2 udp 1845501695 32.64.128.1 54082 typ srflx raddr 172.22.0.56 rport 54082 generation 0\r\n" 1.3441 + "a=candidate:1243276349 1 tcp 1509957375 192.168.137.1 0 typ host generation 0\r\n" 1.3442 + "a=candidate:1243276349 2 tcp 1509957375 192.168.137.1 0 typ host generation 0\r\n" 1.3443 + "a=candidate:1947960086 1 tcp 1509957375 172.22.0.56 0 typ host generation 0\r\n" 1.3444 + "a=candidate:1947960086 2 tcp 1509957375 172.22.0.56 0 typ host generation 0\r\n" 1.3445 + "a=candidate:1808221584 1 udp 33562367 128.64.32.16 32952 typ relay raddr 32.64.128.1 rport 62398 generation 0\r\n" 1.3446 + "a=candidate:1808221584 2 udp 33562367 128.64.32.16 32952 typ relay raddr 32.64.128.1 rport 62398 generation 0\r\n" 1.3447 + "a=candidate:507872740 1 udp 33562367 128.64.32.16 40975 typ relay raddr 32.64.128.1 rport 54085 generation 0\r\n" 1.3448 + "a=candidate:507872740 2 udp 33562367 128.64.32.16 40975 typ relay raddr 32.64.128.1 rport 54085 generation 0\r\n" 1.3449 + "a=ice-ufrag:xQuJwjX3V3eMA81k\r\n" 1.3450 + "a=ice-pwd:ZUiRmjS2GDhG140p73dAsSVP\r\n" 1.3451 + "a=ice-options:google-ice\r\n" 1.3452 + "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" 1.3453 + "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" 1.3454 + "a=sendrecv\r\n" 1.3455 + "a=mid:audio\r\n" 1.3456 + "a=rtcp-mux\r\n" 1.3457 + "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:/U44g3ULdtapeiSg+T3n6dDLBKIjpOhb/NXAL/2b\r\n" 1.3458 + "a=rtpmap:111 opus/48000/2\r\n" 1.3459 + "a=fmtp:111 minptime=10\r\n" 1.3460 + "a=rtpmap:103 ISAC/16000\r\n" 1.3461 + "a=rtpmap:104 ISAC/32000\r\n" 1.3462 + "a=rtpmap:0 PCMU/8000\r\n" 1.3463 + "a=rtpmap:8 PCMA/8000\r\n" 1.3464 + "a=rtpmap:107 CN/48000\r\n" 1.3465 + "a=rtpmap:106 CN/32000\r\n" 1.3466 + "a=rtpmap:105 CN/16000\r\n" 1.3467 + "a=rtpmap:13 CN/8000\r\n" 1.3468 + "a=rtpmap:126 telephone-event/8000\r\n" 1.3469 + "a=maxptime:60\r\n" 1.3470 + "a=ssrc:2271517329 cname:mKDNt7SQf6pwDlIn\r\n" 1.3471 + "a=ssrc:2271517329 msid:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP 1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPa0\r\n" 1.3472 + "a=ssrc:2271517329 mslabel:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n" 1.3473 + "a=ssrc:2271517329 label:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPa0\r\n" 1.3474 + "m=video 32952 RTP/SAVPF 100 116 117\r\n" 1.3475 + "c=IN IP4 128.64.32.16\r\n" 1.3476 + "a=rtcp:32952 IN IP4 128.64.32.16\r\n" 1.3477 + "a=candidate:77142221 1 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n" 1.3478 + "a=candidate:77142221 2 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n" 1.3479 + "a=candidate:983072742 1 udp 2113937151 172.22.0.56 54082 typ host generation 0\r\n" 1.3480 + "a=candidate:983072742 2 udp 2113937151 172.22.0.56 54082 typ host generation 0\r\n" 1.3481 + "a=candidate:2245074553 1 udp 1845501695 32.64.128.1 62397 typ srflx raddr 192.168.137.1 rport 54081 generation 0\r\n" 1.3482 + "a=candidate:2245074553 2 udp 1845501695 32.64.128.1 62397 typ srflx raddr 192.168.137.1 rport 54081 generation 0\r\n" 1.3483 + "a=candidate:2479353907 1 udp 1845501695 32.64.128.1 54082 typ srflx raddr 172.22.0.56 rport 54082 generation 0\r\n" 1.3484 + "a=candidate:2479353907 2 udp 1845501695 32.64.128.1 54082 typ srflx raddr 172.22.0.56 rport 54082 generation 0\r\n" 1.3485 + "a=candidate:1243276349 1 tcp 1509957375 192.168.137.1 0 typ host generation 0\r\n" 1.3486 + "a=candidate:1243276349 2 tcp 1509957375 192.168.137.1 0 typ host generation 0\r\n" 1.3487 + "a=candidate:1947960086 1 tcp 1509957375 172.22.0.56 0 typ host generation 0\r\n" 1.3488 + "a=candidate:1947960086 2 tcp 1509957375 172.22.0.56 0 typ host generation 0\r\n" 1.3489 + "a=candidate:1808221584 1 udp 33562367 128.64.32.16 32952 typ relay raddr 32.64.128.1 rport 62398 generation 0\r\n" 1.3490 + "a=candidate:1808221584 2 udp 33562367 128.64.32.16 32952 typ relay raddr 32.64.128.1 rport 62398 generation 0\r\n" 1.3491 + "a=candidate:507872740 1 udp 33562367 128.64.32.16 40975 typ relay raddr 32.64.128.1 rport 54085 generation 0\r\n" 1.3492 + "a=candidate:507872740 2 udp 33562367 128.64.32.16 40975 typ relay raddr 32.64.128.1 rport 54085 generation 0\r\n" 1.3493 + "a=ice-ufrag:xQuJwjX3V3eMA81k\r\n" 1.3494 + "a=ice-pwd:ZUiRmjS2GDhG140p73dAsSVP\r\n" 1.3495 + "a=ice-options:google-ice\r\n" 1.3496 + "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" 1.3497 + "a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\n" 1.3498 + "a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n" 1.3499 + "a=sendrecv\r\n" 1.3500 + "a=mid:video\r\n" 1.3501 + "a=rtcp-mux\r\n" 1.3502 + "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:/U44g3ULdtapeiSg+T3n6dDLBKIjpOhb/NXAL/2b\r\n" 1.3503 + "a=rtpmap:100 VP8/90000\r\n" 1.3504 + "a=rtcp-fb:100 ccm fir\r\n" 1.3505 + "a=rtcp-fb:100 nack\r\n" 1.3506 + "a=rtcp-fb:100 goog-remb\r\n" 1.3507 + "a=rtpmap:116 red/90000\r\n" 1.3508 + "a=rtpmap:117 ulpfec/90000\r\n" 1.3509 + "a=ssrc:54724160 cname:mKDNt7SQf6pwDlIn\r\n" 1.3510 + "a=ssrc:54724160 msid:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP 1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPv0\r\n" 1.3511 + "a=ssrc:54724160 mslabel:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n" 1.3512 + "a=ssrc:54724160 label:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPv0\r\n"; 1.3513 + 1.3514 + a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); 1.3515 + a1_->SetLocal(TestObserver::OFFER, offer, true); 1.3516 + 1.3517 + a2_->SetRemote(TestObserver::OFFER, offer, true); 1.3518 + ASSERT_GE(a2_->getRemoteDescription().length(), 4096U); 1.3519 + a2_->CreateAnswer(constraints, offer, OFFER_AV); 1.3520 +} 1.3521 + 1.3522 +// Test max_fs and max_fr prefs have proper impact on SDP offer 1.3523 +TEST_F(SignalingTest, MaxFsFrInOffer) 1.3524 +{ 1.3525 + EnsureInit(); 1.3526 + 1.3527 + sipcc::MediaConstraints constraints; 1.3528 + 1.3529 + nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); 1.3530 + ASSERT_TRUE(prefs); 1.3531 + FsFrPrefClearer prefClearer(prefs); 1.3532 + 1.3533 + SetMaxFsFr(prefs, 300, 30); 1.3534 + 1.3535 + a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); 1.3536 + 1.3537 + // Verify that SDP contains correct max-fs and max-fr 1.3538 + CheckMaxFsFrSdp(a1_->offer(), 120, 300, 30); 1.3539 +} 1.3540 + 1.3541 +// Test max_fs and max_fr prefs have proper impact on SDP answer 1.3542 +TEST_F(SignalingTest, MaxFsFrInAnswer) 1.3543 +{ 1.3544 + EnsureInit(); 1.3545 + 1.3546 + sipcc::MediaConstraints constraints; 1.3547 + 1.3548 + nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); 1.3549 + ASSERT_TRUE(prefs); 1.3550 + FsFrPrefClearer prefClearer(prefs); 1.3551 + 1.3552 + // We don't want max_fs and max_fr prefs impact SDP at this moment 1.3553 + SetMaxFsFr(prefs, 0, 0); 1.3554 + 1.3555 + a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); 1.3556 + 1.3557 + // SDP should not contain max-fs and max-fr here 1.3558 + CheckMaxFsFrSdp(a1_->offer(), 120, 0, 0); 1.3559 + 1.3560 + a2_->SetRemote(TestObserver::OFFER, a1_->offer()); 1.3561 + 1.3562 + SetMaxFsFr(prefs, 600, 60); 1.3563 + 1.3564 + a2_->CreateAnswer(constraints, a1_->offer(), OFFER_AV | ANSWER_AV); 1.3565 + 1.3566 + // Verify that SDP contains correct max-fs and max-fr 1.3567 + CheckMaxFsFrSdp(a2_->answer(), 120, 600, 60); 1.3568 +} 1.3569 + 1.3570 +// Test SDP offer has proper impact on callee's codec configuration 1.3571 +TEST_F(SignalingTest, MaxFsFrCalleeCodec) 1.3572 +{ 1.3573 + EnsureInit(); 1.3574 + 1.3575 + sipcc::MediaConstraints constraints; 1.3576 + 1.3577 + nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); 1.3578 + ASSERT_TRUE(prefs); 1.3579 + FsFrPrefClearer prefClearer(prefs); 1.3580 + 1.3581 + // We don't want max_fs and max_fr prefs impact SDP at this moment 1.3582 + SetMaxFsFr(prefs, 0, 0); 1.3583 + 1.3584 + a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); 1.3585 + 1.3586 + ParsedSDP sdpWrapper(a1_->offer()); 1.3587 + 1.3588 + sdpWrapper.ReplaceLine("a=rtpmap:120", 1.3589 + "a=rtpmap:120 VP8/90000\r\na=fmtp:120 max-fs=300;max-fr=30\r\n"); 1.3590 + 1.3591 + std::cout << "Modified SDP " << std::endl 1.3592 + << indent(sdpWrapper.getSdp()) << std::endl; 1.3593 + 1.3594 + // Double confirm that SDP offer contains correct max-fs and max-fr 1.3595 + CheckMaxFsFrSdp(sdpWrapper.getSdp(), 120, 300, 30); 1.3596 + 1.3597 + a1_->SetLocal(TestObserver::OFFER, sdpWrapper.getSdp()); 1.3598 + a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp()); 1.3599 + 1.3600 + a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), OFFER_AV | ANSWER_AV); 1.3601 + 1.3602 + // SDP should not contain max-fs and max-fr here 1.3603 + CheckMaxFsFrSdp(a2_->answer(), 120, 0, 0); 1.3604 + 1.3605 + a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); 1.3606 + a1_->SetRemote(TestObserver::ANSWER, a2_->answer()); 1.3607 + 1.3608 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.3609 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.3610 + 1.3611 + // Checking callee's video sending configuration does respect max-fs and 1.3612 + // max-fr in SDP offer. 1.3613 + mozilla::RefPtr<mozilla::MediaPipeline> pipeline = 1.3614 + a2_->GetMediaPipeline(1, 0, 1); 1.3615 + ASSERT_TRUE(pipeline); 1.3616 + mozilla::MediaSessionConduit *conduit = pipeline->Conduit(); 1.3617 + ASSERT_TRUE(conduit); 1.3618 + ASSERT_EQ(conduit->type(), mozilla::MediaSessionConduit::VIDEO); 1.3619 + mozilla::VideoSessionConduit *video_conduit = 1.3620 + static_cast<mozilla::VideoSessionConduit*>(conduit); 1.3621 + 1.3622 + ASSERT_EQ(video_conduit->SendingMaxFs(), (unsigned short) 300); 1.3623 + ASSERT_EQ(video_conduit->SendingMaxFr(), (unsigned short) 30); 1.3624 +} 1.3625 + 1.3626 +// Test SDP answer has proper impact on caller's codec configuration 1.3627 +TEST_F(SignalingTest, MaxFsFrCallerCodec) 1.3628 +{ 1.3629 + EnsureInit(); 1.3630 + 1.3631 + sipcc::MediaConstraints constraints; 1.3632 + 1.3633 + nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); 1.3634 + ASSERT_TRUE(prefs); 1.3635 + FsFrPrefClearer prefClearer(prefs); 1.3636 + 1.3637 + // We don't want max_fs and max_fr prefs impact SDP at this moment 1.3638 + SetMaxFsFr(prefs, 0, 0); 1.3639 + 1.3640 + a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); 1.3641 + a1_->SetLocal(TestObserver::OFFER, a1_->offer()); 1.3642 + a2_->SetRemote(TestObserver::OFFER, a1_->offer()); 1.3643 + 1.3644 + a2_->CreateAnswer(constraints, a1_->offer(), OFFER_AV | ANSWER_AV); 1.3645 + 1.3646 + ParsedSDP sdpWrapper(a2_->answer()); 1.3647 + 1.3648 + sdpWrapper.ReplaceLine("a=rtpmap:120", 1.3649 + "a=rtpmap:120 VP8/90000\r\na=fmtp:120 max-fs=600;max-fr=60\r\n"); 1.3650 + 1.3651 + std::cout << "Modified SDP " << std::endl 1.3652 + << indent(sdpWrapper.getSdp()) << std::endl; 1.3653 + 1.3654 + // Double confirm that SDP answer contains correct max-fs and max-fr 1.3655 + CheckMaxFsFrSdp(sdpWrapper.getSdp(), 120, 600, 60); 1.3656 + 1.3657 + a2_->SetLocal(TestObserver::ANSWER, sdpWrapper.getSdp()); 1.3658 + a1_->SetRemote(TestObserver::ANSWER, sdpWrapper.getSdp()); 1.3659 + 1.3660 + ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); 1.3661 + ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); 1.3662 + 1.3663 + // Checking caller's video sending configuration does respect max-fs and 1.3664 + // max-fr in SDP answer. 1.3665 + mozilla::RefPtr<mozilla::MediaPipeline> pipeline = 1.3666 + a1_->GetMediaPipeline(1, 0, 1); 1.3667 + ASSERT_TRUE(pipeline); 1.3668 + mozilla::MediaSessionConduit *conduit = pipeline->Conduit(); 1.3669 + ASSERT_TRUE(conduit); 1.3670 + ASSERT_EQ(conduit->type(), mozilla::MediaSessionConduit::VIDEO); 1.3671 + mozilla::VideoSessionConduit *video_conduit = 1.3672 + static_cast<mozilla::VideoSessionConduit*>(conduit); 1.3673 + 1.3674 + ASSERT_EQ(video_conduit->SendingMaxFs(), (unsigned short) 600); 1.3675 + ASSERT_EQ(video_conduit->SendingMaxFr(), (unsigned short) 60); 1.3676 +} 1.3677 + 1.3678 +} // End namespace test. 1.3679 + 1.3680 +bool is_color_terminal(const char *terminal) { 1.3681 + if (!terminal) { 1.3682 + return false; 1.3683 + } 1.3684 + const char *color_terms[] = { 1.3685 + "xterm", 1.3686 + "xterm-color", 1.3687 + "xterm-256color", 1.3688 + "screen", 1.3689 + "linux", 1.3690 + "cygwin", 1.3691 + 0 1.3692 + }; 1.3693 + const char **p = color_terms; 1.3694 + while (*p) { 1.3695 + if (!strcmp(terminal, *p)) { 1.3696 + return true; 1.3697 + } 1.3698 + p++; 1.3699 + } 1.3700 + return false; 1.3701 +} 1.3702 + 1.3703 +static std::string get_environment(const char *name) { 1.3704 + char *value = getenv(name); 1.3705 + 1.3706 + if (!value) 1.3707 + return ""; 1.3708 + 1.3709 + return value; 1.3710 +} 1.3711 + 1.3712 +// This exists to send as an event to trigger shutdown. 1.3713 +static void tests_complete() { 1.3714 + gTestsComplete = true; 1.3715 +} 1.3716 + 1.3717 +// The GTest thread runs this instead of the main thread so it can 1.3718 +// do things like ASSERT_TRUE_WAIT which you could not do on the main thread. 1.3719 +static int gtest_main(int argc, char **argv) { 1.3720 + MOZ_ASSERT(!NS_IsMainThread()); 1.3721 + 1.3722 + ::testing::InitGoogleTest(&argc, argv); 1.3723 + 1.3724 + for(int i=0; i<argc; i++) { 1.3725 + if (!strcmp(argv[i],"-t")) { 1.3726 + kDefaultTimeout = 20000; 1.3727 + } 1.3728 + } 1.3729 + 1.3730 + ::testing::AddGlobalTestEnvironment(new test::SignalingEnvironment); 1.3731 + int result = RUN_ALL_TESTS(); 1.3732 + 1.3733 + test_utils->sts_target()->Dispatch( 1.3734 + WrapRunnableNM(&TestStunServer::ShutdownInstance), NS_DISPATCH_SYNC); 1.3735 + 1.3736 + // Set the global shutdown flag and tickle the main thread 1.3737 + // The main thread did not go through Init() so calling Shutdown() 1.3738 + // on it will not work. 1.3739 + gMainThread->Dispatch(WrapRunnableNM(tests_complete), NS_DISPATCH_SYNC); 1.3740 + 1.3741 + return result; 1.3742 +} 1.3743 + 1.3744 + 1.3745 +int main(int argc, char **argv) { 1.3746 + 1.3747 + // This test can cause intermittent oranges on the builders 1.3748 + CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_TESTS") 1.3749 + 1.3750 + if (isatty(STDOUT_FILENO) && is_color_terminal(getenv("TERM"))) { 1.3751 + std::string ansiMagenta = "\x1b[35m"; 1.3752 + std::string ansiCyan = "\x1b[36m"; 1.3753 + std::string ansiColorOff = "\x1b[0m"; 1.3754 + callerName = ansiCyan + callerName + ansiColorOff; 1.3755 + calleeName = ansiMagenta + calleeName + ansiColorOff; 1.3756 + } 1.3757 + 1.3758 + std::string tmp = get_environment("STUN_SERVER_ADDRESS"); 1.3759 + if (tmp != "") 1.3760 + g_stun_server_address = tmp; 1.3761 + 1.3762 + tmp = get_environment("STUN_SERVER_PORT"); 1.3763 + if (tmp != "") 1.3764 + g_stun_server_port = atoi(tmp.c_str()); 1.3765 + 1.3766 + test_utils = new MtransportTestUtils(); 1.3767 + NSS_NoDB_Init(nullptr); 1.3768 + NSS_SetDomesticPolicy(); 1.3769 + 1.3770 + ::testing::TestEventListeners& listeners = 1.3771 + ::testing::UnitTest::GetInstance()->listeners(); 1.3772 + // Adds a listener to the end. Google Test takes the ownership. 1.3773 + listeners.Append(new test::RingbufferDumper(test_utils)); 1.3774 + test_utils->sts_target()->Dispatch( 1.3775 + WrapRunnableNM(&TestStunServer::GetInstance), NS_DISPATCH_SYNC); 1.3776 + 1.3777 + // Set the main thread global which is this thread. 1.3778 + nsIThread *thread; 1.3779 + NS_GetMainThread(&thread); 1.3780 + gMainThread = thread; 1.3781 + MOZ_ASSERT(NS_IsMainThread()); 1.3782 + 1.3783 + // Now create the GTest thread and run all of the tests on it 1.3784 + // When it is complete it will set gTestsComplete 1.3785 + NS_NewNamedThread("gtest_thread", &thread); 1.3786 + gGtestThread = thread; 1.3787 + 1.3788 + int result; 1.3789 + gGtestThread->Dispatch( 1.3790 + WrapRunnableNMRet(gtest_main, argc, argv, &result), NS_DISPATCH_NORMAL); 1.3791 + 1.3792 + // Here we handle the event queue for dispatches to the main thread 1.3793 + // When the GTest thread is complete it will send one more dispatch 1.3794 + // with gTestsComplete == true. 1.3795 + while (!gTestsComplete && NS_ProcessNextEvent()); 1.3796 + 1.3797 + gGtestThread->Shutdown(); 1.3798 + 1.3799 + sipcc::PeerConnectionCtx::Destroy(); 1.3800 + delete test_utils; 1.3801 + 1.3802 + return result; 1.3803 +}