示例#1
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);
}
示例#2
0
void SipAccount::onCallState(pjsua_call_id call_id, pjsip_event* e) {
  Logger::debug("SipAccount::onCallState(call_id=%d)...", call_id);
  PJ_UNUSED_ARG(e);

  pjsua_call_info ci;
  pjsua_call_get_info(call_id, &ci);

  std::string display, number;
  if (!getNumber(&ci.remote_info, &display, &number)) {
    Logger::warn("invalid URI received '%s'", pj_strbuf(&ci.remote_info));
    return;
  }

  std::string state = std::string(pj_strbuf(&ci.state_text), ci.state_text.slen);
  Logger::debug("[%s] call state changed to %s", number.c_str(), state.c_str());

#if 1
  if (ci.state == PJSIP_INV_STATE_CONFIRMED) {
    Logger::debug("hangup...");
    // code 0: pj takes care of hangup SIP status code
    pj_status_t status = pjsua_call_hangup(call_id, 0, NULL, NULL);
    if (status != PJ_SUCCESS) {
      Logger::warn("pjsua_call_hangup() failed (%s)", Helper::getPjStatusAsString(status).c_str());
    }
  }
#endif
}
示例#3
0
/* Callback from timer when the maximum call duration has been
 * exceeded.
 */
static void call_timeout_callback(pj_timer_heap_t *timer_heap,
				  struct pj_timer_entry *entry)
{
    pjsua_call_id call_id = entry->id;
    pjsua_msg_data msg_data;
    pjsip_generic_string_hdr warn;
    pj_str_t hname = pj_str("Warning");
    pj_str_t hvalue = pj_str("399 pjsua \"Call duration exceeded\"");

    PJ_UNUSED_ARG(timer_heap);

    if (call_id == PJSUA_INVALID_ID) {
	PJ_LOG(1,(THIS_FILE, "Invalid call ID in timer callback"));
	return;
    }
    
    /* Add warning header */
    pjsua_msg_data_init(&msg_data);
    pjsip_generic_string_hdr_init2(&warn, &hname, &hvalue);
    pj_list_push_back(&msg_data.hdr_list, &warn);

    /* Call duration has been exceeded; disconnect the call */
    PJ_LOG(3,(THIS_FILE, "Duration (%d seconds) has been exceeded "
			 "for call %d, disconnecting the call",
			 app_config.duration, call_id));
    entry->id = PJSUA_INVALID_ID;
    pjsua_call_hangup(call_id, 200, NULL, &msg_data);
}
示例#4
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);
	}
}
示例#5
0
void call_hangup_fast(pjsua_call_id call_id,pjsua_call_info *p_call_info)
{
	pjsua_call_info call_info;
	if (!p_call_info) {
		if (pjsua_call_get_info(call_id, &call_info) == PJ_SUCCESS) {
			p_call_info = &call_info;
		}
	}
	if (p_call_info) {
		if (p_call_info->state==PJSIP_INV_STATE_CALLING
			|| (p_call_info->role==PJSIP_ROLE_UAS && p_call_info->state==PJSIP_INV_STATE_CONNECTING)
			) {
				pjsua_call *call = &pjsua_var.calls[call_id];
				pjsip_tx_data *tdata = NULL;
				// Generate an INVITE END message
				if (pjsip_inv_end_session(call->inv, 487, NULL, &tdata) != PJ_SUCCESS || !tdata) {
					pjsip_inv_terminate(call->inv,487,PJ_TRUE);
				} else {
					// Send that END request
					if (pjsip_endpt_send_request(pjsua_get_pjsip_endpt(), tdata, -1, NULL, NULL) != PJ_SUCCESS) {
						pjsip_inv_terminate(call->inv,487,PJ_TRUE);
					}
				}
				return;
		}
	}
	pjsua_call_hangup(call_id, 0, NULL, NULL);
}
示例#6
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());
}
示例#7
0
void QPhoneHandler::onHangup()
{
    pjsua_call_hangup(callId, 0, nullptr, nullptr);

    // TODO
    // view->setButtonText("Anrufen");
    // connect(view, SIGNAL(accept()), SLOT(onCall()));
}
void RinginDlg::OnBnClickedDecline()
{
	pjsua_call_info call_info;
	pjsua_call_get_info(call_id,&call_info);
	if (pjsua_call_hangup(call_id, 0, NULL, NULL) == PJ_SUCCESS) {
		microsipDlg->callIdImcomingIgnore = PjToStr(&call_info.call_id);
	}
	Close();
}
示例#9
0
void QVDoorcom::onHangupPressed() {
    popup->hide();
    if (active_call < 0) {
        return;
    }

    pjsua_call_info ci;
    if (!pjsua_call_get_info(active_call, &ci) == PJ_SUCCESS) {
        return;
    }
    pjsua_conf_disconnect(bell_port_id,0);
    qDebug() << pj2qstring( ci.state_text);
    if ((ci.state == PJSIP_INV_STATE_INCOMING) || (ci.state == PJSIP_INV_STATE_EARLY)) {
        pjsua_call_answer(active_call,486,NULL,NULL); /* Reject with busy */
        active_call = -1;
    } else if (ci.state == PJSIP_INV_STATE_CONNECTING) {
        pjsua_call_hangup(active_call,200,NULL,NULL); /* Hangup */
        active_call = -1;
    } else {
        if (!code_hangup.isEmpty()) {
#ifdef USE_INBAND
            pjmedia_tone_digit d[16];
            unsigned i, count = code_hangup.length();

            if (count > PJ_ARRAY_SIZE(d)) {
                count = PJ_ARRAY_SIZE(d);
            }

            pj_bzero(d, sizeof(d));
            int n=0;
            for (i=0; i<count; i++) {
                char code = code_hangup.at(i).toLatin1();
                qDebug() << "i" << i << code << "n" << n;
                if (((code < '0') || (code > '9')) && (code != '*') && (code != '#')) {
                    continue;
                }
                d[n].digit = code;
                d[n].on_msec = 200;
                d[n].off_msec = 200;
                d[n].volume = 0;
                n++;
            }
            pjmedia_tonegen_play_digits(pj_tonegen, n, d, 0);
#else
            pj_str_t code = pj_str(strdup(code_hangup.toUtf8().data()));
            pjsua_call_dial_dtmf(active_call,&code);
#endif
            hangup_timer.setInterval(400*code_hangup.length());
        } else {
            hangup_timer.setInterval(100);
        }
        qDebug() << "hangup timer started";
        hangup_timer.start();
    }
}
示例#10
0
//----------------------------------------------------------------------
void SipPhone::hangUp(const int &call_id)
{
    LogInfo info(LogInfo::STATUS_DEBUG, "psjip", 0, "hangup");
    LogHandler::getInstance().logData(info);

    pjsua_call_info ci;
    pjsua_call_get_info(call_id,&ci);

    pjsua_call_hangup(call_id,0,0,0);

    finishIncoming();
}
示例#11
0
/**
 * \fn _ics_core_hangup_call()
 * \brief Ket thuc cuoc goi
 * \param agr1: ics_t *data
 * agr2: int renew (1= hangup all, 0= hangup current call)
 */
static void _ics_core_hangup_call(ics_t *data, int renew) {
	if (current_call == PJSUA_INVALID_ID)
		printf("No current call\n");
	else {
		if (renew == -2) 
			pjsua_call_hangup_all();
		else {
			renew = current_call;
			pjsua_call_hangup(renew, 0, NULL, NULL);	
		}
	}
}
示例#12
0
文件: ics.c 项目: mocidis/ics
/**
 * \fn _ics_hangup_call()
 * \brief Ket thuc cuoc goi
 * \param agr1: ics_t *data
 * agr2: int renew (1= hangup all, 0= hangup current call)
 */
static void _ics_hangup_call(ics_t *data, int renew) {
    PJ_UNUSED_ARG(data);

    if (current_call == PJSUA_INVALID_ID)
        SHOW_LOG(3, "No current call\n");
    else {
        if (renew == -2) 
            pjsua_call_hangup_all();
        else {
            renew = current_call;
            pjsua_call_hangup(renew, 0, NULL, NULL);	
        }
    }
}
示例#13
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());
}
示例#14
0
static void ui_hangup_call(char menuin[])
{
    if (current_call == -1) {
	puts("No current call");
	fflush(stdout);
	return;

    } else if (menuin[1] == 'a') {
	/* Hangup all calls */
	pjsua_call_hangup_all();
    } else {
	/* Hangup current calls */
	pjsua_call_hangup(current_call, 0, NULL, NULL);
    }
}
示例#15
0
void QVDoorcom::onHangupTimer() {
    qDebug() << "hangup timer";
    if (active_call < 0) {
        return;
    }
    pjsua_call_info ci;
    if (!pjsua_call_get_info(active_call, &ci) == PJ_SUCCESS) {
        return;
    }
    if (ci.state != PJSIP_INV_STATE_CONFIRMED) {
        return;
    }
    pjsua_call_hangup(active_call,200,NULL,NULL);
    active_call = -1;
}
示例#16
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);
	}
}
示例#17
0
void SipAccount::onIncomingCall(pjsua_call_id call_id, pjsip_rx_data *rdata) {
  Logger::debug("SipAccount::onIncomingCall(call_id=%d)...", call_id);
  PJ_UNUSED_ARG(rdata);

  pj_status_t status = pjsua_call_set_user_data(call_id, this);
  if (status != PJ_SUCCESS) {
    Logger::error("pjsua_acc_set_user_data() failed (%s)", Helper::getPjStatusAsString(status).c_str());
  }

  pjsua_call_info ci;
  pjsua_call_get_info(call_id, &ci);

#if 0
  Logger::debug("local_info %s", pj_strbuf(&ci.local_info));
  Logger::debug("local_contact %s", pj_strbuf(&ci.local_contact));
  Logger::debug("remote_info %s", pj_strbuf(&ci.remote_info));
  Logger::debug("remote_contact %s", pj_strbuf(&ci.remote_contact));
  Logger::debug("call_id %s", pj_strbuf(&ci.call_id));
#endif

  std::string display, number;
  if (!getNumber(&ci.remote_info, &display, &number)) {
    Logger::warn("invalid URI received '%s'", pj_strbuf(&ci.remote_info));
    return;
  }

  std::string msg;
  bool block = false;
  if (number == "anonymous" or number == "") {
    block = m_pPhone->isAnonymousNumberBlocked(&m_settings.base, &msg);
  } else {
    block = m_pPhone->isNumberBlocked(&m_settings.base, number, &msg);
  }
  Logger::notice(msg.c_str());

#if 0
  // 302 redirect
  Use pjsua_call_hangup() and put the destination URL in the Contact
  header of the pjsua_msg_data.

  pj_pool_t* pool = pjsua_pool_create("", 512, 512);
  pjsua_msg_data msgData;
  pjsua_msg_data_init(&msgData);

  pj_str_t tmp;
  pjsip_generic_string_hdr* hdr =
    pjsip_generic_string_hdr_create(pool, pj_cstr(&tmp, "Contact"), pj_cstr(&tmp, "URI ...TODO"));
  pj_list_push_back(&msgData.hdr_list, hdr);
  // codes: http://de.wikipedia.org/wiki/SIP-Status-Codes
   // enum pjsip_status_code...
  pjsua_call_hangup(call_id, PJSIP_SC_MOVED_TEMPORARILY, NULL, &msgData);
  pj_pool_release(pool);
#endif

  if (block) {
    // answer incoming calls with 200/OK, then we hangup in onCallState...
    pj_status_t status = pjsua_call_answer(call_id, 200, NULL, NULL);
    if (status != PJ_SUCCESS) {
      Logger::warn("pjsua_call_answer() failed (%s)", Helper::getPjStatusAsString(status).c_str());
    }
  }
}
示例#18
0
static LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;

    switch (message) {
        case WM_KEYUP:

            if (wParam==114) {
                wParam = ID_MENU_CALL;
            } else if (wParam==115) {
                if (g_current_call == PJSUA_INVALID_ID)
                    wParam = ID_EXIT;
                else
                    wParam = ID_MENU_DISCONNECT;
            } else
                break;

        case WM_COMMAND:
            wmId    = LOWORD (wParam);
            wmEvent = HIWORD (wParam);

            if (wmId == ID_BTN_ACTION)
                wmId = g_current_action;

            switch (wmId) {
                case ID_MENU_CALL:

                    if (g_current_call != PJSUA_INVALID_ID) {
                        MessageBox (NULL, TEXT ("Can not make call"),
                                    TEXT ("You already have one call active"), MB_OK);
                    }

                    pj_str_t dst_uri;
                    wchar_t text[256];
                    char tmp[256];
                    pj_status_t status;

                    GetWindowText (hwndURI, text, PJ_ARRAY_SIZE (text));
                    pj_unicode_to_ansi (text, pj_unicode_strlen (text),
                                        tmp, sizeof (tmp));
                    dst_uri.ptr = tmp;
                    dst_uri.slen = pj_ansi_strlen (tmp);
                    status = pjsua_call_make_call (g_current_acc,
                                                   &dst_uri, 0, NULL,
                                                   NULL, &g_current_call);

                    if (status != PJ_SUCCESS)
                        OnError (TEXT ("Unable to make call"), status);

                    break;
                case ID_MENU_ANSWER:

                    if (g_current_call == PJSUA_INVALID_ID)
                        MessageBox (NULL, TEXT ("Can not answer"),
                                    TEXT ("There is no call!"), MB_OK);
                    else
                        pjsua_call_answer (g_current_call, 200, NULL, NULL);

                    break;
                case ID_MENU_DISCONNECT:

                    if (g_current_call == PJSUA_INVALID_ID)
                        MessageBox (NULL, TEXT ("Can not disconnect"),
                                    TEXT ("There is no call!"), MB_OK);
                    else
                        pjsua_call_hangup (g_current_call, PJSIP_SC_DECLINE, NULL, NULL);

                    break;
                case ID_EXIT:
                    DestroyWindow (hWnd);
                    break;
                default:
                    return DefWindowProc (hWnd, message, wParam, lParam);
            }

            break;

        case WM_CREATE:
            OnCreate (hWnd);
            break;

        case WM_DESTROY:
            OnDestroy();
            CommandBar_Destroy (hwndCB);
            PostQuitMessage (0);
            break;

        case WM_TIMER:
            pjsua_handle_events (1);
            break;

        default:
            return DefWindowProc (hWnd, message, wParam, lParam);
    }

    return 0;
}
示例#19
0
void endCall(int call_id)
{
	pjsua_call_id id = call_id;
	pjsua_call_hangup(id, 0, NULL, NULL);	
}
示例#20
0
/*
* Callback on media state changed event.
* The action may connect the call to sound device, to file, or
* to loop the call.
*/
static void on_call_media_state(pjsua_call_id call_id)
{
    pjsua_call_info call_info;

    pjsua_call_get_info(call_id, &call_info);

    /* Connect ports appropriately when media status is ACTIVE or REMOTE HOLD,
     * otherwise we should NOT connect the ports.
     */
    if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE ||
	call_info.media_status == PJSUA_CALL_MEDIA_REMOTE_HOLD)
    {
	pj_bool_t connect_sound = PJ_TRUE;

	/* Loopback sound, if desired */
	if (app_config.auto_loop) {
	    pjsua_conf_connect(call_info.conf_slot, call_info.conf_slot);
	    connect_sound = PJ_FALSE;
	}

	    /* Automatically record conversation, if desired */
	    if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) {
		pjsua_conf_connect(call_info.conf_slot, app_config.rec_port);
	    }

	/* Stream a file, if desired */
	if ((app_config.auto_play || app_config.auto_play_hangup) && 
	    app_config.wav_port != PJSUA_INVALID_ID)
	{
	    pjsua_conf_connect(app_config.wav_port, call_info.conf_slot);
	    connect_sound = PJ_FALSE;
	}

	/* Put call in conference with other calls, if desired */
	if (app_config.auto_conf) {
	    pjsua_call_id call_ids[PJSUA_MAX_CALLS];
	    unsigned call_cnt=PJ_ARRAY_SIZE(call_ids);
	    unsigned i;

	    /* Get all calls, and establish media connection between
	     * this call and other calls.
	     */
	    pjsua_enum_calls(call_ids, &call_cnt);

	    for (i=0; i<call_cnt; ++i) {
		if (call_ids[i] == call_id)
		    continue;
		
		if (!pjsua_call_has_media(call_ids[i]))
		    continue;

		pjsua_conf_connect(call_info.conf_slot,
				   pjsua_call_get_conf_port(call_ids[i]));
		pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]),
				   call_info.conf_slot);

		/* Automatically record conversation, if desired */
		if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) {
		    pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]), 
				       app_config.rec_port);
		}

	    }

	    /* Also connect call to local sound device */
	    connect_sound = PJ_TRUE;
	}

	/* Otherwise connect to sound device */
	if (connect_sound) {
	    pjsua_conf_connect(call_info.conf_slot, 0);
	    pjsua_conf_connect(0, call_info.conf_slot);

	    /* Automatically record conversation, if desired */
	    if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) {
		pjsua_conf_connect(call_info.conf_slot, app_config.rec_port);
		pjsua_conf_connect(0, app_config.rec_port);
	    }
	}
    }

	PJ_LOG(3,(THIS_FILE, "Media for call %d is active", call_id));

    /* Handle media status */
    switch (call_info.media_status) {
    case PJSUA_CALL_MEDIA_ACTIVE:
	PJ_LOG(3,(THIS_FILE, "Media for call %d is active", call_id));
	break;

    case PJSUA_CALL_MEDIA_LOCAL_HOLD:
	PJ_LOG(3,(THIS_FILE, "Media for call %d is suspended (hold) by local",
		  call_id));
  // call on call hold handler
  cb_callholdconf(call_id);
	break;

    case PJSUA_CALL_MEDIA_REMOTE_HOLD:
	PJ_LOG(3,(THIS_FILE, 
		  "Media for call %d is suspended (hold) by remote",
		  call_id));
	break;

    case PJSUA_CALL_MEDIA_ERROR:
	PJ_LOG(3,(THIS_FILE,
		  "Media has reported error, disconnecting call"));
	{
	    pj_str_t reason = pj_str("ICE negotiation failed");
	pjsua_call_hangup(call_id, 500, &reason, NULL);
	}
	break;

    case PJSUA_CALL_MEDIA_NONE:
	PJ_LOG(3,(THIS_FILE, 
		  "Media for call %d is inactive",
		  call_id));
	break;

    default:
	pj_assert(!"Unhandled media status");
	break;
    }
}
示例#21
0
/*
 * main()
 *
 * argv[] contains the registration information.
 */
int main(int argc, char *argv[]) {
  pj_status_t status;
  int loglevel = 0;

  if (argc < 4) {
    usage(argv[0]);
    exit(1);
  }

  if (argc > 5){
    sscanf(argv[5], "%d", &loglevel);
  }

  pjsua_acc_id acc_id;

  /* Create pjsua first! */
  status = pjsua_create();
  if (status != PJ_SUCCESS) error_exit("Error in pjsua_create()", status);


  /* Init pjsua */
  {
    pjsua_config cfg;
    pjsua_logging_config log_cfg;
    pjsua_media_config media_cfg;

    // This will prevent the SIP stack from trying to switch to TCP.
    // It will prevent the stack from giving "Transport unavailable" errors.
    // http://trac.pjsip.org/repos/wiki/Using_SIP_TCP
    pjsip_cfg()->endpt.disable_tcp_switch = PJ_TRUE;

    pjsua_config_default(&cfg);
    cfg.cb.on_incoming_call    = &on_incoming_call;
    cfg.cb.on_call_media_state = &on_call_media_state;
    cfg.cb.on_call_state       = &on_call_state;
    cfg.cb.on_call_tsx_state   = &on_call_tsx_state;

    pjsua_logging_config_default(&log_cfg);
    log_cfg.console_level = loglevel; // 0 = Mute console, 3 = somewhat useful, 4 = overly verbose.
    pjsua_media_config_default(&media_cfg);

    status = pjsua_init(&cfg, &log_cfg, &media_cfg);
    if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status);
  }
  /* Add UDP transport. */
  {
    pjsua_transport_config cfg;

    pjsua_transport_config_default(&cfg);
    sscanf(argv[4], "%d", &cfg.port);
    status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, NULL);
    if (status != PJ_SUCCESS) error_exit("Error creating transport", status);
    printf("Created UDP transport on port %d.\n", cfg.port);
  }

 /* Initialization is done, now start pjsua */
  status = pjsua_start();
  if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status);

  /* Register to SIP server by creating SIP account. */
  {
    char reg_uri_buf[80] = "sip:";

    char uri_buf[80] = "sip:";
    pjsua_acc_config cfg;
    char* username = argv[1];
    char* password = argv[2];
    char* domain   = argv[3];

    strcat (uri_buf, username);
    strcat (reg_uri_buf, domain);

    strcat (uri_buf, "@");
    strcat (uri_buf, domain);

    pjsua_acc_config_default(&cfg);
    cfg.id = pj_str(uri_buf);

    printf("Registering: %.*s.\n", (int)cfg.id.slen, cfg.id.ptr);

    cfg.reg_uri = pj_str(reg_uri_buf);
    cfg.cred_count = 1;
    cfg.cred_info[0].realm = pj_str(domain);
    cfg.cred_info[0].scheme = pj_str("Digest");
    cfg.cred_info[0].username = pj_str(username);
    cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
    cfg.cred_info[0].data = pj_str(password);
    cfg.register_on_acc_add = PJ_FALSE;


    status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
    if (status != PJ_SUCCESS) error_exit("Error adding account", status);

    or_event(OR_READY, "Agent initialized..");

  }

  /* Start by muting the audio device. This a passive agent, and sound
     is just wasted CPU time and uwanted side effects. */
  pjsua_set_null_snd_dev();
  fflush(stdout);
  /* Wait until user press "q" to quit. */
  for (;;) {
    char option[256];

    if (fgets(option, sizeof (option), stdin) == NULL) {
      or_status (OR_ERROR, "EOF while reading stdin, will quit now..");
      break;
    }

    /* Dial command. */
    if (option[0] == 'd') {
      pj_str_t uri = pj_str(&option[1]);
      status = pjsua_call_make_call(acc_id, &uri, 0, NULL, NULL, NULL);
      if (status != PJ_SUCCESS) {
        or_status (OR_ERROR, "Could not make call");
      }
      else {
        or_status (OR_OK, "Dialling...");
      }
    }

    /* Register */
    else if (option[0] == 'r') {
      register_account(acc_id);
    }

    /* Unregister */
    else if (option[0] == 'u') {
      unregister_account(acc_id);
    }

    /* Enable autoanswer */
    else if (option[0] == 'a') {
      if (option[1] == '1') {
        autoanswer[0] = true;
        or_status(OR_OK, "Autoanswer enabled.");
      } else {
        or_status(OR_ERROR, "Invalid account.");
      }
    }

    /* Disable autoanswer (manual answer) */
    else if (option[0] == 'm') {
      autoanswer[0] = false;
      or_status(OR_OK, "Autoanswer disabled.");
    }

    /* Pickup incoming call, unsupported for now. */
    else if (option[0] == 'p') {
      if (current_call != PJSUA_INVALID_ID) {
        pjsua_call_answer(current_call, 200, NULL, NULL);
        or_status(OR_OK, "Call picked up.");
      } else {
        or_status(OR_ERROR, "No call to pick up.");
      }
    }

    /* Hang up current call */
    else if (option[0] == 'H') {
      if (current_call != PJSUA_INVALID_ID) {
        pjsua_call_hangup (current_call, 0,NULL, NULL);
        or_status (OR_OK, "Hanging up current call...");
      } else {
        or_status(OR_ERROR, "No call to hang up.");
      }
    }

    /* Full hangup.. */
    else if (option[0] == 'h') {
      pjsua_call_hangup_all();
      or_status (OR_OK, "Hanging up all calls...");
    }

    /* Status  */
    else if (option[0] == 's') {
      or_dump_status();
    }

    /* Exit application. */
    else if (option[0] == 'q') {
      break;
    }

    else {
      or_status (OR_ERROR, "Unknown command:");
    }
  }
  pjsua_destroy();
  or_status (OR_OK, "Exiting...");

  return 0;
}