评fred的mid-registrar for kamailio脚本

#!KAMAILIO
#
# Edge proxy configuration
# mid-registrar example
#

#!substdef "!REGISTRAR_IP!a.b.c.d!g"
#!substdef "!REGISTRAR_PORT!5060!g"
#!substdef "!MY_DOMAIN!whatever.net!g"
#!substdef "!MY_IP_ADDR!e.f.g.h!g"
#!substdef "!MY_PUBLIC_IP!i.j.k.l!g"

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

debug=2
log_stderror=no
log_facility=LOG_LOCAL0
log_prefix="{$mt $hdr(CSeq) $ci} "
fork=yes
children=2 #-- use one per core
listen=MY_IP_ADDR advertise MY_PUBLIC_IP:5060
alias="MY_DOMAIN"
alias="MY_PUBLIC_IP"
force_rport=yes


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

loadmodule "jsonrpcs.so"
loadmodule "tm.so"
loadmodule "tmx.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 "textops.so"
loadmodule "corex.so"
loadmodule "textopsx.so"
loadmodule "siputils.so"
loadmodule "htable.so"

# ----------------- setting module-specific parameters ---------------
modparam("tm", "failure_reply_mode", 3)
modparam("rr", "append_fromtag", 0)
modparam("corex", "alias_subdomains", "MY_DOMAIN")
modparam("htable", "htable", "regs=>size=14;autoexpire=3530;") #- 16384 slots

####### 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")) {
		if ($sht(regs=>$fU@$fd)!=$null) {
			if ($sht(regs=>$fU@$fd)==$_s($si:$sp)) {
				sl_send_reply("200", "OK");
				exit;
			}
		}

		$var(host) = $si + ":" + $sp;
		$var(user) = $(sel(contact.uri.user));
		remove_hf("Route");
		remove_hf("Contact");
		if (is_present_hf("Expires")) {
			remove_hf("Expires");
		}
		
		add_path();
		append_hf("Contact: \r\n","CSeq");
		append_hf("Expires: 3600\r\n", "Contact");
		$du = "sip:REGISTRAR_IP:REGISTRAR_PORT";
	} else {
		if (is_method("INVITE|SUBSCRIBE"))
			record_route();

		if(src_ip!=REGISTRAR_IP){
			if ($rU == $null) {
				sl_send_reply("484", "Address Incomplete");
				exit;
			}
			$var(host) = $si + ":" + $sp;
			$var(user) = $(sel(contact.uri.user));
			remove_hf("Contact");
			append_hf("Contact: \r\n","CSeq");
			$du = "sip:REGISTRAR_IP:REGISTRAR_PORT";
		} else {
			# From registrar so route using "Route:" headers...
			if ($(ru{uri.param,lm}) == "midreg") {
				$var(host) = $(ru{uri.param,lhst});
				$du = "sip:" + $(ru{uri.user}) + "@" + $var(host);
			}

			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 (src_ip!=REGISTRAR_IP) {
		$var(host) = $si + ":" + $sp;
		$var(user) = $(sel(contact.uri.user));
		remove_hf("Contact");
		append_hf("Contact: \r\n","CSeq");
		$du = "sip:REGISTRAR_IP:REGISTRAR_PORT";
	}

	if ($(ru{uri.param,lm}) == "midreg") {
		$var(host) = $(ru{uri.param,lhst});
		$du = "sip:" + $(ru{uri.user}) + "@" + $var(host);
		if ($rm == "REGISTER" && $rs == "200") {
			$sht(regs=>$fU@$fd) = $var(host);
	
			if (is_present_hf("Expires")) {
				$var(exp) = $hdr(Expires) - 30;
				$shtex(regs=>$fU@$fd) = $var(exp);
				remove_hf("Expires");
			}

			if (is_present_hf("Contact")) {
				remove_hf("Contact");
			}

			append_hf("Expires: 60\r\n", "Call-ID");
			append_hf("Contact: $var(ct)\r\n","CSeq");
		}
	}
}

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

mid-registrar主要原理是转发register请求时修改contact头(留意contact头里面的uri和参数,invite会带回来)

不得不说fred对kamailio的掌握是非常到位的,脚本短小且精妙,看不到半句废话

如果一定要提建议的话,那么增加nat的处理就更完整了,且更实用。

原文在github上可以找到。

你可能感兴趣的:(Kamailio,Kamailio,fred,mid-registrar)