####### Global Parameters ######### /* uncomment the following lines to enable debugging */ #debug_mode=yes log_level=3 xlog_level=3 syslog_enabled=yes stderror_enabled=yes log_facility=LOG_LOCAL0 udp_workers=4 open_files_limit=4096 tcp_connection_lifetime=300 tcp_connect_timeout=300 /* uncomment the next line to enable the auto temporary blacklisting of not available destinations (default disabled) */ #disable_dns_blacklist=no /* uncomment the next line to enable IPv6 lookup after IPv4 dns lookup failures (default disabled) */ #dns_try_ipv6=yes /* comment the next line to enable the auto discovery of local aliases based on reverse DNS on IPs */ auto_aliases=no /* set the server to try to locate outbound interface on multihomed host */ mhomed=1 /* Server&UA */ server_header="Server: Webitel" user_agent_header="User-Agent: Webitel" ####### Connectivity ######## socket = udp:*:5060 socket = tcp:*:5060 socket = ws:*:5070 #socket = udp:*:5062 #socket = tls:*:5061 #socket = hep_udp:127.0.0.1:6061 ####### Modules Section ######## #set module path mpath="/usr/lib/x86_64-linux-gnu/opensips/modules/" #### SIGNALING module loadmodule "signaling.so" #### StateLess module loadmodule "sl.so" #### Transaction Module loadmodule "tm.so" modparam("tm", "fr_timeout", 5) modparam("tm", "fr_inv_timeout", 90) modparam("tm", "restart_fr_on_each_reply", 0) modparam("tm", "onreply_avp_mode", 1) #### Record Route Module loadmodule "rr.so" /* do not append from tag to the RR (no need for this script) */ modparam("rr", "append_fromtag", 0) #### MAX ForWarD module loadmodule "maxfwd.so" #### SIP MSG OPerationS module loadmodule "sipmsgops.so" #### HTTPD modules loadmodule "httpd.so" modparam("httpd", "ip", "127.0.0.1") modparam("httpd", "port", 8000) #### FIFO Management Interface loadmodule "mi_http.so" loadmodule "mi_fifo.so" modparam("mi_fifo", "fifo_name", "/var/run/opensips/opensips_fifo") modparam("mi_fifo", "fifo_mode", 0666) #### Event modules loadmodule "event_stream.so" loadmodule "event_route.so" loadmodule "event_rabbitmq.so" modparam("event_rabbitmq", "heartbeat", 10) # seconds modparam("event_rabbitmq", "connect_timeout", 1000) modparam("event_rabbitmq", "use_tls", 0) #### Database module loadmodule "db_postgres.so" loadmodule "db_virtual.so" modparam("db_virtual", "db_urls", "define webitel FAILOVER") modparam("db_virtual", "db_probe_time", 10) modparam("db_virtual", "db_max_consec_retrys", 20) modparam("db_virtual", "db_urls", "postgres://opensips:webitel@localhost:5432/webitel?application_name=opensips") #### AVPOPS module loadmodule "avpops.so" modparam("avpops", "db_url", "virtual://webitel") #### USeR LOCation module loadmodule "usrloc.so" modparam("usrloc", "nat_bflag", "NAT") modparam("usrloc", "working_mode_preset", "single-instance-sql-write-through") # single-instance-sql-write-back - All changes are made to memory and database synchronization is done in the timer. modparam("usrloc", "db_url", "virtual://webitel") modparam("usrloc", "attr_column", "device_id") #### REGISTRAR module loadmodule "registrar.so" modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT") modparam("registrar", "attr_avp", "$avp(attr)") modparam("registrar", "received_avp", "$avp(received)") /* uncomment the next line not to allow more than 10 contacts per AOR */ #modparam("registrar", "max_contacts", 10) #### AUTHentication modules loadmodule "auth.so" loadmodule "auth_db.so" modparam("auth_db", "uri_uriuser_column", "user_id") modparam("auth_db", "domain_column", "realm") modparam("auth_db", "uri_domain_column", "realm") modparam("auth_db", "uri_user_column", "auth_id::text") modparam("auth_db", "user_column", "auth_id::text") modparam("auth_db", "password_column", "digest_ha1") modparam("auth_db", "calculate_ha1", 0) modparam("auth_db", "load_credentials", "") modparam("auth_db", "skip_version_check", 1) modparam("auth_db", "db_url", "virtual://webitel") #### UAC modules loadmodule "uac.so" loadmodule "uac_auth.so" loadmodule "uac_registrant.so" modparam("uac","restore_mode","none") modparam("uac_registrant", "db_url", "virtual://webitel") modparam("uac_registrant", "hash_size", 4) modparam("uac_registrant", "timer_interval", 32) #modparam("uac_registrant", "enable_clustering", 0) # [default]: 0 (off) modparam("uac_registrant", "table_name", "sip_registrant") # [default]: "registrant" #modparam("uac_registrant", "registrar_column", "registrar") # [default]: "registrar" (registrar_uri) #modparam("uac_registrant", "proxy_column", "proxy") # [default]: "proxy" (proxy_uri) #modparam("uac_registrant", "aor_column", "aor") # [default]: "aor" (to_uri) #modparam("uac_registrant", "third_party_registrant_column", "third_party_registrant") # [default]: "third_party_registrant" (from_uri) #modparam("uac_registrant", "username_column", "username") # [default]: "username" (auth_username) #modparam("uac_registrant", "password_column", "password") # [default]: "password" (auth_passowrd) #modparam("uac_registrant", "binding_URI_column", "binding_URI") # [default]: "binding_URI" (contact_uri) #modparam("uac_registrant", "binding_params_column", "binding_params") # [default]: "binding_params" (contact_params) modparam("uac_registrant", "expiry_column", "expires") # [default]: "expiry" (expires) #modparam("uac_registrant", "forced_socket_column", "forced_socket") # [default]: "forced_socket" (fs) #modparam("uac_registrant", "cluster_shtag_column", "cluster_shtag") # [default]: "cluster_shtag" (sh) modparam("uac_registrant", "state_column", "status") # [default]: "state" (0 - enabled; 1 - disabled)j #### DOMAIN module loadmodule "domain.so" modparam("domain", "db_url", "virtual://webitel") modparam("domain", "db_mode", 0) /* 1 for cache */ modparam("domain", "domain_table", "directory.wbt_domain") modparam("domain", "domain_col", "name") modparam("domain", "attrs_col", "attrs") modparam("auth_db|usrloc|uri", "use_domain", 1) #### Permissions module loadmodule "permissions.so" modparam("permissions", "db_url", "virtual://webitel") modparam("permissions", "address_table", "sip_address_allow") #### DIALOG module loadmodule "dialog.so" modparam("dialog", "rr_param", "wbt") modparam("dialog", "dlg_match_mode", 1) modparam("dialog", "default_timeout", 21600) # 6 hours timeout modparam("dialog", "db_mode", 0) # disabled DB modparam("dialog", "db_url", "virtual://webitel") modparam("dialog", "options_ping_interval", 30) modparam("dialog", "reinvite_ping_interval", 300) #### DISPATCHER module loadmodule "dispatcher.so" modparam("dispatcher", "db_url", "virtual://webitel") modparam("dispatcher", "ds_ping_method", "OPTIONS") modparam("dispatcher", "ds_probing_mode", 0) modparam("dispatcher", "ds_probing_list", "2,3") modparam("dispatcher", "ds_ping_interval", 30) #### SIP Session Timer module loadmodule "sst.so" modparam("sst", "sst_flag", "SST_FLAG") modparam("sst", "min_se", 120) #### Topology Hiding modules loadmodule "topology_hiding.so" modparam("topology_hiding", "th_callid_passwd", "webitel") modparam("topology_hiding", "th_callid_prefix", "WTL_") #### NAT modules loadmodule "nathelper.so" modparam("nathelper", "natping_tcp", 0) modparam("nathelper", "natping_interval", 30) modparam("nathelper", "ping_nated_only", 1) modparam("nathelper", "sipping_bflag", "NAT") modparam("nathelper", "sipping_method", "OPTIONS") modparam("nathelper", "sipping_from", "sip:pinger@localhost") modparam("nathelper", "remove_on_timeout_bflag", "KILL_ZOMBIES") modparam("nathelper", "max_pings_lost", 10) modparam("registrar|nathelper", "received_avp", "$avp(received)") #### RTPengine protocol loadmodule "rtpengine.so" modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:60000") #modparam("rtpengine", "db_url", "virtual://webitel") #### PIKE #loadmodule "pike.so" #modparam("pike", "sampling_time_unit", 10) #modparam("pike", "reqs_density_per_unit", 30) #modparam("pike", "remove_latency", 3600) #### ACCounting module #loadmodule "acc.so" #/* what special events should be accounted ? */ #modparam("acc", "early_media", 0) #modparam("acc", "report_cancels", 0) #/* by default we do not adjust the direct of the sequential requests. # if you enable this parameter, be sure to enable "append_fromtag" # in "rr" module */ #modparam("acc", "detect_direction", 0) #### Protocols loadmodule "proto_udp.so" loadmodule "proto_tcp.so" #loadmodule "proto_tls.so" loadmodule "proto_ws.so" #loadmodule "proto_wss.so" #modparam("proto_wss", "wss_max_msg_chunks", 16) #loadmodule "tls_openssl.so" #loadmodule "tls_wolfssl.so" #loadmodule "tls_mgm.so" #### TLS Manager # set the TLS client domain AVP #modparam("tls_mgm", "client_sip_domain_avp", "tls_sip_dom") #modparam("tls_mgm", "server_domain", "sip-pstn") #modparam("tls_mgm", "verify_cert", "[sip-pstn]0") #modparam("tls_mgm", "require_cert", "[sip-pstn]0") #modparam("tls_mgm", "match_sip_domain", "[sip-pstn]*") #modparam("tls_mgm", "match_ip_address", "[sip-pstn]*") #modparam("tls_mgm", "tls_method", "[sip-pstn]-") #modparam("tls_mgm", "ca_dir", "[sip-pstn]/etc/ssl/certs") #modparam("tls_mgm", "ca_list", "[sip-pstn]/etc/opensips/ssl/sip-pstn2/fullchain1.pem") #modparam("tls_mgm", "private_key", "[sip-pstn]/etc/opensips/ssl/sip-pstn2/privkey1.pem") #modparam("tls_mgm", "certificate", "[sip-pstn]/etc/opensips/ssl/sip-pstn2/cert1.pem") #modparam("tls_mgm", "client_domain", "sip-pstn2") #modparam("tls_mgm", "verify_cert", "[sip-pstn2]0") #modparam("tls_mgm", "require_cert", "[sip-pstn2]0") #modparam("tls_mgm", "match_sip_domain", "[sip-pstn2]*") #modparam("tls_mgm", "match_ip_address", "[sip-pstn2]*") #modparam("tls_mgm", "tls_method", "[sip-pstn2]-") #modparam("tls_mgm", "ca_dir", "[sip-pstn2]/etc/ssl/certs") #modparam("tls_mgm", "ca_list", "[sip-pstn2]/etc/opensips/ssl/sip-pstn2/fullchain1.pem") #modparam("tls_mgm", "private_key", "[sip-pstn2]/etc/opensips/ssl/sip-pstn2/privkey1.pem") #modparam("tls_mgm", "certificate", "[sip-pstn2]/etc/opensips/ssl/sip-pstn2/cert1.pem") #### HOMER #loadmodule "proto_hep.so" #modparam("proto_hep", "hep_id", "[hid]127.0.0.1:9060;transport=udp;version=3") #loadmodule "tracer.so" #modparam("tracer", "trace_id", "[tid]uri=hep:hid") ####### Routing Logic ######## # startup route logic startup_route { if (!subscribe_event("E_UL_AOR_REGISTER", "rabbitmq:webitel:webitel@localhost/exchange=opensips?sip.register")) xlog("L_ERR","cannot the RabbitMQ server subscribe to the E_UL_AOR_INSERT event\n"); if (!subscribe_event("E_UL_AOR_UNREGISTER", "rabbitmq:webitel:webitel@localhost/exchange=opensips?sip.register")) xlog("L_ERR","cannot the RabbitMQ server subscribe to the E_UL_AOR_DELETE event\n"); if (!subscribe_event("E_DEV_HOTDESK", "rabbitmq:webitel:webitel@localhost/exchange=webitel?hotdesk")) xlog("L_ERR","cannot the RabbitMQ server subscribe to the E_DEV_HOTDESK event\n"); } # from local request route logic local_route { if (is_method("BYE") && $DLG_dir=="UPSTREAM") { # rtpengine_use_set(1); rtpengine_delete(); } } # main request routing logic route{ # we match the TLS client domain using the SIP domain in the RURI #$avp(tls_sip_dom) = $rd; # some scanner mitigation # check to see if the src ip is flooding us and drop requests accordingly #if ( !is_myself("$si") && !pike_check_req() ) { exit; } # check packet for signs that it came from a scanner if( $ua=~"^sipvicious" || $ua=~"^freindly-scanner" || $ua=~"^friendly-scanner" || $ua=~"^VaxSip" || $ua=~"^sipcli" ) { xlog("L_NOTICE","Auth error for $ua from $si (scanners) cause -1"); exit; } # kill any requests that we do not handle if (!is_method("UPDATE|PRACK|SUBSCRIBE|NOTIFY|REGISTER|INVITE|ACK|BYE| CANCEL|REFER|OPTIONS|INFO|MESSAGE")) { sl_send_reply(405,"Method Not Allowed"); exit; } if (!mf_process_maxfwd_header(10)) { send_reply(483,"Too Many Hops"); exit; } # initial NAT handling; detect if the request comes from behind a NAT # and apply contact fixing if (nat_uac_test("diff-port-src-via,diff-ip-src-via")) { if (!nat_uac_test("diff-ip-src-via") && $(hdr(Via){via.port}) < 5099) xlog("L_DBG", "SCRIPT:DBG NOT forcing rport. Via port is $(hdr(Via){via.port})\n"); else force_rport(); } if (nat_uac_test("diff-port-src-via,private-via,diff-ip-src-via,private-contact")) { if (is_method("REGISTER")) { fix_nated_register(); setbflag("NAT"); } else if ($socket_in(proto) == "ws" || $socket_in(proto) == "wss") { # consider the WS client is behind NAT - always fix the contact fix_nated_contact(); setflag("NAT"); } else { # fix_nated_contact(); # setflag("NAT"); } } if (!mf_process_maxfwd_header(10)) { send_reply(483,"Too Many Hops"); exit; } # SIP to HOMER # route(to_homer); # $var(trace_id) = "tid"; if (has_totag()) { if (topology_hiding_match()) { route(relay); exit; } # preloaded route checking if (loose_route()) { if ( is_method("ACK") ) { if ( t_check_trans() ) { t_relay(); exit; } else exit; } route(relay); exit; } # sequential request within a dialog should # take the path determined by record-routing if ( !loose_route() ) { # we do record-routing for all our traffic, so we should not # receive any sequential requests without Route hdr. send_reply(404,"Not here"); exit; } # validate the sequential request against dialog if ( $DLG_status!=NULL && !validate_dialog() ) { # exit; } } # CANCEL processing if (is_method("CANCEL")) { # rtpengine_use_set(1); rtpengine_delete(); if (t_check_trans()) t_relay(); exit; } # OPTIONS processing if( is_method("OPTIONS")) route(handle_options); if (is_method("PUBLISH|SUBSCRIBE")) { send_reply(503, "Service Unavailable"); exit; } # absorb retransmissions, but do not create transaction t_check_trans(); if (is_method("REGISTER")) route(is_register); if ( !(is_method("REGISTER") ) ) route(is_not_register); # preloaded route checking ?? check it if (loose_route()) { xlog("L_ERR", "Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]"); if (!is_method("ACK")) send_reply(403,"Preload Route denied"); exit; } # record routing if (!is_method("REGISTER|MESSAGE")) record_route(); # create dialog on INVITEs if (is_method("INVITE")) { # create dialog with timeout if ( !create_dialog("B") ) { send_reply(500,"Internal Server Error"); exit; } # account only INVITEs # do_accounting("log"); } if ($rU==NULL) { # request with no Username in RURI send_reply(484,"Address Incomplete"); exit; } # do all webitel staff route(check_src_and_dest); # ?? ckeck it if (isbflagset("NAT")) setflag("NAT"); # when routing via usrloc, log the missed calls also # do_accounting("log","missed"); route(relay); } route[relay] { # Detect if UAC is websockets client and set flag for later processing if ($socket_in(proto) == "ws" || $socket_in(proto) == "wss") setflag("SRC_WS"); if(is_method("INVITE") || is_method("UPDATE") || is_method("ACK") || is_method("BYE")) { t_check_trans(); if (check_route_param("nat=yes")) setflag("NAT"); if (check_route_param("ws=yes")) setbflag("DST_WS"); } # for INVITEs enable some additional helper routes if (is_method("INVITE") || is_method("UPDATE")) { t_on_branch("per_branch_ops"); t_on_reply("handle_reply"); t_on_failure("call_failure"); } if (is_method("BYE")) { # rtpengine_use_set(1); rtpengine_delete(); } if (isflagset("NAT")) add_rr_param(";nat=yes"); if (isflagset("SRC_WS")) add_rr_param(";ws=yes"); if(!has_totag() && is_method("INVITE")) { if (is_present_hf("X-FS-Support")) setflag("FS"); topology_hiding("UC"); } if (!t_relay()) { send_reply(500,"Internal Server Error"); } exit; } branch_route[per_branch_ops] { # Detect if UAC is websockets client and set flag for later processing xlog("L_DBG","SCRIPT:DBG BRANCH $T_branch_idx, $oP request $ru contact(s) $ct\n$cs\n $rm: message flags: $mf\n branch flags: $bf\n"); if ($socket_out(proto) == "ws" || $socket_out(proto) == "wss") setbflag("DST_WS"); if ($socket_in(proto) == "ws" || $socket_in(proto) == "wss") setflag("SRC_WS"); resetbflag("sdp_offer"); if ( (is_method("INVITE") || is_method("UPDATE") || is_method("ACK") || is_method("PRACK")) && has_body("application/sdp") ) { if (isbflagset("FS")) # - to FS $var(rtpengine_flags) = "trust-address replace-origin replace-session-connection rtcp-mux-demux ICE=remove RTP/AVP"; else if (isflagset("SRC_WS") && isbflagset("DST_WS")) # - Web to web $var(rtpengine_flags) = "trust-address replace-origin replace-session-connection SDES-off ICE=force"; else if (isflagset("SRC_WS") && !isbflagset("DST_WS")) # - Web to SIP $var(rtpengine_flags) = "trust-address replace-origin replace-session-connection rtcp-mux-demux ICE=remove RTP/AVP"; else if (!isflagset("SRC_WS") && isbflagset("DST_WS")) # - SIP to web $var(rtpengine_flags) = "replace-origin replace-session-connection rtcp-mux-require strict-source ICE=force SDES-off UDP/TLS/RTP/SAVP"; else if (!isflagset("SRC_WS") && !isbflagset("DST_WS")) # - SIP to SIP $var(rtpengine_flags) = "trust-address replace-origin replace-session-connection rtcp-mux-demux ICE=remove RTP/AVP"; ####################### # if (isflagset("vlan")) # $var(rtpengine_flags) = $var(rtpengine_flags) + " in-iface=vlan out-iface=in"; # else if (isbflagset("vlan")) # $var(rtpengine_flags) = $var(rtpengine_flags) + " in-iface=in out-iface=vlan"; # else if (isflagset("FS")) # $var(rtpengine_flags) = $var(rtpengine_flags) + " in-iface=in out-iface=ex"; # else if (isbflagset("FS")) # $var(rtpengine_flags) = $var(rtpengine_flags) + " in-iface=ex out-iface=in"; # else # $var(rtpengine_flags) = $var(rtpengine_flags) + " in-iface=ex out-iface=ex"; ####################### # Codecs if (isflagset("PSTN") || isbflagset("PSTN")) $var(rtpengine_flags) = $var(rtpengine_flags) + " codec-strip-speex codec-strip-gsm codec-strip-iLBC transcode-PCMA"; else $var(rtpengine_flags) = $var(rtpengine_flags) + " codec-strip-speex codec-strip-gsm codec-strip-iLBC codec-mask-opus codec-mask-G722 codec-mask-PCMA transcode-opus transcode-G722 transcode-PCMA"; xlog("L_DBG","SCRIPT:DBG $var(reply_log) $cs: $rs: rtpengine $var(rtpengine_flags)\n"); # rtpengine_use_set(1); rtpengine_manage("$var(rtpengine_flags)"); } } onreply_route[handle_reply] { # Detect if UAC is websockets client and set flag for later processing xlog("L_DBG","SCRIPT:DBG $var(reply_log) $cs: $rs: response\nmessage flags: $mf\nbranch flags: $bf\n"); if (isflagset("SRC_WS") || isbflagset("DST_WS") || isflagset("NAT")) fix_nated_contact(); # rtp proxying for responses if ( has_body("application/sdp") ) { if (isflagset("FS") && isbflagset("DST_WS")) $var(rtpengine_flags) = "trust-address replace-origin replace-session-connection ICE=remove RTP/AVP"; else if (isflagset("SRC_WS") && isbflagset("DST_WS")) $var(rtpengine_flags) = "trust-address replace-origin replace-session-connection SDES-off ICE=force"; else if (isflagset("SRC_WS") && !isbflagset("DST_WS")) $var(rtpengine_flags) = "replace-origin replace-session-connection rtcp-mux-require strict-source ICE=force SDES-off RTP/SAVP"; else if (isflagset("FS")) $var(rtpengine_flags) = "trust-address replace-origin replace-session-connection rtcp-mux-demux ICE=remove RTP/AVP"; else $var(rtpengine_flags) = "trust-address replace-origin replace-session-connection rtcp-mux-demux ICE=remove RTP/AVP"; ####################### # if (isbflagset("vlan")) # $var(rtpengine_flags) = $var(rtpengine_flags) + " in-iface=vlan out-iface=in"; # else if (isflagset("vlan")) # $var(rtpengine_flags) = $var(rtpengine_flags) + " in-iface=in out-iface=vlan"; # else if (isbflagset("FS")) # $var(rtpengine_flags) = $var(rtpengine_flags) + " in-iface=in out-iface=ex"; # else if (isflagset("FS")) # $var(rtpengine_flags) = $var(rtpengine_flags) + " in-iface=ex out-iface=in"; # else # $var(rtpengine_flags) = $var(rtpengine_flags) + " in-iface=ex out-iface=ex"; ####################### xlog("L_DBG","SCRIPT:DBG $var(reply_log) $cs: $rs: rtpengine $var(rtpengine_flags)\n"); # rtpengine_use_set(1); rtpengine_manage("$var(rtpengine_flags)"); } } failure_route[gw_failover] { # rtpengine_use_set(1); if (t_was_cancelled()) { rtpengine_delete(); exit; } # failure detection with redirect to next available trunk if (t_check_status("(408)|([56][0-9][0-9])")) { xlog("L_DBG","SCRIPT:DBG Failed trunk $rd/$du detected \n"); t_on_failure("gw_failover"); t_relay(); exit; } rtpengine_delete(); send_reply(500,"No Destination available"); } failure_route[call_failure] { # rtpengine_use_set(1); # if (t_was_cancelled()) { rtpengine_delete(); exit; # } # uncomment the following lines if you want to block client # redirect based on 3xx replies. # if (t_check_status("3[0-9][0-9]")) { # t_reply(404,"Not found"); # exit; # } } event_route[E_UL_AOR_INSERT] { # [USRLOC] This event is raised when a new AOR is inserted in the USRLOC memory cache. $avp(attrs) = "aor"; $avp(vals) = $param(aor); # The AOR of the inserted record. # $avp(attrs) = "tsec"; # $avp(vals) = $Ts; # get_timestamp($avp(sec), $avp(usec)); $avp(attrs) = "tsec"; $avp(attrs) = "usec"; # guess this will push two sequential $avp(vals) values get_timestamp($avp(vals), $avp(vals)); if (!raise_event("E_UL_AOR_REGISTER", $avp(attrs), $avp(vals))) xlog("L_ERR", "failed to raise E_UL_AOR_INSERT event\n"); exit; } event_route[E_UL_AOR_DELETE] { # [USRLOC] this event is raised when a new AOR is deleted from the USRLOC memory cache. $avp(attrs) = "aor"; $avp(vals) = $param(aor); # The AOR of the inserted record. $avp(attrs) = "tsec"; $avp(attrs) = "usec"; # guess this will push two sequential $avp(vals) values get_timestamp($avp(vals), $avp(vals)); if (!raise_event("E_UL_AOR_UNREGISTER", $avp(attrs), $avp(vals))) xlog("L_ERR", "failed to raise E_UL_AOR_DELETE event\n"); exit; } # All other routes route[handle_options] { send_reply(200, "I See You"); exit; } route[is_register] { # authenticate the REGISTER requests $var(auth_code) = www_authorize("", "sip_subscriber"); if ( $var(auth_code) == -1 || $var(auth_code) == -2 ) xlog("L_NOTICE","Auth error for $fU@$fd from $si ($ua) cause $var(auth_code)"); if ( $var(auth_code) < 0 ) { www_challenge("", "auth,auth-int"); exit; } if (!db_is_to_authorized("sip_subscriber")) { xlog("L_DBG","SCRIPT:DBG Webitel user $tu is not authorized to authenticate with $au credential\n"); send_reply(403,"Forbidden auth ID"); exit; } setbflag("KILL_ZOMBIES"); /* for cluster: disable on the secondary: nh_enable_ping */ if ($socket_in(proto) == "ws" || $socket_in(proto) == "wss") { setbflag("DST_WS"); fix_nated_register(); } if ($socket_in(proto) == "tcp" || $socket_in(proto) == "tls") setflag("TCP_PERSISTENT"); avp_db_query("SELECT dc, oid::text, uid FROM sip_subscriber WHERE realm = '$td' AND user_id = '$tU' AND auth_id = '$au' LIMIT 1", "$avp(pdc);$avp(cid);$avp(uid)"); $avp(attr) = $avp(cid); if (!save("location")) sl_reply_error(); exit; } route[is_not_register] { ########## # From mediaserver if ( ds_is_in_list("$si", $sp, 1) ) { setflag("FS"); # Trunk from host if ($(hdr(X-Webitel-Gateway-Id){s.int})) { # route(check_limits,$(hdr(X-Webitel-Domain-Id){s.int})); setbflag("PSTN"); avp_db_query("SELECT host FROM directory.sip_gateway WHERE register is false AND id='$(hdr(X-Webitel-Gateway-Id){s.int})' LIMIT 1", "$avp(fd)"); if ($avp(fd)) { $var(fromuri)='sip:'+$fU+'@'+$avp(fd); uac_replace_from("", $var(fromuri)); } else { uac_replace_from("", ""); } # if ($(hdr(X-Webitel-Gateway-Id){s.int})==2) { # setbflag("vlan"); # } } ########## # WEBCALL # } else if (is_method("INVITE") && $rU=="call-from-web") { # avp_db_query("select b.dc as domain_id, b.name, ((((metadata->>'call')::jsonb)->>'flow')::jsonb->>'id')::int flow_id from chat.bot b where b.uri = '/$fU' and (((b.metadata->>'call')::jsonb)->>'enabled')::bool limit 1;", "$avp(dc);$avp(cname);$avp(sid)"); # if ( $avp(sid) > 0 ) { # xlog("L_NOTICE", "SCRIPT:DBG Web '$avp(cname)': WebCall\n"); # append_hf("X-Webitel-Domain-Id: $avp(dc)\r\n"); # append_hf("X-Webitel-Schema-Id: $avp(sid)\r\n"); # append_hf("X-Webitel-Direction: inbound\r\n"); # uac_replace_from($avp(cname),""); # } else { # xlog("L_NOTICE","Auth error for $fU@$fd from $si (relay) cause -2"); # exit; # } # WEBCALL ########## # from user } else if (is_from_local()) { # authenticate if from local subscriber # authenticate all initial non-REGISTER request that pretend to be # generated by local subscriber (domain from FROM URI is local) ########## # PORTAL USERS # if ($socket_in(port)=="5062") { # # xlog("L_NOTICE","SCRIPT: Webitel user port 5062\n"); # setflag("NAT"); # force_rport(); # fix_nated_contact(); # set_advertised_address("1.1.1.1"); # # if (!proxy_authorize("", "portal.sip_subscriber")) { # proxy_challenge("", "auth"); # exit; # } # if (!db_is_from_authorized("portal.sip_subscriber")) { # send_reply(403,"Forbidden auth ID"); # exit; # } # } else { if (!proxy_authorize("", "sip_subscriber")) { proxy_challenge("", "auth"); exit; } if (!db_is_from_authorized("sip_subscriber")) { send_reply(403,"Forbidden auth ID"); exit; } ########## # } # PORTAL USERS consume_credentials(); # caller authenticated xlog("L_DBG", "SCRIPT:DBG Caller is authenticated\n"); # Auth hotdesk device with extension if (is_method("INVITE")) { $var(dnum) = $rU; if ($(var(dnum){s.substr,0,4})=="*11*") { lookup("location", "method-filtering", $fu); xlog("L_DBG", "SCRIPT:DBG HOTDESK '$var(dnum)': dev is $avp(attr) and ext is $(var(dnum){s.substr,4,0})\n"); $avp(attrs) = "id"; $avp(vals) = $avp(attr); if ($(var(dnum){s.substr,4,0})) { $avp(attrs) = "auth"; $avp(vals) = $(var(dnum){s.substr,4,0}); } if (!raise_event("E_DEV_HOTDESK", $avp(attrs), $avp(vals))) xlog("L_ERR", "cannot raise E_DEV_HOTDESK event\n"); send_reply(402,"Webitel hotdesk"); exit; } } # Find user by device avp_db_query("SELECT case when exists(select 1 from call_center.cc_member_attempt aa inner join call_center.cc_agent a on a.id = aa.agent_id where aa.channel = 'call' and a.user_id = uid::int8 and aa.leaving_at isnull and aa.state in ('waiting_agent', 'idle', 'offering') ) then '-1' else uid end, dc, extension::varchar, caller_id_name FROM public.sip_subscriber WHERE realm = '$fd' AND user_id='$fU' LIMIT 1", "$avp(uid);$avp(dc);$avp(ext);$avp(cnam)"); if ($avp(uid) >0) { # The otbound call from the user setflag("DEV"); $var(fromuri)='sip:'+$avp(ext)+'@'+$fd; uac_replace_from($avp(cnam),$var(fromuri)); append_hf("X-Webitel-Uuid: $ci\r\n"); append_hf("X-Webitel-User-Id: $avp(uid)\r\n"); append_hf("X-Webitel-Domain-Id: $avp(dc)\r\n"); append_hf("X-Webitel-Direction: outbound\r\n"); append_hf("X-Webitel-Origin: user\r\n"); } else if ($avp(uid) <0) { # Not allowed manual outbound calls send_reply(606,"Not Acceptable"); exit; } else { ########## # PORTAL USERS # if ($socket_in(port)=="5062") { # avp_db_query("SELECT dc,schema_id,caller_id_name,contact_id FROM portal.sip_subscriber WHERE realm = '$fd' AND user_id='$fU' LIMIT 1", "$avp(dc);$avp(schid);$avp(cnam);$avp(cid)"); # uac_replace_from($avp(cnam),""); # append_hf("X-Webitel-Domain-Id: $avp(dc)\r\n"); # append_hf("X-Webitel-Schema-Id: $avp(schid)\r\n"); # append_hf("X-Webitel-Direction: inbound\r\n"); # } else { # Not allowed hotdesk device send_reply(403,"Forbidden hotdesk"); exit; # PORTAL USERS # } ########## } ########## # from PSTN } else { avp_db_query("select uac.id, uac.name, uac.dc from sip_registrant uac where uac.binding_uri like 'sip:$rU@$rd%' and uac.reg_state = 3 order by uac.id limit 1;", "$avp(id);$avp(name);$avp(dc)"); if ( $avp(id) > 0 ) { # From Gateway # route(check_limits,$avp(dc)); setflag("PSTN"); append_hf("X-Webitel-Domain-Id: $avp(dc)\r\n"); append_hf("X-Webitel-Gateway-Id: $avp(id)\r\n"); append_hf("X-Webitel-Gateway: $avp(name)\r\n"); append_hf("X-Webitel-Direction: inbound\r\n"); append_hf("X-Webitel-Origin: gateway\r\n"); } else if (check_address(1,"$si",$sp,"$socket_in(proto)")) { avp_db_query("select uas.id, uas.name, uas.dc from sip_address_allow uas where uas.host = ('$td'||':'||'$socket_in(port)') and ('$si')::inet <<= uas.cidr and coalesce(nullif(port, 0), $sp) = $sp and coalesce(nullif(proto, 'any'), '$socket_in(proto)') = '$socket_in(proto)' order by uas.id limit 1;", "$avp(id);$avp(name);$avp(dc)"); if ( $avp(id) > 0 ) { # From SIP Trunk # route(check_limits,$avp(dc)); setflag("PSTN"); append_hf("X-Webitel-Domain-Id: $avp(dc)\r\n"); append_hf("X-Webitel-Gateway-Id: $avp(id)\r\n"); append_hf("X-Webitel-Gateway: $avp(name)\r\n"); append_hf("X-Webitel-Direction: inbound\r\n"); append_hf("X-Webitel-Origin: gateway\r\n"); # if ($avp(id)==2) { # setflag("vlan"); # } # From unknown host } else { send_reply(403,"Forbidden auth host"); xlog("L_NOTICE","Auth error for $fU@$fd from $si (host) cause -1"); exit; } # From unknown IP } else { send_reply(403,"Relay Forbidden"); xlog("L_NOTICE","Auth error for $fU@$fd from $si (relay) cause -2"); exit; } } } route[check_src_and_dest] { # Inbound from PSTN if (isflagset("PSTN")) { t_on_failure("gw_failover"); setbflag("FS"); if ( !ds_select_dst(1,4) ) { send_reply(500,"No Destination available"); exit; } # Outbound call } else if ($(hdr(X-Webitel-Direction)[0]) == "outbound") { if (is_present_hf("X-Webitel-Domain")) remove_hf("X-Webitel-Domain"); if (is_present_hf("X-Webitel-Display-Direction")) remove_hf("X-Webitel-Display-Direction"); if (is_present_hf("X-Webitel-Direction")) remove_hf("X-Webitel-Direction"); if (is_present_hf("X-Webitel-Domain-Id")) remove_hf("X-Webitel-Domain-Id"); if (is_present_hf("X-Webitel-Gateway-Id")) remove_hf("X-Webitel-Gateway-Id"); if (is_present_hf("X-Webitel-User-Id")) remove_hf("X-Webitel-User-Id"); if (is_present_hf("X-Webitel-Origin")) remove_hf("X-Webitel-Origin"); if (is_present_hf("X-FS-Support")) remove_hf("X-FS-Support"); # Internal to user } else if ($(hdr(X-Webitel-Direction)[0]) == "internal") { if (is_present_hf("X-Webitel-Uuid")) remove_hf("X-Webitel-Uuid"); append_hf("X-Webitel-Uuid: $ci\r\n"); # HotDesking avp_db_query("select hd.id, hd.account::varchar from directory.wbt_device as hd join directory.wbt_domain as ns using(dc) join directory.wbt_user as ua on ua.id = hd.user_id where hd.hotdesk and coalesce(ua.extension, ua.username) = '$tU' and ns.name = '$td' order by logged_in desc limit 1", "$avp(id);$avp(account)"); # do lookup with method filtering if ( $avp(id) > 0 ) { xlog("L_DBG", "SCRIPT:DBG Webitel user has hotdesk device: $avp(id) - $avp(account)\n"); lookup("location", "method-filtering", "sip:$avp(account)@$td"); } else { lookup("location","method-filtering"); } if ($retcode < 0 ) { send_reply(480,"Subscriber absent"); exit; } } else { setbflag("FS"); t_on_failure("gw_failover"); if (!ds_select_dst(1,4) ) { send_reply(500,"No Destination available"); exit; } } } route[check_limits] { # Check outbound channels limit avp_db_query("select count(*) as channels from call_center.cc_calls cc where cc.domain_id = $param(1)::int8 and cc.gateway_id notnull", "$avp(channels)"); xlog("L_DBG", "SCRIPT:DBG Domain $param(1) has $avp(channels) channels\n"); # if ($avp(channels) >50) { # send_reply(409,"Not enough channels"); # exit; # } } #route[to_homer] { # xlog("L_DBG", "SCRIPT:DBG: sending message out to Homer\n"); # see declaration of tid in trace_id section # $var(trace_id) = "tid"; # $var(trace_type) = NULL; # if (!has_totag()) { # if (is_method("INVITE")) # $var(trace_type) = "dialog"; # else if (!is_method("CANCEL")) # $var(trace_type) = "transaction"; # } else if (is_method("SUBSCRIBE|NOTIFY")) { # $var(trace_type) = "transaction"; # } else { # $var(trace_type) = NULL; # } # do trace here # switch ($var(trace_type)) { # case "dialog": # trace("$var(trace_id)", "d", "sip|xlog"); # break; # case "transaction": # trace("$var(trace_id)", "t", "sip|xlog"); # break; # case "message": # trace("$var(trace_id)", "m", "sip|xlog"); # break; # } #}