示例#1
0
// 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);
	}
}
示例#2
0
//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);
	}

}
示例#3
0
void PjsuaManager::AddAccount(const BlabbleAccountPtr &account)
{
	if (account->id() == INVALID_ACCOUNT)
		throw std::runtime_error("Attempt to add uninitialized account.");

	accounts_[account->id()] = account;
}
示例#4
0
//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());
}
示例#5
0
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);
		}
	}
}
示例#6
0
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));
}
示例#7
0
//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);
}
示例#8
0
//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());
}
示例#9
0
//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);
	}
}
示例#10
0
//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);
	}
}
示例#11
0
bool BlabbleCall::Transfer(const FB::VariantMap &params)
{
	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;
}