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;
}
Beispiel #6
0
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;
}
Beispiel #8
0
bool CallControlManagerImpl::destroy()
{
    CSFLogInfo(logTag, "destroy()");
    bool retval = disconnect();
    if(retval == false)
	{
		return retval;
	}
	return retval;
}
Beispiel #9
0
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;
}
Beispiel #10
0
/**
 * 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();
}
Beispiel #13
0
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__);
  }
}
Beispiel #17
0
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;
}
Beispiel #20
0
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;
}