2
0
Эх сурвалжийг харах

smsops: Added an example configuration for an Interworking SMSc-AS

Carsten Bock 10 жил өмнө
parent
commit
59450e0708

+ 418 - 0
modules/smsops/examples/kamailio.cfg

@@ -0,0 +1,418 @@
+#!KAMAILIO
+#
+# This config file implements the basic P-CSCF functionality
+#     - web: http://www.kamailio.org
+#     - git: http://sip-router.org
+#
+# Refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php
+# for an explanation of possible statements, functions and parameters.
+#
+# Direct your questions about this file to: <[email protected]>.
+#
+# For more information about the various parameters, functions and statements
+# try http://sip-router.org/wiki/ .
+#
+
+include_file "smsc.cfg"
+
+####### Global Parameters #########
+debug=2
+log_stderror=no
+sip_warning=no
+children=4
+
+user_agent_header="User-Agent: Kamailio SMSC"
+server_header="Server: Kamailio SMSC"
+
+/* comment the next line to enable the auto discovery of local aliases
+   based on reverse DNS on IPs (default on) */
+auto_aliases=no
+
+check_via=no    # (cmd. line: -v)
+dns=no          # (cmd. line: -r)
+rev_dns=no      # (cmd. line: -R)
+tcp_accept_no_cl=yes
+
+#!define SMS_3GPP 1
+#!define SMS_TEXT 2
+
+alias=SERVER
+
+# ------------------ module loading ----------------------------------
+mpath="/root/kamailio-devel/lib64/kamailio/modules"
+# (we try both the lib64 and the lib directory)
+
+loadmodule "tm"
+loadmodule "tmx"
+loadmodule "smsops"
+loadmodule "xlog"
+loadmodule "maxfwd"
+loadmodule "textops"
+loadmodule "sl"
+loadmodule "sanity"
+loadmodule "siputils"
+loadmodule "pv"
+loadmodule "uac"
+loadmodule "xhttp"
+loadmodule "utils"
+loadmodule "json"
+loadmodule "enum"
+loadmodule "db_mysql"
+loadmodule "dialplan"
+loadmodule "sqlops"
+loadmodule "htable"
+loadmodule "rtimer"
+loadmodule "usrloc"
+loadmodule "registrar"
+loadmodule "pua"
+loadmodule "pua_reginfo"
+
+modparam("sqlops","sqlcon","sms=>mysql://root@localhost/smsc")
+modparam("dialplan|pua", "db_url", "mysql://root@localhost/kamailio")
+modparam("uac","restore_mode","none")
+modparam("enum", "domain_suffix", "DOMAIN.")
+
+modparam("htable", "htable", "publish_sent=>size=8;autoexpire=SUBSCRIBE_EXPIRE")
+
+# time interval set to 3 seconds
+modparam("rtimer", "timer", "name=sms;interval=3;mode=1;")
+modparam("rtimer", "exec", "timer=sms;route=SMS_WORKER")
+
+modparam("pua_reginfo", "server_address", "sip:reginfo@DOMAIN")
+modparam("pua_reginfo", "publish_reginfo", 0)
+
+####### Routing Logic ########
+# Main SIP request routing logic
+# - processing of any incoming SIP request starts with this route
+
+route {
+	xlog("L_DBG", "$rm ($fu ($si:$sp) to $tu, $ci)\n");
+
+	# per request initial checks
+	route(REQINIT);
+
+	if (is_method("NOTIFY")) {
+		route(NOTIFY);
+		send_reply("202", "Accepted");
+		exit;
+	}
+
+	if (!is_method("MESSAGE")) {
+		append_to_reply("Allow: MESSAGE,NOTIFY\r\n");
+		send_reply("405", "Method not allowed");
+		exit;
+	}
+
+	if ($cT == "application/vnd.3gpp.sms") {
+		route(SMS_FROM_3GPP);
+	} else if ($cT == "text/plain") {
+		route(SMS_FROM_SIP);
+	} else {
+		send_reply("488", "Content-Type not supported");
+		exit;
+	}
+}
+
+######################################################################
+# Helper routes (Basic-Checks, NAT-Handling/RTP-Control, XML-RPC)
+######################################################################
+# Per SIP request initial checks
+route[REQINIT] {
+	# Trace this message
+
+	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;
+	}
+
+	# Reply to OPTIONS:
+	if (is_method("OPTIONS") && (uri==myself)) {
+		options_reply();
+		exit;
+	}	
+
+	# Ignore Re-Transmits:
+	if (t_lookup_request()) {
+		exit;
+	}
+}
+
+######################################################################
+# SMS from VoLTE Handsets
+######################################################################
+route[SMS_FROM_3GPP] {
+#!ifdef WITH_DEBUG
+	xlog("3GPP-SMS: $rm ($fu ($si:$sp) to $tu, $ci)\n");
+	xlog("SMS for $tpdu(destination) \"$tpdu(payload)\" (Valid: $tpdu(validity) )\n");
+#!endif
+	send_reply("202", "Accepted");
+
+	if (isRPDATA()) {
+		$uac_req(method) = "MESSAGE";
+		$uac_req(ruri) = $ai;
+		$uac_req(furi) = $ai;
+		$uac_req(turi) = $ai;
+		$uac_req(hdrs) = "Content-Type: application/vnd.3gpp.sms\r\nRequest-Disposition: fork, parallel\r\nAccept-Contact: *;+g.3gpp.smsip;require;explicit\r\n";
+		$uac_req(body) = $smsack;
+		uac_req_send();
+
+
+		$avp(from) = $(ai{uri.user});
+		$avp(to) = $tpdu(destination);
+		# Translate "To":
+		dp_translate("1", "$avp(to)/$avp(to)");
+			
+		$avp(text) = $tpdu(payload);
+#!ifdef WITH_DEBUG
+		xlog("SMS from 3GPP/VoLTE\n");
+		xlog("-------------------------------------\n");
+		xlog("FROM $avp(from)\n");
+		xlog("TO   $avp(to)\n");
+		xlog("TEXT $avp(text)\n");
+#!endif
+		route(SMS);
+	}
+
+	exit;
+}
+
+######################################################################
+# SMS from OTT Handsets
+######################################################################
+route[SMS_FROM_SIP] {
+	send_reply("200", "OK");
+
+	$avp(from) = $(ai{uri.user});
+	# Translate "To":
+	$avp(to) = $tU;
+	dp_translate("1", "$avp(to)/$avp(to)");
+	$avp(text) = $rb;
+#!ifdef WITH_DEBUG
+	xlog("SMS from SIP/OTT\n");
+	xlog("-------------------------------------\n");
+	xlog("FROM $avp(from)\n");
+	xlog("TO   $avp(to)\n");
+	xlog("TEXT $avp(text)\n");
+#!endif
+	route(SMS);
+
+	exit;
+}
+
+
+######################################################################
+# SMS from other networks
+######################################################################
+event_route[xhttp:request] {
+	if ($(hu{url.querystring}{s.len}) > 0) {
+		$avp(from) = $(hu{url.querystring}{param.value,msisdn,&});
+		$avp(to) = $(hu{url.querystring}{param.value,to,&});
+		$avp(text) = $(hu{url.querystring}{param.value,text,&}{s.replace,+,%20}{s.unescape.user});
+		$avp(from_outbound) = 1;
+#!ifdef WITH_DEBUG
+		xlog("SMS from Outbound ($hu)\n");
+		xlog("-------------------------------------\n");
+		xlog("FROM $avp(from)\n");
+		xlog("TO   $avp(to)\n");
+		xlog("TEXT $avp(text)\n");
+#!endif
+	if ($avp(to) == "491771782261")
+		$avp(to) = "494046895124"; 
+	if ($avp(to) == "491771782319") 
+		$avp(to) = "494034927220";
+
+		route(SMS);
+	}
+
+	xhttp_reply("200", "OK", "text/html", "<html><body>OK - [$si:$sp]</body></html>");
+}
+
+######################################################################
+# SMS to VoLTE Handsets
+######################################################################
+route[SMS_TO_3GPP] {
+#!ifdef WITH_DEBUG
+	xlog("SMS to 3GPP/VoLTE\n");
+	xlog("-------------------------------------\n");
+	xlog("FROM $avp(from)\n");
+	xlog("TO   $avp(to)\n");
+	xlog("TEXT $avp(text)\n");
+#!endif
+
+	// Construct a new SMS-Body:
+	$rpdata(all) = $null;
+	$rpdata(type) = 1; // RP-DATA: Network to UE
+	$rpdata(reference) = $avp(id);
+	$rpdata(originator) = $avp(from);
+	$tpdu(type) = 4; // SMS-Deliver
+	$tpdu(origen) = $avp(from); // The Destination becomes the originator of the SMS
+	$tpdu(payload) = $avp(text);
+
+	$uac_req(method) = "MESSAGE";
+	$uac_req(ruri) = "sip:"+$avp(to)+"@"+DOMAIN;
+	$uac_req(furi) = "sip:"+$avp(to)+"@"+DOMAIN;
+	$uac_req(turi) = "sip:"+$avp(to)+"@"+DOMAIN;
+	$uac_req(hdrs) = "Content-Type: application/vnd.3gpp.sms\r\nRequest-Disposition: fork, parallel\r\nAccept-Contact: *;+g.3gpp.smsip;require;explicit\r\nX-MSG-ID: "+$avp(id)+"\r\n";
+	$uac_req(body) = $smsbody;
+	$uac_req(evroute)=1;
+	uac_req_send();
+	sql_query("sms", "delete from messages where id=$avp(id);");
+}
+
+######################################################################
+# SMS to OTT-Handsets
+######################################################################
+route[SMS_TO_SIP] {
+#!ifdef WITH_DEBUG
+	xlog("SMS to SIP/OTT\n");
+	xlog("-------------------------------------\n");
+	xlog("FROM $avp(from)\n");
+	xlog("TO   $avp(to)\n");
+	xlog("TEXT $avp(text)\n");
+#!endif
+
+	$uac_req(method) = "MESSAGE";
+	$uac_req(ruri) = "sip:"+$avp(to)+"@"+DOMAIN;
+	$uac_req(furi) = "sip:+"+$avp(from)+"@"+DOMAIN;
+	$uac_req(turi) = "sip:"+$avp(to)+"@"+DOMAIN;
+	$uac_req(hdrs) = "Content-Type: text/plain\r\nX-MSG-ID: "+$avp(id)+"\r\n";
+	$uac_req(evroute)=1;
+	$uac_req(body) = $avp(text);
+
+	uac_req_send();
+}
+
+######################################################################
+# SMS to Outbound
+######################################################################
+route[SMS_TO_OUTBOUND] {
+#!ifdef WITH_DEBUG
+	xlog("SMS to Outbound\n");
+	xlog("-------------------------------------\n");
+	xlog("FROM $avp(from)\n");
+	xlog("TO   $avp(to)\n");
+	xlog("TEXT $avp(text)\n");
+#!endif
+	if ($avp(from_outbound) == 1) {
+		xlog("Not sending: FROM and TO Outbound!\n");
+		return 1;
+		exit;
+	}
+	if ($avp(from) == "494046895124")
+		$avp(from) = "491771782261";
+	if ($avp(from) == "494034927220")
+		$avp(from) = "491771782319";
+
+	http_query("https://rest.nexmo.com/sms/json?api_key=NEXMO_APIKEY&api_secret=NEXMO_APISECRET&from=$avp(from)&to=$avp(to)&text=$(avp(text){s.escape.user})", "$var(result)");
+	if ($retcode != 200) return -1;
+	json_get_field("$var(result)", "messages", "$var(messages)");
+	json_get_field("$var(messages)", "status", "$var(status)");
+	if ($var(status) != 0) return -1;	
+	return 1;
+}
+
+######################################################################
+# SMS Handling
+######################################################################
+route[SMS] {
+#!ifdef WITH_DEBUG
+	xlog("SMS-Task\n");
+	xlog("-------------------------------------\n");
+	xlog("FROM $avp(from)\n");
+	xlog("TO   $avp(to)\n");
+	xlog("TEXT $avp(text)\n");
+#!endif
+
+	# Query ENUM: Local number?
+	$var(enum) = "+"+$avp(to);
+	if (!enum_pv_query("$var(enum)")) {
+		route(SMS_TO_OUTBOUND);
+		return $retcode;
+	}
+	if (sql_query("sms", "insert into messages (caller, callee, text, valid) values ('$(avp(from){s.escape.common})', '$(avp(to){s.escape.common})', '$(avp(text){s.escape.common})', now());"))
+		return 1;
+	else
+		return -1;
+}
+
+######################################################################
+# SMS Handling
+######################################################################
+route[SMS_WORKER] {
+	sql_query("sms", "select id, caller, callee, text from messages;", "q");
+	if ($dbr(q=>rows) > 0) {
+		$var(i) = 0;
+		while ($var(i) < $dbr(q=>rows)) {
+			$avp(id) = $dbr(q=>[$var(i),0]);
+			$avp(from) = $dbr(q=>[$var(i),1]);
+			$avp(to) = $dbr(q=>[$var(i),2]);
+			$avp(text) = $dbr(q=>[$var(i),3]);
+
+			route(SEND_SMS);
+#!ifdef WITH_DEBUG
+			xlog("ID   $avp(id)\n");
+			xlog("FROM $avp(from)\n");
+			xlog("TO   $avp(to)\n");
+			xlog("TEXT $avp(text)\n");
+#!endif
+			$var(i) = $var(i) + 1;
+		}
+	}
+	sql_result_free("q");
+}
+
+route[NOTIFY] {
+	if (has_body("application/reginfo+xml")) {
+		if (reginfo_handle_notify("location"))
+			send_reply("202", "Accepted");
+	} else {
+		send_reply("503", "Invalid Content-Type");
+	}
+	exit;
+}
+
+route[SEND_SMS] {
+	$var(uri) = "sip:"+$avp(to)+"@"+DOMAIN;
+	
+	if (reg_fetch_contacts("location", "$var(uri)", "caller")) {
+		$var(j) = 0;
+		$var(is3gpp) = 0;
+		while($var(j) < $(ulc(caller=>count))) {
+			$var(k) = 0;
+			while($var(k) < $(ulc(caller=>addr)[$var(j)]{param.count})) {
+				if ($(ulc(caller=>addr)[$var(j)]{param.name,$var(k)}) == "+g.3gpp.smsip")
+					$var(is3gpp) = 1;
+				$var(k) = $var(k) + 1;
+			}
+			if ($var(is3gpp) == 1)
+				route(SMS_TO_3GPP);
+			else
+				route(SMS_TO_SIP);		
+			$var(j) = $var(j) + 1;
+		}
+	} else {
+		if ($sht(publish_sent=>$var(uri)) == $null) {
+			reginfo_subscribe("$var(uri)", "SUBSCRIBE_EXPIRE");
+			$sht(publish_sent=>$var(uri)) = 1;
+		}
+	}
+}
+
+event_route [tm:local-request] {
+	if (is_method("SUBSCRIBE")) {
+		append_hf("P-Asserted-Identity: $ru\r\n");
+	}
+}
+
+event_route[uac:reply] {
+	if (($uac_req(evtype) == 1) && ($uac_req(evcode) == 200)) {
+		$var(msgid) = $(uac_req(hdrs){line.sw,X-MSG-ID:}{s.substr,10,0}{s.int});
+		sql_query("sms", "delete from messages where id=$var(msgid);");
+	}
+}
+

+ 8 - 0
modules/smsops/examples/smsc.cfg

@@ -0,0 +1,8 @@
+listen=udp:127.0.0.1:5060
+listen=tcp:127.0.0.1:80
+
+#!substdef "/DOMAIN/ims.mnc001.mcc001.3gppnetwork.org/"
+#!substdef "/SERVER/smsc.ims.mnc001.mcc001.3gppnetwork.org/"
+#!subst "/NEXMO_APIKEY/abcdef/"
+#!subst "/NEXMO_APISECRET/xyz/"
+#!subst "/SUBSCRIBE_EXPIRE/7200/"