Hi,
I am trying to learn Kamailio to set up a SIP/RTP proxy for WebRTC with
FreeSWITCH, and I wanted to use this configuration file template as a
starting point.
(Source:
https://github.com/havfo/WEBRTC-to-SIP)
But i have the error : *ERROR: [core/ppcfg.c:275]:
pp_ifdef_level_error(): different number of preprocessor directives: 1
more #!if[n]def as #!endif*
I don't understand because I checked and everything seems okay with the
if/endif statements to me.
|# grep '#!ifndef' kamailio.cfg | wc -l 2 # grep '#!ifdef' kamailio.cfg
| wc -l 49 # grep '#!endif' kamailio.cfg | wc -l 51 |
And it's ok for chat gpt too :
|#!ifdef : 49 occurrences #!ifndef : 2 occurrences Total (#!ifdef and
#!ifndef) : 51 occurrences #!endif : 51 occurrences |
Is there a problem with the parser or a compatibility problem (i am on*5.6.3*) ?
|#!KAMAILIO # #!define WITH_MYSQL #!define WITH_AUTH #!define
WITH_USRLOCDB #!define WITH_TLS #!define WITH_HOMER #!define
WITH_WEBSOCKETS #!define WITH_ANTIFLOOD #!define WITH_IPV6 ##!define
WITH_BRIDGE_ON_FAIL #!define WITH_LOCALHOST_WS ##!define
WITH_LOCALHOST_SIP #!substdef "!MY_SIP_PORT!5060!g" #!substdef
"!MY_SIPS_PORT!5061!g" #!substdef "!MY_WS_PORT!8080!g" #!substdef
"!MY_WSS_PORT!4443!g" #!substdef "!MY_IP4_ADDR!XXXXX-XXXXX!g"
#!substdef
"!IP4_LOCALHOST!127.0.0.1!g" #!substdef
"!MY_WS4_ADDR!tcp:MY_IP4_ADDR:MY_WS_PORT!g" #!substdef
"!MY_WSS4_ADDR!tls:MY_IP4_ADDR:MY_WSS_PORT!g" #!substdef
"!LOCALHOST_WS4_ADDR!tcp:IP4_LOCALHOST:MY_WS_PORT!g" #!substdef
"!LOCALHOST_WSS4_ADDR!tls:IP4_LOCALHOST:MY_WSS_PORT!g" #!ifdef WITH_IPV6
#!substdef "!MY_IP6_ADDR![XXXXXX-XXXXXX]!g" #!substdef
"!IP6_LOCALHOST![::1]!g" #!substdef
"!MY_WS6_ADDR!tcp:MY_IP6_ADDR:MY_WS_PORT!g" #!substdef
"!MY_WSS6_ADDR!tls:MY_IP6_ADDR:MY_WSS_PORT!g" #!substdef
"!LOCALHOST_WS6_ADDR!tcp:IP6_LOCALHOST:MY_WS_PORT!g" #!substdef
"!LOCALHOST_WSS6_ADDR!tls:IP6_LOCALHOST:MY_WSS_PORT!g" #!endif
#!substdef "!MY_DOMAIN!XXXX-XXXX!g" # *** Value defines - IDs used later
in config #!ifdef WITH_MYSQL # - database URL - used to connect to
database server by modules such # as: auth_db, acc, usrloc, a.s.o.
#!ifndef DBURL #!define DBURL
"mysql://kamailio:kamailiorw@localhost/kamailio" #!endif #!endif # -
flags # FLT_ - per transaction (message) flags # FLB_ - per branch flags
#!define FLT_NATS 5 #!define FLB_NATB 6 #!define FLB_NATSIPPING 7
#!define FLB_RTPWS 8 #!define FLB_IPV6 9 #!define FLB_V4V6 10 #!define
FLB_BRIDGE 11 ####### Global Parameters ######### ### LOG Levels: 3=DBG,
2=INFO, 1=NOTICE, 0=WARN, -1=ERR #!ifdef WITH_DEBUG debug=4
log_stderror=no #!else debug=2 log_stderror=no #!endif memdbg=5 memlog=5
log_facility=LOG_LOCAL0 fork=yes children=4 port=MY_SIP_PORT
tls_port_no=MY_SIPS_PORT #!ifdef WITH_TLS enable_tls=yes #!endif
listen=MY_IP4_ADDR #!ifdef WITH_LOCALHOST_SIP listen=IP4_LOCALHOST
#!endif #!ifdef WITH_IPV6 listen=MY_IP6_ADDR #!ifdef WITH_LOCALHOST_SIP
listen=IP6_LOCALHOST #!endif #!endif #!ifdef WITH_WEBSOCKETS
listen=MY_WS4_ADDR #!ifdef WITH_LOCALHOST_WS listen=LOCALHOST_WS4_ADDR
#!endif #!ifdef WITH_IPV6 listen=MY_WS6_ADDR #!ifdef WITH_LOCALHOST_WS
listen=LOCALHOST_WS6_ADDR #!endif #!endif #!ifdef WITH_TLS
listen=MY_WSS4_ADDR #!ifdef WITH_LOCALHOST_WS listen=LOCALHOST_WSS4_ADDR
#!endif #!ifdef WITH_IPV6 listen=MY_WSS6_ADDR #!ifdef WITH_LOCALHOST_WS
listen=LOCALHOST_WSS6_ADDR #!endif #!endif #!endif #!endif use_dns_cache
= on # Use KAMAILIO internal DNS cache use_dns_failover = on # Depends
on KAMAILIO internal DNS cache dns_srv_loadbalancing = on #
dns_try_naptr = on # dns_retr_time=1 # Time in seconds before retrying a
DNS request dns_retr_no=3 # Number of DNS retransmissions before giving
up # Set protocol preference order - ignore target priority
dns_naptr_ignore_rfc= yes # Ignore target NAPTR priority dns_tls_pref=50
# First priority: TLS dns_tcp_pref=30 # Second priority: TCP
dns_udp_pref=10 # Third priority: UDP tcp_connection_lifetime=3604
tcp_accept_no_cl=yes tcp_rd_buf_size=16384 # set paths to location of
modules (to sources or installation folders) #!ifdef WITH_SRCPATH
mpath="modules/" #!else
mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/" #!endif #!ifdef
WITH_MYSQL loadmodule "db_mysql.so" #!endif loadmodule "kex.so"
loadmodule "corex.so" loadmodule "tm.so" loadmodule "tmx.so"
loadmodule
"sl.so" loadmodule "rr.so" loadmodule "pv.so" loadmodule
"maxfwd.so"
loadmodule "usrloc.so" loadmodule "registrar.so" loadmodule
"textops.so"
loadmodule "siputils.so" loadmodule "xlog.so" loadmodule
"sanity.so"
loadmodule "ctl.so" loadmodule "cfg_rpc.so" loadmodule
"sdpops.so"
loadmodule "textopsx.so" #!ifdef WITH_AUTH loadmodule "auth.so"
loadmodule "auth_db.so" #!ifdef WITH_IPAUTH loadmodule
"permissions.so"
#!endif #!endif #!ifdef WITH_PRESENCE loadmodule "presence.so"
loadmodule "presence_xml.so" #!endif #!ifdef WITH_TLS loadmodule
"tls.so" #!endif #!ifdef WITH_HOMER loadmodule "siptrace.so" #!endif
#!ifdef WITH_WEBSOCKETS loadmodule "xhttp.so" loadmodule
"websocket.so"
loadmodule "nathelper.so" loadmodule "rtpengine.so" #!endif #!ifdef
WITH_ANTIFLOOD loadmodule "htable.so" loadmodule "pike.so" #!endif
#!ifdef WITH_DEBUG loadmodule "debugger.so" #!endif # -----------------
setting module-specific parameters --------------- # ----- rr params
----- # add value to ;lr param to cope with most of the UAs
modparam("rr", "enable_full_lr", 1) # do not append from tag to the RR
(no need for this script) modparam("rr", "append_fromtag", 0) # -----
registrar params ----- modparam("registrar", "method_filtering", 1) #
max value for expires of registrations modparam("registrar",
"max_expires", 3600) # ----- usrloc params ----- /* enable DB
persistency for location entries */ #!ifdef WITH_USRLOCDB
modparam("usrloc", "db_url", DBURL) modparam("usrloc",
"db_mode", 2)
#!endif # ----- auth_db params ----- #!ifdef WITH_AUTH
modparam("auth_db", "db_url", DBURL) modparam("auth_db",
"calculate_ha1", 1) modparam("auth_db", "password_column",
"password")
modparam("auth_db", "load_credentials", "") #!endif #!ifdef
WITH_PRESENCE # ----- presence params ----- modparam("presence",
"db_url", DBURL) # ----- presence_xml params -----
modparam("presence_xml", "db_url", DBURL)
modparam("presence_xml",
"force_active", 1) #!endif ##!ifdef WITH_NAT # ----- rtpproxy params
----- modparam("rtpengine", "rtpengine_sock",
"udp:127.0.0.1:22222")
modparam("rtpengine", "extra_id_pv", "$avp(extra_id)") #
----- nathelper
params ----- modparam("nathelper", "natping_interval", 30)
modparam("nathelper", "ping_nated_only", 1)
modparam("nathelper",
"sipping_bflag", FLB_NATSIPPING) modparam("nathelper",
"sipping_from",
"sip:pinger@XXXX-XXXX") modparam("nathelper|registrar",
"received_avp",
"$avp(RECEIVED)") modparam("usrloc", "nat_bflag", FLB_NATB)
##!endif #
----- corex params ----- modparam("corex", "alias_subdomains",
"MY_DOMAIN") #!ifdef WITH_TLS # ----- tls params ----- modparam("tls",
"config", "/etc/kamailio/tls.cfg") modparam("tls",
"tls_force_run", 1)
#!endif #!ifdef WITH_WEBSOCKETS modparam("nathelper|registrar",
"received_avp", "$avp(RECEIVED)") #!endif #!ifdef WITH_HOMER #Siptrace
modparam("siptrace", "duplicate_uri", "sip:127.0.0.1:9060")
modparam("siptrace", "hep_mode_on", 1) modparam("siptrace",
"trace_to_database", 0) modparam("siptrace", "trace_flag",
22)
modparam("siptrace", "trace_on", 1) #!endif #!ifdef WITH_ANTIFLOOD #
----- pike params ----- modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 16)
modparam("pike",
"remove_latency", 4) # ----- htable params ----- # ip ban htable with
autoexpire after 5 minutes modparam("htable", "htable",
"ipban=>size=8;autoexpire=300;") #!endif #!ifdef WITH_DEBUG # -----
debugger params ----- modparam("debugger", "cfgtrace", 1) #!endif
####### Routing Logic ######## request_route { #!ifdef WITH_HOMER #
start duplicate the SIP message here sip_trace(); setflag(22); #!endif #
per request initial checks route(REQINIT); xlog("L_INFO", "START: $rm
from $fu (IP:$si:$sp)\n"); #!ifdef WITH_WEBSOCKETS if (nat_uac_test(64))
{ # Do NAT traversal stuff for requests from a WebSocket # connection -
even if it is not behind a NAT! # This won't be needed in the future if
Kamailio and the # WebSocket client support Outbound and Path.
force_rport(); if (is_method("REGISTER")) { fix_nated_register(); } else
if (!add_contact_alias()) { xlog("L_ERR", "Error aliasing contact
<$ct>\n"); sl_send_reply("400", "Bad Request"); exit; } }
#!endif # NAT
detection route(NATDETECT); # CANCEL processing if (is_method("CANCEL"))
{ if (t_check_trans()) { route(RELAY); } exit; } # handle requests
within SIP dialogs route(WITHINDLG); ### only initial requests (no To
tag) t_check_trans(); # authentication route(AUTH); # record routing for
dialog forming requests (in case they are routed) # - remove preloaded
route headers remove_hf("Route"); if (is_method("INVITE|SUBSCRIBE")) {
record_route(); } # dispatch requests to foreign domains route(SIPOUT);
### requests for my local domains # handle presence related requests
route(PRESENCE); # handle registrations route(REGISTRAR); if ($rU ==
$null) { # request with no Username in RURI sl_send_reply("484","Address
Incomplete"); exit; } # user location service route(LOCATION); } #
Wrapper for relaying requests route[RELAY] { # enable additional event
routes for forwarded requests # - serial forking, RTP relaying handling,
a.s.o. if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) { if
(!t_is_set("branch_route")) { t_on_branch("MANAGE_BRANCH"); } } if
(is_method("INVITE|SUBSCRIBE|UPDATE")) { if
(!t_is_set("onreply_route"))
{ t_on_reply("MANAGE_REPLY"); } } if (is_method("INVITE")) { if
(!t_is_set("failure_route")) { t_on_failure("MANAGE_FAILURE"); } } if
(!t_relay()) { sl_reply_error(); } exit; } # Per SIP request initial
checks route[REQINIT] { #!ifdef WITH_ANTIFLOOD # flood dection from same
IP and traffic ban for a while # be sure you exclude checking trusted
peers, such as pstn gateways # - local host excluded (e.g., loop to
self) if (src_ip != myself) { if ($sht(ipban=>$si) != $null) { # ip is
already blocked xdbg("request from blocked IP - $rm from $fu
(IP:$si:$sp)\n"); exit; } if (!pike_check_req()) {
xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n");
$sht(ipban=>$si) = 1; exit; } } #!endif if
(!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many
Hops"); exit; } if (!sanity_check("1511", "7")) {
xlog("Malformed SIP
message from $si:$sp\n"); exit; } } # Handle requests within SIP dialogs
route[WITHINDLG] { if (has_totag()) { # sequential request withing a
dialog should # take the path determined by record-routing if
(loose_route()) { #!ifdef WITH_WEBSOCKETS if ($du == "") { if
(!handle_ruri_alias()) { xlog("L_ERR", "Bad alias <$ru>\n");
sl_send_reply("400", "Bad Request"); exit; } } #!endif route(DLGURI);
if
(is_method("ACK")) { # ACK is forwarded statelessy route(NATMANAGE); }
else if (is_method("NOTIFY")) { # Add Record-Route for in-dialog NOTIFY
as per RFC 6665. record_route(); } route(RELAY); } else { if
(is_method("SUBSCRIBE") && uri == myself) { # in-dialog subscribe
requests route(PRESENCE); exit; } if (is_method("ACK")) { if
(t_check_trans()) { # no loose-route, but stateful ACK; # must be an ACK
after a 487 # or e.g. 404 from upstream server route(RELAY); exit; }
else { # ACK without matching transaction ... ignore and discard exit; }
} sl_send_reply("404","Not here"); } exit; } } # Handle SIP
registrations route[REGISTRAR] { if (is_method("REGISTER")) { if
(isflagset(FLT_NATS)) { setbflag(FLB_NATB); # uncomment next line to do
SIP NAT pinging ## setbflag(FLB_NATSIPPING); } #!ifdef WITH_IPV6 if (af
== INET6) { setbflag(FLB_IPV6); } #!endif if (!save("location")) {
sl_reply_error(); } exit; } } # USER location service route[LOCATION] {
if (!lookup("location")) { $var(rc) = $rc; t_newtran(); switch
($var(rc)) { case -1: case -3: send_reply("404", "Not Found"); exit;
case -2: send_reply("405", "Method Not Allowed"); exit; } }
route(RELAY); exit; } # Presence server route route[PRESENCE] { if
(!is_method("PUBLISH|SUBSCRIBE")) { return; } if
(is_method("SUBSCRIBE")
&& $hdr(Event) == "message-summary") { # returns here if no voicemail
server is configured sl_send_reply("404", "No voicemail service");
exit;
} #!ifdef WITH_PRESENCE if (!t_newtran()) { sl_reply_error(); exit; } if
(is_method("PUBLISH")) { handle_publish(); t_release(); } else if
(is_method("SUBSCRIBE")) { handle_subscribe(); t_release(); } exit;
#!endif # if presence enabled, this part will not be executed if
(is_method("PUBLISH") || $rU == $null) { sl_send_reply("404",
"Not
here"); exit; } return; } # Authentication route route[AUTH] { #!ifdef
WITH_AUTH if (is_method("REGISTER") || from_uri == myself) { #
authenticate requests if (!auth_check("$fd", "subscriber",
"1")) {
auth_challenge("$fd", "0"); exit; } # user authenticated - remove auth
header if (!is_method("REGISTER|PUBLISH")) { consume_credentials(); } }
# if caller is not local subscriber, then check if it calls # a local
destination, otherwise deny, not an open relay here if (from_uri !=
myself && uri != myself) { sl_send_reply("403","Not
relaying"); exit; }
#!endif return; } # Caller NAT detection route route[NATDETECT] {
#!ifdef WITH_IPV6 if(af==INET6) { return; } #!endif force_rport(); if
(nat_uac_test("19")) { if (is_method("REGISTER")) {
fix_nated_register(); } else if (is_first_hop()) { set_contact_alias();
} setflag(FLT_NATS); } return; } # NAT handling route[NATMANAGE] { if
(is_request()) { if (has_totag()) { if (check_route_param("nat=yes")) {
setbflag(FLB_NATB); } if (check_route_param("rtp=bridge")) {
setbflag(FLB_BRIDGE); } if (check_route_param("rtp=ws")) {
setbflag(FLB_RTPWS); } #!ifdef WITH_IPV6 if
(check_route_param("rtp=v46")) { setbflag(FLB_V4V6); } #!endif } } if
(!isbflagset(FLB_BRIDGE)) { return; } if ( !(isflagset(FLT_NATS) ||
isbflagset(FLB_NATB) || isbflagset(FLB_RTPWS) #!ifdef WITH_IPV6 ||
isbflagset(FLB_V4V6) #!endif ) ) { return; } $xavp(r=>$T_branch_idx) =
"replace-origin replace-session-connection"; if (!nat_uac_test("8")) {
$xavp(r=>$T_branch_idx) = $xavp(r=>$T_branch_idx) + " trust-address"; }
if (is_request()) { if (!has_totag()) { if (!t_is_failure_route()) {
$avp(extra_id) = @via[1].branch + $T_branch_idx; $xavp(r=>$T_branch_idx)
= $xavp(r=>$T_branch_idx) + " via-branch=extra"; } } } if (is_reply()) {
$avp(extra_id) = @via[2].branch + $T_branch_idx; $xavp(r=>$T_branch_idx)
= $xavp(r=>$T_branch_idx) + " via-branch=extra"; } #!ifdef WITH_IPV6 if
(af == INET && isbflagset(FLB_IPV6)) { # IPv4 --> IPv6
$xavp(r=>$T_branch_idx) = $xavp(r=>$T_branch_idx) + "
address-family=IP6"; } else if (af == INET6 && !isbflagset(FLB_IPV6)) {
# IPv6 --> IPv4 $xavp(r=>$T_branch_idx) = $xavp(r=>$T_branch_idx) + "
address-family=IP4"; } #!endif if (isbflagset(FLB_RTPWS)) { if ($proto
=~ "ws") { # web --> SIP $xavp(r=>$T_branch_idx) =
$xavp(r=>$T_branch_idx) + " rtcp-mux-demux DTLS=off SDES-off ICE=remove
RTP/AVP"; } else { # SIP --> web $xavp(r=>$T_branch_idx) =
$xavp(r=>$T_branch_idx) + " rtcp-mux-offer generate-mid DTLS=passive
SDES-off ICE=force RTP/SAVPF"; } } else { if ($proto =~ "ws") { # web
--> web $xavp(r=>$T_branch_idx) = $xavp(r=>$T_branch_idx) + "
generate-mid DTLS=passive SDES-off ICE=force"; } # else { #
$xavp(r=>$T_branch_idx) = $xavp(r=>$T_branch_idx) + ""; # } }
xlog("L_INFO", "NATMANAGE branch_id:$T_branch_idx ruri: $ru, method:$rm,
status:$rs, extra_id: $avp(extra_id), rtpengine_manage:
$xavp(r=>$T_branch_idx)\n"); rtpengine_manage($xavp(r=>$T_branch_idx));
if (is_request()) { if (!has_totag()) { if (t_is_branch_route()) { if
(isbflagset(FLB_NATB)) { add_rr_param(";nat=yes"); } if
(isbflagset(FLB_BRIDGE)) { add_rr_param(";rtp=bridge"); } if
(isbflagset(FLB_RTPWS)) { add_rr_param(";rtp=ws"); } #!ifdef WITH_IPV6
if (isbflagset(FLB_V4V6)) { add_rr_param(";rtp=v46"); } #!endif } } } if
(is_reply()) { if (isbflagset(FLB_NATB)) { if (is_first_hop()) { if (af
== INET) { set_contact_alias(); } } } } return; } # URI update for
dialog requests route[DLGURI] { if (!isdsturiset()) {
handle_ruri_alias(); } return; } # Routing to foreign domains
route[SIPOUT] { if (!uri == myself) { append_hf("P-hint: outbound\r\n");
route(RELAY); } } route[BRIDGING] { if (!has_totag()) { if ($proto =~
"ws" && !($ru =~ "transport=ws")) { # Coming from WS, NOT to
WS
setbflag(FLB_RTPWS); # Need bridging } else if (!($proto =~ "ws") && $ru
=~ "transport=ws") { # Coming from NOT WS, going to WS
setbflag(FLB_RTPWS); # Need bridging } #!ifdef WITH_IPV6 if (af == INET6
&& !isbflagset(FLB_IPV6)) { setbflag(FLB_V4V6); } else if(af == INET &&
isbflagset(FLB_IPV6)) { setbflag(FLB_V4V6); } #!endif } } # manage
outgoing branches branch_route[MANAGE_BRANCH] { xlog("L_INFO",
"MANAGE_BRANCH: New branch [$T_branch_idx] to $ru\n");
t_on_branch_failure("rtpengine"); #!ifndef WITH_BRIDGE_ON_FAIL
setbflag(FLB_BRIDGE); #!endif route(BRIDGING); route(NATMANAGE); } #
manage incoming replies onreply_route[MANAGE_REPLY] { xdbg("incoming
reply\n"); if (status =~ "[12][0-9][0-9]") { route(NATMANAGE); } } #
manage failure routing cases failure_route[MANAGE_FAILURE] {
xlog("L_INFO", "Failure: $rs"); } #!ifdef WITH_WEBSOCKETS
onreply_route
{ if ((($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT) && !(proto == WS ||
proto == WSS))) { xlog("L_WARN", "SIP response received on $Rp\n");
drop; } if (nat_uac_test(64)) { # Do NAT traversal stuff for replies to
a WebSocket connection # - even if it is not behind a NAT! # This won't
be needed in the future if Kamailio and the # WebSocket client support
Outbound and Path. add_contact_alias(); } }
event_route[tm:branch-failure:rtpengine] { xlog("L_INFO", "BRANCH
FAILED: $sel(via[1].branch) + $T_branch_idx"); #!ifdef
WITH_BRIDGE_ON_FAIL if (!isbflagset(FLB_BRIDGE) &&
t_check_status("415|488")) { t_reuse_branch(); setbflag(FLB_BRIDGE);
xlog("L_INFO", "event_route[branch-failure:rtpengine]: trying
again\n");
route(RELAY); } else { $avp(extra_id) = @via[1].branch + $T_branch_idx;
rtpengine_delete("via-branch=extra"); xlog("L_INFO",
"event_route[branch-failure:rtpengine]: failed\n"); } #!else
$avp(extra_id) = @via[1].branch + $T_branch_idx;
rtpengine_delete("via-branch=extra"); #!endif }
event_route[xhttp:request] { set_reply_close(); set_reply_no_connect();
if ($Rp != MY_WS_PORT #!ifdef WITH_TLS && $Rp != MY_WSS_PORT #!endif ) {
xlog("L_WARN", "HTTP request received on $Rp\n");
xhttp_reply("403",
"Forbidden", "", ""); exit; } xlog("L_INFO",
"HTTP Request Received\n");
if ($hdr(Upgrade) =~ "websocket" && $hdr(Connection) =~
"Upgrade" && $rm
=~ "GET" ) { # Validate Host - make sure the client is using the correct
# alias for WebSockets if ($hdr(Host) == $null || !is_myself("sip:" +
$hdr(Host))) { xlog("L_WARN", "Bad host $hdr(Host)\n");
xhttp_reply("403", "Forbidden", "", ""); exit; } #
Optional... validate
Origin - make sure the client is from an # authorised website. For
example, # # if ($hdr(Origin) != "https://example.com" # && $hdr(Origin)
!= "https://example.com") { # xlog("L_WARN", "Unauthorised client
$hdr(Origin)\n"); # xhttp_reply("403", "Forbidden", "",
""); # exit; # }
# Optional... perform HTTP authentication # ws_handle_handshake() exits
(no further configuration file # processing of the request) when
complete. if (ws_handle_handshake()) { # Optional... cache some
information about the # successful connection exit; } }
xhttp_reply("404", "Not Found", "", ""); }
event_route[websocket:closed]
{ xlog("L_INFO", "WebSocket connection from $si:$sp has closed\n"); }
#!endif |
Thank.