SMS related additions
This commit is contained in:
3
.env
3
.env
@@ -104,3 +104,6 @@ OSMOMSC_IP=172.22.0.31
|
||||
|
||||
# OSMOHLR
|
||||
OSMOHLR_IP=172.22.0.32
|
||||
|
||||
# SMSC
|
||||
SMSC_IP=172.22.0.33
|
||||
|
@@ -29,6 +29,7 @@
|
||||
cp /mnt/dns/epc_zone /etc/bind
|
||||
cp /mnt/dns/ims_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
|
||||
|
||||
[ ${#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|SCSCF_IP|'$SCSCF_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|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|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|IMS_DOMAIN|'$IMS_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
14
dns/e164.arpa
Normal 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!" .
|
@@ -23,3 +23,7 @@ _sip._udp.scscf 1D SRV 0 0 6060 scscf
|
||||
_sip._tcp.scscf 1D SRV 0 0 6060 scscf
|
||||
|
||||
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
|
||||
|
@@ -46,3 +46,8 @@ zone "PUB_3GPP_DOMAIN" {
|
||||
type master;
|
||||
file "/etc/bind/pub_3gpp_zone";
|
||||
};
|
||||
|
||||
zone "e164.arpa" {
|
||||
type master;
|
||||
file "/etc/bind/e164.arpa";
|
||||
};
|
||||
|
@@ -554,6 +554,27 @@ services:
|
||||
networks:
|
||||
default:
|
||||
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:
|
||||
build: ./osmomsc
|
||||
image: docker_osmomsc
|
||||
|
@@ -252,6 +252,13 @@ route{
|
||||
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")) {
|
||||
route(initial_request);
|
||||
} else {
|
||||
|
@@ -33,7 +33,7 @@ RUN apt-get update && \
|
||||
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 \
|
||||
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
|
||||
|
||||
# Fetch Kamailio code (branch 5.3)
|
||||
|
@@ -43,6 +43,11 @@ elif [[ "$COMPONENT_NAME" =~ ^(pcscf-[[:digit:]]+$) ]]; then
|
||||
/mnt/pcscf/pcscf_init.sh && \
|
||||
mkdir -p /var/run/kamailio_pcscf && \
|
||||
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
|
||||
echo "Error: Invalid component name: '$COMPONENT_NAME'"
|
||||
fi
|
||||
fi
|
||||
|
@@ -7,7 +7,7 @@ modules_dirs:=modules
|
||||
cfg_group_include=
|
||||
|
||||
# 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
|
||||
static_modules=
|
||||
@@ -16,7 +16,7 @@ static_modules=
|
||||
skip_modules=
|
||||
|
||||
# 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_noinc= $(filter-out $(addprefix modules/, $(exclude_modules) $(static_modules)), $(modules_all))
|
||||
|
418
smsc/kamailio_smsc.cfg
Normal file
418
smsc/kamailio_smsc.cfg
Normal 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
9
smsc/smsc-create.sql
Normal 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
17
smsc/smsc.cfg
Normal 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
67
smsc/smsc_init.sh
Executable 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
|
Reference in New Issue
Block a user