/** get the value of key @param short_name or @param name or from the list param_hdr*/ string get_header_keyvalue(const string& param_hdr, const string& short_name, const string& name) { string res = get_header_keyvalue(param_hdr, short_name); if (res.length()) return res; return get_header_keyvalue(param_hdr, name); }
AmSession* CallTimerFactory::onInvite(const AmSipRequest& req) { DBG(" *** creating new call timer session ***\n"); AmDynInvoke* user_timer = user_timer_fact->getInstance(); if(!user_timer) { ERROR("could not get a user timer reference\n"); throw AmSession::Exception(500,"could not get a user timer reference"); } string app_param = getHeader(req.hdrs, PARAM_HDR); unsigned int call_time = CallTimerFactory::DefaultCallTimer; if (CallTimerFactory::UseAppParam) { if (!app_param.length()) { INFO("call_time: no call timer parameters found. " "Using default value of %d seconds\n", CallTimerFactory::DefaultCallTimer); } else { string call_time_s = get_header_keyvalue(app_param,"t", "Timer"); if (str2i(call_time_s, call_time)) { WARN("Error decoding call time value '%s'. Using default time of %d\n", call_time_s.c_str(), call_time); } } } DBG("using call timer %d seconds\n", call_time); return new CallTimerDialog(user_timer, call_time); }
/** get the value of key @param name from \ref PARAM_HDR header in hdrs */ string get_session_param(const string& hdrs, const string& name) { string iptel_app_param = getHeader(hdrs, PARAM_HDR); if (!iptel_app_param.length()) { // DBG("call parameters header PARAM_HDR not found " // "(need to configure ser's tw_append?).\n"); return ""; } return get_header_keyvalue(iptel_app_param, name); }
void EarlyAnnounceDialog::process(AmEvent* event) { AmAudioEvent* audio_event = dynamic_cast<AmAudioEvent*>(event); if(audio_event && (audio_event->event_id == AmAudioEvent::cleared)) { DBG("AmAudioEvent::cleared\n"); unsigned int code_i = 404; string reason = "Not Found"; string iptel_app_param = getHeader(localreq.hdrs, PARAM_HDR); if (iptel_app_param.length()) { string code = get_header_keyvalue(iptel_app_param,"Final-Reply-Code"); if (code.length() && str2i(code, code_i)) { ERROR("while parsing Final-Reply-Code parameter\n"); } reason = get_header_keyvalue(iptel_app_param,"Final-Reply-Reason"); } else { string code = getHeader(localreq.hdrs,"P-Final-Reply-Code"); if (code.length() && str2i(code, code_i)) { ERROR("while parsing P-Final-Reply-Code\n"); } string h_reason = getHeader(localreq.hdrs,"P-Final-Reply-Reason"); if (h_reason.length()) { INFO("Use of P-Final-Reply-Code/P-Final-Reply-Reason is deprecated. "); INFO("Use '%s: Final-Reply-Code=<code>;" "Final-Reply-Reason=<rs>' instead.\n",PARAM_HDR); reason = h_reason; } } DBG("Replying with code %d %s\n", code_i, reason.c_str()); dlg.reply(localreq, code_i, reason); setStopped(); return; } AmSession::process(event); }
void ConferenceDialog::onSipRequest(const AmSipRequest& req) { AmSession::onSipRequest(req); if((dlg.getStatus() >= AmSipDialog::Connected) || (req.method != "REFER")) return; std::swap(dlg.local_party,dlg.remote_party); dlg.remote_tag = ""; // get route set and next hop string iptel_app_param = getHeader(req.hdrs, PARAM_HDR); if (iptel_app_param.length()) { dlg.setRoute(get_header_keyvalue(iptel_app_param,"Transfer-RR")); dlg.next_hop = get_header_keyvalue(iptel_app_param,"Transfer-NH"); } else { INFO("Use of P-Transfer-RR/P-Transfer-NH is deprecated. " "Use '%s: Transfer-RR=<rr>;Transfer-NH=<nh>' instead.\n",PARAM_HDR); dlg.setRoute(getHeader(req.hdrs,"P-Transfer-RR")); dlg.next_hop = getHeader(req.hdrs,"P-Transfer-NH"); } DBG("ConferenceDialog::onSipRequest: local_party = %s\n",dlg.local_party.c_str()); DBG("ConferenceDialog::onSipRequest: local_tag = %s\n",dlg.local_tag.c_str()); DBG("ConferenceDialog::onSipRequest: remote_party = %s\n",dlg.remote_party.c_str()); DBG("ConferenceDialog::onSipRequest: remote_tag = %s\n",dlg.remote_tag.c_str()); string body; int local_port = rtp_str.getLocalPort(); sdp.genRequest(AmConfig::LocalIP,local_port,body); dlg.sendRequest("INVITE","application/sdp",body,""); transfer_req.reset(new AmSipRequest(req)); return; }
AmSession* EarlyAnnounceFactory::onInvite(const AmSipRequest& req) { #ifdef USE_MYSQL string iptel_app_param = getHeader(req.hdrs, PARAM_HDR); string language = get_header_keyvalue(iptel_app_param,"Language"); string announce_file = ""; if (language.empty()) language = DefaultLanguage; get_announce_msg(AnnounceApplication, AnnounceMessage, req.user, req.domain, "", &announce_file); if (!announce_file.empty()) goto end; get_announce_msg(AnnounceApplication, AnnounceMessage, "", req.domain, language, &announce_file); if (!announce_file.empty()) goto end; get_announce_msg(AnnounceApplication, AnnounceMessage, "", "", language, &announce_file); #else string announce_path = AnnouncePath; string announce_file = announce_path + req.domain + "/" + req.user + ".wav"; DBG("trying '%s'\n",announce_file.c_str()); if(file_exists(announce_file)) goto end; announce_file = announce_path + req.user + ".wav"; DBG("trying '%s'\n",announce_file.c_str()); if(file_exists(announce_file)) goto end; announce_file = AnnouncePath + AnnounceFile; #endif end: return new EarlyAnnounceDialog(announce_file); }
void ConferenceDialog::onSessionStart(const AmSipRequest& req) { int i, len; string lonely_user_file; string app_param_hdr = getHeader(req.hdrs, PARAM_HDR); if (app_param_hdr.length()) { from_header = get_header_keyvalue(app_param_hdr, "Dialout-From"); extra_headers = get_header_keyvalue(app_param_hdr, "Dialout-Extra"); dialout_suffix = get_header_keyvalue(app_param_hdr, "Dialout-Suffix"); language = get_header_keyvalue(app_param_hdr, "Language"); } else { from_header = getHeader(req.hdrs, "P-Dialout-From"); extra_headers = getHeader(req.hdrs, "P-Dialout-Extra"); dialout_suffix = getHeader(req.hdrs, "P-Dialout-Suffix"); if (from_header.length() || extra_headers.length() || dialout_suffix.length()) { DBG("Warning: P-Dialout- style headers are deprecated." " Please use P-App-Param header instead.\n"); } language = getHeader(req.hdrs, "P-Language"); if (language.length()) { DBG("Warning: P-Language header is deprecated." " Please use P-App-Param header instead.\n"); } } len = extra_headers.length(); for (i = 0; i < len; i++) { if (extra_headers[i] == '|') extra_headers[i] = '\n'; } if (extra_headers[len - 1] != '\n') { extra_headers += '\n'; } if (dialout_suffix.length() == 0) { if (!ConferenceFactory::DialoutSuffix.empty()) { dialout_suffix = ConferenceFactory::DialoutSuffix; } else { dialout_suffix = ""; } } allow_dialout = dialout_suffix.length() > 0; if (!language.empty()) { #ifdef USE_MYSQL /* Get domain/language specific lonely user file from MySQL */ if (get_audio_file(LONELY_USER_MSG, req.domain, language, lonely_user_file) && !lonely_user_file.empty()) { ConferenceFactory::LonelyUserFile = lonely_user_file; } else { if (get_audio_file(LONELY_USER_MSG, "", language, lonely_user_file) && !lonely_user_file.empty()) { ConferenceFactory::LonelyUserFile = lonely_user_file; } } #else /* Get domain/language specific lonely user file from file system */ lonely_user_file = ConferenceFactory::AudioPath + "/lonely_user_msg/" + req.domain + "/" + "default_" + language + ".wav"; if(file_exists(lonely_user_file)) { ConferenceFactory::LonelyUserFile = lonely_user_file; } else { lonely_user_file = ConferenceFactory::AudioPath + "/lonely_user_msg/default_" + language + ".wav"; if(file_exists(lonely_user_file)) { ConferenceFactory::LonelyUserFile = lonely_user_file; } } #endif } DBG("Using LonelyUserFile <%s>\n", ConferenceFactory::LonelyUserFile.c_str()); setupAudio(); }
void EarlyAnnounceDialog::process(AmEvent* event) { AmAudioEvent* audio_event = dynamic_cast<AmAudioEvent*>(event); if(audio_event && (audio_event->event_id == AmAudioEvent::cleared)) { DBG("AmAudioEvent::cleared\n"); bool continue_b2b = false; if (EarlyAnnounceFactory::ContinueB2B == EarlyAnnounceFactory::Always) { continue_b2b = true; } else if (EarlyAnnounceFactory::ContinueB2B == EarlyAnnounceFactory::AppParam) { string iptel_app_param = getHeader(invite_req.hdrs, PARAM_HDR); if (iptel_app_param.length()) { continue_b2b = get_header_keyvalue(iptel_app_param,"B2B")=="yes"; } else { continue_b2b = getHeader(invite_req.hdrs,"P-B2B")=="yes"; } } DBG("determined: continue_b2b = %s\n", continue_b2b?"true":"false"); if (!continue_b2b) { unsigned int code_i = 404; string reason = "Not Found"; string iptel_app_param = getHeader(invite_req.hdrs, PARAM_HDR); if (iptel_app_param.length()) { string code = get_header_keyvalue(iptel_app_param,"Final-Reply-Code"); if (code.length() && str2i(code, code_i)) { ERROR("while parsing Final-Reply-Code parameter\n"); } reason = get_header_keyvalue(iptel_app_param,"Final-Reply-Reason"); if (!reason.length()) reason = "Not Found"; } else { string code = getHeader(invite_req.hdrs,"P-Final-Reply-Code"); if (code.length() && str2i(code, code_i)) { ERROR("while parsing P-Final-Reply-Code\n"); } string h_reason = getHeader(invite_req.hdrs,"P-Final-Reply-Reason"); if (h_reason.length()) { INFO("Use of P-Final-Reply-Code/P-Final-Reply-Reason is deprecated. "); INFO("Use '%s: Final-Reply-Code=<code>;" "Final-Reply-Reason=<rs>' instead.\n",PARAM_HDR); reason = h_reason; } } DBG("Replying with code %d %s\n", code_i, reason.c_str()); dlg.reply(invite_req, code_i, reason); setStopped(); } else { set_sip_relay_only(true); recvd_req.insert(std::make_pair(invite_req.cseq,invite_req)); relayEvent(new B2BSipRequestEvent(invite_req,true)); } return; } AmB2BCallerSession::process(event); }
AmSession* AnswerMachineFactory::onInvite(const AmSipRequest& req) { string language; string email; string domain; string user; string sender; string typ; int vm_mode = MODE_VOICEMAIL; string iptel_app_param = getHeader(req.hdrs, PARAM_HDR); if (!iptel_app_param.length()) { throw AmSession::Exception(500, "voicemail: parameters not found"); } language = get_header_keyvalue(iptel_app_param, "lng", "Language"); email = get_header_keyvalue(iptel_app_param, "eml", "Email-Address"); string mode = get_header_keyvalue(iptel_app_param,"mod", "Mode"); if (!mode.empty()) { if (mode == "box") vm_mode = MODE_BOX; else if (mode == "both") vm_mode = MODE_BOTH; else if (mode == "ann") vm_mode = MODE_ANN; } if (((vm_mode == MODE_BOTH) || (vm_mode == MODE_VOICEMAIL)) && (email.find('@') == string::npos)) { ERROR("no @ found in email address '%s' from params '%s'\n", email.c_str(), iptel_app_param.c_str()); throw AmSession::Exception(500, "voicemail: no email address"); } user = get_header_keyvalue(iptel_app_param,"usr", "User"); if (!user.length()) user = req.user; sender = get_header_keyvalue(iptel_app_param, "snd", "Sender"); if (!sender.length()) sender = req.from; domain = get_header_keyvalue(iptel_app_param, "dom", "Domain"); if (!domain.length()) domain = req.domain; typ = get_header_keyvalue(iptel_app_param, "typ", "Type"); if (!typ.length()) typ = DEFAULT_TYPE; // checks if (user.empty()) throw AmSession::Exception(500, "voicemail: user missing"); if (sender.empty()) throw AmSession::Exception(500, "voicemail: sender missing"); if (((vm_mode == MODE_BOX) || (vm_mode == MODE_BOTH)) && (NULL == MessageStorage)) { throw AmSession::Exception(500, "voicemail: no message storage available"); } DBG("voicemail invocation parameters: \n"); DBG(" Mode: <%s> \n", mode.c_str()); DBG(" Email: <%s> \n", email.c_str()); DBG(" User: <%s> \n", user.c_str()); DBG(" Sender: <%s> \n", sender.c_str()); DBG(" Domain: <%s> \n", domain.c_str()); DBG(" Language: <%s> \n", language.c_str()); DBG(" Type: <%s> \n", typ.c_str()); FILE* greeting_fp = NULL; if (TryPersonalGreeting) greeting_fp = getMsgStoreGreeting(typ, user, domain); #ifdef USE_MYSQL string announce_file; if (get_audio_file(GREETING_MSG, domain, req.user, "", &announce_file) && !announce_file.empty()) goto announce_found; if (!language.empty()) { if (get_audio_file(GREETING_MSG, domain, "", language, &announce_file) && !announce_file.empty()) goto announce_found; } else { if (get_audio_file(GREETING_MSG, domain, "", "", &announce_file) && !announce_file.empty()) goto announce_found; } if (!language.empty()) if (get_audio_file(GREETING_MSG, "", "", language, &announce_file) && !announce_file.empty()) goto announce_found; get_audio_file(GREETING_MSG, "", "", "", &announce_file); #else string announce_file = add2path(AnnouncePath,2, domain.c_str(), (user + ".wav").c_str()); if (file_exists(announce_file)) goto announce_found; if (!language.empty()) { announce_file = add2path(AnnouncePath,3, domain.c_str(), language.c_str(), DefaultAnnounce.c_str()); if (file_exists(announce_file)) goto announce_found; } announce_file = add2path(AnnouncePath,2, domain.c_str(), DefaultAnnounce.c_str()); if (file_exists(announce_file)) goto announce_found; if (!language.empty()) { announce_file = add2path(AnnouncePath,2, language.c_str(), DefaultAnnounce.c_str()); if (file_exists(announce_file)) goto announce_found; } announce_file = add2path(AnnouncePath,1, DefaultAnnounce.c_str()); if (!file_exists(announce_file)) announce_file = ""; #endif announce_found: if(announce_file.empty()) throw AmSession::Exception(500,"voicemail: no greeting file found"); // VBOX mode does not need email template if ((vm_mode == MODE_BOX) || (vm_mode == MODE_ANN)) return new AnswerMachineDialog(user, sender, domain, email, announce_file, greeting_fp, vm_mode, NULL); if(email.empty()) throw AmSession::Exception(404,"missing email address"); map<string,EmailTemplate>::iterator tmpl_it; if (!language.empty()) { tmpl_it = email_tmpl.find(domain + "_" + language); if(tmpl_it == email_tmpl.end()) { tmpl_it = email_tmpl.find(domain); if(tmpl_it == email_tmpl.end()) { tmpl_it = email_tmpl.find(DEFAULT_MAIL_TMPL + "_" + language); if(tmpl_it == email_tmpl.end()) tmpl_it = email_tmpl.find(DEFAULT_MAIL_TMPL); } } } else { tmpl_it = email_tmpl.find(domain); if(tmpl_it == email_tmpl.end()) tmpl_it = email_tmpl.find(DEFAULT_MAIL_TMPL); } if(tmpl_it == email_tmpl.end()){ ERROR("Voicemail: unable to find an email template.\n"); return 0; } return new AnswerMachineDialog(user, sender, domain, email, announce_file, greeting_fp, vm_mode, &tmpl_it->second); }
AmSession* AnswerMachineFactory::onInvite(const AmSipRequest& req, const string& app_name, const map<string,string>& app_params) { string language; string email; string domain; string user; string sender; string typ; string uid; // user ID string did; // domain ID string mode; string iptel_app_param; EmailTmplDict template_variables; int vm_mode = DefaultVMMode; if(SimpleMode) { email = EmailAddress; uid = user = req.user; //did = domain = req.domain; did = domain = "default"; sender = req.from; typ = DEFAULT_TYPE; } else { iptel_app_param = getHeader(req.hdrs, PARAM_HDR, true); mode = get_header_keyvalue(iptel_app_param,"mod", "Mode"); if (!EmailAddress.length()) { if (!iptel_app_param.length()) { throw AmSession::Exception(500, "voicemail: parameters not found"); } language = get_header_keyvalue(iptel_app_param, "lng", "Language"); email = get_header_keyvalue(iptel_app_param, "eml", "Email-Address"); if (!mode.empty()) { if (mode == "box") vm_mode = MODE_BOX; else if (mode == "both") vm_mode = MODE_BOTH; else if (mode == "ann") vm_mode = MODE_ANN; } } else { // overrides email address //vm_mode = MODE_VOICEMAIL; email = EmailAddress; } if (((vm_mode == MODE_BOTH) || (vm_mode == MODE_VOICEMAIL)) && (email.find('@') == string::npos)) { ERROR("no @ found in email address '%s' from params '%s'\n", email.c_str(), iptel_app_param.c_str()); throw AmSession::Exception(500, "voicemail: no email address"); } user = get_header_keyvalue(iptel_app_param,"usr", "User"); if (!user.length()) user = req.user; sender = get_header_keyvalue(iptel_app_param, "snd", "Sender"); if (!sender.length()) sender = req.from; domain = get_header_keyvalue(iptel_app_param, "dom", "Domain"); if (!domain.length()) domain = req.domain; typ = get_header_keyvalue(iptel_app_param, "typ", "Type"); if (!typ.length()) typ = DEFAULT_TYPE; uid = get_header_keyvalue(iptel_app_param, "uid", "UserID"); if (uid.empty()) uid=user; did = get_header_keyvalue(iptel_app_param, "did", "DomainID"); if (did.empty()) did=domain; } // checks if (uid.empty()) throw AmSession::Exception(500, "voicemail: user missing"); if (sender.empty()) throw AmSession::Exception(500, "voicemail: sender missing"); if (((vm_mode == MODE_BOX) || (vm_mode == MODE_BOTH)) && (NULL == MessageStorage)) { throw AmSession::Exception(500, "voicemail: no message storage available"); } DBG("voicemail invocation parameters: \n"); DBG(" Mode: <%s> \n", mode.c_str()); DBG(" Email: <%s> \n", email.c_str()); DBG(" User: <%s> \n", user.c_str()); DBG(" Sender: <%s> \n", sender.c_str()); DBG(" Domain: <%s> \n", domain.c_str()); DBG(" Language: <%s> \n", language.c_str()); DBG(" Type: <%s> \n", typ.c_str()); DBG(" UID: <%s> \n", uid.c_str()); DBG(" DID: <%s> \n", did.c_str()); FILE* greeting_fp = NULL; if (TryPersonalGreeting) greeting_fp = getMsgStoreGreeting(typ, uid, did); #ifdef USE_MYSQL string announce_file; if (get_audio_file(GREETING_MSG, domain, req.user, "", announce_file) && !announce_file.empty()) goto announce_found; if (!language.empty()) { if (get_audio_file(GREETING_MSG, domain, "", language, announce_file) && !announce_file.empty()) goto announce_found; } else { if (get_audio_file(GREETING_MSG, domain, "", "", announce_file) && !announce_file.empty()) goto announce_found; } if (!language.empty()) if (get_audio_file(GREETING_MSG, "", "", language, announce_file) && !announce_file.empty()) goto announce_found; get_audio_file(GREETING_MSG, "", "", "", announce_file); #else string announce_file = add2path(AnnouncePath,2, did.c_str(), (uid + ".wav").c_str()); if (file_exists(announce_file)) goto announce_found; if (!language.empty()) { announce_file = add2path(AnnouncePath,3, did.c_str(), language.c_str(), DefaultAnnounce.c_str()); if (file_exists(announce_file)) goto announce_found; } announce_file = add2path(AnnouncePath,2, did.c_str(), DefaultAnnounce.c_str()); if (file_exists(announce_file)) goto announce_found; if (!language.empty()) { announce_file = add2path(AnnouncePath,2, language.c_str(), DefaultAnnounce.c_str()); if (file_exists(announce_file)) goto announce_found; } announce_file = add2path(AnnouncePath,1, DefaultAnnounce.c_str()); if (!file_exists(announce_file)) announce_file = ""; #endif announce_found: if(announce_file.empty()) throw AmSession::Exception(500,"voicemail: no greeting file found"); if(!SimpleMode) { // a little inefficient this way - but get_header_keyvalue supports escaping for (vector<string>::iterator it= MailHeaderVariables.begin(); it != MailHeaderVariables.end(); it++) { template_variables[*it] = get_header_keyvalue(iptel_app_param, *it); } } // VBOX mode does not need email template if ((vm_mode == MODE_BOX) || (vm_mode == MODE_ANN)) return new AnswerMachineDialog(user, sender, domain, email, announce_file, uid, did, greeting_fp, vm_mode, template_variables, NULL); if(email.empty()) throw AmSession::Exception(404,"missing email address"); map<string,EmailTemplate>::iterator tmpl_it; if (!language.empty()) { tmpl_it = email_tmpl.find(did + "_" + language); if(tmpl_it == email_tmpl.end()) { tmpl_it = email_tmpl.find(did); if(tmpl_it == email_tmpl.end()) { tmpl_it = email_tmpl.find(DEFAULT_MAIL_TMPL + "_" + language); if(tmpl_it == email_tmpl.end()) tmpl_it = email_tmpl.find(DEFAULT_MAIL_TMPL); } } } else { tmpl_it = email_tmpl.find(did); if(tmpl_it == email_tmpl.end()) tmpl_it = email_tmpl.find(DEFAULT_MAIL_TMPL); } if(tmpl_it == email_tmpl.end()){ ERROR("Voicemail: unable to find an email template.\n"); return 0; } return new AnswerMachineDialog(user, sender, domain, email, announce_file, uid, did, greeting_fp, vm_mode, template_variables, &tmpl_it->second); }
AmSession* AnswerMachineFactory::onInvite(const AmSipRequest& req) { string language; string email; string iptel_app_param = getHeader(req.hdrs, PARAM_HDR); if (!EmailAddress.length()) { if (iptel_app_param.length()) { language = get_header_keyvalue(iptel_app_param,"Language"); email = get_header_keyvalue(iptel_app_param,"Email-Address"); } else { email = getHeader(req.hdrs,"P-Email-Address"); language = getHeader(req.hdrs,"P-Language"); // local user's language if (email.length()) { INFO("Use of P-Email-Address/P-Language is deprecated. \n"); INFO("Use '%s: Email-Address=<addr>;" "Language=<lang>' instead.\n",PARAM_HDR); } } } else { email = EmailAddress; } DBG("email address for user '%s': <%s> \n", req.user.c_str(),email.c_str()); DBG("language: <%s> \n", language.c_str()); #ifdef USE_MYSQL string announce_file; if (get_audio_file(GREETING_MSG, req.domain, req.user, "", &announce_file) && !announce_file.empty()) goto announce_found; if (!language.empty()) { if (get_audio_file(GREETING_MSG, req.domain, "", language, &announce_file) && !announce_file.empty()) goto announce_found; } else { if (get_audio_file(GREETING_MSG, req.domain, "", "", &announce_file) && !announce_file.empty()) goto announce_found; } if (!language.empty()) if (get_audio_file(GREETING_MSG, "", "", language, &announce_file) && !announce_file.empty()) goto announce_found; get_audio_file(GREETING_MSG, "", "", "", &announce_file); #else string announce_file = add2path(AnnouncePath,2, req.domain.c_str(), (req.user + ".wav").c_str()); if (file_exists(announce_file)) goto announce_found; if (!language.empty()) { announce_file = add2path(AnnouncePath,3, req.domain.c_str(), language.c_str(), DefaultAnnounce.c_str()); if (file_exists(announce_file)) goto announce_found; } announce_file = add2path(AnnouncePath,2, req.domain.c_str(), DefaultAnnounce.c_str()); if (file_exists(announce_file)) goto announce_found; if (!language.empty()) { announce_file = add2path(AnnouncePath,2, language.c_str(), DefaultAnnounce.c_str()); if (file_exists(announce_file)) goto announce_found; } announce_file = add2path(AnnouncePath,1, DefaultAnnounce.c_str()); if (!file_exists(announce_file)) announce_file = ""; #endif announce_found: if(announce_file.empty()) throw AmSession::Exception(500,"voicemail: no greeting file found"); if(email.empty()) throw AmSession::Exception(404,"missing email address"); map<string,EmailTemplate>::iterator tmpl_it; if (!language.empty()) { tmpl_it = email_tmpl.find(req.domain + "_" + language); if(tmpl_it == email_tmpl.end()) { tmpl_it = email_tmpl.find(req.domain); if(tmpl_it == email_tmpl.end()) { tmpl_it = email_tmpl.find(DEFAULT_MAIL_TMPL + "_" + language); if(tmpl_it == email_tmpl.end()) tmpl_it = email_tmpl.find(DEFAULT_MAIL_TMPL); } } } else { tmpl_it = email_tmpl.find(req.domain); if(tmpl_it == email_tmpl.end()) tmpl_it = email_tmpl.find(DEFAULT_MAIL_TMPL); } if(tmpl_it == email_tmpl.end()){ ERROR("Voicemail: unable to find an email template.\n"); return 0; } return new AnswerMachineDialog(email,announce_file, &tmpl_it->second); }
string replaceParameters(const string& s, const char* r_type, const AmSipRequest& req, const string& app_param, AmUriParser& ruri_parser, AmUriParser& from_parser, AmUriParser& to_parser) { string res; bool is_replaced = false; size_t p = 0; bool is_escaped = false; // char last_char=' '; while (p<s.length()) { size_t skip_chars = 1; if (is_escaped) { switch (s[p]) { case 'r': res += '\r'; break; case 'n': res += '\n'; break; case 't': res += '\t'; break; default: res += s[p]; break; } is_escaped = false; } else { // not escaped if (s[p]=='\\') { if (p==s.length()-1) { res += '\\'; // add single \ at the end } else { is_escaped = true; is_replaced = true; } } else if ((s[p]=='$') && (s.length() >= p+1)) { is_replaced = true; p++; switch (s[p]) { case 'f': { // from if ((s.length() == p+1) || (s[p+1] == '.')) { res += req.from; break; } if (s[p+1]=='t') { // $ft - from tag res += req.from_tag; break; } if (from_parser.uri.empty()) { size_t end; if (!from_parser.parse_contact(req.from, 0, end)) { WARN("Error parsing From URI '%s'\n", req.from.c_str()); break; } from_parser.dump(); } replaceParsedParam(s, p, from_parser, res); }; break; case 't': { // to if ((s.length() == p+1) || (s[p+1] == '.')) { res += req.to; break; } if (to_parser.uri.empty()) { size_t end; if (!to_parser.parse_contact(req.to, 0, end)) { WARN("Error parsing To URI '%s'\n", req.to.c_str()); break; } } replaceParsedParam(s, p, to_parser, res); }; break; case 'r': { // r-uri if ((s.length() == p+1) || (s[p+1] == '.')) { res += req.r_uri; break; } if (ruri_parser.uri.empty()) { ruri_parser.uri = req.r_uri; if (!ruri_parser.parse_uri()) { WARN("Error parsing R-URI '%s'\n", req.r_uri.c_str()); break; } } replaceParsedParam(s, p, ruri_parser, res); }; break; case 'c': { // call-id if ((s.length() == p+1) || (s[p+1] == 'i')) { res += req.callid; break; } WARN("unknown replacement $c%c\n", s[p+1]); }; break; case 's': { // source (remote) if (s.length() < p+1) { WARN("unknown replacement $s\n"); break; } if (s[p+1] == 'i') { // $si source IP address res += req.remote_ip.c_str(); break; } else if (s[p+1] == 'p') { // $sp source port res += int2str(req.remote_port); break; } WARN("unknown replacement $s%c\n", s[p+1]); }; break; case 'R': { // received (local) if (s.length() < p+1) { WARN("unknown replacement $R\n"); break; } if (s[p+1] == 'i') { // $Ri received IP address res += req.local_ip.c_str(); break; } else if (s[p+1] == 'p') { // $Rp received port res += int2str(req.local_port); break; } else if (s[p+1] == 'f') { // $Rf received interface id res += int2str(req.local_if); } else if (s[p+1] == 'n') { // $Rn received interface name if ((req.local_if >= 0) && req.local_if < AmConfig::Ifs.size()) { res += AmConfig::Ifs[req.local_if].name; } } else if (s[p+1] == 'I') { // $RI received interface public IP if ((req.local_if >= 0) && req.local_if < AmConfig::Ifs.size()) { res += AmConfig::Ifs[req.local_if].PublicIP; } } WARN("unknown replacement $R%c\n", s[p+1]); }; break; #define case_HDR(pv_char, pv_name, hdr_name) \ case pv_char: { \ AmUriParser uri_parser; \ string m_uri = getHeader(req.hdrs, hdr_name); \ if ((s.length() == p+1) || (s[p+1] == '.')) { \ res += m_uri; \ break; \ } \ size_t end; \ if (!uri_parser.parse_contact(m_uri, 0, end)) { \ WARN("Error parsing " pv_name " URI '%s'\n", m_uri.c_str()); \ break; \ } \ if (s[p+1] == 'i') { \ res+=uri_parser.uri_user+"@"+uri_parser.uri_host; \ if (!uri_parser.uri_port.empty()) \ res+=":"+uri_parser.uri_port; \ } else { \ replaceParsedParam(s, p, uri_parser, res); \ } \ }; break; case_HDR('a', "PAI", SIP_HDR_P_ASSERTED_IDENTITY); // P-Asserted-Identity case_HDR('p', "PPI", SIP_HDR_P_PREFERRED_IDENTITY); // P-Preferred-Identity case 'P': { // app-params if (s[p+1] != '(') { WARN("Error parsing P param replacement (missing '(')\n"); break; } if (s.length()<p+3) { WARN("Error parsing P param replacement (short string)\n"); break; } size_t skip_p = p+2; for (;skip_p<s.length() && s[skip_p] != ')';skip_p++) { } if (skip_p==s.length()) { WARN("Error parsing P param replacement (unclosed brackets)\n"); break; } string param_name = s.substr(p+2, skip_p-p-2); // DBG("param_name = '%s' (skip-p - p = %d)\n", param_name.c_str(), skip_p-p); res += get_header_keyvalue(app_param, param_name); skip_chars = skip_p-p; } break; case 'H': { // header size_t name_offset = 2; if (s[p+1] != '(') { if (s[p+2] != '(') { WARN("Error parsing H header replacement (missing '(')\n"); break; } name_offset = 3; } if (s.length()<name_offset+1) { WARN("Error parsing H header replacement (short string)\n"); break; } size_t skip_p = p+name_offset; for (;skip_p<s.length() && s[skip_p] != ')';skip_p++) { } if (skip_p==s.length()) { WARN("Error parsing H header replacement (unclosed brackets)\n"); break; } string hdr_name = s.substr(p+name_offset, skip_p-p-name_offset); // DBG("param_name = '%s' (skip-p - p = %d)\n", param_name.c_str(), skip_p-p); if (name_offset == 2) { // full header res += getHeader(req.hdrs, hdr_name); } else { // parse URI and use component AmUriParser uri_parser; string m_uri = getHeader(req.hdrs, hdr_name); if ((s[p+1] == '.')) { res += m_uri; break; } size_t end; if (!uri_parser.parse_contact(m_uri, 0, end)) { WARN("Error parsing header %s URI '%s'\n", hdr_name.c_str(), m_uri.c_str()); break; } replaceParsedParam(s, p, uri_parser, res); } skip_chars = skip_p-p; } break; case 'M': { // regex map if (s[p+1] != '(') { WARN("Error parsing $M regex map replacement (missing '(')\n"); break; } if (s.length()<p+3) { WARN("Error parsing $M regex map replacement (short string)\n"); break; } size_t skip_p = p+2; skip_p = skip_to_end_of_brackets(s, skip_p); if (skip_p==s.length()) { WARN("Error parsing $M regex map replacement (unclosed brackets)\n"); skip_chars = skip_p-p; break; } string map_str = s.substr(p+2, skip_p-p-2); size_t spos = map_str.rfind("=>"); if (spos == string::npos) { skip_chars = skip_p-p; WARN("Error parsing $M regex map replacement: no => found in '%s'\n", map_str.c_str()); break; } string map_val = map_str.substr(0, spos); string map_val_replaced = replaceParameters(map_val, r_type, req, app_param, ruri_parser, from_parser, to_parser); string mapping_name = map_str.substr(spos+2); string map_res; if (SBCFactory::regex_mappings. mapRegex(mapping_name, map_val_replaced.c_str(), map_res)) { DBG("matched regex mapping '%s' (orig '%s) in '%s'\n", map_val_replaced.c_str(), map_val.c_str(), mapping_name.c_str()); res+=map_res; } else { DBG("no match in regex mapping '%s' (orig '%s') in '%s'\n", map_val_replaced.c_str(), map_val.c_str(), mapping_name.c_str()); } skip_chars = skip_p-p; } break; case '_': { // modify if (s.length()<p+4) { // $_O() WARN("Error parsing $_ modifier replacement (short string)\n"); break; } char operation = s[p+1]; if (operation != 'U' && operation != 'l' && operation != 's' && operation != '5') { WARN("Error parsing $_%c string modifier: unknown operator '%c'\n", operation, operation); } if (s[p+2] != '(') { WARN("Error parsing $U upcase replacement (missing '(')\n"); break; } size_t skip_p = p+3; skip_p = skip_to_end_of_brackets(s, skip_p); if (skip_p==s.length()) { WARN("Error parsing $_ modifier (unclosed brackets)\n"); skip_chars = skip_p-p; break; } string br_str = s.substr(p+3, skip_p-p-3); string br_str_replaced = replaceParameters(br_str, "$_*(...)", req, app_param, ruri_parser, from_parser, to_parser); br_str = br_str_replaced; switch(operation) { case 'u': // uppercase transform(br_str_replaced.begin(), br_str_replaced.end(), br_str_replaced.begin(), ::toupper); break; case 'l': // lowercase transform(br_str_replaced.begin(), br_str_replaced.end(), br_str_replaced.begin(), ::tolower); break; case 's': // size (string length) br_str_replaced = int2str((unsigned int)br_str.length()); break; case '5': // md5 br_str_replaced = calculateMD5(br_str); break; default: break; } DBG("applied operator '%c': '%s' => '%s'\n", operation, br_str.c_str(), br_str_replaced.c_str()); res+=br_str_replaced; skip_chars = skip_p-p; } break; default: { WARN("unknown replace pattern $%c%c\n", s[p], s[p+1]); }; break; }; p+=skip_chars; // skip $.X } else { res += s[p]; } } // end not escaped p++; } if (is_replaced) { DBG("%s pattern replace: '%s' -> '%s'\n", r_type, s.c_str(), res.c_str()); } return res; }
void DSMFactory::runMonitorAppSelect(const AmSipRequest& req, string& start_diag, map<string, string>& vars) { #define FALLBACK_OR_EXCEPTION(code, reason) \ if (MonSelectFallback.empty()) { \ throw AmSession::Exception(code, reason); \ } else { \ DBG("falling back to '%s'\n", MonSelectFallback.c_str()); \ start_diag = MonSelectFallback; \ return; \ } #ifdef USE_MONITORING if (NULL == MONITORING_GLOBAL_INTERFACE) { ERROR("using $(mon_select) but monitoring not loaded\n"); FALLBACK_OR_EXCEPTION(500, "Internal Server Error"); } AmArg di_args, ret; if (MonSelectCaller != MonSelect_NONE) { AmUriParser from_parser; if (MonSelectCaller == MonSelect_FROM) from_parser.uri = req.from_uri; else { size_t end; string pai = getHeader(req.hdrs, SIP_HDR_P_ASSERTED_IDENTITY, true); if (!from_parser.parse_contact(pai, 0, end)) { WARN("Failed to parse " SIP_HDR_P_ASSERTED_IDENTITY " '%s'\n", pai.c_str()); FALLBACK_OR_EXCEPTION(500, "Internal Server Error"); } } if (!from_parser.parse_uri()) { DBG("failed to parse caller uri '%s'\n", from_parser.uri.c_str()); FALLBACK_OR_EXCEPTION(500, "Internal Server Error"); } AmArg caller_filter; caller_filter.push("caller"); caller_filter.push(from_parser.uri_user); DBG(" && looking for caller=='%s'\n", from_parser.uri_user.c_str()); di_args.push(caller_filter); } if (MonSelectCallee != MonSelect_NONE) { AmArg callee_filter; callee_filter.push("callee"); if (MonSelectCallee == MonSelect_RURI) callee_filter.push(req.user); else { AmUriParser to_parser; size_t end; if (!to_parser.parse_contact(req.to, 0, end)) { ERROR("Failed to parse To '%s'\n", req.to.c_str()); FALLBACK_OR_EXCEPTION(500, "Internal Server Error"); } if (!to_parser.parse_uri()) { DBG("failed to parse callee uri '%s'\n", to_parser.uri.c_str()); FALLBACK_OR_EXCEPTION(500, "Internal Server Error"); } callee_filter.push(to_parser.uri_user); } DBG(" && looking for callee=='%s'\n", req.user.c_str()); di_args.push(callee_filter); } // apply additional filters if (MonSelectFilters.size()) { string app_params = getHeader(req.hdrs, PARAM_HDR); for (vector<string>::iterator it = MonSelectFilters.begin(); it != MonSelectFilters.end(); it++) { AmArg filter; filter.push(*it); // avp name string app_param_val = get_header_keyvalue(app_params, *it); filter.push(app_param_val); di_args.push(filter); DBG(" && looking for %s=='%s'\n", it->c_str(), app_param_val.c_str()); } } MONITORING_GLOBAL_INTERFACE->invoke("listByFilter",di_args,ret); if ((ret.getType()!=AmArg::Array)|| !ret.size()) { DBG("call info not found. caller uri %s, r-uri %s\n", req.from_uri.c_str(), req.r_uri.c_str()); FALLBACK_OR_EXCEPTION(500, "Internal Server Error"); } AmArg sess_id, sess_params; if (ret.size()>1) { DBG("multiple call info found - picking the first one\n"); } const char* session_id = ret.get(0).asCStr(); sess_id.push(session_id); MONITORING_GLOBAL_INTERFACE->invoke("get",sess_id,sess_params); if ((sess_params.getType()!=AmArg::Array)|| !sess_params.size() || sess_params.get(0).getType() != AmArg::Struct) { INFO("call parameters not found. caller uri %s, r-uri %s, id %s\n", req.from_uri.c_str(), req.r_uri.c_str(), ret.get(0).asCStr()); FALLBACK_OR_EXCEPTION(500, "Internal Server Error"); } AmArg& sess_dict = sess_params.get(0); if (sess_dict.hasMember("app")) { start_diag = sess_dict["app"].asCStr(); DBG("selected application '%s' for session\n", start_diag.c_str()); } else { ERROR("selected session params don't contain 'app'\n"); FALLBACK_OR_EXCEPTION(500, "Internal Server Error"); } AmArg2DSMStrMap(sess_dict["appParams"], vars); vars["mon_session_record"] = session_id; #else ERROR("using $(mon_select) for dsm application, " "but compiled without monitoring support!\n"); throw AmSession::Exception(500, "Internal Server Error"); #endif #undef FALLBACK_OR_EXCEPTION }