#!KAMAILIO
#
# Registrar configuration
#


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

debug=2
log_stderror=no
log_facility=LOG_LOCAL0
fork=yes
children=4
alias="example.com"
mpath="/usr/lib64/kamailio/modules"


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

loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.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 "usrloc.so"
loadmodule "registrar.so"

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

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


# ----- tm params -----
modparam("tm", "failure_reply_mode", 3)
modparam("tm", "restart_fr_on_each_reply", 0)
modparam("tm", "contact_flows_avp", "tm_contact_flows")
modparam("tm", "contacts_avp", "tm_contacts")

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

# ----- registrar params -----
modparam("registrar", "use_path", 1)
modparam("registrar", "gruu_enabled", 1)
modparam("registrar", "outbound_mode", 1)


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

request_route {
	route(REQINIT);

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

	route(WITHINDLG);

	t_check_trans();

	remove_hf("Route");
	if (is_method("INVITE|SUBSCRIBE"))
		record_route();

	route(REGISTRAR);

	if ($rU==$null) {
		xlog("L_INFO", "Address Incomplete\n");
		send_reply("484", "Address Incomplete");
		exit;
	}

	route(LOCATION);
}


route[RELAY] {
	if (!t_relay()) {
		xlog("L_ERR", "t_relay() failed\n");
		sl_reply_error();
	}
	exit;
}

route[REQINIT] {
	if (!mf_process_maxfwd_header("10")) {
		xlog("L_INFO", "Too Many Hops\n");
		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()) {
			if (is_method("NOTIFY")) {
				record_route();
			}
			route(RELAY);
		} else {
			if (is_method("ACK")) {
				if (t_check_trans()) {
					route(RELAY);
					exit;
				} else {
					exit;
				}
			}
			xlog("L_INFO", "Not Found");
			send_reply("404", "Not Found");
		}
		exit;
	}
}

route[REGISTRAR] {
	if (is_method("REGISTER"))
	{
		if (!save("location")) {
			xlog("L_ERR", "Unable to save location\n");
			sl_reply_error();
		}
		exit;
	}
}

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;
		}
	}

	if (!t_load_contacts() || !t_next_contacts()) {
		xlog("L_ERR", "t_(load|next)_contacts() failed\n");
		sl_reply_error();
		exit;
	}

	t_on_failure("FAIL_TRANSACTION");
	t_on_branch_failure("FAIL-BRANCH");
	route(RELAY);
	exit;
}

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

failure_route[FAIL_TRANSACTION] {
	if (!t_check_status("6[0-9][0-9]")) {
		if (t_next_contacts()) {
			t_relay();
			exit;
		}
	}

	if (t_check_status("430")) {
		t_reply("480", "Temporarily Unavailable");
		exit;
	}
}

event_route[tm:branch-failure:FAIL-BRANCH] {
	if (t_check_status("403|430")
			|| (t_branch_timeout() && !t_branch_replied())) {
		unregister("location", "$tu", "$T_reply_ruid");

		if (t_next_contact_flow()) {
			t_on_branch_failure("FAIL-BRANCH");
			t_relay();
		}
	}
}
