bool CallControlManagerImpl::setProperty(ConfigPropertyKeysEnum::ConfigPropertyKeys key, std::string& value) { unsigned long strtoul_result; char *strtoul_end; CSFLogInfo(logTag, "setProperty( %s )", value.c_str()); if (key == ConfigPropertyKeysEnum::eLocalVoipPort) { errno = 0; strtoul_result = strtoul(value.c_str(), &strtoul_end, 10); if (errno || value.c_str() == strtoul_end || strtoul_result > USHRT_MAX) { return false; } CCAPI_Config_set_local_voip_port((int) strtoul_result); } else if (key == ConfigPropertyKeysEnum::eRemoteVoipPort) { errno = 0; strtoul_result = strtoul(value.c_str(), &strtoul_end, 10); if (errno || value.c_str() == strtoul_end || strtoul_result > USHRT_MAX) { return false; } CCAPI_Config_set_remote_voip_port((int) strtoul_result); } else if (key == ConfigPropertyKeysEnum::eTransport) { if (value == "tcp") CCAPI_Config_set_transport_udp(false); else CCAPI_Config_set_transport_udp(true); } return true; }
nsresult LocalSourceStreamInfo::TakePipelineFrom(RefPtr<LocalSourceStreamInfo>& info, const std::string& oldTrackId, MediaStreamTrack& aNewTrack, const std::string& newTrackId) { if (mPipelines.count(newTrackId)) { CSFLogError(logTag, "%s: Pipeline already exists for %s/%s", __FUNCTION__, mId.c_str(), newTrackId.c_str()); return NS_ERROR_INVALID_ARG; } RefPtr<MediaPipeline> pipeline(info->ForgetPipelineByTrackId_m(oldTrackId)); if (!pipeline) { // Replacetrack can potentially happen in the middle of offer/answer, before // the pipeline has been created. CSFLogInfo(logTag, "%s: Replacing track before the pipeline has been " "created, nothing to do.", __FUNCTION__); return NS_OK; } nsresult rv = static_cast<MediaPipelineTransmit*>(pipeline.get())->ReplaceTrack(aNewTrack); NS_ENSURE_SUCCESS(rv, rv); mPipelines[newTrackId] = pipeline; return NS_OK; }
void PeerConnectionMedia::ProtocolProxyQueryHandler::SetProxyOnPcm( nsIProxyInfo& proxyinfo) { CSFLogInfo(logTag, "%s: Had proxyinfo", __FUNCTION__); nsresult rv; nsCString httpsProxyHost; int32_t httpsProxyPort; rv = proxyinfo.GetHost(httpsProxyHost); if (NS_FAILED(rv)) { CSFLogError(logTag, "%s: Failed to get proxy server host", __FUNCTION__); return; } rv = proxyinfo.GetPort(&httpsProxyPort); if (NS_FAILED(rv)) { CSFLogError(logTag, "%s: Failed to get proxy server port", __FUNCTION__); return; } if (pcm_->mIceCtx.get()) { assert(httpsProxyPort >= 0 && httpsProxyPort < (1 << 16)); pcm_->mProxyServer.reset( new NrIceProxyServer(httpsProxyHost.get(), static_cast<uint16_t>(httpsProxyPort))); } else { CSFLogError(logTag, "%s: Failed to set proxy server (ICE ctx unavailable)", __FUNCTION__); } }
bool CallControlManagerImpl::startP2PMode(const std::string& user) { setConnectionState(ConnectionStatusEnum::eRegistering); CSFLogInfo(logTag, "startP2PMode(%s)", user.c_str()); if(phone != nullptr) { setConnectionState(ConnectionStatusEnum::eReady); CSFLogError(logTag, "startP2PMode() failed - already started in p2p mode!"); return false; } softPhone = CC_SIPCCServicePtr(new CC_SIPCCService()); phone = softPhone; phone->init(user, "", "127.0.0.1", "sipdevice"); softPhone->setLoggingMask(sipccLoggingMask); phone->addCCObserver(this); phone->setP2PMode(true); bool bStarted = phone->startService(); if (!bStarted) { setConnectionState(ConnectionStatusEnum::eFailed); } else { setConnectionState(ConnectionStatusEnum::eReady); } return bStarted; }
bool CallControlManagerImpl::registerUser( const std::string& deviceName, const std::string& user, const std::string& password, const std::string& domain ) { setConnectionState(ConnectionStatusEnum::eRegistering); CSFLogInfo(logTag, "registerUser(%s, %s )", user.c_str(), domain.c_str()); if(phone != nullptr) { setConnectionState(ConnectionStatusEnum::eReady); CSFLogError(logTag, "registerUser() failed - already connected!"); return false; } softPhone = CC_SIPCCServicePtr(new CC_SIPCCService()); phone = softPhone; phone->init(user, password, domain, deviceName); softPhone->setLoggingMask(sipccLoggingMask); phone->addCCObserver(this); phone->setP2PMode(false); bool bStarted = phone->startService(); if (!bStarted) { setConnectionState(ConnectionStatusEnum::eFailed); } else { setConnectionState(ConnectionStatusEnum::eReady); } return bStarted; }
CallControlManagerImpl::CallControlManagerImpl() : m_lock("CallControlManagerImpl"), multiClusterMode(false), sipccLoggingMask(0), authenticationStatus(AuthenticationStatusEnum::eNotAuthenticated), connectionState(ConnectionStatusEnum::eIdle) { CSFLogInfo(logTag, "CallControlManagerImpl()"); }
NS_IMETHODIMP PeerConnectionMedia::ProtocolProxyQueryHandler:: OnProxyAvailable(nsICancelable *request, nsIChannel *aChannel, nsIProxyInfo *proxyinfo, nsresult result) { CSFLogInfo(logTag, "%s: Proxy Available: %d", __FUNCTION__, (int)result); if (NS_SUCCEEDED(result) && proxyinfo) { CSFLogInfo(logTag, "%s: Had proxyinfo", __FUNCTION__); nsresult rv; nsCString httpsProxyHost; int32_t httpsProxyPort; rv = proxyinfo->GetHost(httpsProxyHost); if (NS_FAILED(rv)) { CSFLogError(logTag, "%s: Failed to get proxy server host", __FUNCTION__); return rv; } rv = proxyinfo->GetPort(&httpsProxyPort); if (NS_FAILED(rv)) { CSFLogError(logTag, "%s: Failed to get proxy server port", __FUNCTION__); return rv; } if (pcm_->mIceCtx.get()) { assert(httpsProxyPort >= 0 && httpsProxyPort < (1 << 16)); pcm_->mProxyServer.reset( new NrIceProxyServer(httpsProxyHost.get(), static_cast<uint16_t>(httpsProxyPort))); } else { CSFLogError(logTag, "%s: Failed to set proxy server (ICE ctx unavailable)", __FUNCTION__); } } if (result != NS_ERROR_ABORT) { // NS_ERROR_ABORT means that the PeerConnectionMedia is no longer waiting pcm_->mProxyResolveCompleted = true; pcm_->FlushIceCtxOperationQueueIfReady(); } return NS_OK; }
bool CallControlManagerImpl::destroy() { CSFLogInfo(logTag, "destroy()"); bool retval = disconnect(); if(retval == false) { return retval; } return retval; }
bool CallControlManagerImpl::disconnect() { CSFLogInfo(logTag, "disconnect()"); if(phone == NULL) return true; connectionState = ConnectionStatusEnum::eIdle; phone->removeCCObserver(this); phone->stop(); phone->destroy(); phone.reset(); softPhone.reset(); return true; }
/** * Notice message * * @param _format format string * @param ... variable arg list * * @return Return code from vsnprintf * * @pre (_format not_eq NULL) */ void notice_msg (const char *_format, ...) { char fmt_buf[LOG_MAX + 1]; va_list ap; int rc; va_start(ap, _format); rc = vsnprintf(fmt_buf, LOG_MAX, _format, ap); va_end(ap); if (rc <= 0) { return; } CSFLogInfo("cpr", "%s", fmt_buf); }
void PeerConnectionMedia::EnsureIceGathering_s(bool aDefaultRouteOnly, bool aProxyOnly) { if (mProxyServer) { mIceCtxHdlr->ctx()->SetProxyServer(*mProxyServer); } else if (aProxyOnly) { IceGatheringStateChange_s(mIceCtxHdlr->ctx().get(), NrIceCtx::ICE_CTX_GATHER_COMPLETE); return; } // Make sure we don't call NrIceCtx::StartGathering if we're in e10s mode // and we received no STUN addresses from the parent process. In the // absence of previously provided STUN addresses, StartGathering will // attempt to gather them (as in non-e10s mode), and this will cause a // sandboxing exception in e10s mode. if (!mStunAddrs.Length() && XRE_IsContentProcess()) { CSFLogInfo(LOGTAG, "%s: No STUN addresses returned from parent process", __FUNCTION__); return; } // Belt and suspenders - in e10s mode, the call below to SetStunAddrs // needs to have the proper flags set on ice ctx. For non-e10s, // setting those flags happens in StartGathering. We could probably // just set them here, and only do it here. mIceCtxHdlr->ctx()->SetCtxFlags(aDefaultRouteOnly, aProxyOnly); if (mStunAddrs.Length()) { mIceCtxHdlr->ctx()->SetStunAddrs(mStunAddrs); } // Start gathering, but only if there are streams for (size_t i = 0; i < mIceCtxHdlr->ctx()->GetStreamCount(); ++i) { if (mIceCtxHdlr->ctx()->GetStream(i)) { mIceCtxHdlr->ctx()->StartGathering(aDefaultRouteOnly, aProxyOnly); return; } } // If there are no streams, we're probably in a situation where we've rolled // back while still waiting for our proxy configuration to come back. Make // sure content knows that the rollback has stuck wrt gathering. IceGatheringStateChange_s(mIceCtxHdlr->ctx().get(), NrIceCtx::ICE_CTX_GATHER_COMPLETE); }
bool CallControlManagerImpl::startSDPMode() { CSFLogInfo(logTag, "startSDPMode"); if(phone != nullptr) { CSFLogError(logTag, "%s failed - already started in SDP mode!",__FUNCTION__); return false; } softPhone = CC_SIPCCServicePtr(new CC_SIPCCService()); phone = softPhone; phone->init("JSEP", "", "127.0.0.1", "sipdevice"); softPhone->setLoggingMask(sipccLoggingMask); phone->addCCObserver(this); phone->setSDPMode(true); return phone->startService(); }
std::string CallControlManagerImpl::getProperty(ConfigPropertyKeysEnum::ConfigPropertyKeys key) { std::string retValue = "NONESET"; char tmpString[11]; CSFLogInfo(logTag, "getProperty()"); if (key == ConfigPropertyKeysEnum::eLocalVoipPort) { csf_sprintf(tmpString, sizeof(tmpString), "%u", CCAPI_Config_get_local_voip_port()); retValue = tmpString; } else if (key == ConfigPropertyKeysEnum::eRemoteVoipPort) { csf_sprintf(tmpString, sizeof(tmpString), "%u", CCAPI_Config_get_remote_voip_port()); retValue = tmpString; } else if (key == ConfigPropertyKeysEnum::eVersion) { const char* version = CCAPI_Config_get_version(); retValue = version; } return retValue; }
void PeerConnectionMedia::StunAddrsHandler::OnStunAddrsAvailable( const mozilla::net::NrIceStunAddrArray& addrs) { CSFLogInfo(LOGTAG, "%s: receiving (%d) stun addrs", __FUNCTION__, (int)addrs.Length()); if (pcm_) { pcm_->mStunAddrs = addrs; pcm_->mLocalAddrsCompleted = true; pcm_->mStunAddrsRequest = nullptr; pcm_->FlushIceCtxOperationQueueIfReady(); // If parent process returns 0 STUN addresses, change ICE connection // state to failed. if (!pcm_->mStunAddrs.Length()) { pcm_->SignalIceConnectionStateChange(pcm_->mIceCtxHdlr->ctx().get(), NrIceCtx::ICE_CTX_FAILED); } pcm_ = nullptr; } }
NS_IMETHODIMP PeerConnectionMedia::ProtocolProxyQueryHandler:: OnProxyAvailable(nsICancelable *request, nsIChannel *aChannel, nsIProxyInfo *proxyinfo, nsresult result) { if (result == NS_ERROR_ABORT) { // NS_ERROR_ABORT means that the PeerConnectionMedia is no longer waiting return NS_OK; } CSFLogInfo(logTag, "%s: Proxy Available: %d", __FUNCTION__, (int)result); if (NS_SUCCEEDED(result) && proxyinfo) { SetProxyOnPcm(*proxyinfo); } pcm_->mProxyResolveCompleted = true; pcm_->FlushIceCtxOperationQueueIfReady(); return NS_OK; }
void PeerConnectionMedia::ProtocolProxyQueryHandler::SetProxyOnPcm( nsIProxyInfo& proxyinfo) { CSFLogInfo(logTag, "%s: Had proxyinfo", __FUNCTION__); nsresult rv; nsCString httpsProxyHost; int32_t httpsProxyPort; rv = proxyinfo.GetHost(httpsProxyHost); if (NS_FAILED(rv)) { CSFLogError(logTag, "%s: Failed to get proxy server host", __FUNCTION__); return; } rv = proxyinfo.GetPort(&httpsProxyPort); if (NS_FAILED(rv)) { CSFLogError(logTag, "%s: Failed to get proxy server port", __FUNCTION__); return; } if (pcm_->mIceCtxHdlr.get()) { assert(httpsProxyPort >= 0 && httpsProxyPort < (1 << 16)); // Note that this could check if PrivacyRequested() is set on the PC and // remove "webrtc" from the ALPN list. But that would only work if the PC // was constructed with a peerIdentity constraint, not when isolated // streams are added. If we ever need to signal to the proxy that the // media is isolated, then we would need to restructure this code. pcm_->mProxyServer.reset( new NrIceProxyServer(httpsProxyHost.get(), static_cast<uint16_t>(httpsProxyPort), "webrtc,c-webrtc")); } else { CSFLogError(logTag, "%s: Failed to set proxy server (ICE ctx unavailable)", __FUNCTION__); } }
CallControlManagerImpl::~CallControlManagerImpl() { CSFLogInfo(logTag, "~CallControlManagerImpl()"); destroy(); }
void CallControlManagerImpl::setMultiClusterMode(bool allowMultipleClusters) { CSFLogInfo(logTag, "setMultiClusterMode(%s)", allowMultipleClusters ? "TRUE" : "FALSE"); multiClusterMode = allowMultipleClusters; }
void CallControlManagerImpl::setSecureCachePath(const std::string &secureCachePath) { CSFLogInfo(logTag, "setSecureCachePath(%s)", secureCachePath.c_str()); this->secureCachePath = secureCachePath; }
void CallControlManagerImpl::setAuthenticationString(const std::string &authString) { CSFLogInfo(logTag, "setAuthenticationString()"); this->authString = authString; }
nsresult PeerConnectionMedia::UpdateTransportFlow( size_t aLevel, bool aIsRtcp, const JsepTransport& aTransport) { if (aIsRtcp && aTransport.mComponents < 2) { RemoveTransportFlow(aLevel, aIsRtcp); return NS_OK; } if (!aIsRtcp && !aTransport.mComponents) { RemoveTransportFlow(aLevel, aIsRtcp); return NS_OK; } nsresult rv; RefPtr<TransportFlow> flow = GetTransportFlow(aLevel, aIsRtcp); if (flow) { if (IsIceRestarting()) { CSFLogInfo(LOGTAG, "Flow[%s]: detected ICE restart - level: %u rtcp: %d", flow->id().c_str(), (unsigned)aLevel, aIsRtcp); RefPtr<PeerConnectionMedia> pcMedia(this); rv = GetSTSThread()->Dispatch( WrapRunnableNM(AddNewIceStreamForRestart_s, pcMedia, flow, aLevel, aIsRtcp), NS_DISPATCH_NORMAL); if (NS_FAILED(rv)) { CSFLogError(LOGTAG, "Failed to dispatch AddNewIceStreamForRestart_s"); return rv; } } return NS_OK; } std::ostringstream osId; osId << mParentHandle << ":" << aLevel << "," << (aIsRtcp ? "rtcp" : "rtp"); flow = new TransportFlow(osId.str()); // The media streams are made on STS so we need to defer setup. auto ice = MakeUnique<TransportLayerIce>(); auto dtls = MakeUnique<TransportLayerDtls>(); dtls->SetRole(aTransport.mDtls->GetRole() == JsepDtlsTransport::kJsepDtlsClient ? TransportLayerDtls::CLIENT : TransportLayerDtls::SERVER); RefPtr<DtlsIdentity> pcid = mParent->Identity(); if (!pcid) { CSFLogError(LOGTAG, "Failed to get DTLS identity."); return NS_ERROR_FAILURE; } dtls->SetIdentity(pcid); const SdpFingerprintAttributeList& fingerprints = aTransport.mDtls->GetFingerprints(); for (const auto& fingerprint : fingerprints.mFingerprints) { std::ostringstream ss; ss << fingerprint.hashFunc; rv = dtls->SetVerificationDigest(ss.str(), &fingerprint.fingerprint[0], fingerprint.fingerprint.size()); if (NS_FAILED(rv)) { CSFLogError(LOGTAG, "Could not set fingerprint"); return rv; } } std::vector<uint16_t> srtpCiphers; srtpCiphers.push_back(SRTP_AES128_CM_HMAC_SHA1_80); srtpCiphers.push_back(SRTP_AES128_CM_HMAC_SHA1_32); rv = dtls->SetSrtpCiphers(srtpCiphers); if (NS_FAILED(rv)) { CSFLogError(LOGTAG, "Couldn't set SRTP ciphers"); return rv; } // Always permits negotiation of the confidential mode. // Only allow non-confidential (which is an allowed default), // if we aren't confidential. std::set<std::string> alpn; std::string alpnDefault = ""; alpn.insert("c-webrtc"); if (!mParent->PrivacyRequested()) { alpnDefault = "webrtc"; alpn.insert(alpnDefault); } rv = dtls->SetAlpn(alpn, alpnDefault); if (NS_FAILED(rv)) { CSFLogError(LOGTAG, "Couldn't set ALPN"); return rv; } nsAutoPtr<PtrVector<TransportLayer> > layers(new PtrVector<TransportLayer>); layers->values.push_back(ice.release()); layers->values.push_back(dtls.release()); RefPtr<PeerConnectionMedia> pcMedia(this); rv = GetSTSThread()->Dispatch( WrapRunnableNM(FinalizeTransportFlow_s, pcMedia, flow, aLevel, aIsRtcp, layers), NS_DISPATCH_NORMAL); if (NS_FAILED(rv)) { CSFLogError(LOGTAG, "Failed to dispatch FinalizeTransportFlow_s"); return rv; } AddTransportFlow(aLevel, aIsRtcp, flow); return NS_OK; }
void CallControlManagerImpl::setSIPCCLoggingMask(const cc_int32_t mask) { CSFLogInfo(logTag, "setSIPCCLoggingMask(%u)", mask); sipccLoggingMask = mask; }