mirror of https://github.com/PentHertz/smqueue.git
merged in commercial smqueue
This commit is contained in:
parent
db01753ed4
commit
6914eeca7e
|
@ -10,3 +10,7 @@
|
|||
path = sqlite3
|
||||
url = git@github.com:RangeNetworks/sqlite3.git
|
||||
branch = master
|
||||
[submodule "NodeManager"]
|
||||
path = NodeManager
|
||||
url = git@github.com:RangeNetworks/NodeManager.git
|
||||
branch = 4.0
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit bd94d0a9883002daa8310b601f28eed3b0d87d2f
|
||||
Subproject commit abec8dabb69f8f2bdefdb9bcca340b89f43ce419
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011 Range Networks, Inc.
|
||||
* Copyright 2011, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
* Copyright 2010 Kestrel Signal Processing, Inc.
|
||||
* Copyright 2011 Range Networks, Inc.
|
||||
* Copyright 2011, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
@brief Call Control messages, GSM 04.08 9.3
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008, 2009 Free Software Foundation, Inc.
|
||||
* Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
|
||||
*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**@file Elements for Call Control, GSM 04.08 10.5.4. */
|
||||
/*
|
||||
* Copyright 2008, 2009 Free Software Foundation, Inc.
|
||||
* Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
|
||||
*
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
@brief Elements for Mobility Management messages, GSM 04.08 9.2.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2008, 2014 Free Software Foundation, Inc.
|
||||
* Copyright 2010 Kestrel Signal Processing, Inc.
|
||||
*
|
||||
* Copyright 2014 Range Networks, Inc.
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
/*
|
||||
* Copyright 2008-2010 Free Software Foundation, Inc.
|
||||
* Copyright 2010 Kestrel Signal Processing, Inc.
|
||||
* Copyright 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
* Copyright 2008, 2009, 2010, 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008, 2010 Free Software Foundation, Inc.
|
||||
* Copyright 2008, 2010, 2014 Free Software Foundation, Inc.
|
||||
* Copyright 2010 Kestrel Signal Processing, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2008, 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2008, 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
|
||||
*
|
||||
|
@ -387,7 +387,7 @@ class L2Frame : public BitVector {
|
|||
bool M() const { return mStart[8*2+6] & 0x01; }
|
||||
|
||||
/** Return the L3 payload part. Assumes A or B header format. */
|
||||
BitVector L3Part() const { return segment(8*3,8*L()); }
|
||||
BitVector L3Part() const { return cloneSegment(8*3,8*L()); }
|
||||
|
||||
/** Return NR sequence number, GSM 04.06 3.5.2.4. Assumes A or B header. */
|
||||
unsigned NR() const { return peekField(8*1+0,3); }
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
* Copyright 2010 Kestrel Signal Processing, Inc.
|
||||
* Copyright 2011 Range Networks, Inc.
|
||||
* Copyright 2011, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**@file Global system parameters. */
|
||||
/*
|
||||
* Copyright 2008, 2009 Free Software Foundation, Inc.
|
||||
* Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
|
||||
* Copyright 2011 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
|
|
|
@ -30,11 +30,11 @@ SUBDIRS = \
|
|||
sqlite3 \
|
||||
CommonLibs \
|
||||
Globals \
|
||||
SR \
|
||||
GSM \
|
||||
SMS \
|
||||
doc \
|
||||
tools \
|
||||
NodeManager \
|
||||
smqueue \
|
||||
testing
|
||||
|
||||
|
|
|
@ -24,23 +24,28 @@ SMS_INCLUDEDIR = $(top_srcdir)/SMS
|
|||
GLOBALS_INCLUDEDIR = $(top_srcdir)/Globals
|
||||
SQLITE_INCLUDEDIR = $(top_srcdir)/sqlite3
|
||||
SR_INCLUDEDIR = $(top_srcdir)/SR
|
||||
NODEMANAGER_INCLUDEDIR = $(top_srcdir)/NodeManager
|
||||
JSONBOX_INCLUDEDIR = $(top_srcdir)/NodeManager/JsonBox-0.4.3/include
|
||||
|
||||
SVNDEV = -D'SVN_REV="$(shell svnversion -n $(top_builddir))"'
|
||||
SVNDEV = -D'SVN_REV="$(shell svn info $(top_builddir) | grep "Last Changed Rev:" | cut -d " " -f 4) CommonLibs:rev$(shell svn info $(top_builddir)/CommonLibs | grep "Last Changed Rev:" | cut -d " " -f 4)"'
|
||||
|
||||
STD_DEFINES_AND_INCLUDES = \
|
||||
$(SVNDEV) \
|
||||
-DSR_API_ONLY \
|
||||
-I$(COMMON_INCLUDEDIR) \
|
||||
-I$(GSM_INCLUDEDIR) \
|
||||
-I$(SMS_INCLUDEDIR) \
|
||||
-I$(GLOBALS_INCLUDEDIR) \
|
||||
-I$(SR_INCLUDEDIR) \
|
||||
-I$(NODEMANAGER_INCLUDEDIR) \
|
||||
-I$(JSONBOX_INCLUDEDIR) \
|
||||
-I$(SQLITE_INCLUDEDIR)
|
||||
|
||||
COMMON_LA = $(top_builddir)/CommonLibs/libcommon.la
|
||||
GSM_LA = $(top_builddir)/GSM/libGSM.la
|
||||
SMS_LA = $(top_builddir)/SMS/libSMS.la
|
||||
GLOBALS_LA = $(top_builddir)/Globals/libglobals.la
|
||||
SR_LA = $(top_builddir)/SR/libSR.la
|
||||
NODEMANAGER_LA = $(top_builddir)/NodeManager/libnodemanager.la -lzmq
|
||||
SQLITE_LA = $(top_builddir)/sqlite3/libsqlite.la -ldl
|
||||
|
||||
MOSTLYCLEANFILES = *~
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit c154368a55d081d7be241a14825e9a009dee093a
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
* Copyright 2008, 2009, 2010, 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
|
@ -589,7 +589,7 @@ void TLUserData::parse(const TLFrame& src, size_t& rp)
|
|||
mLength = src.readField(rp,8);
|
||||
#if 1
|
||||
// This tail() works because UD is always the last field in the PDU.
|
||||
mRawData.clone(src.tail(rp));
|
||||
mRawData.clone(src.alias().tail(rp));
|
||||
// Should we do this here?
|
||||
mRawData.LSB8MSB();
|
||||
#else
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2008, 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
|
@ -734,7 +734,7 @@ class CPUserData : public GSM::L3ProtocolElement {
|
|||
|
||||
CPUserData(const RPMessage& RPM)
|
||||
:L3ProtocolElement(),
|
||||
mRPDU(RPM.bitsNeeded())
|
||||
mRPDU(BitVector(RPM.bitsNeeded()))
|
||||
{
|
||||
RPM.write(mRPDU);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2008, 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2008, 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
|
|
2
SR
2
SR
|
@ -1 +1 @@
|
|||
Subproject commit 226fc1c28a82307f7fc0e3f99f47a025be7cae4c
|
||||
Subproject commit 25e81ce18e371cc7e8641dd4bab90a7ff4973484
|
18
configure.ac
18
configure.ac
|
@ -18,7 +18,7 @@ dnl You should have received a copy of the GNU General Public License
|
|||
dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
dnl
|
||||
|
||||
AC_INIT(smqueue,TRUNK)
|
||||
AC_INIT(smqueue,4.0TRUNK)
|
||||
AC_PREREQ(2.57)
|
||||
AC_CONFIG_SRCDIR([config/Makefile.am])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
|
@ -54,6 +54,20 @@ AC_TYPE_SIZE_T
|
|||
AC_HEADER_TIME
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
dnl Check for libzmq
|
||||
if test ! -r "/usr/include/zmq.h" -a ! -r "/usr/local/include/zmq.h"; then
|
||||
AC_MSG_ERROR([/usr/local/include/zmq.h not found. Install the range-libzmq package or manually build and install with $ sudo ./NodeManager/install_libzmq.sh])
|
||||
fi
|
||||
if test ! -r "/usr/include/zmq.hpp" -a ! -r "/usr/local/include/zmq.hpp"; then
|
||||
AC_MSG_ERROR([/usr/local/include/zmq.hpp not found. Install the range-libzmq package or manually build and install with $ sudo ./NodeManager/install_libzmq.sh])
|
||||
fi
|
||||
AC_CHECK_LIB(zmq, zmq_init, ,[AC_MSG_ERROR([Cannot link with -lzmq. Install the range-libzmq package or manually build and install with $ sudo ./NodeManager/install_libzmq.sh])])
|
||||
AC_MSG_CHECKING([whether libzmq installation works])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <zmq.h>],
|
||||
[zmq_init(1);])
|
||||
],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_ERROR([no. Install the range-libzmq package or manually build and install with $ sudo ./NodeManager/install_libzmq.sh])])
|
||||
|
||||
# Defines OSIP_CFLAGS, OSIP_INCLUDEDIR, and OSIP_LIBS
|
||||
PKG_CHECK_MODULES(OSIP, libosip2)
|
||||
|
@ -72,7 +86,7 @@ AC_CONFIG_FILES([\
|
|||
Globals/Makefile \
|
||||
GSM/Makefile \
|
||||
SMS/Makefile \
|
||||
SR/Makefile \
|
||||
NodeManager/Makefile \
|
||||
sqlite3/Makefile \
|
||||
smqueue/Makefile \
|
||||
testing/Makefile \
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
smqueue-public (3.2) UNRELEASED; urgency=low
|
||||
|
||||
* Public release
|
||||
|
||||
-- Kurtis <kheimerl@rangenetworks.com> Thu, 01 Aug 2013 16:13:52 -0700
|
||||
|
||||
smqueue-public (3.2) UNRELEASED; urgency=low
|
||||
smqueue (4.0) untested; urgency=low
|
||||
|
||||
* Test
|
||||
|
||||
-- Donald C. Kirker <donald.kirker@rangenetworks.com> Mon, 22 Apr 2013 00:11:00 -0700
|
||||
-- Donald C. Kirker <donald.kirker@rangenetworks.com> Mon, 22 Apr 2013 00:11:00 -0700
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
1
|
|
@ -1,19 +1,16 @@
|
|||
Source: smqueue-public
|
||||
Provides: smqueue
|
||||
Source: smqueue
|
||||
Section: comm
|
||||
Priority: optional
|
||||
Maintainer: Range Networks, Inc. <info@rangenetworks.com>
|
||||
Homepage: http://www.rangenetworks.com/
|
||||
Build-Depends: build-essential, debhelper (>= 7), libosip2-dev, pkg-config, autoconf
|
||||
Build-Depends: build-essential, debhelper (>= 7), libosip2-dev, pkg-config, autoconf, libtool
|
||||
Standards-Version: 3.7.3
|
||||
|
||||
Package: smqueue-public
|
||||
Provides: smqueue
|
||||
Version: TRUNK
|
||||
Package: smqueue
|
||||
Section: comm
|
||||
Priority: optional
|
||||
Architecture: any
|
||||
Architecture: i386
|
||||
Essential: no
|
||||
Depends: sqlite, sqlite3 (>= 3.7), libosip2-4, libglib2.0-0, libgl1-mesa-glx, libc6, libasound2, pkg-config, libpcre3, gawk, screen
|
||||
Description: OpenBTS Public software.
|
||||
Depends: sqlite3, libosip2-4, libc6-i686, pkg-config, range-libzmq
|
||||
Description: Range Networks - SMQueue RFC-3428 Store and Forward Server
|
||||
|
||||
|
|
|
@ -19,15 +19,19 @@ set -e
|
|||
|
||||
configure()
|
||||
{
|
||||
DB_LOC=/etc/OpenBTS/smqueue.db
|
||||
DATE=$(date +'%Y-%m-%d.%H:%M:%S')
|
||||
CONFIG_BACKUP=$DB_LOC.dump-$DATE
|
||||
DATE=$(date --rfc-3339='date')
|
||||
CONFIG_BACKUP=/etc/OpenBTS/smqueue.dump-$DATE
|
||||
|
||||
if [ ! -e $DB_LOC ]; then
|
||||
sqlite3 $DB_LOC ".dump" > $CONFIG_BACKUP
|
||||
|
||||
if [ ! -e $CONFIG_BACKUP ]; then
|
||||
sqlite3 /etc/OpenBTS/smqueue.db ".dump" > $CONFIG_BACKUP
|
||||
fi
|
||||
|
||||
sqlite3 $DB_LOC ".read /etc/OpenBTS/smqueue.example.sql" &>/dev/null
|
||||
sqlite3 /etc/OpenBTS/smqueue.db ".read /etc/OpenBTS/smqueue.example.sql" &>/dev/null
|
||||
|
||||
if [ ! -e /var/lib/OpenBTS ]; then
|
||||
mkdir /var/lib/OpenBTS
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -16,20 +16,14 @@ set -e
|
|||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
APP=smqueue
|
||||
|
||||
remove()
|
||||
{
|
||||
if [ "$(pidof $APP)" ]; then
|
||||
killall $APP
|
||||
else
|
||||
echo "$APP not running"
|
||||
fi
|
||||
}
|
||||
# remove()
|
||||
# {
|
||||
# killall runloop.smqueue.sh &>/dev/null
|
||||
# }
|
||||
|
||||
case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
remove
|
||||
# remove
|
||||
;;
|
||||
|
||||
failed-upgrade)
|
||||
|
@ -44,6 +38,6 @@ esac
|
|||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -108,7 +108,7 @@ binary-common:
|
|||
# dh_perl
|
||||
dh_makeshlibs
|
||||
dh_installdeb
|
||||
dh_shlibdeps
|
||||
dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
|
74
depcomp
74
depcomp
|
@ -1,10 +1,10 @@
|
|||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2009-04-28.21; # UTC
|
||||
scriptversion=2011-12-04.11; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
|
||||
# Software Foundation, Inc.
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
|
||||
# 2011 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -44,7 +44,7 @@ Environment variables:
|
|||
object Object file output by `PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputing dependencies.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
|
@ -90,10 +90,18 @@ if test "$depmode" = msvcmsys; then
|
|||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u="sed s,\\\\\\\\,/,g"
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
|
@ -158,10 +166,12 @@ gcc)
|
|||
' < "$tmpdepfile" |
|
||||
## Some versions of gcc put a space before the `:'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well.
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
|
@ -405,6 +415,52 @@ tru64)
|
|||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test "$stat" = 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/ \1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/ /
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
@ -503,7 +559,9 @@ makedepend)
|
|||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
sed '1,2d' "$tmpdepfile" | tr ' ' '
|
||||
' | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
|
|
29
install-sh
29
install-sh
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2009-04-28.21; # UTC
|
||||
scriptversion=2011-01-19.21; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
|
@ -156,6 +156,10 @@ while test $# -ne 0; do
|
|||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t) dst_arg=$2
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) no_target_directory=true;;
|
||||
|
@ -186,6 +190,10 @@ if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
|||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
|
@ -200,7 +208,11 @@ if test $# -eq 0; then
|
|||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
|
@ -228,9 +240,9 @@ fi
|
|||
|
||||
for src
|
||||
do
|
||||
# Protect names starting with `-'.
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $src in
|
||||
-*) src=./$src;;
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
|
@ -252,12 +264,7 @@ do
|
|||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dst=$dst_arg
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst;;
|
||||
esac
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
|
@ -385,7 +392,7 @@ do
|
|||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
-*) prefix='./';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
|
@ -403,7 +410,7 @@ do
|
|||
|
||||
for d
|
||||
do
|
||||
test -z "$d" && continue
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
|
|
53
missing
53
missing
|
@ -1,10 +1,10 @@
|
|||
#! /bin/sh
|
||||
# Common stub for a few missing GNU programs while installing.
|
||||
|
||||
scriptversion=2009-04-28.21; # UTC
|
||||
scriptversion=2012-01-06.13; # UTC
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
|
||||
# 2008, 2009 Free Software Foundation, Inc.
|
||||
# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
|
||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
|
@ -84,7 +84,6 @@ Supported PROGRAM values:
|
|||
help2man touch the output file
|
||||
lex create \`lex.yy.c', if possible, from existing .c
|
||||
makeinfo touch the output file
|
||||
tar try tar, gnutar, gtar, then tar without non-portable flags
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
|
||||
Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
|
||||
|
@ -122,15 +121,6 @@ case $1 in
|
|||
# Not GNU programs, they don't have --version.
|
||||
;;
|
||||
|
||||
tar*)
|
||||
if test -n "$run"; then
|
||||
echo 1>&2 "ERROR: \`tar' requires --run"
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
|
@ -226,7 +216,7 @@ WARNING: \`$1' $msg. You should only need it if
|
|||
\`Bison' from any GNU archive site."
|
||||
rm -f y.tab.c y.tab.h
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG="\${$#}"
|
||||
eval LASTARG=\${$#}
|
||||
case $LASTARG in
|
||||
*.y)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||
|
@ -256,7 +246,7 @@ WARNING: \`$1' is $msg. You should only need it if
|
|||
\`Flex' from any GNU archive site."
|
||||
rm -f lex.yy.c
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG="\${$#}"
|
||||
eval LASTARG=\${$#}
|
||||
case $LASTARG in
|
||||
*.l)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||
|
@ -318,41 +308,6 @@ WARNING: \`$1' is $msg. You should only need it if
|
|||
touch $file
|
||||
;;
|
||||
|
||||
tar*)
|
||||
shift
|
||||
|
||||
# We have already tried tar in the generic part.
|
||||
# Look for gnutar/gtar before invocation to avoid ugly error
|
||||
# messages.
|
||||
if (gnutar --version > /dev/null 2>&1); then
|
||||
gnutar "$@" && exit 0
|
||||
fi
|
||||
if (gtar --version > /dev/null 2>&1); then
|
||||
gtar "$@" && exit 0
|
||||
fi
|
||||
firstarg="$1"
|
||||
if shift; then
|
||||
case $firstarg in
|
||||
*o*)
|
||||
firstarg=`echo "$firstarg" | sed s/o//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
case $firstarg in
|
||||
*h*)
|
||||
firstarg=`echo "$firstarg" | sed s/h//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: I can't seem to be able to run \`tar' with the given arguments.
|
||||
You may want to install GNU tar or Free paxutils, or check the
|
||||
command line arguments."
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and is $msg.
|
||||
|
|
|
@ -23,11 +23,11 @@ include $(top_srcdir)/Makefile.common
|
|||
DESTDIR :=
|
||||
|
||||
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
|
||||
AM_CXXFLAGS = -O3 -g -lpthread
|
||||
AM_CXXFLAGS = -lrt -O3 -g -lpthread
|
||||
|
||||
EXTRA_DIST = \
|
||||
README.smqueue \
|
||||
smqueue.config.example
|
||||
smqueue.conf
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
smqueue
|
||||
|
@ -36,16 +36,27 @@ noinst_HEADERS = \
|
|||
poll.h \
|
||||
smnet.h \
|
||||
smqueue.h \
|
||||
smsc.h \
|
||||
diskbackup.h
|
||||
QueuedMsgHdrs.h \
|
||||
SmqGlobals.h \
|
||||
SmqMessageHandler.h \
|
||||
SmqReader.h \
|
||||
SmqWriter.h \
|
||||
SmqTest.h
|
||||
smsc.h
|
||||
|
||||
smqueue_SOURCES = \
|
||||
poll.c \
|
||||
smcommands.cpp \
|
||||
smnet.cpp \
|
||||
smqueue.cpp \
|
||||
QueuedMsgHdrs.cpp \
|
||||
SmqGlobals.cpp \
|
||||
SmqMessageHandler.cpp \
|
||||
SmqReader.cpp \
|
||||
SmqWriter.cpp \
|
||||
SmqTest.cpp \
|
||||
smsc.cpp \
|
||||
diskbackup.cpp
|
||||
../SR/SubscriberRegistry.cpp
|
||||
|
||||
smqueue_LDADD = \
|
||||
$(GLOBALS_LA) \
|
||||
|
@ -53,14 +64,15 @@ smqueue_LDADD = \
|
|||
$(GSM_LA) \
|
||||
$(COMMON_LA) \
|
||||
$(SQLITE_LA) \
|
||||
$(SR_LA) \
|
||||
$(SIP_LA) \
|
||||
$(NODEMANAGER_LA) \
|
||||
$(OSIP_LIBS)
|
||||
|
||||
install: smqueue
|
||||
mkdir -p "$(DESTDIR)/OpenBTS/"
|
||||
install smqueue "$(DESTDIR)/OpenBTS/"
|
||||
install runloop.smqueue.sh "$(DESTDIR)/OpenBTS/"
|
||||
mkdir -p "$(DESTDIR)/etc/init/"
|
||||
install smqueue.conf "$(DESTDIR)/etc/init/"
|
||||
mkdir -p "$(DESTDIR)/etc/OpenBTS/"
|
||||
install smqueue.example.sql "$(DESTDIR)/etc/OpenBTS/"
|
||||
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* HeaderforMsgs.cpp
|
||||
*
|
||||
* Created on: Nov 27, 2013
|
||||
* Author: scott
|
||||
*/
|
||||
|
||||
#include "smqueue.h"
|
||||
#include "QueuedMsgHdrs.h"
|
||||
|
||||
|
||||
|
||||
void * QueuedMsgHdrs::getpData()
|
||||
{
|
||||
return pData;
|
||||
}
|
||||
|
||||
|
||||
void QueuedMsgHdrs::setpData(void * data)
|
||||
{
|
||||
pData = data;
|
||||
}
|
||||
|
||||
|
||||
QueuedMsgHdrs::MessageType QueuedMsgHdrs::getMsgType() const
|
||||
{
|
||||
return msgType;
|
||||
}
|
||||
|
||||
|
||||
void QueuedMsgHdrs::setMsgType(MessageType msgType)
|
||||
{
|
||||
this->msgType = msgType;
|
||||
}
|
||||
|
||||
|
||||
SMqueue::short_msg_pending* QueuedMsgHdrs::getSmp() const
|
||||
{
|
||||
return smp;
|
||||
}
|
||||
|
||||
|
||||
void QueuedMsgHdrs::setSmp(SMqueue::short_msg_pending* smp)
|
||||
{
|
||||
this->smp = smp;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* QueuedMsgHdrs.h
|
||||
*
|
||||
* Created on: Nov 27, 2013setbufferSize
|
||||
* Author: scott
|
||||
* Header for message being sent in SMQ
|
||||
*/
|
||||
|
||||
#ifndef HEADERFORMSGS_H_
|
||||
#define HEADERFORMSGS_H_
|
||||
|
||||
|
||||
class QueuedMsgHdrs {
|
||||
public:
|
||||
|
||||
enum MessageType {
|
||||
TestMessage = 1,
|
||||
SIPAckMsg = 2,
|
||||
SendResponse = 3,
|
||||
ProcessIncommingMsg = 4
|
||||
};
|
||||
|
||||
QueuedMsgHdrs() {}
|
||||
|
||||
QueuedMsgHdrs(enum MessageType eMessageType, void * ptr, int MessageSize) {
|
||||
this->msgType = eMessageType;
|
||||
pData = ptr;
|
||||
smp = 0;
|
||||
setMessageSize(sizeof(QueuedMsgHdrs));
|
||||
}
|
||||
|
||||
virtual ~QueuedMsgHdrs() {
|
||||
//LOG(DEBUG) << "QueuedMsgHdrs DTOR";
|
||||
}
|
||||
|
||||
void setpData(void * data);
|
||||
void * getpData();
|
||||
void setMsgType(enum MessageType msgType);
|
||||
MessageType getMsgType() const;
|
||||
SMqueue::short_msg_pending* getSmp() const;
|
||||
void setSmp(SMqueue::short_msg_pending* smp);
|
||||
int getMessageSize() { return messageSize; }
|
||||
void setMessageSize(int iSize) { messageSize = iSize; }
|
||||
virtual int ProcessMessage() {
|
||||
// Not currently used
|
||||
LOG(DEBUG) << "Process message QueuedMsgHdrs DID NOTHING";
|
||||
}
|
||||
|
||||
private:
|
||||
MessageType msgType;
|
||||
SMqueue::short_msg_pending *smp; // the message in the queue
|
||||
void * pData;
|
||||
int messageSize;
|
||||
};
|
||||
|
||||
|
||||
class SIPAckMessage : public QueuedMsgHdrs {
|
||||
public:
|
||||
|
||||
SIPAckMessage(int err, SMqueue::short_msg_pending * smp, char * netaddr, size_t netaddrlen) {
|
||||
setMsgType(QueuedMsgHdrs::SIPAckMsg);
|
||||
setSmp(smp); // Use the pointer later
|
||||
setpData(0);
|
||||
|
||||
this->errcode = err;
|
||||
this->netaddr = netaddr;
|
||||
this->netaddrlen = netaddrlen;
|
||||
setMessageSize(sizeof(SIPAckMessage));
|
||||
}
|
||||
|
||||
virtual ~SIPAckMessage() {
|
||||
// QueuedMsgHdrs dtor will delete smp
|
||||
//LOG(DEBUG) << "SIPAckMessage DTOR";
|
||||
}
|
||||
|
||||
int getErrcode() const
|
||||
{
|
||||
return errcode;
|
||||
}
|
||||
|
||||
void setErrcode(int errcode)
|
||||
{
|
||||
this->errcode = errcode;
|
||||
}
|
||||
|
||||
char* getNetaddr() const
|
||||
{
|
||||
return netaddr;
|
||||
}
|
||||
|
||||
void setNetaddr(char* netaddr)
|
||||
{
|
||||
this->netaddr = netaddr;
|
||||
}
|
||||
|
||||
size_t getNetaddrlen() const
|
||||
{
|
||||
return netaddrlen;
|
||||
}
|
||||
|
||||
void setNetaddrlen(size_t netaddrlen)
|
||||
{
|
||||
this->netaddrlen = netaddrlen;
|
||||
}
|
||||
|
||||
virtual int ProcessMessage() {
|
||||
LOG(DEBUG) << "Process message SIPAckMessage";
|
||||
smq.respond_sip_ack(this->getErrcode(), (SMqueue::short_msg_pending *) this->getSmp(), // Real call to respond_sip_ack on writer thread
|
||||
(char *) this->getNetaddr(), (int) this->getNetaddrlen());
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int errcode;
|
||||
char* netaddr;
|
||||
size_t netaddrlen;
|
||||
};
|
||||
|
||||
|
||||
class TestMessage : public QueuedMsgHdrs {
|
||||
public:
|
||||
|
||||
TestMessage(std::string sMsg) {
|
||||
strcpy(msg, sMsg.c_str());
|
||||
|
||||
setMsgType(QueuedMsgHdrs::TestMessage);
|
||||
setSmp(0);
|
||||
setpData(0);
|
||||
setMessageSize(sizeof(TestMessage));
|
||||
}
|
||||
virtual ~TestMessage() {
|
||||
//LOG(DEBUG) << "TestMessage DTOR";
|
||||
}
|
||||
|
||||
virtual int ProcessMessage() {
|
||||
LOG(DEBUG) << "Process message TestMessage msg:" << msg; // Log is all this message has to do currently
|
||||
}//
|
||||
|
||||
private:
|
||||
char msg[50];
|
||||
};
|
||||
|
||||
|
||||
class ProcessIncommingMsg : public QueuedMsgHdrs {
|
||||
public:
|
||||
// Message will be sent to the writer thread so that msgs will be processed
|
||||
ProcessIncommingMsg() {
|
||||
setMsgType(QueuedMsgHdrs::ProcessIncommingMsg);
|
||||
setSmp(0);
|
||||
setpData(0);
|
||||
setMessageSize(sizeof(ProcessIncommingMsg));
|
||||
}
|
||||
|
||||
virtual ~ProcessIncommingMsg() {
|
||||
//LOG(DEBUG) << "ProcessIncommingMsg DTOR";
|
||||
|
||||
}
|
||||
|
||||
virtual int ProcessMessage() {
|
||||
// Got a message in the queue go handle it
|
||||
LOG(DEBUG) << "Process message ProcessIncommingMsg";
|
||||
smq.process_timeout();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class SimpleWrapper {
|
||||
public:
|
||||
SimpleWrapper(QueuedMsgHdrs* pData) {
|
||||
msgPtr = pData;
|
||||
}
|
||||
|
||||
~SimpleWrapper() {
|
||||
// don't delete msgPtr this will be doe by receiving client
|
||||
//LOG(DEBUG) << "SimpleWrapper DTOR";
|
||||
}
|
||||
int getSize() { return sizeof(SimpleWrapper); }
|
||||
QueuedMsgHdrs* getMsgPtr() { return msgPtr; }
|
||||
void setMsgPtr(QueuedMsgHdrs* pData) { msgPtr = pData; }
|
||||
|
||||
private:
|
||||
QueuedMsgHdrs* msgPtr;
|
||||
}; // SimpleWrapper
|
||||
|
||||
|
||||
|
||||
#endif /* HEADERFORMSGS_H_ */
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SmqGlobals.cpp
|
||||
*
|
||||
* Created on: Nov 21, 2013
|
||||
* Author: scott
|
||||
* Some common resource used by SMQ
|
||||
*/
|
||||
|
||||
|
||||
#include "SmqGlobals.h"
|
||||
#include <Logger.h>
|
||||
|
||||
SmqGlobals::SmqGlobals() {
|
||||
|
||||
}
|
||||
|
||||
SmqGlobals::~SmqGlobals() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned long getCurrentSeconds() {
|
||||
struct timespec tv;
|
||||
clock_gettime(CLOCK_REALTIME, &tv);;
|
||||
unsigned long time_in_sec =
|
||||
tv.tv_sec + (tv.tv_nsec / 1000000000UL) ; // convert tv_sec & tv_usec to millisecond
|
||||
return time_in_sec;
|
||||
}
|
||||
/*
|
||||
* Returns current MS
|
||||
*/
|
||||
unsigned long getCurrentMS() {
|
||||
struct timespec tv;
|
||||
clock_gettime(CLOCK_REALTIME, &tv);
|
||||
unsigned long time_in_mill =
|
||||
(tv.tv_sec * 1000UL) + (tv.tv_nsec / 1000000UL) ; // convert tv_sec & tv_usec to millisecond
|
||||
return time_in_mill;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns MS from timespec
|
||||
*/
|
||||
unsigned long getMSFromtimespec(struct timespec tv) {
|
||||
unsigned long time_in_mill =
|
||||
(tv.tv_sec * 1000UL) + (tv.tv_nsec / 1000000UL) ; // convert tv_sec & tv_usec to millisecond
|
||||
return time_in_mill;
|
||||
}
|
||||
|
||||
|
||||
struct timespec addTimespec(struct timespec tv1, struct timespec tv2) {
|
||||
struct timespec tvret;
|
||||
|
||||
tvret.tv_sec = tv1.tv_sec + tv2.tv_sec;
|
||||
tvret.tv_nsec = tv1.tv_nsec + tv2.tv_nsec;
|
||||
if (tvret.tv_nsec >= NS_IN_SEC) {
|
||||
tvret.tv_sec++;
|
||||
tvret.tv_nsec = tvret.tv_nsec - NS_IN_SEC;
|
||||
}
|
||||
return tvret;
|
||||
}
|
||||
|
||||
|
||||
void msSleep(int ms) {
|
||||
usleep(ms*1000); // Convert to microseconds
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
time_t msgettime() {
|
||||
//LOG(DEBUG) << "Enter msgettime";
|
||||
struct timespec tv;
|
||||
clock_gettime(CLOCK_REALTIME, &tv);
|
||||
unsigned long time_in_mill =
|
||||
(tv.tv_sec * 1000UL) + (tv.tv_nsec / 1000000UL) ; // convert tv_sec & tv_usec to millisecond
|
||||
//LOG(DEBUG) << "Return msgettime ms" << time_in_mill;
|
||||
return time_in_mill;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* SmqGlobals.h
|
||||
*
|
||||
* Created on: Nov 21, 2013
|
||||
* Author:
|
||||
*/
|
||||
|
||||
#ifndef SMQGLOBALS_H_
|
||||
#define SMQGLOBALS_H_
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#define CLOCK_REALTIME 0 // Fix this svgfix
|
||||
#define NS_IN_SEC 1000000000L // Number of nano seconds in a second
|
||||
|
||||
//#define mq_printf(str, arg...) printf("%d : "str, getpid(), ##arg) // Original
|
||||
#define mq_printf(str, arg...) printf("ms:%lu tid:%lu: "str, getCurrentMS(), pthread_self(), ##arg)
|
||||
|
||||
|
||||
class SmqGlobals {
|
||||
public:
|
||||
SmqGlobals();
|
||||
virtual ~SmqGlobals();
|
||||
};
|
||||
|
||||
extern unsigned long getCurrentMS();
|
||||
extern unsigned long getMSFromtimespec(struct timespec tv);
|
||||
extern struct timespec addTimespec(struct timespec tv1, struct timespec tv2);
|
||||
extern void msSleep(int ms);
|
||||
extern time_t msgettime();
|
||||
extern unsigned long getCurrentSeconds();
|
||||
|
||||
#endif /* SMQGLOBALS_H_ */
|
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SmqMessageHandler.cpp
|
||||
*
|
||||
* Created on: Nov 16, 2013
|
||||
* Author:
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "smqueue.h"
|
||||
#include "QueuedMsgHdrs.h"
|
||||
#include "SmqMessageHandler.h"
|
||||
#include "SmqReader.h"
|
||||
#include "SmqWriter.h"
|
||||
|
||||
// Pointers to handlers for the reader and writer queues
|
||||
SmqReader* smqReader;
|
||||
SmqWriter* smqWriter;
|
||||
|
||||
|
||||
// Static function to start the threads
|
||||
void SmqMessageHandler::StartThreads() {
|
||||
LOG(INFO) << "Start reader and writer threads";
|
||||
smqReader = new SmqReader();
|
||||
smqWriter = new SmqWriter();
|
||||
}
|
||||
|
||||
|
||||
SmqMessageHandler::~SmqMessageHandler() {
|
||||
/* Close the message queue */
|
||||
int ret = mq_close(mqdes);
|
||||
if (ret)
|
||||
LOG(DEBUG) << "Message queue close failed";
|
||||
else
|
||||
LOG(DEBUG) << "Message queue closed";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
returns
|
||||
0 = sent okay
|
||||
-1 failed
|
||||
Should only be used for test need header for all msgs
|
||||
Delete after clean up
|
||||
|
||||
*/
|
||||
int SmqMessageHandler::SmqSendMessage(SimpleWrapper * pMsg) {
|
||||
|
||||
int returnValue;
|
||||
int ret;
|
||||
|
||||
//LOG(DEBUG) << "Sending message to queue:" << getQueueName();;
|
||||
|
||||
// Wait for queue to open
|
||||
while (!queueOpened()) {
|
||||
LOG(DEBUG) << "Try to open queue:" << getQueueName() << "in SmqSendMessage";
|
||||
mqueueOpened = SmqInitReceiver(); // Set up the queue name
|
||||
if (queueOpened()) {
|
||||
LOG(DEBUG) << "Successfully opened queue for sender queue:" << getQueueName();
|
||||
//break;
|
||||
}
|
||||
msSleep(2000);
|
||||
} // while
|
||||
|
||||
ret = mq_send(mqdes, (char*) pMsg, pMsg->getSize(), 0);
|
||||
if (ret) {
|
||||
LOG(DEBUG) << "Message failed to be sent error:" << ret << " errno:" << errno;
|
||||
returnValue = -1;
|
||||
}
|
||||
else {
|
||||
//LOG(DEBUG) << "Message sent okay queue:" << getQueueName();
|
||||
returnValue = 0;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
int SmqMessageHandler::SmqDeleteMessage() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::string SmqMessageHandler::getQueueName() {
|
||||
return mqueueName;
|
||||
}
|
||||
|
||||
|
||||
bool SmqMessageHandler::queueOpened() {
|
||||
return mqueueOpened;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return
|
||||
* Message okay = size of message
|
||||
* -x = Failed
|
||||
* 0 = Timeout
|
||||
*
|
||||
*/
|
||||
int SmqMessageHandler::SmqWaitforMessage(int TimeoutMS, char * MsgBuffer, int MsgBufferSize) {
|
||||
int msgLength = 0;
|
||||
struct mq_attr attrList;
|
||||
|
||||
//LOG(DEBUG) << "Waiting for message in queue:" << getQueueName() << " tmo:" << TimeoutMS << " bufsize:" << MsgBufferSize;
|
||||
|
||||
// Wait for queue to open. This may not be needed
|
||||
while (!queueOpened()) {
|
||||
LOG(DEBUG) << "Try to open queue:" << getQueueName() << " in SmqWaitforMessage";
|
||||
mqueueOpened = SmqInitReceiver(); // Set up the queue name
|
||||
if (mqueueOpened) {
|
||||
LOG(DEBUG) << "Successfully opened queue:" << getQueueName() << " in SmqWaitforMessage";
|
||||
break;
|
||||
}
|
||||
msSleep(2000);
|
||||
} // while
|
||||
|
||||
//mq_getattr(mqdes, &attrList);
|
||||
//LOG(DEBUG) << "mq_attr flags:%ld maxmsg:%ld mq_msgsize:%ld mq_curmsg:%ld",
|
||||
//attrList.mq_flags, attrList.mq_maxmsg, attrList.mq_msgsize, attrList.mq_curmsgs);
|
||||
|
||||
/* get the current time at which mq_receive() is going to be called
|
||||
i.e time since the Epoch time, 1970-01-01 00:00:00 +0000 (UTC) */
|
||||
clock_gettime(CLOCK_REALTIME, ¤ttime_before);
|
||||
|
||||
struct timespec wait_timeout; // Put delay in time spec
|
||||
wait_timeout.tv_sec = (TimeoutMS / 1000);
|
||||
wait_timeout.tv_nsec = ((TimeoutMS % 1000) * 1000000);
|
||||
abs_timeout = addTimespec(currenttime_before, wait_timeout);
|
||||
|
||||
// Wait for the message
|
||||
// LOG(DEBUG) << "Real enter wait for message in queue:"<< getQueueName().c_str() << " tmo:" << TimeoutMS;
|
||||
msgLength = mq_timedreceive(mqdes, MsgBuffer, MsgBufferSize, &msg_prio, &abs_timeout);
|
||||
|
||||
#if 0
|
||||
// only enable for debugging
|
||||
clock_gettime(CLOCK_REALTIME, ¤ttime_after);
|
||||
|
||||
/* Get the time at which the message queue returns */
|
||||
LOG(DEBUG) << "Message queue:%s size:%ld", mqueueName.c_str(), getMessageQueueSize());
|
||||
|
||||
/* Print all time values. We didn't print anything before to avoid the delay caused by printf() */
|
||||
LOG(DEBUG) << "Time before mq_timedreceive is called sec:%ld ns:%ld ms:%lu",
|
||||
currenttime_before.tv_sec, currenttime_before.tv_nsec, getMSFromtimespec(currenttime_before));
|
||||
LOG(DEBUG) << "Absolute time passed to mq_timedreceive sec:%ld ns:%ld ms:%lu",
|
||||
abs_timeout.tv_sec, abs_timeout.tv_nsec, getMSFromtimespec(abs_timeout));
|
||||
LOG(DEBUG) << "Time at which mq_timedreceive returned sec:%ld ns:%ld ms:%lu",
|
||||
currenttime_after.tv_sec, currenttime_after.tv_nsec, getMSFromtimespec(currenttime_after));
|
||||
LOG(DEBUG) << "Actual wait time ms:%ld",
|
||||
getMSFromtimespec(currenttime_after) - getMSFromtimespec(currenttime_before));
|
||||
//LOG(DEBUG) << "Actual passed to wait ms:%lu", getMSFromtimespec(abs_timeout));
|
||||
#endif
|
||||
|
||||
if (msgLength < 0)
|
||||
{ /* mq_timedreceive returned with an error */
|
||||
//LOG(DEBUG) << "Wait for message receive got errno:%d error:%d", errno, msgLength);
|
||||
if (errno == ETIMEDOUT) { // errno = 110
|
||||
// ********* TIMEOUT ***************************
|
||||
//LOG(DEBUG) << "Wait for message got timeout");
|
||||
msgLength = 0;
|
||||
} else {
|
||||
// *********** GOT ERROR ******************
|
||||
//Check for other errors like signal to stop EINTR
|
||||
LOG(DEBUG) << "Wait for message receive got errno:" << errno << " error:" << msgLength;
|
||||
// Return current value of msgLength
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* *****************GOT MESSAGE **************** */
|
||||
//LOG(DEBUG) << "Successfully received %d bytes", (int) msgLength);
|
||||
}
|
||||
|
||||
return msgLength;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Returns
|
||||
true = okay
|
||||
|
||||
*/
|
||||
bool SmqMessageHandler::SmqInitReceiver() {
|
||||
bool retValue = false;
|
||||
|
||||
LOG(DEBUG) << "SmqInitReceiver queue name:" << mqueueName;
|
||||
|
||||
/* Create message queue */
|
||||
mqdes = mq_open(mqueueName.c_str(), O_RDWR | O_CREAT, MQ_MODE, &attr); // Should be this one
|
||||
|
||||
if (mqdes != (mqd_t)-1 ) {
|
||||
LOG(DEBUG) << "Message queue opened:" << mqueueName;
|
||||
retValue = true;
|
||||
mqueueOpened = true;
|
||||
}
|
||||
else {
|
||||
LOG(DEBUG) << "Message Queue FAILED to open";
|
||||
LOG(DEBUG) << "mq_open error:" << errno << " mqdes:" << mqdes;
|
||||
retValue = false;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
long SmqMessageHandler::getMessageQueueSize() {
|
||||
int error;
|
||||
long count = -1;
|
||||
struct mq_attr localAttr;
|
||||
|
||||
error = mq_getattr(mqdes, &localAttr);
|
||||
if (!error)
|
||||
count = localAttr.mq_curmsgs;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send a QueuedMsgHdrs to writer queue
|
||||
* Deleted SimpleWrapper receiver deletes attached message
|
||||
*/
|
||||
int SendWriterMsg(SimpleWrapper* pMsg) {
|
||||
int iret;
|
||||
iret = smqWriter->getqueHan()->SmqSendMessage(pMsg);
|
||||
delete pMsg; // Delete SimpleWrapper
|
||||
return iret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Send a message to the writer thread asking for a sip ack to be sent
|
||||
*/
|
||||
void queue_respond_sip_ack(int errcode, SMqueue::short_msg_pending *shortmsg, char * netaddr, size_t netaddrlen) {
|
||||
LOG(DEBUG) << "Send SIP ACK queue request";
|
||||
QueuedMsgHdrs* pMsg = new SIPAckMessage(errcode, shortmsg, netaddr, netaddrlen);
|
||||
SimpleWrapper* sWrap = new SimpleWrapper(pMsg);
|
||||
SendWriterMsg(sWrap); // Message gets deleted in here
|
||||
}
|
||||
|
||||
|
||||
// Signal writer thread to process incoming message
|
||||
void ProcessReceivedMsg() {
|
||||
LOG(DEBUG) << "Signal writer thread ProcessReceivedMsg";
|
||||
QueuedMsgHdrs* pMsg = new ProcessIncommingMsg();
|
||||
SimpleWrapper* sWrap = new SimpleWrapper(pMsg);
|
||||
SendWriterMsg(sWrap);
|
||||
}
|
||||
|
||||
|
||||
// Only used for testing
|
||||
void SendTestMessage() {
|
||||
QueuedMsgHdrs* pMsg = new TestMessage("Test message from reader thread");
|
||||
SimpleWrapper* sWrap = new SimpleWrapper(pMsg);
|
||||
SendWriterMsg(sWrap); // Message gets deleted in here
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SmqMessageHandler.h
|
||||
*
|
||||
* Created on: Nov 16, 2013
|
||||
using namespace std;
|
||||
using namespace SMqueue;
|
||||
extern ConfigurationTable gConfig;
|
||||
* Author: Scott
|
||||
* This code implements the wait for event function
|
||||
*/
|
||||
|
||||
#ifndef SMQMESSAGEHANDLER_H_
|
||||
#define SMQMESSAGEHANDLER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <mqueue.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <string>
|
||||
#include "SmqGlobals.h"
|
||||
#include <unistd.h>
|
||||
|
||||
void queue_respond_sip_ack(int errcode, SMqueue::short_msg_pending *shortmsg, char * netaddr, size_t netaddrlen);
|
||||
void ProcessReceivedMsg();
|
||||
void SendTestMessage();
|
||||
|
||||
|
||||
using namespace std;
|
||||
/*
|
||||
These are the upper limit on queue sizes
|
||||
/proc/sys/fs/mqueue/msg_max: 1100
|
||||
/proc/sys/fs/mqueue/msgsize_max: 1000
|
||||
/proc/sys/fs/mqueue/queues_max: 256
|
||||
*/
|
||||
|
||||
#define MQ_MESSAGE_MAX_SIZE 1100
|
||||
#define MQ_MAX_NUM_OF_MESSAGES 100
|
||||
#define MQ_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
|
||||
|
||||
/*
|
||||
errno
|
||||
13 permission denied
|
||||
14
|
||||
22 EINVAL
|
||||
90 EMSGSIZE Message too long (POSIX.1)
|
||||
110 ETIMEDOUT
|
||||
*/
|
||||
class SmqMessageHandler {
|
||||
public:
|
||||
static void StartThreads();
|
||||
|
||||
SmqMessageHandler(string queueName) {
|
||||
/* Form the queue attributes */
|
||||
attr.mq_flags = 0; /* i.e mq_send will be block if message queue is full */
|
||||
attr.mq_maxmsg = MQ_MAX_NUM_OF_MESSAGES;
|
||||
attr.mq_msgsize = MQ_MESSAGE_MAX_SIZE;
|
||||
attr.mq_curmsgs = 0;
|
||||
msg_prio = 0;
|
||||
mqueueName = queueName;
|
||||
mqueueOpened = false;
|
||||
}
|
||||
|
||||
~SmqMessageHandler();
|
||||
|
||||
int SmqDeleteMessage();
|
||||
|
||||
int SmqWaitforMessage(int TimeoutMS, char * MsgBuffer, int MsgBufferSize);
|
||||
bool SmqInitReceiver();
|
||||
string getQueueName();
|
||||
bool queueOpened();
|
||||
long getMessageQueueSize();
|
||||
|
||||
// Send functions
|
||||
int SmqSendMessage(SimpleWrapper * pMsg);
|
||||
|
||||
private:
|
||||
// Message queue
|
||||
mqd_t mqdes; // Message queue
|
||||
struct mq_attr attr;
|
||||
unsigned msg_prio;
|
||||
struct timespec currenttime_before;
|
||||
struct timespec abs_timeout;
|
||||
struct timespec currenttime_after;
|
||||
|
||||
string mqueueName; // Name used with this message queue
|
||||
bool mqueueOpened;
|
||||
};
|
||||
|
||||
#endif /* SMQMESSAGEHANDLER_H_ */
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SmqReader.cpp
|
||||
*
|
||||
* Created on: Nov 16, 2013
|
||||
* Author: Scott Van Gundy
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include "smqueue.h"
|
||||
#include "QueuedMsgHdrs.h"
|
||||
#include "SmqMessageHandler.h"
|
||||
#include "SmqReader.h"
|
||||
|
||||
#include <Logger.h>
|
||||
|
||||
std::string SmqReader::MQ_NAME = "/SmqReader";
|
||||
|
||||
extern SmqReader* smqReader;
|
||||
|
||||
|
||||
SmqReader::~SmqReader() {
|
||||
delete mqueHan;
|
||||
}
|
||||
|
||||
|
||||
void* SmqReader::SmqReaderThread(void* ptr) {
|
||||
LOG(DEBUG) <<"Start SMQ reader thread";
|
||||
|
||||
char msgBuffer[MQ_MESSAGE_MAX_SIZE+10]; // Must be larger than size speced in attr
|
||||
int bytesRead = 0;
|
||||
int msgCount = 0;
|
||||
|
||||
smq.InitBeforeMainLoop();
|
||||
smq.InitInsideReaderLoop(); // Updates configuration do here to make sure everything is setup for threads
|
||||
|
||||
// Queue opened Process messages
|
||||
LOG(DEBUG) << "Enter reader thread loop";
|
||||
while (!smq.stop_main_loop) {
|
||||
|
||||
smq.main_loop(60000);
|
||||
|
||||
#if 0
|
||||
// Put this back in if process messages in reader thread
|
||||
LOG(DEBUG) <<"Start SMQ reader thread loop";
|
||||
bytesRead = smqReader->getqueHan()->SmqWaitforMessage(2000, msgBuffer, sizeof(msgBuffer)); // Wait for message
|
||||
|
||||
//LOG(DEBUG) << "Got return from SmqWaitforMessage in reader thread status:%d", bytesRead);
|
||||
if (bytesRead < 0) {
|
||||
// GOT ERROR
|
||||
LOG(DEBUG) << "Reader failed to get message:" << bytesRead;
|
||||
|
||||
} else if (bytesRead == 0) {
|
||||
// TIMEOUT
|
||||
LOG(DEBUG) << "Got timeout waiting for reader message";
|
||||
//Add timeout stuff here
|
||||
|
||||
//LOG(DEBUG) << "Enter InitInsideReaderLoop";
|
||||
smq.InitInsideReaderLoop(); // Updates configuration Moved this to writer queue
|
||||
//LOG(DEBUG) << "Return from InitInsideReaderLoop";
|
||||
|
||||
// This is where all the work is done
|
||||
// Message are read in here
|
||||
//LOG(DEBUG) << "Enter main_loop";
|
||||
smq.main_loop(2000);
|
||||
//LOG(DEBUG) << "Return from main_loop";
|
||||
|
||||
} else if (bytesRead > 0) {
|
||||
// GOT MESSAGE
|
||||
LOG(DEBUG) << "Received message in reader thread length;" << bytesRead;
|
||||
// PROCESS MESSAGES HERE
|
||||
#if 0
|
||||
switch (msgType) {
|
||||
case QueuedMsgHdrs::TestMessage:
|
||||
|
||||
break;
|
||||
|
||||
case QueuedMsgHdrs::SendResponse: // this is a writer message
|
||||
|
||||
break;
|
||||
} // switch
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} // while
|
||||
|
||||
smq.CleaupAfterMainreaderLoop();
|
||||
|
||||
LOG(DEBUG) << "End SMQ reader thread";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SmqReader.h
|
||||
*
|
||||
* Created on: Nov 16, 2013
|
||||
* Author: Scott
|
||||
*/
|
||||
|
||||
#ifndef SMQREADER_H_
|
||||
#define SMQREADER_H_
|
||||
|
||||
|
||||
class SmqReader {
|
||||
public:
|
||||
static std::string MQ_NAME;
|
||||
|
||||
SmqReader() {
|
||||
// create message handler
|
||||
mqueHan = new SmqMessageHandler(SmqReader::MQ_NAME);
|
||||
// Start reader thread
|
||||
pthread_create(&mthread_ID, NULL, SmqReaderThread, (void*) NULL);
|
||||
}
|
||||
|
||||
~SmqReader();
|
||||
static void* SmqReaderThread(void * ptr);
|
||||
|
||||
// get handle to message queue
|
||||
SmqMessageHandler * getqueHan() {
|
||||
return mqueHan;
|
||||
}
|
||||
|
||||
private:
|
||||
pthread_t mthread_ID;
|
||||
SmqMessageHandler* mqueHan;
|
||||
bool please_re_exec;
|
||||
};
|
||||
|
||||
|
||||
#endif /* SMQREADER_H_ */
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SmqTest.cpp
|
||||
*
|
||||
* Created on: Dec 16, 2013
|
||||
* Author: scott
|
||||
*/
|
||||
|
||||
#include "SmqTest.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "smqueue.h"
|
||||
#include "QueuedMsgHdrs.h"
|
||||
#include "SmqMessageHandler.h"
|
||||
#include "SmqReader.h"
|
||||
#include "SmqWriter.h"
|
||||
#include "SmqGlobals.h"
|
||||
|
||||
extern SmqReader* smqReader;
|
||||
extern SmqWriter* smqWriter;
|
||||
|
||||
#define REPEAT 10000
|
||||
|
||||
pthread_t thread1, thread2;
|
||||
|
||||
|
||||
void* ReaderTestThread(void *ptr) {
|
||||
LOG(DEBUG) << "Starting reader test thread";
|
||||
int msgCount = 0;
|
||||
int repeatCount = 0;
|
||||
//while (true) {
|
||||
|
||||
while (++repeatCount < REPEAT) {
|
||||
|
||||
//LOG(DEBUG) << "Send TestMessage from reader test thread");
|
||||
SendTestMessage(); // Send message to writer thread
|
||||
|
||||
//LOG(DEBUG) << "Call originate_sm from readertestthread")
|
||||
//smq.originate_sm("TEST1", "TEST2", "This is a test msg from reader test", SMqueue::INITIAL_STATE); // fake an incommming message
|
||||
|
||||
msSleep(1000);
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "Reader test thread stopped";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int gLevel = 1;
|
||||
void RecursiveMutextTest(int Level) {
|
||||
int iLevel = Level;
|
||||
|
||||
if (Level > 3) return;
|
||||
LOG(DEBUG) << "Enter Level " << iLevel;
|
||||
smq.lockSortedList();
|
||||
|
||||
LOG(DEBUG) << "In lock level " << iLevel;
|
||||
|
||||
gLevel++;
|
||||
RecursiveMutextTest(gLevel);
|
||||
LOG(DEBUG) << "Back from recursive call " << iLevel;
|
||||
|
||||
smq.unlockSortedList();
|
||||
LOG(DEBUG) << "Unlock from Level " << iLevel;
|
||||
} // RecursiveMutextTest
|
||||
|
||||
|
||||
|
||||
// Send fake input to the input socket incomming default 5063
|
||||
#define MAX 100
|
||||
#define tport 5063
|
||||
void WriteToUDP() {
|
||||
int sfd, n;
|
||||
char buffer[MAX];
|
||||
struct sockaddr_in saddr;
|
||||
char IPAddress[100];
|
||||
socklen_t len;
|
||||
int ret;
|
||||
int portNum;
|
||||
|
||||
// Set up test
|
||||
int repeat = 10;
|
||||
strcpy(IPAddress, "127.0.0.1");
|
||||
portNum = tport;
|
||||
|
||||
sfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
bzero(&saddr, sizeof(saddr));
|
||||
saddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, IPAddress, &saddr.sin_addr);
|
||||
saddr.sin_port = htons(portNum);
|
||||
|
||||
LOG(DEBUG) << "WriteToUDP running " << repeat;
|
||||
while(repeat-- > 0) {
|
||||
for (int i = 0; i < sizeof(buffer); i++) { // Write a pattern to the buffer for each write.
|
||||
buffer[i] = 0;
|
||||
}
|
||||
len=sizeof(saddr);
|
||||
LOG(DEBUG) << "Write to UDP port";
|
||||
ret = sendto(sfd, buffer, sizeof(buffer), 0, (struct sockaddr *) &saddr, len);
|
||||
LOG(DEBUG) << "Send length " << ret << " of " << len;
|
||||
|
||||
msSleep(5000);
|
||||
} // while
|
||||
} // WriteToUDP
|
||||
|
||||
|
||||
|
||||
void* WriterTestThread(void *ptr) {
|
||||
LOG(DEBUG) << "Starting writer test thread";
|
||||
int msgCount = 0;
|
||||
int repeatCount = 0;
|
||||
|
||||
// WriteToUDP(); // just run once
|
||||
RecursiveMutextTest(gLevel);
|
||||
|
||||
|
||||
//while (true) {
|
||||
while (++repeatCount < REPEAT) {
|
||||
// Send message to writer
|
||||
//LOG(DEBUG) << "Send msg %d from Writer test thread repeat: %d", msgCount, repeatCount);
|
||||
//msgCount++;
|
||||
//char buffer[50];
|
||||
//sprintf(buffer, "Writer test thread message:%d", msgCount);
|
||||
msSleep(2000);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
} // WriterTestThread
|
||||
|
||||
|
||||
void StartTestThreads() {
|
||||
LOG(DEBUG) << "Start test threads version 14";
|
||||
|
||||
#if 0
|
||||
|
||||
// msSleep(5000); //svgfix
|
||||
|
||||
//pthread_create(&thread1, NULL, ReaderTestThread, (void*) NULL);
|
||||
|
||||
pthread_create(&thread2, NULL, WriterTestThread, (void*) NULL);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SmqTest.h
|
||||
*
|
||||
* Created on: Dec 16, 2013
|
||||
* Author: scott
|
||||
*/
|
||||
|
||||
#ifndef SMQTEST_H_
|
||||
#define SMQTEST_H_
|
||||
|
||||
void StartTestThreads();
|
||||
|
||||
#if 0
|
||||
class SmqTest {
|
||||
public:
|
||||
SmqTest();
|
||||
virtual ~SmqTest();
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* SMQTEST_H_ */
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SmqWriter.cpp
|
||||
*
|
||||
* Created on: Nov 16, 2013
|
||||
* Author: Scott Van Gundy
|
||||
*/
|
||||
|
||||
|
||||
#include <string>
|
||||
#include "smqueue.h"
|
||||
#include "QueuedMsgHdrs.h"
|
||||
|
||||
#include "SmqMessageHandler.h"
|
||||
#include "SmqWriter.h"
|
||||
#include <Logger.h>
|
||||
|
||||
extern SmqWriter* smqWriter;
|
||||
|
||||
|
||||
extern SMqueue::SMq smq;
|
||||
|
||||
std::string SmqWriter::MQ_NAME = "/SmqWriter";
|
||||
|
||||
|
||||
|
||||
SmqWriter::~SmqWriter() {
|
||||
delete mqueHan;
|
||||
}
|
||||
|
||||
|
||||
void* SmqWriter::SmqWriterThread(void * ptr) {
|
||||
LOG(DEBUG) <<"Start SMQ writer thread";
|
||||
|
||||
char msgBuffer[MQ_MESSAGE_MAX_SIZE+10];
|
||||
int bytesRead = 0;
|
||||
int msgCount = 0;
|
||||
SimpleWrapper* pWrap;
|
||||
QueuedMsgHdrs* pMsg;
|
||||
unsigned long currentSeconds;
|
||||
unsigned long lastRunSeconds;
|
||||
SMqueue::short_msg_pending pendingMsg;
|
||||
|
||||
// Queue opened Process messages
|
||||
currentSeconds = getCurrentSeconds();
|
||||
lastRunSeconds = currentSeconds;
|
||||
LOG(DEBUG) << "Enter writer thread loop";
|
||||
while (!smq.stop_main_loop) {
|
||||
|
||||
//LOG(DEBUG) <<"Start SMQ writer thread loop";
|
||||
bytesRead = smqWriter->getqueHan()->SmqWaitforMessage(200, msgBuffer, (int) sizeof(msgBuffer));
|
||||
currentSeconds = getCurrentSeconds();
|
||||
//LOG(DEBUG) << "Got return from SmqWaitforMessage in writer status:" << bytesRead;
|
||||
if (bytesRead < 0) {
|
||||
LOG(DEBUG) << "Writer failed to get message:" << bytesRead;
|
||||
|
||||
} else if (bytesRead == 0) {
|
||||
// ******** Got timeout ***************
|
||||
//LOG(DEBUG) << "Got timeout in writer thread";
|
||||
|
||||
smq.process_timeout(); // Process entries in queue
|
||||
//LOG(DEBUG) << "Return from process_timeout";
|
||||
|
||||
if ((currentSeconds - lastRunSeconds ) > 60) {
|
||||
LOG(DEBUG) << "Run once a minute stuff";
|
||||
smq.InitInsideReaderLoop(); // Updates configuration
|
||||
|
||||
int queueSize = smq.time_sorted_list.size();
|
||||
if (queueSize > 0) { LOG(DEBUG) << "Queue size " << queueSize;}
|
||||
// Save queue to file on timeout
|
||||
//LOG(DEBUG) << "Enter save_queue_to_file";
|
||||
if (!smq.save_queue_to_file(smq.savefile)) { // Save queue file each timeout may want to slow this down
|
||||
LOG(WARNING) << "Failed to read queue file on timeout file:" << smq.savefile;
|
||||
}
|
||||
lastRunSeconds = currentSeconds;
|
||||
}
|
||||
|
||||
} else if (bytesRead > 0) {
|
||||
// ********* Got message *************
|
||||
//LOG(DEBUG) << "Received message in writer thread length:" << bytesRead;
|
||||
pWrap = (SimpleWrapper*) msgBuffer;
|
||||
pMsg = pWrap->getMsgPtr();
|
||||
|
||||
// PROCESS MESSAGES HERE
|
||||
pMsg->ProcessMessage();
|
||||
|
||||
delete pMsg;
|
||||
} // Got message
|
||||
} // while
|
||||
|
||||
LOG(DEBUG) << "End SMQ writer thread";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SmqWriter.h
|
||||
*
|
||||
* Created on: Nov 16, 2013
|
||||
* Author: Scott Van Gundy
|
||||
*/
|
||||
|
||||
#ifndef SMQWRITER_H_
|
||||
#define SMQWRITER_H_
|
||||
|
||||
|
||||
class SmqWriter {
|
||||
public:
|
||||
static std::string MQ_NAME;
|
||||
|
||||
SmqWriter() {
|
||||
mqueHan = new SmqMessageHandler(SmqWriter::MQ_NAME);
|
||||
pthread_create(&mthread_ID, NULL, SmqWriterThread, (void*) NULL);
|
||||
}
|
||||
|
||||
~SmqWriter();
|
||||
static void* SmqWriterThread(void * ptr);
|
||||
|
||||
SmqMessageHandler* getqueHan() {
|
||||
return mqueHan;
|
||||
}
|
||||
|
||||
private:
|
||||
pthread_t mthread_ID;
|
||||
SmqMessageHandler* mqueHan;
|
||||
};
|
||||
|
||||
#endif /* SMQWRITER_H_ */
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012 Range Networks, Inc.
|
||||
*
|
||||
* Written by Kurtis Heimerl, November 2012
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "diskbackup.h"
|
||||
#include <sys/stat.h>
|
||||
#include "sqlite3.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <Configuration.h>
|
||||
|
||||
extern ConfigurationTable gConfig;
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define MICROSECONDS 1000000L
|
||||
|
||||
//basically a copy of the datastructure but in a table
|
||||
static const char* createMessageTable = {
|
||||
"CREATE TABLE IF NOT EXISTS MESSAGES ("
|
||||
"timestamp integer UNIQUE not null, "
|
||||
"message text not null"
|
||||
")"
|
||||
};
|
||||
|
||||
//kurtis utility function
|
||||
long long get_msecs(){
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
long long seconds = tv.tv_sec;
|
||||
seconds *= MICROSECONDS;
|
||||
seconds += tv.tv_usec;
|
||||
return seconds;
|
||||
}
|
||||
|
||||
int SQLiteBackup::init()
|
||||
{
|
||||
string ldb = gConfig.getStr("Backup.db");
|
||||
size_t p = ldb.find_last_of('/');
|
||||
if (p == string::npos) {
|
||||
LOG(EMERG) << "Backup.db not in a directory?";
|
||||
mDB = NULL;
|
||||
return FAILURE;
|
||||
}
|
||||
string dir = ldb.substr(0, p);
|
||||
struct stat buf;
|
||||
if (stat(dir.c_str(), &buf)) {
|
||||
LOG(EMERG) << dir << " does not exist";
|
||||
mDB = NULL;
|
||||
return FAILURE;
|
||||
}
|
||||
int rc = sqlite3_open(ldb.c_str(),&mDB);
|
||||
if (rc) {
|
||||
LOG(EMERG) << "Cannot open SQLiteBackup database: " << sqlite3_errmsg(mDB);
|
||||
sqlite3_close(mDB);
|
||||
mDB = NULL;
|
||||
return FAILURE;
|
||||
}
|
||||
if (!sqlite3_command(mDB,createMessageTable)) {
|
||||
LOG(EMERG) << "Cannot create MESSAGES table";
|
||||
return FAILURE;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
SQLiteBackup::~SQLiteBackup()
|
||||
{
|
||||
if (mDB) sqlite3_close(mDB);
|
||||
}
|
||||
|
||||
backup_msg_list* SQLiteBackup::get_stored_messages(){
|
||||
//record stale messages
|
||||
//should be config variable at some point -kurtis
|
||||
long long min_time = get_msecs() - (72 * 60 * 60 * MICROSECONDS); //hrs*minutes*seconds*microseconds
|
||||
char cmd[100];
|
||||
sprintf(cmd,"SELECT * FROM MESSAGES WHERE timestamp < %lld", min_time);
|
||||
sqlite3_stmt *stmt;
|
||||
if (sqlite3_prepare_statement(mDB,&stmt,cmd)) return NULL;
|
||||
int src = sqlite3_run_query(mDB,stmt);
|
||||
int i = 0;
|
||||
while (src==SQLITE_ROW) {
|
||||
i++;
|
||||
src = sqlite3_run_query(mDB,stmt);
|
||||
}
|
||||
LOG(NOTICE) << "REMOVING " << i << " STALE MESSAGES";
|
||||
|
||||
//remove stale messages
|
||||
sprintf(cmd,"DELETE FROM MESSAGES WHERE timestamp < %lld", min_time);
|
||||
if (sqlite3_prepare_statement(mDB,&stmt,cmd)) return NULL;
|
||||
src = sqlite3_run_query(mDB,stmt);
|
||||
|
||||
//get the remaining messages
|
||||
sprintf(cmd,"SELECT timestamp,message FROM MESSAGES");
|
||||
if (sqlite3_prepare_statement(mDB,&stmt,cmd)) return NULL;
|
||||
// Read the result.
|
||||
backup_msg_list* list = new backup_msg_list(0);
|
||||
src = sqlite3_run_query(mDB,stmt);
|
||||
while (src==SQLITE_ROW) {
|
||||
long long timestamp = sqlite3_column_int64(stmt,0);
|
||||
string text = (char *)sqlite3_column_text(stmt,1);
|
||||
backup_msg msg;
|
||||
msg.timestamp = timestamp;
|
||||
msg.text = text;
|
||||
list->push_back(msg);
|
||||
src = sqlite3_run_query(mDB,stmt);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
return list;
|
||||
}
|
||||
|
||||
int SQLiteBackup::insert(long long timestamp, char* text)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "INSERT into MESSAGES (timestamp, message) values (";
|
||||
os << "\"" << timestamp << "\"";
|
||||
os << ",";
|
||||
os << "\"" << text << "\"";
|
||||
os << ")";
|
||||
LOG(INFO) << "Inserting " << timestamp << " into backup db";
|
||||
LOG(DEBUG) << "Inserting " << timestamp << ":" << text;
|
||||
return sqlite3_command(db(), os.str().c_str());
|
||||
}
|
||||
|
||||
int SQLiteBackup::remove(long long timestamp)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "DELETE from MESSAGES WHERE timestamp=";
|
||||
os << timestamp;
|
||||
LOG(INFO) << "Trying to remove " << timestamp << " from backup db";
|
||||
return sqlite3_command(db(), os.str().c_str());
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012 Range Networks, Inc.
|
||||
*
|
||||
* Written by Kurtis Heimerl, November 2012
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
/* This class stores messages for later replay if SMQ fails */
|
||||
|
||||
#ifndef DISK_BACKUP_H
|
||||
#define DISK_BACKUP_H
|
||||
|
||||
#include <Logger.h>
|
||||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include "sqlite3util.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef struct {
|
||||
long long timestamp;
|
||||
string text;
|
||||
} backup_msg;
|
||||
|
||||
typedef std::list<backup_msg> backup_msg_list;
|
||||
|
||||
//kurtis utility function
|
||||
long long get_msecs();
|
||||
|
||||
class SQLiteBackup {
|
||||
|
||||
private:
|
||||
|
||||
sqlite3 *mDB; ///< database connection
|
||||
|
||||
|
||||
public:
|
||||
|
||||
~SQLiteBackup();
|
||||
|
||||
/**
|
||||
Initialize the backup using parameters from gConfig.
|
||||
@return 0 if the database was successfully opened and initialized; 1 otherwise
|
||||
*/
|
||||
int init();
|
||||
|
||||
typedef enum {
|
||||
SUCCESS=0, ///< operation successful
|
||||
FAILURE=1, ///< operation not successful
|
||||
DELAYED=2, ///< operation successful, but effect delayed
|
||||
TRYAGAIN=3 ///< operation not attempted, try again later
|
||||
} Status;
|
||||
|
||||
|
||||
sqlite3 *db()
|
||||
{
|
||||
return mDB;
|
||||
}
|
||||
|
||||
/* get all the current elements in the db */
|
||||
/* responsibility on caller to delete each entry as well as the list
|
||||
-kurtis */
|
||||
backup_msg_list* get_stored_messages();
|
||||
|
||||
/* insert a message into the storage */
|
||||
int insert(long long timestamp, char* text);
|
||||
|
||||
/* remove an element from storage */
|
||||
int remove(long long timestamp);
|
||||
|
||||
};
|
||||
|
||||
#endif //diskbackup.h
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
This software is released under the following license:
|
||||
|
||||
Copyright (c) 1995-2002 Brian M. Clapper
|
||||
Copyright (c) 1995-2014 Brian M. Clapper
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms are
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
This software is released under the following license:
|
||||
|
||||
Copyright (c) 1995-2002 Brian M. Clapper
|
||||
Copyright (c) 1995-2014 Brian M. Clapper
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms are
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# A script to restart and just keep smqueue running.
|
||||
while true; do killall smqueue; sleep 2; ./smqueue; done
|
|
@ -0,0 +1,45 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Install smqueue and associated configuration files.
|
||||
|
||||
if [ $# -eq 1 ]; then
|
||||
PREFIX=$1
|
||||
else
|
||||
if [ "$USER" != "root" ]; then
|
||||
echo This script must be run as super-user.
|
||||
exit 1
|
||||
fi
|
||||
PREFIX=""
|
||||
fi
|
||||
|
||||
INSTALL_DIR=$PREFIX/OpenBTS
|
||||
UPSTART_DIR=$PREFIX/etc/init
|
||||
CONFIG_DIR=$PREFIX/etc/OpenBTS
|
||||
|
||||
|
||||
|
||||
if [ ! -e $INSTALL_DIR ]; then
|
||||
mkdir -p $INSTALL_DIR
|
||||
fi
|
||||
|
||||
if [ ! -e $UPSTART_DIR ]; then
|
||||
mkdir -p $UPSTART_DIR
|
||||
fi
|
||||
|
||||
if [ ! -e $CONFIG_DIR ]; then
|
||||
mkdir -p $CONFIG_DIR
|
||||
fi
|
||||
|
||||
cp smqueue $INSTALL_DIR
|
||||
cp smqueue.conf $UPSTART_DIR
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
cp smqueue.example.sql $CONFIG_DIR
|
||||
sqlite3 $CONFIG_DIR/smqueue.db ".read smqueue.example.sql"
|
||||
else
|
||||
cp smqueue.example.sql $CONFIG_DIR/
|
||||
fi
|
||||
|
||||
chown -R openbts $CONFIG_DIR
|
||||
chown -R openbts $INSTALL_DIR
|
||||
chmod -R a-w $INSTALL_DIR
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribuion.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Smcommands.cpp - Short Message (SMS) commands ("shortcodes") for OpenBTS.
|
||||
* Written by John Gilmore, August 2009.
|
||||
|
@ -34,7 +50,6 @@
|
|||
|
||||
using namespace std;
|
||||
using namespace SMqueue;
|
||||
|
||||
extern ConfigurationTable gConfig;
|
||||
|
||||
|
||||
|
@ -54,7 +69,7 @@ whiplash_quit (const char *imsi, const char *msgtext, short_code_params *scp)
|
|||
return SCA_EXEC_SMQUEUE;
|
||||
}
|
||||
if (!strncmp("testsave", msgtext+len+1, 4)) {
|
||||
scp->scp_smq->save_queue_to_file(gConfig.getStr("SC.WhiplashQuit.SaveFile").c_str());
|
||||
scp->scp_smq->save_queue_to_file(gConfig.getStr("SC.WhiplashQuit.SaveFile").c_str()); // Save on whiplash_quit
|
||||
scp->scp_reply = new_strdup("Done.");
|
||||
return SCA_REPLY;
|
||||
}
|
||||
|
@ -78,7 +93,7 @@ shortcode_quick_chk (const char *imsi, const char *msgtext,
|
|||
{
|
||||
ostringstream answer;
|
||||
|
||||
answer << scp->scp_smq->time_sorted_list.size() << " queued.";
|
||||
answer << scp->scp_smq->time_sorted_list.size() << " queued."; // No lock okay
|
||||
scp->scp_reply = new_strdup(answer.str().c_str());
|
||||
return SCA_REPLY;
|
||||
}
|
||||
|
@ -93,10 +108,11 @@ shortcode_four_one_one (const char *imsi, const char *msgtext,
|
|||
{
|
||||
ostringstream answer;
|
||||
|
||||
short_msg_p_list::iterator x;
|
||||
int n = 0, missing = 0, registering = 0, bouncing = 0;
|
||||
|
||||
for (x = scp->scp_smq->time_sorted_list.begin();
|
||||
smq.lockSortedList();
|
||||
short_msg_p_list::iterator x;
|
||||
for (x = scp->scp_smq->time_sorted_list.begin(); // locked
|
||||
x != scp->scp_smq->time_sorted_list.end(); x++) {
|
||||
n++;
|
||||
switch (x->state) {
|
||||
|
@ -121,10 +137,13 @@ shortcode_four_one_one (const char *imsi, const char *msgtext,
|
|||
registering++;
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
|
||||
} //switch
|
||||
} // for
|
||||
smq.unlockSortedList();
|
||||
|
||||
answer << n << " queued";
|
||||
if (missing)
|
||||
answer << ", " << missing << " unlocatable";
|
||||
|
@ -148,7 +167,7 @@ shortcode_four_one_one (const char *imsi, const char *msgtext,
|
|||
char *newfrom = scp->scp_smq->my_hlr.getCLIDLocal(username);
|
||||
answer << "phonenum " << newfrom;
|
||||
|
||||
time_t now = time(NULL);
|
||||
time_t now = time(NULL); // Use real time for logging
|
||||
char timebuf[26+/*slop*/4]; //
|
||||
answer << ", ";
|
||||
ctime_r(&now, timebuf);
|
||||
|
@ -166,8 +185,8 @@ shortcode_four_one_one (const char *imsi, const char *msgtext,
|
|||
* Remove a message from the queue, by its tag.
|
||||
* If first char is "-", don't reply, just do it.
|
||||
* (this keeps the reply out of the queue, while debugging.)
|
||||
* If argument is "6000", then delete any queued message with
|
||||
* timeout greater than 5000 seconds.
|
||||
* Delete any queued message with
|
||||
* timeout greater than 5000 seconds (83 minutes).
|
||||
*/
|
||||
enum short_code_action
|
||||
shortcode_zap_queued (const char *imsi, const char *msgtext,
|
||||
|
@ -183,14 +202,14 @@ shortcode_zap_queued (const char *imsi, const char *msgtext,
|
|||
msgtext++;
|
||||
}
|
||||
|
||||
smq.lockSortedList();
|
||||
if (!strcmp(gConfig.getStr("SC.ZapQueued.Password").c_str(), msgtext)) {
|
||||
// Delete all messages in queue in NO_STATE state or with
|
||||
// huge timeouts.
|
||||
short_msg_p_list::iterator x;
|
||||
time_t toolate = 5000
|
||||
+ scp->scp_smq->time_sorted_list.begin()->gettime();
|
||||
int n = 0;
|
||||
|
||||
short_msg_p_list::iterator x;
|
||||
time_t toolate = SMq::LONGDELETMS // 83 minutes
|
||||
+ scp->scp_smq->time_sorted_list.begin()->msgettime();
|
||||
for (x = scp->scp_smq->time_sorted_list.begin();
|
||||
x != scp->scp_smq->time_sorted_list.end(); x++) {
|
||||
if (x->state == NO_STATE || toolate <= x->next_action_time) {
|
||||
|
@ -211,12 +230,13 @@ shortcode_zap_queued (const char *imsi, const char *msgtext,
|
|||
answer << "Deleting queued msg '" << msgtext
|
||||
<< " in state " << sent_msg->state
|
||||
<< " and timeout "
|
||||
<< sent_msg->next_action_time - sent_msg->gettime();
|
||||
<< sent_msg->next_action_time - sent_msg->msgettime();
|
||||
resplist.splice(resplist.begin(),
|
||||
scp->scp_smq->time_sorted_list, sent_msg);
|
||||
resplist.pop_front(); // pop and delete the sent_msg.
|
||||
}
|
||||
}
|
||||
smq.unlockSortedList();
|
||||
|
||||
scp->scp_reply = new_strdup(answer.str().c_str());
|
||||
return noreply? SCA_DONE: SCA_REPLY;
|
||||
|
@ -278,6 +298,7 @@ shortcode_register (const char *imsi, const char *msgtext,
|
|||
default:
|
||||
answer << "Error: invalid character '" << *p << "' in requested number";
|
||||
badnum++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*q++ = '\0'; // Null-terminate it.
|
||||
|
@ -361,25 +382,6 @@ shortcode_register (const char *imsi, const char *msgtext,
|
|||
|
||||
|
||||
|
||||
enum short_code_action
|
||||
shortcode_balance (const char *imsi, const char *msgtext,
|
||||
short_code_params *scp)
|
||||
{
|
||||
SubscriberRegistry& hlr = scp->scp_smq->my_hlr;
|
||||
int accountBalance = 0;
|
||||
SubscriberRegistry::Status stat = hlr.balanceRemaining(imsi,accountBalance);
|
||||
if (stat != SubscriberRegistry::SUCCESS) {
|
||||
LOG(ALERT) << "cannot check account for user " << imsi;
|
||||
scp->scp_reply = new_strdup("operation failed");
|
||||
} else {
|
||||
char rsp[200];
|
||||
sprintf(rsp,gConfig.getStr("SC.Balance.String").c_str(),accountBalance);
|
||||
scp->scp_reply = new_strdup(rsp);
|
||||
}
|
||||
return SCA_REPLY;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Here is where we list all the functions that we care to make
|
||||
* available -- along with their phone numbers.
|
||||
|
@ -401,8 +403,6 @@ SMqueue::init_smcommands (short_code_map_t *scm)
|
|||
(*scm)[gConfig.getStr("SC.WhiplashQuit.Code").c_str()] = whiplash_quit;
|
||||
if (gConfig.defines("SC.SMSC.Code"))
|
||||
(*scm)[gConfig.getStr("SC.SMSC.Code").c_str()] = shortcode_smsc;
|
||||
if (gConfig.defines("SC.Balance.Code"))
|
||||
(*scm)[gConfig.getStr("SC.Balance.Code").c_str()] = shortcode_balance;
|
||||
|
||||
|
||||
// (*scm)["666"] = shortcode_text_access;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Written by John Gilmore, July 2009.
|
||||
*
|
||||
* Copyright 2009 Free Software Foundation, Inc.
|
||||
* Copyright 2014 Range Networks, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -32,11 +33,14 @@
|
|||
#include <cstdlib> // l64a
|
||||
#include <arpa/inet.h> // inet_ntop
|
||||
|
||||
|
||||
#include "smnet.h"
|
||||
#include "smqueue.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace SMqueue {
|
||||
|
||||
// Because the abort function isn't always accessible in C--?
|
||||
|
@ -87,13 +91,15 @@ SMnet::send_dgram(char *buffer, size_t buffsize, char *toaddr,
|
|||
}
|
||||
|
||||
|
||||
/* Talk to the GSM engine... */
|
||||
/* Talk to the GSM engine...
|
||||
* good return true
|
||||
* bad return false
|
||||
* */
|
||||
bool
|
||||
SMnet::deliver_msg_datagram(SMqueue::short_msg_pending *smp)
|
||||
{
|
||||
char *scheme, *host, *port;
|
||||
int s, i;
|
||||
|
||||
// Make sure the text is valid before writing it for debug,
|
||||
// or delivering it to a handset.
|
||||
smp->make_text_valid();
|
||||
|
@ -174,7 +180,7 @@ SMnet::deliver_msg_datagram(SMqueue::short_msg_pending *smp)
|
|||
|
||||
/*
|
||||
* Network listener for SIP Short Messages.
|
||||
* Timeout in milliseconds (negative means infinity).
|
||||
* Timeout in milliseconds (negative means infinity)
|
||||
*
|
||||
* Result is <0 if error;
|
||||
* Result is >0 if buffer contains a received packet.
|
||||
|
@ -182,6 +188,8 @@ SMnet::deliver_msg_datagram(SMqueue::short_msg_pending *smp)
|
|||
* our caller.)
|
||||
* Result == 0 if caller was interested in writing, there's no received
|
||||
* packet yet, and it's OK to write now. OR if we timed out.
|
||||
*
|
||||
* Reads data in from the network (opned UDP socket on a specific port
|
||||
*/
|
||||
int
|
||||
SMnet::get_next_dgram (char *buffer, size_t bufferlen, int mstimeout)
|
||||
|
@ -191,13 +199,21 @@ SMnet::get_next_dgram (char *buffer, size_t bufferlen, int mstimeout)
|
|||
short revents;
|
||||
socklen_t addrlen;
|
||||
size_t recvlength;
|
||||
|
||||
LOG(DEBUG) << "Try to load datagram tmo " << mstimeout << " socket fd " << sockets[0].fd;
|
||||
|
||||
// verifySocket(1); // Was used to verify socket are working correctly
|
||||
i = poll_sockets(mstimeout);
|
||||
if (i < 0) // error
|
||||
if (i < 0) { // error
|
||||
LOG(DEBUG) << "Error returned from poll";
|
||||
return i;
|
||||
if (i == 0) // timeout
|
||||
}
|
||||
if (i == 0) {// timeout
|
||||
LOG(DEBUG) << "Timeout returned from poll";
|
||||
return 0;
|
||||
}
|
||||
|
||||
//LOG(DEBUG) << "Got past poll for socket";
|
||||
for (j = 0; j < numsockets; j++) { // Walk the sockets.
|
||||
fd = sockets[j].fd;
|
||||
revents = sockets[j].revents;
|
||||
|
@ -211,6 +227,8 @@ SMnet::get_next_dgram (char *buffer, size_t bufferlen, int mstimeout)
|
|||
// FIXME, TCP and files aren't supported yet
|
||||
addrlen = sizeof(src_addr);
|
||||
flags = MSG_DONTWAIT|MSG_TRUNC;
|
||||
|
||||
// Read from socket
|
||||
recvlength = recvfrom(fd, buffer, bufferlen, flags,
|
||||
(sockaddr *)&src_addr, &addrlen);
|
||||
if (recvlength < 0) {
|
||||
|
@ -267,6 +285,9 @@ SMnet::get_next_dgram (char *buffer, size_t bufferlen, int mstimeout)
|
|||
* Make one or more sockets and set up to listen on them.
|
||||
* This function is xxx ought-to-be ipv6-agnostic, and is even
|
||||
* almost UDP/TCP-agnostic.
|
||||
* returns
|
||||
* true got socket
|
||||
* false no socket
|
||||
*/
|
||||
bool
|
||||
SMnet::listen_on_port(std::string port)
|
||||
|
@ -284,13 +305,14 @@ SMnet::listen_on_port(std::string port)
|
|||
s = getaddrinfo(NULL, (port.c_str()), &myhints, &myaddrs);
|
||||
if (s != 0) {
|
||||
LOG(ERR) << "listen_on_port(" << port
|
||||
<< ") can't get addr/port to listen on";
|
||||
return -1;
|
||||
<< ") can't get addr/port to listen on" ;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ap = myaddrs; ap != NULL; ap = ap->ai_next) {
|
||||
|
||||
int fd, i;
|
||||
LOG(DEBUG) << "listen_on_port try address " << string_addr (ap, true);
|
||||
|
||||
fd = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
|
||||
if (fd < 0)
|
||||
|
@ -299,9 +321,9 @@ SMnet::listen_on_port(std::string port)
|
|||
i = bind(fd, ap->ai_addr, ap->ai_addrlen);
|
||||
if (i < 0) {
|
||||
LOG(ERR) << "listen_on_port(" << port
|
||||
<< ") can't bind to addr '"
|
||||
<< ") can't bind (It's okay as long as one port is opened) to addr '"
|
||||
<< string_addr (ap, true) << "': "
|
||||
<< strerror(errno);
|
||||
<< strerror(errno) << " errno:" << errno;
|
||||
close(fd); // Don't leave it dangling
|
||||
continue; // Try another
|
||||
}
|
||||
|
@ -312,12 +334,12 @@ SMnet::listen_on_port(std::string port)
|
|||
#endif
|
||||
|
||||
// Now set up our class to poll on, and use, this socket.
|
||||
add_socket (fd, POLLIN|POLLPRI, ap->ai_family,
|
||||
add_socket(fd, POLLIN|POLLPRI, ap->ai_family,
|
||||
ap->ai_socktype, ap->ai_protocol, ap->ai_addr,
|
||||
ap->ai_addrlen);
|
||||
// Be slightly verbose here.
|
||||
LOG(INFO) << "Listening at address '"
|
||||
<< string_addr (ap, true) << "'.";
|
||||
LOG(ERR) << "Listening at address '"
|
||||
<< string_addr (ap, true) << " fd " << fd ;
|
||||
gotasocket++;
|
||||
// And keep looping to make several sockets if we can!
|
||||
}
|
||||
|
@ -576,4 +598,35 @@ SMnet::new_call_number()
|
|||
}
|
||||
|
||||
|
||||
} // namespace SMlistener
|
||||
/*
|
||||
* socketnumber 1-N based
|
||||
*/
|
||||
void SMnet::verifySocket(int socketNum) {
|
||||
int optval;
|
||||
socklen_t optlen;
|
||||
int rc;
|
||||
|
||||
if (!sockets || numsockets == 0 || (socketNum > numsockets )) {
|
||||
LOG(DEBUG) << "No socket to verify";
|
||||
return;
|
||||
}
|
||||
|
||||
optlen = sizeof(optval);
|
||||
rc = getsockopt(sockets[socketNum-1].fd, SOL_SOCKET, SO_TYPE, &optval, &optlen);
|
||||
if (rc == 0) {
|
||||
if (optlen == sizeof(int)) {
|
||||
if (optval == 0) {
|
||||
LOG(DEBUG) << "Socket not valid zero optval";
|
||||
} else {
|
||||
LOG(DEBUG) << "Socket valid type " << optval;
|
||||
}
|
||||
} else {
|
||||
LOG(DEBUG) << "Socket not valid optlen wrong " << optval;
|
||||
}
|
||||
} else {
|
||||
LOG(DEBUG) << "getsockopt returned error " << rc;
|
||||
}
|
||||
|
||||
} // SMnet::verifySocket
|
||||
|
||||
} // namespace SMQueue
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
|
||||
/*
|
||||
* SMlistener.h - Network SIP handler for Short Messages (SMS's) for OpenBTS.
|
||||
* Written by John Gilmore, July 2009.
|
||||
*
|
||||
* Copyright 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
Copyright 2011, 2013, 2014 Range Networks, Inc.
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
|
@ -28,6 +30,7 @@
|
|||
#include "poll.h"
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <Logger.h>
|
||||
|
||||
namespace SMqueue {
|
||||
|
||||
|
@ -266,6 +269,9 @@ class SMnet {
|
|||
*/
|
||||
char *
|
||||
new_call_number();
|
||||
|
||||
void verifySocket(int socketNum);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
# smqueue - Range Networks basic SMSC
|
||||
#
|
||||
# This service runs smqueue from the point the system is
|
||||
# started until it is shut down again.
|
||||
|
||||
start on stopped rc RUNLEVEL=[2345]
|
||||
stop on runlevel [!2345]
|
||||
|
||||
respawn
|
||||
exec /OpenBTS/smqueue
|
1743
smqueue/smqueue.cpp
1743
smqueue/smqueue.cpp
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,7 @@
|
|||
* SMqueue.h - In-memory queue manager for Short Messages (SMS's) for OpenBTS.
|
||||
* Written by John Gilmore, July 2009.
|
||||
*
|
||||
* Copyright 2009 Free Software Foundation, Inc.
|
||||
* Copyright 2009, 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -19,9 +19,11 @@
|
|||
* See the COPYING file in the main directory for details.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SM_QUEUE_H
|
||||
#define SM_QUEUE_H
|
||||
|
||||
#include "SmqGlobals.h"
|
||||
#include <time.h>
|
||||
//#include <osipparser2/osip_message.h> /* from osipparser2 */
|
||||
#include <stdlib.h> /* for osipparser2 */
|
||||
|
@ -35,8 +37,9 @@
|
|||
|
||||
#include "smnet.h" // My network support
|
||||
#include <SubscriberRegistry.h> // My home location register
|
||||
|
||||
#include <Logger.h>
|
||||
#include "diskbackup.h"
|
||||
void ProcessReceivedMsg();
|
||||
|
||||
// That's awful OSIP has a CR define.
|
||||
// It clashes with our innocent L2Address::CR().
|
||||
|
@ -74,19 +77,19 @@ enum sm_state { // timeout, next-state-if-timeout
|
|||
NO_STATE,
|
||||
INITIAL_STATE,
|
||||
REQUEST_FROM_ADDRESS_LOOKUP,
|
||||
ASKED_FOR_FROM_ADDRESS_LOOKUP,
|
||||
ASKED_FOR_FROM_ADDRESS_LOOKUP, //3
|
||||
|
||||
AWAITING_TRY_DESTINATION_IMSI,
|
||||
REQUEST_DESTINATION_IMSI,
|
||||
REQUEST_DESTINATION_IMSI, // 5
|
||||
ASKED_FOR_DESTINATION_IMSI,
|
||||
|
||||
AWAITING_TRY_DESTINATION_SIPURL,
|
||||
REQUEST_DESTINATION_SIPURL,
|
||||
REQUEST_DESTINATION_SIPURL, // 8
|
||||
ASKED_FOR_DESTINATION_SIPURL,
|
||||
|
||||
AWAITING_TRY_MSG_DELIVERY,
|
||||
REQUEST_MSG_DELIVERY,
|
||||
ASKED_FOR_MSG_DELIVERY,
|
||||
AWAITING_TRY_MSG_DELIVERY, // 10
|
||||
REQUEST_MSG_DELIVERY, // 11
|
||||
ASKED_FOR_MSG_DELIVERY, // 12
|
||||
|
||||
DELETE_ME_STATE,
|
||||
|
||||
|
@ -107,6 +110,7 @@ std::string sm_state_name(enum sm_state astate);
|
|||
extern bool osip_initialized;
|
||||
extern struct osip *osipptr;
|
||||
|
||||
|
||||
/* In-memory object representing a Short Message. These are kept as
|
||||
text strings (as we received them) and only parsed when we need to
|
||||
process them. This keeps memory usage way down for medium to long
|
||||
|
@ -151,8 +155,6 @@ class short_msg {
|
|||
|
||||
bool from_relay;
|
||||
|
||||
long long timestamp; //timestamp for backup id'ing
|
||||
|
||||
short_msg () :
|
||||
text_length (0),
|
||||
text (NULL),
|
||||
|
@ -165,8 +167,7 @@ class short_msg {
|
|||
tl_message(NULL),
|
||||
ms_to_sc(false),
|
||||
need_repack(true),
|
||||
from_relay(false),
|
||||
timestamp(get_msecs())
|
||||
from_relay(false)
|
||||
{
|
||||
}
|
||||
// Make a short message, perhaps taking responsibility for deleting
|
||||
|
@ -183,8 +184,7 @@ class short_msg {
|
|||
tl_message(NULL),
|
||||
ms_to_sc(false),
|
||||
need_repack(true),
|
||||
from_relay(false),
|
||||
timestamp(get_msecs())
|
||||
from_relay(false)
|
||||
{
|
||||
if (!use_my_memory) {
|
||||
text = new char [text_length+1];
|
||||
|
@ -211,8 +211,7 @@ class short_msg {
|
|||
tl_message(NULL),
|
||||
ms_to_sc(false),
|
||||
need_repack(true),
|
||||
from_relay(sm.from_relay),
|
||||
timestamp(get_msecs())
|
||||
from_relay(sm.from_relay)
|
||||
{
|
||||
if (text_length) {
|
||||
text = new char [text_length+1];
|
||||
|
@ -233,8 +232,7 @@ class short_msg {
|
|||
rp_data(NULL),
|
||||
tl_message(NULL),
|
||||
ms_to_sc(false),
|
||||
need_repack(false),
|
||||
timestamp(get_msecs())
|
||||
need_repack(false)
|
||||
{
|
||||
text = new char [text_length+1];
|
||||
strncpy(text, str.data(), text_length);
|
||||
|
@ -255,7 +253,7 @@ class short_msg {
|
|||
delete [] text;
|
||||
delete rp_data;
|
||||
delete tl_message;
|
||||
};
|
||||
}
|
||||
|
||||
// Pseudo-constructor due to inability to run constructors on
|
||||
// members of lists.
|
||||
|
@ -335,7 +333,7 @@ class short_msg {
|
|||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // parse
|
||||
|
||||
/* Anytime a caller CHANGES the values in the parsed tree of the
|
||||
message, they MUST call this, to let the caching system
|
||||
|
@ -398,7 +396,7 @@ class short_msg {
|
|||
parsed = NULL;
|
||||
parsed_is_valid = false;
|
||||
parsed_is_better = false;
|
||||
}
|
||||
} //unparse
|
||||
|
||||
std::string get_text() const
|
||||
{
|
||||
|
@ -452,13 +450,16 @@ class short_msg {
|
|||
case UNSUPPORTED_CONTENT:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
} // switch
|
||||
} // get_text
|
||||
|
||||
|
||||
/* Kind of a nasty hack to convert a message as it is going out. Generally from rpdu to text. */
|
||||
void convert_message(ContentType to) {
|
||||
convert_content_type = to;
|
||||
}
|
||||
|
||||
|
||||
void do_not_convert_message() {
|
||||
convert_content_type = UNSUPPORTED_CONTENT;
|
||||
}
|
||||
|
@ -473,14 +474,13 @@ class short_msg {
|
|||
extern /*static*/ int (*timeouts[STATE_MAX_PLUS_ONE])[STATE_MAX_PLUS_ONE];
|
||||
|
||||
class SMq;
|
||||
|
||||
class short_msg_pending: public short_msg {
|
||||
public:
|
||||
enum sm_state state; // State of processing
|
||||
time_t next_action_time; // When to do something different
|
||||
int retries; // How many times we've retried
|
||||
// this message.
|
||||
int cost; // cost of delivering this message, -1 until defined
|
||||
string service; // service cost name
|
||||
char srcaddr[16]; // Source address (ipv4 or 6 or ...)
|
||||
socklen_t srcaddrlen; // Valid length of src address.
|
||||
char *qtag; // Tag that identifies this msg
|
||||
|
@ -505,8 +505,6 @@ class short_msg_pending: public short_msg {
|
|||
state (NO_STATE),
|
||||
next_action_time (0),
|
||||
retries (0),
|
||||
cost(-1),
|
||||
service(""),
|
||||
// srcaddr({0}), // can't seem to initialize an array?
|
||||
srcaddrlen(0),
|
||||
qtag (NULL),
|
||||
|
@ -522,8 +520,6 @@ class short_msg_pending: public short_msg {
|
|||
state (NO_STATE),
|
||||
next_action_time (0),
|
||||
retries (0),
|
||||
cost(-1),
|
||||
service(""),
|
||||
// srcaddr({0}), // can't seem to initialize an array?
|
||||
srcaddrlen(0),
|
||||
qtag (NULL),
|
||||
|
@ -538,7 +534,6 @@ class short_msg_pending: public short_msg {
|
|||
state (NO_STATE),
|
||||
next_action_time (0),
|
||||
retries (0),
|
||||
cost(-1),
|
||||
// srcaddr({0}), // can't seem to initialize an array?
|
||||
srcaddrlen(0),
|
||||
qtag (NULL),
|
||||
|
@ -560,8 +555,6 @@ class short_msg_pending: public short_msg {
|
|||
state (smp.state),
|
||||
next_action_time (smp.next_action_time),
|
||||
retries (smp.retries),
|
||||
cost(smp.cost),
|
||||
service(smp.service),
|
||||
// srcaddr({0}), // can't seem to initialize an array?
|
||||
srcaddrlen(smp.srcaddrlen),
|
||||
qtag (NULL),
|
||||
|
@ -638,18 +631,27 @@ class short_msg_pending: public short_msg {
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Optimize this later so we don't make so many kernel calls. */
|
||||
time_t gettime () { return time(NULL); };
|
||||
|
||||
time_t msgettime() {
|
||||
struct timespec tv;
|
||||
clock_gettime(CLOCK_REALTIME, &tv);
|
||||
unsigned long time_in_mill =
|
||||
(tv.tv_sec * 1000UL) + (tv.tv_nsec / 1000000UL) ; // convert tv_sec & tv_usec to millisecond
|
||||
return time_in_mill;
|
||||
}
|
||||
|
||||
|
||||
/* Reset the message's state and timeout. Timeout is set based
|
||||
on the current state and the new state. */
|
||||
void set_state(enum sm_state newstate) {
|
||||
next_action_time = gettime() +
|
||||
next_action_time = msgettime() +
|
||||
(*SMqueue::timeouts[state])[newstate];
|
||||
LOG(DEBUG) << "Set state orig " << state << " Newstate " << newstate
|
||||
<< " Timeout value " << *SMqueue::timeouts[state][newstate];
|
||||
state = newstate;
|
||||
/* If we're in a queue, some code in another class is now going
|
||||
to have to change our queue position. */
|
||||
};
|
||||
}
|
||||
|
||||
/* Reset the message's state and timeout. Timeout is argument. */
|
||||
void set_state(enum sm_state newstate, time_t timeout) {
|
||||
|
@ -657,7 +659,7 @@ class short_msg_pending: public short_msg {
|
|||
state = newstate;
|
||||
/* If we're in a queue, some code in another class is now going
|
||||
to have to change our queue position. */
|
||||
};
|
||||
}
|
||||
|
||||
/* Check that the message is valid, and set the qtag and qtaghash
|
||||
from the message's contents. Result is 0 for valid, or
|
||||
|
@ -680,21 +682,6 @@ class short_msg_pending: public short_msg {
|
|||
bool
|
||||
check_host_port(char *host, char *port);
|
||||
|
||||
/* Check to see if it is an in-network destination. */
|
||||
bool local_destination(SubscriberRegistry& hlr) const;
|
||||
|
||||
/* Check to see if it is from a local user, as opposed to from the gateway. */
|
||||
bool local_source(SubscriberRegistry& hlr) const;
|
||||
|
||||
/* Calculate the cost of delivering this message and set the cost field. */
|
||||
int set_delivery_cost(SubscriberRegistry& hlr);
|
||||
|
||||
/* Check to see if the user has enough credit to send the message. Also sets the cost field. */
|
||||
bool sufficient_credit(SubscriberRegistry& hlr) const;
|
||||
|
||||
/* Debit the account when a message is verified as delivered. */
|
||||
void debit_account(SubscriberRegistry& hlr) const;
|
||||
|
||||
/* Generate a billing record. */
|
||||
void write_cdr(SubscriberRegistry& hlr) const;
|
||||
|
||||
|
@ -761,10 +748,10 @@ typedef enum short_code_action (*short_func_t)
|
|||
* Associative map between target phone numbers (short codes) and
|
||||
* function pointers that implement those numbers.
|
||||
*/
|
||||
typedef std::map<std::string,short_func_t> short_code_map_t;
|
||||
typedef std::map<std::string,short_func_t> short_code_map_t; // Maps description (phone number) to function to call
|
||||
|
||||
/* What fills in that map */
|
||||
void init_smcommands (short_code_map_t *scm);
|
||||
void init_smcommands(short_code_map_t *scm);
|
||||
|
||||
/*
|
||||
* Main class for SIP Short Message processing.
|
||||
|
@ -773,11 +760,37 @@ void init_smcommands (short_code_map_t *scm);
|
|||
class SMq {
|
||||
public:
|
||||
|
||||
// Put all timeouts in one place
|
||||
const static int TIMEOUTMS = 5000;
|
||||
const static int SMSRATELIMITMS = 1000;
|
||||
const static int LONGDELETMS = 5000000; // 83 minutes Used by SC.ZapQueued.Password
|
||||
const static int INCREASEACKEDMSGTMOMS = 60000; // 5 minutes
|
||||
|
||||
void InitBeforeMainLoop();
|
||||
void CleaupAfterMainreaderLoop();
|
||||
void InitInsideReaderLoop();
|
||||
|
||||
/* A list of all messages we know about, sorted by time of next
|
||||
action (assuming nothing arrives to change our mind before that
|
||||
time). */
|
||||
short_msg_p_list time_sorted_list;
|
||||
|
||||
std::string savefile; //SMq
|
||||
bool please_re_exec;
|
||||
|
||||
pthread_mutexattr_t mutexSLAttr;
|
||||
pthread_mutex_t sortedListMutex;
|
||||
|
||||
void unlockSortedList() {
|
||||
// LOG(DEBUG) << "UNLOCK"; // debug opnly
|
||||
pthread_mutex_unlock(&sortedListMutex);
|
||||
}
|
||||
|
||||
void lockSortedList() {
|
||||
// LOG(DEBUG) << "LOCK"; // debug only
|
||||
pthread_mutex_lock(&sortedListMutex);
|
||||
}
|
||||
|
||||
/* We may later want other accessors for faster access to various
|
||||
messages when things DO arrive. For now, linear search! */
|
||||
|
||||
|
@ -788,8 +801,6 @@ class SMq {
|
|||
messages and looking up their return and destination addresses. */
|
||||
SubscriberRegistry my_hlr;
|
||||
|
||||
SQLiteBackup my_backup;
|
||||
|
||||
/* Where to send SMS's that we can't route locally. */
|
||||
std::string global_relay;
|
||||
std::string global_relay_port;
|
||||
|
@ -814,10 +825,15 @@ class SMq {
|
|||
|
||||
/* Set this to true when you want main loop to stop. */
|
||||
bool stop_main_loop;
|
||||
|
||||
/* Set this to true when you want the program to re-exec itself
|
||||
instead of terminating after the main loop stops. */
|
||||
bool reexec_smqueue;
|
||||
|
||||
// Input from command line
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
/* Constructor */
|
||||
SMq () :
|
||||
time_sorted_list (),
|
||||
|
@ -834,18 +850,31 @@ class SMq {
|
|||
stop_main_loop (false),
|
||||
reexec_smqueue (false)
|
||||
{
|
||||
// We need recursive attribute set
|
||||
int mStatus;
|
||||
mStatus = pthread_mutexattr_init(&mutexSLAttr);
|
||||
if (mStatus != 0) { LOG(DEBUG) << "Mutex pthread_mutexattr_init error " << mStatus; }
|
||||
pthread_mutexattr_settype(&mutexSLAttr, PTHREAD_MUTEX_RECURSIVE);
|
||||
if (mStatus != 0) { LOG(DEBUG) << "Mutex pthread_mutexattr_settype error " << mStatus; }
|
||||
pthread_mutex_init(&sortedListMutex, &mutexSLAttr);
|
||||
if (mStatus != 0) { LOG(DEBUG) << "Mutex pthread_mutex_init error " << mStatus; }
|
||||
|
||||
my_hlr.init();
|
||||
my_backup.init();
|
||||
}
|
||||
|
||||
|
||||
/* Destructor */
|
||||
~SMq() {
|
||||
pthread_mutex_destroy(&sortedListMutex);
|
||||
}
|
||||
|
||||
|
||||
// Override operator= so -Weffc++ doesn't complain
|
||||
// *DISABLE* assignments by making the = operation private.
|
||||
private:
|
||||
SMq & operator= (const SMq &rvalue);
|
||||
public:
|
||||
|
||||
/* Destructor */
|
||||
|
||||
/* Set my own IP address, since I can't tell how I look to others. */
|
||||
void set_my_ipaddress(std::string myip) {
|
||||
my_ipaddress = myip;
|
||||
|
@ -858,7 +887,7 @@ class SMq {
|
|||
void set_my_2nd_ipaddress(std::string myip) {
|
||||
my_2nd_ipaddress = myip;
|
||||
// Point to it for message validity checking.
|
||||
// NOTE: that copy shares same storage as this one.
|
||||
// NOTE: that copy shares same storage as this one.LOG(DEBUG) << "Run once a minute stuff"
|
||||
short_msg_pending::smp_my_2nd_ipaddress = myip.c_str();
|
||||
}
|
||||
|
||||
|
@ -896,23 +925,14 @@ class SMq {
|
|||
/* Convert a short_msg to a given content type */
|
||||
//void convert_message(short_msg_pending *qmsg, short_msg::ContentType toType);
|
||||
|
||||
/* handle an incoming datagram */
|
||||
/* timestamp is used if you want to set the timestamp for an incoming message
|
||||
0 will cause a new timestamp to be generated */
|
||||
void handle_datagram(int len, char* buffer, long long timestamp, bool insert=true);
|
||||
|
||||
// Main loop listening for dgrams and processing them.
|
||||
void main_loop();
|
||||
void main_loop(int tmo);
|
||||
|
||||
/* If nothing happens for a while, handle that. */
|
||||
void process_timeout();
|
||||
|
||||
/* Verify that sufficient funds exist to send a particular message. */
|
||||
enum sm_state verify_funds(short_msg_p_list::iterator& qmsg);
|
||||
|
||||
/* Send a SIP response to acknowledge reciept of a short msg. */
|
||||
void respond_sip_ack(int errcode, short_msg_pending *smp,
|
||||
char *netaddr, size_t netaddrlen);
|
||||
void respond_sip_ack(int errcode, short_msg_pending *smp, char *netaddr, size_t netaddrlen);
|
||||
|
||||
/*
|
||||
* Originate a short message
|
||||
|
@ -1017,22 +1037,39 @@ class SMq {
|
|||
// new messages as a 1-entry short_msg_p_list and then move
|
||||
// them to the real list. Note that this moves the message's list
|
||||
// entry itself off the original list (which can then be discarded).
|
||||
// Push_front only does a copy so use splice ??
|
||||
void insert_new_message(short_msg_p_list &smp) {
|
||||
lockSortedList();
|
||||
time_sorted_list.splice (time_sorted_list.begin(), smp);
|
||||
time_sorted_list.begin()->set_state (INITIAL_STATE); // Note set state can move the entries in the queue
|
||||
// time_sorted_list.begin()->timeout = 0; // it is already
|
||||
// Low timeout will cause this msg to be at front of queue.
|
||||
unlockSortedList();
|
||||
debug_dump(); //svgfix
|
||||
ProcessReceivedMsg();
|
||||
}
|
||||
|
||||
// This version lets the initial state be set.
|
||||
void insert_new_message(short_msg_p_list &smp, enum sm_state s) {
|
||||
LOG(DEBUG) << "Insert message into queue 2";
|
||||
lockSortedList();
|
||||
time_sorted_list.splice (time_sorted_list.begin(), smp);
|
||||
time_sorted_list.begin()->set_state (s);
|
||||
// time_sorted_list.begin()->timeout = 0; // it is already
|
||||
// Low timeout will cause this msg to be at front of queue.
|
||||
unlockSortedList();
|
||||
debug_dump(); //svgfix
|
||||
ProcessReceivedMsg();
|
||||
}
|
||||
// This version lets the state and timeout be set.
|
||||
void insert_new_message(short_msg_p_list &smp, enum sm_state s,
|
||||
time_t t, bool insert = true) {
|
||||
if (insert && !my_backup.insert(smp.begin()->timestamp, smp.begin()->text)){
|
||||
LOG(INFO) << "Unable to backup message: " << time_sorted_list.begin()->timestamp;
|
||||
}
|
||||
void insert_new_message(short_msg_p_list &smp, enum sm_state s, time_t t) {
|
||||
LOG(DEBUG) << "Insert message into queue 3";
|
||||
lockSortedList();
|
||||
time_sorted_list.splice (time_sorted_list.begin(), smp);
|
||||
time_sorted_list.begin()->set_state (s, t);
|
||||
}
|
||||
// This version lets the initial state be set.
|
||||
void insert_new_message(short_msg_p_list &smp, enum sm_state s, bool insert=true) {
|
||||
insert_new_message(smp, s, 0, insert);
|
||||
}
|
||||
//Basic version
|
||||
void insert_new_message(short_msg_p_list &smp, bool insert=true) {
|
||||
insert_new_message(smp, INITIAL_STATE, insert);
|
||||
unlockSortedList();
|
||||
debug_dump(); //svgfix
|
||||
ProcessReceivedMsg();
|
||||
}
|
||||
|
||||
/* Debug dump of the queue and the SMq class in general. */
|
||||
|
@ -1056,6 +1093,7 @@ class SMq {
|
|||
*/
|
||||
void set_state(short_msg_p_list::iterator sm, enum sm_state newstate) {
|
||||
short_msg_p_list temp;
|
||||
lockSortedList();
|
||||
/* Extract the current sm from the time_sorted_list */
|
||||
temp.splice(temp.begin(), time_sorted_list, sm);
|
||||
sm->set_state(newstate);
|
||||
|
@ -1071,7 +1109,8 @@ class SMq {
|
|||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
unlockSortedList();
|
||||
} // set_state
|
||||
|
||||
/*
|
||||
* When we reset the state and timestamp of a message,
|
||||
|
@ -1081,8 +1120,8 @@ class SMq {
|
|||
* With multisets you can't splice an element out while keeping the
|
||||
* element... etc.
|
||||
*/
|
||||
void set_state(short_msg_p_list::iterator sm, enum sm_state newstate,
|
||||
time_t timestamp) {
|
||||
void set_state(short_msg_p_list::iterator sm, enum sm_state newstate, time_t timestamp) {
|
||||
lockSortedList();
|
||||
short_msg_p_list temp;
|
||||
/* Extract the current sm from the time_sorted_list */
|
||||
temp.splice(temp.begin(), time_sorted_list, sm);
|
||||
|
@ -1099,7 +1138,8 @@ class SMq {
|
|||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
unlockSortedList();
|
||||
} // set_state
|
||||
|
||||
/* Save the queue to a file; read it back from a file.
|
||||
Reading a queue file doesn't delete things that might already
|
||||
|
@ -1109,9 +1149,12 @@ class SMq {
|
|||
save_queue_to_file(std::string qfile);
|
||||
bool
|
||||
read_queue_from_file(std::string qfile);
|
||||
};
|
||||
|
||||
|
||||
}; // SMq class
|
||||
} // namespace SMqueue
|
||||
|
||||
extern SMqueue::SMq smq;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* SMSC.h - SMS Center implementation for OpenBTS.
|
||||
* Written by Alexander Chemeris, 2010.
|
||||
*
|
||||
* Copyright 2010 Free Software Foundation, Inc.
|
||||
* Copyright 2010, 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -181,7 +181,7 @@ short_code_action sendSIP_init_text(const char *imsi,
|
|||
void pack_tpdu(short_msg_p_list::iterator &smsg)
|
||||
{
|
||||
// Pack RP-DATA to bitstream
|
||||
RLFrame RPDU_new(smsg->rp_data->bitsNeeded());
|
||||
RLFrame RPDU_new(BitVector(smsg->rp_data->bitsNeeded()));
|
||||
smsg->rp_data->write(RPDU_new);
|
||||
LOG(DEBUG) << "New RLFrame: " << RPDU_new;
|
||||
|
||||
|
@ -274,46 +274,6 @@ short_code_action submitSMS(const char *imsi, const TLSubmit& submit,
|
|||
LOG(INFO) << "from " << imsi << " message: " << submit;
|
||||
const TLAddress& address = submit.DA();
|
||||
|
||||
// Hey! You can get to the HLR through the scp argument!
|
||||
SubscriberRegistry& hlr = scp->scp_smq->my_hlr;
|
||||
|
||||
// Is this message going to a short code?
|
||||
// Short codes costs are special cases and will be checked im the short code handlers thmeselves.
|
||||
bool isShortCode = (short_code_map.find(address.digits()) != short_code_map.end());
|
||||
|
||||
// TODO: If this is a short code, and we know that the cost will be 0, why waste time hitting the subscriber registry? -DCK
|
||||
// That means, don't look up the service, and don't check to see if any user is prepaid.
|
||||
|
||||
// FIXME: There are some helper functions in smqueue.cpp. Why not use those? Or move them somewhere to be used commonly. -DCK
|
||||
|
||||
// Get the delivery cost.
|
||||
string service;
|
||||
const char * dialedNumber = address.digits();
|
||||
if (hlr.getIMSI(dialedNumber)) service = gConfig.getStr("ServiceType.Local");
|
||||
else service = gConfig.getStr("ServiceType.Networked");
|
||||
int cost = hlr.serviceCost(service.c_str());
|
||||
if (isShortCode) cost = 0;
|
||||
if (cost>=0) scp->scp_qmsg_it->cost = cost;
|
||||
else { LOG(ALERT) << "cannot get cost for service type " << service; }
|
||||
scp->scp_qmsg_it->service = service;
|
||||
|
||||
// If the message is NOT inbound from the relay, bill
|
||||
if (!scp->scp_qmsg_it->from_relay) {
|
||||
// Check the subscriber's balance now.
|
||||
bool prepaid;
|
||||
hlr.isPrepaid(imsi,prepaid);
|
||||
int accountBalance = 0;
|
||||
SubscriberRegistry::Status stat = hlr.balanceRemaining(imsi,accountBalance);
|
||||
if (stat != SubscriberRegistry::SUCCESS) { LOG(ALERT) << "cannot check account for user " << imsi; }
|
||||
if (prepaid && cost!=0 && accountBalance<cost) {
|
||||
ostringstream os;
|
||||
// TODO: Make customizable
|
||||
os << "Account balance of " << accountBalance << " too low for service cost of " << cost << ".";
|
||||
scp->scp_reply = new_strdup(os.str().c_str());
|
||||
return SCA_REPLY;
|
||||
}
|
||||
}
|
||||
|
||||
//#if 0
|
||||
//This is broken under Unbuntu becasue of changes in the "mail" program.
|
||||
|
||||
|
@ -330,7 +290,7 @@ short_code_action submitSMS(const char *imsi, const TLSubmit& submit,
|
|||
*term = '\0';
|
||||
char* SMTPPayload = term+1;
|
||||
// Get the sender's E.164 to put in the subject line.
|
||||
char* clid = hlr.getCLIDLocal(imsi);
|
||||
char* clid = scp->scp_smq->my_hlr.getCLIDLocal(imsi);
|
||||
char subjectLine[200];
|
||||
if (!clid) sprintf(subjectLine,"from %s",imsi);
|
||||
else {
|
||||
|
@ -350,7 +310,7 @@ short_code_action submitSMS(const char *imsi, const TLSubmit& submit,
|
|||
// And whether of not we can resolve the destination, and a global relay does not exist,
|
||||
// AND the message is not to a shortcode.
|
||||
if (gConfig.getStr("SIP.GlobalRelay.IP").length() == 0 && gConfig.getStr("SMS.HTTPGateway.URL").length() != 0 &&
|
||||
!destinationNumber && !isShortCode)
|
||||
!destinationNumber)
|
||||
// If there is an external HTTP gateway, use it.
|
||||
return sendHTTP(address.digits(), body);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* SMSC.h - SMS Center implementation for OpenBTS.
|
||||
* Written by Alexander Chemeris, 2010.
|
||||
*
|
||||
* Copyright 2010 Free Software Foundation, Inc.
|
||||
* Copyright 2010, 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
|
2
sqlite3
2
sqlite3
|
@ -1 +1 @@
|
|||
Subproject commit 3d0dbe8e7a819585cac5064beabe9b22f8d47235
|
||||
Subproject commit effc8fe4744285c07e3710ab97231537a27b7997
|
|
@ -1,4 +0,0 @@
|
|||
SR http://wush.net/svn/range/software/public/subscriberRegistry/trunk
|
||||
CommonLibs http://wush.net/svn/range/software/public/CommonLibs/trunk
|
||||
sqlite3 http://wush.net/svn/range/software/public/sqlite3/trunk
|
||||
|
|
@ -31,12 +31,14 @@ noinst_PROGRAMS = \
|
|||
smtest_SOURCES = \
|
||||
smtest.cpp
|
||||
smtest_LDADD = \
|
||||
$(COMMON_LA)
|
||||
$(COMMON_LA) \
|
||||
$(SQLITE_LA)
|
||||
|
||||
smrelaytest_SOURCES = \
|
||||
smrelaytest.cpp
|
||||
smrelaytest_LDADD = \
|
||||
$(COMMON_LA)
|
||||
$(COMMON_LA) \
|
||||
$(SQLITE_LA)
|
||||
|
||||
sminterface_SOURCES = \
|
||||
sminterface.cpp
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
||||
* Copyright 2011 Range Networks, Inc.
|
||||
* Copyright 2011, 2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2013 Range Networks, Inc.
|
||||
* Copyright 2012-2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
|
@ -29,6 +29,10 @@
|
|||
|
||||
#include <Sockets.h>
|
||||
|
||||
// (pat 8-9-2013) Unfortunately we need a default config to eliminate link errors.
|
||||
#include <Configuration.h>
|
||||
ConfigurationTable gConfig("/etc/OpenBTS/smqueue.db","smrelaytest");
|
||||
|
||||
/** Submit an SMS for delivery.
|
||||
* @return The server return code.
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2013 Range Networks, Inc.
|
||||
* Copyright 2012-2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
|
|
|
@ -1,7 +1,27 @@
|
|||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright 2012-2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "smtest.h"
|
||||
|
||||
|
@ -10,6 +30,10 @@
|
|||
|
||||
#include <Sockets.h>
|
||||
|
||||
// (pat 8-9-2013) Unfortunately we need a default config to eliminate link errors.
|
||||
#include <Configuration.h>
|
||||
ConfigurationTable gConfig("/etc/OpenBTS/smqueue.db","smtest");
|
||||
|
||||
/** Submit an SMS for delivery.
|
||||
* @return The server return code.
|
||||
*/
|
||||
|
|
|
@ -1,8 +1,28 @@
|
|||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright 2012-2014 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef smtest_h
|
||||
#define smtest_h
|
||||
|
|
Loading…
Reference in New Issue