// REITEK: Callback to handle transaction state changes //Static void PjsuaManager::OnCallTsxState(pjsua_call_id call_id, pjsip_transaction *tsx, pjsip_event *e) { PjsuaManagerPtr manager = PjsuaManager::instance_.lock(); if (!manager) return; pjsua_call_info info; pj_status_t status; if ((status = pjsua_call_get_info(call_id, &info)) == PJ_SUCCESS) { std::string str = "PjsuaManager::OnCallTsxState called with PJSIP call id: " + boost::lexical_cast<std::string>(call_id)+", state: " + boost::lexical_cast<std::string>(info.state); BlabbleLogging::blabbleLog(0, str.c_str(), 0); //BLABBLE_LOG_TRACE("PjsuaManager::OnCallTsxState called with PJSIP call id: "<< call_id << ", state: " << info.state); BlabbleAccountPtr acc = manager->FindAcc(info.acc_id); if (acc) { acc->OnCallTsxState(call_id, tsx, e); } // REITEK: !!! CHECK: If this necessary/wanted? if (info.state == PJSIP_INV_STATE_DISCONNECTED) { //Just make sure we get rid of the call pjsua_call_hangup(call_id, 0, NULL, NULL); } } else { std::string str = "PjsuaManager::OnCallTsxState failed to call pjsua_call_get_info for PJSIP call id: " + boost::lexical_cast<std::string>(call_id)+", got status: " + boost::lexical_cast<std::string>(status); BlabbleLogging::blabbleLog(0, str.c_str(), 0); //BLABBLE_LOG_ERROR("PjsuaManager::OnCallTsxState failed to call pjsua_call_get_info for PJSIP call id: "<< call_id << ", got status: " << status); } }
//Static void PjsuaManager::OnCallMediaState(pjsua_call_id call_id) { PjsuaManagerPtr manager = PjsuaManager::instance_.lock(); if (!manager) return; pjsua_call_info info; pj_status_t status; if ((status = pjsua_call_get_info(call_id, &info)) == PJ_SUCCESS) { std::string str = "PjsuaManager::OnCallMediaState called with PJSIP call id: " + boost::lexical_cast<std::string>(call_id)+", state: " + boost::lexical_cast<std::string>(info.state); BlabbleLogging::blabbleLog(0, str.c_str(), 0); //BLABBLE_LOG_TRACE("PjsuaManager::OnCallMediaState called with PJSIP call id: " << call_id << ", state: " << info.state); BlabbleAccountPtr acc = manager->FindAcc(info.acc_id); if (acc) { acc->OnCallMediaState(call_id); } } else { std::string str = "PjsuaManager::OnCallMediaState failed to call pjsua_call_get_info for PJSIP call id: " + boost::lexical_cast<std::string>(call_id)+", got status: " + boost::lexical_cast<std::string>(status); BlabbleLogging::blabbleLog(0, str.c_str(), 0); //BLABBLE_LOG_ERROR("PjsuaManager::OnCallMediaState failed to call pjsua_call_get_info for PJSIP call id: " << call_id << ", got status: " << status); } }
void PjsuaManager::AddAccount(const BlabbleAccountPtr &account) { if (account->id() == INVALID_ACCOUNT) throw std::runtime_error("Attempt to add uninitialized account."); accounts_[account->id()] = account; }
//Ended by us void BlabbleCall::LocalEnd() { pjsua_call_id old_id = INTERLOCKED_EXCHANGE((volatile long *)&call_id_, (long)INVALID_CALL); if (old_id == INVALID_CALL || old_id < 0 || old_id >= (long)pjsua_call_get_max_count()) { return; } StopRinging(); pjsua_call_info info; if (pjsua_call_get_info(old_id, &info) == PJ_SUCCESS && info.conf_slot > 0) { //Kill the audio pjsua_conf_disconnect(info.conf_slot, 0); pjsua_conf_disconnect(0, info.conf_slot); } pjsua_call_hangup(old_id, 0, NULL, NULL); if (on_call_end_) { BlabbleCallPtr call = get_shared(); on_call_end_->getHost()->ScheduleOnMainThread(call, boost::bind(&BlabbleCall::CallOnCallEnd, call)); } BlabbleAccountPtr p = parent_.lock(); if (p) p->OnCallEnd(get_shared()); }
void BlabbleCall::OnCallState(pjsua_call_id call_id, pjsip_event *e) { pjsua_call_info info; if (pjsua_call_get_info(call_id, &info) == PJ_SUCCESS) { if (info.state == PJSIP_INV_STATE_DISCONNECTED) { RemoteEnd(info); } else if (info.state == PJSIP_INV_STATE_CALLING) { if (on_call_ringing_) on_call_ringing_->InvokeAsync("", FB::variant_list_of(BlabbleCallWeakPtr(get_shared()))); BlabbleAccountPtr p = parent_.lock(); if (p) p->OnCallRingChange(get_shared(), info); } else if (info.state == PJSIP_INV_STATE_CONFIRMED) { if (on_call_connected_) on_call_connected_->InvokeAsync("", FB::variant_list_of(BlabbleCallWeakPtr(get_shared()))); BlabbleAccountPtr p = parent_.lock(); if (p) p->OnCallRingChange(get_shared(), info); } } }
BlabbleCall::BlabbleCall(const BlabbleAccountPtr& parent_account) : call_id_(-1), ringing_(false) { if (parent_account) { acct_id_ = parent_account->id(); audio_manager_ = parent_account->GetManager()->audio_manager(); parent_ = BlabbleAccountWeakPtr(parent_account); } else { acct_id_ = -1; } id_ = BlabbleCall::GetNextId(); BLABBLE_LOG_DEBUG("New call created. Global id: " << id_); registerMethod("answer", make_method(this, &BlabbleCall::Answer)); registerMethod("hangup", make_method(this, &BlabbleCall::LocalEnd)); registerMethod("hold", make_method(this, &BlabbleCall::Hold)); registerMethod("unhold", make_method(this, &BlabbleCall::Unhold)); registerMethod("sendDTMF", make_method(this, &BlabbleCall::SendDTMF)); registerMethod("transferReplace", make_method(this, &BlabbleCall::TransferReplace)); registerMethod("transfer", make_method(this, &BlabbleCall::Transfer)); registerProperty("callerId", make_property(this, &BlabbleCall::caller_id)); registerProperty("isActive", make_property(this, &BlabbleCall::is_active)); registerProperty("status", make_property(this, &BlabbleCall::status)); registerProperty("onCallConnected", make_write_only_property(this, &BlabbleCall::set_on_call_connected)); registerProperty("onCallEnd", make_write_only_property(this, &BlabbleCall::set_on_call_end)); }
//Static void PjsuaManager::OnIncomingCall(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata) { std::string str = "OnIncomingCall called for PJSIP account id: " + boost::lexical_cast<std::string>(acc_id)+", PJSIP call id: " + boost::lexical_cast<std::string>(call_id); BlabbleLogging::blabbleLog(0, str.c_str(), 0); //BLABBLE_LOG_TRACE("OnIncomingCall called for PJSIP account id: " << acc_id << ", PJSIP call id: " << call_id); PjsuaManagerPtr manager = PjsuaManager::instance_.lock(); if (!manager) { //How is this even possible? pjsua_call_hangup(call_id, 0, NULL, NULL); return; } // REITEK: Prefer local codec ordering (!!! CHECK: Make it configurable ?) pjsua_call *call; pjsip_dialog *dlg; pj_status_t status; status = acquire_call("PjsuaManager::OnIncomingCall", call_id, &call, &dlg); if (status == PJ_SUCCESS) { if (call->inv->neg != NULL) { status = pjmedia_sdp_neg_set_prefer_remote_codec_order(call->inv->neg, PJ_FALSE); if (status != PJ_SUCCESS) { std::string str = "Could not set codec negotiation preference on local side for PJSIP account id: " + boost::lexical_cast<std::string>(acc_id)+", PJSIP call id: " + boost::lexical_cast<std::string>(call_id); BlabbleLogging::blabbleLog(0, str.c_str(), 0); //BLABBLE_LOG_ERROR("Could not set codec negotiation preference on local side for PJSIP account id: " << acc_id << ", PJSIP call id: " << call_id); } } else { std::string str = "WARNING: NULL SDP negotiator: cannot set codec negotiation preference on local side for PJSIP account id: " + boost::lexical_cast<std::string>(acc_id)+", PJSIP call id: " + boost::lexical_cast<std::string>(call_id); BlabbleLogging::blabbleLog(0, str.c_str(), 0); //BLABBLE_LOG_DEBUG("WARNING: NULL SDP negotiator: cannot set codec negotiation preference on local side for PJSIP account id: " << acc_id << ", PJSIP call id: " << call_id); } pjsip_dlg_dec_lock(dlg); } else { std::string str = "Could not acquire lock to set codec negotiation preference on local side for PJSIP account id: " + boost::lexical_cast<std::string>(acc_id)+", PJSIP call id: " + boost::lexical_cast<std::string>(call_id); BlabbleLogging::blabbleLog(0, str.c_str(), 0); //BLABBLE_LOG_ERROR("Could not acquire lock to set codec negotiation preference on local side for PJSIP account id: " << acc_id << ", PJSIP call id: " << call_id); } BlabbleAccountPtr acc = manager->FindAcc(acc_id); if (acc && acc->OnIncomingCall(call_id, rdata)) { return; } //Otherwise we respond busy if no one wants the call pjsua_call_hangup(call_id, 486, NULL, NULL); }
//Ended by remote, could be becuase of an error void BlabbleCall::RemoteEnd(const pjsua_call_info &info) { pjsua_call_id old_id = INTERLOCKED_EXCHANGE((volatile long *)&call_id_, (long)INVALID_CALL); if (old_id == INVALID_CALL || old_id < 0 || old_id >= (long)pjsua_call_get_max_count()) { return; } StopRinging(); //Kill the audio if (info.conf_slot > 0) { pjsua_conf_disconnect(info.conf_slot, 0); pjsua_conf_disconnect(0, info.conf_slot); } pjsua_call_hangup(old_id, 0, NULL, NULL); if (info.last_status > 400) { std::string callerId; if (info.remote_contact.ptr == NULL) { callerId =std::string(info.remote_info.ptr, info.remote_info.slen); } else { callerId = std::string(info.remote_contact.ptr, info.remote_contact.slen); } if (on_call_end_) { BlabbleCallPtr call = get_shared(); on_call_end_->getHost()->ScheduleOnMainThread(call, boost::bind(&BlabbleCall::CallOnCallEnd, call, info.last_status)); } } else { if (on_call_end_) { BlabbleCallPtr call = get_shared(); on_call_end_->getHost()->ScheduleOnMainThread(call, boost::bind(&BlabbleCall::CallOnCallEnd, call)); } } BlabbleAccountPtr p = parent_.lock(); if (p) p->OnCallEnd(get_shared()); }
//Static void PjsuaManager::OnCallState(pjsua_call_id call_id, pjsip_event *e) { PjsuaManagerPtr manager = PjsuaManager::instance_.lock(); if (!manager) return; pjsua_call_info info; pj_status_t status; if ((status = pjsua_call_get_info(call_id, &info)) == PJ_SUCCESS) { std::string str = "PjsuaManager::OnCallState called with PJSIP call id: " + boost::lexical_cast<std::string>(call_id)+", state: " + boost::lexical_cast<std::string>(info.state); BlabbleLogging::blabbleLog(0, str.c_str(), 0); //BLABBLE_LOG_TRACE("PjsuaManager::OnCallState called with PJSIP call id: " << call_id << ", state: " << info.state); BlabbleAccountPtr acc = manager->FindAcc(info.acc_id); if (acc) { acc->OnCallState(call_id, e); } if (info.state == PJSIP_INV_STATE_DISCONNECTED) { // REITEK: Dump call statistics std::string dbgstr = "Dumping statistics for PJSIP call id: " + boost::lexical_cast<std::string>(call_id); BlabbleLogging::blabbleLog(0, dbgstr.c_str(), 0); char stats_buf[STATS_BUF_SIZE]; memset(stats_buf, 0, STATS_BUF_SIZE); pjsua_call_dump(call_id, PJ_TRUE, stats_buf, STATS_BUF_SIZE, " "); stats_buf[STATS_BUF_SIZE - 1] = '\0'; BlabbleLogging::blabbleLog(0, stats_buf, 0); //Just make sure we get rid of the call pjsua_call_hangup(call_id, 0, NULL, NULL); } } else { std::string str = "PjsuaManager::OnCallState failed to call pjsua_call_get_info for PJSIP call id: " + boost::lexical_cast<std::string>(call_id)+", got status: " + boost::lexical_cast<std::string>(status); BlabbleLogging::blabbleLog(0, str.c_str(), 0); //BLABBLE_LOG_ERROR("PjsuaManager::OnCallState failed to call pjsua_call_get_info for PJSIP call id: " << call_id << ", got status: " << status); } }
//Static void PjsuaManager::OnRegState(pjsua_acc_id acc_id) { PjsuaManagerPtr manager = PjsuaManager::instance_.lock(); if (!manager) return; BlabbleAccountPtr acc = manager->FindAcc(acc_id); if (acc) { acc->OnRegState(); } else { std::string str = "PjsuaManager::OnRegState failed to find account PJSIP account id: " + boost::lexical_cast<std::string>(acc_id); BlabbleLogging::blabbleLog(0, str.c_str(), 0); //BLABBLE_LOG_ERROR("PjsuaManager::OnRegState failed to find account PJSIP account id: " << acc_id); } }
bool BlabbleCall::Transfer(const FB::VariantMap ¶ms) { std::string destination; pj_str_t desturi; BlabbleAccountPtr p = parent_.lock(); if (!p) return false; if (call_id_ == INVALID_CALL) return false; FB::VariantMap::const_iterator iter = params.find("destination"); if (iter == params.end()) { throw FB::script_error("No destination given!"); } else { destination = iter->second.cast<std::string>(); if (destination.size() <= 4 || destination.substr(0, 4) != "sip:") destination = "sip:" + destination + "@" + p->server(); if (p->use_tls() && destination.find("transport=TLS") == std::string::npos) destination += ";transport=TLS"; } if ((iter = params.find("onStatusChange")) != params.end() && iter->second.is_of_type<FB::JSObjectPtr>()) { set_on_transfer_status(iter->second.cast<FB::JSObjectPtr>()); } desturi.ptr = const_cast<char*>(destination.c_str()); desturi.slen = destination.length(); return pjsua_call_xfer(call_id_, &desturi, NULL) == PJ_SUCCESS; }