/* * Copyright (C) 2010-2011 Stefan Sayer * * This file is part of SEMS, a free SIP media server. * * SEMS is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * For a license to use the SEMS software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: * info@iptel.org * * SEMS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SBCCallProfile_h #define _SBCCallProfile_h #include "AmConfigReader.h" #include "HeaderFilter.h" #include "ampi/UACAuthAPI.h" #include "ParamReplacer.h" #include "atomic_types.h" #include "sip/msg_logger.h" #include #include #include #include using std::string; using std::map; using std::set; using std::pair; typedef map SBCVarMapT; typedef SBCVarMapT::iterator SBCVarMapIteratorT; typedef SBCVarMapT::const_iterator SBCVarMapConstIteratorT; struct CCInterface { string cc_name; string cc_module; map cc_values; CCInterface(string cc_name) : cc_name(cc_name) { } CCInterface() { } }; typedef std::list CCInterfaceListT; typedef CCInterfaceListT::iterator CCInterfaceListIteratorT; typedef CCInterfaceListT::const_iterator CCInterfaceListConstIteratorT; template class ref_counted_ptr { private: T *ptr; public: void reset(T *p) { if (ptr) dec_ref(ptr); ptr = p; if (ptr) inc_ref(ptr); } T *get() const { return ptr; } ref_counted_ptr(): ptr(0) { } ~ref_counted_ptr() { if (ptr) dec_ref(ptr); } ref_counted_ptr(const ref_counted_ptr &other): ptr(other.ptr) { if (ptr) inc_ref(ptr); } ref_counted_ptr &operator=(const ref_counted_ptr &other) { reset(other.ptr); return *this; } }; class PayloadDesc { protected: std::string name; unsigned clock_rate; // 0 means "doesn't matter" public: bool match(const SdpPayload &p) const; std::string print() const; bool operator==(const PayloadDesc &other) const; /* FIXME: really want all of this? * reads from format: name/clock_rate, nothing need to be set * for example: * PCMU * bla/48000 * /48000 * */ bool read(const std::string &s); }; typedef pair ReplyCodeReasonPair; typedef map ReplyTranslationMap; struct SBCCallProfile : public AmObject { string md5hash; string profile_file; string ruri; /* updated if set */ string ruri_host; /* updated if set */ string from; /* updated if set */ string to; /* updated if set */ struct Contact { string displayname; string user; string host; string port; bool hiding; string hiding_prefix; string hiding_vars; }; Contact contact; string callid; string dlg_contact_params; string bleg_dlg_contact_params; bool transparent_dlg_id; bool dlg_nat_handling; bool keep_vias; bool bleg_keep_vias; string outbound_proxy; bool force_outbound_proxy; string aleg_outbound_proxy; bool aleg_force_outbound_proxy; string next_hop; bool next_hop_1st_req; bool patch_ruri_next_hop; bool next_hop_fixed; string aleg_next_hop; bool allow_subless_notify; vector headerfilter; vector messagefilter; bool anonymize_sdp; vector sdpfilter; vector sdpalinesfilter; vector mediafilter; string sst_enabled; bool sst_enabled_value; string sst_aleg_enabled; AmConfigReader sst_a_cfg; // SST config (A leg) AmConfigReader sst_b_cfg; // SST config (B leg) string fix_replaces_inv; string fix_replaces_ref; bool auth_enabled; UACAuthCred auth_credentials; bool auth_aleg_enabled; UACAuthCred auth_aleg_credentials; bool uas_auth_bleg_enabled; UACAuthCred uas_auth_bleg_credentials; CCInterfaceListT cc_interfaces; SBCVarMapT cc_vars; ReplyTranslationMap reply_translations; string append_headers; string append_headers_req; string aleg_append_headers_req; string refuse_with; string rtprelay_enabled; bool rtprelay_enabled_value; string force_symmetric_rtp; string aleg_force_symmetric_rtp; bool force_symmetric_rtp_value; bool aleg_force_symmetric_rtp_value; bool msgflags_symmetric_rtp; bool rtprelay_transparent_seqno; bool rtprelay_transparent_ssrc; bool rtprelay_dtmf_filtering; bool rtprelay_dtmf_detection; string rtprelay_interface; int rtprelay_interface_value; string aleg_rtprelay_interface; int aleg_rtprelay_interface_value; int rtprelay_bw_limit_rate; int rtprelay_bw_limit_peak; list aleg_rtp_counters; list bleg_rtp_counters; string outbound_interface; int outbound_interface_value; string aleg_outbound_interface; int aleg_outbound_interface_value; struct TranscoderSettings { // non-replaced parameters string callee_codec_capabilities_str, audio_codecs_str, transcoder_mode_str, lowfi_codecs_str, dtmf_mode_str, audio_codecs_norelay_str, audio_codecs_norelay_aleg_str; std::vector callee_codec_capabilities; std::vector audio_codecs; std::vector audio_codecs_norelay; std::vector audio_codecs_norelay_aleg; std::vector lowfi_codecs; enum { Always, OnMissingCompatible, Never } transcoder_mode; enum { DTMFAlways, DTMFLowFiCodecs, DTMFNever } dtmf_mode; bool readTranscoderMode(const std::string &src); bool readDTMFMode(const std::string &src); bool enabled; bool evaluate(ParamReplacerCtx& ctx, const AmSipRequest& req); bool readConfig(AmConfigReader &cfg); void infoPrint() const; bool operator==(const TranscoderSettings& rhs) const; string print() const; bool isActive() { return enabled; } TranscoderSettings(): enabled(false), transcoder_mode(Never) { } } transcoder; struct CodecPreferences { // non-replaced parameters string aleg_prefer_existing_payloads_str, aleg_payload_order_str; string bleg_prefer_existing_payloads_str, bleg_payload_order_str; /** when reordering payloads in relayed SDP from B leg to A leg prefer already * present payloads to the added ones by transcoder; i.e. transcoder codecs * are not ordered but added after ordering is done */ bool aleg_prefer_existing_payloads; std::vector aleg_payload_order; /** when reordering payloads in relayed SDP from A leg to B leg prefer already * present payloads to the added ones by transcoder; i.e. transcoder codecs * are not ordered but added after ordering is done */ bool bleg_prefer_existing_payloads; std::vector bleg_payload_order; bool readConfig(AmConfigReader &cfg); void infoPrint() const; bool operator==(const CodecPreferences& rhs) const; string print() const; void orderSDP(AmSdp& sdp, bool a_leg); // do the SDP changes bool shouldOrderPayloads(bool a_leg); // returns if call to orderSDP is needed // return true if ordering should be done before adding transcoder codecs bool preferExistingCodecs(bool a_leg) { return a_leg ? bleg_prefer_existing_payloads : aleg_prefer_existing_payloads; } bool evaluate(ParamReplacerCtx& ctx, const AmSipRequest& req); // default settings CodecPreferences(): aleg_prefer_existing_payloads(false) ,bleg_prefer_existing_payloads(false) { } } codec_prefs; bool contact_hiding; string contact_hiding_prefix; string contact_hiding_vars; bool reg_caching; unsigned int min_reg_expires; unsigned int max_ua_expires; // todo: RTP transcoding mode // hold settings class HoldSettings { public: enum Activity { sendrecv, sendonly, recvonly, inactive }; private: struct HoldParams { // non-replaced params string mark_zero_connection_str, activity_str, alter_b2b_str; bool mark_zero_connection; Activity activity; bool alter_b2b; // transform B2B hold requests (not locally generated ones) bool setActivity(const string &s); HoldParams(): mark_zero_connection(false), activity(sendonly), alter_b2b(false) { } } aleg, bleg; public: bool mark_zero_connection(bool a_leg) { return a_leg ? aleg.mark_zero_connection : bleg.mark_zero_connection; } Activity activity(bool a_leg) { return a_leg ? aleg.activity : bleg.activity; } const string &activity_str(bool a_leg) { return a_leg ? aleg.activity_str : bleg.activity_str; } bool alter_b2b(bool a_leg) { return a_leg ? aleg.alter_b2b : bleg.alter_b2b; } void readConfig(AmConfigReader &cfg); bool evaluate(ParamReplacerCtx& ctx, const AmSipRequest& req); } hold_settings; // maximum retry time for repeating reINVITE after 491 response (in // milliseconds), according to RFC 3261 should be 2000 ms int max_491_retry_time; private: // message logging feature string msg_logger_path; ref_counted_ptr logger; void create_logger(const AmSipRequest& req); public: bool log_rtp; bool log_sip; bool has_logger() { return logger.get() != NULL; } msg_logger* get_logger(const AmSipRequest& req); void set_logger_path(const std::string path) { msg_logger_path = path; } const string &get_logger_path() { return msg_logger_path; } SBCCallProfile() : auth_enabled(false), transparent_dlg_id(false), dlg_nat_handling(false), keep_vias(false),bleg_keep_vias(false), sst_enabled_value(false), rtprelay_enabled_value(false), force_symmetric_rtp_value(false), aleg_force_symmetric_rtp_value(false), rtprelay_transparent_seqno(true), rtprelay_transparent_ssrc(true), rtprelay_interface_value(-1), aleg_rtprelay_interface_value(-1), rtprelay_bw_limit_rate(-1), rtprelay_bw_limit_peak(-1), outbound_interface_value(-1), contact_hiding(false), reg_caching(false), log_rtp(false), log_sip(false), patch_ruri_next_hop(false), next_hop_1st_req(false), next_hop_fixed(false), allow_subless_notify(false), max_491_retry_time(2000) { } ~SBCCallProfile() { } bool readFromConfiguration(const string& name, const string profile_file_name); bool operator==(const SBCCallProfile& rhs) const; string print() const; int refuse(ParamReplacerCtx& ctx, const AmSipRequest& req) const; int apply_a_routing(ParamReplacerCtx& ctx, const AmSipRequest& req, AmBasicSipDialog& dlg) const; int apply_b_routing(ParamReplacerCtx& ctx, const AmSipRequest& req, AmBasicSipDialog& dlg) const; int apply_common_fields(ParamReplacerCtx& ctx, AmSipRequest& req) const; bool evaluateOutboundInterface(); bool evaluate(ParamReplacerCtx& ctx, const AmSipRequest& req); bool evaluateRTPRelayInterface(); bool evaluateRTPRelayAlegInterface(); void eval_sst_config(ParamReplacerCtx& ctx, const AmSipRequest& req, AmConfigReader& sst_cfg); void replace_cc_values(ParamReplacerCtx& ctx, const AmSipRequest& req, AmArg* values); void eval_cc_list(ParamReplacerCtx& ctx, const AmSipRequest& req); void fix_append_hdrs(ParamReplacerCtx& ctx, const AmSipRequest& req); void fix_reg_contact(ParamReplacerCtx& ctx, const AmSipRequest& req, AmUriParser& contact) const; /** * Reg-cache lookup: * - searches for alias in the reg-cache. * - sets next-hop & outbound_interface on the given dialog * @return retargeted R-URI */ string retarget(const string& alias, AmBasicSipDialog& dlg) const; /** * Reg-cache lookup: * - searches for alias in the reg-cache. * - sets next-hop & outbound_interface in this profile * @return retargeted R-URI */ string retarget(const string& alias); }; #endif // _SBCCallProfile_h