SMS related additions

This commit is contained in:
herlesupreeth
2022-02-10 06:53:02 +01:00
parent 114afb8726
commit e7a89c0e66
14 changed files with 579 additions and 4 deletions

3
.env
View File

@@ -104,3 +104,6 @@ OSMOMSC_IP=172.22.0.31
# OSMOHLR # OSMOHLR
OSMOHLR_IP=172.22.0.32 OSMOHLR_IP=172.22.0.32
# SMSC
SMSC_IP=172.22.0.33

View File

@@ -29,6 +29,7 @@
cp /mnt/dns/epc_zone /etc/bind cp /mnt/dns/epc_zone /etc/bind
cp /mnt/dns/ims_zone /etc/bind cp /mnt/dns/ims_zone /etc/bind
cp /mnt/dns/pub_3gpp_zone /etc/bind cp /mnt/dns/pub_3gpp_zone /etc/bind
cp /mnt/dns/e164.arpa /etc/bind
cp /mnt/dns/named.conf /etc/bind cp /mnt/dns/named.conf /etc/bind
[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" [ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org"
@@ -45,11 +46,15 @@ sed -i 's|PCSCF_IP|'$PCSCF_IP'|g' /etc/bind/ims_zone
sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' /etc/bind/ims_zone sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' /etc/bind/ims_zone
sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/bind/ims_zone sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/bind/ims_zone
sed -i 's|FHOSS_IP|'$FHOSS_IP'|g' /etc/bind/ims_zone sed -i 's|FHOSS_IP|'$FHOSS_IP'|g' /etc/bind/ims_zone
sed -i 's|SMSC_IP|'$SMSC_IP'|g' /etc/bind/ims_zone
sed -i 's|PUB_3GPP_DOMAIN|'$PUB_3GPP_DOMAIN'|g' /etc/bind/pub_3gpp_zone sed -i 's|PUB_3GPP_DOMAIN|'$PUB_3GPP_DOMAIN'|g' /etc/bind/pub_3gpp_zone
sed -i 's|DNS_IP|'$DNS_IP'|g' /etc/bind/pub_3gpp_zone sed -i 's|DNS_IP|'$DNS_IP'|g' /etc/bind/pub_3gpp_zone
sed -i 's|ENTITLEMENT_SERVER_IP|'$ENTITLEMENT_SERVER_IP'|g' /etc/bind/pub_3gpp_zone sed -i 's|ENTITLEMENT_SERVER_IP|'$ENTITLEMENT_SERVER_IP'|g' /etc/bind/pub_3gpp_zone
sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/bind/e164.arpa
sed -i 's|DNS_IP|'$DNS_IP'|g' /etc/bind/e164.arpa
sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/bind/named.conf sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/bind/named.conf
sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/bind/named.conf sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/bind/named.conf
sed -i 's|PUB_3GPP_DOMAIN|'$PUB_3GPP_DOMAIN'|g' /etc/bind/named.conf sed -i 's|PUB_3GPP_DOMAIN|'$PUB_3GPP_DOMAIN'|g' /etc/bind/named.conf

14
dns/e164.arpa Normal file
View File

@@ -0,0 +1,14 @@
$TTL 1h
@ IN SOA ns.e164.arpa. root.e164.arpa. (
2009010918 ;serial
3600 ;refresh
3600 ;retry
3600 ;expire
3600 ;minimum TTL
)
@ IN NS e164.arpa.
@ IN A DNS_IP
; Wildcard to match any tel:+xxxx and change to sip:xxxx@IMS_DOMAIN
* IN NAPTR 10 100 "u" "E2U+sip" "!(^.*$)!sip:\\1@IMS_DOMAIN!" .
* IN NAPTR 20 100 "u" "E2U+sip" "!(^.*$)!sip:+\\1@IMS_DOMAIN!" .

View File

@@ -23,3 +23,7 @@ _sip._udp.scscf 1D SRV 0 0 6060 scscf
_sip._tcp.scscf 1D SRV 0 0 6060 scscf _sip._tcp.scscf 1D SRV 0 0 6060 scscf
hss 1D IN A FHOSS_IP hss 1D IN A FHOSS_IP
smsc 1D IN A SMSC_IP
_sip._udp.smsc 1D SRV 0 0 7060 smsc
_sip._tcp.smsc 1D SRV 0 0 7060 smsc

View File

@@ -46,3 +46,8 @@ zone "PUB_3GPP_DOMAIN" {
type master; type master;
file "/etc/bind/pub_3gpp_zone"; file "/etc/bind/pub_3gpp_zone";
}; };
zone "e164.arpa" {
type master;
file "/etc/bind/e164.arpa";
};

View File

@@ -554,6 +554,27 @@ services:
networks: networks:
default: default:
ipv4_address: ${PCSCF_IP} ipv4_address: ${PCSCF_IP}
smsc:
image: docker_kamailio
container_name: smsc
dns: ${DNS_IP}
volumes:
- ./smsc:/mnt/smsc
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
env_file:
- .env
environment:
- COMPONENT_NAME=smsc-1
depends_on:
- dns
- mysql
expose:
- "7060/udp"
- "7060/tcp"
networks:
default:
ipv4_address: ${SMSC_IP}
osmomsc: osmomsc:
build: ./osmomsc build: ./osmomsc
image: docker_osmomsc image: docker_osmomsc

View File

@@ -252,6 +252,13 @@ route{
route(register); route(register);
} }
if (is_method("NOTIFY") && search("^(Event|o)([ \t]*):([ \t]*)reg")) {
if (!t_relay()) {
sl_reply_error();
}
exit;
}
if (is_method("INVITE|SUBSCRIBE|MESSAGE|INFO|PUBLISH|CANCEL")) { if (is_method("INVITE|SUBSCRIBE|MESSAGE|INFO|PUBLISH|CANCEL")) {
route(initial_request); route(initial_request);
} else { } else {

View File

@@ -33,7 +33,7 @@ RUN apt-get update && \
apt-get -y install mysql-server tcpdump screen tmux ntp ntpdate git-core dkms \ apt-get -y install mysql-server tcpdump screen tmux ntp ntpdate git-core dkms \
gcc flex bison libmysqlclient-dev make libssl-dev libcurl4-openssl-dev \ gcc flex bison libmysqlclient-dev make libssl-dev libcurl4-openssl-dev \
libxml2-dev libpcre3-dev bash-completion g++ autoconf libmnl-dev \ libxml2-dev libpcre3-dev bash-completion g++ autoconf libmnl-dev \
libsctp-dev libradcli-dev libradcli4 iproute2 net-tools \ libsctp-dev libradcli-dev libradcli4 libjson-c-dev pkg-config iproute2 net-tools \
iputils-ping iputils-ping
# Fetch Kamailio code (branch 5.3) # Fetch Kamailio code (branch 5.3)

View File

@@ -43,6 +43,11 @@ elif [[ "$COMPONENT_NAME" =~ ^(pcscf-[[:digit:]]+$) ]]; then
/mnt/pcscf/pcscf_init.sh && \ /mnt/pcscf/pcscf_init.sh && \
mkdir -p /var/run/kamailio_pcscf && \ mkdir -p /var/run/kamailio_pcscf && \
kamailio -f /etc/kamailio_pcscf/kamailio_pcscf.cfg -P /kamailio_pcscf.pid -DD -E -e kamailio -f /etc/kamailio_pcscf/kamailio_pcscf.cfg -P /kamailio_pcscf.pid -DD -E -e
elif [[ "$COMPONENT_NAME" =~ ^(smsc-[[:digit:]]+$) ]]; then
echo "Deploying component: '$COMPONENT_NAME'"
/mnt/smsc/smsc_init.sh && \
mkdir -p /var/run/kamailio_smsc && \
kamailio -f /etc/kamailio_smsc/kamailio_smsc.cfg -P /kamailio_smsc.pid -DD -E -e
else else
echo "Error: Invalid component name: '$COMPONENT_NAME'" echo "Error: Invalid component name: '$COMPONENT_NAME'"
fi fi

View File

@@ -7,7 +7,7 @@ modules_dirs:=modules
cfg_group_include= cfg_group_include=
# the list of extra modules to compile # the list of extra modules to compile
include_modules= cdp cdp_avp db_mysql dialplan ims_auth ims_charging ims_dialog ims_diameter_server ims_icscf ims_ipsec_pcscf ims_isc ims_ocs ims_qos ims_registrar_pcscf ims_registrar_scscf ims_usrloc_pcscf ims_usrloc_scscf outbound presence presence_conference presence_dialoginfo presence_mwi presence_profile presence_reginfo presence_xml pua pua_bla pua_dialoginfo pua_reginfo pua_rpc pua_usrloc pua_xmpp sctp tls utils xcap_client xcap_server xmlops xmlrpc include_modules= cdp cdp_avp db_mysql dialplan enum json http_client ims_auth ims_charging ims_dialog ims_diameter_server ims_icscf ims_ipsec_pcscf ims_isc ims_ocs ims_qos ims_registrar_pcscf ims_registrar_scscf ims_usrloc_pcscf ims_usrloc_scscf outbound presence presence_conference presence_dialoginfo presence_mwi presence_profile presence_reginfo presence_xml pua pua_bla pua_dialoginfo pua_reginfo pua_rpc pua_usrloc pua_xmpp sctp tls utils xcap_client xcap_server xmlops xmlrpc
# the list of static modules # the list of static modules
static_modules= static_modules=
@@ -16,7 +16,7 @@ static_modules=
skip_modules= skip_modules=
# the list of modules to exclude from compile list # the list of modules to exclude from compile list
exclude_modules= acc_json acc_radius app_java app_lua app_lua_sr app_mono app_perl app_python app_python3 app_ruby auth_ephemeral auth_identity auth_radius cnxcc cplc crypto db2_ldap db_berkeley db_cassandra db_mongodb db_oracle db_perlvdb db_postgres db_redis db_sqlite db_unixodbc dnssec erlang evapi geoip geoip2 gzcompress h350 http_async_client http_client jansson janssonrpcc json jsonrpcc jwt kafka kazoo lcr ldap log_systemd lost lwsc memcached misc_radius ndb_cassandra mqtt ndb_mongodb ndb_redis nsq osp peering phonenum pua_json rabbitmq regex rls rtp_media_server secsipid secsipid_proc snmpstats stirshaken systemdops topos_redis uuid websocket xhttp_pi xmpp $(skip_modules) exclude_modules= acc_json acc_radius app_java app_lua app_lua_sr app_mono app_perl app_python app_python3 app_ruby auth_ephemeral auth_identity auth_radius cnxcc cplc crypto db2_ldap db_berkeley db_cassandra db_mongodb db_oracle db_perlvdb db_postgres db_redis db_sqlite db_unixodbc dnssec erlang evapi geoip geoip2 gzcompress h350 http_async_client jansson janssonrpcc jsonrpcc jwt kafka kazoo lcr ldap log_systemd lost lwsc memcached misc_radius ndb_cassandra mqtt ndb_mongodb ndb_redis nsq osp peering phonenum pua_json rabbitmq regex rls rtp_media_server secsipid secsipid_proc snmpstats stirshaken systemdops topos_redis uuid websocket xhttp_pi xmpp $(skip_modules)
modules_all= $(filter-out modules/CVS,$(wildcard modules/*)) modules_all= $(filter-out modules/CVS,$(wildcard modules/*))
modules_noinc= $(filter-out $(addprefix modules/, $(exclude_modules) $(static_modules)), $(modules_all)) modules_noinc= $(filter-out $(addprefix modules/, $(exclude_modules) $(static_modules)), $(modules_all))

418
smsc/kamailio_smsc.cfg Normal file
View File

@@ -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: <sr-users@lists.kamailio.org>.
#
# 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=SMSC_SERVER
# ------------------ module loading ----------------------------------
mpath="/usr/lib64/kamailio/modules_k/:/usr/lib64/kamailio/modules/:/usr/lib/kamailio/modules_k/:/usr/lib/kamailio/modules/:/usr/lib/x86_64-linux-gnu/kamailio/modules/:/usr/local/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 "http_client"
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_DB_URL)
modparam("dialplan|pua", "db_url", DIALPLAN_PUA_DB_URL)
modparam("uac", "restore_mode", "none")
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:SMSC_SERVER")
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) = "sip:"+SMSC_SERVER;
$uac_req(turi) = $ai;
$uac_req(hdrs) = "Content-Type: application/vnd.3gpp.sms\r\nRequest-Disposition: no-fork\r\nAccept-Contact: *;+g.3gpp.smsip\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:"+SMSC_SERVER;
$uac_req(turi) = "sip:"+$avp(to)+"@"+DOMAIN;
$uac_req(hdrs) = "Content-Type: application/vnd.3gpp.sms\r\nRequest-Disposition: no-fork\r\nAccept-Contact: *;+g.3gpp.smsip\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_client_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);");
}
}

9
smsc/smsc-create.sql Normal file
View File

@@ -0,0 +1,9 @@
CREATE TABLE `messages` (
`id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
`caller` VARCHAR(255) NOT NULL,
`callee` VARCHAR(255) NOT NULL,
`text` VARCHAR(512),
`valid` datetime NOT NULL
);
INSERT INTO version (table_name, table_version) values ('messages','1');

17
smsc/smsc.cfg Normal file
View File

@@ -0,0 +1,17 @@
listen=udp:SMSC_IP:7060
listen=tcp:SMSC_IP:7060
#!define DOMAIN "IMS_DOMAIN"
#!subst "/DOMAIN/IMS_DOMAIN/"
#!define SMSC_SERVER "smsc.IMS_DOMAIN"
#!subst "/SMSC_SERVER/smsc.IMS_DOMAIN/"
# Connection URL for the database:
#!define SMS_DB_URL "sms=>mysql://smsc:heslo@MYSQL_IP/smsc"
#!define DIALPLAN_PUA_DB_URL "mysql://smsc:heslo@MYSQL_IP/smsc"
#!subst "/NEXMO_APIKEY/abcdef/"
#!subst "/NEXMO_APISECRET/xyz/"
#!subst "/SUBSCRIBE_EXPIRE/7200/"
#!define WITH_DEBUG

67
smsc/smsc_init.sh Executable file
View File

@@ -0,0 +1,67 @@
#!/bin/bash
# BSD 2-Clause License
# Copyright (c) 2020, Supreeth Herle
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org"
mkdir -p /etc/kamailio_smsc
cp /mnt/smsc/smsc.cfg /etc/kamailio_smsc
cp /mnt/smsc/kamailio_smsc.cfg /etc/kamailio_smsc
while ! mysqladmin ping -h ${MYSQL_IP} --silent; do
sleep 5;
done
# Sleep until permissions are set
sleep 10;
# Create SMSC database, populate tables and grant privileges
if [[ -z "`mysql -u root -h ${MYSQL_IP} -qfsBe "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='smsc'" 2>&1`" ]];
then
mysql -u root -h ${MYSQL_IP} -e "create database smsc;"
mysql -u root -h ${MYSQL_IP} smsc < /usr/local/src/kamailio/utils/kamctl/mysql/standard-create.sql
mysql -u root -h ${MYSQL_IP} smsc < /mnt/smsc/smsc-create.sql
mysql -u root -h ${MYSQL_IP} smsc < /usr/local/src/kamailio/utils/kamctl/mysql/dialplan-create.sql
mysql -u root -h ${MYSQL_IP} smsc < /usr/local/src/kamailio/utils/kamctl/mysql/presence-create.sql
SMSC_USER_EXISTS=`mysql -u root -h ${MYSQL_IP} -s -N -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE User = 'smsc' AND Host = '%')"`
if [[ "$SMSC_USER_EXISTS" == 0 ]]
then
mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'smsc'@'%' IDENTIFIED WITH mysql_native_password BY 'heslo'";
mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'smsc'@'$SMSC_IP' IDENTIFIED WITH mysql_native_password BY 'heslo'";
mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON smsc.* TO 'smsc'@'%'";
mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON smsc.* TO 'smsc'@'$SMSC_IP'";
mysql -u root -h ${MYSQL_IP} -e "FLUSH PRIVILEGES;"
fi
fi
sed -i 's|SMSC_IP|'$SMSC_IP'|g' /etc/kamailio_smsc/smsc.cfg
sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/kamailio_smsc/smsc.cfg
sed -i 's|MYSQL_IP|'$MYSQL_IP'|g' /etc/kamailio_smsc/smsc.cfg
# Sync docker time
#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone