void WebConferenceDialog::connectConference(const string& room) { // set the conference id ('conference room') conf_id = room; // disconnect in/out for safety setInOut(NULL, NULL); // we need to be in the same callgroup as the other // people in the conference (important if we have multiple // MediaProcessor threads changeCallgroup(conf_id); // get a channel from the status if (channel.get() == NULL) channel.reset(AmConferenceStatus::getChannel(conf_id,getLocalTag())); else AmConferenceStatus::postConferenceEvent(conf_id, ConfNewParticipant,getLocalTag()); // clear the playlist play_list.close(); // add the channel to our playlist play_list.addToPlaylist(new AmPlaylistItem(channel.get(), channel.get())); // set the playlist as output and input if (muted) setInOut(NULL, &play_list); else setInOut(&play_list,&play_list); }
void AnswerMachineDialog::process(AmEvent* event) { AmAudioEvent* ae = dynamic_cast<AmAudioEvent*>(event); if(ae){ switch(ae->event_id){ case AmAudioEvent::noAudio: switch(status){ case 0: playlist.addToPlaylist(new AmPlaylistItem(NULL,&a_msg)); {AmArgArray di_args,ret; di_args.push(RECORD_TIMER); di_args.push(AnswerMachineFactory::MaxRecordTime); di_args.push(getLocalTag().c_str()); user_timer->invoke("setTimer",di_args,ret);} status = 1; break; case 1: a_beep.rewind(); playlist.addToPlaylist(new AmPlaylistItem(&a_beep,NULL)); status = 2; break; case 2: dlg.bye(); sendMailNotification(); setStopped(); break; } break; case AmAudioEvent::cleared: DBG("AmAudioEvent::cleared\n"); break; default: DBG("Unknown event id %i\n",ae->event_id); break; } return; } AmPluginEvent* plugin_event = dynamic_cast<AmPluginEvent*>(event); if(plugin_event && plugin_event->name == "timer_timeout" && plugin_event->data.get(0).asInt() == RECORD_TIMER) { // clear list playlist.close(); } else AmSession::process(event); }
void AmB2BCalleeSession::onB2BEvent(B2BEvent* ev) { if(ev->event_id == B2BConnectLeg){ B2BConnectEvent* co_ev = dynamic_cast<B2BConnectEvent*>(ev); if (!co_ev) return; MONITORING_LOG3(getLocalTag().c_str(), "b2b_leg", other_id.c_str(), "to", co_ev->remote_party.c_str(), "ruri", co_ev->remote_uri.c_str()); dlg.remote_party = co_ev->remote_party; dlg.remote_uri = co_ev->remote_uri; if (co_ev->relayed_invite) { relayed_req[dlg.cseq] = AmSipTransaction("INVITE", co_ev->r_cseq); } dlg.sendRequest("INVITE",co_ev->content_type,co_ev->body,co_ev->hdrs,SIP_FLAGS_VERBATIM); return; } AmB2BSession::onB2BEvent(ev); }
bool AmSession::removeTimer(int timer_id) { DBG("removing timer %d\n", timer_id); AmAppTimer::instance()->removeTimer(getLocalTag(), timer_id); return true; }
bool AmSession::removeTimers() { DBG("removing timers\n"); AmAppTimer::instance()->removeTimers(getLocalTag()); return true; }
void WebConferenceDialog::onSipReply(const AmSipReply& reply, int old_dlg_status) { //int status = dlg.getStatus(); AmSession::onSipReply(reply,old_dlg_status); if ((old_dlg_status < AmSipDialog::Connected) && (dlg.getStatus() == AmSipDialog::Disconnected)) { DBG("Call failed.\n"); setStopped(); } // update status to map if (is_dialout) { // map AmSipDialog state to WebConferenceState ConferenceRoomParticipant::ParticipantStatus rep_st = ConferenceRoomParticipant::Connecting; switch (dlg.getStatus()) { case AmSipDialog::Pending: { rep_st = ConferenceRoomParticipant::Connecting; if (reply.code == 180) rep_st = ConferenceRoomParticipant::Ringing; } break; case AmSipDialog::Connected: rep_st = ConferenceRoomParticipant::Connected; break; case AmSipDialog::Disconnecting: rep_st = ConferenceRoomParticipant::Disconnecting; break; case AmSipDialog::Disconnected: rep_st = ConferenceRoomParticipant::Finished; break; } DBG("is dialout: updateing status\n"); factory->updateStatus(dlg.user, getLocalTag(), rep_st, int2str(reply.code) + " " + reply.reason); } }
void AmB2BSession::setRtpRelayMode(RTPRelayMode mode) { DBG("enabled RTP relay mode for B2B call '%s'\n", getLocalTag().c_str()); rtp_relay_mode = mode; }
void ConferenceDialog::setupAudio() { if(!ConferenceFactory::JoinSound.empty()) { JoinSound.reset(new AmAudioFile()); if(JoinSound->open(ConferenceFactory::JoinSound, AmAudioFile::Read)) JoinSound.reset(0); } if(!ConferenceFactory::DropSound.empty()) { DropSound.reset(new AmAudioFile()); if(DropSound->open(ConferenceFactory::DropSound, AmAudioFile::Read)) DropSound.reset(0); } play_list.close();// !!! if(dialout_channel.get()){ DBG("adding dialout_channel to the playlist (dialedout = %i)\n",dialedout); play_list.addToPlaylist(new AmPlaylistItem(dialout_channel.get(), dialout_channel.get())); } else { channel.reset(AmConferenceStatus::getChannel(conf_id,getLocalTag())); play_list.addToPlaylist(new AmPlaylistItem(channel.get(), channel.get())); } setInOut(&play_list,&play_list); setCallgroup(conf_id); MONITORING_LOG(getLocalTag().c_str(), "conf_id", conf_id.c_str()); if(dialedout || !allow_dialout) { DBG("Dialout not enabled or dialout channel. Disabling DTMF detection.\n"); setDtmfDetectionEnabled(false); } }
void AmSession::setStopped(bool wakeup) { if (!sess_stopped.get()) { sess_stopped.set(true); onStop(); } if (wakeup) AmSessionContainer::instance()->postEvent(getLocalTag(), new AmEvent(0)); }
void WebConferenceDialog::onKicked() { DBG("########## WebConference::onKick #########\n"); dlg.bye(); disconnectConference(); factory->updateStatus(conf_id, getLocalTag(), ConferenceRoomParticipant::Disconnecting, "disconnect"); }
void AmB2BCalleeSession::onB2BEvent(B2BEvent* ev) { if(ev->event_id == B2BConnectLeg){ B2BConnectEvent* co_ev = dynamic_cast<B2BConnectEvent*>(ev); if (!co_ev) return; MONITORING_LOG3(getLocalTag().c_str(), "b2b_leg", getOtherId().c_str(), "to", co_ev->remote_party.c_str(), "ruri", co_ev->remote_uri.c_str()); dlg->setRemoteParty(co_ev->remote_party); dlg->setRemoteUri(co_ev->remote_uri); if (co_ev->relayed_invite) { AmSipRequest fake_req; fake_req.method = SIP_METH_INVITE; fake_req.cseq = co_ev->r_cseq; relayed_req[dlg->cseq] = fake_req; } AmMimeBody body(co_ev->body); try { updateLocalBody(body); } catch (const string& s) { relayError(SIP_METH_INVITE, co_ev->r_cseq, co_ev->relayed_invite, 500, SIP_REPLY_SERVER_INTERNAL_ERROR); throw; } int res = dlg->sendRequest(SIP_METH_INVITE, &body, co_ev->hdrs, SIP_FLAGS_VERBATIM); if (res < 0) { DBG("sending INVITE failed, relaying back error reply\n"); relayError(SIP_METH_INVITE, co_ev->r_cseq, co_ev->relayed_invite, res); if (co_ev->relayed_invite) relayed_req.erase(dlg->cseq); setStopped(); return; } saveSessionDescription(co_ev->body); // save CSeq of establising INVITE est_invite_cseq = dlg->cseq - 1; est_invite_other_cseq = co_ev->r_cseq; return; } AmB2BSession::onB2BEvent(ev); }
void ConferenceDialog::createDialoutParticipant(const string& uri_user) { string uri; uri = "sip:" + uri_user + dialout_suffix; dialout_channel.reset(AmConferenceStatus::getChannel(getLocalTag(),getLocalTag())); dialout_id = AmSession::getNewId(); ConferenceDialog* dialout_session = new ConferenceDialog(conf_id, AmConferenceStatus::getChannel(getLocalTag(), dialout_id)); AmSipDialog& dialout_dlg = dialout_session->dlg; dialout_dlg.local_tag = dialout_id; dialout_dlg.callid = AmSession::getNewId() + "@" + AmConfig::LocalIP; if (from_header.length() > 0) { dialout_dlg.local_party = from_header; } else { dialout_dlg.local_party = dlg.local_party; } dialout_dlg.remote_party = uri; dialout_dlg.remote_uri = uri; string body; int local_port = dialout_session->rtp_str.getLocalPort(); dialout_session->sdp.genRequest(AmConfig::LocalIP,local_port,body); if (extra_headers.length() == 0) { extra_headers = ""; } dialout_dlg.sendRequest("INVITE","application/sdp",body,extra_headers); dialout_session->start(); AmSessionContainer* sess_cont = AmSessionContainer::instance(); sess_cont->addSession(dialout_id,dialout_session); }
void WebConferenceDialog::onSessionStart(const AmSipRequest& req) { // direct room access? if (conf_id.empty()) { state = EnteringPin; prompts.addToPlaylist(ENTER_PIN, (long)this, play_list); // set the playlist as input and output setInOut(&play_list,&play_list); } else { DBG("########## direct connect conference #########\n"); factory->newParticipant(conf_id, getLocalTag(), dlg.remote_party); factory->updateStatus(conf_id, getLocalTag(), ConferenceRoomParticipant::Connected, "direct access: entered"); state = InConference; connectConference(conf_id); } }
void WebConferenceDialog::onBye(const AmSipRequest& req) { if (InConference == state) { factory->updateStatus(conf_id, getLocalTag(), ConferenceRoomParticipant::Disconnecting, req.method); } disconnectConference(); }
WebConferenceDialog::~WebConferenceDialog() { prompts.cleanup((long)this); play_list.close(false); if (is_dialout || (InConference == state)) { factory->updateStatus(is_dialout?dlg.user:conf_id, getLocalTag(), ConferenceRoomParticipant::Finished, ""); } }
void EarlyRecordDialog::onEarlySessionStart(const AmSipReply& req) { DBG("Early Session Start\n"); msg_filename = "/tmp/" + getLocalTag() + ".wav"; if(a_msg.open(msg_filename,AmAudioFile::Write,false)) throw string("EarlyRecordDialog: couldn't open ") + msg_filename + string(" for writing"); setInput(&a_msg); setMute(true); }
void DtmfTesterDialog::startSession(){ if(wav_file.open(filename,AmAudioFile::Read)) throw string("DtmfTesterDialog::onSessionStart: Cannot open file\n"); string rec_fname = "/tmp/dtmftest_"+getLocalTag()+".wav"; if(rec_file.open(rec_fname,AmAudioFile::Write)) throw string("DtmfTesterDialog::onSessionStart: Cannot open rec_file\n"); play_list.addToPlaylist(new AmPlaylistItem(&wav_file, NULL)); setInOut(&rec_file, &play_list); }
bool AmSession::setTimer(int timer_id, double timeout) { if (timeout <= 0.005) { DBG("setting timer %d with immediate timeout - posting Event\n", timer_id); AmTimeoutEvent* ev = new AmTimeoutEvent(timer_id); postEvent(ev); return true; } DBG("setting timer %d with timeout %f\n", timer_id, timeout); AmAppTimer::instance()->setTimer(getLocalTag(), timer_id, timeout); return true; }
void AmB2BSession::relayError(const string &method, unsigned cseq, bool forward, int sip_code, const char *reason) { if (method != "ACK") { AmSipReply n_reply; n_reply.code = sip_code; n_reply.reason = reason; n_reply.cseq = cseq; n_reply.cseq_method = method; n_reply.from_tag = dlg->getLocalTag(); DBG("relaying B2B SIP reply %d %s\n", sip_code, reason); relayEvent(new B2BSipReplyEvent(n_reply, forward, method, getLocalTag())); } }
void AmB2BSession::relayError(const string &method, unsigned cseq, bool forward, int err_code) { if (method != "ACK") { AmSipReply n_reply; errCode2RelayedReply(n_reply, err_code, 500); n_reply.cseq = cseq; n_reply.cseq_method = method; n_reply.from_tag = dlg->getLocalTag(); DBG("relaying B2B SIP error reply %u %s\n", n_reply.code, n_reply.reason.c_str()); relayEvent(new B2BSipReplyEvent(n_reply, forward, method, getLocalTag())); } }
void AmB2ABCallerSession::relayEvent(AmEvent* ev) { if(other_id.empty()){ B2ABConnectLegEvent* co_ev = dynamic_cast<B2ABConnectLegEvent*>(ev); if( co_ev ) { setupCalleeSession(createCalleeSession(), co_ev); if (other_id.length()) { MONITORING_LOG(getLocalTag().c_str(), "b2b_leg", other_id.c_str()); } } } AmB2ABSession::relayEvent(ev); }
void EarlyRecordDialog::onSessionStart(const AmSipReply& req) { setInOut(NULL, NULL); a_msg.close(); // replay the recorded early media msg_filename = "/tmp/" + getLocalTag() + ".wav"; if(a_msg.open(msg_filename,AmAudioFile::Read,false)) throw string("EarlyRecordDialog: couldn't open ") + msg_filename + string(" for writing"); setOutput(&a_msg); }
void AmB2ABCalleeSession::onB2ABEvent(B2ABEvent* ev) { if(ev->event_id == B2ABConnectLeg){ try { B2ABConnectLegEvent* co_ev = dynamic_cast<B2ABConnectLegEvent*>(ev); assert(co_ev); MONITORING_LOG4(getLocalTag().c_str(), "b2b_leg", other_id.c_str(), "from", co_ev->local_party.c_str(), "to", co_ev->remote_party.c_str(), "ruri", co_ev->remote_uri.c_str()); dlg.local_party = co_ev->local_party; dlg.local_uri = co_ev->local_uri; dlg.remote_party = co_ev->remote_party; dlg.remote_uri = co_ev->remote_uri; setCallgroup(co_ev->callgroup); setNegotiateOnReply(true); if (sendInvite(co_ev->headers)) { throw string("INVITE could not be sent\n"); } return; } catch(const AmSession::Exception& e){ ERROR("%i %s\n",e.code,e.reason.c_str()); relayEvent(new B2ABConnectOtherLegExceptionEvent(e.code,e.reason)); setStopped(); } catch(const string& err){ ERROR("startSession: %s\n",err.c_str()); relayEvent(new B2ABConnectOtherLegExceptionEvent(500,err)); setStopped(); } catch(...){ ERROR("unexpected exception\n"); relayEvent(new B2ABConnectOtherLegExceptionEvent(500,"unexpected exception")); setStopped(); } } AmB2ABSession::onB2ABEvent(ev); }
void ConferenceDialog::connectMainChannel() { dialout_id = ""; dialedout = false; dialout_channel.reset(NULL); play_list.close(); if(!channel.get()) channel.reset(AmConferenceStatus ::getChannel(conf_id, getLocalTag())); play_list.addToPlaylist(new AmPlaylistItem(channel.get(), channel.get())); }
void AmB2ABCallerSession::connectCallee(const string& remote_party, const string& remote_uri, const string& local_party, const string& local_uri, const string& headers) { if(callee_status != None) terminateOtherLeg(); B2ABConnectLegEvent* ev = new B2ABConnectLegEvent(remote_party,remote_uri, local_party,local_uri, getLocalTag(), // callgroup headers); // extra headers relayEvent(ev); callee_status = NoReply; }
WebConferenceDialog::~WebConferenceDialog() { // provide statistics if ((connect_ts == -1)||(disconnect_ts == -1)) { factory->callStats(false, 0); } else { factory->callStats(true, disconnect_ts - connect_ts); } prompts.cleanup((long)this); play_list.close(false); if (is_dialout || (InConference == state)) { factory->updateStatus(is_dialout?dlg.user:conf_id, getLocalTag(), ConferenceRoomParticipant::Finished, ""); } }
AmB2ABCalleeSession* ServiceLineCallerDialog::createCalleeSession() { ServiceLineCalleeDialog* sess = new ServiceLineCalleeDialog(getLocalTag()); AmSessionEventHandlerFactory* uac_auth_f = AmPlugIn::instance()->getFactory4Seh("uac_auth"); if (NULL != uac_auth_f) { DBG("UAC Auth enabled for new serviceline session.\n"); AmSessionEventHandler* h = uac_auth_f->getHandler(sess); if (h != NULL ) sess->addHandler(h); else { ERROR("unable to set SIP UAC auth for new session."); } } else { ERROR("unable to get SIP UAC auth." "(uac_auth module loaded?)\n"); } return sess; }
void AmB2BCallerSession::relayEvent(AmEvent* ev) { if(other_id.empty()){ if(dynamic_cast<B2BEvent*>(ev)){ B2BSipEvent* sip_ev = dynamic_cast<B2BSipEvent*>(ev); B2BConnectEvent* co_ev = dynamic_cast<B2BConnectEvent*>(ev); if( (sip_ev && sip_ev->forward) || co_ev ) { createCalleeSession(); if (other_id.length()) { MONITORING_LOG(getLocalTag().c_str(), "b2b_leg", other_id.c_str()); } } } } AmB2BSession::relayEvent(ev); }
int AmB2BCallerSession::relayEvent(AmEvent* ev) { if(getOtherId().empty() && !getStopped()){ bool create_callee = false; B2BSipEvent* sip_ev = dynamic_cast<B2BSipEvent*>(ev); if (sip_ev && sip_ev->forward) create_callee = true; else create_callee = dynamic_cast<B2BConnectEvent*>(ev) != NULL; if (create_callee) { createCalleeSession(); if (getOtherId().length()) { MONITORING_LOG(getLocalTag().c_str(), "b2b_leg", getOtherId().c_str()); } } } return AmB2BSession::relayEvent(ev); }
void ConferenceDialog::disconnectDialout() { if(dialedout){ if(dialout_channel.get()){ AmSessionContainer::instance() ->postEvent(dialout_channel->getConfID(), new DialoutConfEvent(DoConfDisconnect, dialout_channel->getConfID())); } } else { AmSessionContainer::instance() ->postEvent(dialout_id, new DialoutConfEvent(DoConfDisconnect, getLocalTag())); connectMainChannel(); } }