Skip to content

Instantly share code, notes, and snippets.

@adeshpandey
Created November 19, 2019 11:15
Show Gist options
  • Save adeshpandey/2c338db7f5d992267f7415de0325e0b4 to your computer and use it in GitHub Desktop.
Save adeshpandey/2c338db7f5d992267f7415de0325e0b4 to your computer and use it in GitHub Desktop.
#!KAMAILIO
#!define DBURL "mysql://mysql_user:mysql_pass@localhost/kamailio"
#!substdef "!MY_IP_ADDR!LOCAL_IP_ADDRESS!g"
#!substdef "!MY_DOMAIN!PUBLIC_DOMAIN!g"
#!substdef "!MY_WS_PORT!8080!g"
#!substdef "!MY_WSS_PORT!8081!g"
#!substdef "!MY_WS_ADDR!tcp:MY_IP_ADDR:MY_WS_PORT!g"
#!substdef "!MY_WSS_ADDR!tls:MY_IP_ADDR:MY_WSS_PORT!g"
#!define WITH_NAT
#!define FLB_NATB 6
#!define FLB_NATSIPPING 7
#!define FLT_NATS 5
#!define FLT_OUT 8
#!define WITH_TLS
#!define WITH_AUTH
##!define WITH_DEBUG
include_file "webrtc/modules.cfg"
listen=udp:MY_IP_ADDR:5090 advertise MY_DOMAIN:5090
listen=MY_WSS_ADDR advertise MY_DOMAIN:MY_WSS_PORT
listen=MY_WS_ADDR advertise MY_DOMAIN:MY_WS_PORT
alias = MY_DOMAIN
request_route {
if ((($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT)
&& !(proto == WS || proto == WSS))) {
xlog("L_WARN", "SIP request received on $Rp\n");
sl_send_reply("403", "Forbidden");
exit;
}
xlog("L_INFO","Message buffer $mb");
# per request initial checks
route(REQINIT);
# 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();
if (!is_method("REGISTER|INVITE|ACK|BYE|CANCEL|PRACK|MESSAGE|INFO|UPDATE")) {
sl_send_reply("405", "Method not allowed");
exit;
}
# 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_preset("DOMAIN_NAME:5090;nat=yes");
# handle registrations
route(REGISTRAR);
if ($rU==$null) {
# request with no Username in RURI
sl_send_reply("484","Address Incomplete");
exit;
}
if (!is_method("INVITE")) {
route(RELAY);
exit;
}
xlog("L_INFO","Call will be forwarded to location");
if (allow_trusted()) {
xlog("L_ALERT","Send to Location..........");
# user location service
route(LOCATION);
}
else
{
xlog("L_INFO","Dispatch not trusted");
# dispatch to webrtc servers
route(DISPATCH);
}
}
route[DISPATCH] {
# round robin dispatching on gateways group '1'
if(!ds_select_dst("1", "6"))
{
send_reply("404", "No destination");
exit;
}
xlog("L_INFO", "--- SCRIPT: going to <$ru> via <$du>\n");
t_on_failure("RTF_DISPATCH");
route(RELAY);
#forward();
exit;
}
route[SETUP_BY_TRANSPORT] {
xlog("L_INFO","Setup transport");
if ($ru =~ "transport=ws") {
xlog("L_INFO", "Request going to WS");
if(sdp_with_transport("RTP/SAVPF")) {
rtpengine_manage("trust-address replace-origin replace-session-connection ICE=force SDES-off");
t_on_reply("REPLY_WS_TO_WS");
return;
}
# rtpengine_manage("froc+SP");
rtpengine_manage("trust-address replace-origin replace-session-connection ICE=force RTP/SAVPF SDES-off");
t_on_reply("REPLY_FROM_WS");
}
else if ($proto =~ "ws") {
xlog("L_INFO", "Request coming from WS");
# rtpengine_manage("froc-sp");
rtpengine_manage("trust-address replace-origin replace-session-connection ICE=remove RTP/AVP");
t_on_reply("REPLY_TO_WS");
}
else {
xlog("L_INFO", "This is a classic phone call");
# rtpengine_manage("co");
rtpengine_manage("replace-origin replace-session-connection ICE=force");
t_on_reply("MANAGE_CLASSIC_REPLY");
}
}
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;
}
if (ws_handle_handshake())
{
# Optional... cache some information about the
# successful connection
exit;
}
}
xhttp_reply("404", "Not Found", "", "");
}
route[RELAY] {
if (is_method("INVITE")) {
route(SETUP_BY_TRANSPORT);
#route(RTP_PROXY);
if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");
}
if (!t_relay()) {
sl_reply_error();
}
xlog("L_INFO","Relayed here");
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()) {
if ($du == "") {
if (!handle_ruri_alias()) {
xlog("L_ERR", "Bad alias <$ru>\n");
sl_send_reply("400", "Bad Request");
exit;
}
}
# else
# route(DLGURI);
xlog("==> duri=[$du]");
if ( is_method("ACK") ) {
# ACK is forwarded statelessy
route(NATMANAGE);
}
route(RELAY);
} else {
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);
}
if (!save("location"))
sl_reply_error();
exit;
}
}
# USER location service
route[LOCATION] {
xlog("L_INFO","call in location..........$ru");
$avp(oexten) = $rU;
if (!lookup("location")) {
xlog("L_INFO","No Location......... $rc");
$var(rc) = $rc;
#route(TOVOICEMAIL);
t_newtran();
switch ($var(rc)) {
case -1:
case -3:
send_reply("404", "Not Found");
exit;
case -2:
send_reply("405", "Method Not Allowed");
exit;
}
}
else{
route(RELAY);
}
exit;
}
# Routing to voicemail server
route[TOVOICEMAIL] {
#!ifdef WITH_VOICEMAIL
if(!is_method("INVITE|SUBSCRIBE")) return;
# check if VoiceMail server IP is defined
if (strempty($sel(cfg_get.voicemail.srv_ip))) {
xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n");
return;
}
if(is_method("INVITE")) {
if($avp(oexten)==$null) return;
$ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip)
+ ":" + $sel(cfg_get.voicemail.srv_port);
} else {
if($rU==$null) return;
$ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip)
+ ":" + $sel(cfg_get.voicemail.srv_port);
}
route(RELAY);
exit;
#!endif
return;
}
# Authentication route
route[AUTH] {
#!ifdef WITH_AUTH
if (is_method("REGISTER")) {
# authenticate requests
if (!auth_check("$fd", "subscriber", "1")) {
xlog("L_INFO","Could not authenticate: $fd");
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] {
force_rport();
# if (nat_uac_test("64")) {
if (is_method("REGISTER")) {
fix_nated_register();
} else {
add_contact_alias();
# fix_nated_contact();
}
setflag(FLT_NATS);
# }
return;
}
# RTPProxy control
route[NATMANAGE] {
if (is_request()) {
if(has_totag()) {
if(check_route_param("nat=yes")) {
setbflag(FLB_NATB);
}
}
}
if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB)))
return;
if (is_request()) {
if (!has_totag()) {
if(t_is_branch_route()) {
add_rr_param(";nat=yes");
}
}
}
if (is_reply()) {
if(isbflagset(FLB_NATB)) {
add_contact_alias();
}
}
}
# URI update for dialog requests
route[DLGURI] {
if(!isdsturiset()) {
handle_ruri_alias();
}
return;
}
onreply_route[REPLY_TO_WS] {
xlog("L_INFO", "Reply from softphone: $rs");
if (t_check_status("183")) {
change_reply_status("180", "Ringing");
remove_body();
exit;
}
if(!(status=~"[12][0-9][0-9]"))
return;
# rtpengine_manage("froc+SP");
rtpengine_manage("trust-address replace-origin replace-session-connection ICE=force RTP/SAVPF");
route(NATMANAGE);
}
onreply_route[REPLY_FROM_WS] {
xlog("L_INFO", "Reply from webrtc client: $rs");
if(status=~"[12][0-9][0-9]") {
rtpengine_manage("force trust-address replace-origin replace-session-connection ICE=remove RTP/AVP");
# rtpengine_manage("froc-sp");
route(NATMANAGE);
}
}
onreply_route[MANAGE_CLASSIC_REPLY] {
xlog("L_INFO", "Boring reply from softphone: $rs");
if(status=~"[12][0-9][0-9]") {
rtpengine_manage("replace-origin replace-session-connection");
# rtpengine_manage("co");
xlog("L_INFO", "Boring reply from softphone: $rs again");
route(NATMANAGE);
}
}
onreply_route[REPLY_WS_TO_WS] {
xlog("L_INFO", "WS to WS");
if(status=~"[12][0-9][0-9]") {
rtpengine_manage("force trust-address replace-origin replace-session-connection ICE=force");
route(NATMANAGE);
}
}
# manage failure routing cases
failure_route[MANAGE_FAILURE] {
route(NATMANAGE);
if (t_is_canceled()) {
exit;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment