#!KAMAILIO

####### Defined Values #########

#!substdef "!MY_IP_ADDR!<privateip>!g"
#!substdef "!MY_EXTERNAL_IP!<publicip>!g"
#!substdef "!MY_UDP_PORT!5060!g"
#!substdef "!MY_TCP_PORT!5060!g"
#!substdef "!MY_UDP_ADDR!udp:MY_IP_ADDR:MY_UDP_PORT!g"
#!substdef "!MY_TCP_ADDR!tcp:MY_IP_ADDR:MY_TCP_PORT!g"


## 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 setting
log_facility = LOG_LOCAL0

children = 8
# async_workers=8

listen = MY_UDP_ADDR advertise MY_EXTERNAL_IP:MY_UDP_PORT
listen = MY_TCP_ADDR advertise MY_EXTERNAL_IP:MY_TCP_PORT

# life time of TCP connection when there is no traffic
# - a bit higher than registration expires to cope with UA behind NAT
tcp_max_connections=25000
tcp_connection_lifetime=3605
tcp_accept_no_cl=yes
tcp_rd_buf_size=16384

server_header="Server: Barebone Kamailio Server"
sip_warning=0


####### Modules Section ########
#!ifdef WITH_SRCPATH
mpath = "modules/"
#!else
mpath = "/usr/local/lib64/kamailio/modules/:/usr/lib/x86_64-linux-gnu/kamailio/modules/"
#!endif
# ------------------ module loading ----------------------------------
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "maxfwd.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "path.so"
loadmodule "cfg_rpc.so"
loadmodule "ctl.so"
loadmodule "db_text.so"
loadmodule "permissions.so"
loadmodule "corex.so"
loadmodule "dialog.so"

# ----------------- setting module-specific parameters ---------------


# ----- record routing rr params -----
# set next param to 1 to add value to ;lr param (helps with some UAs)
modparam("rr", "enable_full_lr", 0)

#request's from-tag is appended to record-route; 
# do not append from tag to the RR (no need for this script)
modparam("rr", "append_fromtag", 1)

#nsert two Record-Route header fields instead of one
modparam("rr", "enable_double_rr", 1)


# ----- ctl ------
modparam("ctl", "binrpc", "tcp:MY_IP_ADDR:2046")

# ----- dialog params ------
modparam("dialog", "dlg_flag", 4)
modparam("dialog", "track_cseq_updates", 1)
modparam("dialog", "noack_timeout", 90)
modparam("dialog", "event_callback", "ksr_dialog_event")

# ----- tm params -----
# auto-discard branches from previous serial forking leg
modparam("tm", "failure_reply_mode", 3)
modparam("tm", "fr_timer", 5000)
modparam("tm", "fr_inv_timer", 120000)
modparam("tm", "restart_fr_on_each_reply", 1)
modparam("tm", "pass_provisional_replies", 1)
modparam("tm", "contacts_avp", "tm_contacts")
modparam("tm", "contact_flows_avp", "tm_contact_flows")
modparam("tm", "remap_503_500", 0)

request_route {

	# per request initial checks
	route(REQINIT);

	# CANCEL processing
	if (is_method("CANCEL")) {
		if (t_check_trans()) {
			route(RELAY);
		}
		exit;
	}

	# handle retransmissions
	if (!is_method("ACK")) {
		if(t_precheck_trans()) {
			t_check_trans();
			exit;
		}
		t_check_trans();
	}

	# handle requests within SIP dialogs
	route(WITHINDLG);

	### only initial requests (no To tag)

	# record routing for dialog forming requests (in case they are routed)
	# - remove preloaded route headers
	remove_hf("Route");
	if (is_method("INVITE|SUBSCRIBE")) {
                xlog(" INVITE or SUBSCRIBE , Add record route \n");
		record_route();
	}

	# account only INVITEs
	if (is_method("INVITE")) {
		xlog(" --------------------------------------  Request received INVITE \n");
		# Do Other things like start accounting do auth etc 
	}

	if ($rU==$null) {
		# request with no Username in RURI
		sl_send_reply("484","Address Incomplete");
		exit;
	}

	# update $du to set the destination address for proxying
	$du = "sip:" + $rd + ":9";
	route(RELAY);
	exit;
}

# 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")) {
        	xlog(" Route relay --- setting MANAGE_BRANCH");
		if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY");
	}
	if (is_method("INVITE")) {
		xlog(" Route relay --- setting MANAGE_FAILURE");
		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] {
	if($ua =~ "friendly-scanner|sipcli|VaxSIPUserAgent") {
		# silent drop for scanners - uncomment next line if want to reply
		# sl_send_reply("200", "OK");
		exit;
	}

	if (!mf_process_maxfwd_header("10")) {
		sl_send_reply("483","Too Many Hops");
		exit;
	}

	# handle OPTION with 200 Keepalive
	if(is_method("OPTIONS") && uri==myself && $rU==$null) {
		sl_send_reply("200","Keepalive");
		exit;
	}

	# Check SIP URI format
	if(!sanity_check("1511", "7")) {
		xlog("Malformed SIP message from $si:$sp\n");
		exit;
	}
}

# Handle requests within SIP dialogs
route[WITHINDLG] {
	
	# Do nothing for first request which does not have a to tag 
	if (!has_totag()) return;

	# sequential request withing a dialog should take the path determined by record-routing
	if (loose_route()) {
		if (is_method("BYE")) {
			xdbg(" BYE request \n");
		} else if ( is_method("NOTIFY") ) {
			# Add Record-Route for in-dialog NOTIFY as per RFC 6665.
			record_route();
		}
		route(RELAY);
		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;
}

# Manage outgoing branches
branch_route[MANAGE_BRANCH] {
	xdbg("new branch [$T_branch_idx] to $ru\n");
}

# Manage incoming replies
onreply_route[MANAGE_REPLY] {
	xdbg("incoming reply\n");
}

# Manage failure routing cases
failure_route[MANAGE_FAILURE] {
	if (t_is_canceled()) exit;
	xlog(" FAILURE ");
}

