diff --git a/.gitmodules b/.gitmodules index 1f3a80c..65bd2bd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,3 +6,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 diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e69de29 diff --git a/COPYING b/COPYING index 28e4621..b5af151 100644 --- a/COPYING +++ b/COPYING @@ -693,14 +693,6 @@ Interaction; Use with the GNU General Public License"). This exemption of interfaces other than the GSM air interface from the requirements of Section 13 is an additional permission granted to you. -2. GSM "A5" cipher stream generation libraries - -Notwithstanding any other provision of this License, you have -permission to link the Program with GSM "A5" cipher-stream generation -libraries provided under any license that allows redistribution of -those libraries in binary form, provided that the function of any such -library is limited to the generation of cipher-steam bits. - Non-Permissive Terms Supplementing The License @@ -712,9 +704,11 @@ license does not include the right to use the OpenBTS trademark in commerce. This additional non-permissive term is consistent with Section 7 of the AGPLv3 license. + END OF ADDITIONAL TERMS + How to comply with Section 13 of the AGPLv3 license. The recommended method for compliance with Section 13 of the AGPLv3 license is diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/CommonLibs b/CommonLibs index bd94d0a..abec8da 160000 --- a/CommonLibs +++ b/CommonLibs @@ -1 +1 @@ -Subproject commit bd94d0a9883002daa8310b601f28eed3b0d87d2f +Subproject commit abec8dabb69f8f2bdefdb9bcca340b89f43ce419 diff --git a/Globals/Globals.cpp b/Globals/Globals.cpp new file mode 100644 index 0000000..a8830bb --- /dev/null +++ b/Globals/Globals.cpp @@ -0,0 +1,25 @@ +/**@file Global system parameters. */ +/* +* Copyright 2013 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. + +*/ + +/* + This file keeps global system parameters. +*/ + +#include "config.h" +#include + +const char *gVersionString = "release " VERSION " built " __DATE__ " rev" SVN_REV " "; diff --git a/Globals/Globals.h b/Globals/Globals.h new file mode 100644 index 0000000..cdde551 --- /dev/null +++ b/Globals/Globals.h @@ -0,0 +1,36 @@ +/**@file Global system parameters. */ +/* +* Copyright 2013 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. + +*/ + +/* + This file keeps global system parameters. +*/ + +#ifndef GLOBALS_H +#define GLOBALS_H + +#include + + +/** + Just about everything goes into the configuration table. + This should be defined in the main body of the top-level application. +*/ +extern ConfigurationTable gConfig; + +/** The version string. */ +extern const char *gVersionString; +#endif diff --git a/Globals/Makefile.am b/Globals/Makefile.am new file mode 100644 index 0000000..f987b33 --- /dev/null +++ b/Globals/Makefile.am @@ -0,0 +1,33 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This software is distributed under the terms of the GNU Public License. +# See the COPYING 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 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +include $(top_srcdir)/Makefile.common + +AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) +AM_CXXFLAGS = -Wall + +noinst_LTLIBRARIES = libglobals.la + +libglobals_la_SOURCES = Globals.cpp + +noinst_PROGRAMS = + +noinst_HEADERS = \ + Globals.h diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..7d1c323 --- /dev/null +++ b/INSTALL @@ -0,0 +1,365 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007, 2008, 2009 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile b/Makefile deleted file mode 100644 index b8fc3b4..0000000 --- a/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -COM=CommonLibs -SQL=sqlite3 -SR=. -LOCALLIBS=$(COM)/Logger.cpp $(COM)/Timeval.cpp $(COM)/Threads.cpp $(COM)/Sockets.cpp $(COM)/Configuration.cpp $(COM)/sqlite3util.cpp $(SR)/SubscriberRegistry.cpp $(COM)/Utils.cpp servershare.cpp -LIBS= -L$(SQL) $(LOCALLIBS) -losipparser2 -losip2 -lc -lpthread -lsqlite3 -INCLUDES=-I$(COM) -I$(SQL) -I$(SR) -CPPFLAGS=-g -Wall -Wno-deprecated - -DESTDIR := - -all: comp128 srmanager.cgi subscriberserver.cgi sipauthserve - -comp128: comp128.c - g++ -o comp128 comp128.c - -subscriberserver.cgi: subscriberserver.cpp $(LOCALLIBS) - g++ -o subscriberserver.cgi $(CPPFLAGS) $(INCLUDES) subscriberserver.cpp $(LIBS) - -srmanager.cgi: srmanager.cpp $(LOCALLIBS) - g++ -o srmanager.cgi $(CPPFLAGS) $(INCLUDES) srmanager.cpp $(LIBS) - -sipauthserve: sipauthserve.cpp $(LOCALLIBS) - g++ -o sipauthserve $(CPPFLAGS) $(INCLUDES) sipauthserve.cpp $(LIBS) - -clean: - rm -f comp128 subscriberserver.cgi srmanager.cgi sipauthserve test.SubscriberRegistry/test - rm -r -f *.dSYM - -# this needs "local7.debug/var/log/openbts.log" in /etc/syslog.conf -test: all - cd test.SubscriberRegistry; ./runtest - cd test.sipauthserve; ./runtest - cd test.srmanager; ./runtest - cd test.subscriberserver; ./runtest - -just3: all - cd test.SubscriberRegistry; ./runtest - cd test.srmanager; ./runtest - cd test.subscriberserver; ./runtest - -IPATH=$(DESTDIR)/usr/local/bin/ -CGIPATH=$(DESTDIR)/var/cgi-bin/ -OPATH=$(DESTDIR)/OpenBTS/ -CONFIGPATH=$(DESTDIR)/etc/OpenBTS/ - -# specifically for boa web server -install: all - mkdir -p $(IPATH) - install comp128 $(IPATH) - install hexmapper $(IPATH) - install syslogextractor $(IPATH) - mkdir -p $(CGIPATH) - install -m +s -o root srmanager.cgi $(CGIPATH) - install -m +s -o root subscriberserver.cgi $(CGIPATH) - mkdir -p $(OPATH) - install comp128 $(OPATH) - install sipauthserve $(OPATH) - install runloop.sipauthserve.sh $(OPATH) - mkdir -p $(CONFIGPATH) - install subscriberRegistry.example.sql $(CONFIGPATH) - diff --git a/Makefile.am b/Makefile.am index b3a97ee..64f51f3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,5 @@ # -# Copyright 2009 Free Software Foundation, Inc. -# Copyright 2010 Kestrel Signal Processing, Inc. +# Copyright 2008 Free Software Foundation, Inc. # # This software is distributed under the terms of the GNU Public License. # See the COPYING file in the main directory for details. @@ -21,8 +20,10 @@ include $(top_srcdir)/Makefile.common -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) -AM_CXXFLAGS = $(STD_DEFINES_AND_INCLUDES) -Wall -ldl -lpthread +DESTDIR := + +AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(WITH_INCLUDES) +AM_CXXFLAGS = -Wall -pthread -ldl noinst_LTLIBRARIES = libSR.la @@ -32,3 +33,19 @@ libSR_la_SOURCES = \ noinst_HEADERS = \ SubscriberRegistry.h +# Order must be preserved +SUBDIRS = \ + config \ + sqlite3 \ + CommonLibs \ + Globals \ + NodeManager \ + apps + +install: all + $(MAKE) -C ./apps install + +dox: FORCE + doxygen doxconfig + +FORCE: diff --git a/Makefile.common b/Makefile.common new file mode 100644 index 0000000..ba0748c --- /dev/null +++ b/Makefile.common @@ -0,0 +1,48 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This software is distributed under the terms of the GNU Public License. +# See the COPYING 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 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(WITH_INCLUDES) +AM_CXXFLAGS = -Wall -pthread -ldl + +COMMON_INCLUDEDIR = $(top_srcdir)/CommonLibs +GLOBALS_INCLUDEDIR = $(top_srcdir)/Globals +SQLITE_INCLUDEDIR = $(top_srcdir)/sqlite3 +NODEMANAGER_INCLUDEDIR = $(top_srcdir)/NodeManager +JSONBOX_INCLUDEDIR = $(top_srcdir)/NodeManager/JsonBox-0.4.3/include +JSONDB_INCLUDEDIR = $(top_srcdir)/NodeManager/JSONDB + +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) \ + -I$(COMMON_INCLUDEDIR) \ + -I$(GLOBALS_INCLUDEDIR) \ + -I$(NODEMANAGER_INCLUDEDIR) \ + -I$(JSONBOX_INCLUDEDIR) \ + -I$(JSONDB_INCLUDEDIR) \ + -I$(SQLITE_INCLUDEDIR) + +# These macros are referenced in apps/Makefile.am, which must be changed in sync with these. +COMMON_LA = $(top_builddir)/CommonLibs/libcommon.la +GLOBALS_LA = $(top_builddir)/Globals/libglobals.la +NODEMANAGER_LA = $(top_builddir)/NodeManager/libnodemanager.la -lzmq +SQLITE_LA = $(top_builddir)/sqlite3/libsqlite.la -ldl + +MOSTLYCLEANFILES = *~ diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/NodeManager b/NodeManager new file mode 160000 index 0000000..c154368 --- /dev/null +++ b/NodeManager @@ -0,0 +1 @@ +Subproject commit c154368a55d081d7be241a14825e9a009dee093a diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/SubscriberRegistry.cpp b/SubscriberRegistry.cpp index 0cba03e..bb04a6a 100644 --- a/SubscriberRegistry.cpp +++ b/SubscriberRegistry.cpp @@ -1,6 +1,6 @@ /* * Copyright 2011 Kestrel Signal Processing, Inc. -* Copyright 2011, 2012 Range Networks, Inc. +* Copyright 2011, 2012, 2013, 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. @@ -33,6 +33,7 @@ #include #include #include +#include // for sort() #include extern ConfigurationTable gConfig; @@ -157,6 +158,15 @@ static const char* createSBTable = { ")" }; +static const char* createMEMSBTable = { + "CREATE TABLE IF NOT EXISTS memcache.mem_sip_buddies (" + "username varchar(80) primary key, " + "ipaddr varchar(45), " + "port int(5) default 5062, " + "rand varchar(33) default '', " + "sres varchar(33) default ''" + ")" +}; int SubscriberRegistry::init() { @@ -202,10 +212,243 @@ int SubscriberRegistry::init() if (!sqlite3_command(mDB,enableWAL,mNumSQLTries)) { LOG(EMERG) << "Cannot enable WAL mode on database at " << ldb << ", error message: " << sqlite3_errmsg(mDB); } + +#ifndef SR_API_ONLY + // memory based sip_buddies table + if (!sqlite3_command(mDB,"attach database ':memory:' as memcache",mNumSQLTries)) { + LOG(EMERG) << "Cannot create memcache database"; + return 1; + } + if (!sqlite3_command(mDB,createMEMSBTable,mNumSQLTries)) { + LOG(EMERG) << "Cannot create memcache mem_sip_buddies table"; + return 1; + } + if (!sqlite3_command(mDB,"INSERT INTO mem_sip_buddies SELECT username, ipaddr, port, rand, sres FROM sip_buddies",mNumSQLTries)) { + LOG(EMERG) << "Cannot populate mem_sip_buddies table with disk contents"; + return 1; + } + if (!sqlite3_command(mDB,"ALTER TABLE mem_sip_buddies ADD dirty INTEGER DEFAULT 0",mNumSQLTries)) { + LOG(EMERG) << "Cannot add dirty column to mem_sip_buddies table"; + return 1; + } + + // Start the sync thread + mSyncer.start((void*(*)(void*))subscriberRegistrySyncer,NULL); +#endif + return 0; } +string SubscriberRegistry::getResultsAsString(string query) +{ + sqlite3_stmt *stmt; + if (sqlite3_prepare_statement(mDB, &stmt, query.c_str(), 5)) { + std::cout << " - sqlite3_prepare_statement() failed" << std::endl; + return ""; + } + + int state; + int row = 0; + int col; + int colMax = sqlite3_column_count(stmt); + const char* colName; + const char* colText; + ostringstream colNames; + ostringstream colTexts; + while (1) { + state = sqlite3_step(stmt); + if (state == SQLITE_ROW) { + for (col = 0; col < colMax; col++) { + colName = (const char*)sqlite3_column_name(stmt, col); + colText = (const char*)sqlite3_column_text(stmt, col); + + if (row == 0) { + colNames << colName << " "; + } + if (colText == NULL) { + colTexts << "NULL" << " "; + } else { + colTexts << colText << " "; + } + } + } else if (state == SQLITE_DONE) { + break; + // TODO : handle more SQLITE_FAILURECODES here + } else { + return " - failed in while(1) in } else {"; + } + colTexts << std::endl; + row++; + } + sqlite3_finalize(stmt); + + ostringstream s; + string title = colNames.str(); + if (title.length()) { + s << title << std::endl; + s << colTexts << std::endl; + } else { + s << " - none found" << std::endl; + } + + return s.str(); +} + +vector SubscriberRegistry::getTableColumns(string tableName) +{ + vector colNames; + stringstream tmp; + tmp << "select * from " << tableName << " limit 1"; + + sqlite3_stmt *stmt; + + if (sqlite3_prepare_statement(mDB, &stmt, tmp.str().c_str(), 5)) { + std::cout << " - getTableColumns() - sqlite3_prepare_statement() failed" << std::endl; + return colNames; + } + tmp.str(""); + + int state; + int col; + int colMax = sqlite3_column_count(stmt); + while (1) { + state = sqlite3_step(stmt); + if (state == SQLITE_ROW) { + for (col = 0; col < colMax; col++) { + tmp << (const char*)sqlite3_column_name(stmt, col); + colNames.push_back(tmp.str()); + tmp.str(""); + } + } else if (state == SQLITE_DONE) { + break; + // TODO : handle more SQLITE_FAILURECODES here + } else { + std::cout << " - getTableColumns() - failed in while(1) in } else {" << std::endl; + return colNames; + } + } + sqlite3_finalize(stmt); + + return colNames; +} + +#ifndef SR_API_ONLY +string SubscriberRegistry::generateSyncToDiskQuery() +{ + vector columns = getTableColumns("sip_buddies"); + if (!columns.size()) { + LOG(DEBUG) << "sip_buddies is empty"; + return ""; + } + + sort(columns.begin(), columns.end()); + std::stringstream ss; + unsigned i; + + ss << "replace into sip_buddies (ipaddr, port, rand, sres, "; + + for (i = 0; i < columns.size(); i++) { + if (columns[i].compare("ipaddr") == 0 || columns[i].compare("port") == 0 || + columns[i].compare("rand") == 0 || columns[i].compare("sres") == 0) { + continue; + } + if (i != 0) { + ss << ", "; + } + + if (columns[i].find("-") != std::string::npos) { + ss << "'" << columns[i] << "'"; + } else { + ss << columns[i]; + } + } + + ss << ") select src.ipaddr, src.port, src.rand, src.sres, "; + + for (i = 0; i < columns.size(); i++) { + if (columns[i].compare("ipaddr") == 0 || columns[i].compare("port") == 0 || + columns[i].compare("rand") == 0 || columns[i].compare("sres") == 0) { + continue; + } + if (i != 0) { + ss << ", "; + } + + ss << "dest."; + if (columns[i].find("-") != std::string::npos) { + ss << "'" << columns[i] << "'"; + } else { + ss << columns[i]; + } + } + + ss << " from mem_sip_buddies src "; + ss << "inner join sip_buddies dest on src.username = dest.username "; + ss << "where src.dirty = \"1\""; + + return ss.str(); +} + +bool SubscriberRegistry::syncMemoryDB() +{ + bool ret = true; + string syncToDisk = generateSyncToDiskQuery(); + + string cleanDirty = "update mem_sip_buddies set dirty = \"0\""; + + string syncFromDiskAddNewEntries = "INSERT INTO mem_sip_buddies " + "(username, ipaddr, port, rand, sres, dirty) " + "SELECT sip_buddies.username, sip_buddies.ipaddr, sip_buddies.port, sip_buddies.rand, sip_buddies.sres, '0' FROM sip_buddies " + "LEFT OUTER JOIN mem_sip_buddies ON (mem_sip_buddies.username=sip_buddies.username) " + "WHERE mem_sip_buddies.username IS NULL"; + + string syncFromDiskDeleteOldEntries = "DELETE FROM mem_sip_buddies " + "WHERE username IN " + "(SELECT mem_sip_buddies.username FROM mem_sip_buddies" + " LEFT JOIN sip_buddies ON mem_sip_buddies.username=sip_buddies.username" + " WHERE sip_buddies.username IS NULL" + ")"; + + Timeval timer; + mLock.lock(); + + // this string is only non-empty if there are entries in sip_buddies + if (syncToDisk.length()) { + // sync dirty entries to disk + if (sqlUpdate(syncToDisk.c_str()) == FAILURE) { + LOG(ERR) << "syncToDisk failed"; + } else { + // if it succeeds, mark these entries as clean again + LOG(INFO) << "syncToDisk succeeded"; + if (sqlUpdate(cleanDirty.c_str()) == FAILURE) { + LOG(ERR) << "cleanDirty failed"; + } else { + LOG(INFO) << "cleanDirty succeeded"; + } + } + + // sync new rows from the disk into memory + if (sqlUpdate(syncFromDiskAddNewEntries.c_str()) == FAILURE) { + LOG(ERR) << "syncFromDiskAddNewEntries failed"; + } else { + LOG(INFO) << "syncFromDiskAddNewEntries succeeded"; + } + } + + // delete old entries from memory no longer found on the disk + if (sqlUpdate(syncFromDiskDeleteOldEntries.c_str()) == FAILURE) { + LOG(ERR) << "syncFromDiskDeleteOldEntries failed"; + } else { + LOG(INFO) << "syncFromDiskDeleteOldEntries succeeded"; + } + + mLock.unlock(); + LOG(INFO) << "syncMemoryDB() locked the db for " << timer.elapsed() << "ms"; + + return ret; +} +#endif SubscriberRegistry::~SubscriberRegistry() { @@ -214,20 +457,6 @@ SubscriberRegistry::~SubscriberRegistry() -SubscriberRegistry::Status SubscriberRegistry::sqlHttp(const char *stmt, char **resultptr) -{ - LOG(INFO) << stmt; - HttpQuery qry("sql"); - qry.send("stmts", stmt); - if (!qry.http(false)) return FAILURE; - const char *res = qry.receive("res"); - if (!res) return FAILURE; - *resultptr = strdup(res); - return SUCCESS; -} - - - SubscriberRegistry::Status SubscriberRegistry::sqlLocal(const char *query, char **resultptr) { LOG(INFO) << query; @@ -273,19 +502,7 @@ char *SubscriberRegistry::sqlQuery(const char *unknownColumn, const char *table, LOG(INFO) << "result = " << result; return result; } - // didn't find locally, so try over http - st = sqlHttp(os.str().c_str(), &result); - if ((st == SUCCESS) && result) { - // found over http but not locally, so cache locally - ostringstream os2; - os2 << "insert into " << table << "(" << knownColumn << ", " << unknownColumn << ") values (\"" << - knownValue << "\",\"" << result << "\")"; - // ignore whether it succeeds - sqlLocal(os2.str().c_str(), NULL); - LOG(INFO) << "result = " << result; - return result; - } - // didn't find locally or over http + // didn't find locally LOG(INFO) << "not found: " << os.str(); return NULL; } @@ -295,32 +512,48 @@ char *SubscriberRegistry::sqlQuery(const char *unknownColumn, const char *table, SubscriberRegistry::Status SubscriberRegistry::sqlUpdate(const char *stmt) { LOG(INFO) << stmt; - SubscriberRegistry::Status st = sqlLocal(stmt, NULL); - sqlHttp(stmt, NULL); - // status of local is only important one because asterisk talks to that db directly - // must update local no matter what - return st; + return sqlLocal(stmt, NULL); } string SubscriberRegistry::imsiGet(string imsi, string key) { string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi; - char *st = sqlQuery(key.c_str(), "sip_buddies", "name", imsi.c_str()); + char *st = sqlQuery(key.c_str(), "sip_buddies", "username", name.c_str()); if (!st) { - LOG(WARNING) << "cannot get key " << key << " for username " << imsi; + LOG(INFO) << "cannot get key " << key << " for username " << name; return ""; } return st; } +#ifndef SR_API_ONLY bool SubscriberRegistry::imsiSet(string imsi, string key, string value) { string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi; ostringstream os; - os << "update sip_buddies set " << key << " = \"" << value << "\" where name = \"" << name << "\""; - return sqlUpdate(os.str().c_str()) == FAILURE; + os << "update mem_sip_buddies set dirty = \"1\", " << key << " = \"" << value << "\" where username = \"" << name << "\""; + + mLock.lock(); + SubscriberRegistry::Status ret = sqlUpdate(os.str().c_str()); + mLock.unlock(); + + return ret == FAILURE; } +bool SubscriberRegistry::imsiSet(string imsi, string key1, string value1, string key2, string value2) +{ + string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi; + ostringstream os; + os << "update mem_sip_buddies set dirty = \"1\", " << key1 << " = \"" << value1 << "\"," << key2 << " = \"" << value2 << "\" where username = \"" << name << "\""; + + mLock.lock(); + SubscriberRegistry::Status ret = sqlUpdate(os.str().c_str()); + mLock.unlock(); + + return ret == FAILURE; +} +#endif + char *SubscriberRegistry::getIMSI(const char *ISDN) { if (!ISDN) { @@ -431,34 +664,6 @@ SubscriberRegistry::Status SubscriberRegistry::addUser(const char* IMSI, const c } -// For handover. Only remove the local cache. BS2 will have updated the global. -SubscriberRegistry::Status SubscriberRegistry::removeUser(const char* IMSI) -{ - if (!IMSI) { - LOG(WARNING) << "SubscriberRegistry::addUser attempting add of NULL IMSI"; - return FAILURE; - } - LOG(INFO) << "removeUser(" << IMSI << ")"; - string server = gConfig.getStr("SubscriberRegistry.UpstreamServer"); - if (server.length() == 0) { - LOG(INFO) << "not removing user if no upstream server"; - return FAILURE; - } - ostringstream os; - os << "delete from sip_buddies where name = "; - os << "\"" << IMSI << "\""; - os << ";"; - LOG(INFO) << os.str(); - SubscriberRegistry::Status st = sqlLocal(os.str().c_str(), NULL); - ostringstream os2; - os2 << "delete from dialdata_table where dial = "; - os2 << "\"" << IMSI << "\""; - LOG(INFO) << os2.str(); - SubscriberRegistry::Status st2 = sqlLocal(os2.str().c_str(), NULL); - return st == SUCCESS && st2 == SUCCESS ? SUCCESS : FAILURE; -} - - char *SubscriberRegistry::mapCLIDGlobal(const char *local) { @@ -487,307 +692,17 @@ SubscriberRegistry::Status SubscriberRegistry::RRLPUpdate(string name, string la return sqlUpdate(os.str().c_str()); } - - -string SubscriberRegistry::getRandForAuthentication(bool sip, string IMSI) +#ifndef SR_API_ONLY +extern SubscriberRegistry gSubscriberRegistry; +void* subscriberRegistrySyncer(void*) { - if (IMSI.length() == 0) { - LOG(WARNING) << "SubscriberRegistry::getRandForAuthentication attempting lookup of NULL IMSI"; - return ""; - } - LOG(INFO) << "getRandForAuthentication(" << IMSI << ")"; - // get rand from SR server - HttpQuery qry("rand"); - qry.send("imsi", IMSI); - qry.log(); - if (!qry.http(sip)) return ""; - return qry.receive("rand"); -} - -bool SubscriberRegistry::getRandForAuthentication(bool sip, string IMSI, uint64_t *hRAND, uint64_t *lRAND) -{ - string strRAND = getRandForAuthentication(sip, IMSI); - if (strRAND.length() == 0) { - *hRAND = 0; - *lRAND = 0; - return false; - } - stringToUint(strRAND, hRAND, lRAND); - return true; -} - -void SubscriberRegistry::stringToUint(string strRAND, uint64_t *hRAND, uint64_t *lRAND) -{ - assert(strRAND.size() == 32); - string strhRAND = strRAND.substr(0, 16); - string strlRAND = strRAND.substr(16, 16); - stringstream ssh; - ssh << hex << strhRAND; - ssh >> *hRAND; - stringstream ssl; - ssl << hex << strlRAND; - ssl >> *lRAND; -} - -string SubscriberRegistry::uintToString(uint64_t h, uint64_t l) -{ - ostringstream os1; - os1.width(16); - os1.fill('0'); - os1 << hex << h; - ostringstream os2; - os2.width(16); - os2.fill('0'); - os2 << hex << l; - ostringstream os3; - os3 << os1.str() << os2.str(); - return os3.str(); -} - -string SubscriberRegistry::uintToString(uint32_t x) -{ - ostringstream os; - os.width(8); - os.fill('0'); - os << hex << x; - return os.str(); -} - -SubscriberRegistry::Status SubscriberRegistry::authenticate(bool sip, string IMSI, uint64_t hRAND, uint64_t lRAND, uint32_t SRES) -{ - string strRAND = uintToString(hRAND, lRAND); - string strSRES = uintToString(SRES); - return authenticate(sip, IMSI, strRAND, strSRES); -} - - -SubscriberRegistry::Status SubscriberRegistry::authenticate(bool sip, string IMSI, string rand, string sres) -{ - if (IMSI.length() == 0) { - LOG(WARNING) << "SubscriberRegistry::authenticate attempting lookup of NULL IMSI"; - return FAILURE; - } - LOG(INFO) << "authenticate(" << IMSI << "," << rand << "," << sres << ")"; - HttpQuery qry("auth"); - qry.send("imsi", IMSI); - qry.send("rand", rand); - qry.send("sres", sres); - qry.log(); - if (!qry.http(sip)) return FAILURE; - const char *status = qry.receive("status"); - if (strcmp(status, "SUCCESS") == 0) return SUCCESS; - if (strcmp(status, "FAILURE") == 0) return FAILURE; - // status is Kc - return SUCCESS; -} - - - -bool SubscriberRegistry::useGateway(const char* ISDN) -{ - // FIXME -- Do something more general in Asterisk. - // This is a hack for Burning Man. - int cmp = strncmp(ISDN,"88351000125",11); - return cmp!=0; -} - - - -SubscriberRegistry::Status SubscriberRegistry::setPrepaid(const char *IMSI, bool yes) -{ - ostringstream os; - os << "update sip_buddies set prepaid = " << (yes ? 1 : 0) << " where username = " << '"' << IMSI << '"'; - return sqlUpdate(os.str().c_str()); -} - - -SubscriberRegistry::Status SubscriberRegistry::isPrepaid(const char *IMSI, bool &yes) -{ - char *st = sqlQuery("prepaid", "sip_buddies", "username", IMSI); - if (!st) { - LOG(NOTICE) << "cannot get prepaid status for username " << IMSI; - return FAILURE; - } - yes = *st == '1'; - free(st); - return SUCCESS; -} - - -SubscriberRegistry::Status SubscriberRegistry::balanceRemaining(const char *IMSI, int &balance) -{ - char *st = sqlQuery("account_balance", "sip_buddies", "username", IMSI); - if (!st) { - LOG(NOTICE) << "cannot get balance for " << IMSI; - return FAILURE; - } - balance = (int)strtol(st, (char **)NULL, 10); - free(st); - return SUCCESS; -} - - -SubscriberRegistry::Status SubscriberRegistry::addMoney(const char *IMSI, int moneyToAdd) -{ - ostringstream os; - os << "update sip_buddies set account_balance = account_balance + " << moneyToAdd << " where username = " << '"' << IMSI << '"'; - if (sqlUpdate(os.str().c_str()) == FAILURE) { - LOG(NOTICE) << "cannot update rate for username " << IMSI; - return FAILURE; - } - return SUCCESS; -} - -int SubscriberRegistry::serviceCost(const char* service) -{ - char *rateSt = sqlQuery("rate", "rates", "service", service); - if (!rateSt) { - LOG(ALERT) << "cannot get rate for service " << service; - return -1; - } - int rate = (int)strtol(rateSt, (char **)NULL, 10); - free(rateSt); - return rate; -} - -SubscriberRegistry::Status SubscriberRegistry::serviceUnits(const char *IMSI, const char* service, int &units) -{ - int balance; - Status stat = balanceRemaining(IMSI,balance); - if (stat == FAILURE) return FAILURE; - int rate = serviceCost(service); - if (rate<0) return FAILURE; - units = balance / rate; - return SUCCESS; -} - - - -HttpQuery::HttpQuery(const char *req) -{ - sends = map(); - sends["req"] = req; - receives = map(); -} - -void HttpQuery::send(const char *label, string value) -{ - sends[label] = value; -} - -void HttpQuery::log() -{ - ostringstream os; - bool first = true; - for (map::iterator it = sends.begin(); it != sends.end(); it++) { - if (first) { - first = false; - } else { - os << "&"; - } - os << it->first << "=" << it->second; - } - LOG(INFO) << os.str(); -} - -bool HttpQuery::http(bool sip) -{ - // unique temporary file names - ostringstream os1; - ostringstream os2; - os1 << "/tmp/subscriberregistry.1." << getpid(); - os2 << "/tmp/subscriberregistry.2." << getpid(); - string tmpFile1 = os1.str(); - string tmpFile2 = os2.str(); - - // write the request and params to temp file - ofstream file1(tmpFile1.c_str()); - if (file1.fail()) { - LOG(ERR) << "HttpQuery::http: can't write " << tmpFile1.c_str(); - return false; - } - bool first = true; - for (map::iterator it = sends.begin(); it != sends.end(); it++) { - if (first) { - first = false; - } else { - file1 << "&"; - } - file1 << it->first << "=" << it->second; - } - file1.close(); - - // call the server - string server = sip ? - gConfig.getStr("SIP.Proxy.Registration"): - gConfig.getStr("SubscriberRegistry.UpstreamServer"); - if (server.length() == 0 && !sip) return false; - ostringstream os; - os << "curl -s --data-binary @" << tmpFile1.c_str() << " " << server << " > " << tmpFile2.c_str(); - LOG(INFO) << os.str(); - if (server == "testing") { - return false; - } else { - int st = system(os.str().c_str()); - if (st != 0) { - LOG(ERR) << "curl call returned " << st; - return false; - } + while (true) { + sleep(15); + gSubscriberRegistry.syncMemoryDB(); } - // read the http return from another temp file - ifstream file2(tmpFile2.c_str()); - if (file2.fail()) { - LOG(ERR) << "HTTPQuery::http: can't read " << tmpFile2.c_str(); - return false; - } - string tmp; - while (getline(file2, tmp)) { - size_t pos = tmp.find('='); - if (pos != string::npos) { - string key = tmp.substr(0, pos); - string value = tmp.substr(pos+1); - if (key == "error") { - LOG(ERR) << "HTTPQuery::http error: " << value; - file2.close(); - return false; - } - receives[key] = value; - } else { - file2.close(); - LOG(ERR) << "HTTPQuery::http: bad server return:"; - ifstream file22(tmpFile2.c_str()); - while (getline(file22, tmp)) { - LOG(ERR) << tmp; - } - file22.close(); - return false; - } - } - file2.close(); - return true; + return NULL; } - -const char *HttpQuery::receive(const char *label) -{ - map::iterator it = receives.find(label); - return it == receives.end() ? NULL : it->second.c_str(); -} - - - - - - - +#endif // vim: ts=4 sw=4 - - - - - - - - - diff --git a/SubscriberRegistry.h b/SubscriberRegistry.h index 413a5ff..96e662d 100644 --- a/SubscriberRegistry.h +++ b/SubscriberRegistry.h @@ -29,8 +29,8 @@ #include #include #include -// #include -// #include +#include +#include #include #include #include "sqlite3.h" @@ -44,6 +44,11 @@ class SubscriberRegistry { sqlite3 *mDB; ///< database connection unsigned mNumSQLTries; ///< Number of times to try an sqlite command before giving up. +#ifndef SR_API_ONLY + mutable Mutex mLock; ///< control for multithreaded read/write access to the memory based sip_buddies table + Thread mSyncer; ///< thread responsible for synchronizing the memory and disk based sip_buddies tables +#endif + public: ~SubscriberRegistry(); @@ -68,6 +73,28 @@ class SubscriberRegistry { } + /** + Grab the memory based sqlite db as a table string + */ + string getResultsAsString(string query); + + /** + Grab the columns from a table + */ + vector getTableColumns(string tableName); + +#ifndef SR_API_ONLY + /** + Generate the SQL query which is used to sync the in-memory database to disk + to account for differences in database schemas. + */ + string generateSyncToDiskQuery(); + + /** + Sync the in-memory sip_buddies table to disk. + */ + bool syncMemoryDB(); +#endif /** Resolve an ISDN or other numeric address to an IMSI. @@ -102,20 +129,32 @@ class SubscriberRegistry { char* getRegistrationIP(const char* IMSI); /** - Set a specific variable indexed by imsi from sip_buddies - @param imsi The user's IMSI or SIP username. - @param key to index into table + Get a subscriber's property. + @param imsi imsi of the subscriber + @param key name of the property */ string imsiGet(string imsi, string key); +#ifndef SR_API_ONLY /** - Set a specific variable indexed by imsi_from sip_buddies - @param imsi The user's IMSI or SIP username. - @param key to index into table - @param value to set indexed by the key + Set a subscriber's property. + @param imsi imsi of the subscriber + @param key name of the property + @param value value of the property */ bool imsiSet(string imsi, string key, string value); + /** + Set a subscriber's property. + @param imsi imsi of the subscriber + @param key1 name of the property + @param value1 value of the property + @param key2 name of the property + @param value2 value of the property + */ + bool imsiSet(string imsi, string key1, string value1, string key2, string value2); +#endif + /** Add a new user to the SubscriberRegistry. @param IMSI The user's IMSI or SIP username. @@ -141,99 +180,6 @@ class SubscriberRegistry { char *mapCLIDGlobal(const char *local); - - /** - Get a 128-bit number for authentication. - @param sip sip server (true) or http - @param IMSI The user's IMSI or SIP username. - @return the 128-bit number in hex - */ - string getRandForAuthentication(bool sip, string IMSI); - - - /** - Get a 128-bit number for authentication. - @param sip sip server (true) or http - @param IMSI The user's IMSI or SIP username; - @param hRAND upper 64 bits - @param lRAND lower 64 bits - */ - bool getRandForAuthentication(bool sip, string IMSI, uint64_t *hRAND, uint64_t *lRAND); - - void stringToUint(string strRAND, uint64_t *hRAND, uint64_t *lRAND); - - string uintToString(uint64_t h, uint64_t l); - - string uintToString(uint32_t x); - - SubscriberRegistry::Status authenticate(bool sip, string IMSI, uint64_t hRAND, uint64_t lRAND, uint32_t SRES); - - - - /** - Authenticate a handset. - @param sip sip server (true) or http - @param IMSI The user's IMSI or SIP username. - @param rand RAND. - @param sres SRES - @return ok or fail - */ - SubscriberRegistry::Status authenticate(bool sip, string IMSI, string rand, string sres); - - - - bool useGateway(const char* ISDN); - - - /** - Set whether a subscriber is prepaid. - @param IMSI Subscriber's IMSI - @param yes true for prepaid, false for postpaid - @return SUCCESS or FAILURE - */ - Status setPrepaid(const char *IMSI, bool yes); - - - /** - Is a subscriber postpaid? - @param IMSI Subscriber's IMSI - @param yes set to true if subscriber is postpaid, false if prepaid - @return SUCCESS or FAILURE - */ - Status isPrepaid(const char *IMSI, bool &yes); - - - /** - Get the balance remaining in a subscriber's account. - @param IMSI Subscriber's IMSI - @param balance current account balance - @return SUCCESS or FAILURE - */ - Status balanceRemaining(const char *IMSI, int &balance); - - - /** - Atomic operation to add to the account balance - @param IMSI subscriber's IMSI - @param moneyToAdd money to add (negative to subtract) - @return SUCCESS or FAILURE - */ - Status addMoney(const char *IMSI, int moneyToAdd); - - /** - Return the number of "units" of a particular transcation type available in the user's account. - @param IMSI subscriber's IMSI - @param service the service type - @param units number of units of this service type remaining - @return SUCCESS or FAILURE - */ - Status serviceUnits(const char *IMSI, const char* service, int &units); - - /** - Return the cost per unit of a specific service type. - */ - int serviceCost(const char* service); - /** Update the RRLP location for user @param name IMSI to be updated @@ -257,15 +203,6 @@ class SubscriberRegistry { - /** - Run sql statments over http. - @param stmt The sql statements. - @param resultptr Set this to point to the result of executing the statements. - */ - Status sqlHttp(const char *stmt, char **resultptr); - - - /** Run an sql query (select unknownColumn from table where knownColumn = knownValue). @param unknownColumn The column whose value you want. @@ -284,82 +221,10 @@ class SubscriberRegistry { Status sqlUpdate(const char *stmt); - - - - - - -}; - - - -/** Class that SubscriberRegistry uses to setup an http query, run it, and get the results. */ -class HttpQuery { - - - - public: - - - - /** - Constructor. - @param req The type of http query (sql, (get a)rand(om number) auth(enticate), etc). - */ - HttpQuery(const char *req); - - - - /** - Specify a parameter to send in the http query. - @param label The label or name for the parameter. - @param value The value of the parameter. - */ - void send(const char *label, string value); - - - - /** - Log the query. - */ - void log(); - - - /** - This runs the http query. - @param sip Whether to call the sip server as opposed to the http server. - */ - bool http(bool sip); - - - - /** - Get result from the http query. - @param label The label or name of the parameter whose value you want. - */ - const char *receive(const char *label); - - - - - - private: - - - - /** stores the parameters to send. */ - map sends; - - - - /** stores the return parameters. */ - map receives; - - - }; +/** Periodically triggers SubscriberRegistry::syncMemoryDB(). */ +void* subscriberRegistrySyncer(void*); #endif diff --git a/apps/Makefile.am b/apps/Makefile.am new file mode 100644 index 0000000..c47e659 --- /dev/null +++ b/apps/Makefile.am @@ -0,0 +1,58 @@ +# +# Copyright 2013 Range Networks, Inc. +# +# This software is distributed under the terms of the GNU Public License. +# See the COPYING 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 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +include $(top_srcdir)/Makefile.common + +DESTDIR := + +ourlibs = \ + $(GLOBALS_LA) \ + $(COMMON_LA) \ + $(SQLITE_LA) \ + $(NODEMANAGER_LA) + +bin_PROGRAMS = sipauthserve comp128 + +sipauthserve_SOURCES = sipauthserve.cpp ../servershare.cpp ../SubscriberRegistry.cpp \ + ../NodeManager/JSONDB/JSONDB.cpp +sipauthserve_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) +sipauthserve_LDADD = $(ourlibs) -losipparser2 -losip2 + +comp128_SOURCES = comp128.c +comp128_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) +comp128_LDADD = $(ourlibs) + +EXTRA_DIST = \ + subscriberRegistry.example.sql \ + sipauthserve.conf + +# Populating comp128 in both locations for backwards compat +install: sipauthserve comp128 + mkdir -p "$(DESTDIR)/OpenBTS/" + install comp128 "$(DESTDIR)/OpenBTS/" + install sipauthserve "$(DESTDIR)/OpenBTS/" + mkdir -p "$(DESTDIR)/usr/local/bin/" + install comp128 "$(DESTDIR)/usr/local/bin/" + install syslogextractor "$(DESTDIR)/usr/local/bin/" + install hexmapper "$(DESTDIR)/usr/local/bin/" + mkdir -p "$(DESTDIR)/etc/init/" + install sipauthserve.conf "$(DESTDIR)/etc/init/" + mkdir -p "$(DESTDIR)/etc/OpenBTS/" + install subscriberRegistry.example.sql "$(DESTDIR)/etc/OpenBTS/" diff --git a/comp128.c b/apps/comp128.c similarity index 100% rename from comp128.c rename to apps/comp128.c diff --git a/hexmapper b/apps/hexmapper similarity index 100% rename from hexmapper rename to apps/hexmapper diff --git a/apps/sipauthserve.conf b/apps/sipauthserve.conf new file mode 100644 index 0000000..66684c7 --- /dev/null +++ b/apps/sipauthserve.conf @@ -0,0 +1,10 @@ +# sipauthserve - Range Networks SIP Authorization Server +# +# This service runs sipauthserve 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/sipauthserve diff --git a/sipauthserve.cpp b/apps/sipauthserve.cpp similarity index 81% rename from sipauthserve.cpp rename to apps/sipauthserve.cpp index 41e6e29..e411d0c 100644 --- a/sipauthserve.cpp +++ b/apps/sipauthserve.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. @@ -44,7 +44,9 @@ #include #include -#include +#include +#include +#include #include "servershare.h" #include "SubscriberRegistry.h" @@ -58,6 +60,29 @@ int my_udp_port; // just using this for the database access SubscriberRegistry gSubscriberRegistry; +/** The remote node manager. */ +NodeManager gNodeManager; + +/** The JSON<->DB interface. */ +JSONDB gJSONDB; + +/** Application specific NodeManager logic for handling requests. */ +JsonBox::Object nmHandler(JsonBox::Object& request) +{ + JsonBox::Object response; + std::string command = request["command"].getString(); + std::string action = request["action"].getString(); + + if (command.compare("subscribers") == 0) { + request["table"] = JsonBox::Value("subscribers"); + response = gJSONDB.query(request); + } else { + response["code"] = JsonBox::Value(501); + } + + return response; +} + void prettyPrint(const char *label, osip_message_t *sip) { char *dest=NULL; @@ -73,14 +98,13 @@ void prettyPrint(const char *label, osip_message_t *sip) string imsiFromSip(osip_message_t *sip) { - int i; char *dest; osip_uri_t *fromUri = osip_from_get_url(sip->from); if (!fromUri) { LOG(ERR) << "osip_from_get_url problem"; return ""; } - i = osip_uri_to_str(fromUri, &dest); + osip_uri_to_str(fromUri, &dest); string imsi = dest; osip_free(dest); return imsi; @@ -88,14 +112,13 @@ string imsiFromSip(osip_message_t *sip) string imsiToSip(osip_message_t *sip) { - int i; char *dest; osip_uri_t *toUri = osip_to_get_url(sip->to); if (!toUri) { LOG(ERR) << "osip_to_get_url problem"; return ""; } - i = osip_uri_to_str(toUri, &dest); + osip_uri_to_str(toUri, &dest); string imsi = dest; osip_free(dest); return imsi; @@ -104,7 +127,7 @@ string imsiToSip(osip_message_t *sip) // is imsi in the database? bool imsiFound(string imsi) { - string x = imsiGet(imsi, "id"); + string x = gSubscriberRegistry.imsiGet(imsi, "id"); return x.length() != 0; } @@ -180,7 +203,7 @@ char *processBuffer(char *buffer) osip_message_set_status_code (response, 200); osip_message_set_reason_phrase (response, osip_strdup("OK")); LOG(INFO) << "success, registering for IP address " << remote_host; - imsiSet(imsi,"ipaddr", remote_host, "port", remote_port); + gSubscriberRegistry.imsiSet(imsi,"ipaddr", remote_host, "port", remote_port); } else { // look for rand and sres in Authorization header (assume imsi same as in from) string randx; @@ -238,9 +261,19 @@ char *processBuffer(char *buffer) i = osip_list_add (&response->authentication_infos, auth, -1); if (i < 0) LOG(ERR) << "problem adding authentication_infos"; } + // (pat 9-2013) Add the caller id. + static string calleridstr("callerid"); + string callid = gSubscriberRegistry.imsiGet(imsi,calleridstr); + if (callid.size()) { + char buf[120]; + // Per RFC3966 the telephone numbers should begin with "+" only if it is globally unique throughout the world. + // We should not add the "+" here, it should be in the database if appropriate. + snprintf(buf,120,"",callid.c_str()); + osip_message_set_header(response,"P-Associated-URI",buf); + } // And register it. LOG(INFO) << "success, registering for IP address " << remote_host; - imsiSet(imsi,"ipaddr", remote_host, "port", remote_port); + gSubscriberRegistry.imsiSet(imsi,"ipaddr", remote_host, "port", remote_port); } else { // sres does not match rand => 401 Unauthorized osip_message_set_status_code (response, 401); @@ -269,6 +302,24 @@ char *processBuffer(char *buffer) int main(int argc, char **argv) { + // TODO: Properly parse and handle any arguments + if (argc > 1) { + for (int argi = 0; argi < argc; argi++) { + if (!strcmp(argv[argi], "--version") || + !strcmp(argv[argi], "-v")) { + cout << gVersionString << endl; + } + if (!strcmp(argv[argi], "--gensql")) { + cout << gConfig.getDefaultSQL(string(argv[0]), gVersionString) << endl; + } + if (!strcmp(argv[argi], "--gentex")) { + cout << gConfig.getTeX(string(argv[0]), gVersionString) << endl; + } + } + + return 0; + } + sockaddr_in si_me; sockaddr_in si_other; int aSocket; @@ -278,13 +329,15 @@ main(int argc, char **argv) srand ( time(NULL) + (int)getpid() ); my_udp_port = gConfig.getNum("SubscriberRegistry.Port"); gSubscriberRegistry.init(); + gNodeManager.setAppLogicHandler(&nmHandler); + gNodeManager.start(45064); // init osip lib osip_t *osip; int i=osip_init(&osip); if (i!=0) { LOG(ALERT) << "cannot init sip lib"; - return NULL; + exit(1); } if ((aSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { diff --git a/apps/subscriberRegistry.example.sql b/apps/subscriberRegistry.example.sql new file mode 100644 index 0000000..94f13b0 --- /dev/null +++ b/apps/subscriberRegistry.example.sql @@ -0,0 +1,20 @@ +-- +-- This file was generated using: ./sipauthserve --gensql +-- binary version: release 4.0TRUNK built Nov 20 2013 rev6847M +-- +-- Future changes should not be put in this file directly but +-- rather in the program's ConfigurationKey schema. +-- +PRAGMA foreign_keys=OFF; +BEGIN TRANSACTION; +CREATE TABLE IF NOT EXISTS CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT ''); +INSERT OR IGNORE INTO "CONFIG" VALUES('Control.NumSQLTries','3',0,0,'Number of times to retry SQL queries before declaring a database access failure.'); +INSERT OR IGNORE INTO "CONFIG" VALUES('Log.Alarms.Max','20',0,0,'Maximum number of alarms to remember inside the application.'); +INSERT OR IGNORE INTO "CONFIG" VALUES('Log.File','',0,0,'Path to use for textfile based logging. By default, this feature is disabled. To enable, specify an absolute path to the file you wish to use, eg: /tmp/my-debug.log. To disable again, execute "unconfig Log.File".'); +INSERT OR IGNORE INTO "CONFIG" VALUES('Log.Level','NOTICE',0,0,'Default logging level when no other level is defined for a file.'); +INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.A3A8','/OpenBTS/comp128',0,0,'Path to the program that implements the A3/A8 algorithm.'); +INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.Port','5064',0,0,'Port used by the SIP Authentication Server. NOTE: In some older releases (pre-2.8.1) this is called SIP.myPort.'); +INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.db','/var/lib/asterisk/sqlite3dir/sqlite3.db',0,0,'The location of the sqlite3 database holding the subscriber registry.'); +COMMIT; + + diff --git a/syslogextractor b/apps/syslogextractor similarity index 100% rename from syslogextractor rename to apps/syslogextractor diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..b2ed160 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,1578 @@ +#!/bin/sh +# a u t o g e n . s h +# +# Copyright (c) 2005-2009 United States Government as represented by +# the U.S. Army Research Laboratory. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# 3. The name of the author may not be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +### +# +# Script for automatically preparing the sources for compilation by +# performing the myrid of necessary steps. The script attempts to +# detect proper version support, and outputs warnings about particular +# systems that have autotool peculiarities. +# +# Basically, if everything is set up and installed correctly, the +# script will validate that minimum versions of the GNU Build System +# tools are installed, account for several common configuration +# issues, and then simply run autoreconf for you. +# +# If autoreconf fails, which can happen for many valid configurations, +# this script proceeds to run manual preparation steps effectively +# providing a POSIX shell script (mostly complete) reimplementation of +# autoreconf. +# +# The AUTORECONF, AUTOCONF, AUTOMAKE, LIBTOOLIZE, ACLOCAL, AUTOHEADER +# environment variables and corresponding _OPTIONS variables (e.g. +# AUTORECONF_OPTIONS) may be used to override the default automatic +# detection behaviors. Similarly the _VERSION variables will override +# the minimum required version numbers. +# +# Examples: +# +# To obtain help on usage: +# ./autogen.sh --help +# +# To obtain verbose output: +# ./autogen.sh --verbose +# +# To skip autoreconf and prepare manually: +# AUTORECONF=false ./autogen.sh +# +# To verbosely try running with an older (unsupported) autoconf: +# AUTOCONF_VERSION=2.50 ./autogen.sh --verbose +# +# Author: +# Christopher Sean Morrison +# +# Patches: +# Sebastian Pipping +# +###################################################################### + +# set to minimum acceptible version of autoconf +if [ "x$AUTOCONF_VERSION" = "x" ] ; then + AUTOCONF_VERSION=2.52 +fi +# set to minimum acceptible version of automake +if [ "x$AUTOMAKE_VERSION" = "x" ] ; then + AUTOMAKE_VERSION=1.6.0 +fi +# set to minimum acceptible version of libtool +if [ "x$LIBTOOL_VERSION" = "x" ] ; then + LIBTOOL_VERSION=1.4.2 +fi + + +################## +# ident function # +################## +ident ( ) { + # extract copyright from header + __copyright="`grep Copyright $AUTOGEN_SH | head -${HEAD_N}1 | awk '{print $4}'`" + if [ "x$__copyright" = "x" ] ; then + __copyright="`date +%Y`" + fi + + # extract version from CVS Id string + __id="$Id: autogen.sh 33925 2009-03-01 23:27:06Z brlcad $" + __version="`echo $__id | sed 's/.*\([0-9][0-9][0-9][0-9]\)[-\/]\([0-9][0-9]\)[-\/]\([0-9][0-9]\).*/\1\2\3/'`" + if [ "x$__version" = "x" ] ; then + __version="" + fi + + echo "autogen.sh build preparation script by Christopher Sean Morrison" + echo " + config.guess download patch by Sebastian Pipping (2008-12-03)" + echo "revised 3-clause BSD-style license, copyright (c) $__copyright" + echo "script version $__version, ISO/IEC 9945 POSIX shell script" +} + + +################## +# USAGE FUNCTION # +################## +usage ( ) { + echo "Usage: $AUTOGEN_SH [-h|--help] [-v|--verbose] [-q|--quiet] [-d|--download] [--version]" + echo " --help Help on $NAME_OF_AUTOGEN usage" + echo " --verbose Verbose progress output" + echo " --quiet Quiet suppressed progress output" + echo " --download Download the latest config.guess from gnulib" + echo " --version Only perform GNU Build System version checks" + echo + echo "Description: This script will validate that minimum versions of the" + echo "GNU Build System tools are installed and then run autoreconf for you." + echo "Should autoreconf fail, manual preparation steps will be run" + echo "potentially accounting for several common preparation issues. The" + + echo "AUTORECONF, AUTOCONF, AUTOMAKE, LIBTOOLIZE, ACLOCAL, AUTOHEADER," + echo "PROJECT, & CONFIGURE environment variables and corresponding _OPTIONS" + echo "variables (e.g. AUTORECONF_OPTIONS) may be used to override the" + echo "default automatic detection behavior." + echo + + ident + + return 0 +} + + +########################## +# VERSION_ERROR FUNCTION # +########################## +version_error ( ) { + if [ "x$1" = "x" ] ; then + echo "INTERNAL ERROR: version_error was not provided a version" + exit 1 + fi + if [ "x$2" = "x" ] ; then + echo "INTERNAL ERROR: version_error was not provided an application name" + exit 1 + fi + $ECHO + $ECHO "ERROR: To prepare the ${PROJECT} build system from scratch," + $ECHO " at least version $1 of $2 must be installed." + $ECHO + $ECHO "$NAME_OF_AUTOGEN does not need to be run on the same machine that will" + $ECHO "run configure or make. Either the GNU Autotools will need to be installed" + $ECHO "or upgraded on this system, or $NAME_OF_AUTOGEN must be run on the source" + $ECHO "code on another system and then transferred to here. -- Cheers!" + $ECHO +} + +########################## +# VERSION_CHECK FUNCTION # +########################## +version_check ( ) { + if [ "x$1" = "x" ] ; then + echo "INTERNAL ERROR: version_check was not provided a minimum version" + exit 1 + fi + _min="$1" + if [ "x$2" = "x" ] ; then + echo "INTERNAL ERROR: version check was not provided a comparison version" + exit 1 + fi + _cur="$2" + + # needed to handle versions like 1.10 and 1.4-p6 + _min="`echo ${_min}. | sed 's/[^0-9]/./g' | sed 's/\.\././g'`" + _cur="`echo ${_cur}. | sed 's/[^0-9]/./g' | sed 's/\.\././g'`" + + _min_major="`echo $_min | cut -d. -f1`" + _min_minor="`echo $_min | cut -d. -f2`" + _min_patch="`echo $_min | cut -d. -f3`" + + _cur_major="`echo $_cur | cut -d. -f1`" + _cur_minor="`echo $_cur | cut -d. -f2`" + _cur_patch="`echo $_cur | cut -d. -f3`" + + if [ "x$_min_major" = "x" ] ; then + _min_major=0 + fi + if [ "x$_min_minor" = "x" ] ; then + _min_minor=0 + fi + if [ "x$_min_patch" = "x" ] ; then + _min_patch=0 + fi + if [ "x$_cur_minor" = "x" ] ; then + _cur_major=0 + fi + if [ "x$_cur_minor" = "x" ] ; then + _cur_minor=0 + fi + if [ "x$_cur_patch" = "x" ] ; then + _cur_patch=0 + fi + + $VERBOSE_ECHO "Checking if ${_cur_major}.${_cur_minor}.${_cur_patch} is greater than ${_min_major}.${_min_minor}.${_min_patch}" + + if [ $_min_major -lt $_cur_major ] ; then + return 0 + elif [ $_min_major -eq $_cur_major ] ; then + if [ $_min_minor -lt $_cur_minor ] ; then + return 0 + elif [ $_min_minor -eq $_cur_minor ] ; then + if [ $_min_patch -lt $_cur_patch ] ; then + return 0 + elif [ $_min_patch -eq $_cur_patch ] ; then + return 0 + fi + fi + fi + return 1 +} + + +###################################### +# LOCATE_CONFIGURE_TEMPLATE FUNCTION # +###################################### +locate_configure_template ( ) { + _pwd="`pwd`" + if test -f "./configure.ac" ; then + echo "./configure.ac" + elif test -f "./configure.in" ; then + echo "./configure.in" + elif test -f "$_pwd/configure.ac" ; then + echo "$_pwd/configure.ac" + elif test -f "$_pwd/configure.in" ; then + echo "$_pwd/configure.in" + elif test -f "$PATH_TO_AUTOGEN/configure.ac" ; then + echo "$PATH_TO_AUTOGEN/configure.ac" + elif test -f "$PATH_TO_AUTOGEN/configure.in" ; then + echo "$PATH_TO_AUTOGEN/configure.in" + fi +} + + +################## +# argument check # +################## +ARGS="$*" +PATH_TO_AUTOGEN="`dirname $0`" +NAME_OF_AUTOGEN="`basename $0`" +AUTOGEN_SH="$PATH_TO_AUTOGEN/$NAME_OF_AUTOGEN" + +LIBTOOL_M4="${PATH_TO_AUTOGEN}/misc/libtool.m4" + +if [ "x$HELP" = "x" ] ; then + HELP=no +fi +if [ "x$QUIET" = "x" ] ; then + QUIET=no +fi +if [ "x$VERBOSE" = "x" ] ; then + VERBOSE=no +fi +if [ "x$VERSION_ONLY" = "x" ] ; then + VERSION_ONLY=no +fi +if [ "x$DOWNLOAD" = "x" ] ; then + DOWNLOAD=no +fi +if [ "x$AUTORECONF_OPTIONS" = "x" ] ; then + AUTORECONF_OPTIONS="-i -f" +fi +if [ "x$AUTOCONF_OPTIONS" = "x" ] ; then + AUTOCONF_OPTIONS="-f" +fi +if [ "x$AUTOMAKE_OPTIONS" = "x" ] ; then + AUTOMAKE_OPTIONS="-a -c -f" +fi +ALT_AUTOMAKE_OPTIONS="-a -c" +if [ "x$LIBTOOLIZE_OPTIONS" = "x" ] ; then + LIBTOOLIZE_OPTIONS="--automake -c -f" +fi +ALT_LIBTOOLIZE_OPTIONS="--automake --copy --force" +if [ "x$ACLOCAL_OPTIONS" = "x" ] ; then + ACLOCAL_OPTIONS="" +fi +if [ "x$AUTOHEADER_OPTIONS" = "x" ] ; then + AUTOHEADER_OPTIONS="" +fi +if [ "x$CONFIG_GUESS_URL" = "x" ] ; then + CONFIG_GUESS_URL="http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob_plain;f=build-aux/config.guess;hb=HEAD" +fi +for arg in $ARGS ; do + case "x$arg" in + x--help) HELP=yes ;; + x-[hH]) HELP=yes ;; + x--quiet) QUIET=yes ;; + x-[qQ]) QUIET=yes ;; + x--verbose) VERBOSE=yes ;; + x-[dD]) DOWNLOAD=yes ;; + x--download) DOWNLOAD=yes ;; + x-[vV]) VERBOSE=yes ;; + x--version) VERSION_ONLY=yes ;; + *) + echo "Unknown option: $arg" + echo + usage + exit 1 + ;; + esac +done + + +##################### +# environment check # +##################### + +# sanity check before recursions potentially begin +if [ ! -f "$AUTOGEN_SH" ] ; then + echo "INTERNAL ERROR: $AUTOGEN_SH does not exist" + if [ ! "x$0" = "x$AUTOGEN_SH" ] ; then + echo "INTERNAL ERROR: dirname/basename inconsistency: $0 != $AUTOGEN_SH" + fi + exit 1 +fi + +# force locale setting to C so things like date output as expected +LC_ALL=C + +# commands that this script expects +for __cmd in echo head tail pwd ; do + echo "test" | $__cmd > /dev/null 2>&1 + if [ $? != 0 ] ; then + echo "INTERNAL ERROR: '${__cmd}' command is required" + exit 2 + fi +done +echo "test" | grep "test" > /dev/null 2>&1 +if test ! x$? = x0 ; then + echo "INTERNAL ERROR: grep command is required" + exit 1 +fi +echo "test" | sed "s/test/test/" > /dev/null 2>&1 +if test ! x$? = x0 ; then + echo "INTERNAL ERROR: sed command is required" + exit 1 +fi + + +# determine the behavior of echo +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +# determine the behavior of head +case "x`echo 'head' | head -n 1 2>&1`" in + *xhead*) HEAD_N="n " ;; + *) HEAD_N="" ;; +esac + +# determine the behavior of tail +case "x`echo 'tail' | tail -n 1 2>&1`" in + *xtail*) TAIL_N="n " ;; + *) TAIL_N="" ;; +esac + +VERBOSE_ECHO=: +ECHO=: +if [ "x$QUIET" = "xyes" ] ; then + if [ "x$VERBOSE" = "xyes" ] ; then + echo "Verbose output quelled by quiet option. Further output disabled." + fi +else + ECHO=echo + if [ "x$VERBOSE" = "xyes" ] ; then + echo "Verbose output enabled" + VERBOSE_ECHO=echo + fi +fi + + +# allow a recursive run to disable further recursions +if [ "x$RUN_RECURSIVE" = "x" ] ; then + RUN_RECURSIVE=yes +fi + + +################################################ +# check for help arg and bypass version checks # +################################################ +if [ "x`echo $ARGS | sed 's/.*[hH][eE][lL][pP].*/help/'`" = "xhelp" ] ; then + HELP=yes +fi +if [ "x$HELP" = "xyes" ] ; then + usage + $ECHO "---" + $ECHO "Help was requested. No preparation or configuration will be performed." + exit 0 +fi + + +####################### +# set up signal traps # +####################### +untrap_abnormal ( ) { + for sig in 1 2 13 15; do + trap - $sig + done +} + +# do this cleanup whenever we exit. +trap ' + # start from the root + if test -d "$START_PATH" ; then + cd "$START_PATH" + fi + + # restore/delete backup files + if test "x$PFC_INIT" = "x1" ; then + recursive_restore + fi +' 0 + +# trap SIGHUP (1), SIGINT (2), SIGPIPE (13), SIGTERM (15) +for sig in 1 2 13 15; do + trap ' + $ECHO "" + $ECHO "Aborting $NAME_OF_AUTOGEN: caught signal '$sig'" + + # start from the root + if test -d "$START_PATH" ; then + cd "$START_PATH" + fi + + # clean up on abnormal exit + $VERBOSE_ECHO "rm -rf autom4te.cache" + rm -rf autom4te.cache + + if test -f "acinclude.m4.$$.backup" ; then + $VERBOSE_ECHO "cat acinclude.m4.$$.backup > acinclude.m4" + chmod u+w acinclude.m4 + cat acinclude.m4.$$.backup > acinclude.m4 + + $VERBOSE_ECHO "rm -f acinclude.m4.$$.backup" + rm -f acinclude.m4.$$.backup + fi + + { (exit 1); exit 1; } +' $sig +done + + +############################# +# look for a configure file # +############################# +if [ "x$CONFIGURE" = "x" ] ; then + CONFIGURE="`locate_configure_template`" + if [ ! "x$CONFIGURE" = "x" ] ; then + $VERBOSE_ECHO "Found a configure template: $CONFIGURE" + fi +else + $ECHO "Using CONFIGURE environment variable override: $CONFIGURE" +fi +if [ "x$CONFIGURE" = "x" ] ; then + if [ "x$VERSION_ONLY" = "xyes" ] ; then + CONFIGURE=/dev/null + else + $ECHO + $ECHO "A configure.ac or configure.in file could not be located implying" + $ECHO "that the GNU Build System is at least not used in this directory. In" + $ECHO "any case, there is nothing to do here without one of those files." + $ECHO + $ECHO "ERROR: No configure.in or configure.ac file found in `pwd`" + exit 1 + fi +fi + +#################### +# get project name # +#################### +if [ "x$PROJECT" = "x" ] ; then + PROJECT="`grep AC_INIT $CONFIGURE | grep -v '.*#.*AC_INIT' | tail -${TAIL_N}1 | sed 's/^[ ]*AC_INIT(\([^,)]*\).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" + if [ "x$PROJECT" = "xAC_INIT" ] ; then + # projects might be using the older/deprecated arg-less AC_INIT .. look for AM_INIT_AUTOMAKE instead + PROJECT="`grep AM_INIT_AUTOMAKE $CONFIGURE | grep -v '.*#.*AM_INIT_AUTOMAKE' | tail -${TAIL_N}1 | sed 's/^[ ]*AM_INIT_AUTOMAKE(\([^,)]*\).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" + fi + if [ "x$PROJECT" = "xAM_INIT_AUTOMAKE" ] ; then + PROJECT="project" + fi + if [ "x$PROJECT" = "x" ] ; then + PROJECT="project" + fi +else + $ECHO "Using PROJECT environment variable override: $PROJECT" +fi +$ECHO "Preparing the $PROJECT build system...please wait" +$ECHO + + +######################## +# check for autoreconf # +######################## +HAVE_AUTORECONF=no +if [ "x$AUTORECONF" = "x" ] ; then + for AUTORECONF in autoreconf ; do + $VERBOSE_ECHO "Checking autoreconf version: $AUTORECONF --version" + $AUTORECONF --version > /dev/null 2>&1 + if [ $? = 0 ] ; then + HAVE_AUTORECONF=yes + break + fi + done +else + HAVE_AUTORECONF=yes + $ECHO "Using AUTORECONF environment variable override: $AUTORECONF" +fi + + +########################## +# autoconf version check # +########################## +_acfound=no +if [ "x$AUTOCONF" = "x" ] ; then + for AUTOCONF in autoconf ; do + $VERBOSE_ECHO "Checking autoconf version: $AUTOCONF --version" + $AUTOCONF --version > /dev/null 2>&1 + if [ $? = 0 ] ; then + _acfound=yes + break + fi + done +else + _acfound=yes + $ECHO "Using AUTOCONF environment variable override: $AUTOCONF" +fi + +_report_error=no +if [ ! "x$_acfound" = "xyes" ] ; then + $ECHO "ERROR: Unable to locate GNU Autoconf." + _report_error=yes +else + _version="`$AUTOCONF --version | head -${HEAD_N}1 | sed 's/[^0-9]*\([0-9\.][0-9\.]*\)/\1/'`" + if [ "x$_version" = "x" ] ; then + _version="0.0.0" + fi + $ECHO "Found GNU Autoconf version $_version" + version_check "$AUTOCONF_VERSION" "$_version" + if [ $? -ne 0 ] ; then + _report_error=yes + fi +fi +if [ "x$_report_error" = "xyes" ] ; then + version_error "$AUTOCONF_VERSION" "GNU Autoconf" + exit 1 +fi + + +########################## +# automake version check # +########################## +_amfound=no +if [ "x$AUTOMAKE" = "x" ] ; then + for AUTOMAKE in automake ; do + $VERBOSE_ECHO "Checking automake version: $AUTOMAKE --version" + $AUTOMAKE --version > /dev/null 2>&1 + if [ $? = 0 ] ; then + _amfound=yes + break + fi + done +else + _amfound=yes + $ECHO "Using AUTOMAKE environment variable override: $AUTOMAKE" +fi + + +_report_error=no +if [ ! "x$_amfound" = "xyes" ] ; then + $ECHO + $ECHO "ERROR: Unable to locate GNU Automake." + _report_error=yes +else + _version="`$AUTOMAKE --version | head -${HEAD_N}1 | sed 's/[^0-9]*\([0-9\.][0-9\.]*\)/\1/'`" + if [ "x$_version" = "x" ] ; then + _version="0.0.0" + fi + $ECHO "Found GNU Automake version $_version" + version_check "$AUTOMAKE_VERSION" "$_version" + if [ $? -ne 0 ] ; then + _report_error=yes + fi +fi +if [ "x$_report_error" = "xyes" ] ; then + version_error "$AUTOMAKE_VERSION" "GNU Automake" + exit 1 +fi + + +######################## +# check for libtoolize # +######################## +HAVE_LIBTOOLIZE=yes +HAVE_ALT_LIBTOOLIZE=no +_ltfound=no +if [ "x$LIBTOOLIZE" = "x" ] ; then + LIBTOOLIZE=libtoolize + $VERBOSE_ECHO "Checking libtoolize version: $LIBTOOLIZE --version" + $LIBTOOLIZE --version > /dev/null 2>&1 + if [ ! $? = 0 ] ; then + HAVE_LIBTOOLIZE=no + $ECHO + if [ "x$HAVE_AUTORECONF" = "xno" ] ; then + $ECHO "Warning: libtoolize does not appear to be available." + else + $ECHO "Warning: libtoolize does not appear to be available. This means that" + $ECHO "the automatic build preparation via autoreconf will probably not work." + $ECHO "Preparing the build by running each step individually, however, should" + $ECHO "work and will be done automatically for you if autoreconf fails." + fi + + # look for some alternates + for tool in glibtoolize libtoolize15 libtoolize14 libtoolize13 ; do + $VERBOSE_ECHO "Checking libtoolize alternate: $tool --version" + _glibtoolize="`$tool --version > /dev/null 2>&1`" + if [ $? = 0 ] ; then + $VERBOSE_ECHO "Found $tool --version" + _glti="`which $tool`" + if [ "x$_glti" = "x" ] ; then + $VERBOSE_ECHO "Cannot find $tool with which" + continue; + fi + if test ! -f "$_glti" ; then + $VERBOSE_ECHO "Cannot use $tool, $_glti is not a file" + continue; + fi + _gltidir="`dirname $_glti`" + if [ "x$_gltidir" = "x" ] ; then + $VERBOSE_ECHO "Cannot find $tool path with dirname of $_glti" + continue; + fi + if test ! -d "$_gltidir" ; then + $VERBOSE_ECHO "Cannot use $tool, $_gltidir is not a directory" + continue; + fi + HAVE_ALT_LIBTOOLIZE=yes + LIBTOOLIZE="$tool" + $ECHO + $ECHO "Fortunately, $tool was found which means that your system may simply" + $ECHO "have a non-standard or incomplete GNU Autotools install. If you have" + $ECHO "sufficient system access, it may be possible to quell this warning by" + $ECHO "running:" + $ECHO + sudo -V > /dev/null 2>&1 + if [ $? = 0 ] ; then + $ECHO " sudo ln -s $_glti $_gltidir/libtoolize" + $ECHO + else + $ECHO " ln -s $_glti $_gltidir/libtoolize" + $ECHO + $ECHO "Run that as root or with proper permissions to the $_gltidir directory" + $ECHO + fi + _ltfound=yes + break + fi + done + else + _ltfound=yes + fi +else + _ltfound=yes + $ECHO "Using LIBTOOLIZE environment variable override: $LIBTOOLIZE" +fi + + +############################ +# libtoolize version check # +############################ +_report_error=no +if [ ! "x$_ltfound" = "xyes" ] ; then + $ECHO + $ECHO "ERROR: Unable to locate GNU Libtool." + _report_error=yes +else + _version="`$LIBTOOLIZE --version | head -${HEAD_N}1 | sed 's/[^0-9]*\([0-9\.][0-9\.]*\)/\1/'`" + if [ "x$_version" = "x" ] ; then + _version="0.0.0" + fi + $ECHO "Found GNU Libtool version $_version" + version_check "$LIBTOOL_VERSION" "$_version" + if [ $? -ne 0 ] ; then + _report_error=yes + fi +fi +if [ "x$_report_error" = "xyes" ] ; then + version_error "$LIBTOOL_VERSION" "GNU Libtool" + exit 1 +fi + + +##################### +# check for aclocal # +##################### +if [ "x$ACLOCAL" = "x" ] ; then + for ACLOCAL in aclocal ; do + $VERBOSE_ECHO "Checking aclocal version: $ACLOCAL --version" + $ACLOCAL --version > /dev/null 2>&1 + if [ $? = 0 ] ; then + break + fi + done +else + $ECHO "Using ACLOCAL environment variable override: $ACLOCAL" +fi + + +######################## +# check for autoheader # +######################## +if [ "x$AUTOHEADER" = "x" ] ; then + for AUTOHEADER in autoheader ; do + $VERBOSE_ECHO "Checking autoheader version: $AUTOHEADER --version" + $AUTOHEADER --version > /dev/null 2>&1 + if [ $? = 0 ] ; then + break + fi + done +else + $ECHO "Using AUTOHEADER environment variable override: $AUTOHEADER" +fi + + +######################### +# check if version only # +######################### +$VERBOSE_ECHO "Checking whether to only output version information" +if [ "x$VERSION_ONLY" = "xyes" ] ; then + $ECHO + ident + $ECHO "---" + $ECHO "Version requested. No preparation or configuration will be performed." + exit 0 +fi + + +################################# +# PROTECT_FROM_CLOBBER FUNCTION # +################################# +protect_from_clobber ( ) { + PFC_INIT=1 + + # protect COPYING & INSTALL from overwrite by automake. the + # automake force option will (inappropriately) ignore the existing + # contents of a COPYING and/or INSTALL files (depending on the + # version) instead of just forcing *missing* files like it does + # for AUTHORS, NEWS, and README. this is broken but extremely + # prevalent behavior, so we protect against it by keeping a backup + # of the file that can later be restored. + + for file in COPYING INSTALL ; do + if test -f ${file} ; then + if test -f ${file}.$$.protect_from_automake.backup ; then + $VERBOSE_ECHO "Already backed up ${file} in `pwd`" + else + $VERBOSE_ECHO "Backing up ${file} in `pwd`" + $VERBOSE_ECHO "cp -p ${file} ${file}.$$.protect_from_automake.backup" + cp -p ${file} ${file}.$$.protect_from_automake.backup + fi + fi + done +} + + +############################## +# RECURSIVE_PROTECT FUNCTION # +############################## +recursive_protect ( ) { + + # for projects using recursive configure, run the build + # preparation steps for the subdirectories. this function assumes + # START_PATH was set to pwd before recursion begins so that + # relative paths work. + + # git 'r done, protect COPYING and INSTALL from being clobbered + protect_from_clobber + + if test -d autom4te.cache ; then + $VERBOSE_ECHO "Found an autom4te.cache directory, deleting it" + $VERBOSE_ECHO "rm -rf autom4te.cache" + rm -rf autom4te.cache + fi + + # find configure template + _configure="`locate_configure_template`" + if [ "x$_configure" = "x" ] ; then + return + fi + # $VERBOSE_ECHO "Looking for configure template found `pwd`/$_configure" + + # look for subdirs + # $VERBOSE_ECHO "Looking for subdirs in `pwd`" + _det_config_subdirs="`grep AC_CONFIG_SUBDIRS $_configure | grep -v '.*#.*AC_CONFIG_SUBDIRS' | sed 's/^[ ]*AC_CONFIG_SUBDIRS(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" + CHECK_DIRS="" + for dir in $_det_config_subdirs ; do + if test -d "`pwd`/$dir" ; then + CHECK_DIRS="$CHECK_DIRS \"`pwd`/$dir\"" + fi + done + + # process subdirs + if [ ! "x$CHECK_DIRS" = "x" ] ; then + $VERBOSE_ECHO "Recursively scanning the following directories:" + $VERBOSE_ECHO " $CHECK_DIRS" + for dir in $CHECK_DIRS ; do + $VERBOSE_ECHO "Protecting files from automake in $dir" + cd "$START_PATH" + eval "cd $dir" + + # recursively git 'r done + recursive_protect + done + fi +} # end of recursive_protect + + +############################# +# RESTORE_CLOBBERED FUNCION # +############################# +restore_clobbered ( ) { + + # The automake (and autoreconf by extension) -f/--force-missing + # option may overwrite COPYING and INSTALL even if they do exist. + # Here we restore the files if necessary. + + spacer=no + + for file in COPYING INSTALL ; do + if test -f ${file}.$$.protect_from_automake.backup ; then + if test -f ${file} ; then + # compare entire content, restore if needed + if test "x`cat ${file}`" != "x`cat ${file}.$$.protect_from_automake.backup`" ; then + if test "x$spacer" = "xno" ; then + $VERBOSE_ECHO + spacer=yes + fi + # restore the backup + $VERBOSE_ECHO "Restoring ${file} from backup (automake -f likely clobbered it)" + $VERBOSE_ECHO "rm -f ${file}" + rm -f ${file} + $VERBOSE_ECHO "mv ${file}.$$.protect_from_automake.backup ${file}" + mv ${file}.$$.protect_from_automake.backup ${file} + fi # check contents + elif test -f ${file}.$$.protect_from_automake.backup ; then + $VERBOSE_ECHO "mv ${file}.$$.protect_from_automake.backup ${file}" + mv ${file}.$$.protect_from_automake.backup ${file} + fi # -f ${file} + + # just in case + $VERBOSE_ECHO "rm -f ${file}.$$.protect_from_automake.backup" + rm -f ${file}.$$.protect_from_automake.backup + fi # -f ${file}.$$.protect_from_automake.backup + done + + CONFIGURE="`locate_configure_template`" + if [ "x$CONFIGURE" = "x" ] ; then + return + fi + + _aux_dir="`grep AC_CONFIG_AUX_DIR $CONFIGURE | grep -v '.*#.*AC_CONFIG_AUX_DIR' | tail -${TAIL_N}1 | sed 's/^[ ]*AC_CONFIG_AUX_DIR(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" + if test ! -d "$_aux_dir" ; then + _aux_dir=. + fi + + for file in config.guess config.sub ltmain.sh ; do + if test -f "${_aux_dir}/${file}" ; then + $VERBOSE_ECHO "rm -f \"${_aux_dir}/${file}.backup\"" + rm -f "${_aux_dir}/${file}.backup" + fi + done +} # end of restore_clobbered + + +############################## +# RECURSIVE_RESTORE FUNCTION # +############################## +recursive_restore ( ) { + + # restore COPYING and INSTALL from backup if they were clobbered + # for each directory recursively. + + # git 'r undone + restore_clobbered + + # find configure template + _configure="`locate_configure_template`" + if [ "x$_configure" = "x" ] ; then + return + fi + + # look for subdirs + _det_config_subdirs="`grep AC_CONFIG_SUBDIRS $_configure | grep -v '.*#.*AC_CONFIG_SUBDIRS' | sed 's/^[ ]*AC_CONFIG_SUBDIRS(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" + CHECK_DIRS="" + for dir in $_det_config_subdirs ; do + if test -d "`pwd`/$dir" ; then + CHECK_DIRS="$CHECK_DIRS \"`pwd`/$dir\"" + fi + done + + # process subdirs + if [ ! "x$CHECK_DIRS" = "x" ] ; then + $VERBOSE_ECHO "Recursively scanning the following directories:" + $VERBOSE_ECHO " $CHECK_DIRS" + for dir in $CHECK_DIRS ; do + $VERBOSE_ECHO "Checking files for automake damage in $dir" + cd "$START_PATH" + eval "cd $dir" + + # recursively git 'r undone + recursive_restore + done + fi +} # end of recursive_restore + + +####################### +# INITIALIZE FUNCTION # +####################### +initialize ( ) { + + # this routine performs a variety of directory-specific + # initializations. some are sanity checks, some are preventive, + # and some are necessary setup detection. + # + # this function sets: + # CONFIGURE + # SEARCH_DIRS + # CONFIG_SUBDIRS + + ################################## + # check for a configure template # + ################################## + CONFIGURE="`locate_configure_template`" + if [ "x$CONFIGURE" = "x" ] ; then + $ECHO + $ECHO "A configure.ac or configure.in file could not be located implying" + $ECHO "that the GNU Build System is at least not used in this directory. In" + $ECHO "any case, there is nothing to do here without one of those files." + $ECHO + $ECHO "ERROR: No configure.in or configure.ac file found in `pwd`" + exit 1 + fi + + ##################### + # detect an aux dir # + ##################### + _aux_dir="`grep AC_CONFIG_AUX_DIR $CONFIGURE | grep -v '.*#.*AC_CONFIG_AUX_DIR' | tail -${TAIL_N}1 | sed 's/^[ ]*AC_CONFIG_AUX_DIR(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" + if test ! -d "$_aux_dir" ; then + _aux_dir=. + else + $VERBOSE_ECHO "Detected auxillary directory: $_aux_dir" + fi + + ################################ + # detect a recursive configure # + ################################ + CONFIG_SUBDIRS="" + _det_config_subdirs="`grep AC_CONFIG_SUBDIRS $CONFIGURE | grep -v '.*#.*AC_CONFIG_SUBDIRS' | sed 's/^[ ]*AC_CONFIG_SUBDIRS(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" + for dir in $_det_config_subdirs ; do + if test -d "`pwd`/$dir" ; then + $VERBOSE_ECHO "Detected recursive configure directory: `pwd`/$dir" + CONFIG_SUBDIRS="$CONFIG_SUBDIRS `pwd`/$dir" + fi + done + + ########################################################### + # make sure certain required files exist for GNU projects # + ########################################################### + _marker_found="" + _marker_found_message_intro='Detected non-GNU marker "' + _marker_found_message_mid='" in ' + for marker in foreign cygnus ; do + _marker_found_message=${_marker_found_message_intro}${marker}${_marker_found_message_mid} + _marker_found="`grep 'AM_INIT_AUTOMAKE.*'${marker} $CONFIGURE`" + if [ ! "x$_marker_found" = "x" ] ; then + $VERBOSE_ECHO "${_marker_found_message}`basename \"$CONFIGURE\"`" + break + fi + if test -f "`dirname \"$CONFIGURE\"/Makefile.am`" ; then + _marker_found="`grep 'AUTOMAKE_OPTIONS.*'${marker} Makefile.am`" + if [ ! "x$_marker_found" = "x" ] ; then + $VERBOSE_ECHO "${_marker_found_message}Makefile.am" + break + fi + fi + done + if [ "x${_marker_found}" = "x" ] ; then + _suggest_foreign=no + for file in AUTHORS COPYING ChangeLog INSTALL NEWS README ; do + if [ ! -f $file ] ; then + $VERBOSE_ECHO "Touching ${file} since it does not exist" + _suggest_foreign=yes + touch $file + fi + done + + if [ "x${_suggest_foreign}" = "xyes" ] ; then + $ECHO + $ECHO "Warning: Several files expected of projects that conform to the GNU" + $ECHO "coding standards were not found. The files were automatically added" + $ECHO "for you since you do not have a 'foreign' declaration specified." + $ECHO + $ECHO "Considered adding 'foreign' to AM_INIT_AUTOMAKE in `basename \"$CONFIGURE\"`" + if test -f "`dirname \"$CONFIGURE\"/Makefile.am`" ; then + $ECHO "or to AUTOMAKE_OPTIONS in your top-level Makefile.am file." + fi + $ECHO + fi + fi + + ################################################## + # make sure certain generated files do not exist # + ################################################## + for file in config.guess config.sub ltmain.sh ; do + if test -f "${_aux_dir}/${file}" ; then + $VERBOSE_ECHO "mv -f \"${_aux_dir}/${file}\" \"${_aux_dir}/${file}.backup\"" + mv -f "${_aux_dir}/${file}" "${_aux_dir}/${file}.backup" + fi + done + + ############################ + # search alternate m4 dirs # + ############################ + SEARCH_DIRS="" + for dir in m4 ; do + if [ -d $dir ] ; then + $VERBOSE_ECHO "Found extra aclocal search directory: $dir" + SEARCH_DIRS="$SEARCH_DIRS -I $dir" + fi + done + + ###################################### + # remove any previous build products # + ###################################### + if test -d autom4te.cache ; then + $VERBOSE_ECHO "Found an autom4te.cache directory, deleting it" + $VERBOSE_ECHO "rm -rf autom4te.cache" + rm -rf autom4te.cache + fi +# tcl/tk (and probably others) have a customized aclocal.m4, so can't delete it +# if test -f aclocal.m4 ; then +# $VERBOSE_ECHO "Found an aclocal.m4 file, deleting it" +# $VERBOSE_ECHO "rm -f aclocal.m4" +# rm -f aclocal.m4 +# fi + +} # end of initialize() + + +############## +# initialize # +############## + +# stash path +START_PATH="`pwd`" + +# Before running autoreconf or manual steps, some prep detection work +# is necessary or useful. Only needs to occur once per directory, but +# does need to traverse the entire subconfigure hierarchy to protect +# files from being clobbered even by autoreconf. +recursive_protect + +# start from where we started +cd "$START_PATH" + +# get ready to process +initialize + + +######################################### +# DOWNLOAD_GNULIB_CONFIG_GUESS FUNCTION # +######################################### + +# TODO - should make sure wget/curl exist and/or work before trying to +# use them. + +download_gnulib_config_guess () { + # abuse gitweb to download gnulib's latest config.guess via HTTP + config_guess_temp="config.guess.$$.download" + ret=1 + for __cmd in wget curl fetch ; do + $VERBOSE_ECHO "Checking for command ${__cmd}" + ${__cmd} --version > /dev/null 2>&1 + ret=$? + if [ ! $ret = 0 ] ; then + continue + fi + + __cmd_version=`${__cmd} --version | head -n 1 | sed -e 's/^[^0-9]\+//' -e 's/ .*//'` + $VERBOSE_ECHO "Found ${__cmd} ${__cmd_version}" + + opts="" + case ${__cmd} in + wget) + opts="-O" + ;; + curl) + opts="-o" + ;; + fetch) + opts="-t 5 -f" + ;; + esac + + $VERBOSE_ECHO "Running $__cmd \"${CONFIG_GUESS_URL}\" $opts \"${config_guess_temp}\"" + eval "$__cmd \"${CONFIG_GUESS_URL}\" $opts \"${config_guess_temp}\"" > /dev/null 2>&1 + if [ $? = 0 ] ; then + mv -f "${config_guess_temp}" ${_aux_dir}/config.guess + ret=0 + break + fi + done + + if [ ! $ret = 0 ] ; then + $ECHO "Warning: config.guess download failed from: $CONFIG_GUESS_URL" + rm -f "${config_guess_temp}" + fi +} + + +############################## +# LIBTOOLIZE_NEEDED FUNCTION # +############################## +libtoolize_needed () { + ret=1 # means no, don't need libtoolize + for feature in AC_PROG_LIBTOOL AM_PROG_LIBTOOL LT_INIT ; do + $VERBOSE_ECHO "Searching for $feature in $CONFIGURE" + found="`grep \"^$feature.*\" $CONFIGURE`" + if [ ! "x$found" = "x" ] ; then + ret=0 # means yes, need to run libtoolize + break + fi + done + return ${ret} +} + + + +############################################ +# prepare build via autoreconf or manually # +############################################ +reconfigure_manually=no +if [ "x$HAVE_AUTORECONF" = "xyes" ] ; then + $ECHO + $ECHO $ECHO_N "Automatically preparing build ... $ECHO_C" + + $VERBOSE_ECHO "$AUTORECONF $SEARCH_DIRS $AUTORECONF_OPTIONS" + autoreconf_output="`$AUTORECONF $SEARCH_DIRS $AUTORECONF_OPTIONS 2>&1`" + ret=$? + $VERBOSE_ECHO "$autoreconf_output" + + if [ ! $ret = 0 ] ; then + if [ "x$HAVE_ALT_LIBTOOLIZE" = "xyes" ] ; then + if [ ! "x`echo \"$autoreconf_output\" | grep libtoolize | grep \"No such file or directory\"`" = "x" ] ; then + $ECHO + $ECHO "Warning: autoreconf failed but due to what is usually a common libtool" + $ECHO "misconfiguration issue. This problem is encountered on systems that" + $ECHO "have installed libtoolize under a different name without providing a" + $ECHO "symbolic link or without setting the LIBTOOLIZE environment variable." + $ECHO + $ECHO "Restarting the preparation steps with LIBTOOLIZE set to $LIBTOOLIZE" + + export LIBTOOLIZE + RUN_RECURSIVE=no + export RUN_RECURSIVE + untrap_abnormal + + $VERBOSE_ECHO sh $AUTOGEN_SH "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" + sh "$AUTOGEN_SH" "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" + exit $? + fi + fi + + $ECHO "Warning: $AUTORECONF failed" + + if test -f ltmain.sh ; then + $ECHO "libtoolize being run by autoreconf is not creating ltmain.sh in the auxillary directory like it should" + fi + + $ECHO "Attempting to run the preparation steps individually" + reconfigure_manually=yes + else + if [ "x$DOWNLOAD" = "xyes" ] ; then + if libtoolize_needed ; then + download_gnulib_config_guess + fi + fi + fi +else + reconfigure_manually=yes +fi + + +############################ +# LIBTOOL_FAILURE FUNCTION # +############################ +libtool_failure ( ) { + + # libtool is rather error-prone in comparison to the other + # autotools and this routine attempts to compensate for some + # common failures. the output after a libtoolize failure is + # parsed for an error related to AC_PROG_LIBTOOL and if found, we + # attempt to inject a project-provided libtool.m4 file. + + _autoconf_output="$1" + + if [ "x$RUN_RECURSIVE" = "xno" ] ; then + # we already tried the libtool.m4, don't try again + return 1 + fi + + if test -f "$LIBTOOL_M4" ; then + found_libtool="`$ECHO $_autoconf_output | grep AC_PROG_LIBTOOL`" + if test ! "x$found_libtool" = "x" ; then + if test -f acinclude.m4 ; then + rm -f acinclude.m4.$$.backup + $VERBOSE_ECHO "cat acinclude.m4 > acinclude.m4.$$.backup" + cat acinclude.m4 > acinclude.m4.$$.backup + fi + $VERBOSE_ECHO "cat \"$LIBTOOL_M4\" >> acinclude.m4" + chmod u+w acinclude.m4 + cat "$LIBTOOL_M4" >> acinclude.m4 + + # don't keep doing this + RUN_RECURSIVE=no + export RUN_RECURSIVE + untrap_abnormal + + $ECHO + $ECHO "Restarting the preparation steps with libtool macros in acinclude.m4" + $VERBOSE_ECHO sh $AUTOGEN_SH "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" + sh "$AUTOGEN_SH" "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" + exit $? + fi + fi +} + + +########################### +# MANUAL_AUTOGEN FUNCTION # +########################### +manual_autogen ( ) { + + ################################################## + # Manual preparation steps taken are as follows: # + # aclocal [-I m4] # + # libtoolize --automake -c -f # + # aclocal [-I m4] # + # autoconf -f # + # autoheader # + # automake -a -c -f # + ################################################## + + ########### + # aclocal # + ########### + $VERBOSE_ECHO "$ACLOCAL $SEARCH_DIRS $ACLOCAL_OPTIONS" + aclocal_output="`$ACLOCAL $SEARCH_DIRS $ACLOCAL_OPTIONS 2>&1`" + ret=$? + $VERBOSE_ECHO "$aclocal_output" + if [ ! $ret = 0 ] ; then $ECHO "ERROR: $ACLOCAL failed" && exit 2 ; fi + + ############## + # libtoolize # + ############## + if libtoolize_needed ; then + if [ "x$HAVE_LIBTOOLIZE" = "xyes" ] ; then + $VERBOSE_ECHO "$LIBTOOLIZE $LIBTOOLIZE_OPTIONS" + libtoolize_output="`$LIBTOOLIZE $LIBTOOLIZE_OPTIONS 2>&1`" + ret=$? + $VERBOSE_ECHO "$libtoolize_output" + + if [ ! $ret = 0 ] ; then $ECHO "ERROR: $LIBTOOLIZE failed" && exit 2 ; fi + else + if [ "x$HAVE_ALT_LIBTOOLIZE" = "xyes" ] ; then + $VERBOSE_ECHO "$LIBTOOLIZE $ALT_LIBTOOLIZE_OPTIONS" + libtoolize_output="`$LIBTOOLIZE $ALT_LIBTOOLIZE_OPTIONS 2>&1`" + ret=$? + $VERBOSE_ECHO "$libtoolize_output" + + if [ ! $ret = 0 ] ; then $ECHO "ERROR: $LIBTOOLIZE failed" && exit 2 ; fi + fi + fi + + ########### + # aclocal # + ########### + # re-run again as instructed by libtoolize + $VERBOSE_ECHO "$ACLOCAL $SEARCH_DIRS $ACLOCAL_OPTIONS" + aclocal_output="`$ACLOCAL $SEARCH_DIRS $ACLOCAL_OPTIONS 2>&1`" + ret=$? + $VERBOSE_ECHO "$aclocal_output" + + # libtoolize might put ltmain.sh in the wrong place + if test -f ltmain.sh ; then + if test ! -f "${_aux_dir}/ltmain.sh" ; then + $ECHO + $ECHO "Warning: $LIBTOOLIZE is creating ltmain.sh in the wrong directory" + $ECHO + $ECHO "Fortunately, the problem can be worked around by simply copying the" + $ECHO "file to the appropriate location (${_aux_dir}/). This has been done for you." + $ECHO + $VERBOSE_ECHO "cp -p ltmain.sh \"${_aux_dir}/ltmain.sh\"" + cp -p ltmain.sh "${_aux_dir}/ltmain.sh" + $ECHO $ECHO_N "Continuing build preparation ... $ECHO_C" + fi + fi # ltmain.sh + + if [ "x$DOWNLOAD" = "xyes" ] ; then + download_gnulib_config_guess + fi + fi # libtoolize_needed + + ############ + # autoconf # + ############ + $VERBOSE_ECHO + $VERBOSE_ECHO "$AUTOCONF $AUTOCONF_OPTIONS" + autoconf_output="`$AUTOCONF $AUTOCONF_OPTIONS 2>&1`" + ret=$? + $VERBOSE_ECHO "$autoconf_output" + + if [ ! $ret = 0 ] ; then + # retry without the -f and check for usage of macros that are too new + ac2_59_macros="AC_C_RESTRICT AC_INCLUDES_DEFAULT AC_LANG_ASSERT AC_LANG_WERROR AS_SET_CATFILE" + ac2_55_macros="AC_COMPILER_IFELSE AC_FUNC_MBRTOWC AC_HEADER_STDBOOL AC_LANG_CONFTEST AC_LANG_SOURCE AC_LANG_PROGRAM AC_LANG_CALL AC_LANG_FUNC_TRY_LINK AC_MSG_FAILURE AC_PREPROC_IFELSE" + ac2_54_macros="AC_C_BACKSLASH_A AC_CONFIG_LIBOBJ_DIR AC_GNU_SOURCE AC_PROG_EGREP AC_PROG_FGREP AC_REPLACE_FNMATCH AC_FUNC_FNMATCH_GNU AC_FUNC_REALLOC AC_TYPE_MBSTATE_T" + + macros_to_search="" + ac_major="`echo ${AUTOCONF_VERSION}. | cut -d. -f1 | sed 's/[^0-9]//g'`" + ac_minor="`echo ${AUTOCONF_VERSION}. | cut -d. -f2 | sed 's/[^0-9]//g'`" + + if [ $ac_major -lt 2 ] ; then + macros_to_search="$ac2_59_macros $ac2_55_macros $ac2_54_macros" + else + if [ $ac_minor -lt 54 ] ; then + macros_to_search="$ac2_59_macros $ac2_55_macros $ac2_54_macros" + elif [ $ac_minor -lt 55 ] ; then + macros_to_search="$ac2_59_macros $ac2_55_macros" + elif [ $ac_minor -lt 59 ] ; then + macros_to_search="$ac2_59_macros" + fi + fi + + configure_ac_macros=__none__ + for feature in $macros_to_search ; do + $VERBOSE_ECHO "Searching for $feature in $CONFIGURE" + found="`grep \"^$feature.*\" $CONFIGURE`" + if [ ! "x$found" = "x" ] ; then + if [ "x$configure_ac_macros" = "x__none__" ] ; then + configure_ac_macros="$feature" + else + configure_ac_macros="$feature $configure_ac_macros" + fi + fi + done + if [ ! "x$configure_ac_macros" = "x__none__" ] ; then + $ECHO + $ECHO "Warning: Unsupported macros were found in $CONFIGURE" + $ECHO + $ECHO "The `basename \"$CONFIGURE\"` file was scanned in order to determine if any" + $ECHO "unsupported macros are used that exceed the minimum version" + $ECHO "settings specified within this file. As such, the following macros" + $ECHO "should be removed from configure.ac or the version numbers in this" + $ECHO "file should be increased:" + $ECHO + $ECHO "$configure_ac_macros" + $ECHO + $ECHO $ECHO_N "Ignorantly continuing build preparation ... $ECHO_C" + fi + + ################### + # autoconf, retry # + ################### + $VERBOSE_ECHO + $VERBOSE_ECHO "$AUTOCONF" + autoconf_output="`$AUTOCONF 2>&1`" + ret=$? + $VERBOSE_ECHO "$autoconf_output" + + if [ ! $ret = 0 ] ; then + # test if libtool is busted + libtool_failure "$autoconf_output" + + # let the user know what went wrong + cat < header file. */ -#define HAVE_BYTESWAP_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if libc implements gethostbyname2_r */ -#define HAVE_GETHOSTBYNAME2_R 1 - -/* Define if libc implements gethostbyname_r */ -#define HAVE_GETHOSTBYNAME_R 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define LT_OBJDIR ".libs/" - -/* Name of package */ -#define PACKAGE "openbts" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "openbts" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "openbts 3.0TRUNK" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "openbts" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "3.0TRUNK" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both and . */ -#define TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define VERSION "3.0TRUNK" - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -/* # undef WORDS_BIGENDIAN */ -# endif -#endif - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ diff --git a/config/Makefile.am b/config/Makefile.am new file mode 100644 index 0000000..69263e3 --- /dev/null +++ b/config/Makefile.am @@ -0,0 +1,30 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This software is distributed under the terms of the GNU Public License. +# See the COPYING 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 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +include $(top_srcdir)/Makefile.common + +# Install m4 macros in this directory +m4datadir = $(datadir)/aclocal + +# List your m4 macros here +m4macros = \ + pkg.m4 + +EXTRA_DIST = $(m4macros) diff --git a/config/pkg.m4 b/config/pkg.m4 new file mode 100644 index 0000000..80bdfed --- /dev/null +++ b/config/pkg.m4 @@ -0,0 +1,188 @@ +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# +# Copyright © 2004 Scott James Remnant . +# Copyright © 2008 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 +# the Free Software Foundation; either version 2 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.18]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi + +fi[]dnl +])# PKG_PROG_PKG_CONFIG + +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# +# Similar to PKG_CHECK_MODULES, make sure that the first instance of +# this or PKG_CHECK_MODULES is called, or make sure to call +# PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_ifval([$2], [$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + + +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- +m4_define([_PKG_CONFIG], +[if test -n "$PKG_CONFIG"; then + if test -n "$$1"; then + pkg_cv_[]$1="$$1" + else + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], + [pkg_failed=yes]) + fi +else + pkg_failed=untried +fi[]dnl +])# _PKG_CONFIG + +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])# _PKG_SHORT_ERRORS_SUPPORTED + + +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# E.g., +# PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) +# defines: +# +# GSTUFF_LIBS +# GSTUFF_CFLAGS +# GSTUFF_INCLUDEDIR +# GSTUFF_CPPFLAGS # the -I, -D and -U's out of CFLAGS +# +# see pkg-config man page also defines GSTUFF_PKG_ERRORS on error +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_INCLUDEDIR], [includedir for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) + +if test x$cross_compiling = xyes +then + _PKG_CONFIG([$1][_LIBS], [libs-only-l --static], [$2]) +else + _PKG_CONFIG([$1][_LIBS], [libs --static], [$2]) +fi + +_PKG_CONFIG([$1][_INCLUDEDIR], [variable=includedir], [$2]) + + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + ifelse([$4], , [AC_MSG_ERROR(dnl +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT +])], + [AC_MSG_RESULT([no]) + $4]) +elif test $pkg_failed = untried; then + ifelse([$4], , [AC_MSG_FAILURE(dnl +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])], + [$4]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + $1[]_INCLUDEDIR=$pkg_cv_[]$1[]_INCLUDEDIR + + $1[]_CPPFLAGS="" + for flag in $$1[]_CFLAGS; do + case $flag in + -I* | -D* | -U*) $1[]_CPPFLAGS="$$1[]_CPPFLAGS $flag" ;; + esac + done + pkg_cv_[]$1[]_CPPFLAGS=$$1[]_CPPFLAGS + AC_SUBST($1[]_CPPFLAGS) + + AC_MSG_RESULT([yes]) + ifelse([$3], , :, [$3]) +fi[]dnl +])# PKG_CHECK_MODULES diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..06f71a7 --- /dev/null +++ b/configure.ac @@ -0,0 +1,87 @@ +dnl +dnl Copyright 2008, 2009, 2010 Free Software Foundation, Inc. +dnl +dnl This software is distributed under the terms of the GNU Public License. +dnl See the COPYING file in the main directory for details. +dnl +dnl This program is free software: you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation, either version 3 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program. If not, see . +dnl + +AC_INIT(subscriberregistry,4.0TRUNK) +AC_PREREQ(2.57) +AC_CONFIG_SRCDIR([config/Makefile.am]) +AC_CONFIG_AUX_DIR([.]) +AM_CONFIG_HEADER(config.h) + +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +AM_INIT_AUTOMAKE + +AM_PROG_AS +AC_PROG_CXX +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_INSTALL +AC_PATH_PROG([RM_PROG], [rm]) + +AC_LIBTOOL_WIN32_DLL +AC_ENABLE_SHARED dnl do build shared libraries +AC_DISABLE_STATIC dnl don't build static libraries +AC_PROG_LIBTOOL + +dnl Checks for header files. +AC_HEADER_STDC +dnl This is required for GnuRadio includes to understand endianess correctly: +AC_CHECK_HEADERS([byteswap.h]) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +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_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])]) + +# Check for glibc-specific network functions +AC_CHECK_FUNC(gethostbyname_r, [AC_DEFINE(HAVE_GETHOSTBYNAME_R, 1, Define if libc implements gethostbyname_r)]) +AC_CHECK_FUNC(gethostbyname2_r, [AC_DEFINE(HAVE_GETHOSTBYNAME2_R, 1, Define if libc implements gethostbyname2_r)]) + +dnl Output files +AC_CONFIG_FILES([\ + Makefile \ + apps/Makefile \ + config/Makefile \ + CommonLibs/Makefile \ + Globals/Makefile \ + NodeManager/Makefile \ + sqlite3/Makefile \ +]) + +AC_OUTPUT diff --git a/debian/changelog b/debian/changelog index ab7e2af..e1dd50c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,12 +1,5 @@ -sipauthserve-public (3.2) UNRELEASED; urgency=low - - * Non-maintainer upload. - * Public release - - -- Kurtis Tue, 30 Jul 2013 23:01:28 -0700 - -sipauthserve-public (3.2) UNRELEASED; urgency=low +sipauthserve (4.0) unstable; urgency=low * Test - -- Donald C. Kirker Mon, 22 Apr 2013 00:11:00 -0700 + -- Donald C. Kirker Mon, 22 Apr 2013 00:11:00 -0700 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index d00491f..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/debian/control b/debian/control index cee9340..b4be927 100755 --- a/debian/control +++ b/debian/control @@ -1,19 +1,16 @@ -Source: sipauthserve-public -Provides: sipauthserve +Source: sipauthserve Section: comm Priority: optional Maintainer: Range Networks, Inc. Homepage: http://www.rangenetworks.com/ -Build-Depends: build-essential, debhelper (>= 7), libosip2-dev, pkg-config, autoconf, libsqlite3-dev (>= 3.7) +Build-Depends: build-essential, debhelper (>= 7), libosip2-dev, pkg-config, autoconf, libtool Standards-Version: 3.7.3 -Package: sipauthserve-public -Provides: sipauthserve -Version: TRUNK +Package: sipauthserve 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 - SIP Authorization Server diff --git a/debian/postinst b/debian/postinst index aa5ccc8..ea97a39 100755 --- a/debian/postinst +++ b/debian/postinst @@ -19,37 +19,37 @@ set -e configure() { -DB_LOC=/etc/OpenBTS/sipauthserve.db -DATE=$(date +'%Y-%m-%d.%H:%M:%S') -CONFIG_BACKUP=$DB_LOC.dump-$DATE +DATE=$(date --rfc-3339='date') +CONFIG_BACKUP=/etc/OpenBTS/OpenBTS.dump-$DATE + if [ ! -e $CONFIG_BACKUP ]; then - sqlite3 $DB_LOC ".dump" > $CONFIG_BACKUP + sqlite3 /etc/OpenBTS/OpenBTS.db ".dump" > $CONFIG_BACKUP fi -sqlite3 $DB_LOC ".read /etc/OpenBTS/subscriberRegistry.example.sql" > /dev/null 2>&1 +sqlite3 /etc/OpenBTS/OpenBTS.db ".read /etc/OpenBTS/subscriberRegistry.example.sql" > /dev/null 2>&1 -SR_DIR=/var/lib/asterisk/sqlite3dir -SRPATH=$SR_DIR/sqlite3.db +if [ ! -d /var/lib/asterisk/sqlite3dir ]; then + mkdir -p /var/lib/asterisk/sqlite3dir +fi + +SRPATH=/var/lib/asterisk/sqlite3dir/sqlite3.db + +DATE=$(date --rfc-3339='date') SR_CONFIG_BACKUP=$SRPATH.dump-$DATE -if [ ! -d $SR_DIR ]; then - mkdir -p $SR_DIR -fi -chown -R root:www-data $SR_DIR -chmod 775 $SR_DIR -if [[ -e $SRPATH && "`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)"`" != "" ]]; then +if [[ -e $SRPATH && "`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" || true`" != "" ]]; then if [ ! -e $SR_CONFIG_BACKUP ]; then sqlite3 $SRPATH ".dump" > $SR_CONFIG_BACKUP fi - HASPREPAID=`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" | grep prepaid` + HASPREPAID=`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" | grep prepaid || true` if [ "$HASPREPAID" = "" ]; then sqlite3 $SRPATH "alter table sip_buddies add prepaid int(1) DEFAULT 0 not null" fi - HASBALANCE=`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" | grep account_balance` + HASBALANCE=`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" | grep account_balance || true` if [ "$HASBALANCE" = "" ]; then sqlite3 $SRPATH "alter table sip_buddies add column account_balance int(9) default 0" fi @@ -64,8 +64,10 @@ fi # set up permissions for webui, temporary fix until ui is replumbed to use json # directory permissions -if [ -e $SRPATH ]; then - chmod 664 $SR_DIR/sqlite3* +chown -R root:www-data /var/lib/asterisk/sqlite3dir +chmod 775 /var/lib/asterisk/sqlite3dir/ +if [ -e /var/lib/asterisk/sqlite3dir/sqlite3.db ]; then + chmod 664 /var/lib/asterisk/sqlite3dir/sqlite3* fi } diff --git a/debian/prerm b/debian/prerm index 6ebebb4..75395ca 100755 --- a/debian/prerm +++ b/debian/prerm @@ -16,16 +16,14 @@ set -e # for details, see http://www.debian.org/doc/debian-policy/ or # the debian-policy package -APP=sipauthserve - -remove() -{ - killall $APP &>/dev/null -} +# remove() +# { +# killall runloop.sipauthserve.sh &>/dev/null +# } case "$1" in remove|upgrade|deconfigure) - remove +# remove ;; failed-upgrade) diff --git a/debian/rules b/debian/rules index 3504451..1c30205 100755 --- a/debian/rules +++ b/debian/rules @@ -20,11 +20,13 @@ export DH_ALWAYS_EXCLUDE=.svn:.git export DH_OPTIONS configure: + ./autogen.sh config: configure-stamp configure-stamp: configure dh_testdir # Add here commands to configure the package. + ./configure $(confflags) touch configure-stamp #Architecture diff --git a/runloop.sipauthserve.sh b/runloop.sipauthserve.sh deleted file mode 100755 index b3ec49d..0000000 --- a/runloop.sipauthserve.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -# A script to restart and just keep sipauthserve running. -while true; do killall sipauthserve; sleep 2; ./sipauthserve; done diff --git a/servershare.cpp b/servershare.cpp index 85430cd..ea42b61 100755 --- a/servershare.cpp +++ b/servershare.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "servershare.h" @@ -51,18 +52,6 @@ ConfigurationKeyMap getConfigurationKeys() ConfigurationKeyMap map; ConfigurationKey *tmp; - tmp = new ConfigurationKey("SIP.Proxy.Registration","127.0.0.1:5064", - "", - ConfigurationKey::CUSTOMERWARN, - ConfigurationKey::IPANDPORT, - "", - false, - "The IP host and port of the proxy to be used for registration and authentication. " - "This should normally be the subscriber registry SIP interface, not Asterisk." - ); - map[tmp->getName()] = *tmp; - delete tmp; - tmp = new ConfigurationKey("SubscriberRegistry.A3A8","/OpenBTS/comp128", "", ConfigurationKey::CUSTOMERWARN, @@ -85,28 +74,6 @@ ConfigurationKeyMap getConfigurationKeys() map[tmp->getName()] = *tmp; delete tmp; - tmp = new ConfigurationKey("SubscriberRegistry.Manager.Title","Subscriber Registry", - "", - ConfigurationKey::CUSTOMER, - ConfigurationKey::STRING, - "^[[:print:]]+$", - false, - "Title text to be displayed on the subscriber registry manager." - ); - map[tmp->getName()] = *tmp; - delete tmp; - - tmp = new ConfigurationKey("SubscriberRegistry.Manager.VisibleColumns","name username type context host", - "", - ConfigurationKey::CUSTOMERTUNE, - ConfigurationKey::STRING, - "^(name){0,1} (username){0,1} (type){0,1} (context){0,1} (host){0,1}$", - false, - "A space separated list of columns to display in the subscriber registry manager." - ); - map[tmp->getName()] = *tmp; - delete tmp; - tmp = new ConfigurationKey("SubscriberRegistry.Port","5064", "", ConfigurationKey::CUSTOMERWARN, @@ -118,58 +85,9 @@ ConfigurationKeyMap getConfigurationKeys() map[tmp->getName()] = *tmp; delete tmp; - tmp = new ConfigurationKey("SubscriberRegistry.UpstreamServer","", - "", - ConfigurationKey::CUSTOMERWARN, - ConfigurationKey::STRING_OPT,// audited - "", - false, - "URL of the subscriber registry HTTP interface on the upstream server. " - "By default, this feature is disabled. " - "To enable, specify a server URL eg: http://localhost/cgi/subreg.cgi. " - "To disable again, execute \"unconfig SubscriberRegistry.UpstreamServer\"." - ); - map[tmp->getName()] = *tmp; - delete tmp; - return map; } -string imsiGet(string imsi, string key) -{ - string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi; - char *value; - if (!sqlite3_single_lookup(gSubscriberRegistry.db(), "sip_buddies", "username", name.c_str(), key.c_str(), value)) { - return ""; - } - if (!value) { return ""; } - string retValue = value; - free(value); - return retValue; -} - -void imsiSet(string imsi, string key, string value) -{ - string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi; - ostringstream os2; - os2 << "update sip_buddies set " << key << " = \"" << value << "\" where username = \"" << name << "\""; - if (!sqlite3_command(gSubscriberRegistry.db(), os2.str().c_str())) { - LOG(ERR) << "sqlite3_command problem"; - return; - } -} - -void imsiSet(string imsi, string key1, string value1, string key2, string value2) -{ - string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi; - ostringstream os2; - os2 << "update sip_buddies set " << key1 << " = \"" << value1 << "\"," << key2 << " = \"" << value2 << "\" where username = \"" << name << "\""; - if (!sqlite3_command(gSubscriberRegistry.db(), os2.str().c_str())) { - LOG(ERR) << "sqlite3_command problem"; - return; - } -} - string soGenerateIt() { ostringstream os; @@ -180,20 +98,18 @@ string soGenerateIt() return os.str(); } - - // generate a 128' random number string generateRand(string imsi) { - string ki = imsiGet(imsi, "ki"); + string ki = gSubscriberRegistry.imsiGet(imsi, "ki"); string ret; if (ki.length() != 0) { LOG(INFO) << "ki is known"; // generate and return rand (clear any cached rand or sres) - imsiSet(imsi, "rand", "", "sres", ""); + gSubscriberRegistry.imsiSet(imsi, "rand", "", "sres", ""); ret = soGenerateIt(); } else { - string wRand = imsiGet(imsi, "rand"); + string wRand = gSubscriberRegistry.imsiGet(imsi, "rand"); if (wRand.length() != 0) { LOG(INFO) << "ki is unknown, rand is cached"; // return cached rand @@ -202,7 +118,7 @@ string generateRand(string imsi) LOG(INFO) << "ki is unknown, rand is not cached"; // generate rand, cache rand, clear sres, and return rand wRand = soGenerateIt(); - imsiSet(imsi, "rand", wRand, "sres", ""); + gSubscriberRegistry.imsiSet(imsi, "rand", wRand, "sres", ""); ret = wRand; } } @@ -246,8 +162,8 @@ bool randEqual(string a, string b) if (a.empty() || b.empty()) return false; - gSubscriberRegistry.stringToUint(a, &rand1h, &rand1l); - gSubscriberRegistry.stringToUint(b, &rand2h, &rand2l); + Utils::stringToUint(a, &rand1h, &rand1l); + Utils::stringToUint(b, &rand2h, &rand2l); LOG(DEBUG) << "rand1h = " << rand1h << ", rand1l = " << rand1l; LOG(DEBUG) << "rand2h = " << rand2h << ", rand2l = " << rand2l; @@ -260,40 +176,31 @@ bool randEqual(string a, string b) // may cache sres and rand bool authenticate(string imsi, string randx, string sres, string *kc) { - string ki = imsiGet(imsi, "ki"); + string ki = gSubscriberRegistry.imsiGet(imsi, "ki"); bool ret; if (ki.length() == 0) { // Ki is unknown - string upstream_server = gConfig.getStr("SubscriberRegistry.UpstreamServer"); - if (upstream_server.length()) { - LOG(INFO) << "ki unknown, upstream server"; - // there's an upstream server for authentication. - // TODO - call the upstream server - ret = false; + string sres2 = gSubscriberRegistry.imsiGet(imsi, "sres"); + if (sres2.length() == 0) { + LOG(INFO) << "ki unknown, no upstream server, sres not cached"; + // first time - cache sres and rand so next time + // correct cell phone will calc same sres from same rand + gSubscriberRegistry.imsiSet(imsi, "sres", sres, "rand", randx); + ret = true; } else { - // there's no upstream server for authentication. fake it. - string sres2 = imsiGet(imsi, "sres"); - if (sres2.length() == 0) { - LOG(INFO) << "ki unknown, no upstream server, sres not cached"; - // first time - cache sres and rand so next time - // correct cell phone will calc same sres from same rand - imsiSet(imsi, "sres", sres, "rand", randx); - ret = true; - } else { - LOG(INFO) << "ki unknown, no upstream server, sres cached"; - // check against cached values of rand and sres - string rand2 = imsiGet(imsi, "rand"); - // TODO - on success, compute and return kc - LOG(DEBUG) << "comparing " << sres << " to " << sres2 << " and " << randx << " to " << rand2; - ret = sresEqual(sres, sres2) && randEqual(randx, rand2); - } + LOG(INFO) << "ki unknown, no upstream server, sres cached"; + // check against cached values of rand and sres + string rand2 = gSubscriberRegistry.imsiGet(imsi, "rand"); + // TODO - on success, compute and return kc + LOG(DEBUG) << "comparing " << sres << " to " << sres2 << " and " << randx << " to " << rand2; + ret = sresEqual(sres, sres2) && randEqual(randx, rand2); } } else { LOG(INFO) << "ki known"; // Ki is known, so do normal authentication ostringstream os; // per user value from subscriber registry - string a3a8 = imsiGet(imsi, "a3_a8"); + string a3a8 = gSubscriberRegistry.imsiGet(imsi, "a3_a8"); if (a3a8.length() == 0) { // config value is default a3a8 = gConfig.getStr("SubscriberRegistry.A3A8"); @@ -328,62 +235,6 @@ bool authenticate(string imsi, string randx, string sres, string *kc) return ret; } -void decodeQuery(map &args) -{ - string query; - // this works for GET or POST. - // get the request method - char *g = getenv("REQUEST_METHOD"); - string method = g ? g : ""; - LOG(INFO) << "REQUEST_METHOD = " << g; - // if POST, then read from stdin the number of bytes specified in CONTENT_LENGTH, and that's the query - if (method == "POST") { - int lth = atoi(getenv("CONTENT_LENGTH")); - LOG(INFO) << "CONTENT_LENGTH = " << lth; - char *buf = new char[lth+1]; - cin.get(buf, lth+1); - int nread = cin.gcount(); - if (nread != lth) { - LOG(ERR) << "content length changed to " << nread; - lth = nread; - } - query = string(buf, lth); - LOG(INFO) << "QUERY = " << query; - delete[] buf; - // if GET, then the query is in the environment variable QUERY_STRING - } else if (method == "GET") { - char *q = getenv("QUERY_STRING"); - query = q ? q : ""; - LOG(INFO) << "QUERY_STRING = " << q; - } - if (query.length() != 0) { - // fields of http request are separated with "&" - vector fields; - split('&', query, &fields); - vector::iterator it; - for (it = fields.begin(); it != fields.end(); it++) { - string field = *it; - size_t p = field.find('='); - string key = field.substr(0, p); - string value = field.substr(p+1); - p = 0; - while (1) { - size_t q = value.find('%', p); - if (q == string::npos) break; - string hex = value.substr(q+1, 2); - char s[2]; - strcpy(s, "x"); - int i; - sscanf(hex.c_str(), "%x", &i); - s[0] = i; - string hexx = s; - value.replace(q, 3, hexx); - } - args[key] = value; - } - } -} - string join(string separator, vector &strings) { string result(""); diff --git a/servershare.h b/servershare.h index 821ccc9..8bc30cc 100755 --- a/servershare.h +++ b/servershare.h @@ -34,31 +34,6 @@ using namespace std; */ ConfigurationKeyMap getConfigurationKeys(); -/** - Get a subscriber's property. - @param imsi imsi of the subscriber - @param key name of the property -*/ -string imsiGet(string imsi, string key); - -/** - Set a subscriber's property. - @param imsi imsi of the subscriber - @param key name of the property - @param value value of the property -*/ -void imsiSet(string imsi, string key, string value); - -/** - Set a subscriber's property. - @param imsi imsi of the subscriber - @param key1 name of the property - @param value1 value of the property - @param key2 name of the property - @param value2 value of the property -*/ -void imsiSet(string imsi, string key1, string value1, string key2, string value2); - /** Generate a 128-bit random number. @param imsi imsi of subscriber the random number is for @@ -73,12 +48,6 @@ string generateRand(string imsi); */ bool authenticate(string imsi, string rand, string sres, string *kc); -/** - Decode the html query. - @param args mapping of query key->value pairs. -*/ -void decodeQuery(map &args); - /** Join the strings in strings, separated by separator @param separator the separator diff --git a/sqlite3 b/sqlite3 index 3d0dbe8..effc8fe 160000 --- a/sqlite3 +++ b/sqlite3 @@ -1 +1 @@ -Subproject commit 3d0dbe8e7a819585cac5064beabe9b22f8d47235 +Subproject commit effc8fe4744285c07e3710ab97231537a27b7997 diff --git a/srmanager.cpp b/srmanager.cpp deleted file mode 100755 index e7e28ec..0000000 --- a/srmanager.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/* -* Copyright 2011 Kestrel Signal Processing, Inc. -* Copyright 2011 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 . - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "Configuration.h" -#include "Logger.h" -#include -#include "servershare.h" -#include "SubscriberRegistry.h" -#include - -using namespace std; - -ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS.db", "srmanager", getConfigurationKeys()); -Log dummy("srmanager",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7); -map gArgs; -string gDatabase; -string gVisibleSipColumns; -string gUrl; -string gTitle; -string gVisibleExtColumns = "exten dial"; - -// just using this for the database access -SubscriberRegistry gSubscriberRegistry; - - -#define NO_BUTTON 0 -#define UPDATE_BUTTON 1 -#define ADD_BUTTON 2 -#define DELETE_BUTTON 4 - -// may need some way to add/update a NULL field -void tableRow(vector &names, vector &values, int buttons, string id) -{ - cout << "
\n"; - for (size_t i = 0; i < names.size(); i++) { - string name = names[i]; - string value = values.size() == 0 ? "" : values[i]; - cout << "\n"; - } - cout << "\n"; - if (buttons & UPDATE_BUTTON) { - cout << "\n"; - } - if (buttons & ADD_BUTTON) { - cout << "\n"; - } - if (buttons & DELETE_BUTTON) { - cout << "\n"; - } - cout << "
\n"; -} - -// make the header a fake form to get the same widths -void initTable(vector &cols) -{ - tableRow(cols, cols, NO_BUTTON, "0"); -} - -void table(const char *tableName, vector &cols, bool addButtonP, const char *note) -{ - cout << "

" << gDatabase << "." << tableName << " " << note << "

\n"; - initTable(cols); - ostringstream os; - os << "select id," << join(",", cols) << " from " << tableName; - sqlite3_stmt *stmt; - if (sqlite3_prepare_statement(gSubscriberRegistry.db(), &stmt,os.str().c_str())) { - LOG(ERR) << "sqlite3_prepare_statement problem - statement: " << os.str(); - LOG(ERR) << " " << sqlite3_errmsg(gSubscriberRegistry.db()); - return; - } - int src = sqlite3_run_query(gSubscriberRegistry.db(), stmt); - while (src == SQLITE_ROW) { - vector values; - const char *id = (const char*)sqlite3_column_text(stmt, 0); - for (int i = 1; i <= (int)cols.size(); i++) { - const char *value = (const char*)sqlite3_column_text(stmt, i); - values.push_back(value ? value : "(null)"); - } - tableRow(cols, values, UPDATE_BUTTON | DELETE_BUTTON, id); - src = sqlite3_run_query(gSubscriberRegistry.db(), stmt); - } - sqlite3_finalize(stmt); - if (addButtonP) { - vector dummy; - tableRow(cols, dummy, ADD_BUTTON, "0"); - } -} - -void getFields(vector *fields, vector *isSet) -{ - vector vsc; - split(' ', gVisibleSipColumns, &vsc); - sqlite3_stmt *stmt; - const char *cmd = "pragma table_info(sip_buddies)"; - if (sqlite3_prepare_statement(gSubscriberRegistry.db(), &stmt, cmd)) { - LOG(ERR) << "sqlite3_prepare_statement problem - statement: " << cmd; - LOG(ERR) << " " << sqlite3_errmsg(gSubscriberRegistry.db()); - return; - } - int src = sqlite3_run_query(gSubscriberRegistry.db(), stmt); - while (src == SQLITE_ROW) { - string field = (char*)sqlite3_column_text(stmt, 1); - fields->push_back(field); - isSet->push_back(find(vsc.begin(), vsc.end(), field) != vsc.end()); - src = sqlite3_run_query(gSubscriberRegistry.db(), stmt); - } - sqlite3_finalize(stmt); -} - -void mainTables() -{ - cout << "
\n"; - cout << "Phone Number = "; - cout << "\n"; - cout << "IMSI = "; - cout << "\n"; - cout << "\n"; - cout << "
\n"; - cout << "


\n"; - - vector vsc; - split(' ', gVisibleSipColumns, &vsc); - table("sip_buddies", vsc, false, "(scroll down to change which fields of sip_buddies are visible)"); - cout << "
"; - vector vec; - split(' ', gVisibleExtColumns, &vec); - table("dialdata_table", vec, true, ""); - - cout << "


\n"; - cout << "
\n"; - - cout << "


\n"; - cout << "

Selected fields are included in sip_buddies table (submit button at bottom)

\n"; - cout << "
\n"; - vector fields; - vector isSet; - getFields(&fields, &isSet); - for (int i = 0; i < (int)fields.size(); i++) { - string field = fields[i]; - string checked = isSet[i] ? "checked" : ""; - cout << " " << field << "
\n"; - } - cout << "
\n"; - cout << "\n"; -} - -string nullCheck(string s) -{ - if (s == "(null)") { - return "NULL"; - } else { - return "\"" + s + "\""; - } -} - -void doCmd(string cmd) -{ - string table; - vector cols; - if (gArgs.find("dial") == gArgs.end()) { - table = "sip_buddies"; - split(' ', gVisibleSipColumns, &cols); - } else { - table = "dialdata_table"; - split(' ', gVisibleExtColumns, &cols); - } - string id = gArgs["id"]; - ostringstream os; - if (cmd == "add") { - string names = join(",", cols); - vector values0; - vector::iterator it; - for (it = cols.begin(); it != cols.end(); it++) { - values0.push_back(nullCheck(gArgs[*it])); - } - string values = join(",", values0); - os << "insert into " << table << " (" << names << ") values (" << values << ")"; - } else if (cmd == "delete") { - os << "delete from " << table << " where id = " << id; - } else if (cmd == "update") { - vector sets0; - vector::iterator it; - for (it = cols.begin(); it != cols.end(); it++) { - sets0.push_back(*it + "=" + nullCheck(gArgs[*it])); - } - string sets = join(",", sets0); - os << "update " << table << " set " << sets << " where id = " << id; - } else { - LOG(ERR) << "internal error"; - } - LOG(INFO) << os.str(); - if (!sqlite3_command(gSubscriberRegistry.db(), os.str().c_str())) { - LOG(ERR) << "sqlite3_command problem - statement: " << os.str(); - return; - } - mainTables(); -} - -void initHtml() -{ - cout << "Content-Type: text/html\n\n"; - cout << "\n"; - cout << "\n"; - cout << "" << gTitle << "\n"; - cout << "\n"; - cout << "\n"; - cout << "

" << gTitle << "

\n"; - time_t rawtime; - time ( &rawtime ); - struct tm * timeinfo; - timeinfo = localtime ( &rawtime ); - cout << "

" << asctime(timeinfo) << "

\n"; -} - -void endHtml() -{ - cout << "\n"; - cout << "\n"; -} - -void doVisibles() -{ - gVisibleSipColumns = ""; - map::iterator it; - bool first = true; - for (it = gArgs.begin(); it != gArgs.end(); it++) { - if (it->first == "what") continue; - if (first) { - first = false; - } else { - gVisibleSipColumns += " "; - } - gVisibleSipColumns += it->first; - } - if (!gConfig.set("SubscriberRegistry.Manager.VisibleColumns", gVisibleSipColumns)) { - LOG(ERR) << "unable to update SubscriberRegistry.Manager.VisibleColumns"; - } -} - -int main(int argc, char **argv) -{ - gSubscriberRegistry.init(); - // start the html return - initHtml(); - // read the config file - gVisibleSipColumns = gConfig.getStr("SubscriberRegistry.Manager.VisibleColumns"); - gUrl = "/cgi/srmanager.cgi"; - gTitle = gConfig.getStr("SubscriberRegistry.Manager.Title"); - // connect to the database - gDatabase = gConfig.getStr("SubscriberRegistry.db"); - // decode the http query - decodeQuery(gArgs); - // execute command - string what = gArgs["what"]; - if (!what.length() || what == "Main") { - mainTables(); - } else if (what == "Add") { - doCmd("add"); - } else if (what == "Update") { - doCmd("update"); - } else if (what == "Delete") { - doCmd("delete"); - } else if (what == "Provision") { - gSubscriberRegistry.addUser(gArgs["imsi"].c_str(), gArgs["phonenumber"].c_str()); - mainTables(); - } else if (what == "Submit") { - doVisibles(); - mainTables(); - } else { - cout << "unrecognized what parameter
\n"; - map::iterator it; - for (it = gArgs.begin(); it != gArgs.end(); it++) { - cout << it->first << " -> " << it->second << "
\n"; - } - } - // finish the html return - endHtml(); -} diff --git a/subscriberRegistry.example.sql b/subscriberRegistry.example.sql deleted file mode 100644 index 8a9f6b5..0000000 --- a/subscriberRegistry.example.sql +++ /dev/null @@ -1,11 +0,0 @@ -PRAGMA foreign_keys=OFF; -BEGIN TRANSACTION; -CREATE TABLE IF NOT EXISTS CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT ''); -INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.A3A8','./comp128',0,0,'Path to the program that implements the A3/A8 algorithm.'); -INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.Manager.Title','Subscriber Registry',0,0,'Title text to be displayed on the subscriber registry manager.'); -INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.Port','5064',0,0,'Port used by the SIP Authentication Server. NOTE: In some older releases (pre-2.8.1) this is called SIP.myPort.'); -INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.UpstreamServer','',0,0,'URL of the subscriber registry HTTP interface on the upstream server. By default, this feature is disabled. To enable, specify a server URL eg: http://localhost/cgi/subreg.cgi. To disable again, execute "unconfig SubscriberRegistry.UpstreamServer".'); -INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.db','/var/lib/asterisk/sqlite3dir/sqlite3.db',0,0,'The location of the sqlite3 database holding the subscriber registry.'); -COMMIT; - - diff --git a/subscriberserver.cpp b/subscriberserver.cpp deleted file mode 100755 index d7fd7db..0000000 --- a/subscriberserver.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* -* Copyright 2011 Kestrel Signal Processing, Inc. -* Copyright 2011 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 . - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "Configuration.h" -#include "Logger.h" -#include -#include "servershare.h" -#include "SubscriberRegistry.h" - - -using namespace std; - -ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS.db", "subscriberserver", getConfigurationKeys()); -Log dummy("subscriberserver",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7); - -// just using this for the database access -SubscriberRegistry gSubscriberRegistry; - -// map of http query parameters and values -map gArgs; -// lines of http response -vector gResponse; - - - -// retrieve a query field from args -string getArg(string label) -{ - if (gArgs.find(label) == gArgs.end()) { - LOG(ERR) << "error: " << label << " missing"; - return ""; - } - return gArgs[label]; -} - -// run an sql statement through sqlite3 to get a response -void generateSqlResponse() -{ - string stmts = getArg("stmts"); - vector vstmts; - split(';', stmts, &vstmts); - vector::iterator it; - for (it = vstmts.begin(); it != vstmts.end(); it++) { - sqlite3_stmt *stmt; - if (sqlite3_prepare_statement(gSubscriberRegistry.db(), &stmt, it->c_str())) { - LOG(ERR) << "sqlite3_prepare_statement problem - statement: " << it->c_str(); - return; - } - int src = sqlite3_run_query(gSubscriberRegistry.db(), stmt); - while (src == SQLITE_ROW) { - string resp = "res="; - int cols = sqlite3_column_count(stmt); - for (int i = 0; i < cols; i++) { - resp.append((const char*)sqlite3_column_text(stmt, i)); - } - gResponse.push_back(resp); - src = sqlite3_run_query(gSubscriberRegistry.db(), stmt); - } - } -} - -void sresCheck(bool b) -{ - if (b) { - // SRESs match. return success (or Kc (TODO)) - gResponse.push_back("status=SUCCESS"); - } else { - // SRESs don't match. return failure. - gResponse.push_back("status=FAILURE"); - } -} - -// authenticate -void generateAuthResponse() -{ - string imsi = getArg("imsi"); - string randx = getArg("rand"); - string sres = getArg("sres"); - string kc; - bool st = authenticate(imsi, randx, sres, &kc); - sresCheck(st); -} - -// generate a 128' random number -void generateRandResponse() -{ - string imsi = getArg("imsi"); - string randx = generateRand(imsi); - gResponse.push_back("rand=" + randx); - gResponse.push_back("imsi=" + imsi); -} - -// generate our http response, putting each line of it into vector response -void generateResponse() -{ - if (gArgs.find("req") == gArgs.end()) { - LOG(ERR) << "req not specified"; - return; - } - // check for request types - string req = gArgs["req"]; - if (req == "sql") { - generateSqlResponse(); - return; - } - if (req == "rand") { - generateRandResponse(); - return; - } - if (req == "auth") { - generateAuthResponse(); - return; - } - // if none of the above, then it's an error - LOG(ERR) << "unrecognized request"; -} - -// write the query to the log file -void logQuery() -{ - // list query key->value pairs - map::iterator it; - LOG(INFO) << "query"; - for (it = gArgs.begin(); it != gArgs.end(); it++) { - LOG(INFO) << " " << it->first << " -> " << it->second; - } -} - -// write the http response from the global array @response to the log file -void logResponse() -{ - LOG(INFO) << "response"; - vector::iterator it; - for (it = gResponse.begin(); it != gResponse.end(); it++) { - LOG(INFO) << " " << *it; - } -} - -// print the http response to stdout -void respond() -{ - vector::iterator it; - for (it = gResponse.begin(); it != gResponse.end(); it++) { - cout << *it << endl; - } -} - -int main() -{ - cout << "Content-Type: text\n\n"; - srand ( time(NULL) + (int)getpid() ); - // decode the http query - decodeQuery(gArgs); - // write the http query into the log file - logQuery(); - // put the http response into the global array @response - generateResponse(); - // write the http response to the log file - logResponse(); - // print out the http response to stdout - respond(); -} diff --git a/svn.externals b/svn.externals deleted file mode 100644 index 5f2f946..0000000 --- a/svn.externals +++ /dev/null @@ -1,3 +0,0 @@ -CommonLibs http://wush.net/svn/range/software/public/CommonLibs/trunk -sqlite3 http://wush.net/svn/range/software/public/sqlite3/trunk - diff --git a/test.SubscriberRegistry/test.cpp b/test.SubscriberRegistry/test.cpp index 47f5493..d7c6240 100644 --- a/test.SubscriberRegistry/test.cpp +++ b/test.SubscriberRegistry/test.cpp @@ -4,6 +4,7 @@ #include #include "../SubscriberRegistry.h" #include "Configuration.h" +#include "Utils.h" using namespace std; @@ -14,15 +15,15 @@ SubscriberRegistry sr; void foo(uint32_t n, string s) { - LOG(INFO) << sr.uintToString(n) << " " << s; + LOG(INFO) << Utils::uintToString(n) << " " << s; } void foo(string s) { uint64_t h; uint64_t l; - sr.stringToUint(s, &h, &l); - LOG(INFO) << sr.uintToString(h, l) << " " << s; + Utils::stringToUint(s, &h, &l); + LOG(INFO) << Utils::uintToString(h, l) << " " << s; } int main(int argc, char **argv) @@ -39,8 +40,8 @@ int main(int argc, char **argv) sr.getIMSI("clid"); // test mapping of unknow user (so it won't be found locally) sr.getCLIDLocal("imsi_unknown"); - sr.getRandForAuthentication(false, "imsi_r1"); - sr.authenticate(false, "imsi_a1","rand_a1","sres_a1"); + //sr.getRandForAuthentication(false, "imsi_r1"); + //sr.authenticate(false, "imsi_a1","rand_a1","sres_a1"); // but test the conversions diff --git a/test.SubscriberRegistry/test.db.init1 b/test.SubscriberRegistry/test.db.init1 index 2be0dc8..4fb4459 100644 --- a/test.SubscriberRegistry/test.db.init1 +++ b/test.SubscriberRegistry/test.db.init1 @@ -2,7 +2,5 @@ BEGIN TRANSACTION; CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT ''); INSERT INTO "CONFIG" VALUES('Log.Level','DEBUG',0,0,''); INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,''); -INSERT INTO "CONFIG" VALUES('SubscriberRegistry.HTTP.Server','',0,0,''); INSERT INTO "CONFIG" VALUES('SIP.Proxy.Registration','testing',0,0,''); -INSERT INTO "CONFIG" VALUES('SubscriberRegistry.UpstreamServer','',0,0,''); COMMIT; diff --git a/test.SubscriberRegistry/test.db.init2 b/test.SubscriberRegistry/test.db.init2 index cb18694..4fb4459 100644 --- a/test.SubscriberRegistry/test.db.init2 +++ b/test.SubscriberRegistry/test.db.init2 @@ -2,7 +2,5 @@ BEGIN TRANSACTION; CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT ''); INSERT INTO "CONFIG" VALUES('Log.Level','DEBUG',0,0,''); INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,''); -INSERT INTO "CONFIG" VALUES('SubscriberRegistry.HTTP.Server','testing',0,0,''); INSERT INTO "CONFIG" VALUES('SIP.Proxy.Registration','testing',0,0,''); -INSERT INTO "CONFIG" VALUES('SubscriberRegistry.UpstreamServer','',0,0,''); COMMIT; diff --git a/test.sipauthserve/sipauthserve.db.init b/test.sipauthserve/sipauthserve.db.init index beb9136..b663aae 100644 --- a/test.sipauthserve/sipauthserve.db.init +++ b/test.sipauthserve/sipauthserve.db.init @@ -2,7 +2,6 @@ BEGIN TRANSACTION; CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT ''); INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,'The location of the sqlite3 database holding the subscriber registry.'); INSERT INTO "CONFIG" VALUES('SubscriberRegistry.A3A8','../comp128',0,0,''); -INSERT INTO "CONFIG" VALUES('SubscriberRegistry.UpstreamServer','',0,0,''); INSERT INTO "CONFIG" VALUES('Log.Level','INFO',0,0,''); INSERT INTO "CONFIG" VALUES('Log.Level.smcommands.cpp','INFO',0,0,''); INSERT INTO "CONFIG" VALUES('savefile','savedqueue.txt',0,0,''); diff --git a/test.srmanager/output.exp b/test.srmanager/output.exp deleted file mode 100644 index 90b47b7..0000000 --- a/test.srmanager/output.exp +++ /dev/null @@ -1,1027 +0,0 @@ -Thu Feb 17 13:28:47 PST 2011 -Content-Type: text/html - - - - - - -

-

-DATE- -

-

test.db.sip_buddies

-
- - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - -
-

test.db.dialdata_table

-
- - - -
-
- - - - - -
-
- - - - - -
-
- - - - -
-

-
- - -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET -servershare.cpp:-0-:decodeQuery: QUERY_STRING = -Content-Type: text/html - - - - - - -

-

-DATE- -

-

test.db.sip_buddies

-
- - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - -
-

test.db.dialdata_table

-
- - - -
-
- - - - - -
-
- - - - - -
-
- - - - -
-

-
- - -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET -servershare.cpp:-0-:decodeQuery: QUERY_STRING = what=Main -Content-Type: text/html - - - - - - -

-

-DATE- -

-

test.db.sip_buddies

-
- - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - -
-

test.db.dialdata_table

-
- - - -
-
- - - - - -
-
- - - - - -
-
- - - - -
-

-
- - -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = POST -servershare.cpp:-0-:decodeQuery: CONTENT_LENGTH = 0 -servershare.cpp:-0-:decodeQuery: QUERY = -Content-Type: text/html - - - - - - -

-

-DATE- -

-

test.db.sip_buddies

-
- - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - -
-

test.db.dialdata_table

-
- - - -
-
- - - - - -
-
- - - - - -
-
- - - - -
-

-
- - -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = POST -servershare.cpp:-0-:decodeQuery: CONTENT_LENGTH = 9 -servershare.cpp:-0-:decodeQuery: QUERY = what=Main -Content-Type: text/html - - - - - - -

-

-DATE- -

-

test.db.sip_buddies

-
- - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - -
-

test.db.dialdata_table

-
- - - -
-
- - - - - -
-
- - - - - -
-
- - - - -
-

-
- - -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = POST -servershare.cpp:-0-:decodeQuery: CONTENT_LENGTH = 55 -servershare.cpp:-0-:decodeQuery: QUERY = name=a&username=b&type=c&context=d&host=e&id=0&what=Add -1000|1000|friend|phones|dynamic -1001|1001|friend|phones|dynamic -imsi2||friend|| -imsi_r1||friend|| -imsi_r2||friend|| -imsi_a1||friend|| -imsi_a2||friend|| -imsi_a3||friend|| -a|b|c|d|e -1000|1000 -1001|1001 -Content-Type: text/html - - - - - - -

-

-DATE- -

-

test.db.sip_buddies

-
- - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - -
-

test.db.dialdata_table

-
- - - -
-
- - - - - -
-
- - - - - -
-
- - - - -
-

-
- - -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = POST -servershare.cpp:-0-:decodeQuery: CONTENT_LENGTH = 58 -servershare.cpp:-0-:decodeQuery: QUERY = name=a&username=b&type=c&context=d&host=e&id=9&what=Delete -1000|1000|friend|phones|dynamic -1001|1001|friend|phones|dynamic -imsi2||friend|| -imsi_r1||friend|| -imsi_r2||friend|| -imsi_a1||friend|| -imsi_a2||friend|| -imsi_a3||friend|| -1000|1000 -1001|1001 -Content-Type: text/html - - - - - - -

-

-DATE- -

-

test.db.sip_buddies

-
- - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - - -
-
- - - - - - - -
-

test.db.dialdata_table

-
- - - -
-
- - - - - -
-
- - - - - -
-
- - - - -
-

-
- - -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = POST -servershare.cpp:-0-:decodeQuery: CONTENT_LENGTH = 35 -servershare.cpp:-0-:decodeQuery: QUERY = exten=qrs&dial=tuv&id=1&what=Update -1000|1000|friend|phones|dynamic -1001|1001|friend|phones|dynamic -imsi2||friend|| -imsi_r1||friend|| -imsi_r2||friend|| -imsi_a1||friend|| -imsi_a2||friend|| -imsi_a3||friend|| -qrs|tuv -1001|1001 diff --git a/test.srmanager/query.sql b/test.srmanager/query.sql deleted file mode 100644 index b91265c..0000000 --- a/test.srmanager/query.sql +++ /dev/null @@ -1,2 +0,0 @@ -select name, username, type, context, host from sip_buddies; -select exten, dial from dialdata_table; diff --git a/test.srmanager/runtest b/test.srmanager/runtest deleted file mode 100755 index dec35a3..0000000 --- a/test.srmanager/runtest +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/bash - -# start with a known state in DBs -rm -f /etc/OpenBTS/OpenBTS.db test.db -# initialize the config db -sqlite3 /etc/OpenBTS/OpenBTS.db < srmanager.db.init -chmod 666 /etc/OpenBTS/OpenBTS.db -# initialize the SR db -sqlite3 test.db < test.db.init -# initialize the output file -date > output.got - -# Each test below enters a mark in the syslog so we can extract only -# the log entries for that test. -# Then it sets the environment variables (and stdin for POST) to duplicate -# http state, then it runs the test. -# Then it extracts the test's log entries. -# On some it then dumps the SR database. - -# empty http get -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=GET; -export REQUEST_METHOD -QUERY_STRING= -export QUERY_STRING -../srmanager.cgi >> output.got -../syslogextractor >> output.got - -# http get for main page -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=GET; -export REQUEST_METHOD -QUERY_STRING=what=Main -export QUERY_STRING -../srmanager.cgi >> output.got -../syslogextractor >> output.got - -# empty http post -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=POST; -export REQUEST_METHOD -CONTENT_LENGTH=0 -export CONTENT_LENGTH -echo '' | ../srmanager.cgi >> output.got -../syslogextractor >> output.got - -# http post for main page -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=POST; -export REQUEST_METHOD -CONTENT_LENGTH=9 -export CONTENT_LENGTH -echo 'what=Main' | ../srmanager.cgi >> output.got -../syslogextractor >> output.got - -# http post for add -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=POST; -export REQUEST_METHOD -CONTENT_LENGTH=55 -export CONTENT_LENGTH -echo 'name=a&username=b&type=c&context=d&host=e&id=0&what=Add' | ../srmanager.cgi >> output.got -../syslogextractor >> output.got -sqlite3 test.db < ./query.sql >> output.got - -# http post for delete -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=POST; -export REQUEST_METHOD -CONTENT_LENGTH=58 -export CONTENT_LENGTH -echo 'name=a&username=b&type=c&context=d&host=e&id=9&what=Delete' | ../srmanager.cgi >> output.got -../syslogextractor >> output.got -sqlite3 test.db < ./query.sql >> output.got - -# http post for update -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=POST; -export REQUEST_METHOD -CONTENT_LENGTH=35 -export CONTENT_LENGTH -echo 'exten=qrs&dial=tuv&id=1&what=Update' | ../srmanager.cgi >> output.got -../syslogextractor >> output.got -sqlite3 test.db < ./query.sql >> output.got - -# normalize the output file for diffing -mv output.got ootput.got -../hexmapper ootput.got > output.got -diff output.exp output.got -exit 0 diff --git a/test.srmanager/srmanager.db.init b/test.srmanager/srmanager.db.init deleted file mode 100644 index 6746ba4..0000000 --- a/test.srmanager/srmanager.db.init +++ /dev/null @@ -1,9 +0,0 @@ -BEGIN TRANSACTION; -CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT ''); -INSERT INTO "CONFIG" VALUES('Log.Level','DEBUG',0,0,''); -INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','test.db',0,0,''); -INSERT INTO "CONFIG" VALUES('SubscriberRegistry.Manager.VisibleColumns','name username type context host',0,0,''); -INSERT INTO "CONFIG" VALUES('SubscriberRegistry.Manager.Url','http://localhost/~doug/foo.cgi',0,0,''); -INSERT INTO "CONFIG" VALUES('SubscriberRegistry.Manager.Title','Some Title',0,0,''); -COMMIT; - diff --git a/test.srmanager/test.db.init b/test.srmanager/test.db.init deleted file mode 100644 index 6ea2a47..0000000 --- a/test.srmanager/test.db.init +++ /dev/null @@ -1,102 +0,0 @@ -BEGIN TRANSACTION; -CREATE TABLE dialdata_table ( - id INTEGER, - exten VARCHAR(40) NOT NULL DEFAULT '', - dial VARCHAR(128) NOT NULL DEFAULT '', - PRIMARY KEY (id) -); -INSERT INTO "dialdata_table" VALUES(1,'1000','1000'); -INSERT INTO "dialdata_table" VALUES(2,'1001','1001'); -CREATE TABLE 'sip_buddies' -( -id integer, -name VARCHAR(80) unique not null, -context VARCHAR(80), -callingpres VARCHAR(30) DEFAULT 'allowed_not_screened', -deny VARCHAR(95), -permit VARCHAR(95), -secret VARCHAR(80), -md5secret VARCHAR(80), -remotesecret VARCHAR(250), -transport VARCHAR(10), -host VARCHAR(31) DEFAULT '' not null, -nat VARCHAR(5) DEFAULT 'no' not null, -type VARCHAR(10) DEFAULT 'friend' not null, -accountcode VARCHAR(20), -amaflags VARCHAR(13), -callgroup VARCHAR(10), -callerid VARCHAR(80), -defaultip VARCHAR(40) DEFAULT '0.0.0.0', -dtmfmode VARCHAR(7) DEFAULT 'rfc2833', -fromuser VARCHAR(80), -fromdomain VARCHAR(80), -insecure VARCHAR(4), -language CHAR(2), -mailbox VARCHAR(50), -pickupgroup VARCHAR(10), -qualify CHAR(3), -regexten VARCHAR(80), -rtptimeout CHAR(3), -rtpholdtimeout CHAR(3), -setvar VARCHAR(100), -disallow VARCHAR(100) DEFAULT 'all', -allow VARCHAR(100) DEFAULT 'ulaw' not null, -fullcontact VARCHAR(80), -ipaddr VARCHAR(40), -port int(5) DEFAULT 0, -username VARCHAR(80), -defaultuser VARCHAR(80), -subscribecontext VARCHAR(80), -directmedia VARCHAR(3), -trustrpid VARCHAR(3), -sendrpid VARCHAR(3), -progressinband VARCHAR(5), -promiscredir VARCHAR(3), -useclientcode VARCHAR(3), -callcounter VARCHAR(3), -busylevel int(11), -allowoverlap VARCHAR(3) DEFAULT 'yes', -allowsubscribe VARCHAR(3) DEFAULT 'yes', -allowtransfer VARCHAR(3) DEFAULT 'yes', -ignoresdpversion VARCHAR(3) DEFAULT 'no', -template VARCHAR(100), -videosupport VARCHAR(6) DEFAULT 'no', -maxcallbitrate int(11), -rfc2833compensate VARCHAR(3) DEFAULT 'yes', -'session-timers' VARCHAR(10) DEFAULT 'accept', -'session-expires' int(6) DEFAULT 1800, -'session-minse' int(6) DEFAULT 90, -'session-refresher' VARCHAR(3) DEFAULT 'uas', -t38pt_usertpsource VARCHAR(3), -outboundproxy VARCHAR(250), -callbackextension VARCHAR(250), -registertrying VARCHAR(3) DEFAULT 'yes', -timert1 int(6) DEFAULT 500, -timerb int(9), -qualifyfreq int(6) DEFAULT 120, -contactpermit VARCHAR(250), -contactdeny VARCHAR(250), -lastms int(11) DEFAULT 0 not null, -regserver VARCHAR(100), -regseconds int(11) DEFAULT 0 not null, -useragent VARCHAR(100), -cancallforward CHAR(3) DEFAULT 'yes' not null, -canreinvite CHAR(3) DEFAULT 'yes' not null, -mask VARCHAR(95), -musiconhold VARCHAR(100), -restrictcid CHAR(3), -calllimit int(5), -ki VARCHAR(32) DEFAULT '' not null, -rand VARCHAR(32) DEFAULT '' not null, -sres VARCHAR(32) DEFAULT '' not null, -primary key(id) -); -INSERT INTO "sip_buddies" VALUES(1,'1000','phones','allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'dynamic','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,'1000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','',''); -INSERT INTO "sip_buddies" VALUES(2,'1001','phones','allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'dynamic','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,'1001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','',''); -INSERT INTO "sip_buddies" VALUES(3,'imsi2',NULL,'allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,'imsi2ipaddr',0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','',''); -INSERT INTO "sip_buddies" VALUES(4,'imsi_r1',NULL,'allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','',''); -INSERT INTO "sip_buddies" VALUES(5,'imsi_r2',NULL,'allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','12345678901234567890123456789012',''); -INSERT INTO "sip_buddies" VALUES(6,'imsi_a1',NULL,'allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'7f4d7fbff290e20e60466bc7b5b08e4b','',''); -INSERT INTO "sip_buddies" VALUES(7,'imsi_a2',NULL,'allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','123','456'); -INSERT INTO "sip_buddies" VALUES(8,'imsi_a3',NULL,'allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','123456789012345678901234567890a3','1234567890123456789012a3'); -COMMIT; diff --git a/test.subscriberserver/output.exp b/test.subscriberserver/output.exp deleted file mode 100644 index e112a19..0000000 --- a/test.subscriberserver/output.exp +++ /dev/null @@ -1,133 +0,0 @@ -Fri Mar 18 16:47:36 PDT 2011 -Content-Type: text - -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET -servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=sql&stmts=insert into sip_buddies (name) values ("newname") -subscriberserver.cpp:-0-:logQuery: query -subscriberserver.cpp:-0-:logQuery: req -> sql -subscriberserver.cpp:-0-:logQuery: stmts -> insert into sip_buddies (name) values ("newname") -subscriberserver.cpp:-0-:logResponse: response -IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000||| -IMSI12345678901232|||| -IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000| -newname|||| -Content-Type: text - -res=IMSI12345678901232 -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET -servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=sql&stmts=select name from sip_buddies where id=2 -subscriberserver.cpp:-0-:logQuery: query -subscriberserver.cpp:-0-:logQuery: req -> sql -subscriberserver.cpp:-0-:logQuery: stmts -> select name from sip_buddies where id=2 -subscriberserver.cpp:-0-:logResponse: response -subscriberserver.cpp:-0-:logResponse: res=IMSI12345678901232 -IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000||| -IMSI12345678901232|||| -IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000| -newname|||| -Content-Type: text - -rand=hexhexhexhexhexhexhexhexhexh1000 -imsi=IMSI12345678901231 -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET -servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=rand&imsi=IMSI12345678901231 -subscriberserver.cpp:-0-:logQuery: query -subscriberserver.cpp:-0-:logQuery: imsi -> IMSI12345678901231 -subscriberserver.cpp:-0-:logQuery: req -> rand -servershare.cpp:-0-:generateRand: ki is unknown, rand is cached -subscriberserver.cpp:-0-:logResponse: response -subscriberserver.cpp:-0-:logResponse: rand=hexhexhexhexhexhexhexhexhexh1000 -subscriberserver.cpp:-0-:logResponse: imsi=IMSI12345678901231 -IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000||| -IMSI12345678901232|||| -IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000| -newname|||| -Content-Type: text - -rand=hexhexhexhexhexhexhexhexhexh1000 -imsi=IMSI12345678901231 -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET -servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=rand&imsi=IMSI12345678901231 -subscriberserver.cpp:-0-:logQuery: query -subscriberserver.cpp:-0-:logQuery: imsi -> IMSI12345678901231 -subscriberserver.cpp:-0-:logQuery: req -> rand -servershare.cpp:-0-:generateRand: ki is unknown, rand is cached -subscriberserver.cpp:-0-:logResponse: response -subscriberserver.cpp:-0-:logResponse: rand=hexhexhexhexhexhexhexhexhexh1000 -subscriberserver.cpp:-0-:logResponse: imsi=IMSI12345678901231 -IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000||| -IMSI12345678901232|||| -IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000| -newname|||| -Content-Type: text - -rand=hexhexhexhexhexhexhexhexhexh1001 -imsi=IMSI12345678901232 -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET -servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=rand&imsi=IMSI12345678901232 -subscriberserver.cpp:-0-:logQuery: query -subscriberserver.cpp:-0-:logQuery: imsi -> IMSI12345678901232 -subscriberserver.cpp:-0-:logQuery: req -> rand -servershare.cpp:-0-:generateRand: ki is unknown, rand is not cached -subscriberserver.cpp:-0-:logResponse: response -subscriberserver.cpp:-0-:logResponse: rand=hexhexhexhexhexhexhexhexhexh1001 -subscriberserver.cpp:-0-:logResponse: imsi=IMSI12345678901232 -IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000||| -IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1001||| -IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000| -newname|||| -Content-Type: text - -rand=hexhexhexhexhexhexhexhexhexh1001 -imsi=IMSI12345678901232 -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET -servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=rand&imsi=IMSI12345678901232 -subscriberserver.cpp:-0-:logQuery: query -subscriberserver.cpp:-0-:logQuery: imsi -> IMSI12345678901232 -subscriberserver.cpp:-0-:logQuery: req -> rand -servershare.cpp:-0-:generateRand: ki is unknown, rand is cached -subscriberserver.cpp:-0-:logResponse: response -subscriberserver.cpp:-0-:logResponse: rand=hexhexhexhexhexhexhexhexhexh1001 -subscriberserver.cpp:-0-:logResponse: imsi=IMSI12345678901232 -IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000||| -IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1001||| -IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000| -newname|||| -Content-Type: text - -status=SUCCESS -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET -servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=auth&imsi=IMSI12345678901233&rand=hexhexhexhexhexhexhexhexhexh1002&sres=hexh1003 -subscriberserver.cpp:-0-:logQuery: query -subscriberserver.cpp:-0-:logQuery: imsi -> IMSI12345678901233 -subscriberserver.cpp:-0-:logQuery: rand -> hexhexhexhexhexhexhexhexhexh1002 -subscriberserver.cpp:-0-:logQuery: req -> auth -subscriberserver.cpp:-0-:logQuery: sres -> hexh1003 -servershare.cpp:-0-:authenticate: ki known -servershare.cpp:-0-:authenticate: result = hexh1003 -servershare.cpp:-0-:authenticate: returning = 1 -subscriberserver.cpp:-0-:logResponse: response -subscriberserver.cpp:-0-:logResponse: status=SUCCESS -IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000||| -IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1001||| -IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000| -newname|||| -Content-Type: text - -status=FAILURE -servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET -servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=auth&imsi=IMSI12345678901233&rand=hexhexhexhexhexhexhexhexhexh1002&sres=hexh1004 -subscriberserver.cpp:-0-:logQuery: query -subscriberserver.cpp:-0-:logQuery: imsi -> IMSI12345678901233 -subscriberserver.cpp:-0-:logQuery: rand -> hexhexhexhexhexhexhexhexhexh1002 -subscriberserver.cpp:-0-:logQuery: req -> auth -subscriberserver.cpp:-0-:logQuery: sres -> hexh1004 -servershare.cpp:-0-:authenticate: ki known -servershare.cpp:-0-:authenticate: result = hexh1003 -servershare.cpp:-0-:authenticate: returning = 0 -subscriberserver.cpp:-0-:logResponse: response -subscriberserver.cpp:-0-:logResponse: status=FAILURE -IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000||| -IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1001||| -IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000| -newname|||| diff --git a/test.subscriberserver/query.sql b/test.subscriberserver/query.sql deleted file mode 100644 index 4693755..0000000 --- a/test.subscriberserver/query.sql +++ /dev/null @@ -1 +0,0 @@ -select name, rand, sres, ki, kc from sip_buddies; diff --git a/test.subscriberserver/runtest b/test.subscriberserver/runtest deleted file mode 100755 index afd10c9..0000000 --- a/test.subscriberserver/runtest +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash - -rm -f /etc/OpenBTS/OpenBTS.db sr.db -sqlite3 /etc/OpenBTS/OpenBTS.db < subscriberserver.db.init -sqlite3 sr.db < sr.db.init -date > output.got - -# test an sql update -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=GET -export REQUEST_METHOD -QUERY_STRING="req=sql&stmts=insert into sip_buddies (name) values (\"newname\")" -export QUERY_STRING -../subscriberserver.cgi >> output.got -../syslogextractor >> output.got -sqlite3 sr.db < query.sql >> output.got - -# test an sql query -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=GET -export REQUEST_METHOD -QUERY_STRING="req=sql&stmts=select name from sip_buddies where id=2" -export QUERY_STRING -../subscriberserver.cgi >> output.got -../syslogextractor >> output.got -sqlite3 sr.db < query.sql >> output.got - -# Some rand and auth tests just to see that things are connected ok. -# No need for exhaustive testing because the code is shared, and -# tested better elsewhere. - -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=GET -export REQUEST_METHOD -QUERY_STRING="req=rand&imsi=IMSI12345678901231" -export QUERY_STRING -../subscriberserver.cgi >> output.got -../syslogextractor >> output.got -sqlite3 sr.db < query.sql >> output.got - -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=GET -export REQUEST_METHOD -QUERY_STRING="req=rand&imsi=IMSI12345678901231" -export QUERY_STRING -../subscriberserver.cgi >> output.got -../syslogextractor >> output.got -sqlite3 sr.db < query.sql >> output.got - -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=GET -export REQUEST_METHOD -QUERY_STRING="req=rand&imsi=IMSI12345678901232" -export QUERY_STRING -../subscriberserver.cgi >> output.got -../syslogextractor >> output.got -sqlite3 sr.db < query.sql >> output.got - -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=GET -export REQUEST_METHOD -QUERY_STRING="req=rand&imsi=IMSI12345678901232" -export QUERY_STRING -../subscriberserver.cgi >> output.got -../syslogextractor >> output.got -sqlite3 sr.db < query.sql >> output.got - -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=GET -export REQUEST_METHOD -QUERY_STRING="req=auth&imsi=IMSI12345678901233&rand=d76fe9a5839089a2ebeb269b46bf46ff&sres=726259AF" -export QUERY_STRING -../subscriberserver.cgi >> output.got -../syslogextractor >> output.got -sqlite3 sr.db < query.sql >> output.got - -logger -plocal7.Debug dwb syslog mark -REQUEST_METHOD=GET -export REQUEST_METHOD -QUERY_STRING="req=auth&imsi=IMSI12345678901233&rand=d76fe9a5839089a2ebeb269b46bf46ff&sres=726259A0" -export QUERY_STRING -../subscriberserver.cgi >> output.got -../syslogextractor >> output.got -sqlite3 sr.db < query.sql >> output.got - -mv output.got ootput.got -../hexmapper ootput.got > output.got -diff output.exp output.got -exit 0 diff --git a/test.subscriberserver/sr.db.init b/test.subscriberserver/sr.db.init deleted file mode 100644 index 9eaa6f7..0000000 --- a/test.subscriberserver/sr.db.init +++ /dev/null @@ -1,101 +0,0 @@ -BEGIN TRANSACTION; -CREATE TABLE dialdata_table ( - id INTEGER, - exten VARCHAR(40) NOT NULL DEFAULT '', - dial VARCHAR(128) NOT NULL DEFAULT '', - PRIMARY KEY (id) -); -INSERT INTO "dialdata_table" VALUES(1,'1000','1000'); -INSERT INTO "dialdata_table" VALUES(2,'1001','1001'); -INSERT INTO "dialdata_table" VALUES(3,'clid1','imsi1'); -CREATE TABLE 'sip_buddies' -( -id integer, -name VARCHAR(80) unique not null, -context VARCHAR(80), -callingpres VARCHAR(30) DEFAULT 'allowed_not_screened', -deny VARCHAR(95), -permit VARCHAR(95), -secret VARCHAR(80), -md5secret VARCHAR(80), -remotesecret VARCHAR(250), -transport VARCHAR(10), -host VARCHAR(31) DEFAULT '' not null, -nat VARCHAR(5) DEFAULT 'no' not null, -type VARCHAR(10) DEFAULT 'friend' not null, -accountcode VARCHAR(20), -amaflags VARCHAR(13), -callgroup VARCHAR(10), -callerid VARCHAR(80), -defaultip VARCHAR(40) DEFAULT '0.0.0.0', -dtmfmode VARCHAR(7) DEFAULT 'rfc2833', -fromuser VARCHAR(80), -fromdomain VARCHAR(80), -insecure VARCHAR(4), -language CHAR(2), -mailbox VARCHAR(50), -pickupgroup VARCHAR(10), -qualify CHAR(3), -regexten VARCHAR(80), -rtptimeout CHAR(3), -rtpholdtimeout CHAR(3), -setvar VARCHAR(100), -disallow VARCHAR(100) DEFAULT 'all', -allow VARCHAR(100) DEFAULT 'ulaw' not null, -fullcontact VARCHAR(80), -ipaddr VARCHAR(40), -port int(5) DEFAULT 0, -username VARCHAR(80), -defaultuser VARCHAR(80), -subscribecontext VARCHAR(80), -directmedia VARCHAR(3), -trustrpid VARCHAR(3), -sendrpid VARCHAR(3), -progressinband VARCHAR(5), -promiscredir VARCHAR(3), -useclientcode VARCHAR(3), -callcounter VARCHAR(3), -busylevel int(11), -allowoverlap VARCHAR(3) DEFAULT 'yes', -allowsubscribe VARCHAR(3) DEFAULT 'yes', -allowtransfer VARCHAR(3) DEFAULT 'yes', -ignoresdpversion VARCHAR(3) DEFAULT 'no', -template VARCHAR(100), -videosupport VARCHAR(6) DEFAULT 'no', -maxcallbitrate int(11), -rfc2833compensate VARCHAR(3) DEFAULT 'yes', -'session-timers' VARCHAR(10) DEFAULT 'accept', -'session-expires' int(6) DEFAULT 1800, -'session-minse' int(6) DEFAULT 90, -'session-refresher' VARCHAR(3) DEFAULT 'uas', -t38pt_usertpsource VARCHAR(3), -outboundproxy VARCHAR(250), -callbackextension VARCHAR(250), -registertrying VARCHAR(3) DEFAULT 'yes', -timert1 int(6) DEFAULT 500, -timerb int(9), -qualifyfreq int(6) DEFAULT 120, -contactpermit VARCHAR(250), -contactdeny VARCHAR(250), -lastms int(11) DEFAULT 0 not null, -regserver VARCHAR(100), -regseconds int(11) DEFAULT 0 not null, -useragent VARCHAR(100), -cancallforward CHAR(3) DEFAULT 'yes' not null, -canreinvite CHAR(3) DEFAULT 'yes' not null, -mask VARCHAR(95), -musiconhold VARCHAR(100), -restrictcid CHAR(3), -calllimit int(5), -rand varchar(33) default '', -sres varchar(33) default '', -ki varchar(33) default '', -kc varchar(33) default '', -primary key(id) -); - -insert into sip_buddies (name,rand,sres,ki,kc) values ('IMSI12345678901231','48091124c1155bd95c6f1860dc66ce92','','',''); -insert into sip_buddies (name,rand,sres,ki,kc) values ('IMSI12345678901232','','','',''); -insert into sip_buddies (name,rand,sres,ki,kc) values ('IMSI12345678901233','','','48091124c1155bd95c6f1860dc66ce92',''); - -COMMIT; diff --git a/test.subscriberserver/subscriberserver.db.init b/test.subscriberserver/subscriberserver.db.init deleted file mode 100644 index 8426c93..0000000 --- a/test.subscriberserver/subscriberserver.db.init +++ /dev/null @@ -1,7 +0,0 @@ -BEGIN TRANSACTION; -CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT ''); -INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,''); -INSERT INTO "CONFIG" VALUES('SubscriberRegistry.A3A8','../comp128',0,0,''); -INSERT INTO "CONFIG" VALUES('SubscriberRegistry.UpstreamServer','',0,0,''); -INSERT INTO "CONFIG" VALUES('Log.Level','DEBUG',0,0,''); -COMMIT;