You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sems/apps/sbc/SBCCallProfile.h

434 lines
12 KiB

/*
* 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 <set>
#include <string>
#include <map>
#include <list>
using std::string;
using std::map;
using std::set;
using std::pair;
typedef map<string, AmArg> SBCVarMapT;
typedef SBCVarMapT::iterator SBCVarMapIteratorT;
typedef SBCVarMapT::const_iterator SBCVarMapConstIteratorT;
struct CCInterface {
string cc_name;
string cc_module;
map<string, string> cc_values;
CCInterface(string cc_name)
: cc_name(cc_name) { }
CCInterface() { }
};
typedef std::list<CCInterface> CCInterfaceListT;
typedef CCInterfaceListT::iterator CCInterfaceListIteratorT;
typedef CCInterfaceListT::const_iterator CCInterfaceListConstIteratorT;
template <class T>
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<unsigned int, std::string> ReplyCodeReasonPair;
typedef map<unsigned int, ReplyCodeReasonPair> 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<FilterEntry> headerfilter;
vector<FilterEntry> messagefilter;
bool anonymize_sdp;
vector<FilterEntry> sdpfilter;
vector<FilterEntry> aleg_sdpfilter;
bool have_aleg_sdpfilter;
vector<FilterEntry> sdpalinesfilter;
vector<FilterEntry> 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<atomic_int*> aleg_rtp_counters;
list<atomic_int*> 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<PayloadDesc> callee_codec_capabilities;
std::vector<SdpPayload> audio_codecs;
std::vector<SdpPayload> audio_codecs_norelay;
std::vector<SdpPayload> audio_codecs_norelay_aleg;
std::vector<SdpPayload> 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<PayloadDesc> 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<PayloadDesc> 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<msg_logger> 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),
have_aleg_sdpfilter(false),
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