//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); }
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 }
/* 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); }
// 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); } }
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); }
//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 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(); }
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(); } }
//---------------------------------------------------------------------- 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(); }
/** * \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); } } }
/** * \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); } } }
//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 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); } }
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; }
//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); } }
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()); } } }
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; }
void endCall(int call_id) { pjsua_call_id id = call_id; pjsua_call_hangup(id, 0, NULL, NULL); }
/* * 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; } }
/* * 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; }