1 /* 2 * Copyright (C) 2010-2011 Stefan Sayer 3 * 4 * This file is part of SEMS, a free SIP media server. 5 * 6 * SEMS is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * For a license to use the SEMS software under conditions 12 * other than those described here, or to purchase support for this 13 * software, please contact iptel.org by e-mail at the following addresses: 14 * info@iptel.org 15 * 16 * SEMS is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26 #ifndef _SBCCallProfile_h 27 #define _SBCCallProfile_h 28 29 #include "AmConfigReader.h" 30 #include "HeaderFilter.h" 31 #include "ampi/UACAuthAPI.h" 32 #include "ParamReplacer.h" 33 #include "atomic_types.h" 34 #include "sip/msg_logger.h" 35 36 #include <set> 37 #include <string> 38 #include <map> 39 #include <list> 40 41 using std::string; 42 using std::map; 43 using std::set; 44 using std::pair; 45 46 typedef map<string, AmArg> SBCVarMapT; 47 typedef SBCVarMapT::iterator SBCVarMapIteratorT; 48 typedef SBCVarMapT::const_iterator SBCVarMapConstIteratorT; 49 50 struct CCInterface { 51 string cc_name; 52 string cc_module; 53 map<string, string> cc_values; 54 CCInterfaceCCInterface55 CCInterface(string cc_name) 56 : cc_name(cc_name) { } CCInterfaceCCInterface57 CCInterface() { } 58 }; 59 60 typedef std::list<CCInterface> CCInterfaceListT; 61 typedef CCInterfaceListT::iterator CCInterfaceListIteratorT; 62 typedef CCInterfaceListT::const_iterator CCInterfaceListConstIteratorT; 63 64 template <class T> 65 class ref_counted_ptr 66 { 67 private: 68 T *ptr; 69 70 public: reset(T * p)71 void reset(T *p) { if (ptr) dec_ref(ptr); ptr = p; if (ptr) inc_ref(ptr); } get()72 T *get() const { return ptr; } 73 ref_counted_ptr()74 ref_counted_ptr(): ptr(0) { } ~ref_counted_ptr()75 ~ref_counted_ptr() { if (ptr) dec_ref(ptr); } 76 ref_counted_ptr(const ref_counted_ptr & other)77 ref_counted_ptr(const ref_counted_ptr &other): ptr(other.ptr) { if (ptr) inc_ref(ptr); } 78 ref_counted_ptr &operator=(const ref_counted_ptr &other) { reset(other.ptr); return *this; } 79 80 }; 81 82 class PayloadDesc { 83 protected: 84 std::string name; 85 unsigned clock_rate; // 0 means "doesn't matter" 86 87 public: 88 bool match(const SdpPayload &p) const; 89 std::string print() const; 90 bool operator==(const PayloadDesc &other) const; 91 92 /* FIXME: really want all of this? 93 * reads from format: name/clock_rate, nothing need to be set 94 * for example: 95 * PCMU 96 * bla/48000 97 * /48000 98 * */ 99 bool read(const std::string &s); 100 }; 101 102 typedef pair<unsigned int, std::string> ReplyCodeReasonPair; 103 typedef map<unsigned int, ReplyCodeReasonPair> ReplyTranslationMap; 104 105 struct SBCCallProfile 106 : public AmObject { 107 string md5hash; 108 string profile_file; 109 110 string ruri; /* updated if set */ 111 string ruri_host; /* updated if set */ 112 string from; /* updated if set */ 113 string to; /* updated if set */ 114 115 struct Contact { 116 string displayname; 117 string user; 118 string host; 119 string port; 120 121 bool hiding; 122 string hiding_prefix; 123 string hiding_vars; 124 }; 125 126 Contact contact; 127 128 class BLegContact 129 : public AmUriParser 130 { 131 public: 132 bool readConfig(AmConfigReader &cfg); 133 bool evaluate(ParamReplacerCtx& ctx, const AmSipRequest& req); 134 void infoPrint() const; 135 } bleg_contact; 136 137 string callid; 138 139 string dlg_contact_params; 140 141 bool transparent_dlg_id; 142 bool dlg_nat_handling; 143 bool keep_vias; 144 bool bleg_keep_vias; 145 146 string outbound_proxy; 147 bool force_outbound_proxy; 148 149 string aleg_outbound_proxy; 150 bool aleg_force_outbound_proxy; 151 152 string next_hop; 153 bool next_hop_1st_req; 154 bool patch_ruri_next_hop; 155 bool next_hop_fixed; 156 157 string aleg_next_hop; 158 159 bool allow_subless_notify; 160 161 vector<FilterEntry> headerfilter; 162 vector<FilterEntry> messagefilter; 163 164 bool anonymize_sdp; 165 vector<FilterEntry> sdpfilter; 166 vector<FilterEntry> aleg_sdpfilter; 167 bool have_aleg_sdpfilter; 168 vector<FilterEntry> sdpalinesfilter; 169 vector<FilterEntry> mediafilter; 170 171 string sst_enabled; 172 bool sst_enabled_value; 173 string sst_aleg_enabled; 174 AmConfigReader sst_a_cfg; // SST config (A leg) 175 AmConfigReader sst_b_cfg; // SST config (B leg) 176 177 string fix_replaces_inv; 178 string fix_replaces_ref; 179 180 bool auth_enabled; 181 UACAuthCred auth_credentials; 182 183 bool auth_aleg_enabled; 184 UACAuthCred auth_aleg_credentials; 185 bool uas_auth_bleg_enabled; 186 UACAuthCred uas_auth_bleg_credentials; 187 188 CCInterfaceListT cc_interfaces; 189 190 SBCVarMapT cc_vars; 191 192 ReplyTranslationMap reply_translations; 193 194 string append_headers; 195 string append_headers_req; 196 string aleg_append_headers_req; 197 198 string refuse_with; 199 200 string rtprelay_enabled; 201 bool rtprelay_enabled_value; 202 string force_symmetric_rtp; 203 string aleg_force_symmetric_rtp; 204 bool force_symmetric_rtp_value; 205 bool aleg_force_symmetric_rtp_value; 206 207 bool msgflags_symmetric_rtp; 208 bool rtprelay_transparent_seqno; 209 bool rtprelay_transparent_ssrc; 210 bool rtprelay_dtmf_filtering; 211 bool rtprelay_dtmf_detection; 212 213 string rtprelay_interface; 214 int rtprelay_interface_value; 215 string aleg_rtprelay_interface; 216 int aleg_rtprelay_interface_value; 217 218 int rtprelay_bw_limit_rate; 219 int rtprelay_bw_limit_peak; 220 221 list<atomic_int*> aleg_rtp_counters; 222 list<atomic_int*> bleg_rtp_counters; 223 224 string a_remote_rtp_mux_ip; 225 unsigned short a_remote_rtp_mux_port; 226 string b_remote_rtp_mux_ip; 227 unsigned short b_remote_rtp_mux_port; 228 229 string outbound_interface; 230 int outbound_interface_value; 231 232 string aleg_outbound_interface; 233 int aleg_outbound_interface_value; 234 235 struct TranscoderSettings { 236 // non-replaced parameters 237 string callee_codec_capabilities_str, audio_codecs_str, 238 transcoder_mode_str, lowfi_codecs_str, dtmf_mode_str, 239 audio_codecs_norelay_str, audio_codecs_norelay_aleg_str; 240 241 std::vector<PayloadDesc> callee_codec_capabilities; 242 std::vector<SdpPayload> audio_codecs; 243 std::vector<SdpPayload> audio_codecs_norelay; 244 std::vector<SdpPayload> audio_codecs_norelay_aleg; 245 std::vector<SdpPayload> lowfi_codecs; 246 enum { Always, OnMissingCompatible, Never } transcoder_mode; 247 enum { DTMFAlways, DTMFLowFiCodecs, DTMFNever } dtmf_mode; 248 bool readTranscoderMode(const std::string &src); 249 bool readDTMFMode(const std::string &src); 250 251 bool enabled; 252 253 bool evaluate(ParamReplacerCtx& ctx, const AmSipRequest& req); 254 255 bool readConfig(AmConfigReader &cfg); 256 void infoPrint() const; 257 bool operator==(const TranscoderSettings& rhs) const; 258 string print() const; 259 isActiveSBCCallProfile::TranscoderSettings260 bool isActive() { return enabled; } TranscoderSettingsSBCCallProfile::TranscoderSettings261 TranscoderSettings(): transcoder_mode(Never), enabled(false) { } 262 } transcoder; 263 264 struct CodecPreferences { 265 // non-replaced parameters 266 string aleg_prefer_existing_payloads_str, aleg_payload_order_str; 267 string bleg_prefer_existing_payloads_str, bleg_payload_order_str; 268 269 /** when reordering payloads in relayed SDP from B leg to A leg prefer already 270 * present payloads to the added ones by transcoder; i.e. transcoder codecs 271 * are not ordered but added after ordering is done */ 272 bool aleg_prefer_existing_payloads; 273 std::vector<PayloadDesc> aleg_payload_order; 274 275 /** when reordering payloads in relayed SDP from A leg to B leg prefer already 276 * present payloads to the added ones by transcoder; i.e. transcoder codecs 277 * are not ordered but added after ordering is done */ 278 bool bleg_prefer_existing_payloads; 279 std::vector<PayloadDesc> bleg_payload_order; 280 281 bool readConfig(AmConfigReader &cfg); 282 void infoPrint() const; 283 bool operator==(const CodecPreferences& rhs) const; 284 string print() const; 285 286 void orderSDP(AmSdp& sdp, bool a_leg); // do the SDP changes 287 bool shouldOrderPayloads(bool a_leg); // returns if call to orderSDP is needed 288 289 // return true if ordering should be done before adding transcoder codecs preferExistingCodecsSBCCallProfile::CodecPreferences290 bool preferExistingCodecs(bool a_leg) { 291 return a_leg ? bleg_prefer_existing_payloads : aleg_prefer_existing_payloads; 292 } 293 294 bool evaluate(ParamReplacerCtx& ctx, const AmSipRequest& req); 295 296 // default settings CodecPreferencesSBCCallProfile::CodecPreferences297 CodecPreferences(): aleg_prefer_existing_payloads(false) ,bleg_prefer_existing_payloads(false) { } 298 } codec_prefs; 299 300 bool contact_hiding; 301 string contact_hiding_prefix; 302 string contact_hiding_vars; 303 304 bool reg_caching; 305 unsigned int min_reg_expires; 306 unsigned int max_ua_expires; 307 308 // todo: RTP transcoding mode 309 310 // hold settings 311 class HoldSettings { 312 public: 313 enum Activity { sendrecv, sendonly, recvonly, inactive }; 314 315 private: 316 struct HoldParams { 317 // non-replaced params 318 string mark_zero_connection_str, activity_str, alter_b2b_str; 319 320 bool mark_zero_connection; 321 Activity activity; 322 bool alter_b2b; // transform B2B hold requests (not locally generated ones) 323 324 bool setActivity(const string &s); HoldParamsSBCCallProfile::HoldParams325 HoldParams(): mark_zero_connection(false), activity(sendonly), alter_b2b(false) { } 326 } aleg, bleg; 327 328 public: mark_zero_connectionSBCCallProfile329 bool mark_zero_connection(bool a_leg) { return a_leg ? aleg.mark_zero_connection : bleg.mark_zero_connection; } activitySBCCallProfile330 Activity activity(bool a_leg) { return a_leg ? aleg.activity : bleg.activity; } activity_strSBCCallProfile331 const string &activity_str(bool a_leg) { return a_leg ? aleg.activity_str : bleg.activity_str; } alter_b2bSBCCallProfile332 bool alter_b2b(bool a_leg) { return a_leg ? aleg.alter_b2b : bleg.alter_b2b; } 333 334 void readConfig(AmConfigReader &cfg); 335 bool evaluate(ParamReplacerCtx& ctx, const AmSipRequest& req); 336 } hold_settings; 337 338 // maximum retry time for repeating reINVITE after 491 response (in 339 // milliseconds), according to RFC 3261 should be 2000 ms 340 int max_491_retry_time; 341 342 private: 343 // message logging feature 344 string msg_logger_path; 345 ref_counted_ptr<msg_logger> logger; 346 347 void create_logger(const AmSipRequest& req); 348 349 public: 350 bool log_rtp; 351 bool log_sip; has_loggerSBCCallProfile352 bool has_logger() { return logger.get() != NULL; } 353 msg_logger* get_logger(const AmSipRequest& req); set_logger_pathSBCCallProfile354 void set_logger_path(const std::string path) { msg_logger_path = path; } get_logger_pathSBCCallProfile355 const string &get_logger_path() { return msg_logger_path; } 356 SBCCallProfileSBCCallProfile357 SBCCallProfile() 358 : transparent_dlg_id(false), 359 dlg_nat_handling(false), 360 keep_vias(false), 361 bleg_keep_vias(false), 362 next_hop_1st_req(false), patch_ruri_next_hop(false), 363 next_hop_fixed(false), 364 allow_subless_notify(false), 365 have_aleg_sdpfilter(false), 366 sst_enabled_value(false), 367 auth_enabled(false), 368 rtprelay_enabled_value(false), 369 force_symmetric_rtp_value(false), 370 aleg_force_symmetric_rtp_value(false), 371 rtprelay_transparent_seqno(true), 372 rtprelay_transparent_ssrc(true), 373 rtprelay_interface_value(-1), 374 aleg_rtprelay_interface_value(-1), 375 rtprelay_bw_limit_rate(-1), 376 rtprelay_bw_limit_peak(-1), 377 outbound_interface_value(-1), 378 contact_hiding(false), 379 reg_caching(false), 380 max_491_retry_time(2000), 381 log_rtp(false), 382 log_sip(false) 383 { } 384 ~SBCCallProfileSBCCallProfile385 ~SBCCallProfile() 386 { } 387 388 bool readFromConfiguration(const string& name, const string profile_file_name); 389 390 bool operator==(const SBCCallProfile& rhs) const; 391 string print() const; 392 393 int refuse(ParamReplacerCtx& ctx, const AmSipRequest& req) const; 394 395 int apply_a_routing(ParamReplacerCtx& ctx, 396 const AmSipRequest& req, 397 AmBasicSipDialog& dlg) const; 398 399 int apply_b_routing(ParamReplacerCtx& ctx, 400 const AmSipRequest& req, 401 AmBasicSipDialog& dlg) const; 402 403 int apply_common_fields(ParamReplacerCtx& ctx, 404 AmSipRequest& req) const; 405 406 bool evaluateOutboundInterface(); 407 408 bool evaluate(ParamReplacerCtx& ctx, 409 const AmSipRequest& req); 410 411 bool evaluateRTPRelayInterface(); 412 bool evaluateRTPRelayAlegInterface(); 413 414 void eval_sst_config(ParamReplacerCtx& ctx, 415 const AmSipRequest& req, 416 AmConfigReader& sst_cfg); 417 418 void replace_cc_values(ParamReplacerCtx& ctx, 419 const AmSipRequest& req, 420 AmArg* values); 421 422 void eval_cc_list(ParamReplacerCtx& ctx, const AmSipRequest& req); 423 424 void fix_append_hdrs(ParamReplacerCtx& ctx, const AmSipRequest& req); 425 426 void fix_reg_contact(ParamReplacerCtx& ctx, const AmSipRequest& req, 427 AmUriParser& contact) const; 428 429 /** 430 * Reg-cache lookup: 431 * - searches for alias in the reg-cache. 432 * - sets next-hop & outbound_interface on the given dialog 433 * @return retargeted R-URI 434 */ 435 string retarget(const string& alias, AmBasicSipDialog& dlg) const; 436 437 /** 438 * Reg-cache lookup: 439 * - searches for alias in the reg-cache. 440 * - sets next-hop & outbound_interface in this profile 441 * @return retargeted R-URI 442 */ 443 string retarget(const string& alias); 444 }; 445 446 #endif // _SBCCallProfile_h 447