moved mm1 mm7 code into base
This commit is contained in:
parent
6a34ce5ca2
commit
1e14a17e39
|
@ -1,3 +1,5 @@
|
||||||
|
2011-03-24 P. A. Bagyenda <bagyenda@dsmagic.com>
|
||||||
|
* Rolled MM1 MM7 module into main MMSBox code
|
||||||
2011-01-28 P. A. Bagyenda <bagyenda@dsmagic.com>
|
2011-01-28 P. A. Bagyenda <bagyenda@dsmagic.com>
|
||||||
* Fix bug in http mmsc module
|
* Fix bug in http mmsc module
|
||||||
2011-01-12 P. A. Bagyenda <bagyenda@dsmagic.com>
|
2011-01-12 P. A. Bagyenda <bagyenda@dsmagic.com>
|
||||||
|
|
185
mbuni/INSTALL
185
mbuni/INSTALL
|
@ -2,12 +2,10 @@ Installation Instructions
|
||||||
*************************
|
*************************
|
||||||
|
|
||||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||||
2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
2006 Free Software Foundation, Inc.
|
||||||
|
|
||||||
Copying and distribution of this file, with or without modification,
|
This file is free documentation; the Free Software Foundation gives
|
||||||
are permitted in any medium without royalty provided the copyright
|
unlimited permission to copy, distribute and modify it.
|
||||||
notice and this notice are preserved. This file is offered as-is,
|
|
||||||
without warranty of any kind.
|
|
||||||
|
|
||||||
Basic Installation
|
Basic Installation
|
||||||
==================
|
==================
|
||||||
|
@ -15,11 +13,7 @@ Basic Installation
|
||||||
Briefly, the shell commands `./configure; make; make install' should
|
Briefly, the shell commands `./configure; make; make install' should
|
||||||
configure, build, and install this package. The following
|
configure, build, and install this package. The following
|
||||||
more-detailed instructions are generic; see the `README' file for
|
more-detailed instructions are generic; see the `README' file for
|
||||||
instructions specific to this package. Some packages provide this
|
instructions specific to this package.
|
||||||
`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
|
The `configure' shell script attempts to guess correct values for
|
||||||
various system-dependent variables used during compilation. It uses
|
various system-dependent variables used during compilation. It uses
|
||||||
|
@ -59,22 +53,12 @@ of `autoconf'.
|
||||||
2. Type `make' to compile the package.
|
2. Type `make' to compile the package.
|
||||||
|
|
||||||
3. Optionally, type `make check' to run any self-tests that come with
|
3. Optionally, type `make check' to run any self-tests that come with
|
||||||
the package, generally using the just-built uninstalled binaries.
|
the package.
|
||||||
|
|
||||||
4. Type `make install' to install the programs and any data files and
|
4. Type `make install' to install the programs and any data files and
|
||||||
documentation. When installing into a prefix owned by root, it is
|
documentation.
|
||||||
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
|
5. You can remove the program binaries and object files from the
|
||||||
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
|
source code directory by typing `make clean'. To also remove the
|
||||||
files that `configure' created (so you can compile the package for
|
files that `configure' created (so you can compile the package for
|
||||||
a different kind of computer), type `make distclean'. There is
|
a different kind of computer), type `make distclean'. There is
|
||||||
|
@ -83,22 +67,12 @@ of `autoconf'.
|
||||||
all sorts of other programs in order to regenerate files that came
|
all sorts of other programs in order to regenerate files that came
|
||||||
with the distribution.
|
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
|
Compilers and Options
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
Some systems require unusual options for compilation or linking that
|
Some systems require unusual options for compilation or linking that the
|
||||||
the `configure' script does not know about. Run `./configure --help'
|
`configure' script does not know about. Run `./configure --help' for
|
||||||
for details on some of the pertinent environment variables.
|
details on some of the pertinent environment variables.
|
||||||
|
|
||||||
You can give `configure' initial values for configuration parameters
|
You can give `configure' initial values for configuration parameters
|
||||||
by setting variables in the command line or in the environment. Here
|
by setting variables in the command line or in the environment. Here
|
||||||
|
@ -116,36 +90,20 @@ 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
|
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
|
directory where you want the object files and executables to go and run
|
||||||
the `configure' script. `configure' automatically checks for the
|
the `configure' script. `configure' automatically checks for the
|
||||||
source code in the directory that `configure' is in and in `..'. This
|
source code in the directory that `configure' is in and in `..'.
|
||||||
is known as a "VPATH" build.
|
|
||||||
|
|
||||||
With a non-GNU `make', it is safer to compile the package for one
|
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
|
architecture at a time in the source code directory. After you have
|
||||||
installed the package for one architecture, use `make distclean' before
|
installed the package for one architecture, use `make distclean' before
|
||||||
reconfiguring for another architecture.
|
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
|
Installation Names
|
||||||
==================
|
==================
|
||||||
|
|
||||||
By default, `make install' installs the package's commands under
|
By default, `make install' installs the package's commands under
|
||||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||||
can specify an installation prefix other than `/usr/local' by giving
|
can specify an installation prefix other than `/usr/local' by giving
|
||||||
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
`configure' the option `--prefix=PREFIX'.
|
||||||
absolute file name.
|
|
||||||
|
|
||||||
You can specify separate installation prefixes for
|
You can specify separate installation prefixes for
|
||||||
architecture-specific files and architecture-independent files. If you
|
architecture-specific files and architecture-independent files. If you
|
||||||
|
@ -156,46 +114,15 @@ Documentation and other data files still use the regular prefix.
|
||||||
In addition, if you use an unusual directory layout you can give
|
In addition, if you use an unusual directory layout you can give
|
||||||
options like `--bindir=DIR' to specify different values for particular
|
options like `--bindir=DIR' to specify different values for particular
|
||||||
kinds of files. Run `configure --help' for a list of the directories
|
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
|
you can set and what kinds of files go in them.
|
||||||
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
|
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
|
with an extra prefix or suffix on their names by giving `configure' the
|
||||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||||
|
|
||||||
|
Optional Features
|
||||||
|
=================
|
||||||
|
|
||||||
Some packages pay attention to `--enable-FEATURE' options to
|
Some packages pay attention to `--enable-FEATURE' options to
|
||||||
`configure', where FEATURE indicates an optional part of the package.
|
`configure', where FEATURE indicates an optional part of the package.
|
||||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||||
|
@ -208,53 +135,14 @@ find the X include and library files automatically, but if it doesn't,
|
||||||
you can use the `configure' options `--x-includes=DIR' and
|
you can use the `configure' options `--x-includes=DIR' and
|
||||||
`--x-libraries=DIR' to specify their locations.
|
`--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 `<wchar.h>' 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
|
Specifying the System Type
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
There may be some features `configure' cannot figure out
|
There may be some features `configure' cannot figure out automatically,
|
||||||
automatically, but needs to determine by the type of machine the package
|
but needs to determine by the type of machine the package will run on.
|
||||||
will run on. Usually, assuming the package is built to be run on the
|
Usually, assuming the package is built to be run on the _same_
|
||||||
_same_ architectures, `configure' can figure that out, but if it prints
|
architectures, `configure' can figure that out, but if it prints a
|
||||||
a message saying it cannot guess the machine type, give it the
|
message saying it cannot guess the machine type, give it the
|
||||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
`--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:
|
type, such as `sun4', or a canonical name which has the form:
|
||||||
|
|
||||||
|
@ -262,8 +150,7 @@ type, such as `sun4', or a canonical name which has the form:
|
||||||
|
|
||||||
where SYSTEM can have one of these forms:
|
where SYSTEM can have one of these forms:
|
||||||
|
|
||||||
OS
|
OS KERNEL-OS
|
||||||
KERNEL-OS
|
|
||||||
|
|
||||||
See the file `config.sub' for the possible values of each field. If
|
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
|
`config.sub' isn't included in this package, then this package doesn't
|
||||||
|
@ -281,9 +168,9 @@ eventually be run) with `--host=TYPE'.
|
||||||
Sharing Defaults
|
Sharing Defaults
|
||||||
================
|
================
|
||||||
|
|
||||||
If you want to set default values for `configure' scripts to share,
|
If you want to set default values for `configure' scripts to share, you
|
||||||
you can create a site shell script called `config.site' that gives
|
can create a site shell script called `config.site' that gives default
|
||||||
default values for variables like `CC', `cache_file', and `prefix'.
|
values for variables like `CC', `cache_file', and `prefix'.
|
||||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||||
`CONFIG_SITE' environment variable to the location of the site script.
|
`CONFIG_SITE' environment variable to the location of the site script.
|
||||||
|
@ -311,19 +198,11 @@ an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||||
`configure' Invocation
|
`configure' Invocation
|
||||||
======================
|
======================
|
||||||
|
|
||||||
`configure' recognizes the following options to control how it
|
`configure' recognizes the following options to control how it operates.
|
||||||
operates.
|
|
||||||
|
|
||||||
`--help'
|
`--help'
|
||||||
`-h'
|
`-h'
|
||||||
Print a summary of all of the options to `configure', and exit.
|
Print a summary 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'
|
`--version'
|
||||||
`-V'
|
`-V'
|
||||||
|
@ -350,16 +229,6 @@ operates.
|
||||||
Look for the package's source code in directory DIR. Usually
|
Look for the package's source code in directory DIR. Usually
|
||||||
`configure' can determine that directory automatically.
|
`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' also accepts some other, not widely useful, options. Run
|
||||||
`configure --help' for more details.
|
`configure --help' for more details.
|
||||||
|
|
||||||
|
|
|
@ -350,7 +350,10 @@ if test "$CURL_CONFIG" != "no"; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_CHECK_LIB([curl], [curl_global_init], [has_libcurl=true])
|
AC_CHECK_LIB([curl], [curl_global_init], [
|
||||||
|
CFLAGS="-DHAVE_LIBCURL=1 $CFLAGS";
|
||||||
|
has_libcurl=true
|
||||||
|
])
|
||||||
|
|
||||||
AM_CONDITIONAL([BUILD_MMSBOXMM1], [test x$has_libcurl = xtrue])
|
AM_CONDITIONAL([BUILD_MMSBOXMM1], [test x$has_libcurl = xtrue])
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,17 @@ incoming-port = 12345
|
||||||
type = soap
|
type = soap
|
||||||
|
|
||||||
# Sample conf for MMSBox using a modem (MM1)
|
# Sample conf for MMSBox using a modem (MM1)
|
||||||
#group = mmsc
|
group = mmsc
|
||||||
#id = modem
|
id = modem
|
||||||
#type = custom
|
type = mm1
|
||||||
#custom-settings = "smsc-on=lynx -dump 'http://localhost:13000/start-smsc?password=bar&smsc=nokia-modem';smsc-off=lynx -dump 'http://localhost:13000/stop-smsc?password=bar&smsc=nokia-modem';gprs-on=/usr/local/sbin/start-net-gprs;gprs-pid=cat /var/run/ppp-net.pid|head -1;port=13014;mmsc-url=http://net.mmsc/servlets/mms;proxy=10.11.12.13:8080;msisdn=100"
|
mm1-sms-on-command = lynx -dump 'http://localhost:13000/start-smsc?password=bar&smsc=nokia-modem'
|
||||||
#mmsc-library = /usr/local/lib/libmmsbox_mm1.so
|
mm1-sms-off-command = lynx -dump 'http://localhost:13000/stop-smsc?password=bar&smsc=nokia-modem'
|
||||||
|
mm1-msisdn = "100"
|
||||||
|
mm1-http-proxy = 10.11.12.13:8080
|
||||||
|
incoming-port = 13014
|
||||||
|
mmsc-url = http://net.mmsc/servlets/mms
|
||||||
|
mm1-gprs-on-command = /usr/local/sbin/start-net-gprs
|
||||||
|
mm1-gprs-pid-command = "cat /var/run/ppp-net.pid|head -1"
|
||||||
|
|
||||||
group = mms-service
|
group = mms-service
|
||||||
name = me
|
name = me
|
||||||
|
|
|
@ -285,7 +285,7 @@ provisioned, etc.
|
||||||
<li>Operating as a <b>VAS Gateway</b>, Mbuni provides:
|
<li>Operating as a <b>VAS Gateway</b>, Mbuni provides:
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li> Support for SOAP, EAIF and MM4 connectivity with an operator
|
<li> Support for SOAP, EAIF, MM1 and MM4 connectivity with an operator
|
||||||
MMSC (plus a special HTTP-based relay mechanism)
|
MMSC (plus a special HTTP-based relay mechanism)
|
||||||
<li> Multiple connections to different MMSC of different types can
|
<li> Multiple connections to different MMSC of different types can
|
||||||
be maintained
|
be maintained
|
||||||
|
@ -2488,15 +2488,23 @@ Supported configuration parameters are:
|
||||||
<td valign=top >
|
<td valign=top >
|
||||||
Mandatory:
|
Mandatory:
|
||||||
Protocol spoken by this MMSC, one of <tt>soap</tt> for 3GPP MM7
|
Protocol spoken by this MMSC, one of <tt>soap</tt> for 3GPP MM7
|
||||||
SOAP, <tt>eaif</tt> for Nokia EAIF protocol, <tt>mm4</t> for 3GPP
|
SOAP, <tt>eaif</tt> for Nokia EAIF protocol, <tt>mm4</tt> for 3GPP
|
||||||
MM4, <tt>http</tt> for
|
MM4, <tt>http</tt> for
|
||||||
special HTTP-based inter-mmsbox message relay (see below), or <tt>custom</tt> for
|
special HTTP-based inter-mmsbox message relay (see
|
||||||
|
below), <tt>mm1</tt> for GPRS/3G modem access to an operator MMSC, or <tt>custom</tt> for
|
||||||
a custom implementation handled by a loadable module (see
|
a custom implementation handled by a loadable module (see
|
||||||
<tt>mmsc-library</tt> below).<br> For <tt>type = http</tt> the VAS GW
|
<tt>mmsc-library</tt> below).<br> For <tt>type = http</tt> the VAS GW
|
||||||
will forward the message to the URL provided using HTTP POST, with
|
will forward the message to the URL provided using HTTP POST, with
|
||||||
CGI parameters: <tt>mms</tt> – the binary mms, <tt>from</tt>
|
CGI parameters: <tt>mms</tt> – the binary mms, <tt>from</tt>
|
||||||
– the sender address, <tt>to</tt> – the recipient
|
– the sender address, <tt>to</tt> – the recipient
|
||||||
address. This allows fast inter-mmsbox message exchange.
|
address. This allows fast inter-mmsbox message
|
||||||
|
exchange. <br>For <tt>type=mm1</tt> it is expected
|
||||||
|
that <tt>mmsbox</tt> will send/receive messages directly from the
|
||||||
|
operator using an attached modem. To receive MMS, Kannel (or similar
|
||||||
|
SMS Gateway) must pass all received SMS to Mbuni via the
|
||||||
|
MMSC <tt>port</tt>. To send MMS, Mbuni will use
|
||||||
|
the <tt>mm1-sms-off-command</tt> (see below) to temporarily shutdown
|
||||||
|
the SMS Gateway, and then use the modem to send MMS
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -2598,7 +2606,10 @@ Supported configuration parameters are:
|
||||||
</td>
|
</td>
|
||||||
<td valign=top >
|
<td valign=top >
|
||||||
Port at which Mbuni listens for incoming messages from MMSC. Not
|
Port at which Mbuni listens for incoming messages from MMSC. Not
|
||||||
used for MM4 incoming connections (<tt>mm4-port</tt> is used instead).
|
used for MM4 incoming connections (<tt>mm4-port</tt> is used
|
||||||
|
instead). For <tt>mm1</tt> MMSCs this is the port to which (MO) MMS
|
||||||
|
notification messages should be routed. In this case, the
|
||||||
|
notification SMS should be contained in a <tt>text</tt> CGI parameter.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -2888,6 +2899,132 @@ string
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td valign=top >
|
||||||
|
<tt>mm1-http-proxy</tt>
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
String
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
HTTP Proxy (in the form <i>host:port</i> to be used when sending MMS to the MMSC. (<tt>mm1</tt> MMSC only)
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td valign=top >
|
||||||
|
<tt>mm1-http-proxy</tt>
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
String
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
HTTP Proxy (in the form <i>host:port</i>) to be used when sending MMS to the MMSC. (<tt>mm1</tt> MMSC only.)
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td valign=top >
|
||||||
|
<tt>mm1-gprs-on-command</tt>
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
String
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
Command <tt>mmsbox</tt> will call to start a GPRS/3G operator
|
||||||
|
connection when sending MT MMS via the <tt>mm1</tt> type. This
|
||||||
|
command typically invokes <tt>pppd</tt> with suitable
|
||||||
|
parameters. <b>NOTE</b>: This command should return immediately
|
||||||
|
(i.e. it shouldn't block). (<tt>mm1</tt> MMSC only.)
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td valign=top >
|
||||||
|
<tt>mm1-gprs-off-command</tt>
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
String
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
Command <tt>mmsbox</tt> will call to stop the GPRS/3G operator
|
||||||
|
connection after sending MT MMS via the <tt>mm1</tt> type. This
|
||||||
|
command typically kills the <tt>pppd</tt> in charge of the
|
||||||
|
connection started with the command above. (<tt>mm1</tt> MMSC only.)
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td valign=top >
|
||||||
|
<tt>mm1-gprs-pid-command</tt>
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
String
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
Command <tt>mmsbox</tt> will call to determine the ID of
|
||||||
|
the process controlling the GPRS/3G operator
|
||||||
|
connection after it is started. If this option is provided, then
|
||||||
|
a <tt>kill(2)</tt> will be used to terminate the GPRS/3G
|
||||||
|
connection, rather than the <tt>mm1-gprs-off-command</tt>. (<tt>mm1</tt> MMSC only.)
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td valign=top >
|
||||||
|
<tt>mm1-sms-off-command</tt>
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
String
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
Command <tt>mmsbox</tt> will call to stop the SMS Gateway modem link, just
|
||||||
|
before starting the GPRS/3G operator
|
||||||
|
connection. Because MO MMS is received as (SMS) notifications, the
|
||||||
|
modem must be shared with the SMS Gateway (such as Kannel). When a
|
||||||
|
notification is received by <tt>mmsbox</tt>, we must shutdown the
|
||||||
|
SMS Gateway's connection to the modem (typically, if using Kannel,
|
||||||
|
this means a call to the admin interface), fetch the MMS (via a
|
||||||
|
GPRS/3G connection initiated using the same modem), and then turn
|
||||||
|
SMS reception back on (see below). (<tt>mm1</tt> MMSC only.)
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td valign=top >
|
||||||
|
<tt>mm1-sms-on-command</tt>
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
String
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
Command <tt>mmsbox</tt> will call to start the SMS Gateway modem
|
||||||
|
link, once <tt>mmsbox</tt> has completed fetching MO MMS or sending
|
||||||
|
MT MMS via a GPRS/3G operator
|
||||||
|
connection. Typically, if using Kannel,
|
||||||
|
this means a call to the Kannel admin interface to start the
|
||||||
|
specific modem SMSC link. (<tt>mm1</tt> MMSC only.)
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td valign=top >
|
||||||
|
<tt>mm1-ua-string</tt>
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
String
|
||||||
|
</td>
|
||||||
|
<td valign=top >
|
||||||
|
HTTP USer Agent String to send to MMSC in HTTP requests (e.g. "Mozilla/5.0 (SymbianOS/9.4;U;
|
||||||
|
Series60/5.0 Nokia5800d-1/52.50.2008.24;
|
||||||
|
Profile/MIDP-2.1Configuration/CLDC-1.1 )
|
||||||
|
AppleWebKit/413 (KHTML, like Gecko)
|
||||||
|
Safari/413" to fake a request as
|
||||||
|
a Nokia 5800). This is
|
||||||
|
useful if the MMSC transcodes MT MMS based on the receiver type. (<tt>mm1</tt> MMSC only.)
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ typedef struct {
|
||||||
long h_tid, d_tid; /* thread IDs. */
|
long h_tid, d_tid; /* thread IDs. */
|
||||||
|
|
||||||
int sender_alive;
|
int sender_alive;
|
||||||
|
|
||||||
} MM1Settings;
|
} MM1Settings;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -382,7 +383,8 @@ static void handle_mm1(MM1Settings *mm1)
|
||||||
pid = start_gprs(mm1->gprs_on, mm1->gprs_pid);
|
pid = start_gprs(mm1->gprs_on, mm1->gprs_pid);
|
||||||
|
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
mms_warning(0, "mmsbox-mm1", NULL,"failed to start GPRS connection. waiting...");
|
mms_warning(0, "mmsbox-mm1", NULL,
|
||||||
|
"Failed to start GPRS connection. waiting...");
|
||||||
gwthread_sleep(2);
|
gwthread_sleep(2);
|
||||||
goto kill_gprs;
|
goto kill_gprs;
|
||||||
} else
|
} else
|
||||||
|
@ -627,7 +629,8 @@ static int write_octstr_data(void *buffer, size_t size, size_t nmemb, void *user
|
||||||
Octstr *out = userp;
|
Octstr *out = userp;
|
||||||
|
|
||||||
octstr_append_data(out, buffer, size*nmemb);
|
octstr_append_data(out, buffer, size*nmemb);
|
||||||
mms_info(0, "mmsbox-mm1", NULL, "write_data called with nmemn=%ld, size=%ld", nmemb, size);
|
mms_info(0, "mmsbox-mm1", NULL, "write_data called with nmemn=%ld, size=%ld",
|
||||||
|
nmemb, size);
|
||||||
return size*nmemb;
|
return size*nmemb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,6 +661,11 @@ static Octstr *fetch_content(Octstr *url, Octstr *proxy, Octstr *body, int *hsta
|
||||||
h = curl_slist_append(h, "Accept: */*");
|
h = curl_slist_append(h, "Accept: */*");
|
||||||
if (body) { /* POST. */
|
if (body) { /* POST. */
|
||||||
h = curl_slist_append(h, "Content-Type: application/vnd.wap.mms-message");
|
h = curl_slist_append(h, "Content-Type: application/vnd.wap.mms-message");
|
||||||
|
h = curl_slist_append(h, "User-Agent: Mozilla/5.0 (SymbianOS/9.4;U;"
|
||||||
|
"Series60/5.0 Nokia5800d-1/52.50.2008.24;"
|
||||||
|
"Profile/MIDP-2.1Configuration/CLDC-1.1 ) "
|
||||||
|
"AppleWebKit/413 (KHTML, like Gecko) "
|
||||||
|
"Safari/413");
|
||||||
curl_easy_setopt(cl, CURLOPT_POSTFIELDS, octstr_get_cstr(body));
|
curl_easy_setopt(cl, CURLOPT_POSTFIELDS, octstr_get_cstr(body));
|
||||||
curl_easy_setopt(cl, CURLOPT_POSTFIELDSIZE, octstr_len(body));
|
curl_easy_setopt(cl, CURLOPT_POSTFIELDSIZE, octstr_len(body));
|
||||||
}
|
}
|
||||||
|
@ -668,10 +676,12 @@ static Octstr *fetch_content(Octstr *url, Octstr *proxy, Octstr *body, int *hsta
|
||||||
|
|
||||||
*hstatus = curl_easy_perform(cl); /* post away! */
|
*hstatus = curl_easy_perform(cl); /* post away! */
|
||||||
if (*hstatus != 0)
|
if (*hstatus != 0)
|
||||||
mms_error(0, "mmsbox-mm1", NULL, "failed to fetch/post content: %.256s",
|
mms_error(0, "mmsbox-mm1", NULL, "failed to fetch/post content to host %s [proxy: %s] [http_status=%d] : %.256s",
|
||||||
errbuf);
|
octstr_get_cstr(url), octstr_len(proxy) > 0 ? octstr_get_cstr(proxy) : "n/a",
|
||||||
|
*hstatus, errbuf);
|
||||||
|
|
||||||
curl_slist_free_all(h); /* free the header list */
|
curl_slist_free_all(h); /* free the header list */
|
||||||
|
curl_easy_setopt(cl, CURLOPT_NOSIGNAL, 0L);
|
||||||
curl_easy_cleanup(cl);
|
curl_easy_cleanup(cl);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
noinst_LIBRARIES = libmms.a
|
noinst_LIBRARIES = libmms.a
|
||||||
libmms_a_SOURCES = mms_eventlogger.c mms_mmbox.c mms_msg.c mms_queue.c mms_strings.c mms_uaprof.c mms_util.c mms_mm7soap.c mms_cfg.c
|
libmms_a_SOURCES = charmibenum.def mms_eventlogger.c mms_mmbox.c mms_msg.c mms_queue.c mms_strings.c mms_uaprof.c mms_util.c mms_mm7soap.c mms_cfg.c
|
||||||
|
|
||||||
EXTRA_DIST=mms_strings.def mms_eventlogger.h mms_mm7soap.h mms_mmbox.h mms_msg.h mms_queue.h mms_strings.h mms_uaprof.h mms_util.h mms_cfg.h mms_cfg.def mms_cfg-impl.h
|
EXTRA_DIST=mms_strings.def mms_eventlogger.h mms_mm7soap.h mms_mmbox.h mms_msg.h mms_queue.h mms_strings.h mms_uaprof.h mms_util.h mms_cfg.h mms_cfg.def mms_cfg-impl.h
|
||||||
|
|
|
@ -198,6 +198,14 @@ MULTI_GROUP(mmsc,
|
||||||
OCTSTR(max-recipients)
|
OCTSTR(max-recipients)
|
||||||
|
|
||||||
OCTSTR(strip-prefixes)
|
OCTSTR(strip-prefixes)
|
||||||
|
OCTSTR(mm1-http-proxy)
|
||||||
|
OCTSTR(mm1-gprs-on-command)
|
||||||
|
OCTSTR(mm1-gprs-off-command)
|
||||||
|
OCTSTR(mm1-gprs-pid-command)
|
||||||
|
OCTSTR(mm1-sms-on-command)
|
||||||
|
OCTSTR(mm1-sms-off-command)
|
||||||
|
OCTSTR(mm1-msisdn)
|
||||||
|
OCTSTR(mm1-ua-string)
|
||||||
)
|
)
|
||||||
|
|
||||||
MULTI_GROUP(mms-service,
|
MULTI_GROUP(mms-service,
|
||||||
|
|
|
@ -1784,7 +1784,7 @@ int mms_url_fetch_content(int method, Octstr *url, List *request_headers,
|
||||||
if (octstr_search(url, octstr_imm("data:"), 0) == 0) {
|
if (octstr_search(url, octstr_imm("data:"), 0) == 0) {
|
||||||
int i = octstr_search_char(url, ',',0);
|
int i = octstr_search_char(url, ',',0);
|
||||||
Octstr *ctype = (i >= 0) ? octstr_copy(url, 5, i-5) : octstr_create("text/plain; charset=us-ascii");
|
Octstr *ctype = (i >= 0) ? octstr_copy(url, 5, i-5) : octstr_create("text/plain; charset=us-ascii");
|
||||||
Octstr *data = (i >= 0) ? octstr_copy(url, i+1, octstr_len(url)) : octstr_duplicate(url);
|
Octstr *data = (i >= 0) ? octstr_copy(url, i+1, octstr_len(url)) : octstr_copy(url,5,octstr_len(url));
|
||||||
|
|
||||||
Octstr *n = NULL, *h = NULL;
|
Octstr *n = NULL, *h = NULL;
|
||||||
|
|
||||||
|
|
|
@ -1018,7 +1018,7 @@ done:
|
||||||
return http_status_class(hstatus) == HTTP_STATUS_SUCCESSFUL ? 0 : -1;
|
return http_status_class(hstatus) == HTTP_STATUS_SUCCESSFUL ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mm7mm1_receive(MmsBoxHTTPClientInfo *);
|
||||||
static void dispatch_mm7_recv(List *rl)
|
static void dispatch_mm7_recv(List *rl)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1026,9 +1026,10 @@ static void dispatch_mm7_recv(List *rl)
|
||||||
|
|
||||||
/* hmon->register_thread( "dispatch_mm7" ); */
|
/* hmon->register_thread( "dispatch_mm7" ); */
|
||||||
while ((h = gwlist_consume(rl)) != NULL) {
|
while ((h = gwlist_consume(rl)) != NULL) {
|
||||||
int ret = -1, has_auth = 0;
|
|
||||||
MmscGrp *m = h->m;
|
MmscGrp *m = h->m;
|
||||||
if (auth_check(m->incoming.user,
|
int ret = -1, has_auth = (m->type != MM1_MMSC); /* We dont authenticate mm1. right? */
|
||||||
|
|
||||||
|
if (!has_auth && auth_check(m->incoming.user,
|
||||||
m->incoming.pass,
|
m->incoming.pass,
|
||||||
h->headers, &has_auth) != 0) { /* Ask it to authenticate... */
|
h->headers, &has_auth) != 0) { /* Ask it to authenticate... */
|
||||||
List *hh = http_create_empty_headers();
|
List *hh = http_create_empty_headers();
|
||||||
|
@ -1047,6 +1048,8 @@ static void dispatch_mm7_recv(List *rl)
|
||||||
ret = mm7soap_receive(h);
|
ret = mm7soap_receive(h);
|
||||||
else if (h->m->type == EAIF_MMSC)
|
else if (h->m->type == EAIF_MMSC)
|
||||||
ret = mm7eaif_receive(h);
|
ret = mm7eaif_receive(h);
|
||||||
|
else if (h->m->type == MM1_MMSC)
|
||||||
|
ret = mm7mm1_receive(h);
|
||||||
else
|
else
|
||||||
ret = mm7http_receive(h);
|
ret = mm7http_receive(h);
|
||||||
|
|
||||||
|
@ -1503,7 +1506,10 @@ done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Octstr *mm7mm1_send(MmscGrp *mmc, Octstr *from, List *lto,
|
||||||
|
Octstr *transid,
|
||||||
|
Octstr *linkedid, char *vasid, Octstr *service_code,
|
||||||
|
MmsMsg *m, List *hdrs, Octstr **err, int *retry);
|
||||||
static int mms_sendtommsc(MmscGrp *mmc, MmsEnvelope *e,
|
static int mms_sendtommsc(MmscGrp *mmc, MmsEnvelope *e,
|
||||||
List *lto, /* Of Octstr * */
|
List *lto, /* Of Octstr * */
|
||||||
Octstr *orig_transid,
|
Octstr *orig_transid,
|
||||||
|
@ -1531,6 +1537,9 @@ static int mms_sendtommsc(MmscGrp *mmc, MmsEnvelope *e,
|
||||||
id = mm7eaif_send(mmc, from, lto, transid, vasid, e, m, &err, &retry);
|
id = mm7eaif_send(mmc, from, lto, transid, vasid, e, m, &err, &retry);
|
||||||
else if (mmc->type == HTTP_MMSC)
|
else if (mmc->type == HTTP_MMSC)
|
||||||
id = mm7http_send(mmc,e, from, lto, m, &err, &retry);
|
id = mm7http_send(mmc,e, from, lto, m, &err, &retry);
|
||||||
|
else if (mmc->type == MM1_MMSC)
|
||||||
|
id = mm7mm1_send(mmc, from, lto, transid, linkedid, vasid,
|
||||||
|
service_code, m, hdrs, &err, &retry);
|
||||||
else if (mmc->type == CUSTOM_MMSC && mmc->started) {
|
else if (mmc->type == CUSTOM_MMSC && mmc->started) {
|
||||||
Octstr *to = gwlist_get(lto, 0); /* XXX Send one at a time*/
|
Octstr *to = gwlist_get(lto, 0); /* XXX Send one at a time*/
|
||||||
id = mmc->fns->send_msg(mmc->data,
|
id = mmc->fns->send_msg(mmc->data,
|
||||||
|
@ -2562,3 +2571,567 @@ void mm4_receive_func(int *sock)
|
||||||
|
|
||||||
gwlist_destroy(slist, NULL);
|
gwlist_destroy(slist, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* MM1 functions and data */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
enum {MM1_GET, MM1_PUSH} type;
|
||||||
|
int waiter_exists; /* set to true if after handling, should signal and NOT destroy struct.*/
|
||||||
|
pthread_cond_t cond;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
union {
|
||||||
|
MmsMsg *m; /* for push. */
|
||||||
|
Octstr *url; /* for get */
|
||||||
|
} u;
|
||||||
|
void *result; /* set to the result for a PUSH */
|
||||||
|
Octstr *err;
|
||||||
|
} MM1Request;
|
||||||
|
|
||||||
|
static long start_gprs(Octstr *cmd, Octstr *id, Octstr *pid_cmd);
|
||||||
|
static Octstr *fetch_content_with_curl(MmscGrp *mmc, Octstr *url, Octstr *body, int *hstatus);
|
||||||
|
static void stop_gprs(Octstr *cmd);
|
||||||
|
|
||||||
|
static Octstr *mm7mm1_send(MmscGrp *mmc, Octstr *from, List *lto,
|
||||||
|
Octstr *transid,
|
||||||
|
Octstr *linkedid, char *vasid, Octstr *service_code,
|
||||||
|
MmsMsg *m, List *hdrs, Octstr **err, int *retry)
|
||||||
|
{
|
||||||
|
MM1Request *r = gw_malloc(sizeof *r);
|
||||||
|
Octstr *id;
|
||||||
|
struct MM1Info_t *s = &mmc->mm1;
|
||||||
|
|
||||||
|
gw_assert(m);
|
||||||
|
|
||||||
|
if (!s->sender_alive) {
|
||||||
|
*err = octstr_imm("internal error, mm1 notify not started!");
|
||||||
|
*retry = 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the from address first of all, replace the to address as well */
|
||||||
|
mms_replace_header_value(m, "From", "#insert");
|
||||||
|
mms_replace_header_values(m, "To", lto); /* Put in recipient list */
|
||||||
|
mms_remove_headers(m, "Message-ID");
|
||||||
|
|
||||||
|
r->u.m = m;
|
||||||
|
pthread_cond_init(&r->cond, NULL);
|
||||||
|
pthread_mutex_init(&r->mutex, NULL);
|
||||||
|
r->waiter_exists = 1;
|
||||||
|
r->type = MM1_PUSH;
|
||||||
|
r->result = NULL;
|
||||||
|
r->err = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&r->mutex); /* at pickup, must grab mutex before signalling. otherwise race condition.*/
|
||||||
|
|
||||||
|
gwlist_produce(s->requests, r);
|
||||||
|
|
||||||
|
pthread_cond_wait(&r->cond, &r->mutex);
|
||||||
|
|
||||||
|
*err = r->err;
|
||||||
|
|
||||||
|
id = r->result;
|
||||||
|
mms_info(0, "MM1", mmc->id, "mm1_send: sent message, type=%s, result=%s",
|
||||||
|
mms_message_type_to_cstr(mms_messagetype(m)),
|
||||||
|
r->err ? octstr_get_cstr(r->err) : "(none)");
|
||||||
|
/* destroy the structure. */
|
||||||
|
if(r->err && (octstr_compare(r->err, octstr_imm("Error-service-denied")) == 0 ||
|
||||||
|
octstr_compare(r->err, octstr_imm("Error-permanent-failure")) == 0))
|
||||||
|
*retry = 0;
|
||||||
|
else
|
||||||
|
*retry = 1;
|
||||||
|
|
||||||
|
pthread_cond_destroy(&r->cond);
|
||||||
|
pthread_mutex_destroy(&r->mutex);
|
||||||
|
gw_free(r);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_mm1_mt_requests(MmscGrp *mmsc)
|
||||||
|
{
|
||||||
|
/* stop smsc, start GPRS, transact, stop GPRS, start SMSC. And so on. */
|
||||||
|
MM1Request *r;
|
||||||
|
|
||||||
|
mms_info(0, "MM7", mmsc->id, "handle_mm1 [%s] started", octstr_get_cstr(mmsc->id));
|
||||||
|
mmsc->mm1.sender_alive++;
|
||||||
|
while ((r = gwlist_consume(mmsc->mm1.requests)) != NULL) {
|
||||||
|
long n, pid = -1;
|
||||||
|
if (mmsc->mm1.smsc_off) {
|
||||||
|
n = system(octstr_get_cstr(mmsc->mm1.smsc_off));
|
||||||
|
gwthread_sleep(5); /* allow it to die. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mmsc->mm1.gprs_on)
|
||||||
|
pid = start_gprs(mmsc->mm1.gprs_on, mmsc->id, mmsc->mm1.gprs_pid);
|
||||||
|
|
||||||
|
if (pid < 0) {
|
||||||
|
mms_warning(0, "MM7", mmsc->id,
|
||||||
|
"Failed to start GPRS connection. waiting...");
|
||||||
|
gwthread_sleep(2);
|
||||||
|
goto kill_gprs;
|
||||||
|
} else
|
||||||
|
mms_info(0, "MM7", mmsc->id, "handle_mm1 [start_gprs] returned PID: %ld", pid);
|
||||||
|
|
||||||
|
do {
|
||||||
|
Octstr *body;
|
||||||
|
Octstr *url;
|
||||||
|
int hstatus = 0;
|
||||||
|
Octstr *ms;
|
||||||
|
MmsMsg *m;
|
||||||
|
int msize;
|
||||||
|
pid_t wp;
|
||||||
|
int st;
|
||||||
|
|
||||||
|
if (r->waiter_exists)
|
||||||
|
pthread_mutex_lock(&r->mutex); /* grab lock to avoid race condition */
|
||||||
|
|
||||||
|
body = (r->type == MM1_PUSH) ? mms_tobinary(r->u.m) : NULL;
|
||||||
|
url = (r->type == MM1_PUSH) ? mmsc->mmsc_url : r->u.url;
|
||||||
|
ms = fetch_content_with_curl(mmsc, url, body, &hstatus);
|
||||||
|
msize = ms ? octstr_len(ms) : 0;
|
||||||
|
m = (hstatus == 0 && ms) ? mms_frombinary(ms, mmsc->mm1.msisdn) : NULL;
|
||||||
|
|
||||||
|
if (r->type == MM1_GET) {
|
||||||
|
if (m == NULL)
|
||||||
|
mms_error(0, "MM7", mmsc->id, "failed to fetch mms from URL: %s!",
|
||||||
|
octstr_get_cstr(url));
|
||||||
|
else {
|
||||||
|
List *mh = mms_message_headers(m), *to = gwlist_create();
|
||||||
|
Octstr *subject = NULL, *otransid = NULL, *msgid = NULL, *value;
|
||||||
|
Octstr *hfrom = mh ? http_header_value(mh, octstr_imm("From")) : octstr_imm("anon@anon");
|
||||||
|
Octstr *qf = NULL, *qdir = NULL, *mmc_id = NULL;
|
||||||
|
time_t expiryt = -1, deliveryt = -1;
|
||||||
|
int dlr;
|
||||||
|
|
||||||
|
/* we assume it is a true message (send_req|retrieve_conf) */
|
||||||
|
mms_collect_envdata_from_msgheaders(mh, &to, &subject,
|
||||||
|
&otransid, &expiryt, &deliveryt,
|
||||||
|
DEFAULT_EXPIRE, -1,
|
||||||
|
octstr_get_cstr(unified_prefix),
|
||||||
|
strip_prefixes);
|
||||||
|
|
||||||
|
msgid = http_header_value(mh, octstr_imm("Message-ID"));
|
||||||
|
value = http_header_value(mh, octstr_imm("X-Mms-Delivery-Report"));
|
||||||
|
if (value &&
|
||||||
|
octstr_case_compare(value, octstr_imm("Yes")) == 0)
|
||||||
|
dlr = 1;
|
||||||
|
else
|
||||||
|
dlr = 0;
|
||||||
|
octstr_destroy(value);
|
||||||
|
|
||||||
|
if (deliveryt < 0)
|
||||||
|
deliveryt = time(NULL);
|
||||||
|
|
||||||
|
if (expiryt < 0)
|
||||||
|
expiryt = time(NULL) + DEFAULT_EXPIRE;
|
||||||
|
|
||||||
|
if (hfrom == NULL)
|
||||||
|
hfrom = http_header_value(mh, octstr_imm("From"));
|
||||||
|
|
||||||
|
mms_remove_headers(m, "Bcc");
|
||||||
|
mms_remove_headers(m, "X-Mms-Delivery-Time");
|
||||||
|
mms_remove_headers(m, "X-Mms-Expiry");
|
||||||
|
mms_remove_headers(m, "X-Mms-Sender-Visibility");
|
||||||
|
|
||||||
|
qdir = get_mmsbox_queue_dir(hfrom, to, mmsc, &mmc_id); /* get routing info. */
|
||||||
|
/* Save it, put message id in header, return. */
|
||||||
|
qf = qfs->mms_queue_add(hfrom, to, subject,
|
||||||
|
mmsc->id, mmc_id,
|
||||||
|
deliveryt, expiryt, m, NULL,
|
||||||
|
NULL, NULL,
|
||||||
|
NULL, NULL,
|
||||||
|
NULL,
|
||||||
|
dlr,
|
||||||
|
octstr_get_cstr(qdir),
|
||||||
|
"MM7/MM1-IN",
|
||||||
|
octstr_imm(MM_NAME));
|
||||||
|
|
||||||
|
if (qf) {
|
||||||
|
/* Log to access log */
|
||||||
|
mms_log("Received", hfrom, to, msize,
|
||||||
|
msgid, NULL, mmsc->id, "MMSBox",octstr_imm("MM1"), NULL);
|
||||||
|
MMSC_CLEAR_ALARM(mmsc, MMSBOX_ALARM_QUEUE_WRITE_ERROR);
|
||||||
|
} else {
|
||||||
|
mms_error(0, "MM7", mmsc->id, "handle_mm1: failed to create queue entry for URL %s",
|
||||||
|
octstr_get_cstr(url));
|
||||||
|
MMSC_ISSUE_ALARM(mmsc, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (otransid) { /* tell mmsc that we fetched fine. */
|
||||||
|
int _status;
|
||||||
|
MmsMsg *mresp = mms_notifyresp_ind(octstr_get_cstr(otransid),
|
||||||
|
mms_message_enc(m), "Retrieved", 1);
|
||||||
|
Octstr *sm = mms_tobinary(mresp);
|
||||||
|
Octstr *_x = fetch_content_with_curl(mmsc,
|
||||||
|
NULL,
|
||||||
|
sm,
|
||||||
|
&_status);
|
||||||
|
|
||||||
|
octstr_destroy(_x);
|
||||||
|
octstr_destroy(sm);
|
||||||
|
mms_destroy(mresp);
|
||||||
|
}
|
||||||
|
gwlist_destroy(to, (void *)octstr_destroy);
|
||||||
|
octstr_destroy(hfrom);
|
||||||
|
octstr_destroy(subject);
|
||||||
|
octstr_destroy(otransid);
|
||||||
|
octstr_destroy(msgid);
|
||||||
|
octstr_destroy(qf);
|
||||||
|
octstr_destroy(mmc_id);
|
||||||
|
|
||||||
|
http_destroy_headers(mh);
|
||||||
|
}
|
||||||
|
octstr_destroy(r->u.url); /* For GET only, because caller doesn't wait */
|
||||||
|
} else if (r->type == MM1_PUSH) {
|
||||||
|
Octstr *xs = NULL;
|
||||||
|
/* we expect a send-conf. */
|
||||||
|
if (ms) {
|
||||||
|
octstr_dump(ms, 0);
|
||||||
|
|
||||||
|
mms_msgdump(m, 1);
|
||||||
|
} else
|
||||||
|
mms_warning(0, "MM7", mmsc->id,"handle_mm1: No send-conf returned by operator");
|
||||||
|
|
||||||
|
if (m == NULL ||
|
||||||
|
(r->result = mms_get_header_value(m, octstr_imm("Message-ID"))) == NULL ||
|
||||||
|
octstr_compare((xs = mms_get_header_value(m, octstr_imm("X-Mms-Response-Status"))),
|
||||||
|
octstr_imm("Ok")) != 0) {
|
||||||
|
Octstr *err = m ? mms_get_header_value(m, octstr_imm("X-Mms-Response-Text")) : NULL;
|
||||||
|
Octstr *status = m ? mms_get_header_value(m, octstr_imm("X-Mms-Response-Status")) : NULL;
|
||||||
|
if(status && (octstr_compare(status, octstr_imm("Error-service-denied")) == 0 ||
|
||||||
|
octstr_compare(status, octstr_imm("Error-permanent-failure")) == 0)) {
|
||||||
|
r->err = octstr_duplicate(status);
|
||||||
|
}
|
||||||
|
r->result = NULL; /* indicate failure to bearerbox */
|
||||||
|
mms_error(0, "MM7", mmsc->id, "Sending failed: %s, %s!",
|
||||||
|
err ? octstr_get_cstr(err) : "(none)",
|
||||||
|
status ? octstr_get_cstr(status) : "(none)");
|
||||||
|
octstr_destroy(err);
|
||||||
|
octstr_destroy(status);
|
||||||
|
}
|
||||||
|
octstr_destroy(xs);
|
||||||
|
} else
|
||||||
|
mms_error(0, "MM7", mmsc->id, "unknown type: %d", r->type);
|
||||||
|
|
||||||
|
if (r->waiter_exists) {
|
||||||
|
pthread_mutex_unlock(&r->mutex);
|
||||||
|
pthread_cond_signal(&r->cond);
|
||||||
|
} else /* no waiter, so we free it ourselves. */
|
||||||
|
gw_free(r);
|
||||||
|
|
||||||
|
octstr_destroy(body);
|
||||||
|
octstr_destroy(ms);
|
||||||
|
mms_destroy(m);
|
||||||
|
r = NULL;
|
||||||
|
|
||||||
|
if (pid > 0) {
|
||||||
|
wp = waitpid(pid, &st, WNOHANG);
|
||||||
|
if(wp == pid && WIFEXITED(st)) {
|
||||||
|
mms_info(0, "MM7", mmsc->id, "GPRS pid (%d) appears to be dead - quitting loop", pid);
|
||||||
|
goto after_gprs_dead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gwthread_sleep(2); /* according to Piotr Isajew, this makes life better */
|
||||||
|
} while (gwlist_len(mmsc->mm1.requests) > 0 &&
|
||||||
|
(r = gwlist_consume(mmsc->mm1.requests)) != NULL);
|
||||||
|
|
||||||
|
kill_gprs:
|
||||||
|
if(r != NULL) {
|
||||||
|
if(r->waiter_exists) {
|
||||||
|
pthread_mutex_unlock(&r->mutex);
|
||||||
|
pthread_cond_signal(&r->cond);
|
||||||
|
} else{
|
||||||
|
gw_free(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mmsc->mm1.gprs_off) {
|
||||||
|
stop_gprs(mmsc->mm1.gprs_off);
|
||||||
|
} else if (pid > 0) { /* stop GPRS, restart SMSC connection. */
|
||||||
|
int xkill, status;
|
||||||
|
pid_t wpid;
|
||||||
|
do {
|
||||||
|
xkill = kill(pid, SIGTERM);
|
||||||
|
mms_info(0, "MM7", mmsc->id, "GPRS turned off returned: %d", xkill);
|
||||||
|
if (xkill < 0 && errno == ESRCH)
|
||||||
|
break;
|
||||||
|
wpid = waitpid(pid, &status, 0);
|
||||||
|
if (wpid == pid && WIFEXITED(status))
|
||||||
|
break;
|
||||||
|
else if (wpid < 0 && errno == ECHILD)
|
||||||
|
break;
|
||||||
|
} while (1);
|
||||||
|
gwthread_sleep(2);
|
||||||
|
}
|
||||||
|
after_gprs_dead:
|
||||||
|
if (mmsc->mm1.smsc_on) {
|
||||||
|
system(octstr_get_cstr(mmsc->mm1.smsc_on));
|
||||||
|
gwthread_sleep(5);
|
||||||
|
mms_info(0, "MM7", mmsc->id, "SMSC turned on");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
mmsc->mm1.sender_alive--;
|
||||||
|
mms_info(0, "MM7", mmsc->id, "handle_mm1 exits");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
|
#include <curl/curl.h>
|
||||||
|
static int write_octstr_data(void *buffer, size_t size, size_t nmemb, void *userp)
|
||||||
|
{
|
||||||
|
Octstr *out = userp;
|
||||||
|
|
||||||
|
octstr_append_data(out, buffer, size*nmemb);
|
||||||
|
mms_info(0, "mmsbox-mm1", NULL, "write_data called with nmemn=%ld, size=%ld",
|
||||||
|
nmemb, size);
|
||||||
|
return size*nmemb;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static Octstr *fetch_content_with_curl(MmscGrp *mmc, Octstr *url, Octstr *body, int *hstatus)
|
||||||
|
{
|
||||||
|
Octstr *s = octstr_create("");
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
|
|
||||||
|
Octstr *proxy = mmc->mm1.proxy;
|
||||||
|
Octstr *ua = mmc->mm1.ua;
|
||||||
|
|
||||||
|
CURL *cl;
|
||||||
|
struct curl_slist *h = NULL;
|
||||||
|
char errbuf[512];
|
||||||
|
static int curl_inited = 0;
|
||||||
|
|
||||||
|
Octstr *xurl = url ? url : mmc->mmsc_url;
|
||||||
|
if (curl_inited == 0) {
|
||||||
|
curl_global_init(CURL_GLOBAL_ALL);
|
||||||
|
curl_inited = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl = curl_easy_init();
|
||||||
|
curl_easy_setopt(cl, CURLOPT_URL, octstr_get_cstr(xurl));
|
||||||
|
if (octstr_len(proxy) > 0)
|
||||||
|
curl_easy_setopt(cl, CURLOPT_PROXY, octstr_get_cstr(proxy));
|
||||||
|
curl_easy_setopt(cl, CURLOPT_WRITEFUNCTION, write_octstr_data);
|
||||||
|
curl_easy_setopt(cl, CURLOPT_WRITEDATA, s);
|
||||||
|
curl_easy_setopt(cl, CURLOPT_NOSIGNAL, 1L);
|
||||||
|
curl_easy_setopt(cl, CURLOPT_TIMEOUT, 120L);
|
||||||
|
curl_easy_setopt(cl, CURLOPT_FORBID_REUSE, 1L);
|
||||||
|
curl_easy_setopt(cl, CURLOPT_CONNECTTIMEOUT, 40L);
|
||||||
|
|
||||||
|
h = curl_slist_append(h, "Accept: */*");
|
||||||
|
if (body) { /* POST. */
|
||||||
|
h = curl_slist_append(h, "Content-Type: application/vnd.wap.mms-message");
|
||||||
|
curl_easy_setopt(cl, CURLOPT_POSTFIELDS, octstr_get_cstr(body));
|
||||||
|
curl_easy_setopt(cl, CURLOPT_POSTFIELDSIZE, octstr_len(body));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ua) {
|
||||||
|
Octstr *x = octstr_format("User-Agent: %S", ua);
|
||||||
|
h = curl_slist_append(h, octstr_get_cstr(x));
|
||||||
|
octstr_destroy(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(cl, CURLOPT_HTTPHEADER, h);
|
||||||
|
curl_easy_setopt(cl, CURLOPT_ERRORBUFFER, errbuf);
|
||||||
|
|
||||||
|
*hstatus = curl_easy_perform(cl); /* post away! */
|
||||||
|
if (*hstatus != 0) {
|
||||||
|
MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_MM7_NON_200_RESULT, 3);
|
||||||
|
|
||||||
|
mms_error(0, "mmsbox-mm1", NULL, "failed to fetch/post content to host %s [proxy: %s] [http_status=%d] : %.256s",
|
||||||
|
octstr_get_cstr(url), octstr_len(proxy) > 0 ? octstr_get_cstr(proxy) : "n/a",
|
||||||
|
*hstatus, errbuf);
|
||||||
|
} else
|
||||||
|
MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_MM7_NON_200_RESULT);
|
||||||
|
curl_slist_free_all(h); /* free the header list */
|
||||||
|
curl_easy_setopt(cl, CURLOPT_NOSIGNAL, 0L); /* Stop blocking signals */
|
||||||
|
curl_easy_cleanup(cl);
|
||||||
|
#else
|
||||||
|
panic(0, "Libcurl not linked in.");
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stop_gprs(Octstr *cmd)
|
||||||
|
{
|
||||||
|
char *xcmd = octstr_get_cstr(cmd);
|
||||||
|
FILE *f = popen(xcmd, "r");
|
||||||
|
|
||||||
|
if (f)
|
||||||
|
pclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_GPRS_WAIT 80
|
||||||
|
#define GPRS_POLL 5
|
||||||
|
static long start_gprs(Octstr *cmd, Octstr *id, Octstr *pid_cmd)
|
||||||
|
{
|
||||||
|
int ct = 0;
|
||||||
|
char *xcmd = octstr_get_cstr(cmd);
|
||||||
|
char *pcmd = pid_cmd ? octstr_get_cstr(pid_cmd) : NULL;
|
||||||
|
FILE *f = popen(xcmd, "r");
|
||||||
|
|
||||||
|
if (f == NULL) {
|
||||||
|
mms_error(0, "MM7", id, "start_gprs: failed to start process!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pclose(f);
|
||||||
|
|
||||||
|
if (pid_cmd != NULL)
|
||||||
|
do { /* Wait for it. */
|
||||||
|
long xpid = -1;
|
||||||
|
|
||||||
|
gwthread_sleep(GPRS_POLL); /* wait a little. */
|
||||||
|
if ((f = popen(pcmd, "r")) != NULL) {
|
||||||
|
fscanf(f, "%ld", &xpid);
|
||||||
|
pclose(f);
|
||||||
|
if (xpid >= 0)
|
||||||
|
return xpid;
|
||||||
|
}
|
||||||
|
mms_info(0, "MM7", id,
|
||||||
|
"start_gprs: waiting for connection: %d",ct);
|
||||||
|
} while (GPRS_POLL*ct++ < MAX_GPRS_WAIT);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
mms_error(0, "MM7", id, "start_gprs: failed to get PID!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int mm7mm1_receive(MmsBoxHTTPClientInfo *hci)
|
||||||
|
{
|
||||||
|
HTTPClient *client = hci->client;
|
||||||
|
List *cgivar_ctypes = NULL;
|
||||||
|
Octstr *text, *rb = NULL, *s = NULL, *loc = NULL;
|
||||||
|
MmsMsg *m = NULL;
|
||||||
|
int hdrlen, status = HTTP_ACCEPTED, mtype;
|
||||||
|
List *mh = NULL, *to = gwlist_create(), *rh = http_create_empty_headers();
|
||||||
|
time_t expiryt = -1, deliveryt = -1;
|
||||||
|
Octstr *from = NULL, *subject = NULL, *otransid = NULL, *mmc_id = NULL;
|
||||||
|
Octstr *qdir;
|
||||||
|
|
||||||
|
parse_cgivars(hci->headers, hci->body, &hci->cgivars, &cgivar_ctypes);
|
||||||
|
|
||||||
|
if ((text = http_cgi_variable(hci->cgivars, "text")) == NULL) {
|
||||||
|
rb = octstr_imm("mmsbox-mm1: missing 'text' CGI parameter!");
|
||||||
|
status = HTTP_NOT_FOUND;
|
||||||
|
MMSC_ISSUE_ALARM(hci->m, MMSBOX_ALARM_MM7_PARSING_FAILURE,2);
|
||||||
|
goto done;
|
||||||
|
} else
|
||||||
|
MMSC_CLEAR_ALARM(hci->m, MMSBOX_ALARM_MM7_PARSING_FAILURE);
|
||||||
|
|
||||||
|
hdrlen = octstr_get_char(text, 2);
|
||||||
|
if ((s = octstr_copy(text, 3 + hdrlen, octstr_len(text))) != NULL)
|
||||||
|
m = mms_frombinary(s, hci->m->mm1.msisdn);
|
||||||
|
else
|
||||||
|
m = NULL;
|
||||||
|
|
||||||
|
if (m == NULL) {
|
||||||
|
rb = octstr_imm("mmsbox-mm1: mal-formed mms packet on interface!");
|
||||||
|
status = HTTP_FORBIDDEN;
|
||||||
|
goto done;
|
||||||
|
} else
|
||||||
|
mms_msgdump(m, 1);
|
||||||
|
|
||||||
|
/* rest of this copied largely from EAIF code. */
|
||||||
|
mh = mms_message_headers(m);
|
||||||
|
mtype = mms_messagetype(m);
|
||||||
|
mms_collect_envdata_from_msgheaders(mh, &to, &subject,
|
||||||
|
&otransid, &expiryt, &deliveryt,
|
||||||
|
DEFAULT_EXPIRE, -1,
|
||||||
|
octstr_get_cstr(unified_prefix),
|
||||||
|
strip_prefixes);
|
||||||
|
from = http_header_value(mh, octstr_imm("From"));
|
||||||
|
qdir = get_mmsbox_queue_dir(from, to, hci->m, &mmc_id); /* get routing info. */
|
||||||
|
switch (mtype) {
|
||||||
|
Octstr *qf;
|
||||||
|
Octstr *dlr_url, *status_value, *msgid;
|
||||||
|
List *rqh;
|
||||||
|
case MMS_MSGTYPE_DELIVERY_IND: /* notification of a delivery. */
|
||||||
|
case MMS_MSGTYPE_READ_ORIG_IND: /* message read. */
|
||||||
|
msgid = http_header_value(mh, octstr_imm("Message-ID"));
|
||||||
|
status_value = http_header_value(mh,
|
||||||
|
(mtype == MMS_MSGTYPE_DELIVERY_IND) ?
|
||||||
|
octstr_imm("X-Mms-Status") :
|
||||||
|
octstr_imm("X-Mms-Read-Status"));
|
||||||
|
|
||||||
|
rqh = http_create_empty_headers();
|
||||||
|
|
||||||
|
dlr_url = mmsbox_get_report_info(m, hci->m, mmc_id,
|
||||||
|
(mtype == MMS_MSGTYPE_DELIVERY_IND) ?
|
||||||
|
"delivery-report" : "read-report",
|
||||||
|
status_value, rqh, NULL, 0, msgid);
|
||||||
|
|
||||||
|
qf = qfs->mms_queue_add(from, to, NULL,
|
||||||
|
hci->m->id, mmc_id,
|
||||||
|
0, time(NULL) + default_msgexpiry, m, NULL,
|
||||||
|
NULL, NULL,
|
||||||
|
dlr_url, NULL,
|
||||||
|
rqh,
|
||||||
|
0,
|
||||||
|
octstr_get_cstr(qdir),
|
||||||
|
"MM7/MM1-IN",
|
||||||
|
octstr_imm(MM_NAME));
|
||||||
|
if (qf) {
|
||||||
|
/* Log to access log */
|
||||||
|
mms_log((mtype == MMS_MSGTYPE_DELIVERY_IND) ? "Received DLR" : "Received RR",
|
||||||
|
from, to, -1, msgid, status_value, hci->m->id,
|
||||||
|
"MMSBox", octstr_imm("MM1"), NULL);
|
||||||
|
MMSC_CLEAR_ALARM(hci->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR);
|
||||||
|
} else {
|
||||||
|
MMSC_ISSUE_ALARM(hci->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4);
|
||||||
|
status = HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
octstr_destroy(qf);
|
||||||
|
octstr_destroy(msgid);
|
||||||
|
octstr_destroy(dlr_url);
|
||||||
|
octstr_destroy(status_value);
|
||||||
|
http_destroy_headers(rqh);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMS_MSGTYPE_NOTIFICATION_IND: /* notification of an incoming message. */
|
||||||
|
if ((loc = http_header_value(mh, octstr_imm("X-Mms-Content-Location"))) != NULL) {
|
||||||
|
MM1Request *r = gw_malloc(sizeof *r);
|
||||||
|
|
||||||
|
memset(r, 0, sizeof *r);
|
||||||
|
r->type = MM1_GET;
|
||||||
|
r->u.url = loc;
|
||||||
|
r->waiter_exists = 0;
|
||||||
|
loc = NULL;
|
||||||
|
gw_assert(hci->m->mm1.requests);
|
||||||
|
gwlist_produce(hci->m->mm1.requests, r);
|
||||||
|
} else
|
||||||
|
rb = octstr_format("mmsbox-mm1: notification with content-location??");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rb = octstr_format("mmsbox-mm1: unexpected message type: %s",
|
||||||
|
mms_message_type_to_cstr(mtype));
|
||||||
|
status = HTTP_NOT_FOUND;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
done:
|
||||||
|
/* send reply. */
|
||||||
|
http_header_add(rh, "Content-Type", "text/plain");
|
||||||
|
http_send_reply(client, status, rh, rb ? rb : octstr_imm(""));
|
||||||
|
|
||||||
|
octstr_destroy(s);
|
||||||
|
octstr_destroy(loc);
|
||||||
|
octstr_destroy(mmc_id);
|
||||||
|
octstr_destroy(from);
|
||||||
|
octstr_destroy(subject);
|
||||||
|
octstr_destroy(otransid);
|
||||||
|
|
||||||
|
octstr_destroy(rb);
|
||||||
|
gwlist_destroy(to, (void *)octstr_destroy);
|
||||||
|
|
||||||
|
http_destroy_headers(rh);
|
||||||
|
http_destroy_headers(mh);
|
||||||
|
http_destroy_cgiargs(cgivar_ctypes);
|
||||||
|
mms_destroy(m);
|
||||||
|
|
||||||
|
return http_status_class(status) == HTTP_STATUS_SUCCESSFUL ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ Octstr *mmsbox_get_report_info(MmsMsg *m, MmscGrp *mmsc, Octstr *out_mmc_id,
|
||||||
void mmsc_receive_func(MmscGrp *m);
|
void mmsc_receive_func(MmscGrp *m);
|
||||||
void mmsbox_outgoing_queue_runner(volatile sig_atomic_t *rstop);
|
void mmsbox_outgoing_queue_runner(volatile sig_atomic_t *rstop);
|
||||||
void mm4_receive_func(int *sock);
|
void mm4_receive_func(int *sock);
|
||||||
|
void handle_mm1_mt_requests(MmscGrp *m); /* MM1 loop */
|
||||||
|
|
||||||
/* Just a convenience, should go away in future! */
|
/* Just a convenience, should go away in future! */
|
||||||
#define mmsbox_url_fetch_content mms_url_fetch_content
|
#define mmsbox_url_fetch_content mms_url_fetch_content
|
||||||
|
|
|
@ -569,12 +569,20 @@ static void mmsbox_stop_mmsc_conn_real(MmscGrp *mmc)
|
||||||
if (mmc->threadid >= 0)
|
if (mmc->threadid >= 0)
|
||||||
gwthread_join(mmc->threadid);
|
gwthread_join(mmc->threadid);
|
||||||
mmc->threadid = -1;
|
mmc->threadid = -1;
|
||||||
|
|
||||||
|
if (mmc->type == MM1_MMSC) { /* Shutdown MM1 threads */
|
||||||
|
gwlist_remove_producer(mmc->mm1.requests);
|
||||||
|
gwthread_join(mmc->mm1.d_tid);
|
||||||
|
mmc->mm1.d_tid = -1;
|
||||||
|
}
|
||||||
|
|
||||||
MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_HTTP_DOWN, 1);
|
MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_HTTP_DOWN, 1);
|
||||||
}
|
}
|
||||||
mms_info(0, "mmsbox", NULL,"Shutdown for mmsc [%s] complete", octstr_get_cstr(mmc->id));
|
mms_info(0, "mmsbox", NULL,"Shutdown for mmsc [%s] complete", octstr_get_cstr(mmc->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void mmsbox_start_mmsc_conn(MmscGrp *m, List *errors, List *warnings)
|
static void mmsbox_start_mmsc_conn(MmscGrp *m, List *errors, List *warnings)
|
||||||
{
|
{
|
||||||
if (m->type == CUSTOM_MMSC) {
|
if (m->type == CUSTOM_MMSC) {
|
||||||
|
@ -607,6 +615,13 @@ static void mmsbox_start_mmsc_conn(MmscGrp *m, List *errors, List *warnings)
|
||||||
MMSC_CLEAR_ALARM(m, MMSBOX_ALARM_HTTP_DOWN);
|
MMSC_CLEAR_ALARM(m, MMSBOX_ALARM_HTTP_DOWN);
|
||||||
MMSC_CLEAR_ALARM(m, MMSBOX_ALARM_SOCKET_CONNECT_FAILED);
|
MMSC_CLEAR_ALARM(m, MMSBOX_ALARM_SOCKET_CONNECT_FAILED);
|
||||||
}
|
}
|
||||||
|
if (m->type == MM1_MMSC && m->incoming.port > 0) {
|
||||||
|
m->mm1.requests = gwlist_create();
|
||||||
|
gwlist_add_producer(m->mm1.requests);
|
||||||
|
|
||||||
|
m->mm1.d_tid = gwthread_create((gwthread_func_t *)handle_mm1_mt_requests, m);
|
||||||
|
}
|
||||||
|
|
||||||
if (mmsc_receiver_func &&
|
if (mmsc_receiver_func &&
|
||||||
m->incoming.port > 0) { /* Only start threads if func passed and ... */
|
m->incoming.port > 0) { /* Only start threads if func passed and ... */
|
||||||
if ((m->threadid = gwthread_create(mmsc_receiver_func, m)) < 0)
|
if ((m->threadid = gwthread_create(mmsc_receiver_func, m)) < 0)
|
||||||
|
@ -630,7 +645,7 @@ static MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *warnings, List
|
||||||
Octstr *xver;
|
Octstr *xver;
|
||||||
Octstr *s;
|
Octstr *s;
|
||||||
|
|
||||||
memset(m, 0, sizeof *m);
|
memset(m, 0, sizeof *m); /* Clear it: Important */
|
||||||
|
|
||||||
m->id = _mms_cfg_getx(cfg, x, octstr_imm("id"));
|
m->id = _mms_cfg_getx(cfg, x, octstr_imm("id"));
|
||||||
if (octstr_len(m->id) < 1) {
|
if (octstr_len(m->id) < 1) {
|
||||||
|
@ -706,7 +721,21 @@ static MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *warnings, List
|
||||||
m->type = MM4_MMSC;
|
m->type = MM4_MMSC;
|
||||||
else if (octstr_case_compare(type, octstr_imm("http")) == 0)
|
else if (octstr_case_compare(type, octstr_imm("http")) == 0)
|
||||||
m->type = HTTP_MMSC;
|
m->type = HTTP_MMSC;
|
||||||
else if (octstr_case_compare(type, octstr_imm("custom")) == 0) {
|
else if (octstr_case_compare(type, octstr_imm("mm1")) == 0) {
|
||||||
|
m->type = MM1_MMSC;
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
|
m->mm1.proxy = mms_cfg_get(cfg, x, octstr_imm("mm1-http-proxy"));
|
||||||
|
m->mm1.gprs_on = mms_cfg_get(cfg, x, octstr_imm("mm1-gprs-on-command"));
|
||||||
|
m->mm1.gprs_pid = mms_cfg_get(cfg, x, octstr_imm("mm1-gprs-pid-command"));
|
||||||
|
m->mm1.gprs_off = mms_cfg_get(cfg, x, octstr_imm("mm1-gprs-off-command"));
|
||||||
|
m->mm1.smsc_on = mms_cfg_get(cfg, x, octstr_imm("mm1-sms-on-command"));
|
||||||
|
m->mm1.smsc_off = mms_cfg_get(cfg, x, octstr_imm("mm1-sms-off-command"));
|
||||||
|
m->mm1.msisdn = _mms_cfg_getx(cfg, x, octstr_imm("mm1-msisdn"));
|
||||||
|
m->mm1.ua = mms_cfg_get(cfg, x, octstr_imm("mm1-ua-string"));
|
||||||
|
#else
|
||||||
|
panic(0, "MMSBox: MM1 MMSC will not work because you do not have libcurl");
|
||||||
|
#endif
|
||||||
|
} else if (octstr_case_compare(type, octstr_imm("custom")) == 0) {
|
||||||
m->type = CUSTOM_MMSC;
|
m->type = CUSTOM_MMSC;
|
||||||
m->settings = _mms_cfg_getx(cfg, x, octstr_imm("custom-settings"));
|
m->settings = _mms_cfg_getx(cfg, x, octstr_imm("custom-settings"));
|
||||||
/* also load the libary. */
|
/* also load the libary. */
|
||||||
|
@ -1075,6 +1104,8 @@ static void append_mmsc_status(Octstr *rbody, MmscGrp *m, List *warnings)
|
||||||
typ = "EAIF";
|
typ = "EAIF";
|
||||||
else if (m->type == MM4_MMSC)
|
else if (m->type == MM4_MMSC)
|
||||||
typ = "MM4";
|
typ = "MM4";
|
||||||
|
else if (m->type == MM1_MMSC)
|
||||||
|
typ = "MM1";
|
||||||
else if (m->type == CUSTOM_MMSC)
|
else if (m->type == CUSTOM_MMSC)
|
||||||
typ = "CUSTOM";
|
typ = "CUSTOM";
|
||||||
else
|
else
|
||||||
|
@ -1291,7 +1322,8 @@ void free_mmsbox_http_clientInfo(MmsBoxHTTPClientInfo *h, int freeh)
|
||||||
http_destroy_cgiargs(h->cgivars);
|
http_destroy_cgiargs(h->cgivars);
|
||||||
http_destroy_headers(h->headers);
|
http_destroy_headers(h->headers);
|
||||||
|
|
||||||
if (freeh) gw_free(h);
|
if (freeh)
|
||||||
|
gw_free(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_mmsc_struct (MmscGrp *m)
|
static void free_mmsc_struct (MmscGrp *m)
|
||||||
|
@ -1319,5 +1351,15 @@ static void free_mmsc_struct (MmscGrp *m)
|
||||||
mutex_destroy(m->mutex);
|
mutex_destroy(m->mutex);
|
||||||
gwlist_destroy(m->strip_prefixes, (void *)octstr_destroy);
|
gwlist_destroy(m->strip_prefixes, (void *)octstr_destroy);
|
||||||
|
|
||||||
|
octstr_destroy(m->mm1.proxy);
|
||||||
|
octstr_destroy(m->mm1.gprs_on);
|
||||||
|
octstr_destroy(m->mm1.gprs_off);
|
||||||
|
octstr_destroy(m->mm1.gprs_pid);
|
||||||
|
octstr_destroy(m->mm1.smsc_on);
|
||||||
|
octstr_destroy(m->mm1.smsc_off);
|
||||||
|
octstr_destroy(m->mm1.msisdn);
|
||||||
|
octstr_destroy(m->mm1.ua);
|
||||||
|
gwlist_destroy(m->mm1.requests, NULL);
|
||||||
|
|
||||||
gw_free(m);
|
gw_free(m);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ typedef struct MmscGrp {
|
||||||
} incoming; /* user, pass, port (and whether SSL) that MMSC uses to connect to us. */
|
} incoming; /* user, pass, port (and whether SSL) that MMSC uses to connect to us. */
|
||||||
Octstr *allowed_prefix, *denied_prefix;
|
Octstr *allowed_prefix, *denied_prefix;
|
||||||
Octstr *allowed_sender_prefix, *denied_sender_prefix;
|
Octstr *allowed_sender_prefix, *denied_sender_prefix;
|
||||||
enum {UNKNOWN_MMSC = -1, CUSTOM_MMSC, SOAP_MMSC, EAIF_MMSC, MM4_MMSC, HTTP_MMSC} type; /* type of connection. */
|
enum {UNKNOWN_MMSC = -1, CUSTOM_MMSC, SOAP_MMSC, EAIF_MMSC, MM4_MMSC, HTTP_MMSC, MM1_MMSC} type; /* type of connection. */
|
||||||
double throughput; /* Max send rate. */
|
double throughput; /* Max send rate. */
|
||||||
long threadid; /* handler thread. */
|
long threadid; /* handler thread. */
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ typedef struct MmscGrp {
|
||||||
|
|
||||||
time_t last_alarm[MMSBOX_ALARM_MAX_ALARM];
|
time_t last_alarm[MMSBOX_ALARM_MAX_ALARM];
|
||||||
int use_count; /* use counter. */
|
int use_count; /* use counter. */
|
||||||
time_t delete_after; /* used to control deletion of object -- not ver clean, but... */
|
time_t delete_after; /* used to control deletion of object -- not very clean, but... */
|
||||||
|
|
||||||
long max_pkt_size;
|
long max_pkt_size;
|
||||||
|
|
||||||
|
@ -86,6 +86,21 @@ typedef struct MmscGrp {
|
||||||
long max_recipients; /* Max recpients per transaction */
|
long max_recipients; /* Max recpients per transaction */
|
||||||
|
|
||||||
List *strip_prefixes; /* List of prefixes to be stripped before sending out*/
|
List *strip_prefixes; /* List of prefixes to be stripped before sending out*/
|
||||||
|
|
||||||
|
struct MM1Info_t { /* Stuff used only by the MM1 MMSC */
|
||||||
|
Octstr *proxy; /* Proxy within the operator network, form of host:port */
|
||||||
|
Octstr *gprs_on; /* Command to start GPRS link. Must not exit. */
|
||||||
|
Octstr *gprs_off; /* Command to stop GPRS link. */
|
||||||
|
Octstr *gprs_pid; /* command to call to get PID of GPRS for stopping GPRS link (i.e. pppd). */
|
||||||
|
Octstr *smsc_on; /* command to start smsc connection */
|
||||||
|
Octstr *smsc_off; /* commadn to stop smsc connection */
|
||||||
|
Octstr *msisdn; /* Our msisdn */
|
||||||
|
Octstr *ua; /* User agent string, if given */
|
||||||
|
List *requests; /* list of requests. */
|
||||||
|
long d_tid;/* thread ID for mm1 handler. */
|
||||||
|
|
||||||
|
int sender_alive;
|
||||||
|
} mm1;
|
||||||
} MmscGrp;
|
} MmscGrp;
|
||||||
|
|
||||||
#define DEFAULT_MAX_PKT_SIZE 1024*1024
|
#define DEFAULT_MAX_PKT_SIZE 1024*1024
|
||||||
|
|
|
@ -10,4 +10,4 @@ mmsc_LDADD = $(libmmsc) $(libmms)
|
||||||
mmsfromemail_LDADD = $(libmmsc) $(libmms)
|
mmsfromemail_LDADD = $(libmmsc) $(libmms)
|
||||||
mmssend_LDADD = $(libmmsc) $(libmms)
|
mmssend_LDADD = $(libmmsc) $(libmms)
|
||||||
|
|
||||||
EXTRA_DIST = mms_billing.h mms_detokenize_shell.h mms_billing_shell.h mms_resolve_shell.h mmsc_cfg.h mms_detokenize.h mms_resolve.h mmsc_mm5.h
|
EXTRA_DIST = mmsc.h mms_billing.h mms_detokenize_shell.h mms_billing_shell.h mms_resolve_shell.h mmsc_cfg.h mms_detokenize.h mms_resolve.h mmsc_mm5.h
|
||||||
|
|
Loading…
Reference in New Issue