/* Copyright (C) 2005-2009 Michel de Boer This program 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. This program 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, see . */ #include #include #include #include #include #include #include #include #include #include "diamondcard.h" #include "log.h" #include "phone.h" #include "twinkle_config.h" #include "user.h" #include "userintf.h" #include "util.h" #include "protocol.h" #include "sys_settings.h" #include "audits/memman.h" #include "sdp/sdp.h" #include "parser/parse_ctrl.h" #include "parser/request.h" extern t_phone *phone; // Field names in the config file // USER fields #define FLD_NAME "user_name" #define FLD_DOMAIN "user_domain" #define FLD_DISPLAY "user_display" #define FLD_ORGANIZATION "user_organization" #define FLD_AUTH_REALM "auth_realm" #define FLD_AUTH_NAME "auth_name" #define FLD_AUTH_PASS "auth_pass" #define FLD_AUTH_AKA_OP "auth_aka_op" #define FLD_AUTH_AKA_AMF "auth_aka_amf" // SIP SERVER fields #define FLD_OUTBOUND_PROXY "outbound_proxy" #define FLD_ALL_REQUESTS_TO_PROXY "all_requests_to_proxy" #define FLD_NON_RESOLVABLE_TO_PROXY "non_resolvable_to_proxy" #define FLD_REGISTRAR "registrar" #define FLD_REGISTRATION_TIME "registration_time" #define FLD_REGISTER_AT_STARTUP "register_at_startup" #define FLD_REG_ADD_QVALUE "reg_add_qvalue" #define FLD_REG_QVALUE "reg_qvalue" // AUDIO fields #define FLD_CODECS "codecs" #define FLD_PTIME "ptime" #define FLD_OUT_FAR_END_CODEC_PREF "out_far_end_codec_pref" #define FLD_IN_FAR_END_CODEC_PREF "in_far_end_codec_pref" #define FLD_SPEEX_NB_PAYLOAD_TYPE "speex_nb_payload_type" #define FLD_SPEEX_WB_PAYLOAD_TYPE "speex_wb_payload_type" #define FLD_SPEEX_UWB_PAYLOAD_TYPE "speex_uwb_payload_type" #define FLD_SPEEX_BIT_RATE_TYPE "speex_bit_rate_type" #define FLD_SPEEX_ABR_NB "speex_abr_nb" #define FLD_SPEEX_ABR_WB "speex_abr_wb" #define FLD_SPEEX_DTX "speex_dtx" #define FLD_SPEEX_PENH "speex_penh" #define FLD_SPEEX_QUALITY "speex_quality" #define FLD_SPEEX_COMPLEXITY "speex_complexity" #define FLD_SPEEX_DSP_VAD "speex_dsp_vad" #define FLD_SPEEX_DSP_AGC "speex_dsp_agc" #define FLD_SPEEX_DSP_AGC_LEVEL "speex_dsp_agc_level" #define FLD_SPEEX_DSP_AEC "speex_dsp_aec" #define FLD_SPEEX_DSP_NRD "speex_dsp_nrd" #define FLD_ILBC_PAYLOAD_TYPE "ilbc_payload_type" #define FLD_ILBC_MODE "ilbc_mode" #define FLD_G726_16_PAYLOAD_TYPE "g726_16_payload_type" #define FLD_G726_24_PAYLOAD_TYPE "g726_24_payload_type" #define FLD_G726_32_PAYLOAD_TYPE "g726_32_payload_type" #define FLD_G726_40_PAYLOAD_TYPE "g726_40_payload_type" #define FLD_G726_PACKING "g726_packing" #define FLD_DTMF_TRANSPORT "dtmf_transport" #define FLD_DTMF_PAYLOAD_TYPE "dtmf_payload_type" #define FLD_DTMF_DURATION "dtmf_duration" #define FLD_DTMF_PAUSE "dtmf_pause" #define FLD_DTMF_VOLUME "dtmf_volume" // SIP PROTOCOL fields #define FLD_HOLD_VARIANT "hold_variant" #define FLD_CHECK_MAX_FORWARDS "check_max_forwards" #define FLD_ALLOW_MISSING_CONTACT_REG "allow_missing_contact_reg" #define FLD_REGISTRATION_TIME_IN_CONTACT "registration_time_in_contact" #define FLD_COMPACT_HEADERS "compact_headers" #define FLD_ENCODE_MULTI_VALUES_AS_LIST "encode_multi_values_as_list" #define FLD_USE_DOMAIN_IN_CONTACT "use_domain_in_contact" #define FLD_ALLOW_SDP_CHANGE "allow_sdp_change" #define FLD_ALLOW_REDIRECTION "allow_redirection" #define FLD_ASK_USER_TO_REDIRECT "ask_user_to_redirect" #define FLD_MAX_REDIRECTIONS "max_redirections" #define FLD_EXT_100REL "ext_100rel" #define FLD_EXT_REPLACES "ext_replaces" #define FLD_REFEREE_HOLD "referee_hold" #define FLD_REFERRER_HOLD "referrer_hold" #define FLD_ALLOW_REFER "allow_refer" #define FLD_ASK_USER_TO_REFER "ask_user_to_refer" #define FLD_AUTO_REFRESH_REFER_SUB "auto_refresh_refer_sub" #define FLD_ATTENDED_REFER_TO_AOR "attended_refer_to_aor" #define FLD_ALLOW_XFER_CONSULT_INPROG "allow_xfer_consult_inprog" #define FLD_SEND_P_PREFERRED_ID "send_p_preferred_id" #define FLD_SEND_P_ASSERTED_ID "send_p_asserted_id" // Transport/NAT fields #define FLD_SIP_TRANSPORT "sip_transport" #define FLD_SIP_TRANSPORT_UDP_THRESHOLD "sip_transport_udp_threshold" #define FLD_NAT_PUBLIC_IP "nat_public_ip" #define FLD_STUN_SERVER "stun_server" #define FLD_PERSISTENT_TCP "persistent_tcp" #define FLD_ENABLE_NAT_KEEPALIVE "enable_nat_keepalive" // TIMER fields #define FLD_TIMER_NOANSWER "timer_noanswer" #define FLD_TIMER_NAT_KEEPALIVE "timer_nat_keepalive" #define FLD_TIMER_TCP_PING "timer_tcp_ping" // ADDRESS FORMAT fields #define FLD_DISPLAY_USERONLY_PHONE "display_useronly_phone" #define FLD_NUMERICAL_USER_IS_PHONE "numerical_user_is_phone" #define FLD_REMOVE_SPECIAL_PHONE_SYM "remove_special_phone_symbols" #define FLD_SPECIAL_PHONE_SYMBOLS "special_phone_symbols" #define FLD_USE_TEL_URI_FOR_PHONE "use_tel_uri_for_phone" // Ring tone settings #define FLD_USER_RINGTONE_FILE "ringtone_file" #define FLD_USER_RINGBACK_FILE "ringback_file" // Incoming call script #define FLD_SCRIPT_INCOMING_CALL "script_incoming_call" #define FLD_SCRIPT_IN_CALL_ANSWERED "script_in_call_answered" #define FLD_SCRIPT_IN_CALL_FAILED "script_in_call_failed" #define FLD_SCRIPT_OUTGOING_CALL "script_outgoing_call" #define FLD_SCRIPT_OUT_CALL_ANSWERED "script_out_call_answered" #define FLD_SCRIPT_OUT_CALL_FAILED "script_out_call_failed" #define FLD_SCRIPT_LOCAL_RELEASE "script_local_release" #define FLD_SCRIPT_REMOTE_RELEASE "script_remote_release" // Number conversion #define FLD_NUMBER_CONVERSION "number_conversion" // Security #define FLD_ZRTP_ENABLED "zrtp_enabled" #define FLD_ZRTP_GOCLEAR_WARNING "zrtp_goclear_warning" #define FLD_ZRTP_SDP "zrtp_sdp" #define FLD_ZRTP_SEND_IF_SUPPORTED "zrtp_send_if_supported" // MWI #define FLD_MWI_SOLICITED "mwi_solicited" #define FLD_MWI_USER "mwi_user" #define FLD_MWI_SERVER "mwi_server" #define FLD_MWI_VIA_PROXY "mwi_via_proxy" #define FLD_MWI_SUBSCRIPTION_TIME "mwi_subscription_time" #define FLD_MWI_VM_ADDRESS "mwi_vm_address" // INSTANT MESSAGE #define FLD_IM_MAX_SESSIONS "im_max_sessions" #define FLD_IM_SEND_ISCOMPOSING "im_send_iscomposing" // PRESENCE #define FLD_PRES_SUBSCRIPTION_TIME "pres_subscription_time" #define FLD_PRES_PUBLICATION_TIME "pres_publication_time" #define FLD_PRES_PUBLISH_STARTUP "pres_publish_startup" ///////////////////////// // class t_user ///////////////////////// //////////////////// // Private //////////////////// t_ext_support t_user::str2ext_support(const string &s) const { if (s == "disabled") return EXT_DISABLED; if (s == "supported") return EXT_SUPPORTED; if (s == "preferred") return EXT_PREFERRED; if (s == "required") return EXT_REQUIRED; return EXT_INVALID; } string t_user::ext_support2str(t_ext_support e) const { switch(e) { case EXT_INVALID: return "invalid"; case EXT_DISABLED: return "disabled"; case EXT_SUPPORTED: return "supported"; case EXT_PREFERRED: return "preferred"; case EXT_REQUIRED: return "required"; default: assert(false); } return ""; } t_bit_rate_type t_user::str2bit_rate_type(const string &s) const { if (s == "cbr") return BIT_RATE_CBR; if (s == "vbr") return BIT_RATE_VBR; if (s == "abr") return BIT_RATE_ABR; return BIT_RATE_INVALID; } string t_user::bit_rate_type2str(t_bit_rate_type b) const { switch (b) { case BIT_RATE_INVALID: return "invalid"; case BIT_RATE_CBR: return "cbr"; case BIT_RATE_VBR: return "vbr"; case BIT_RATE_ABR: return "abr"; default: assert(false); } return ""; } t_dtmf_transport t_user::str2dtmf_transport(const string &s) const { if (s == "inband") return DTMF_INBAND; if (s == "rfc2833") return DTMF_RFC2833; if (s == "auto") return DTMF_AUTO; if (s == "info") return DTMF_INFO; return DTMF_AUTO; } string t_user::dtmf_transport2str(t_dtmf_transport d) const { switch (d) { case DTMF_INBAND: return "inband"; case DTMF_RFC2833: return "rfc2833"; case DTMF_AUTO: return "auto"; case DTMF_INFO: return "info"; default: assert(false); } return ""; } t_g726_packing t_user::str2g726_packing(const string &s) const { if (s == "rfc3551") return G726_PACK_RFC3551; if (s == "aal2") return G726_PACK_AAL2; return G726_PACK_AAL2; } string t_user::g726_packing2str(t_g726_packing packing) const { switch (packing) { case G726_PACK_RFC3551: return "rfc3551"; case G726_PACK_AAL2: return "aal2"; default: assert(false); } return ""; } t_sip_transport t_user::str2sip_transport(const string &s) const { if (s == "udp") return SIP_TRANS_UDP; if (s == "tcp") return SIP_TRANS_TCP; if (s == "auto") return SIP_TRANS_AUTO; return SIP_TRANS_AUTO; } string t_user::sip_transport2str(t_sip_transport transport) const { switch (transport) { case SIP_TRANS_UDP: return "udp"; case SIP_TRANS_TCP: return "tcp"; case SIP_TRANS_AUTO: return "auto"; default: assert(false); } return ""; } string t_user::expand_filename(const string &filename) { string f; if (filename[0] == '/') { f = filename; } else { f = string(DIR_HOME); f += "/"; f += USER_DIR; f += "/"; f += filename; } return f; } bool t_user::parse_num_conversion(const string &value, t_number_conversion &c) { vector l = split_escaped(value, ','); if (l.size() != 2) { // Invalid conversion rule return false; } try { c.re.assign(l[0]); c.fmt = l[1]; } catch (std::regex_error) { // Invalid regular expression log_file->write_header("t_user::parse_num_conversion", LOG_NORMAL, LOG_WARNING); log_file->write_raw("Bad number conversion:\n"); log_file->write_raw(l.front()); log_file->write_raw(" --> "); log_file->write_raw(l.back()); log_file->write_endl(); log_file->write_footer(); return false; } return true; } bool t_user::set_server_value(t_url &server, const string &scheme, const string &value) { if (value.empty()) { server.set_url(""); return false; } string s = scheme + ":" + value; server.set_url(s); if (!server.is_valid() || server.get_user() != "") { string err_msg = "Invalid server value: "; err_msg += value; log_file->write_report(err_msg, "t_user::set_server_value", LOG_NORMAL, LOG_WARNING); server.set_url(""); return false; } return true; } //////////////////// // Public //////////////////// t_user::t_user() { // Set defaults memset(auth_aka_op, 0, AKA_OPLEN); memset(auth_aka_amf, 0, AKA_AMFLEN); use_outbound_proxy = false; all_requests_to_proxy = false; non_resolvable_to_proxy = false; use_registrar = false; registration_time = 3600; #ifdef HAVE_SPEEX codecs.push_back(CODEC_SPEEX_WB); codecs.push_back(CODEC_SPEEX_NB); #endif #ifdef HAVE_ILBC codecs.push_back(CODEC_ILBC); #endif codecs.push_back(CODEC_G711_ALAW); codecs.push_back(CODEC_G711_ULAW); codecs.push_back(CODEC_GSM); #ifdef HAVE_BCG729 codecs.push_back(CODEC_G729A); #endif ptime = 20; out_obey_far_end_codec_pref = true; in_obey_far_end_codec_pref = true; hold_variant = HOLD_RFC3264; use_nat_public_ip = false; use_stun = false; persistent_tcp = true; enable_nat_keepalive = false; register_at_startup = true; reg_add_qvalue = false; reg_qvalue = 1.0; check_max_forwards = false; allow_missing_contact_reg = true; compact_headers = false; encode_multi_values_as_list = true; registration_time_in_contact = true; use_domain_in_contact = false; allow_sdp_change = false; allow_redirection = true; ask_user_to_redirect = true; max_redirections = 5; timer_noanswer = 30; timer_nat_keepalive = DUR_NAT_KEEPALIVE; timer_tcp_ping = DUR_TCP_PING; ext_100rel = EXT_SUPPORTED; ext_replaces = true; speex_nb_payload_type = 97; speex_wb_payload_type = 98; speex_uwb_payload_type = 99; speex_bit_rate_type = BIT_RATE_CBR; speex_abr_nb = 0; speex_abr_wb = 0; speex_dtx = false; speex_penh = true; speex_quality = 6; speex_complexity = 3; speex_dsp_vad = true; speex_dsp_agc = true; speex_dsp_aec = false; speex_dsp_nrd = true; speex_dsp_agc_level = 20; ilbc_payload_type = 96; ilbc_mode = 30; g726_16_payload_type = 102; g726_24_payload_type = 103; g726_32_payload_type = 104; g726_40_payload_type = 105; g726_packing = G726_PACK_RFC3551; dtmf_transport = DTMF_AUTO; dtmf_duration = 100; dtmf_pause = 40; dtmf_payload_type = 101; dtmf_volume = 10; display_useronly_phone = true; numerical_user_is_phone = false; remove_special_phone_symbols = true; special_phone_symbols = SPECIAL_PHONE_SYMBOLS; use_tel_uri_for_phone = false; referee_hold = false; referrer_hold = true; allow_refer = true; ask_user_to_refer = true; auto_refresh_refer_sub = false; attended_refer_to_aor = false; allow_transfer_consultation_inprog = false; send_p_preferred_id = false; send_p_asserted_id = false; sip_transport = SIP_TRANS_AUTO; sip_transport_udp_threshold = 1300; // RFC 3261 18.1.1 ringtone_file.clear(); ringback_file.clear(); script_incoming_call.clear(); script_in_call_answered.clear(); script_in_call_failed.clear(); script_outgoing_call.clear(); script_out_call_answered.clear(); script_out_call_failed.clear(); script_local_release.clear(); script_remote_release.clear(); number_conversions.clear(); zrtp_enabled = false; zrtp_goclear_warning = true; zrtp_sdp = true; zrtp_send_if_supported = false; mwi_solicited = false; mwi_user.clear(); mwi_via_proxy = false; mwi_subscription_time = 3600; mwi_vm_address.clear(); im_max_sessions = 10; im_send_iscomposing = true; pres_subscription_time = 3600; pres_publication_time = 3600; pres_publish_startup = true; } t_user::t_user(const t_user &u) { u.mtx_user.lock(); config_filename = u.config_filename; name = u.name; domain = u.domain; display = u.display; organization = u.organization; auth_realm = u.auth_realm; auth_name = u.auth_name; auth_pass = u.auth_pass; memcpy(auth_aka_op, u.auth_aka_op, AKA_OPLEN); memcpy(auth_aka_amf, u.auth_aka_amf, AKA_AMFLEN); use_outbound_proxy = u.use_outbound_proxy; outbound_proxy = u.outbound_proxy; all_requests_to_proxy = u.all_requests_to_proxy; non_resolvable_to_proxy = u.non_resolvable_to_proxy; use_registrar = u.use_registrar; reg_add_qvalue = u.reg_add_qvalue; reg_qvalue = u.reg_qvalue; registrar = u.registrar; registration_time = u.registration_time; register_at_startup = u.register_at_startup; codecs = u.codecs; ptime = u.ptime; out_obey_far_end_codec_pref = u.out_obey_far_end_codec_pref; in_obey_far_end_codec_pref = u.in_obey_far_end_codec_pref; speex_nb_payload_type = u.speex_nb_payload_type; speex_wb_payload_type = u.speex_wb_payload_type; speex_uwb_payload_type = u.speex_uwb_payload_type; speex_bit_rate_type = u.speex_bit_rate_type; speex_abr_nb = u.speex_abr_nb; speex_abr_wb = u.speex_abr_wb; speex_dtx = u.speex_dtx; speex_penh = u.speex_penh; speex_quality = u.speex_quality; speex_complexity = u.speex_complexity; speex_dsp_vad = u.speex_dsp_vad; speex_dsp_agc = u.speex_dsp_agc; speex_dsp_agc_level = u.speex_dsp_agc_level; speex_dsp_aec = u.speex_dsp_aec; speex_dsp_nrd = u.speex_dsp_nrd; ilbc_payload_type = u.ilbc_payload_type; ilbc_mode = u.ilbc_mode; g726_16_payload_type = u.g726_16_payload_type; g726_24_payload_type = u.g726_24_payload_type; g726_32_payload_type = u.g726_32_payload_type; g726_40_payload_type = u.g726_40_payload_type; g726_packing = u.g726_packing; dtmf_transport = u.dtmf_transport; dtmf_payload_type = u.dtmf_payload_type; dtmf_duration = u.dtmf_duration; dtmf_pause = u.dtmf_pause; dtmf_volume = u.dtmf_volume; hold_variant = u.hold_variant; check_max_forwards = u.check_max_forwards; allow_missing_contact_reg = u.allow_missing_contact_reg; registration_time_in_contact = u.registration_time_in_contact; compact_headers = u.compact_headers; encode_multi_values_as_list = u.encode_multi_values_as_list; use_domain_in_contact = u.use_domain_in_contact; allow_sdp_change = u.allow_sdp_change; allow_redirection = u.allow_redirection; ask_user_to_redirect = u.ask_user_to_redirect; max_redirections = u.max_redirections; ext_100rel = u.ext_100rel; ext_replaces = u.ext_replaces; referee_hold = u.referee_hold; referrer_hold = u.referrer_hold; allow_refer = u.allow_refer; ask_user_to_refer = u.ask_user_to_refer; auto_refresh_refer_sub = u.auto_refresh_refer_sub; attended_refer_to_aor = u.attended_refer_to_aor; allow_transfer_consultation_inprog = u.allow_transfer_consultation_inprog; send_p_preferred_id = u.send_p_preferred_id; send_p_asserted_id = u.send_p_asserted_id; sip_transport = u.sip_transport; sip_transport_udp_threshold = u.sip_transport_udp_threshold; use_nat_public_ip = u.use_nat_public_ip; nat_public_ip = u.nat_public_ip; use_stun = u.use_stun; stun_server = u.stun_server; persistent_tcp = u.persistent_tcp; enable_nat_keepalive = u.enable_nat_keepalive; timer_noanswer = u.timer_noanswer; timer_nat_keepalive = u.timer_nat_keepalive; timer_tcp_ping = u.timer_tcp_ping; display_useronly_phone = u.display_useronly_phone; numerical_user_is_phone = u.numerical_user_is_phone; remove_special_phone_symbols = u.remove_special_phone_symbols; special_phone_symbols = u.special_phone_symbols; use_tel_uri_for_phone = u.use_tel_uri_for_phone; ringtone_file = u.ringtone_file; ringback_file = u.ringback_file; script_incoming_call = u.script_incoming_call; script_in_call_answered = u.script_in_call_answered; script_in_call_failed = u.script_in_call_failed; script_outgoing_call = u.script_outgoing_call; script_out_call_answered = u.script_out_call_answered; script_out_call_failed = u.script_out_call_failed; script_local_release = u.script_local_release; script_remote_release = u.script_remote_release; number_conversions = u.number_conversions; zrtp_enabled = u.zrtp_enabled; zrtp_goclear_warning = u.zrtp_goclear_warning; zrtp_sdp = u.zrtp_sdp; zrtp_send_if_supported = u.zrtp_send_if_supported; mwi_solicited = u.mwi_solicited; mwi_user = u.mwi_user; mwi_server = u.mwi_server; mwi_via_proxy = u.mwi_via_proxy; mwi_subscription_time = u.mwi_subscription_time; mwi_vm_address = u.mwi_vm_address; im_max_sessions = u.im_max_sessions; im_send_iscomposing = u.im_send_iscomposing; pres_subscription_time = u.pres_subscription_time; pres_publication_time = u.pres_publication_time; pres_publish_startup = u.pres_publish_startup; u.mtx_user.unlock(); } t_user *t_user::copy(void) const { t_user *u = new t_user(*this); MEMMAN_NEW(u); return u; } string t_user::get_name(void) const { string result; mtx_user.lock(); result = name; mtx_user.unlock(); return result; } string t_user::get_domain(void) const { string result; mtx_user.lock(); result = domain; mtx_user.unlock(); return result; } string t_user::get_display(bool anonymous) const { if (anonymous) return ANONYMOUS_DISPLAY; string result; mtx_user.lock(); result = display; mtx_user.unlock(); return result; } string t_user::get_organization(void) const { string result; mtx_user.lock(); result = organization; mtx_user.unlock(); return result; } string t_user::get_auth_realm(void) const { string result; mtx_user.lock(); result = auth_realm; mtx_user.unlock(); return result; } string t_user::get_auth_name(void) const { string result; mtx_user.lock(); result = auth_name; mtx_user.unlock(); return result; } string t_user::get_auth_pass(void) const { string result; mtx_user.lock(); result = auth_pass; mtx_user.unlock(); return result; } void t_user::get_auth_aka_op(uint8 *aka_op) const { t_mutex_guard guard(mtx_user); memcpy(aka_op, auth_aka_op, AKA_OPLEN); } void t_user::get_auth_aka_amf(uint8 *aka_amf) const { t_mutex_guard guard(mtx_user); memcpy(aka_amf, auth_aka_amf, AKA_AMFLEN); } bool t_user::get_use_outbound_proxy(void) const { bool result; mtx_user.lock(); result = use_outbound_proxy; mtx_user.unlock(); return result; } t_url t_user::get_outbound_proxy(void) const { t_url result; mtx_user.lock(); result = outbound_proxy; mtx_user.unlock(); return result; } bool t_user::get_all_requests_to_proxy(void) const { bool result; mtx_user.lock(); result = all_requests_to_proxy; mtx_user.unlock(); return result; } bool t_user::get_non_resolvable_to_proxy(void) const { bool result; mtx_user.lock(); result = non_resolvable_to_proxy; mtx_user.unlock(); return result; } bool t_user::get_use_registrar(void) const { bool result; mtx_user.lock(); result = use_registrar; mtx_user.unlock(); return result; } t_url t_user::get_registrar(void) const { t_url result; mtx_user.lock(); result = registrar; mtx_user.unlock(); return result; } unsigned long t_user::get_registration_time(void) const { unsigned long result; mtx_user.lock(); result = registration_time; mtx_user.unlock(); return result; } bool t_user::get_register_at_startup(void) const { bool result; mtx_user.lock(); result = register_at_startup; mtx_user.unlock(); return result; } bool t_user::get_reg_add_qvalue(void) const { bool result; mtx_user.lock(); result = reg_add_qvalue; mtx_user.unlock(); return result; } float t_user::get_reg_qvalue(void) const { float result; mtx_user.lock(); result = reg_qvalue; mtx_user.unlock(); return result; } list t_user::get_codecs(void) const { list result; mtx_user.lock(); result = codecs; mtx_user.unlock(); return result; } unsigned short t_user::get_ptime(void) const { unsigned short result; mtx_user.lock(); result = ptime; mtx_user.unlock(); return result; } bool t_user::get_out_obey_far_end_codec_pref(void) const { bool result; mtx_user.lock(); result = out_obey_far_end_codec_pref; mtx_user.unlock(); return result; } bool t_user::get_in_obey_far_end_codec_pref(void) const { bool result; mtx_user.lock(); result = in_obey_far_end_codec_pref; mtx_user.unlock(); return result; } unsigned short t_user::get_speex_nb_payload_type(void) const { unsigned short result; mtx_user.lock(); result = speex_nb_payload_type; mtx_user.unlock(); return result; } unsigned short t_user::get_speex_wb_payload_type(void) const { unsigned short result; mtx_user.lock(); result = speex_wb_payload_type; mtx_user.unlock(); return result; } unsigned short t_user::get_speex_uwb_payload_type(void) const { unsigned short result; mtx_user.lock(); result = speex_uwb_payload_type; mtx_user.unlock(); return result; } t_bit_rate_type t_user::get_speex_bit_rate_type(void) const { t_bit_rate_type result; mtx_user.lock(); result = speex_bit_rate_type; mtx_user.unlock(); return result; } int t_user::get_speex_abr_nb(void) const { int result; mtx_user.lock(); result = speex_abr_nb; mtx_user.unlock(); return result; } int t_user::get_speex_abr_wb(void) const { int result; mtx_user.lock(); result = speex_abr_wb; mtx_user.unlock(); return result; } bool t_user::get_speex_dtx(void) const { bool result; mtx_user.lock(); result = speex_dtx; mtx_user.unlock(); return result; } bool t_user::get_speex_penh(void) const { bool result; mtx_user.lock(); result = speex_penh; mtx_user.unlock(); return result; } unsigned short t_user::get_speex_quality(void) const { unsigned short result; mtx_user.lock(); result = speex_quality; mtx_user.unlock(); return result; } unsigned short t_user::get_speex_complexity(void) const { unsigned short result; mtx_user.lock(); result = speex_complexity; mtx_user.unlock(); return result; } bool t_user::get_speex_dsp_vad(void) const { bool result; mtx_user.lock(); result = speex_dsp_vad; mtx_user.unlock(); return result; } bool t_user::get_speex_dsp_agc(void) const { bool result; mtx_user.lock(); result = speex_dsp_agc; mtx_user.unlock(); return result; } unsigned short t_user::get_speex_dsp_agc_level(void) const { unsigned short result; mtx_user.lock(); result = speex_dsp_agc_level; mtx_user.unlock(); return result; } bool t_user::get_speex_dsp_aec(void) const { bool result; mtx_user.lock(); result = speex_dsp_aec; mtx_user.unlock(); return result; } bool t_user::get_speex_dsp_nrd(void) const { bool result; mtx_user.lock(); result = speex_dsp_nrd; mtx_user.unlock(); return result; } unsigned short t_user::get_ilbc_payload_type(void) const { unsigned short result; mtx_user.lock(); result = ilbc_payload_type; mtx_user.unlock(); return result; } unsigned short t_user::get_ilbc_mode(void) const { unsigned short result; mtx_user.lock(); result = ilbc_mode; mtx_user.unlock(); return result; } unsigned short t_user::get_g726_16_payload_type(void) const { unsigned short result; mtx_user.lock(); result = g726_16_payload_type; mtx_user.unlock(); return result; } unsigned short t_user::get_g726_24_payload_type(void) const { unsigned short result; mtx_user.lock(); result = g726_24_payload_type; mtx_user.unlock(); return result; } unsigned short t_user::get_g726_32_payload_type(void) const { unsigned short result; mtx_user.lock(); result = g726_32_payload_type; mtx_user.unlock(); return result; } unsigned short t_user::get_g726_40_payload_type(void) const { unsigned short result; mtx_user.lock(); result = g726_40_payload_type; mtx_user.unlock(); return result; } t_g726_packing t_user::get_g726_packing(void) const { t_g726_packing result; mtx_user.lock(); result = g726_packing; mtx_user.unlock(); return result; } t_dtmf_transport t_user::get_dtmf_transport(void) const { t_dtmf_transport result; mtx_user.lock(); result = dtmf_transport; mtx_user.unlock(); return result; } unsigned short t_user::get_dtmf_payload_type(void) const { unsigned short result; mtx_user.lock(); result = dtmf_payload_type; mtx_user.unlock(); return result; } unsigned short t_user::get_dtmf_duration(void) const { unsigned short result; mtx_user.lock(); result = dtmf_duration; mtx_user.unlock(); return result; } unsigned short t_user::get_dtmf_pause(void) const { unsigned short result; mtx_user.lock(); result = dtmf_pause; mtx_user.unlock(); return result; } unsigned short t_user::get_dtmf_volume(void) const { unsigned short result; mtx_user.lock(); result = dtmf_volume; mtx_user.unlock(); return result; } t_hold_variant t_user::get_hold_variant(void) const { t_hold_variant result; mtx_user.lock(); result = hold_variant; mtx_user.unlock(); return result; } bool t_user::get_check_max_forwards(void) const { bool result; mtx_user.lock(); result = check_max_forwards; mtx_user.unlock(); return result; } bool t_user::get_allow_missing_contact_reg(void) const { bool result; mtx_user.lock(); result = allow_missing_contact_reg; mtx_user.unlock(); return result; } bool t_user::get_registration_time_in_contact(void) const { bool result; mtx_user.lock(); result = registration_time_in_contact; mtx_user.unlock(); return result; } bool t_user::get_compact_headers(void) const { bool result; mtx_user.lock(); result = compact_headers; mtx_user.unlock(); return result; } bool t_user::get_encode_multi_values_as_list(void) const { bool result; mtx_user.lock(); result = encode_multi_values_as_list; mtx_user.unlock(); return result; } bool t_user::get_use_domain_in_contact(void) const { bool result; mtx_user.lock(); result = use_domain_in_contact; mtx_user.unlock(); return result; } bool t_user::get_allow_sdp_change(void) const { bool result; mtx_user.lock(); result = allow_sdp_change; mtx_user.unlock(); return result; } bool t_user::get_allow_redirection(void) const { bool result; mtx_user.lock(); result = allow_redirection; mtx_user.unlock(); return result; } bool t_user::get_ask_user_to_redirect(void) const { bool result; mtx_user.lock(); result = ask_user_to_redirect; mtx_user.unlock(); return result; } unsigned short t_user::get_max_redirections(void) const { unsigned short result; mtx_user.lock(); result = max_redirections; mtx_user.unlock(); return result; } t_ext_support t_user::get_ext_100rel(void) const { t_ext_support result; mtx_user.lock(); result = ext_100rel; mtx_user.unlock(); return result; } bool t_user::get_ext_replaces(void) const { bool result; mtx_user.lock(); result = ext_replaces; mtx_user.unlock(); return result; } bool t_user::get_referee_hold(void) const { t_mutex_guard guard(mtx_user); return referee_hold; } bool t_user::get_referrer_hold(void) const { t_mutex_guard guard(mtx_user); return referrer_hold; } bool t_user::get_allow_refer(void) const { t_mutex_guard guard(mtx_user); return allow_refer; } bool t_user::get_ask_user_to_refer(void) const { t_mutex_guard guard(mtx_user); return ask_user_to_refer; } bool t_user::get_auto_refresh_refer_sub(void) const { t_mutex_guard guard(mtx_user); return auto_refresh_refer_sub; } bool t_user::get_attended_refer_to_aor(void) const { t_mutex_guard guard(mtx_user); return attended_refer_to_aor; } bool t_user::get_allow_transfer_consultation_inprog(void) const { t_mutex_guard guard(mtx_user); return allow_transfer_consultation_inprog; } bool t_user::get_send_p_preferred_id(void) const { bool result; mtx_user.lock(); result = send_p_preferred_id; mtx_user.unlock(); return result; } bool t_user::get_send_p_asserted_id(void) const { bool result; mtx_user.lock(); result = send_p_asserted_id; mtx_user.unlock(); return result; } t_sip_transport t_user::get_sip_transport(void) const { t_mutex_guard guard(mtx_user); return sip_transport; } unsigned short t_user::get_sip_transport_udp_threshold(void) const { t_mutex_guard guard(mtx_user); return sip_transport_udp_threshold; } bool t_user::get_use_nat_public_ip(void) const { bool result; mtx_user.lock(); result = use_nat_public_ip; mtx_user.unlock(); return result; } string t_user::get_nat_public_ip(void) const { string result; mtx_user.lock(); result = nat_public_ip; mtx_user.unlock(); return result; } bool t_user::get_use_stun(void) const { bool result; mtx_user.lock(); result = use_stun; mtx_user.unlock(); return result; } t_url t_user::get_stun_server(void) const { t_url result; mtx_user.lock(); result = stun_server; mtx_user.unlock(); return result; } bool t_user::get_persistent_tcp(void) const { t_mutex_guard guard(mtx_user); return persistent_tcp; } bool t_user::get_enable_nat_keepalive(void) const { t_mutex_guard guard(mtx_user); return enable_nat_keepalive; } unsigned short t_user::get_timer_noanswer(void) const { unsigned short result; mtx_user.lock(); result = timer_noanswer; mtx_user.unlock(); return result; } unsigned short t_user::get_timer_nat_keepalive(void) const { unsigned short result; mtx_user.lock(); result = timer_nat_keepalive; mtx_user.unlock(); return result; } unsigned short t_user::get_timer_tcp_ping(void) const { t_mutex_guard guard(mtx_user); return timer_tcp_ping; } bool t_user::get_display_useronly_phone(void) const { bool result; mtx_user.lock(); result = display_useronly_phone; mtx_user.unlock(); return result; } bool t_user::get_numerical_user_is_phone(void) const { bool result; mtx_user.lock(); result = numerical_user_is_phone; mtx_user.unlock(); return result; } bool t_user::get_remove_special_phone_symbols(void) const { bool result; mtx_user.lock(); result = remove_special_phone_symbols; mtx_user.unlock(); return result; } string t_user::get_special_phone_symbols(void) const { string result; mtx_user.lock(); result = special_phone_symbols; mtx_user.unlock(); return result; } bool t_user::get_use_tel_uri_for_phone(void) const { t_mutex_guard guard(mtx_user); return use_tel_uri_for_phone; } string t_user::get_ringtone_file(void) const { string result; mtx_user.lock(); result = ringtone_file; mtx_user.unlock(); return result; } string t_user::get_ringback_file(void) const { string result; mtx_user.lock(); result = ringback_file; mtx_user.unlock(); return result; } string t_user::get_script_incoming_call(void) const { string result; mtx_user.lock(); result = script_incoming_call; mtx_user.unlock(); return result; } string t_user::get_script_in_call_answered(void) const { string result; mtx_user.lock(); result = script_in_call_answered; mtx_user.unlock(); return result; } string t_user::get_script_in_call_failed(void) const { string result; mtx_user.lock(); result = script_in_call_failed; mtx_user.unlock(); return result; } string t_user::get_script_outgoing_call(void) const { string result; mtx_user.lock(); result = script_outgoing_call; mtx_user.unlock(); return result; } string t_user::get_script_out_call_answered(void) const { string result; mtx_user.lock(); result = script_out_call_answered; mtx_user.unlock(); return result; } string t_user::get_script_out_call_failed(void) const { string result; mtx_user.lock(); result = script_out_call_failed; mtx_user.unlock(); return result; } string t_user::get_script_local_release(void) const { string result; mtx_user.lock(); result = script_local_release; mtx_user.unlock(); return result; } string t_user::get_script_remote_release(void) const { string result; mtx_user.lock(); result = script_remote_release; mtx_user.unlock(); return result; } list t_user::get_number_conversions(void) const { list result; mtx_user.lock(); result = number_conversions; mtx_user.unlock(); return result; } bool t_user::get_zrtp_enabled(void) const { bool result; mtx_user.lock(); result = zrtp_enabled; mtx_user.unlock(); return result; } bool t_user::get_zrtp_goclear_warning(void) const { bool result; mtx_user.lock(); result = zrtp_goclear_warning; mtx_user.unlock(); return result; } bool t_user::get_zrtp_sdp(void) const { bool result; mtx_user.lock(); result = zrtp_sdp; mtx_user.unlock(); return result; } bool t_user::get_zrtp_send_if_supported(void) const { bool result; mtx_user.lock(); result = zrtp_send_if_supported; mtx_user.unlock(); return result; } bool t_user::get_mwi_solicited(void) const { bool result; mtx_user.lock(); result = mwi_solicited; mtx_user.unlock(); return result; } string t_user::get_mwi_user(void) const { string result; mtx_user.lock(); result = mwi_user; mtx_user.unlock(); return result; } t_url t_user::get_mwi_server(void) const { t_url result; mtx_user.lock(); result = mwi_server; mtx_user.unlock(); return result; } bool t_user::get_mwi_via_proxy(void) const { bool result; mtx_user.lock(); result = mwi_via_proxy; mtx_user.unlock(); return result; } unsigned long t_user::get_mwi_subscription_time(void) const { unsigned long result; mtx_user.lock(); result = mwi_subscription_time; mtx_user.unlock(); return result; } string t_user::get_mwi_vm_address(void) const { string result; mtx_user.lock(); result = mwi_vm_address; mtx_user.unlock(); return result; } unsigned short t_user::get_im_max_sessions(void) const { unsigned short result; mtx_user.lock(); result = im_max_sessions; mtx_user.unlock(); return result; } bool t_user::get_im_send_iscomposing(void) const { t_mutex_guard guard(mtx_user); return im_send_iscomposing; } unsigned long t_user::get_pres_subscription_time(void) const { unsigned long result; mtx_user.lock(); result = pres_subscription_time; mtx_user.unlock(); return result; } unsigned long t_user::get_pres_publication_time(void) const { unsigned long result; mtx_user.lock(); result = pres_publication_time; mtx_user.unlock(); return result; } bool t_user::get_pres_publish_startup(void) const { bool result; mtx_user.lock(); result = pres_publish_startup; mtx_user.unlock(); return result; } void t_user::set_name(const string &_name) { mtx_user.lock(); name = _name; mtx_user.unlock(); } void t_user::set_domain(const string &_domain) { mtx_user.lock(); domain = _domain; mtx_user.unlock(); } void t_user::set_display(const string &_display) { mtx_user.lock(); display = _display; mtx_user.unlock(); } void t_user::set_organization(const string &_organization) { mtx_user.lock(); organization = _organization; mtx_user.unlock(); } void t_user::set_auth_realm(const string &realm) { mtx_user.lock(); auth_realm = realm; mtx_user.unlock(); } void t_user::set_auth_name(const string &name) { mtx_user.lock(); auth_name = name; mtx_user.unlock(); } void t_user::set_auth_pass(const string &pass) { mtx_user.lock(); auth_pass = pass; mtx_user.unlock(); } void t_user::set_auth_aka_op(const uint8 *aka_op) { t_mutex_guard guard(mtx_user); memcpy(auth_aka_op, aka_op, AKA_OPLEN); } void t_user::set_auth_aka_amf(const uint8 *aka_amf) { t_mutex_guard guard(mtx_user); memcpy(auth_aka_amf, aka_amf, AKA_AMFLEN); } void t_user::set_use_outbound_proxy(bool b) { mtx_user.lock(); use_outbound_proxy = b; mtx_user.unlock(); } void t_user::set_outbound_proxy(const t_url &url) { mtx_user.lock(); outbound_proxy = url; mtx_user.unlock(); } void t_user::set_all_requests_to_proxy(bool b) { mtx_user.lock(); all_requests_to_proxy = b; mtx_user.unlock(); } void t_user::set_non_resolvable_to_proxy(bool b) { mtx_user.lock(); non_resolvable_to_proxy = b; mtx_user.unlock(); } void t_user::set_use_registrar(bool b) { mtx_user.lock(); use_registrar = b; mtx_user.unlock(); } void t_user::set_registrar(const t_url &url) { mtx_user.lock(); registrar = url; mtx_user.unlock(); } void t_user::set_registration_time(const unsigned long time) { mtx_user.lock(); registration_time = time; mtx_user.unlock(); } void t_user::set_register_at_startup(bool b) { mtx_user.lock(); register_at_startup = b; mtx_user.unlock(); } void t_user::set_reg_add_qvalue(bool b) { mtx_user.lock(); reg_add_qvalue = b; mtx_user.unlock(); } void t_user::set_reg_qvalue(float q) { mtx_user.lock(); reg_qvalue = q; mtx_user.unlock(); } void t_user::set_codecs(const list &_codecs) { mtx_user.lock(); codecs = _codecs; mtx_user.unlock(); } void t_user::set_ptime(unsigned short _ptime) { mtx_user.lock(); ptime = _ptime; mtx_user.unlock(); } void t_user::set_out_obey_far_end_codec_pref(bool b) { mtx_user.lock(); out_obey_far_end_codec_pref = b; mtx_user.unlock(); } void t_user::set_in_obey_far_end_codec_pref(bool b) { mtx_user.lock(); in_obey_far_end_codec_pref = b; mtx_user.unlock(); } void t_user::set_speex_nb_payload_type(unsigned short payload_type) { mtx_user.lock(); speex_nb_payload_type = payload_type; mtx_user.unlock(); } void t_user::set_speex_wb_payload_type(unsigned short payload_type) { mtx_user.lock(); speex_wb_payload_type = payload_type; mtx_user.unlock(); } void t_user::set_speex_uwb_payload_type(unsigned short payload_type) { mtx_user.lock(); speex_uwb_payload_type = payload_type; mtx_user.unlock(); } void t_user::set_speex_bit_rate_type(t_bit_rate_type bit_rate_type) { mtx_user.lock(); speex_bit_rate_type = bit_rate_type; mtx_user.unlock(); } void t_user::set_speex_abr_nb(int abr) { mtx_user.lock(); speex_abr_nb = abr; mtx_user.unlock(); } void t_user::set_speex_abr_wb(int abr) { mtx_user.lock(); speex_abr_wb = abr; mtx_user.unlock(); } void t_user::set_speex_dtx(bool b) { mtx_user.lock(); speex_dtx = b; mtx_user.unlock(); } void t_user::set_speex_penh(bool b) { mtx_user.lock(); speex_penh = b; mtx_user.unlock(); } void t_user::set_speex_quality(unsigned short quality) { mtx_user.lock(); speex_quality = quality; mtx_user.unlock(); } void t_user::set_speex_complexity(unsigned short complexity) { mtx_user.lock(); speex_complexity = complexity; mtx_user.unlock(); } void t_user::set_speex_dsp_vad(bool b) { mtx_user.lock(); speex_dsp_vad = b; mtx_user.unlock(); } void t_user::set_speex_dsp_agc(bool b) { mtx_user.lock(); speex_dsp_agc = b; mtx_user.unlock(); } void t_user::set_speex_dsp_agc_level(unsigned short level) { mtx_user.lock(); speex_dsp_agc_level = level; mtx_user.unlock(); } void t_user::set_speex_dsp_aec(bool b) { mtx_user.lock(); speex_dsp_aec = b; mtx_user.unlock(); } void t_user::set_speex_dsp_nrd(bool b) { mtx_user.lock(); speex_dsp_nrd = b; mtx_user.unlock(); } void t_user::set_ilbc_payload_type(unsigned short payload_type) { mtx_user.lock(); ilbc_payload_type = payload_type; mtx_user.unlock(); } void t_user::set_ilbc_mode(unsigned short mode) { mtx_user.lock(); ilbc_mode = mode; mtx_user.unlock(); } void t_user::set_g726_16_payload_type(unsigned short payload_type) { mtx_user.lock(); g726_16_payload_type = payload_type; mtx_user.unlock(); } void t_user::set_g726_24_payload_type(unsigned short payload_type) { mtx_user.lock(); g726_24_payload_type = payload_type; mtx_user.unlock(); } void t_user::set_g726_32_payload_type(unsigned short payload_type) { mtx_user.lock(); g726_32_payload_type = payload_type; mtx_user.unlock(); } void t_user::set_g726_40_payload_type(unsigned short payload_type) { mtx_user.lock(); g726_40_payload_type = payload_type; mtx_user.unlock(); } void t_user::set_g726_packing(t_g726_packing packing) { mtx_user.lock(); g726_packing = packing; mtx_user.unlock(); } void t_user::set_dtmf_transport(t_dtmf_transport _dtmf_transport) { mtx_user.lock(); dtmf_transport = _dtmf_transport; mtx_user.unlock(); } void t_user::set_dtmf_payload_type(unsigned short payload_type) { mtx_user.lock(); dtmf_payload_type = payload_type; mtx_user.unlock(); } void t_user::set_dtmf_duration(unsigned short duration) { mtx_user.lock(); dtmf_duration = duration; mtx_user.unlock(); } void t_user::set_dtmf_pause(unsigned short pause) { mtx_user.lock(); dtmf_pause = pause; mtx_user.unlock(); } void t_user::set_dtmf_volume(unsigned short volume) { mtx_user.lock(); dtmf_volume = volume; mtx_user.unlock(); } void t_user::set_hold_variant(t_hold_variant _hold_variant) { mtx_user.lock(); hold_variant = _hold_variant; mtx_user.unlock(); } void t_user::set_check_max_forwards(bool b) { mtx_user.lock(); check_max_forwards = b; mtx_user.unlock(); } void t_user::set_allow_missing_contact_reg(bool b) { mtx_user.lock(); allow_missing_contact_reg = b; mtx_user.unlock(); } void t_user::set_registration_time_in_contact(bool b) { mtx_user.lock(); registration_time_in_contact = b; mtx_user.unlock(); } void t_user::set_compact_headers(bool b) { mtx_user.lock(); compact_headers = b; mtx_user.unlock(); } void t_user::set_encode_multi_values_as_list(bool b) { mtx_user.lock(); encode_multi_values_as_list = b; mtx_user.unlock(); } void t_user::set_use_domain_in_contact(bool b) { mtx_user.lock(); use_domain_in_contact = b; mtx_user.unlock(); } void t_user::set_allow_sdp_change(bool b) { mtx_user.lock(); allow_sdp_change = b; mtx_user.unlock(); } void t_user::set_allow_redirection(bool b) { mtx_user.lock(); allow_redirection = b; mtx_user.unlock(); } void t_user::set_ask_user_to_redirect(bool b) { mtx_user.lock(); ask_user_to_redirect = b; mtx_user.unlock(); } void t_user::set_max_redirections(unsigned short _max_redirections) { mtx_user.lock(); max_redirections = _max_redirections; mtx_user.unlock(); } void t_user::set_ext_100rel(t_ext_support ext_support) { mtx_user.lock(); ext_100rel = ext_support; mtx_user.unlock(); } void t_user::set_ext_replaces(bool b) { mtx_user.lock(); ext_replaces = b; mtx_user.unlock(); } void t_user::set_referee_hold(bool b) { t_mutex_guard guard(mtx_user); referee_hold = b; } void t_user::set_referrer_hold(bool b) { mtx_user.lock(); referrer_hold = b; mtx_user.unlock(); } void t_user::set_allow_refer(bool b) { t_mutex_guard guard(mtx_user); allow_refer = b; } void t_user::set_ask_user_to_refer(bool b) { t_mutex_guard guard(mtx_user); ask_user_to_refer = b; } void t_user::set_auto_refresh_refer_sub(bool b) { t_mutex_guard guard(mtx_user); auto_refresh_refer_sub = b; } void t_user::set_attended_refer_to_aor(bool b) { t_mutex_guard guard(mtx_user); attended_refer_to_aor = b; } void t_user::set_allow_transfer_consultation_inprog(bool b) { t_mutex_guard guard(mtx_user); allow_transfer_consultation_inprog = b; } void t_user::set_send_p_preferred_id(bool b) { mtx_user.lock(); send_p_preferred_id = b; mtx_user.unlock(); } void t_user::set_send_p_asserted_id(bool b) { mtx_user.lock(); send_p_asserted_id = b; mtx_user.unlock(); } void t_user::set_sip_transport(t_sip_transport transport) { t_mutex_guard guard(mtx_user); sip_transport = transport; } void t_user::set_sip_transport_udp_threshold(unsigned short threshold) { t_mutex_guard guard(mtx_user); sip_transport_udp_threshold = threshold; } void t_user::set_use_nat_public_ip(bool b) { mtx_user.lock(); use_nat_public_ip = b; mtx_user.unlock(); } void t_user::set_nat_public_ip(const string &public_ip) { mtx_user.lock(); nat_public_ip = public_ip; mtx_user.unlock(); } void t_user::set_use_stun(bool b) { mtx_user.lock(); use_stun = b; mtx_user.unlock(); } void t_user::set_stun_server(const t_url &url) { mtx_user.lock(); stun_server = url; mtx_user.unlock(); } void t_user::set_persistent_tcp(bool b) { t_mutex_guard guard(mtx_user); persistent_tcp = b; } void t_user::set_enable_nat_keepalive(bool b) { t_mutex_guard guard(mtx_user); enable_nat_keepalive = b; } void t_user::set_timer_noanswer(unsigned short timer) { mtx_user.lock(); timer_noanswer = timer; mtx_user.unlock(); } void t_user::set_timer_nat_keepalive(unsigned short timer) { mtx_user.lock(); timer_nat_keepalive = timer; mtx_user.unlock(); } void t_user::set_timer_tcp_ping(unsigned short timer) { t_mutex_guard guard(mtx_user); timer_tcp_ping = timer; } void t_user::set_display_useronly_phone(bool b) { mtx_user.lock(); display_useronly_phone = b; mtx_user.unlock(); } void t_user::set_numerical_user_is_phone(bool b) { mtx_user.lock(); numerical_user_is_phone = b; mtx_user.unlock(); } void t_user::set_remove_special_phone_symbols(bool b) { mtx_user.lock(); remove_special_phone_symbols = b; mtx_user.unlock(); } void t_user::set_special_phone_symbols(const string &symbols) { mtx_user.lock(); special_phone_symbols = symbols; mtx_user.unlock(); } void t_user::set_use_tel_uri_for_phone(bool b) { t_mutex_guard guard(mtx_user); use_tel_uri_for_phone = b; } void t_user::set_ringtone_file(const string &file) { mtx_user.lock(); ringtone_file = file; mtx_user.unlock(); } void t_user::set_ringback_file(const string &file) { mtx_user.lock(); ringback_file = file; mtx_user.unlock(); } void t_user::set_script_incoming_call(const string &script) { mtx_user.lock(); script_incoming_call = script; mtx_user.unlock(); } void t_user::set_script_in_call_answered(const string &script) { mtx_user.lock(); script_in_call_answered = script; mtx_user.unlock(); } void t_user::set_script_in_call_failed(const string &script) { mtx_user.lock(); script_in_call_failed = script; mtx_user.unlock(); } void t_user::set_script_outgoing_call(const string &script) { mtx_user.lock(); script_outgoing_call = script; mtx_user.unlock(); } void t_user::set_script_out_call_answered(const string &script) { mtx_user.lock(); script_out_call_answered = script; mtx_user.unlock(); } void t_user::set_script_out_call_failed(const string &script) { mtx_user.lock(); script_out_call_failed = script; mtx_user.unlock(); } void t_user::set_script_local_release(const string &script) { mtx_user.lock(); script_local_release = script; mtx_user.unlock(); } void t_user::set_script_remote_release(const string &script) { mtx_user.lock(); script_remote_release = script; mtx_user.unlock(); } void t_user::set_number_conversions(const list &l) { mtx_user.lock(); number_conversions = l; mtx_user.unlock(); } void t_user::set_zrtp_enabled(bool b) { mtx_user.lock(); zrtp_enabled = b; mtx_user.unlock(); } void t_user::set_zrtp_goclear_warning(bool b) { mtx_user.lock(); zrtp_goclear_warning = b; mtx_user.unlock(); } void t_user::set_zrtp_sdp(bool b) { mtx_user.lock(); zrtp_sdp = b; mtx_user.unlock(); } void t_user::set_zrtp_send_if_supported(bool b) { mtx_user.lock(); zrtp_send_if_supported = b; mtx_user.unlock(); } void t_user::set_mwi_solicited(bool b) { mtx_user.lock(); mwi_solicited = b; mtx_user.unlock(); } void t_user::set_mwi_user(const string &user) { mtx_user.lock(); mwi_user = user; mtx_user.unlock(); } void t_user::set_mwi_server(const t_url &url) { mtx_user.lock(); mwi_server = url; mtx_user.unlock(); } void t_user::set_mwi_via_proxy(bool b) { mtx_user.lock(); mwi_via_proxy = b; mtx_user.unlock(); } void t_user::set_mwi_subscription_time(unsigned long t) { mtx_user.lock(); mwi_subscription_time = t; mtx_user.unlock(); } void t_user::set_mwi_vm_address(const string &address) { mtx_user.lock(); mwi_vm_address = address; mtx_user.unlock(); } void t_user::set_im_max_sessions(unsigned short max_sessions) { mtx_user.lock(); im_max_sessions = max_sessions; mtx_user.unlock(); } void t_user::set_im_send_iscomposing(bool b) { t_mutex_guard guard(mtx_user); im_send_iscomposing = b; } void t_user::set_pres_subscription_time(unsigned long t) { mtx_user.lock(); pres_subscription_time = t; mtx_user.unlock(); } void t_user::set_pres_publication_time(unsigned long t) { mtx_user.lock(); pres_publication_time = t; mtx_user.unlock(); } void t_user::set_pres_publish_startup(bool b) { mtx_user.lock(); pres_publish_startup = b; mtx_user.unlock(); } bool t_user::read_config(const string &filename, string &error_msg) { string f; string msg; mtx_user.lock(); if (filename.size() == 0) { error_msg = "Cannot read user profile: missing file name."; log_file->write_report(error_msg, "t_user::read_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } config_filename = filename; f = expand_filename(filename); ifstream config(f.c_str()); if (!config) { error_msg = "Cannot open file for reading: "; error_msg += f; log_file->write_report(error_msg, "t_user::read_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } log_file->write_header("t_user::read_config"); log_file->write_raw("Reading config: "); log_file->write_raw(filename); log_file->write_endl(); log_file->write_footer(); while (!config.eof()) { string line; getline(config, line); // Check if read operation succeeded if (!config.good() && !config.eof()) { error_msg = "File system error while reading file "; error_msg += f; log_file->write_report(error_msg, "t_user::read_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } line = trim(line); // Skip empty lines if (line.size() == 0) continue; // Skip comment lines if (line[0] == '#') continue; vector l = split_on_first(line, '='); if (l.size() != 2) { error_msg = "Syntax error in file "; error_msg += f; error_msg += "\n"; error_msg += line; log_file->write_report(error_msg, "t_user::read_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } string parameter = trim(l[0]); string value = trim(l[1]); if (parameter == FLD_NAME) { name = value; } else if (parameter == FLD_DOMAIN) { domain = value; } else if (parameter == FLD_DISPLAY) { display = value; } else if (parameter == FLD_ORGANIZATION) { organization = value; } else if (parameter == FLD_REGISTRATION_TIME) { registration_time = atol(value.c_str()); } else if (parameter == FLD_REGISTRATION_TIME_IN_CONTACT) { registration_time_in_contact = yesno2bool(value); } else if (parameter == FLD_REGISTRAR) { use_registrar = set_server_value(registrar, USER_SCHEME, value); } else if (parameter == FLD_REGISTER_AT_STARTUP) { register_at_startup = yesno2bool(value); } else if (parameter == FLD_REG_ADD_QVALUE) { reg_add_qvalue = yesno2bool(value); } else if (parameter == FLD_REG_QVALUE) { reg_qvalue = atof(value.c_str()); } else if (parameter == FLD_OUTBOUND_PROXY) { use_outbound_proxy = set_server_value(outbound_proxy, USER_SCHEME, value); } else if (parameter == FLD_ALL_REQUESTS_TO_PROXY) { all_requests_to_proxy = yesno2bool(value); } else if (parameter == FLD_NON_RESOLVABLE_TO_PROXY) { non_resolvable_to_proxy = yesno2bool(value); } else if (parameter == FLD_AUTH_REALM) { auth_realm = value; } else if (parameter == FLD_AUTH_NAME) { auth_name = value; } else if (parameter == FLD_AUTH_PASS) { auth_pass = value; } else if (parameter == FLD_AUTH_AKA_OP) { hex2binary(value, auth_aka_op); } else if (parameter == FLD_AUTH_AKA_AMF) { hex2binary(value, auth_aka_amf); } else if (parameter == FLD_CODECS) { vector l = split(value, ','); if (l.size() > 0) codecs.clear(); for (vector::iterator i = l.begin(); i != l.end(); i++) { string codec = trim(*i); if (codec == "g711a") { codecs.push_back(CODEC_G711_ALAW); } else if (codec == "g711u") { codecs.push_back(CODEC_G711_ULAW); } else if (codec == "gsm") { codecs.push_back(CODEC_GSM); #ifdef HAVE_SPEEX } else if (codec == "speex-nb") { codecs.push_back(CODEC_SPEEX_NB); } else if (codec == "speex-wb") { codecs.push_back(CODEC_SPEEX_WB); } else if (codec == "speex-uwb") { codecs.push_back(CODEC_SPEEX_UWB); #endif #ifdef HAVE_ILBC } else if (codec == "ilbc") { codecs.push_back(CODEC_ILBC); #endif } else if (codec == "g726-16") { codecs.push_back(CODEC_G726_16); } else if (codec == "g726-24") { codecs.push_back(CODEC_G726_24); } else if (codec == "g726-32") { codecs.push_back(CODEC_G726_32); } else if (codec == "g726-40") { codecs.push_back(CODEC_G726_40); #ifdef HAVE_BCG729 } else if (codec == "g729a") { codecs.push_back(CODEC_G729A); #endif } else { msg = "Syntax error in file "; msg += f; msg += "\n"; msg += "Invalid codec: "; msg += value; log_file->write_report(msg, "t_user::read_config", LOG_NORMAL, LOG_WARNING); } } } else if (parameter == FLD_PTIME) { ptime = atoi(value.c_str()); } else if (parameter == FLD_OUT_FAR_END_CODEC_PREF) { out_obey_far_end_codec_pref = yesno2bool(value); } else if (parameter == FLD_IN_FAR_END_CODEC_PREF) { in_obey_far_end_codec_pref = yesno2bool(value); } else if (parameter == FLD_HOLD_VARIANT) { if (value == "rfc2543") { hold_variant = HOLD_RFC2543; } else if (value == "rfc3264") { hold_variant = HOLD_RFC3264; } else { error_msg = "Syntax error in file "; error_msg += f; error_msg += "\n"; error_msg += "Invalid hold variant: "; error_msg += value; log_file->write_report(error_msg, "t_user::read_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } } else if (parameter == FLD_CHECK_MAX_FORWARDS) { check_max_forwards = yesno2bool(value); } else if (parameter == FLD_ALLOW_MISSING_CONTACT_REG) { allow_missing_contact_reg = yesno2bool(value); } else if (parameter == FLD_USE_DOMAIN_IN_CONTACT) { use_domain_in_contact = yesno2bool(value); } else if (parameter == FLD_ALLOW_SDP_CHANGE) { allow_sdp_change = yesno2bool(value); } else if (parameter == FLD_ALLOW_REDIRECTION) { allow_redirection = yesno2bool(value); } else if (parameter == FLD_ASK_USER_TO_REDIRECT) { ask_user_to_redirect = yesno2bool(value); } else if (parameter == FLD_MAX_REDIRECTIONS) { max_redirections = atoi(value.c_str()); } else if (parameter == FLD_REFEREE_HOLD) { referee_hold = yesno2bool(value); } else if (parameter == FLD_REFERRER_HOLD) { referrer_hold = yesno2bool(value); } else if (parameter == FLD_ALLOW_REFER) { allow_refer = yesno2bool(value); } else if (parameter == FLD_ASK_USER_TO_REFER) { ask_user_to_refer = yesno2bool(value); } else if (parameter == FLD_AUTO_REFRESH_REFER_SUB) { auto_refresh_refer_sub = yesno2bool(value); } else if (parameter == FLD_ATTENDED_REFER_TO_AOR) { attended_refer_to_aor = yesno2bool(value); } else if (parameter == FLD_ALLOW_XFER_CONSULT_INPROG) { allow_transfer_consultation_inprog = yesno2bool(value); } else if (parameter == FLD_SEND_P_PREFERRED_ID) { send_p_preferred_id = yesno2bool(value); } else if (parameter == FLD_SEND_P_ASSERTED_ID) { send_p_asserted_id = yesno2bool(value); } else if (parameter == FLD_SIP_TRANSPORT) { sip_transport = str2sip_transport(value); } else if (parameter == FLD_SIP_TRANSPORT_UDP_THRESHOLD) { sip_transport_udp_threshold = atoi(value.c_str()); } else if (parameter == FLD_NAT_PUBLIC_IP) { if (value.size() == 0) continue; use_nat_public_ip = true; nat_public_ip = value; } else if (parameter == FLD_STUN_SERVER) { use_stun = set_server_value(stun_server, "stun", value); } else if (parameter == FLD_PERSISTENT_TCP) { persistent_tcp = yesno2bool(value); } else if (parameter == FLD_ENABLE_NAT_KEEPALIVE) { enable_nat_keepalive = yesno2bool(value); } else if (parameter == FLD_TIMER_NOANSWER) { timer_noanswer = atoi(value.c_str()); } else if (parameter == FLD_TIMER_NAT_KEEPALIVE) { timer_nat_keepalive = atoi(value.c_str()); } else if (parameter == FLD_TIMER_TCP_PING) { timer_tcp_ping = atoi(value.c_str()); } else if (parameter == FLD_EXT_100REL) { ext_100rel = str2ext_support(value); if (ext_100rel == EXT_INVALID) { error_msg = "Syntax error in file "; error_msg += f; error_msg += "\n"; error_msg += "Invalid value for ext_100rel: "; error_msg += value; log_file->write_report(error_msg, "t_user::read_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } } else if (parameter == FLD_EXT_REPLACES) { ext_replaces = yesno2bool(value); } else if (parameter == FLD_COMPACT_HEADERS) { compact_headers = yesno2bool(value); } else if (parameter == FLD_ENCODE_MULTI_VALUES_AS_LIST) { encode_multi_values_as_list = yesno2bool(value); } else if (parameter == FLD_SPEEX_NB_PAYLOAD_TYPE) { speex_nb_payload_type = atoi(value.c_str()); } else if (parameter == FLD_SPEEX_WB_PAYLOAD_TYPE) { speex_wb_payload_type = atoi(value.c_str()); } else if (parameter == FLD_SPEEX_UWB_PAYLOAD_TYPE) { speex_uwb_payload_type = atoi(value.c_str()); } else if (parameter == FLD_SPEEX_BIT_RATE_TYPE) { speex_bit_rate_type = str2bit_rate_type(value); if (speex_bit_rate_type == BIT_RATE_INVALID) { error_msg = "Syntax error in file "; error_msg += f; error_msg += "\n"; error_msg += "Invalid value for speex bit rate type: "; error_msg += value; log_file->write_report(error_msg, "t_user::read_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } } else if (parameter == FLD_SPEEX_ABR_NB) { speex_abr_nb = atoi(value.c_str()); } else if (parameter == FLD_SPEEX_ABR_WB) { speex_abr_wb = atoi(value.c_str()); } else if (parameter == FLD_SPEEX_DTX) { speex_dtx = yesno2bool(value); } else if (parameter == FLD_SPEEX_PENH) { speex_penh = yesno2bool(value); } else if (parameter == FLD_SPEEX_QUALITY) { speex_quality = atoi(value.c_str()); if (speex_quality > 10) { error_msg = "Syntax error in file "; error_msg += f; error_msg += "\n"; error_msg += "Invalid value for speex quality: "; error_msg += value; log_file->write_report(error_msg, "t_user::read_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } } else if (parameter == FLD_SPEEX_COMPLEXITY) { speex_complexity = atoi(value.c_str()); if (speex_complexity < 1 || speex_complexity > 10) { error_msg = "Syntax error in file "; error_msg += f; error_msg += "\n"; error_msg += "Invalid value for speex complexity: "; error_msg += value; log_file->write_report(error_msg, "t_user::read_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } } else if (parameter == FLD_SPEEX_DSP_VAD) { speex_dsp_vad = yesno2bool(value); } else if (parameter == FLD_SPEEX_DSP_AGC) { speex_dsp_agc = yesno2bool(value); } else if (parameter == FLD_SPEEX_DSP_AEC) { speex_dsp_aec = yesno2bool(value); } else if (parameter == FLD_SPEEX_DSP_NRD) { speex_dsp_nrd = yesno2bool(value); } else if (parameter == FLD_SPEEX_DSP_AGC_LEVEL) { speex_dsp_agc_level = atoi(value.c_str()); if (speex_dsp_agc_level < 1 || speex_dsp_agc_level > 100) { error_msg = "Syntax error in file "; error_msg += f; error_msg += "\n"; error_msg += "Invalid value for automatic gain control level: "; error_msg += value; log_file->write_report(error_msg, "t_user::read_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } } else if (parameter == FLD_ILBC_PAYLOAD_TYPE) { ilbc_payload_type = atoi(value.c_str()); } else if (parameter == FLD_ILBC_MODE) { ilbc_mode = atoi(value.c_str()); } else if (parameter == FLD_G726_16_PAYLOAD_TYPE) { g726_16_payload_type = atoi(value.c_str()); } else if (parameter == FLD_G726_24_PAYLOAD_TYPE) { g726_24_payload_type = atoi(value.c_str()); } else if (parameter == FLD_G726_32_PAYLOAD_TYPE) { g726_32_payload_type = atoi(value.c_str()); } else if (parameter == FLD_G726_40_PAYLOAD_TYPE) { g726_40_payload_type = atoi(value.c_str()); } else if (parameter == FLD_G726_PACKING) { g726_packing = str2g726_packing(value); } else if (parameter == FLD_DTMF_TRANSPORT) { dtmf_transport = str2dtmf_transport(value); } else if (parameter == FLD_DTMF_PAYLOAD_TYPE) { dtmf_payload_type = atoi(value.c_str()); } else if (parameter == FLD_DTMF_DURATION) { dtmf_duration = atoi(value.c_str()); } else if (parameter == FLD_DTMF_PAUSE) { dtmf_pause = atoi(value.c_str()); } else if (parameter == FLD_DTMF_VOLUME) { dtmf_volume = atoi(value.c_str()); } else if (parameter == FLD_DISPLAY_USERONLY_PHONE) { display_useronly_phone = yesno2bool(value); } else if (parameter == FLD_NUMERICAL_USER_IS_PHONE) { numerical_user_is_phone = yesno2bool(value); } else if (parameter == FLD_REMOVE_SPECIAL_PHONE_SYM) { remove_special_phone_symbols = yesno2bool(value); } else if (parameter == FLD_SPECIAL_PHONE_SYMBOLS) { special_phone_symbols = value; } else if (parameter == FLD_USE_TEL_URI_FOR_PHONE) { use_tel_uri_for_phone = yesno2bool(value); } else if (parameter == FLD_USER_RINGTONE_FILE) { ringtone_file = value; } else if (parameter == FLD_USER_RINGBACK_FILE) { ringback_file = value; } else if (parameter == FLD_SCRIPT_INCOMING_CALL) { script_incoming_call = value; } else if (parameter == FLD_SCRIPT_IN_CALL_ANSWERED) { script_in_call_answered = value; } else if (parameter == FLD_SCRIPT_IN_CALL_FAILED) { script_in_call_failed = value; } else if (parameter == FLD_SCRIPT_OUTGOING_CALL) { script_outgoing_call = value; } else if (parameter == FLD_SCRIPT_OUT_CALL_ANSWERED) { script_out_call_answered = value; } else if (parameter == FLD_SCRIPT_OUT_CALL_FAILED) { script_out_call_failed = value; } else if (parameter == FLD_SCRIPT_LOCAL_RELEASE) { script_local_release = value; } else if (parameter == FLD_SCRIPT_REMOTE_RELEASE) { script_remote_release = value; } else if (parameter == FLD_NUMBER_CONVERSION) { t_number_conversion c; if (parse_num_conversion(value, c)) { number_conversions.push_back(c); } } else if (parameter == FLD_ZRTP_ENABLED) { zrtp_enabled = yesno2bool(value); } else if (parameter == FLD_ZRTP_GOCLEAR_WARNING) { zrtp_goclear_warning = yesno2bool(value); } else if (parameter == FLD_ZRTP_SDP) { zrtp_sdp = yesno2bool(value); } else if (parameter == FLD_ZRTP_SEND_IF_SUPPORTED) { zrtp_send_if_supported = yesno2bool(value); } else if (parameter == FLD_MWI_SOLICITED) { mwi_solicited = yesno2bool(value); } else if (parameter == FLD_MWI_USER) { mwi_user = value; } else if (parameter == FLD_MWI_SERVER) { (void)set_server_value(mwi_server, USER_SCHEME, value); } else if (parameter == FLD_MWI_VIA_PROXY) { mwi_via_proxy = yesno2bool(value); } else if (parameter == FLD_MWI_SUBSCRIPTION_TIME) { mwi_subscription_time = atol(value.c_str()); } else if (parameter == FLD_MWI_VM_ADDRESS) { mwi_vm_address = value; } else if (parameter == FLD_IM_MAX_SESSIONS) { im_max_sessions = atoi(value.c_str()); } else if (parameter == FLD_IM_SEND_ISCOMPOSING) { im_send_iscomposing = yesno2bool(value); } else if (parameter == FLD_PRES_SUBSCRIPTION_TIME) { pres_subscription_time = atol(value.c_str()); } else if (parameter == FLD_PRES_PUBLICATION_TIME) { pres_publication_time = atol(value.c_str()); } else if (parameter == FLD_PRES_PUBLISH_STARTUP) { pres_publish_startup = yesno2bool(value); } else { // Ignore unknown parameters. Only report in log file. log_file->write_header("t_user::read_config", LOG_NORMAL, LOG_WARNING); log_file->write_raw("Unknown parameter in user profile: "); log_file->write_raw(parameter); log_file->write_endl(); log_file->write_footer(); } } // Set parser options t_parser::check_max_forwards = check_max_forwards; t_parser::compact_headers = compact_headers; t_parser::multi_values_as_list = encode_multi_values_as_list; mtx_user.unlock(); return true; } bool t_user::write_config(const string &filename, string &error_msg) { struct stat stat_buf; string f; mtx_user.lock(); if (filename.size() == 0) { error_msg = "Cannot write user profile: missing file name."; log_file->write_report(error_msg, "t_user::write_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } config_filename = filename; f = expand_filename(filename); // Make a backup of the file if we are editing an existing file, so // that can be restored when writing fails. string f_backup = f + '~'; if (stat(f.c_str(), &stat_buf) == 0) { if (rename(f.c_str(), f_backup.c_str()) != 0) { string err = get_error_str(errno); error_msg = "Failed to backup "; error_msg += f; error_msg += " to "; error_msg += f_backup; error_msg += "\n"; error_msg += err; log_file->write_report(error_msg, "t_user::write_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } } ofstream config(f.c_str()); if (!config) { error_msg = "Cannot open file for writing: "; error_msg += f; log_file->write_report(error_msg, "t_user::write_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } log_file->write_header("t_user::write_config"); log_file->write_raw("Writing config: "); log_file->write_raw(filename); log_file->write_endl(); log_file->write_footer(); // Write USER settings config << "# USER\n"; config << FLD_NAME << '=' << name << endl; config << FLD_DOMAIN << '=' << domain << endl; config << FLD_DISPLAY << '=' << display << endl; config << FLD_ORGANIZATION << '=' << organization << endl; config << FLD_AUTH_REALM << '=' << auth_realm << endl; config << FLD_AUTH_NAME << '=' << auth_name << endl; config << FLD_AUTH_PASS << '=' << auth_pass << endl; config << FLD_AUTH_AKA_OP << '=' << binary2hex(auth_aka_op, AKA_OPLEN) << endl; config << FLD_AUTH_AKA_AMF << '=' << binary2hex(auth_aka_amf, AKA_AMFLEN) << endl; config << endl; // Write SIP SERVER settings config << "# SIP SERVER\n"; if (use_outbound_proxy) { config << FLD_OUTBOUND_PROXY << '='; config << outbound_proxy.encode_noscheme() << endl; config << FLD_ALL_REQUESTS_TO_PROXY << '='; config << bool2yesno(all_requests_to_proxy) << endl; config << FLD_NON_RESOLVABLE_TO_PROXY << '='; config << bool2yesno(non_resolvable_to_proxy) << endl; } else { config << FLD_OUTBOUND_PROXY << '=' << endl; config << FLD_ALL_REQUESTS_TO_PROXY << "=no" << endl; } if (use_registrar) { config << FLD_REGISTRAR << '=' << registrar.encode_noscheme(); config << endl; } else { config << FLD_REGISTRAR << '=' << endl; } config << FLD_REGISTER_AT_STARTUP << '='; config << bool2yesno(register_at_startup) << endl; config << FLD_REGISTRATION_TIME << '=' << registration_time << endl; config << FLD_REG_ADD_QVALUE << '=' << bool2yesno(reg_add_qvalue) << endl; config << FLD_REG_QVALUE << '=' << reg_qvalue << endl; config << endl; // Write AUDIO settings config << "# RTP AUDIO\n"; config << FLD_CODECS << '='; for (list::iterator i = codecs.begin(); i != codecs.end(); i++) { if (i != codecs.begin()) config << ','; switch(*i) { case CODEC_G711_ALAW: config << "g711a"; break; case CODEC_G711_ULAW: config << "g711u"; break; case CODEC_GSM: config << "gsm"; break; case CODEC_SPEEX_NB: config << "speex-nb"; break; case CODEC_SPEEX_WB: config << "speex-wb"; break; case CODEC_SPEEX_UWB: config << "speex-uwb"; break; case CODEC_ILBC: config << "ilbc"; break; case CODEC_G726_16: config << "g726-16"; break; case CODEC_G726_24: config << "g726-24"; break; case CODEC_G726_32: config << "g726-32"; break; case CODEC_G726_40: config << "g726-40"; break; case CODEC_G729A: config << "g729a"; break; default: assert(false); } } config << endl; config << FLD_PTIME << '=' << ptime << endl; config << FLD_OUT_FAR_END_CODEC_PREF << '=' << bool2yesno(out_obey_far_end_codec_pref) << endl; config << FLD_IN_FAR_END_CODEC_PREF << '=' << bool2yesno(in_obey_far_end_codec_pref) << endl; config << FLD_SPEEX_NB_PAYLOAD_TYPE << '=' << speex_nb_payload_type << endl; config << FLD_SPEEX_WB_PAYLOAD_TYPE << '=' << speex_wb_payload_type << endl; config << FLD_SPEEX_UWB_PAYLOAD_TYPE << '=' << speex_uwb_payload_type << endl; config << FLD_SPEEX_BIT_RATE_TYPE << '='; // config << FLD_SPEEX_ABR_NB << '=' << speex_abr_nb << endl; // config << FLD_SPEEX_ABR_WB << '=' << speex_abr_wb << endl; config << bit_rate_type2str(speex_bit_rate_type) << endl; config << FLD_SPEEX_DTX << '=' << bool2yesno(speex_dtx) << endl; config << FLD_SPEEX_PENH << '=' << bool2yesno(speex_penh) << endl; config << FLD_SPEEX_QUALITY << '=' << speex_quality << endl; config << FLD_SPEEX_COMPLEXITY << '=' << speex_complexity << endl; config << FLD_SPEEX_DSP_VAD << '=' << bool2yesno(speex_dsp_vad) << endl; config << FLD_SPEEX_DSP_AGC << '=' << bool2yesno(speex_dsp_agc) << endl; config << FLD_SPEEX_DSP_AEC << '=' << bool2yesno(speex_dsp_aec) << endl; config << FLD_SPEEX_DSP_NRD << '=' << bool2yesno(speex_dsp_nrd) << endl; config << FLD_SPEEX_DSP_AGC_LEVEL << '=' << speex_dsp_agc_level << endl; config << FLD_ILBC_PAYLOAD_TYPE << '=' << ilbc_payload_type << endl; config << FLD_ILBC_MODE << '=' << ilbc_mode << endl; config << FLD_G726_16_PAYLOAD_TYPE << '=' << g726_16_payload_type << endl; config << FLD_G726_24_PAYLOAD_TYPE << '=' << g726_24_payload_type << endl; config << FLD_G726_32_PAYLOAD_TYPE << '=' << g726_32_payload_type << endl; config << FLD_G726_40_PAYLOAD_TYPE << '=' << g726_40_payload_type << endl; config << FLD_G726_PACKING << '=' << g726_packing2str(g726_packing) << endl; config << FLD_DTMF_TRANSPORT << '=' << dtmf_transport2str(dtmf_transport) << endl; config << FLD_DTMF_PAYLOAD_TYPE << '=' << dtmf_payload_type << endl; config << FLD_DTMF_DURATION << '=' << dtmf_duration << endl; config << FLD_DTMF_PAUSE << '=' << dtmf_pause << endl; config << FLD_DTMF_VOLUME << '=' << dtmf_volume << endl; config << endl; // Write SIP PROTOCOL settings config << "# SIP PROTOCOL\n"; config << FLD_HOLD_VARIANT << '='; switch(hold_variant) { case HOLD_RFC2543: config << "rfc2543"; break; case HOLD_RFC3264: config << "rfc3264"; break; default: assert(false); } config << endl; config << FLD_CHECK_MAX_FORWARDS << '='; config << bool2yesno(check_max_forwards) << endl; config << FLD_ALLOW_MISSING_CONTACT_REG << '='; config << bool2yesno(allow_missing_contact_reg) << endl; config << FLD_REGISTRATION_TIME_IN_CONTACT << '='; config << bool2yesno(registration_time_in_contact) << endl; config << FLD_COMPACT_HEADERS << '=' << bool2yesno(compact_headers) << endl; config << FLD_ENCODE_MULTI_VALUES_AS_LIST << '='; config << bool2yesno(encode_multi_values_as_list) << endl; config << FLD_USE_DOMAIN_IN_CONTACT << '='; config << bool2yesno(use_domain_in_contact) << endl; config << FLD_ALLOW_SDP_CHANGE << '=' << bool2yesno(allow_sdp_change) << endl; config << FLD_ALLOW_REDIRECTION << '=' << bool2yesno(allow_redirection); config << endl; config << FLD_ASK_USER_TO_REDIRECT << '='; config << bool2yesno(ask_user_to_redirect) << endl; config << FLD_MAX_REDIRECTIONS << '=' << max_redirections << endl; config << FLD_EXT_100REL << '=' << ext_support2str(ext_100rel) << endl; config << FLD_EXT_REPLACES << '=' << bool2yesno(ext_replaces) << endl; config << FLD_REFEREE_HOLD << '=' << bool2yesno(referee_hold) << endl; config << FLD_REFERRER_HOLD << '=' << bool2yesno(referrer_hold) << endl; config << FLD_ALLOW_REFER << '=' << bool2yesno(allow_refer) << endl; config << FLD_ASK_USER_TO_REFER << '='; config << bool2yesno(ask_user_to_refer) << endl; config << FLD_AUTO_REFRESH_REFER_SUB << '='; config << bool2yesno(auto_refresh_refer_sub) << endl; config << FLD_ATTENDED_REFER_TO_AOR << '='; config << bool2yesno(attended_refer_to_aor) << endl; config << FLD_ALLOW_XFER_CONSULT_INPROG << '='; config << bool2yesno(allow_transfer_consultation_inprog) << endl; config << FLD_SEND_P_PREFERRED_ID << '='; config << bool2yesno(send_p_preferred_id) << endl; config << FLD_SEND_P_ASSERTED_ID << '='; config << bool2yesno(send_p_asserted_id) << endl; config << endl; // Write Transport/NAT settings config << "# Transport/NAT\n"; config << FLD_SIP_TRANSPORT << '=' << sip_transport2str(sip_transport) << endl; config << FLD_SIP_TRANSPORT_UDP_THRESHOLD << '=' << sip_transport_udp_threshold << endl; if (use_nat_public_ip) { config << FLD_NAT_PUBLIC_IP << '=' << nat_public_ip << endl; } else { config << FLD_NAT_PUBLIC_IP << '=' << endl; } if (use_stun) { config << FLD_STUN_SERVER << '=' << stun_server.encode_noscheme() << endl; } else { config << FLD_STUN_SERVER << '=' << endl; } config << FLD_PERSISTENT_TCP << '=' << bool2yesno(persistent_tcp) << endl; config << FLD_ENABLE_NAT_KEEPALIVE << '=' << bool2yesno(enable_nat_keepalive) << endl; config << endl; // Write TIMER settings config << "# TIMERS\n"; config << FLD_TIMER_NOANSWER << '=' << timer_noanswer << endl; config << FLD_TIMER_NAT_KEEPALIVE << '=' << timer_nat_keepalive << endl; config << FLD_TIMER_TCP_PING << '=' << timer_tcp_ping << endl; config << endl; // Write ADDRESS FORMAT settings config << "# ADDRESS FORMAT\n"; config << FLD_DISPLAY_USERONLY_PHONE << '='; config << bool2yesno(display_useronly_phone) << endl; config << FLD_NUMERICAL_USER_IS_PHONE << '='; config << bool2yesno(numerical_user_is_phone) << endl; config << FLD_REMOVE_SPECIAL_PHONE_SYM << '='; config << bool2yesno(remove_special_phone_symbols) << endl; config << FLD_SPECIAL_PHONE_SYMBOLS << '=' << special_phone_symbols << endl; config << FLD_USE_TEL_URI_FOR_PHONE << '=' << bool2yesno(use_tel_uri_for_phone) << endl; config << endl; // Write RING TONE settings config << "# RING TONES\n"; config << FLD_USER_RINGTONE_FILE << '=' << ringtone_file << endl; config << FLD_USER_RINGBACK_FILE << '=' << ringback_file << endl; config << endl; // Write script settings config << "# SCRIPTS\n"; config << FLD_SCRIPT_INCOMING_CALL << '=' << script_incoming_call << endl; config << FLD_SCRIPT_IN_CALL_ANSWERED << '=' << script_in_call_answered << endl; config << FLD_SCRIPT_IN_CALL_FAILED << '=' << script_in_call_failed << endl; config << FLD_SCRIPT_OUTGOING_CALL << '=' << script_outgoing_call << endl; config << FLD_SCRIPT_OUT_CALL_ANSWERED << '=' << script_out_call_answered << endl; config << FLD_SCRIPT_OUT_CALL_FAILED << '=' << script_out_call_failed << endl; config << FLD_SCRIPT_LOCAL_RELEASE << '=' << script_local_release << endl; config << FLD_SCRIPT_REMOTE_RELEASE << '=' << script_remote_release << endl; config << endl; // Write number conversion rules config << "# NUMBER CONVERSION\n"; for (list::iterator i = number_conversions.begin(); i != number_conversions.end(); i++) { config << FLD_NUMBER_CONVERSION << '='; config << escape(i->re, ','); config << ','; config << escape(i->fmt, ','); config << endl; } config << endl; // Write security settings config << "# SECURITY\n"; config << FLD_ZRTP_ENABLED << '=' << bool2yesno(zrtp_enabled) << endl; config << FLD_ZRTP_GOCLEAR_WARNING << '=' << bool2yesno(zrtp_goclear_warning) << endl; config << FLD_ZRTP_SDP << '=' << bool2yesno(zrtp_sdp) << endl; config << FLD_ZRTP_SEND_IF_SUPPORTED << '=' << bool2yesno(zrtp_send_if_supported) << endl; config << endl; // Write MWI settings config << "# MWI\n"; config << FLD_MWI_SOLICITED << '=' << bool2yesno(mwi_solicited) << endl; config << FLD_MWI_USER << '=' << mwi_user << endl; if (mwi_server.is_valid()) { config << FLD_MWI_SERVER << '=' << mwi_server.encode_noscheme() << endl; } else { config << FLD_MWI_SERVER << '=' << endl; } config << FLD_MWI_VIA_PROXY << '=' << bool2yesno(mwi_via_proxy) << endl; config << FLD_MWI_SUBSCRIPTION_TIME << '=' << mwi_subscription_time << endl; config << FLD_MWI_VM_ADDRESS << '=' << mwi_vm_address << endl; config << endl; config << "# INSTANT MESSAGE\n"; config << FLD_IM_MAX_SESSIONS << '=' << im_max_sessions << endl; config << FLD_IM_SEND_ISCOMPOSING << '=' << bool2yesno(im_send_iscomposing) << endl; config << endl; // Write presence settings config << "# PRESENCE\n"; config << FLD_PRES_SUBSCRIPTION_TIME << '=' << pres_subscription_time << endl; config << FLD_PRES_PUBLICATION_TIME << '=' << pres_publication_time << endl; config << FLD_PRES_PUBLISH_STARTUP << '=' << bool2yesno(pres_publish_startup) << endl; // Check if writing succeeded if (!config.good()) { // Restore backup config.close(); rename(f_backup.c_str(), f.c_str()); error_msg = "File system error while writing file "; error_msg += f; log_file->write_report(error_msg, "t_user::write_config", LOG_NORMAL, LOG_CRITICAL); mtx_user.unlock(); return false; } // Set parser options t_parser::check_max_forwards = check_max_forwards; t_parser::compact_headers = compact_headers; t_parser::multi_values_as_list = encode_multi_values_as_list; mtx_user.unlock(); return true; } string t_user::get_filename(void) const { string result; mtx_user.lock(); result = config_filename; mtx_user.unlock(); return result; } bool t_user::set_config(string filename) { t_mutex_guard guard(mtx_user); struct stat stat_buf; config_filename = filename; string fullpath = expand_filename(filename); return (stat(fullpath.c_str(), &stat_buf) != 0); } string t_user::get_profile_name(void) const { string result; mtx_user.lock(); string::size_type pos_ext = config_filename.find(USER_FILE_EXT); if (pos_ext == string::npos) { result = config_filename; } else { result = config_filename.substr(0, pos_ext); } mtx_user.unlock(); return result; } string t_user::get_contact_name(void) const { mtx_user.lock(); string s = name; // Some broken proxies expect the contact name to be the same // as the SIP user name. if (!use_domain_in_contact) { mtx_user.unlock(); return s; } // Create a unique contact name from the user name and domain: // // username_domain, where all dots in domain are replace // // This way it is possible to activate 2 profiles that have the // same username, but different domains, e.g. // // michel@domainA // michel@domainB s += '_'; // Cut of port and/or uri-parameters if present in domain string::size_type i = domain.find_first_of(":;"); if (i != string::npos) { // Some broken SIP proxies think that their own address appears // in the contact header when they see the domain in the user part. // By replacing the dots with underscores Twinkle interoperates // with those proxies (yuck). s += replace_char(domain.substr(0, i), '.', '_'); } else { s += replace_char(domain, '.', '_'); } mtx_user.unlock(); return s; } string t_user::get_display_uri(void) const { mtx_user.lock(); string s; s = display; if (!s.empty()) s += ' '; s += '<'; s += USER_SCHEME; s += ':'; s += name; s += '@'; s += domain; s += '>'; mtx_user.unlock(); return s; } bool t_user::check_required_ext(t_request *r, list &unsupported) const { bool all_supported = true; mtx_user.lock(); unsupported.clear(); if (!r->hdr_require.is_populated()) { mtx_user.unlock(); return true; } for (list::iterator i = r->hdr_require.features.begin(); i != r->hdr_require.features.end(); i++) { if (*i == EXT_100REL) { if (ext_100rel != EXT_DISABLED) continue; } else if (*i == EXT_REPLACES) { if (ext_replaces) continue; } else if (*i == EXT_NOREFERSUB) { continue; } // Extension is not supported unsupported.push_back(*i); all_supported = false; } mtx_user.unlock(); return all_supported; } string t_user::create_user_contact(bool anonymous, const string &auto_ip) { string s; mtx_user.lock(); s = USER_SCHEME; s += ':'; if (!anonymous) { s += t_url::escape_user_value(get_contact_name()); s += '@'; } s += USER_HOST(this, auto_ip); if (PUBLIC_SIP_PORT(this) != get_default_port(USER_SCHEME)) { s += ':'; s += int2str(PUBLIC_SIP_PORT(this)); } if (phone->use_stun(this)) { // The port discovered via STUN can only be used for UDP. s += ";transport=udp"; } else { // Add transport parameter if a single transport is provisioned only. switch (sip_transport) { case SIP_TRANS_UDP: s += ";transport=udp"; break; case SIP_TRANS_TCP: s += ";transport=tcp"; break; default: break; } } if (!anonymous && numerical_user_is_phone && looks_like_phone(name, special_phone_symbols)) { // RFC 3261 19.1.1 // If the URI contains a telephone number it SHOULD contain // the user=phone parameter. s += ";user=phone"; } mtx_user.unlock(); return s; } string t_user::create_user_uri(bool anonymous) { if (anonymous) return ANONYMOUS_URI; string s; mtx_user.lock(); s = USER_SCHEME; s += ':'; s += t_url::escape_user_value(name); s += '@'; s += domain; if (numerical_user_is_phone && looks_like_phone(name, special_phone_symbols)) { // RFC 3261 19.1.1 // If the URI contains a telephone number it SHOULD contain // the user=phone parameter. s += ";user=phone"; } mtx_user.unlock(); return s; } string t_user::convert_number(const string &number, const list &l) const { for (list::const_iterator i = l.begin(); i != l.end(); i++) { std::smatch m; try { if (std::regex_match(number, m, std::regex(i->re))) { string result; m.format(std::back_inserter(result), i->fmt); log_file->write_header("t_user::convert_number", LOG_NORMAL, LOG_DEBUG); log_file->write_raw("Apply conversion: "); log_file->write_raw(i->str()); log_file->write_endl(); log_file->write_raw(number); log_file->write_raw(" converted to "); log_file->write_raw(result); log_file->write_endl(); log_file->write_footer(); return result; } } catch (std::runtime_error) { log_file->write_header("t_user::convert_number", LOG_NORMAL, LOG_WARNING); log_file->write_raw("Number conversion rule too complex:\n"); log_file->write_raw("Number: "); log_file->write_raw(number); log_file->write_endl(); log_file->write_raw(i->str()); log_file->write_endl(); log_file->write_footer(); return number; } } // No match found return number; } string t_user::convert_number(const string &number) const { return convert_number(number, number_conversions); } t_url t_user::get_mwi_uri(void) const { t_url u(mwi_server); u.set_user(mwi_user); return u; } bool t_user::is_diamondcard_account(void) const { // A profile is a Diamondcard account if the end configured domain // is equal to the DIAMONDCARD_DOMAIN size_t domain_len = strlen(DIAMONDCARD_DOMAIN); if (domain.size() < domain_len) return false; size_t pos = domain.size() - domain_len; return (domain.substr(pos) == DIAMONDCARD_DOMAIN); }