nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread, nsIEventTarget* stsThread) { if (!gMainThread) { gMainThread = mainThread; CSF::VcmSIPCCBinding::setMainThread(gMainThread); init_thread_monitor(&thread_ended_dispatcher, &join_waiter); } else { MOZ_ASSERT(gMainThread == mainThread); } CSF::VcmSIPCCBinding::setSTSThread(stsThread); nsresult res; MOZ_ASSERT(NS_IsMainThread()); if (!gInstance) { CSFLogDebug(logTag, "Creating PeerConnectionCtx"); PeerConnectionCtx *ctx = new PeerConnectionCtx(); res = ctx->Initialize(); PR_ASSERT(NS_SUCCEEDED(res)); if (!NS_SUCCEEDED(res)) return res; gInstance = ctx; if (!sipcc::PeerConnectionCtx::gPeerConnectionCtxShutdown) { sipcc::PeerConnectionCtx::gPeerConnectionCtxShutdown = new PeerConnectionCtxShutdown(); sipcc::PeerConnectionCtx::gPeerConnectionCtxShutdown->Init(); } } return NS_OK; }
nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread, nsIEventTarget* stsThread) { if (!gMainThread) { gMainThread = mainThread; } else { MOZ_ASSERT(gMainThread == mainThread); } nsresult res; MOZ_ASSERT(NS_IsMainThread()); if (!gInstance) { CSFLogDebug(logTag, "Creating PeerConnectionCtx"); PeerConnectionCtx *ctx = new PeerConnectionCtx(); res = ctx->Initialize(); PR_ASSERT(NS_SUCCEEDED(res)); if (!NS_SUCCEEDED(res)) return res; gInstance = ctx; if (!PeerConnectionCtx::gPeerConnectionCtxShutdown) { PeerConnectionCtx::gPeerConnectionCtxShutdown = new PeerConnectionCtxShutdown(); PeerConnectionCtx::gPeerConnectionCtxShutdown->Init(); } } return NS_OK; }
NS_IMETHODIMP PeerConnectionImpl::GetSipccState(uint32_t* aState) { MOZ_ASSERT(aState); PeerConnectionCtx* pcctx = PeerConnectionCtx::GetInstance(); *aState = pcctx ? pcctx->sipcc_state() : kIdle; return NS_OK; }
NS_IMETHODIMP PeerConnectionImpl::GetSipccState(uint32_t* aState) { PC_AUTO_ENTER_API_CALL_NO_CHECK(); MOZ_ASSERT(aState); PeerConnectionCtx* pcctx = PeerConnectionCtx::GetInstance(); *aState = pcctx ? pcctx->sipcc_state() : kIdle; return NS_OK; }
nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread, nsIEventTarget* stsThread) { if (!gMainThread) { gMainThread = mainThread; CSF::VcmSIPCCBinding::setMainThread(gMainThread); init_thread_monitor(&thread_ended_dispatcher, &join_waiter); } else { #ifdef MOZILLA_INTERNAL_API MOZ_ASSERT(gMainThread == mainThread); #endif } CSF::VcmSIPCCBinding::setSTSThread(stsThread); nsresult res; #ifdef MOZILLA_INTERNAL_API // This check fails on the unit tests because they do not // have the right thread behavior. bool on; res = gMainThread->IsOnCurrentThread(&on); NS_ENSURE_SUCCESS(res, res); MOZ_ASSERT(on); #endif if (!gInstance) { CSFLogDebug(logTag, "Creating PeerConnectionCtx"); PeerConnectionCtx *ctx = new PeerConnectionCtx(); res = ctx->Initialize(); PR_ASSERT(NS_SUCCEEDED(res)); if (!NS_SUCCEEDED(res)) return res; gInstance = ctx; if (!sipcc::PeerConnectionCtx::gPeerConnectionCtxShutdown) { sipcc::PeerConnectionCtx::gPeerConnectionCtxShutdown = new PeerConnectionCtxShutdown(); sipcc::PeerConnectionCtx::gPeerConnectionCtxShutdown->Init(); } } return NS_OK; }
NS_IMETHODIMP PeerConnectionImpl::Initialize(IPeerConnectionObserver* aObserver, nsIDOMWindow* aWindow, nsIThread* aThread) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aObserver); MOZ_ASSERT(aThread); mPCObserver = aObserver; nsresult res; #ifdef MOZILLA_INTERNAL_API // This code interferes with the C++ unit test startup code. nsCOMPtr<nsISupports> nssDummy = do_GetService("@mozilla.org/psm;1", &res); NS_ENSURE_SUCCESS(res, res); #endif mThread = aThread; #ifdef MOZILLA_INTERNAL_API // Currently no standalone unit tests for DataChannel, // which is the user of mWindow MOZ_ASSERT(aWindow); mWindow = do_QueryInterface(aWindow); NS_ENSURE_STATE(mWindow); #endif res = PeerConnectionCtx::InitializeGlobal(mThread); NS_ENSURE_SUCCESS(res, res); PeerConnectionCtx *pcctx = PeerConnectionCtx::GetInstance(); MOZ_ASSERT(pcctx); mCall = pcctx->createCall(); if(!mCall.get()) { CSFLogErrorS(logTag, __FUNCTION__ << ": Couldn't Create Call Object"); return NS_ERROR_FAILURE; } // Connect ICE slots. mMedia->SignalIceGatheringCompleted.connect(this, &PeerConnectionImpl::IceGatheringCompleted); mMedia->SignalIceCompleted.connect(this, &PeerConnectionImpl::IceCompleted); // Initialize the media object. res = mMedia->Init(); if (NS_FAILED(res)) { CSFLogErrorS(logTag, __FUNCTION__ << ": Couldn't initialize media object"); return res; } // Generate a random handle unsigned char handle_bin[8]; PK11_GenerateRandom(handle_bin, sizeof(handle_bin)); char hex[17]; PR_snprintf(hex,sizeof(hex),"%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", handle_bin[0], handle_bin[1], handle_bin[2], handle_bin[3], handle_bin[4], handle_bin[5], handle_bin[6], handle_bin[7]); mHandle += hex; // Store under mHandle mCall->setPeerConnection(mHandle); PeerConnectionCtx::GetInstance()->mPeerConnections[mHandle] = this; // Create the DTLS Identity mIdentity = DtlsIdentity::Generate(); if (!mIdentity) { CSFLogErrorS(logTag, __FUNCTION__ << ": Generate returned NULL"); return NS_ERROR_FAILURE; } // Set the fingerprint. Right now assume we only have one // DTLS identity unsigned char fingerprint[DTLS_FINGERPRINT_LENGTH]; size_t fingerprint_length; res = mIdentity->ComputeFingerprint("sha-1", fingerprint, sizeof(fingerprint), &fingerprint_length); if (NS_FAILED(res)) { CSFLogErrorS(logTag, __FUNCTION__ << ": ComputeFingerprint failed: " << static_cast<uint32_t>(res)); return res; } mFingerprint = "sha-1 " + mIdentity->FormatFingerprint(fingerprint, fingerprint_length); // Find the STS thread mSTSThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &res); if (NS_FAILED(res)) { CSFLogErrorS(logTag, __FUNCTION__ << ": do_GetService failed: " << static_cast<uint32_t>(res)); return res; } #ifndef MOZILLA_INTERNAL_API // Busy-wait until we are ready, for C++ unit tests. Remove when tests are fixed. CSFLogDebugS(logTag, __FUNCTION__ << ": Sleeping until kStarted"); while(PeerConnectionCtx::GetInstance()->sipcc_state() != kStarted) { PR_Sleep(100); } #endif return NS_OK; }
NS_IMETHODIMP PeerConnectionImpl::Initialize(IPeerConnectionObserver* aObserver, nsIDOMWindow* aWindow, nsIThread* aThread) { MOZ_ASSERT(aObserver); mPCObserver = aObserver; #ifdef MOZILLA_INTERNAL_API // Currently no standalone unit tests for DataChannel, // which is the user of mWindow MOZ_ASSERT(aWindow); mWindow = do_QueryInterface(aWindow); NS_ENSURE_STATE(mWindow); #endif // The thread parameter can be passed in as NULL mThread = aThread; PeerConnectionCtx *pcctx = PeerConnectionCtx::GetInstance(); MOZ_ASSERT(pcctx); mCall = pcctx->createCall(); if(!mCall.get()) { CSFLogErrorS(logTag, __FUNCTION__ << ": Couldn't Create Call Object"); return NS_ERROR_FAILURE; } // Generate a random handle unsigned char handle_bin[8]; PK11_GenerateRandom(handle_bin, sizeof(handle_bin)); char hex[17]; PR_snprintf(hex,sizeof(hex),"%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", handle_bin[0], handle_bin[1], handle_bin[2], handle_bin[3], handle_bin[4], handle_bin[5], handle_bin[6], handle_bin[7]); mHandle += hex; // TODO([email protected]): need some way to set not offerer later // Looks like a bug in the NrIceCtx API. mIceCtx = NrIceCtx::Create("PC:" + mHandle, true); if(!mIceCtx) { CSFLogErrorS(logTag, __FUNCTION__ << ": Failed to create Ice Context"); return NS_ERROR_FAILURE; } mIceCtx->SignalGatheringCompleted.connect(this, &PeerConnectionImpl::IceGatheringCompleted); mIceCtx->SignalCompleted.connect(this, &PeerConnectionImpl::IceCompleted); // Create three streams to start with. // One each for audio, video and DataChannel // TODO: this will be re-visited RefPtr<NrIceMediaStream> audioStream = mIceCtx->CreateStream("stream1", 2); RefPtr<NrIceMediaStream> videoStream = mIceCtx->CreateStream("stream2", 2); RefPtr<NrIceMediaStream> dcStream = mIceCtx->CreateStream("stream3", 2); if (!audioStream) { CSFLogErrorS(logTag, __FUNCTION__ << ": audio stream is NULL"); return NS_ERROR_FAILURE; } else { mIceStreams.push_back(audioStream); } if (!videoStream) { CSFLogErrorS(logTag, __FUNCTION__ << ": video stream is NULL"); return NS_ERROR_FAILURE; } else { mIceStreams.push_back(videoStream); } if (!dcStream) { CSFLogErrorS(logTag, __FUNCTION__ << ": datachannel stream is NULL"); return NS_ERROR_FAILURE; } else { mIceStreams.push_back(dcStream); } for (std::size_t i=0; i<mIceStreams.size(); i++) { mIceStreams[i]->SignalReady.connect(this, &PeerConnectionImpl::IceStreamReady); } // Start gathering nsresult res; mIceCtx->thread()->Dispatch(WrapRunnableRet( mIceCtx, &NrIceCtx::StartGathering, &res), NS_DISPATCH_SYNC ); if (NS_FAILED(res)) { CSFLogErrorS(logTag, __FUNCTION__ << ": StartGathering failed: " << res); return res; } // Store under mHandle mCall->setPeerConnection(mHandle); peerconnections[mHandle] = this; // Create the DTLS Identity mIdentity = DtlsIdentity::Generate(); if (!mIdentity) { CSFLogErrorS(logTag, __FUNCTION__ << ": Generate returned NULL"); return NS_ERROR_FAILURE; } // Set the fingerprint. Right now assume we only have one // DTLS identity unsigned char fingerprint[DTLS_FINGERPRINT_LENGTH]; size_t fingerprint_length; res = mIdentity->ComputeFingerprint("sha-1", fingerprint, sizeof(fingerprint), &fingerprint_length); if (NS_FAILED(res)) { CSFLogErrorS(logTag, __FUNCTION__ << ": ComputeFingerprint failed: " << res); return res; } mFingerprint = "sha-1 " + mIdentity->FormatFingerprint(fingerprint, fingerprint_length); // Find the STS thread mSTSThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &res); if (NS_FAILED(res)) { CSFLogErrorS(logTag, __FUNCTION__ << ": do_GetService failed: " << res); return res; } #ifndef MOZILLA_INTERNAL_API // Busy-wait until we are ready, for C++ unit tests. Remove when tests are fixed. CSFLogDebugS(logTag, __FUNCTION__ << ": Sleeping until kStarted"); while(PeerConnectionCtx::GetInstance()->sipcc_state() != kStarted) { PR_Sleep(100); } #endif return NS_OK; }