#!KAMAILIO
#
# Edge proxy configuration
#

#!substdef "!REGISTRAR_IP!a.b.c.d!g"
#!substdef "!REGISTRAR_PORT!5060!g"
#!substdef "!FLOW_TIMER!20!g"

####### Global Parameters #########

debug=2
log_stderror=no
log_facility=LOG_LOCAL0
fork=yes
children=4
alias="example.com"
mpath="/usr/lib64/kamailio/modules"
tcp_connection_lifetime=30 # FLOW_TIMER + 10
force_rport=yes


####### Modules Section ########

loadmodule "tm.so"
loadmodule "sl.so"
loadmodule "outbound.so"
loadmodule "rr.so"
loadmodule "path.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "mi_rpc.so"
loadmodule "mi_fifo.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "stun.so"

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

# ----- mi_fifo params -----
modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")

# ----- tm params -----
modparam("tm", "failure_reply_mode", 3)

# ----- rr params -----
modparam("rr", "append_fromtag", 0)


####### Routing Logic ########

request_route {
	route(REQINIT);

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

	route(WITHINDLG);

	t_check_trans();

	if (is_method("REGISTER")) {
		remove_hf("Route");
		add_path();
		$du = "sip:REGISTRAR_IP:REGISTRAR_PORT";
	} else {
		if (is_method("INVITE|SUBSCRIBE"))
			record_route();

		if (@via[2] == "") {
			# From client so route to registrar...

			if ($rU == $null) {
				sl_send_reply("484", "Address Incomplete");
				exit;
			}
			remove_hf("Route");
			$du = "sip:REGISTRAR_IP:REGISTRAR_PORT";
		} else {
			# From registrar so route using "Route:" headers...

			if (!loose_route()) {
				switch($rc) {
				case -2:
					sl_send_reply("403", "Forbidden");
					exit;
				default:
					xlog("L_ERR", "in request_route\n");
					sl_reply_error();
					exit;
				}
			}

			t_on_failure("FAIL_OUTBOUND");
		}
	}

	route(RELAY);
}

route[RELAY] {
	if (!t_relay()) {
		sl_reply_error();
	}
	exit;
}

route[REQINIT] {
	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;
	}
}

route[WITHINDLG] {
	if (has_totag()) {
		if (!loose_route()) {
			switch($rc) {
			case -2:
				sl_send_reply("403", "Forbidden");
				exit;
			default:
				if (is_method("ACK")) {
					if ( t_check_trans() ) {
						route(RELAY);
						exit;
					} else {
						exit;
					}
				}
				sl_send_reply("404","Not Found");
			}
		} else {
			if (is_method("NOTIFY")) {
				record_route();
			}
			route(RELAY);
		}
		exit;
	}
}

onreply_route {
	if (!t_check_trans()) {
		drop;
	}

	if ($rm == "REGISTER" && $rs >= 200 && $rs <= 299) {
		remove_hf("Flow-Timer");
		if ($(hdr(Require)[*])=~"outbound")
			insert_hf("Flow-Timer: FLOW_TIMER\r\n", "Call-ID");
	}
}

failure_route[FAIL_OUTBOUND] {
	if (t_branch_timeout() || !t_branch_replied()) {
		send_reply("430", "Flow Failed");
	}
}