/* Copyright (C) 2005-2007 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // NOTE: // When adding attributes to t_user, make sure to add them to the // copy constructor too! #ifndef _H_USER #define _H_USER #include #include #include "sys_settings.h" #include "audio/audio_codecs.h" #include "sockets/url.h" #include "threads/mutex.h" #include "boost/regex.hpp" // Forward declaration class t_request; // Default config file name #define USER_CONFIG_FILE "twinkle.cfg" #define USER_FILE_EXT ".cfg" #define USER_DIR DIR_USER #define USER_SCHEME "sip" #define PUBLIC_SIP_UDP_PORT(u) phone->get_public_port_sip(u) #define USER_HOST(u) phone->get_ip_sip(u) #define LOCAL_IP user_host #define SPECIAL_PHONE_SYMBOLS "-()/." using namespace std; enum t_hold_variant { HOLD_RFC2543, // set IP = 0.0.0.0 in c-line HOLD_RFC3264 // use direction attribute to put call on-hold }; enum t_ext_support { EXT_INVALID, EXT_DISABLED, EXT_SUPPORTED, EXT_PREFERRED, EXT_REQUIRED }; enum t_bit_rate_type { BIT_RATE_INVALID, BIT_RATE_CBR, // Constant BIT_RATE_VBR, // Variable BIT_RATE_ABR // Average }; enum t_dtmf_transport { DTMF_INBAND, DTMF_RFC2833, DTMF_AUTO, DTMF_INFO }; enum t_g726_packing { G726_PACK_RFC3551, G726_PACK_AAL2 }; struct t_number_conversion { boost::regex re; string fmt; string str(void) const { return re.str() + " --> " + fmt; } }; class t_user { private: string config_filename; // Mutex for exclusive access to the user profile mutable t_recursive_mutex mtx_user; // USER // SIP user string name; string domain; string display; // The organization will be put in an initial INVITE and in a // 200 OK on an INVITE. string organization; // SIP authentication string auth_realm; // an empty realm matches with all realms string auth_name; string auth_pass; // SIP SERVER // Send all non-REGISTER requests to the outbound proxy bool use_outbound_proxy; t_url outbound_proxy; // By default only out-of-dialog requests (including the ones the // establish a dialog) are sent to the outbound proxy. // In-dialog requests go to the address established via the contact // header. // By setting this parameter to true, in-dialog requests go to the // outbound proxy as well. bool all_requests_to_proxy; // Only send the request to the proxy, if the destination cannot // be resolved to an IP address, adhearing to the previous setting // though. I.e. use_outbound_proxy must be true. And an in-dialog // request will only be sent to the proxy if all_requests_to_proxy // is true. bool non_resolvable_to_proxy; // Send REGISTER to registrar bool use_registrar; t_url registrar; // Registration time requested by the client. If set to zero, then // no specific time is requested. The registrar will set a time. unsigned long registration_time; // Automatically register at startup of the client. bool register_at_startup; // AUDIO list codecs; // in order of preference unsigned short ptime; // ptime (ms) for G.711/G.726 // For outgoing calls, obey the preference from the far-end (SDP answer), // i.e. pick the first codec from the SDP answer that we support. bool out_obey_far_end_codec_pref; // For incoming calls, obey the preference from the far-end (SDP offer), // i.e. pick the first codec from the SDP offer that we support. bool in_obey_far_end_codec_pref; // RTP dynamic payload types for speex unsigned short speex_nb_payload_type; unsigned short speex_wb_payload_type; unsigned short speex_uwb_payload_type; // Speex options t_bit_rate_type speex_bit_rate_type; int speex_abr_nb; int speex_abr_wb; bool speex_vad; bool speex_dtx; bool speex_penh; unsigned short speex_complexity; // RTP dynamic payload types for iLBC unsigned short ilbc_payload_type; // iLBC options unsigned short ilbc_mode; // 20 or 30 ms frame size // RTP dynamic payload types for G.726 unsigned short g726_16_payload_type; unsigned short g726_24_payload_type; unsigned short g726_32_payload_type; unsigned short g726_40_payload_type; // Bit packing order for G,726 t_g726_packing g726_packing; // Transport mode for DTMF t_dtmf_transport dtmf_transport; // RTP dynamic payload type for out-of-band DTMF. unsigned short dtmf_payload_type; // DTMF duration and pause between 2 tones. During the pause the last // DTMF event will be repeated so the far end can detect the end of // the event in case of packet loss. unsigned short dtmf_duration; // ms unsigned short dtmf_pause; // ms // Volume of the tone in -dBm unsigned short dtmf_volume; // SIP PROTOCOL // SIP protocol options // hold variants: rfc2543, rfc3264 // rfc2543 - set IP address to 0.0.0.0 // rfc3264 - use direction attribute (sendrecv, sendonly, ...) t_hold_variant hold_variant; // Indicate if the mandatory Max-Forwards header should be present. // If true and the header is missing, then the request will fail. bool check_max_forwards; // RFC 3261 10.3 states that a registrar must include a contact // header in a 200 OK on a REGISTER. This contact should match the // contact that a UA puts in the REGISTER. Unfortunately many // registrars do not include the contact header or put a wrong // IP address in the host-part due to NAT. // This settings allows for a missing/non-matching contact header. // In that case Twinkle assumes that it is registered for the // requested interval. bool allow_missing_contact_reg; // Indicate the place of the requested registration time in a REGISTER. // true - expires parameter in contact header // false - Expires header bool registration_time_in_contact; // Indicate if compact header names should be used in outgoing messages. bool compact_headers; // Indicate if headers containing multiple values should be encoded // as a comma separated list or as multiple headers. bool encode_multi_values_as_list; // Indicate if a unique contact name should be created by using // the domain name: username_domain // If false then the SIP user name is used as contact name bool use_domain_in_contact; // Allow SDP to change in different INVITE responses. // According to RFC 3261 13.2.1, if SDP is received in a 1XX response, // then SDP received in subsequent responses should be ignored. // Some SIP proxies do send different SDP in 1XX and 200 though. // E.g. first SDP is to play ring tone, second SDP is to create // an end-to-end media path. bool allow_sdp_change; // Redirections // Allow redirection of a request when a 3XX is received. bool allow_redirection; // Ask user for permission to redirect a request when a 3XX is received. bool ask_user_to_redirect; // Maximum number of locations to be tried when a request is redirected. unsigned short max_redirections; // SIP extensions // 100rel extension (PRACK, RFC 3262) // Possible values: // - disabled 100rel extension is disabled // - supported 100rel is supported (it is added in the supported header of // an outgoing INVITE). A far-end can now require a PRACK on a // 1xx response. // - required 100rel is required (it is put in the require header of an // outgoing INVITE). // If an incoming INVITE indicates that it supports 100rel, then // Twinkle will require a PRACK when sending a 1xx response. // - preferred Similar to required, but if a call fails because the far-end // indicates it does not support 100rel (420 response) then the // call will be re-attempted without the 100rel requirement. t_ext_support ext_100rel; // Replaces (RFC 3891) bool ext_replaces; // REFER options // Hold the current call when an incoming REFER is accepted. bool referee_hold; // Hold the current call before sending a REFER. bool referrer_hold; // Allow an incoming refer bool allow_refer; // Ask user for permission when a REFER is received. bool ask_user_to_refer; // Referrer automatically refreshes subscription before expiry. bool auto_refresh_refer_sub; // An attended transfer should use the contact-URI of the transfer target. // This contact-URI is not always globally routable however. As an // alternative the AoR (address of record) can be used. Disadvantage is // that the AoR may route to multiple phones in case of forking, whereas // the contact-URI routes to a particular phone. bool attended_refer_to_aor; // Privacy options // Send P-Preferred-Identity header in initial INVITE when hiding // user identity. bool send_p_preferred_id; // NAT // NAT traversal // You can set nat_public_ip to your public IP or FQDN if you are behind // a NAT. This will then be used inside the SIP messages instead of your // private IP. On your NAT you have to create static bindings for port 5060 // and ports 8000 - 8003 to the same ports on your private IP address. bool use_nat_public_ip; string nat_public_ip; // NAT traversal via STUN bool use_stun; t_url stun_server; // TIMERS // Noanswer timer is started when an initial INVITE is received. If // the user does not respond within the timer, then the call will be // released with a 480 Temporarily Unavailable response. unsigned short timer_noanswer; // seconds // Duration of NAT keepalive timer (s) unsigned long timer_nat_keepalive; // ADDRESS FORMAT // Telephone numbers // Display only the user-part of a URI if it is a telephone number // I.e. the user=phone parameter is present, or the user indicated // that the format of the user-part is a telephone number. bool display_useronly_phone; // Consider user-parts that consist of 0-9,+,-,*,# as a telephone // number. I.e. in outgoing messages the user=phone parameter will // be added to the URI. For incoming messages the URI will be considered // to be a telephone number regardless of the presence of the // user=phone parameter. bool numerical_user_is_phone; // Remove special symbols from numerical dial strings bool remove_special_phone_symbols; // Special symbols that must be removed from telephone numbers string special_phone_symbols; // Number conversion list number_conversions; // RING TONES string ringtone_file; string ringback_file; // SCRIPTS // Script to be called on incoming call string script_incoming_call; string script_in_call_answered; string script_in_call_failed; string script_outgoing_call; string script_out_call_answered; string script_out_call_failed; string script_local_release; string script_remote_release; // SECURITY // zrtp setting bool zrtp_enabled; // Popup warning when far-end sends goclear command bool zrtp_goclear_warning; // Send a=zrtp in SDP bool zrtp_sdp; // Only negotiate zrtp if far-end signalled support for zrtp bool zrtp_send_if_supported; // MWI // Indicate if MWI is sollicited or unsollicited. // RFC 3842 specifies that MWI must be sollicited (SUBSCRIBE). // Asterisk however only supported non-standard unsollicited MWI. bool mwi_sollicited; // User name for subscribing to the mailbox string mwi_user; // The mailbox server to which the SUBSCRIBE must be sent t_url mwi_server; // Send the SUBSCRIBE via the proxy to the mailbox server bool mwi_via_proxy; // Requested MWI subscription duration unsigned long mwi_subscription_time; // The voice mail address to call to access messages string mwi_vm_address; /** @name INSTANT MESSAGE */ //@{ /** Maximum number of simultaneous IM sessions. */ unsigned short im_max_sessions; //@} /** @name PRESENCE */ //@{ /** Requested presence subscription duration in seconds. */ unsigned long pres_subscription_time; /** Requested presence publication duration in seconds. */ unsigned long pres_publication_time; /** Publish online presence state at startup */ bool pres_publish_startup; //@} t_ext_support str2ext_support(const string &s) const; string ext_support2str(t_ext_support e) const; t_bit_rate_type str2bit_rate_type(const string &s) const; string bit_rate_type2str(t_bit_rate_type b) const; t_dtmf_transport str2dtmf_transport(const string &s) const; string dtmf_transport2str(t_dtmf_transport d) const; t_g726_packing str2g726_packing(const string &s) const; string g726_packing2str(t_g726_packing packing) const; // Parse a number conversion rule // If the rule can be parsed, then c contains the conversion rule and // true is returned. Otherwise false is returned. bool parse_num_conversion(const string &value, t_number_conversion &c); // Set a server URL. // Returns false, if the passed value is not a valid URL. bool set_server_value(t_url &server, const string &scheme, const string &value); public: t_user(); t_user(const t_user &u); t_user *copy(void) const; /** @name Getters */ //@{ string get_name(void) const; string get_domain(void) const; string get_display(bool anonymous) const; string get_organization(void) const; string get_auth_realm(void) const; string get_auth_name(void) const; string get_auth_pass(void) const; bool get_use_outbound_proxy(void) const; t_url get_outbound_proxy(void) const; bool get_all_requests_to_proxy(void) const; bool get_non_resolvable_to_proxy(void) const; bool get_use_registrar(void) const; t_url get_registrar(void) const; unsigned long get_registration_time(void) const; bool get_register_at_startup(void) const; list get_codecs(void) const; unsigned short get_ptime(void) const; bool get_out_obey_far_end_codec_pref(void) const; bool get_in_obey_far_end_codec_pref(void) const; unsigned short get_speex_nb_payload_type(void) const; unsigned short get_speex_wb_payload_type(void) const; unsigned short get_speex_uwb_payload_type(void) const; t_bit_rate_type get_speex_bit_rate_type(void) const; int get_speex_abr_nb(void) const; int get_speex_abr_wb(void) const; bool get_speex_vad(void) const; bool get_speex_dtx(void) const; bool get_speex_penh(void) const; unsigned short get_speex_complexity(void) const; unsigned short get_ilbc_payload_type(void) const; unsigned short get_ilbc_mode(void) const; unsigned short get_g726_16_payload_type(void) const; unsigned short get_g726_24_payload_type(void) const; unsigned short get_g726_32_payload_type(void) const; unsigned short get_g726_40_payload_type(void) const; t_g726_packing get_g726_packing(void) const; t_dtmf_transport get_dtmf_transport(void) const; unsigned short get_dtmf_payload_type(void) const; unsigned short get_dtmf_duration(void) const; unsigned short get_dtmf_pause(void) const; unsigned short get_dtmf_volume(void) const; t_hold_variant get_hold_variant(void) const; bool get_check_max_forwards(void) const; bool get_allow_missing_contact_reg(void) const; bool get_registration_time_in_contact(void) const; bool get_compact_headers(void) const; bool get_encode_multi_values_as_list(void) const; bool get_use_domain_in_contact(void) const; bool get_allow_sdp_change(void) const; bool get_allow_redirection(void) const; bool get_ask_user_to_redirect(void) const; unsigned short get_max_redirections(void) const; t_ext_support get_ext_100rel(void) const; bool get_ext_replaces(void) const; bool get_referee_hold(void) const; bool get_referrer_hold(void) const; bool get_allow_refer(void) const; bool get_ask_user_to_refer(void) const; bool get_auto_refresh_refer_sub(void) const; bool get_attended_refer_to_aor(void) const; bool get_send_p_preferred_id(void) const; bool get_use_nat_public_ip(void) const; string get_nat_public_ip(void) const; bool get_use_stun(void) const; t_url get_stun_server(void) const; unsigned short get_timer_noanswer(void) const; unsigned long get_timer_nat_keepalive(void) const; bool get_display_useronly_phone(void) const; bool get_numerical_user_is_phone(void) const; bool get_remove_special_phone_symbols(void) const; string get_special_phone_symbols(void) const; string get_ringtone_file(void) const; string get_ringback_file(void) const; string get_script_incoming_call(void) const; string get_script_in_call_answered(void) const; string get_script_in_call_failed(void) const; string get_script_outgoing_call(void) const; string get_script_out_call_answered(void) const; string get_script_out_call_failed(void) const; string get_script_local_release(void) const; string get_script_remote_release(void) const; list get_number_conversions(void) const; bool get_zrtp_enabled(void) const; bool get_zrtp_goclear_warning(void) const; bool get_zrtp_sdp(void) const; bool get_zrtp_send_if_supported(void) const; bool get_mwi_sollicited(void) const; string get_mwi_user(void) const; t_url get_mwi_server(void) const; bool get_mwi_via_proxy(void) const; unsigned long get_mwi_subscription_time(void) const; string get_mwi_vm_address(void) const; unsigned short get_im_max_sessions(void) const; unsigned long get_pres_subscription_time(void) const; unsigned long get_pres_publication_time(void) const; bool get_pres_publish_startup(void) const; //@} /** @name Setters */ //@{ void set_name(const string &_name); void set_domain(const string &_domain); void set_display(const string &_display); void set_organization(const string &_organization); void set_auth_realm(const string &realm); void set_auth_name(const string &name); void set_auth_pass(const string &pass); void set_use_outbound_proxy(bool b); void set_outbound_proxy(const t_url &url); void set_all_requests_to_proxy(bool b); void set_non_resolvable_to_proxy(bool b); void set_use_registrar(bool b); void set_registrar(const t_url &url); void set_registration_time(const unsigned long time); void set_register_at_startup(bool b); void set_codecs(const list &_codecs); void set_ptime(unsigned short _ptime); void set_out_obey_far_end_codec_pref(bool b); void set_in_obey_far_end_codec_pref(bool b); void set_speex_nb_payload_type(unsigned short payload_type); void set_speex_wb_payload_type(unsigned short payload_type); void set_speex_uwb_payload_type(unsigned short payload_type); void set_speex_bit_rate_type(t_bit_rate_type bit_rate_type); void set_speex_abr_nb(int abr); void set_speex_abr_wb(int abr); void set_speex_vad(bool b); void set_speex_dtx(bool b); void set_speex_penh(bool b); void set_speex_complexity(unsigned short complexity); void set_ilbc_payload_type(unsigned short payload_type); void set_g726_16_payload_type(unsigned short payload_type); void set_g726_24_payload_type(unsigned short payload_type); void set_g726_32_payload_type(unsigned short payload_type); void set_g726_40_payload_type(unsigned short payload_type); void set_g726_packing(t_g726_packing packing); void set_ilbc_mode(unsigned short mode); void set_dtmf_transport(t_dtmf_transport _dtmf_transport); void set_dtmf_payload_type(unsigned short payload_type); void set_dtmf_duration(unsigned short duration); void set_dtmf_pause(unsigned short pause); void set_dtmf_volume(unsigned short volume); void set_hold_variant(t_hold_variant _hold_variant); void set_check_max_forwards(bool b); void set_allow_missing_contact_reg(bool b); void set_registration_time_in_contact(bool b); void set_compact_headers(bool b); void set_encode_multi_values_as_list(bool b); void set_use_domain_in_contact(bool b); void set_allow_sdp_change(bool b); void set_allow_redirection(bool b); void set_ask_user_to_redirect(bool b); void set_max_redirections(unsigned short _max_redirections); void set_ext_100rel(t_ext_support ext_support); void set_ext_replaces(bool b); void set_referee_hold(bool b); void set_referrer_hold(bool b); void set_allow_refer(bool b); void set_ask_user_to_refer(bool b); void set_auto_refresh_refer_sub(bool b); void set_attended_refer_to_aor(bool b); void set_send_p_preferred_id(bool b); void set_use_nat_public_ip(bool b); void set_nat_public_ip(const string &public_ip); void set_use_stun(bool b); void set_stun_server(const t_url &url); void set_timer_noanswer(unsigned short timer); void set_timer_nat_keepalive(unsigned short timer); void set_display_useronly_phone(bool b); void set_numerical_user_is_phone(bool b); void set_remove_special_phone_symbols(bool b); void set_special_phone_symbols(const string &symbols); void set_ringtone_file(const string &file); void set_ringback_file(const string &file); void set_script_incoming_call(const string &script); void set_script_in_call_answered(const string &script); void set_script_in_call_failed(const string &script); void set_script_outgoing_call(const string &script); void set_script_out_call_answered(const string &script); void set_script_out_call_failed(const string &script); void set_script_local_release(const string &script); void set_script_remote_release(const string &script); void set_number_conversions(const list &l); void set_zrtp_enabled(bool b); void set_zrtp_goclear_warning(bool b); void set_zrtp_sdp(bool b); void set_zrtp_send_if_supported(bool b); void set_mwi_sollicited(bool b); void set_mwi_user(const string &user); void set_mwi_server(const t_url &url); void set_mwi_via_proxy(bool b); void set_mwi_subscription_time(unsigned long t); void set_mwi_vm_address(const string &address); void set_im_max_sessions(unsigned short max_sessions); void set_pres_subscription_time(unsigned long t); void set_pres_publication_time(unsigned long t); void set_pres_publish_startup(bool b); //@} // Read and parse a config file into the user object. // Returns false if it fails. error_msg is an error message that can // be given to the user. bool read_config(const string &filename, string &error_msg); // Write the settings into a config file bool write_config(const string &filename, string &error_msg); string get_filename(void) const; // Set a config file name void set_config(string _filename); // Get the name of the profile (filename without extension) string get_profile_name(void) const; // Expand file name to a fully qualified file name string expand_filename(const string &filename); // The contact name is created from the name and domain values. // Just the name value is not unique when multiple user profiles are // activated. string get_contact_name(void) const; // Returns "display " string get_display_uri(void) const; // Check if all required extensions are supported bool check_required_ext(t_request *r, list &unsupported) const; // Create user uri and contact uri string create_user_contact(bool anonymous); string create_user_uri(bool anonymous); // Convert a number by applying the number conversions. string convert_number(const string &number, const list &l) const; string convert_number(const string &number) const; // Get URI for sending a SUBSCRIBE for MWI t_url get_mwi_uri(void) const; }; #endif