// outgoing calls AmSession* WebConferenceFactory::onInvite(const AmSipRequest& req, AmArg& session_params) { UACAuthCred* cred = NULL; if (session_params.getType() == AmArg::AObject) { ArgObject* cred_obj = session_params.asObject(); if (cred_obj) cred = dynamic_cast<UACAuthCred*>(cred_obj); } AmSession* s = new WebConferenceDialog(prompts, getInstance(), cred); AmSessionEventHandlerFactory* uac_auth_f = AmPlugIn::instance()->getFactory4Seh("uac_auth"); if (uac_auth_f != NULL) { DBG("UAC Auth enabled for new announcement session.\n"); AmSessionEventHandler* h = uac_auth_f->getHandler(s); if (h != NULL ) s->addHandler(h); } else { ERROR("uac_auth interface not accessible. Load uac_auth for authenticated dialout.\n"); } s->setUri(getAccessUri(req.user)); return s; }
string DIDial::dialout_pin(const string& application, const string& pin, const string& user, const string& to_user ) { DBG("dialout application '%s', user '%s', to_user '%s', pin '%s'", application.c_str(), user.c_str(), to_user.c_str(), pin.c_str()); // find pin map<string, DIDialoutInfo>::iterator it = DIDialFactory::dialout_pins.find(pin); if (it != DIDialFactory::dialout_pins.end()) { AmArg* a = new AmArg(); a->setBorrowedPointer(new UACAuthCred(it->second.realm, it->second.user, it->second.pwd)); AmSession* s = AmUAC::dialout(user.c_str(), application, "sip:"+to_user+"@"+it->second.realm, "<sip:" + it->second.user+"@"+it->second.realm + ">", "sip:"+it->second.user+"@"+it->second.realm, "<sip:" + to_user+"@"+it->second.realm + ">", string(""), // callid a); if (s) return s->getLocalTag(); else return "<failed>\n"; } else return "incorrect dialout pin.\n"; }
AmSession* AmSessionContainer::startSessionUAC(AmSipRequest& req) { AmSession* session = NULL; as_mut.lock(); try { if((session = createSession(req)) != 0){ session->dlg.updateStatusFromLocalRequest(req); // sets local tag as well session->setCallgroup(req.from_tag); session->setNegotiateOnReply(true); session->sendInvite(); session->start(); addSession_unsafe(req.callid,req.from_tag,req.from_tag,session); // session does not get its own INVITE // session->postEvent(new AmSipRequestEvent(req)); } } catch(const AmSession::Exception& e){ ERROR("%i %s\n",e.code,e.reason.c_str()); AmSipDialog::reply_error(req,e.code,e.reason); } catch(const string& err){ ERROR("startSession: %s\n",err.c_str()); AmSipDialog::reply_error(req,500,err); } catch(...){ ERROR("unexpected exception\n"); AmSipDialog::reply_error(req,500,"unexpected exception"); } as_mut.unlock(); return session; }
AmSession* AnnouncementFactory::onInvite(const AmSipRequest& req, AmArg& session_params) { UACAuthCred* cred = NULL; if (session_params.getType() == AmArg::AObject) { ArgObject* cred_obj = session_params.asObject(); if (cred_obj) cred = dynamic_cast<UACAuthCred*>(cred_obj); } AmSession* s = new AnnouncementDialog(getAnnounceFile(req), cred); if (NULL == cred) { WARN("discarding unknown session parameters.\n"); } else { AmSessionEventHandlerFactory* uac_auth_f = AmPlugIn::instance()->getFactory4Seh("uac_auth"); if (uac_auth_f != NULL) { DBG("UAC Auth enabled for new announcement session.\n"); AmSessionEventHandler* h = uac_auth_f->getHandler(s); if (h != NULL ) s->addHandler(h); } else { ERROR("uac_auth interface not accessible. " "Load uac_auth for authenticated dialout.\n"); } } return s; }
/** * process pending DTMF events */ void AmMediaProcessorThread::processDtmfEvents() { for(set<AmSession*>::iterator it = sessions.begin(); it != sessions.end(); it++) { AmSession* s = (*it); s->processDtmfEvents(); } }
void AmMediaProcessorThread::process(AmEvent* e) { SchedRequest* sr = dynamic_cast<SchedRequest*>(e); if(!sr){ ERROR("AmMediaProcessorThread::process: wrong event type\n"); return; } switch(sr->event_id){ case AmMediaProcessor::InsertSession: DBG("Session inserted to the scheduler\n"); sessions.insert(sr->s); break; case AmMediaProcessor::RemoveSession:{ AmSession* s = sr->s; set<AmSession*>::iterator s_it = sessions.find(s); if(s_it != sessions.end()){ sessions.erase(s_it); s->detached.set(true); DBG("Session removed from the scheduler\n"); } } break; case AmMediaProcessor::ClearSession:{ AmSession* s = sr->s; set<AmSession*>::iterator s_it = sessions.find(s); if(s_it != sessions.end()){ sessions.erase(s_it); s->clearAudio(); s->detached.set(true); DBG("Session removed from the scheduler\n"); } } break; case AmMediaProcessor::SoftRemoveSession:{ AmSession* s = sr->s; set<AmSession*>::iterator s_it = sessions.find(s); if(s_it != sessions.end()){ sessions.erase(s_it); DBG("Session removed softly from the scheduler\n"); } } break; default: ERROR("AmMediaProcessorThread::process: unknown event id."); break; } }
void WebConferenceFactory::dialout(const AmArg& args, AmArg& ret) { for (int i=0;i<6;i++) assertArgCStr(args.get(1)); string room = args.get(0).asCStr(); string adminpin = args.get(1).asCStr(); string callee = args.get(2).asCStr(); string from_user = args.get(3).asCStr(); string domain = args.get(4).asCStr(); string auth_user = args.get(5).asCStr(); string auth_pwd = args.get(6).asCStr(); string from = "sip:" + from_user + "@" + domain; string to = "sip:" + callee + "@" + domain; // check adminpin rooms_mut.lock(); ConferenceRoom* r = getRoom(room, adminpin); rooms_mut.unlock(); if (NULL == r) { ret.push(1); ret.push("wrong adminpin"); ret.push(""); return; } DBG("dialout webconference room '%s', from '%s', to '%s'", room.c_str(), from.c_str(), to.c_str()); AmArg* a = new AmArg(); a->setBorrowedPointer(new UACAuthCred("", auth_user, auth_pwd)); AmSession* s = AmUAC::dialout(room.c_str(), APP_NAME, to, "<" + from + ">", from, "<" + to + ">", string(""), // local tag string(""), // hdrs a); if (s) { string localtag = s->getLocalTag(); ret.push(0); ret.push("OK"); ret.push(localtag.c_str()); newParticipant(room, localtag, to); updateStatus(room, localtag, ConferenceRoomParticipant::Connecting, "INVITE"); } else { ret.push(1); ret.push("internal error"); ret.push(""); } }
void AmZRTP::on_zrtp_protocol_event(zrtp_stream_t *stream, zrtp_protocol_event_t event) { DBG("on_zrtp_protocol_event(stream [%p])\n", stream); if (NULL==stream) { ERROR("event received without stream context.\n"); return; } void* udata = zrtp_stream_get_userdata(stream); if (NULL == udata) { ERROR("ZRTP on_send_packet without session set context.\n"); return; } AmSession* sess = reinterpret_cast<AmSession*>(udata); sess->postEvent(new AmZRTPProtocolEvent(event, stream)); }
string DIDial::dialout(const string& application, const string& user, const string& from, const string& to) { DBG("dialout application '%s', user '%s', from '%s', to '%s'", application.c_str(), user.c_str(), from.c_str(), to.c_str()); AmSession* s = AmUAC::dialout(user.c_str(), application, to, "<" + from + ">", from, "<" + to + ">"); if (s) return s->getLocalTag(); else return "<failed>"; }
void zrtp_event_callback(zrtp_event_t event, zrtp_stream_ctx_t *stream_ctx) { if (NULL==stream_ctx) { ERROR("event received without stream context.\n"); return; } AmSession* sess = reinterpret_cast<AmSession*>(stream_ctx->stream_usr_data); if (NULL==sess) { ERROR("event received without session set up.\n"); return; } sess->postEvent(new AmZRTPEvent(event, stream_ctx)); }
int AmZRTP::on_send_packet(const zrtp_stream_t *stream, char *packet, unsigned int length) { DBG("on_send_packet(stream [%p], len=%u)\n", stream, length); if (NULL==stream) { ERROR("on_send_packet without stream context.\n"); return -1; } void* udata = zrtp_stream_get_userdata(stream); if (NULL == udata) { ERROR("ZRTP on_send_packet without session context.\n"); return -1; } AmSession* sess = reinterpret_cast<AmSession*>(udata); return sess->RTPStream()->send_raw(packet, length); }
void AmSessionContainer::startSessionUAS(AmSipRequest& req) { as_mut.lock(); try { AmSession* session = getSession(req.callid,req.from_tag); if( session ){ // it's a forked-and-merged INVITE // reply 482 Loop detected throw AmSession::Exception(482, "Loop detected"); } else { // Call-ID and From-Tag are unknown: it's a new session AmSession* session; if((session = createSession(req)) != 0){ string local_tag = AmSession::getNewId(); session->setLocalTag(local_tag); session->setCallgroup(local_tag); session->start(); addSession_unsafe(req.callid,req.from_tag,local_tag,session); session->postEvent(new AmSipRequestEvent(req)); } //else //throw AmSession::Exception(500,"internal error"); } } // catch(const AmSession::SessionTimerException& e){ // ERROR("%i %s\n",e.code,e.reason.c_str()); // AmSipDialog::reply_error(req,e.code,e.reason,e.getErrorHeaders()); // } catch(const AmSession::Exception& e){ ERROR("%i %s\n",e.code,e.reason.c_str()); AmSipDialog::reply_error(req,e.code,e.reason); } catch(const string& err){ ERROR("startSession: %s\n",err.c_str()); AmSipDialog::reply_error(req,500,err); } catch(...){ ERROR("unexpected exception\n"); AmSipDialog::reply_error(req,500,"unexpected exception"); } as_mut.unlock(); }
AmSession* EchoFactory::onInvite(const AmSipRequest& req) { AmSession* s = new EchoDialog(); if (NULL != session_timer_f) { AmSessionEventHandler* h = session_timer_f->getHandler(s); if(h->configure(conf)){ ERROR("Could not configure the session timer: disabling session timers.\n"); delete h; } else { s->addHandler(h); } } return s; }
bool AmSessionContainer::postEvent(const string& callid, const string& remote_tag, AmEvent* event) { // DBG("postEvent: callid = %s; remote_tag = %s\n", // callid.c_str(),remote_tag.c_str()); as_mut.lock(); AmSession* s = getSession(callid,remote_tag); as_mut.unlock(); if(!s){ delete event; return false; } s->postEvent(event); return true; }
void AmSessionContainer::destroySession(const string& local_tag) { as_mut.lock(); SessionMapIter sess_it = a_sessions.find(local_tag); if(sess_it != a_sessions.end()){ AmSession* sess = sess_it->second; as_id_lookup.erase(sess->getCallID() + sess->getRemoteTag()); a_sessions.erase(sess_it); stopAndQueue(sess); DBG("session stopped and queued for deletion (#sessions=%u)\n", (unsigned int)a_sessions.size()); } else { DBG("could not remove session: id not found\n"); } as_mut.unlock(); }
bool AmSessionContainer::postEvent(const string& local_tag, AmEvent* event) { // DBG("postEvent: local_tag = %s\n",local_tag.c_str()); as_mut.lock(); AmSession* s = getSession(local_tag); as_mut.unlock(); if (s != NULL) { s->postEvent(event); return true; } // try session factories AmSessionFactory* sf = AmPlugIn::instance()->getFactory4App(local_tag); if (sf != NULL) { sf->postEvent(event); return true; } delete event; return false; }
string DIDial::dialout_auth(const string& application, const string& user, const string& from, const string& to, const string& a_realm, const string& a_user, const string& a_pwd ) { DBG("dialout application '%s', user '%s', from '%s', to '%s'", application.c_str(), user.c_str(), from.c_str(), to.c_str()); AmArg* a = new AmArg(); a->setBorrowedPointer(new UACAuthCred(a_realm, a_user, a_pwd)); AmSession* s = AmUAC::dialout(user.c_str(), application, to, "<" + from + ">", from, "<" + to + ">", string(""), // callid a); if (s) return s->getLocalTag(); else return "<failed>\n"; }
void AmSessionContainer::startSessionUAS(AmSipRequest& req) { as_mut.lock(); try { AmSession* session = getSession(req.callid,req.from_tag); if( session ){ // it's a forked-and-merged INVITE // reply 482 Loop detected throw AmSession::Exception(482, "Loop detected"); } else { // Call-ID and From-Tag are unknown: it's a new session AmSession* session; if((session = createSession(req)) != 0){ // update session's local tag (ID) if not already set session->setLocalTag(); const string& local_tag = session->getLocalTag(); // by default each session is in its own callgroup session->setCallgroup(local_tag); if (AmConfig::LogSessions) { INFO("Starting UAS session %s app %s\n", session->getLocalTag().c_str(), req.cmd.c_str()); } session->start(); addSession_unsafe(req.callid,req.from_tag,local_tag,session); session->postEvent(new AmSipRequestEvent(req)); } } } catch(const AmSession::Exception& e){ ERROR("%i %s\n",e.code,e.reason.c_str()); AmSipDialog::reply_error(req,e.code,e.reason); } catch(const string& err){ ERROR("startSession: %s\n",err.c_str()); AmSipDialog::reply_error(req,500,err); } catch(...){ ERROR("unexpected exception\n"); AmSipDialog::reply_error(req,500,"unexpected exception"); } as_mut.unlock(); }
AmSession* AmSessionContainer::startSessionUAC(AmSipRequest& req, AmArg* session_params) { AmSession* session = NULL; as_mut.lock(); try { if((session = createSession(req, session_params)) != 0){ session->dlg.updateStatusFromLocalRequest(req); // sets local tag as well session->setCallgroup(req.from_tag); session->setNegotiateOnReply(true); if (int err = session->sendInvite(req.hdrs)) { ERROR("INVITE could not be sent: error code = %d.\n", err); delete session; as_mut.unlock(); return NULL; } if (AmConfig::LogSessions) { INFO("Starting UAC session %s app %s\n", session->getLocalTag().c_str(), req.cmd.c_str()); } session->start(); addSession_unsafe(req.callid,"",req.from_tag,session); // session does not get its own INVITE // session->postEvent(new AmSipRequestEvent(req)); } } catch(const AmSession::Exception& e){ ERROR("%i %s\n",e.code,e.reason.c_str()); AmSipDialog::reply_error(req,e.code,e.reason); } catch(const string& err){ ERROR("startSession: %s\n",err.c_str()); AmSipDialog::reply_error(req,500,err); } catch(...){ ERROR("unexpected exception\n"); AmSipDialog::reply_error(req,500,"unexpected exception"); } as_mut.unlock(); return session; }
void AmMediaProcessorThread::processAudio(unsigned int ts) { for(set<AmSession*>::iterator it = sessions.begin(); it != sessions.end(); it++){ AmSession* s = (*it); s->lockAudio(); AmAudio* input = s->getInput(); if(s->rtp_str.checkInterval(ts)){ //DBG("ts = %u\n",ts); int ret = s->rtp_str.receive(ts); if(ret < 0){ switch(ret){ case RTP_DTMF: case RTP_UNKNOWN_PL: case RTP_PARSE_ERROR: break; case RTP_TIMEOUT: postRequest(new SchedRequest(AmMediaProcessor::RemoveSession,s)); s->postEvent(new AmRtpTimeoutEvent()); break; case RTP_BUFFER_SIZE: default: ERROR("AmRtpAudio::receive() returned %i\n",ret); postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); break; } } else { unsigned int f_size = s->rtp_str.getFrameSize(); int size = s->rtp_str.get(ts,buffer,f_size); if (input) { int ret = input->put(ts,buffer,size); if(ret < 0){ DBG("input->put() returned: %i\n",ret); postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); } } if (s->isDtmfDetectionEnabled()) s->putDtmfAudio(buffer, size, ts); } } s->unlockAudio(); } for(set<AmSession*>::iterator it = sessions.begin(); it != sessions.end(); it++){ AmSession* s = (*it); s->lockAudio(); AmAudio* output = s->getOutput(); if(output && s->rtp_str.sendIntReached()){ int size = output->get(ts,buffer,s->rtp_str.getFrameSize()); if(size <= 0){ DBG("output->get() returned: %i\n",size); postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); //removeSession(s); } else if(!s->rtp_str.mute){ if(s->rtp_str.put(ts,buffer,size)<0) postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); // removeSession(s); } } s->unlockAudio(); } }
void AmMediaProcessorThread::processAudio(unsigned int ts) { // receiving for(set<AmSession*>::iterator it = sessions.begin(); it != sessions.end(); it++){ AmSession* s = (*it); // todo: get frame size/checkInterval from local audio if local in+out (?) unsigned int frame_length = s->rtp_str.getFrameLength(); // ms // complete frame time reached? if (s->rtp_str.checkInterval(ts)) { s->lockAudio(); int rcvd_audio_len = -1; // get/receive audio if (!s->getAudioLocal(AM_AUDIO_IN)) { // input is not local - receive from rtp stream if (s->rtp_str.receiving || s->rtp_str.getPassiveMode()) { int ret = s->rtp_str.receive(ts); if(ret < 0){ switch(ret){ case RTP_DTMF: case RTP_UNKNOWN_PL: case RTP_PARSE_ERROR: break; case RTP_TIMEOUT: postRequest(new SchedRequest(AmMediaProcessor::RemoveSession,s)); s->postEvent(new AmRtpTimeoutEvent()); break; case RTP_BUFFER_SIZE: default: ERROR("AmRtpAudio::receive() returned %i\n",ret); postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); break; } } else { rcvd_audio_len = s->rtp_str.get(ts,buffer,frame_length); if (s->isDtmfDetectionEnabled() && rcvd_audio_len > 0) s->putDtmfAudio(buffer, rcvd_audio_len, ts); } } } else { // input is local - get audio from local_in AmAudio* local_input = s->getLocalInput(); if (local_input) { rcvd_audio_len = local_input->get(ts,buffer,frame_length); } } // process received audio if (rcvd_audio_len >= 0) { AmAudio* input = s->getInput(); if (input) { int ret = input->put(ts,buffer,rcvd_audio_len); if(ret < 0){ DBG("input->put() returned: %i\n",ret); postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); } } } s->unlockAudio(); } } // sending for(set<AmSession*>::iterator it = sessions.begin(); it != sessions.end(); it++){ AmSession* s = (*it); s->lockAudio(); AmAudio* output = s->getOutput(); if(output && s->rtp_str.sendIntReached()){ unsigned int frame_length = s->rtp_str.getFrameLength(); int size = output->get(ts,buffer,frame_length); if(size <= 0){ DBG("output->get() returned: %i\n",size); postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); } else { if (!s->getAudioLocal(AM_AUDIO_OUT)) { // audio should go to RTP if(!s->rtp_str.mute){ if(s->rtp_str.put(ts,buffer,size)<0) postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); } } else { // output is local - audio should go in local_out AmAudio* local_output = s->getLocalOutput(); if (local_output) { if (local_output->put(ts,buffer,size)) { postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); } } } } } s->unlockAudio(); } }
void WebConferenceFactory::dialout(const AmArg& args, AmArg& ret) { for (int i=0;i<6;i++) assertArgCStr(args.get(i)); string room = args.get(0).asCStr(); string adminpin = args.get(1).asCStr(); string callee = args.get(2).asCStr(); string from_user = args.get(3).asCStr(); string domain = args.get(4).asCStr(); string auth_user = args.get(5).asCStr(); string auth_pwd = args.get(6).asCStr(); string callee_domain; string headers; try { assertArgCStr(args.get(7)); headers = args.get(7).asCStr(); int i, len; len = headers.length(); for (i = 0; i < len; i++) { if (headers[i] == '|') headers[i] = '\n'; } if (headers[len - 1] != '\n') { headers += '\n'; } } catch (AmArg::OutOfBoundsException &e) { headers = ""; } try { assertArgCStr(args.get(8)); callee_domain = args.get(8).asCStr(); } catch (AmArg::OutOfBoundsException &e) { callee_domain = domain; } string from = "sip:" + from_user + "@" + domain; string to = "sip:" + callee + "@" + callee_domain; // check adminpin rooms_mut.lock(); // sweep rooms (if necessary) sweepRooms(); ConferenceRoom* r = getRoom(room, adminpin); rooms_mut.unlock(); if (NULL == r) { ret.push(1); ret.push("wrong adminpin"); ret.push(""); return; } DBG("dialout webconference room '%s', from '%s', to '%s'", room.c_str(), from.c_str(), to.c_str()); AmArg* a = new AmArg(); a->setBorrowedPointer(new UACAuthCred("", auth_user, auth_pwd)); AmSession* s = AmUAC::dialout(room.c_str(), APP_NAME, to, "<" + from + ">", from, "<" + to + ">", string(""), // callid headers, // headers a); if (s) { string localtag = s->getLocalTag(); ret.push(0); ret.push("OK"); ret.push(localtag.c_str()); newParticipant(room, localtag, to); updateStatus(room, localtag, ConferenceRoomParticipant::Connecting, "INVITE"); } else { ret.push(1); ret.push("internal error"); ret.push(""); } }
AmSession* Click2DialFactory::onInvite(const AmSipRequest& req, AmArg& session_params) { UACAuthCred* cred = NULL; string callee_uri, a_realm, a_user, a_pwd; if(session_params.size() != 4) { ERROR("Need 4 parameters, got %lu\n", (long unsigned int)session_params.size()); return NULL; } if(session_params.get(0).getType() == AmArg::CStr) { a_realm = string(session_params.get(0).asCStr()); } else { ERROR("All arguments have to be CStr\n"); return NULL; } if(session_params.get(1).getType() == AmArg::CStr) { a_user = string(session_params.get(1).asCStr()); } else { ERROR("All arguments have to be CStr\n"); return NULL; } if (session_params.get(2).getType() == AmArg::CStr) { a_pwd = string(session_params.get(2).asCStr()); } else { ERROR("All arguments have to be CStr\n"); return NULL; } cred = new UACAuthCred(a_realm, a_user, a_pwd); if(cred == NULL) { ERROR("Failed to create authentication handle\n"); return NULL; } if (session_params.get(3).getType() == AmArg::CStr) { callee_uri = string(session_params.get(3).asCStr()); } else { ERROR("All arguments have to be CStr\n"); return NULL; } AmSession* s = new C2DCallerDialog(req, getAnnounceFile(req), callee_uri, cred); if(s == NULL) { ERROR("Failed to create a click2dial dialog"); return NULL; } AmSessionEventHandlerFactory* uac_auth_f = AmPlugIn::instance()->getFactory4Seh("uac_auth"); if(uac_auth_f != NULL) { DBG("UAC Auth enabled for new announcement session.\n"); AmSessionEventHandler *h = uac_auth_f->getHandler(s); if (h != NULL) { s->addHandler(h); } else { ERROR("Failed to get authentication event handler"); delete s; return NULL; } } else { ERROR("uac_auth interface not accessible. " "Load uac_auth for authenticated dialout.\n"); return NULL; } return s; }