added mm4 incoming handler for mmsbox
This commit is contained in:
parent
20ae441d94
commit
fd2ed9038f
|
@ -1,3 +1,7 @@
|
|||
2010-10-25 P. A. Bagyenda <bagyenda@dsmagic.com>
|
||||
* Added MM4 incoming handler for mmsbox
|
||||
2010-10-22 P. A. Bagyenda <bagyenda@dsmagic.com>
|
||||
* Make a lib for mmsbox, make it easier to link external apps to its engine
|
||||
2010-10-19 P. A. Bagyenda <bagyenda@dsmagic.com>
|
||||
* Added new func to mms_cfg -- make it easier to implement module-based configuration
|
||||
* Extended mmsbox_cfg load functions to make it easier to configure using modules
|
||||
|
|
252
mbuni/INSTALL
252
mbuni/INSTALL
|
@ -1,16 +1,25 @@
|
|||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
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
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
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
|
||||
|
@ -23,9 +32,9 @@ 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
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.)
|
||||
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
|
||||
|
@ -35,30 +44,37 @@ 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 only need
|
||||
`configure.ac' if you want to change it or regenerate `configure' using
|
||||
a newer version of `autoconf'.
|
||||
`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:
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./bootstrap' followed by `./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
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.
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
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. You can remove the program binaries and object files from the
|
||||
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
|
||||
|
@ -67,65 +83,120 @@ The simplest way to compile this package is:
|
|||
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.
|
||||
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=c89 CFLAGS=-O2 LIBS=-lposix
|
||||
./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
|
||||
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 must use a version of `make' that
|
||||
supports the `VPATH' variable, such as 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
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
source code in the directory that `configure' is in and in `..'. This
|
||||
is known as a "VPATH" build.
|
||||
|
||||
If you have to use a `make' that does not support the `VPATH'
|
||||
variable, you have 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.
|
||||
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' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PREFIX'.
|
||||
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
|
||||
give `configure' the option `--exec-prefix=PREFIX', the package will
|
||||
use PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
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.
|
||||
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'.
|
||||
|
||||
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.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
|
@ -137,14 +208,53 @@ 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 `<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
|
||||
==========================
|
||||
|
||||
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
|
||||
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:
|
||||
|
||||
|
@ -152,14 +262,15 @@ type, such as `sun4', or a canonical name which has the form:
|
|||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
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 `--target=TYPE' option to select the type of system they will
|
||||
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
|
||||
|
@ -170,9 +281,9 @@ 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'.
|
||||
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.
|
||||
|
@ -181,7 +292,7 @@ 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
|
||||
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
|
||||
|
@ -189,17 +300,30 @@ them in the `configure' command line, using `VAR=value'. For example:
|
|||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
will cause the specified gcc to be used as the C compiler (unless it is
|
||||
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.
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
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'
|
||||
|
@ -226,6 +350,16 @@ overridden in the site shell script).
|
|||
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.
|
||||
|
||||
|
|
|
@ -285,7 +285,7 @@ provisioned, etc.
|
|||
<li>Operating as a <b>VAS Gateway</b>, Mbuni provides:
|
||||
|
||||
<ul>
|
||||
<li> Support for both SOAP and EAIF connectivity with an operator
|
||||
<li> Support for SOAP, EAIF and MM4 connectivity with an operator
|
||||
MMSC (plus a special HTTP-based relay mechanism)
|
||||
<li> Multiple connections to different MMSC of different types can
|
||||
be maintained
|
||||
|
@ -1235,6 +1235,40 @@ value given above (<tt>queue-run-interval</tt>)
|
|||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr >
|
||||
<td valign=top >
|
||||
<tt>mm4-port</tt>
|
||||
|
||||
</td>
|
||||
|
||||
<td valign=top >
|
||||
<i>MMSBOX</i>
|
||||
|
||||
</td>
|
||||
|
||||
<td valign=top >
|
||||
Integer
|
||||
</td>
|
||||
<td valign=top >
|
||||
Port on which <tt>mmsbox</tt> listens for MM4 requests from Value
|
||||
Added Services providers. If this port is not supplied, the MM4 receiver
|
||||
sub-system is not started.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr >
|
||||
<td valign=top >
|
||||
<tt>mmsbox-mm4-domain-number-prefixes</tt>
|
||||
|
||||
</td>
|
||||
|
||||
<td valign=top >
|
||||
<i>MMSBOX</i>
|
||||
|
||||
</td>
|
||||
|
||||
<tr>
|
||||
<td valign=top >
|
||||
<tt>allow-ip</tt>
|
||||
|
@ -2432,7 +2466,8 @@ Supported configuration parameters are:
|
|||
<td valign=top >
|
||||
Mandatory:
|
||||
Protocol spoken by this MMSC, one of <tt>soap</tt> for 3GPP MM7
|
||||
SOAP, <tt>eaif</tt> for Nokia EAIF protocol, <tt>http</tt> for
|
||||
SOAP, <tt>eaif</tt> for Nokia EAIF protocol, <tt>mm4</t> for 3GPP
|
||||
MM4, <tt>http</tt> for
|
||||
special HTTP-based inter-mmsbox message relay (see below), or <tt>custom</tt> for
|
||||
a custom implementation handled by a loadable module (see
|
||||
<tt>mmsc-library</tt> below).<br> For <tt>type = http</tt> the VAS GW
|
||||
|
@ -2508,10 +2543,29 @@ Supported configuration parameters are:
|
|||
</td>
|
||||
<td valign=top >
|
||||
Mandatory:
|
||||
URL address for the MMSC. Used for outgoing messages
|
||||
URL address for the MMSC. Used for outgoing messages. When type
|
||||
is <tt>MM4</tt>, this <b>must</b> be set to the MM4 domain. If you
|
||||
wish to support email senders, create an <tt>mmsc</tt> group where
|
||||
the domain is set to <tt>*</tt>.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign=top >
|
||||
<tt>maximum-request-size</tt>
|
||||
|
||||
</td>
|
||||
<td valign=top >
|
||||
int
|
||||
</td>
|
||||
<td valign=top >
|
||||
Optional:
|
||||
Maximum request size that this interface will receive. Larger
|
||||
requests will be dropped. Default is 500k.
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign=top >
|
||||
<tt>incoming-port</tt>
|
||||
|
@ -2521,11 +2575,29 @@ Supported configuration parameters are:
|
|||
Number
|
||||
</td>
|
||||
<td valign=top >
|
||||
Port at which Mbuni listens for incoming messages from MMSC
|
||||
Port at which Mbuni listens for incoming messages from MMSC. Not
|
||||
used for MM4 incoming connections (<tt>mm4-port</tt> is used instead).
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td valign=top >
|
||||
<tt>strip-domain</tt>
|
||||
|
||||
</td>
|
||||
<td valign=top >
|
||||
boolean
|
||||
</td>
|
||||
<td valign=top >
|
||||
Optional:
|
||||
MM4 MMSC connections only: Whether to strip the domain name from
|
||||
the received sender/recipient addresses (if they are phone numbers)
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign=top >
|
||||
<tt>incoming-user</tt>
|
||||
|
|
|
@ -66,10 +66,10 @@ static int pgq_init_module(Octstr *conninfo, char *xtopdir, int max_connections)
|
|||
|
||||
/* Now look for flags */
|
||||
if ((i = octstr_search_char(xcinfo, ';', 0)) > 0) {
|
||||
Octstr *x = octstr_copy(xcinfo, 0, i);
|
||||
Octstr *x = octstr_copy(xcinfo, i+1, octstr_len(xcinfo));
|
||||
|
||||
octstr_delete(xcinfo, i, octstr_len(xcinfo));
|
||||
|
||||
octstr_delete(xcinfo, 0, i+1);
|
||||
|
||||
if (octstr_case_search(x, octstr_imm("internal"), 0) >= 0)
|
||||
external_storage = 0;
|
||||
if (octstr_case_search(x, octstr_imm("no-archive"), 0) >= 0)
|
||||
|
|
|
@ -75,6 +75,7 @@ SINGLE_GROUP(mbuni,
|
|||
OCTSTR(sendsms-global-sender)
|
||||
OCTSTR(mms-port)
|
||||
OCTSTR(mm7-port)
|
||||
OCTSTR(mm4-port)
|
||||
OCTSTR(allow-ip)
|
||||
OCTSTR(deny-ip)
|
||||
OCTSTR(email2mms-relay-hosts)
|
||||
|
@ -121,7 +122,6 @@ SINGLE_GROUP(mbuni,
|
|||
|
||||
OCTSTR(mmsbox-cdr-module)
|
||||
OCTSTR(mmsbox-cdr-module-parameters)
|
||||
|
||||
OCTSTR(mmsc-services)
|
||||
)
|
||||
|
||||
|
@ -191,6 +191,8 @@ MULTI_GROUP(mmsc,
|
|||
OCTSTR(no-sender-address)
|
||||
|
||||
OCTSTR(default-vasid)
|
||||
OCTSTR(maximum-request-size)
|
||||
OCTSTR(strip-domain)
|
||||
)
|
||||
|
||||
MULTI_GROUP(mms-service,
|
||||
|
|
|
@ -1025,6 +1025,9 @@ int mm7_msgtype_to_soaptype(int mtype, int isclientside)
|
|||
case MMS_MSGTYPE_DELIVERY_IND:
|
||||
t = MM7_TAG_DeliveryReportReq;
|
||||
break;
|
||||
case MMS_MSGTYPE_SEND_CONF:
|
||||
t = isclientside ? MM7_TAG_SubmitRsp : MM7_TAG_DeliverRsp;
|
||||
break;
|
||||
case -1:
|
||||
t = isclientside ? MM7_TAG_RSErrorRsp : MM7_TAG_VASPErrorRsp;
|
||||
break;
|
||||
|
@ -1233,7 +1236,7 @@ MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto,
|
|||
}
|
||||
|
||||
if (m) { /* Add custom headers, hope caller knows what they are doing */
|
||||
List *l = http_header_find_all(hdrs, "X-Mbuni-MM7-Headers");
|
||||
List *l = hdrs ? http_header_find_all(hdrs, "X-Mbuni-MM7-Headers") : NULL;
|
||||
int i, n;
|
||||
|
||||
|
||||
|
|
|
@ -29,6 +29,16 @@ struct MmsMsg {
|
|||
};
|
||||
|
||||
|
||||
struct MM4_types_map_t mm4_types[] = {
|
||||
{"MM4_forward.REQ", MMS_MSGTYPE_SEND_REQ},
|
||||
{"MM4_forward.RES",MMS_MSGTYPE_SEND_CONF},
|
||||
{"MM4_read_reply_report.REQ", MMS_MSGTYPE_READ_REC_IND},
|
||||
{"MM4_read_reply_report.RES",-1},
|
||||
{"MM4_delivery_report.REQ",MMS_MSGTYPE_DELIVERY_IND},
|
||||
{"MM4_delivery_report.RES",-1},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
#define SIZHINT 47
|
||||
|
||||
|
||||
|
@ -1960,7 +1970,9 @@ int mms_msgsize(MmsMsg *m)
|
|||
Octstr *s;
|
||||
int n;
|
||||
|
||||
gw_assert(m);
|
||||
if (m == NULL)
|
||||
return 0;
|
||||
|
||||
s = mms_tobinary(m); /* Dirty, but works... */
|
||||
n = octstr_len(s);
|
||||
octstr_destroy(s);
|
||||
|
|
|
@ -133,4 +133,13 @@ int mms_make_sendreq(MmsMsg *retrieveconf);
|
|||
|
||||
/* Compute message size -- not altogether efficiently */
|
||||
int mms_msgsize(MmsMsg *m);
|
||||
|
||||
/* MM4 stuff */
|
||||
enum MM4_types_t {MM4_FORWARD_REQ = 0, MM4_FORWARD_RES, MM4_READ_REPLY_REPORT_REQ,
|
||||
MM4_READ_REPLY_REPORT_RES, MM4_DELIVERY_REPORT_REQ, MM4_DELIVERY_REPORT_RES};
|
||||
extern struct MM4_types_map_t {
|
||||
char *mm4str;
|
||||
int mm1_type;
|
||||
} mm4_types[];
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -225,6 +225,9 @@ Octstr *extract_phonenum(Octstr *num, Octstr *unified_prefix);
|
|||
/* strip quotes off a quoted string. */
|
||||
void strip_quoted_string(Octstr *s);
|
||||
|
||||
/* Remove quotes from string */
|
||||
void strip_quotes(Octstr *s);
|
||||
|
||||
/* Make a mime entity representing a multipart/form-data HTTP request. */
|
||||
MIMEEntity *make_multipart_formdata(void);
|
||||
|
||||
|
@ -240,7 +243,10 @@ MIMEEntity *multipart_from_urls(List *url_list);
|
|||
void *_mms_load_module(mCfg *cfg, mCfgGrp *grp, char *config_key, char *symbolname,
|
||||
void *shell_builtin);
|
||||
|
||||
|
||||
/* Clean addresses by type: remove prefixes, etc. */
|
||||
void fixup_address_type(List *headers, char *hdr,
|
||||
char *unified_prefix,
|
||||
List *strip_prefixes);
|
||||
#define MAXQTRIES 100
|
||||
#define BACKOFF_FACTOR 5*60 /* In seconds */
|
||||
#define QUEUERUN_INTERVAL 1*60 /* 1 minutes. */
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
libmms = $(top_builddir)/mmlib/libmms.a
|
||||
|
||||
noinst_LIBRARIES = libmmsbox.a
|
||||
libmmsbox_a_SOURCES = mmsbox_cdr.c mmsbox_cfg.c dlr.c bearerbox.c mmsbox_resolve.c mmsbox_resolve_shell.c
|
||||
bin_PROGRAMS = mmsbox
|
||||
mmsbox_SOURCES = mmsbox.c mmsbox_cdr.c mmsbox_cfg.c dlr.c bearerbox.c mmsbox_resolve.c mmsbox_resolve_shell.c
|
||||
mmsbox_LDADD = $(libmms)
|
||||
mmsbox_SOURCES = mmsbox.c
|
||||
mmsbox_LDADD = libmmsbox.a $(libmms)
|
||||
|
||||
EXTRA_DIST = mmsbox_cdr.h mmsbox_cfg.h mmsbox.h mmsbox_mt_filter.h mmsbox_resolve_shell.h mmsbox_resolve.h mmsbox_mmsc.h
|
||||
|
|
|
@ -396,7 +396,7 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h)
|
|||
s = mm7_soap_header_value(mreq, octstr_imm("MM7Version"));
|
||||
r = mm7_soap_header_value(mreq, octstr_imm("MessageID"));
|
||||
transid = mm7_soap_header_value(mreq, octstr_imm("TransactionID"));
|
||||
mmsbox_event_cb(h->m->id, mm7_msgtype(mreq), 0, s, 0,
|
||||
mmsbox_event_cb(h->m->id, mm7_msgtype(mreq), 0, s, 200,
|
||||
octstr_len(h->body), 0, from,
|
||||
to && gwlist_len(to) > 0 ? gwlist_get(to,0) : NULL, r, transid, NULL, value);
|
||||
octstr_destroy(s);
|
||||
|
@ -466,7 +466,12 @@ static int queue_dlr(MmscGrp *mmc, Octstr *from, Octstr *to, Octstr *msgid, Octs
|
|||
qdir = get_mmsbox_queue_dir(from, lto, mmc, &mmc_id); /* get routing info. */
|
||||
|
||||
rr_uri = mmsbox_get_report_info(m, mmc, mmc_id, "delivery-report", status, rqh, NULL, 0, msgid);
|
||||
|
||||
|
||||
mmsbox_event_cb(mmc->id, MM7_TAG_DeliveryReportReq, 0,octstr_imm("5.3.0"), 200,
|
||||
0, 0, from,
|
||||
lto && gwlist_len(lto) > 0 ? gwlist_get(lto,0) : NULL,
|
||||
msgid, NULL, NULL, status);
|
||||
|
||||
qf = qfs->mms_queue_add(from, lto, NULL,
|
||||
mmc ? mmc->id : NULL, mmc_id,
|
||||
0, time(NULL) + default_msgexpiry, m, NULL,
|
||||
|
@ -699,7 +704,7 @@ static int mm7eaif_receive(MmsBoxHTTPClientInfo *h)
|
|||
|
||||
|
||||
s = http_header_value(h->headers, octstr_imm("X-NOKIA-MMSC-Version"));
|
||||
mmsbox_event_cb(h->m->id, mm7type, 0, s, 0,
|
||||
mmsbox_event_cb(h->m->id, mm7type, 0, s, hstatus,
|
||||
msize, 0, hfrom,
|
||||
to && gwlist_len(to) > 0 ? gwlist_get(to,0) : NULL,
|
||||
msgid, otransid, NULL, value);
|
||||
|
@ -963,7 +968,7 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h)
|
|||
}
|
||||
|
||||
|
||||
mmsbox_event_cb(h->m->id, mm7type, 0, octstr_imm("1.0"), 0,
|
||||
mmsbox_event_cb(h->m->id, mm7type, 0, octstr_imm("1.0"), 200,
|
||||
msize, 0, hfrom,
|
||||
to && gwlist_len(to) > 0 ? gwlist_get(to,0) : NULL,
|
||||
msgid, octstr_imm("0000"), NULL, value);
|
||||
|
@ -1181,7 +1186,7 @@ static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to,
|
|||
/* Invoke call back */
|
||||
s = mm7_soap_header_value(mreq, octstr_imm("MM7Version"));
|
||||
r = mm7_soap_header_value(mreq, octstr_imm("MessageID"));
|
||||
mmsbox_event_cb(mmc->id, mm7_msgtype(mreq), 0, s, 0,
|
||||
mmsbox_event_cb(mmc->id, mm7_msgtype(mreq), 0, s, hstatus,
|
||||
mms_msgsize(m), e->attempts, e->from,
|
||||
to,r, transid, hdrs, NULL);
|
||||
octstr_destroy(s);
|
||||
|
@ -1497,12 +1502,16 @@ static int mms_sendtommsc(MmscGrp *mmc, MmsEnvelope *e, Octstr *to,
|
|||
id = mm7eaif_send(mmc, from, to, transid, vasid, e, m, &err, &retry);
|
||||
else if (mmc->type == HTTP_MMSC)
|
||||
id = mm7http_send(mmc,e, from, to, m, &err, &retry);
|
||||
else if (mmc->type == CUSTOM_MMSC && mmc->custom_started)
|
||||
else if (mmc->type == CUSTOM_MMSC && mmc->started)
|
||||
id = mmc->fns->send_msg(mmc->data,
|
||||
from, to, transid, linkedid, vasid,
|
||||
service_code, m, hdrs, &err, &retry);
|
||||
else
|
||||
mms_error_ex("MT", 0, "MM7", mmc->id, "MMC[%s] of unknown type, can't send!",
|
||||
#if 0
|
||||
else if (mmc->type == MM4_MMSC && mmc->started)
|
||||
(void )0; /* Already sent above */
|
||||
#endif
|
||||
else
|
||||
mms_error_ex("MT", 0, "MM7", mmc->id, "Can't send to MMC[%s]!",
|
||||
mmc->id ? octstr_get_cstr(mmc->id) : "");
|
||||
|
||||
throughput = mmc->throughput;
|
||||
|
@ -1591,11 +1600,11 @@ static int sendMsg(MmsEnvelope *e)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (is_email) {
|
||||
if (is_email || (mmc->type == MM4_MMSC && mmc->started)) { /* Handle MM4 recipient here as well */
|
||||
int j = octstr_case_search(e->from, octstr_imm("/TYPE=PLMN"), 0);
|
||||
int k = octstr_case_search(e->from, octstr_imm("/TYPE=IPv"), 0);
|
||||
int len = octstr_len(e->from);
|
||||
Octstr *pfrom;
|
||||
Octstr *pfrom, *xto;
|
||||
|
||||
|
||||
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
|
||||
|
@ -1604,11 +1613,18 @@ static int sendMsg(MmsEnvelope *e)
|
|||
pfrom = octstr_copy(e->from, 0, k);
|
||||
else
|
||||
pfrom = octstr_duplicate(e->from);
|
||||
|
||||
if (!is_email)
|
||||
xto = octstr_format("%S@%S", to->rcpt,
|
||||
mmc && octstr_str_compare(mmc->mmsc_url, "*") != 0 ? mmc->mmsc_url :
|
||||
octstr_imm("unknown"));
|
||||
else
|
||||
xto = octstr_duplicate(to->rcpt);
|
||||
|
||||
if (octstr_search_char(e->from, '@', 0) < 0)
|
||||
octstr_format_append(pfrom,"@%S", myhostname);
|
||||
|
||||
res = mms_sendtoemail(pfrom, to->rcpt,
|
||||
res = mms_sendtoemail(pfrom, xto,
|
||||
e->subject ? e->subject : octstr_imm(""),
|
||||
e->msgId, msg, 0, &err, octstr_get_cstr(sendmail_cmd),
|
||||
myhostname, 0, 0,
|
||||
|
@ -1616,7 +1632,13 @@ static int sendMsg(MmsEnvelope *e)
|
|||
"", 0,
|
||||
e->xqfname,
|
||||
e->hdrs);
|
||||
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED)
|
||||
mmsbox_event_cb(NULL, MM7_TAG_SubmitReq, 1, octstr_imm("1.0"), 200,
|
||||
mms_msgsize(msg), e->attempts, pfrom,
|
||||
to->rcpt,NULL, NULL, e->hdrs, NULL);
|
||||
|
||||
octstr_destroy(pfrom);
|
||||
octstr_destroy(xto);
|
||||
} else {
|
||||
res = mms_sendtommsc(mmc, e,
|
||||
to->rcpt,
|
||||
|
@ -1740,3 +1762,640 @@ void mmsbox_outgoing_queue_runner(volatile sig_atomic_t *rstop)
|
|||
sendMsg, queue_interval, maxthreads, rstop);
|
||||
hmon->unregister_thread();
|
||||
}
|
||||
|
||||
|
||||
/* MM4 handler stuff */
|
||||
static void fixup_addresses(List *headers)
|
||||
{
|
||||
fixup_address_type(headers, "To",
|
||||
octstr_get_cstr(unified_prefix), strip_prefixes);
|
||||
fixup_address_type(headers, "From",
|
||||
octstr_get_cstr(unified_prefix), strip_prefixes);
|
||||
}
|
||||
|
||||
|
||||
static int send_mm4_res(int mtype, Octstr *to, Octstr *sender, Octstr *transid,
|
||||
char *status, Octstr *msgid,
|
||||
char *sendmail_cmd)
|
||||
{
|
||||
char tmp[32];
|
||||
List *h = http_create_empty_headers();
|
||||
MIMEEntity *m = mime_entity_create();
|
||||
Octstr *err = NULL;
|
||||
|
||||
/* Make headers */
|
||||
sprintf(tmp, "%d.%d.%d",
|
||||
MAJOR_VERSION(MMS_3GPP_VERSION),
|
||||
MINOR1_VERSION(MMS_3GPP_VERSION),
|
||||
MINOR2_VERSION(MMS_3GPP_VERSION));
|
||||
|
||||
http_header_add(h, "X-Mms-3GPP-MMS-Version", tmp);
|
||||
http_header_add(h, "X-Mms-Transaction-ID", octstr_get_cstr(transid));
|
||||
http_header_add(h, "X-Mms-Message-Type", mm4_types[mtype].mm4str);
|
||||
if (msgid)
|
||||
http_header_add(h, "X-Mms-Message-ID", octstr_get_cstr(msgid));
|
||||
http_header_add(h, "X-Mms-Request-Status-Code", status);
|
||||
http_header_add(h, "Sender", octstr_get_cstr(sender));
|
||||
http_header_add(h, "To", octstr_get_cstr(to));
|
||||
|
||||
mime_replace_headers(m, h);
|
||||
http_destroy_headers(h);
|
||||
|
||||
mm_send_to_email(to, sender, octstr_imm(""), msgid, m, 0,
|
||||
&err, sendmail_cmd,
|
||||
myhostname);
|
||||
if (err) {
|
||||
mms_warning(0, "MM4", NULL, "send.RES reported: %s!", octstr_get_cstr(err));
|
||||
octstr_destroy(err);
|
||||
}
|
||||
mime_entity_destroy(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Octstr *handle_msg(MIMEEntity *mm, Octstr *from, List *to, MmscGrp *mmc)
|
||||
{
|
||||
char *err = NULL;
|
||||
List *headers, *h2;
|
||||
Octstr *mm4_type;
|
||||
Octstr *transid = NULL, *orig_sys = NULL, *ack = NULL, *res = NULL, *me = NULL, *rstatus = NULL;
|
||||
int i, mtype = -1, mm1_type = -1, mm7type;
|
||||
MmsMsg *msg = NULL;
|
||||
Octstr *qdir = NULL, *mmc_id = NULL, *value = NULL, *msgid = NULL;
|
||||
|
||||
Octstr *xproxy = mmc != NULL && octstr_str_compare(mmc->mmsc_url, "*") != 0 ? mmc->mmsc_url : NULL;
|
||||
|
||||
/* Taken largely from mmsfromeamil.c */
|
||||
/* Take the entity, recode it --> remove base64 stuff, split headers. */
|
||||
unbase64_mimeparts(mm);
|
||||
unpack_mimeheaders(mm);
|
||||
|
||||
/* Delete some headers... */
|
||||
headers = mime_entity_headers(mm);
|
||||
http_header_remove_all(headers, "Received");
|
||||
http_header_remove_all(headers, "X-MimeOLE");
|
||||
http_header_remove_all(headers, "X-Mailer");
|
||||
|
||||
/* rebuild headers, removing nasty looking ones. */
|
||||
h2 = http_create_empty_headers();
|
||||
for (i = 0; i<gwlist_len(headers); i++) {
|
||||
Octstr *name = NULL, *value = NULL;
|
||||
http_header_get(headers, i, &name, &value);
|
||||
|
||||
if (!name ||
|
||||
octstr_case_search(name, octstr_imm("spam"), 0) >= 0 ||
|
||||
octstr_case_search(name, octstr_imm("mailscanner"), 0) >= 0)
|
||||
goto loop;
|
||||
|
||||
http_header_add(h2, octstr_get_cstr(name), octstr_get_cstr(value));
|
||||
loop:
|
||||
octstr_destroy(name);
|
||||
octstr_destroy(value);
|
||||
}
|
||||
http_destroy_headers(headers);
|
||||
headers = h2;
|
||||
|
||||
/* Look for MM4 headers... */
|
||||
mm4_type = http_header_value(headers, octstr_imm("X-Mms-Message-Type"));
|
||||
ack = http_header_value(headers, octstr_imm("X-Mms-Ack-Request"));
|
||||
rstatus = http_header_value(headers, octstr_imm("X-Mms-Request-Status-Code"));
|
||||
|
||||
if ((transid = http_header_value(headers, octstr_imm("X-Mms-Transaction-ID"))) == NULL)
|
||||
transid = octstr_create("001");
|
||||
/* get originator system. */
|
||||
if ((orig_sys = http_header_value(headers, octstr_imm("X-Mms-Originator-System"))) == NULL)
|
||||
orig_sys = http_header_value(headers, octstr_imm("Sender"));
|
||||
|
||||
if ((msgid = http_header_value(headers, octstr_imm("X-Mms-Message-ID"))) == NULL)
|
||||
msgid = http_header_value(headers, octstr_imm("Message-ID"));
|
||||
|
||||
strip_quoted_string(msgid);
|
||||
strip_quoted_string(transid);
|
||||
|
||||
|
||||
debug("mmsbox.MM4receive", 0,
|
||||
"Received [message type: %s] [transaction id: %s] [msgid: %s]",
|
||||
mm4_type ? octstr_get_cstr(mm4_type) : "",
|
||||
transid ? octstr_get_cstr(transid) : "",
|
||||
msgid ? octstr_get_cstr(msgid) : "");
|
||||
|
||||
/* ... and remove non-essential ones */
|
||||
http_header_remove_all(headers, "X-Mms-3GPP-MMS-Version");
|
||||
http_header_remove_all(headers, "MIME-Version");
|
||||
http_header_remove_all(headers, "X-Mms-Message-ID");
|
||||
http_header_remove_all(headers, "Message-ID");
|
||||
http_header_remove_all(headers, "X-Mms-Ack-Request");
|
||||
http_header_remove_all(headers, "X-Mms-Originator-System");
|
||||
|
||||
http_header_remove_all(headers, "Sender");
|
||||
|
||||
/* msgid was there, put it back in proper form. */
|
||||
if (msgid)
|
||||
http_header_add(headers, "Message-ID", octstr_get_cstr(msgid));
|
||||
|
||||
fixup_addresses(headers);
|
||||
|
||||
|
||||
if (mm4_type) {
|
||||
unsigned char *x = NULL;
|
||||
Octstr *y;
|
||||
int i;
|
||||
|
||||
http_header_remove_all(headers, "X-Mms-Message-Type");
|
||||
for (i = 0; mm4_types[i].mm4str; i++)
|
||||
if (octstr_str_case_compare(mm4_type, mm4_types[i].mm4str) == 0) {
|
||||
mtype = i;
|
||||
mm1_type = mm4_types[i].mm1_type;
|
||||
x = mms_message_type_to_cstr(mm1_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (x) {
|
||||
http_header_add(headers, "X-Mms-Message-Type", (char *)x);
|
||||
if (orig_sys == NULL) /* Make it up! */
|
||||
orig_sys = octstr_format("system-user@%S",
|
||||
xproxy ? xproxy : octstr_imm("unknown"));
|
||||
} else {
|
||||
octstr_destroy(mm4_type);
|
||||
mm4_type = NULL; /* So that we assume normal message below. */
|
||||
}
|
||||
|
||||
if ((y = http_header_value(headers, octstr_imm("X-Mms-MM-Status-Code"))) != NULL) {
|
||||
/* This field is different on MM1. */
|
||||
http_header_remove_all(headers, "X-Mms-MM-Status-Code");
|
||||
http_header_add(headers, "X-Mms-Status", octstr_get_cstr(y));
|
||||
octstr_destroy(y);
|
||||
}
|
||||
}
|
||||
if (mm4_type == NULL) { /* else assume a normal send message. */
|
||||
http_header_add(headers, "X-Mms-Message-Type", "m-send-req");
|
||||
mm1_type = MMS_MSGTYPE_SEND_REQ;
|
||||
mtype = MM4_FORWARD_REQ;
|
||||
}
|
||||
|
||||
mime_replace_headers(mm, headers);
|
||||
http_destroy_headers(headers);
|
||||
|
||||
/* Now convert from mime to MMS message, if we should */
|
||||
if (mm1_type >= 0) {
|
||||
if ((msg = mms_frommime(mm)) == NULL) {
|
||||
mms_error(0, "MM4", mmc ? mmc->id : NULL, "Unable to parse Message!");
|
||||
MMSC_ISSUE_ALARM(mmc ? mmc : NULL, MMSBOX_ALARM_MM4_PARSING_FAILURE, 3);
|
||||
res = NULL;
|
||||
|
||||
goto done;
|
||||
} else
|
||||
MMSC_CLEAR_ALARM(mmc ? mmc : NULL, MMSBOX_ALARM_MM4_PARSING_FAILURE);
|
||||
} else
|
||||
msg = NULL;
|
||||
|
||||
me = octstr_format("system-user@%S", myhostname);
|
||||
|
||||
qdir = get_mmsbox_queue_dir(from, to, mmc, &mmc_id); /* get routing info. */
|
||||
switch(mtype) {
|
||||
case MM4_FORWARD_REQ:
|
||||
{
|
||||
Octstr *qf;
|
||||
Octstr *dreport = mms_get_header_value(msg, octstr_imm("X-Mms-Delivery-Report"));
|
||||
Octstr *subject = mms_get_header_value(msg, octstr_imm("Subject"));
|
||||
int dlr;
|
||||
|
||||
if (dreport &&
|
||||
octstr_case_compare(dreport, octstr_imm("Yes")) == 0)
|
||||
dlr = 1;
|
||||
else
|
||||
dlr = 0;
|
||||
|
||||
qf = qfs->mms_queue_add(from, to, subject, mmc ? mmc->id : NULL, mmc_id,
|
||||
0, time(NULL) + default_msgexpiry, msg, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
dlr,
|
||||
octstr_get_cstr(qdir),
|
||||
"MM7/MM4-IN",
|
||||
NULL);
|
||||
if (qf) {
|
||||
res = mms_make_msgid(octstr_get_cstr(qf), NULL);
|
||||
mms_log("Received", from, to, -1, res, NULL, mmc->id, "MMSBox", octstr_imm("smtp"), NULL);
|
||||
err = "Ok";
|
||||
MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_QUEUE_WRITE_ERROR);
|
||||
} else {
|
||||
MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4);
|
||||
err = "Error-network-problem";
|
||||
}
|
||||
octstr_destroy(dreport);
|
||||
octstr_destroy(subject);
|
||||
octstr_destroy(qf);
|
||||
}
|
||||
break;
|
||||
case MM4_DELIVERY_REPORT_REQ:
|
||||
{
|
||||
Octstr *qf;
|
||||
Octstr *value2 = NULL, *rr_uri = NULL;
|
||||
List *rqh = http_create_empty_headers();
|
||||
|
||||
value = mms_get_header_value(msg, octstr_imm("X-Mms-Status"));
|
||||
value2 = mms_get_header_value(msg, octstr_imm("X-Mbuni-Orig-Message-ID"));
|
||||
|
||||
|
||||
rr_uri = mmsbox_get_report_info(msg, mmc, mmc_id, "delivery-report",
|
||||
value, rqh, NULL, 0, msgid);
|
||||
if (value2 && mmc_id == NULL)
|
||||
http_header_add(rqh, "X-Mbuni-Orig-Message-ID", octstr_get_cstr(value2));
|
||||
|
||||
qf = qfs->mms_queue_add(from, to, NULL,
|
||||
mmc ? mmc->id : NULL, mmc_id,
|
||||
0, time(NULL) + default_msgexpiry, msg, NULL,
|
||||
NULL, NULL,
|
||||
rr_uri, NULL,
|
||||
rqh,
|
||||
0,
|
||||
octstr_get_cstr(qdir),
|
||||
"MM7/MM4-IN",
|
||||
NULL);
|
||||
|
||||
if (qf) {
|
||||
mms_log("DeliveryReport", from, to, -1, msgid, value, mmc->id, "MMSBox", octstr_imm("smtp"), NULL);
|
||||
err = "Ok";
|
||||
res = octstr_duplicate(qf);
|
||||
MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_QUEUE_WRITE_ERROR);
|
||||
} else {
|
||||
MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4);
|
||||
err = "Error-network-problem";
|
||||
}
|
||||
|
||||
octstr_destroy(qf);
|
||||
octstr_destroy(value2);
|
||||
octstr_destroy(rr_uri);
|
||||
http_destroy_headers(rqh);
|
||||
}
|
||||
break;
|
||||
|
||||
case MM4_READ_REPLY_REPORT_REQ:
|
||||
{
|
||||
Octstr *qf;
|
||||
Octstr *value2 = NULL, *rr_uri = NULL;
|
||||
List *rqh = http_create_empty_headers();
|
||||
|
||||
value = mms_get_header_value(msg, octstr_imm("X-Mms-Read-Status"));
|
||||
value2 = mms_get_header_value(msg, octstr_imm("X-Mbuni-Orig-Message-ID"));
|
||||
|
||||
rr_uri = mmsbox_get_report_info(msg, mmc, mmc_id, "read-report",
|
||||
value, rqh, NULL, 0, msgid);
|
||||
if (value2 && mmc_id == NULL)
|
||||
http_header_add(rqh, "X-Mbuni-Orig-Message-ID", octstr_get_cstr(value2));
|
||||
|
||||
|
||||
qf = qfs->mms_queue_add(from, to, NULL,
|
||||
mmc->id,mmc_id,
|
||||
0, time(NULL) + default_msgexpiry, msg, NULL,
|
||||
NULL, NULL,
|
||||
rr_uri, NULL,
|
||||
rqh,
|
||||
0,
|
||||
octstr_get_cstr(qdir),
|
||||
"MM7/MM4-IN",
|
||||
NULL);
|
||||
if (qf) {
|
||||
mms_log("Received RR", from, to, -1, msgid, value, mmc->id, "MMSBox", octstr_imm("smtp"), NULL);
|
||||
res = octstr_duplicate(qf);
|
||||
err = "Ok";
|
||||
MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_QUEUE_WRITE_ERROR);
|
||||
} else {
|
||||
err = "Error-network-problem";
|
||||
MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4);
|
||||
}
|
||||
octstr_destroy(qf);
|
||||
octstr_destroy(value2);
|
||||
octstr_destroy(rr_uri);
|
||||
http_destroy_headers(rqh);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case MM4_FORWARD_RES:
|
||||
case MM4_READ_REPLY_REPORT_RES:
|
||||
case MM4_DELIVERY_REPORT_RES: /* remove corresponding queue entry. */
|
||||
/* Do nothing */
|
||||
break;
|
||||
default:
|
||||
mms_warning(0, "MM4", xproxy, "Unexpected message type: %s",
|
||||
mm4_type ? octstr_get_cstr(mm4_type) : "not given!");
|
||||
break;
|
||||
}
|
||||
|
||||
mm7type = mm7_msgtype_to_soaptype(mm1_type,1);
|
||||
if (mm7type >= 0) /* Issue event call back */
|
||||
mmsbox_event_cb(mmc->id, mm7type, 1, octstr_imm("1.0"), 200,
|
||||
mms_msgsize(msg), 0, from,
|
||||
to && gwlist_len(to) > 0 ? gwlist_get(to,0) : NULL,
|
||||
msgid, transid, NULL, value);
|
||||
|
||||
/* respond to the sender as necessary. */
|
||||
if (mm4_type &&
|
||||
err &&
|
||||
ack && octstr_str_case_compare(ack, "Yes") == 0) {
|
||||
int size = send_mm4_res(mtype+1, orig_sys, me, transid, err, res, octstr_get_cstr(sendmail_cmd));
|
||||
|
||||
mmsbox_event_cb(mmc->id, mm7type >= 0 ? mm7type + 1 : MM7_TAG_VASPErrorRsp,
|
||||
1, octstr_imm("1.0"), 200,
|
||||
size, 0, me, orig_sys, res, NULL, NULL, NULL);
|
||||
}
|
||||
octstr_destroy(mm4_type);
|
||||
octstr_destroy(transid);
|
||||
octstr_destroy(orig_sys);
|
||||
octstr_destroy(msgid);
|
||||
|
||||
octstr_destroy(rstatus);
|
||||
octstr_destroy(ack);
|
||||
|
||||
octstr_destroy(me);
|
||||
|
||||
octstr_destroy(mmc_id);
|
||||
octstr_destroy(value);
|
||||
mms_destroy(msg);
|
||||
|
||||
done:
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void clean_address(Octstr **addr, int *isphone, Octstr **xproxy)
|
||||
{
|
||||
int i;
|
||||
|
||||
octstr_strip_blanks(*addr);
|
||||
*isphone = 1;
|
||||
if ((i = octstr_search_char(*addr, '<', 0)) >= 0) {
|
||||
octstr_delete(*addr, 0, i+1);
|
||||
|
||||
i = octstr_search_char(*addr, '>', 0);
|
||||
if (i > 0)
|
||||
octstr_delete(*addr, i, octstr_len(*addr));
|
||||
|
||||
}
|
||||
/* Find number type */
|
||||
i = octstr_case_search(*addr, octstr_imm("/TYPE="), 0);
|
||||
if (i>0) {
|
||||
int j = octstr_search_char(*addr, '@', 0);
|
||||
if (j > i) { /* we have @, remove it */
|
||||
*xproxy = octstr_copy(*addr, j+1, octstr_len(*addr));
|
||||
octstr_delete(*addr, j, octstr_len(*addr));
|
||||
}
|
||||
} else if (isphonenum(*addr)) /* Add the TYPE element if missing. */
|
||||
octstr_append(*addr, octstr_imm("/TYPE=PLMN"));
|
||||
else {
|
||||
i = octstr_search_char(*addr, '@', 0);
|
||||
if (i<0)
|
||||
octstr_format_append(*addr, "@unknown");
|
||||
else if (*xproxy == NULL)
|
||||
*xproxy = octstr_copy(*addr, i+1, octstr_len(*addr));
|
||||
*isphone = 0;
|
||||
}
|
||||
/* clean the number. */
|
||||
if (*isphone)
|
||||
_mms_fixup_address(addr,
|
||||
octstr_get_cstr(unified_prefix),
|
||||
strip_prefixes, 1);
|
||||
|
||||
}
|
||||
|
||||
static void smtp_process(int fd, Octstr *ip)
|
||||
{
|
||||
enum smtp_state_t {MLISTEN, MFROM, MTO, MDATA,MERROR};
|
||||
int i, state = MLISTEN;
|
||||
Connection *c = conn_wrap_fd(fd,0);
|
||||
Octstr *from = NULL;
|
||||
MmscGrp *mmc = NULL;
|
||||
List *to = NULL;
|
||||
Octstr *body = NULL;
|
||||
MIMEEntity *m = NULL;
|
||||
Octstr *line;
|
||||
|
||||
socket_set_blocking(fd,1); /* Because we want each line as it comes */
|
||||
|
||||
/* Issue greeting */
|
||||
line = octstr_format("220 %S SMTP Mbuni %s\r\n", myhostname, MMSC_VERSION);
|
||||
conn_write(c, line);
|
||||
octstr_destroy(line);
|
||||
|
||||
do {
|
||||
Octstr *res;
|
||||
Octstr *cmd = NULL, *arg = NULL;
|
||||
int stop, max_size;
|
||||
|
||||
line = conn_read_line(c);
|
||||
if (line == NULL)
|
||||
state = MERROR;
|
||||
else if (state != MDATA) {
|
||||
i = octstr_search_char(line, ' ', 0);
|
||||
if (i > 0) {
|
||||
cmd = octstr_copy(line, 0, i);
|
||||
arg = octstr_copy(line, i+1, octstr_len(line));
|
||||
} else {
|
||||
cmd = octstr_copy(line, 0, octstr_len(line));
|
||||
arg = octstr_create("");
|
||||
}
|
||||
octstr_strip_blanks(cmd);
|
||||
octstr_strip_blanks(arg);
|
||||
}
|
||||
switch(state) {
|
||||
|
||||
case MLISTEN:
|
||||
if (octstr_str_case_compare(cmd, "HELO") == 0)
|
||||
conn_write(c, octstr_imm("250 Hello and welcome\r\n")); /* ... and stay in same state */
|
||||
else if (octstr_str_case_compare(cmd, "MAIL") == 0) { /* Sender */
|
||||
if ((i = octstr_case_search(arg, octstr_imm("FROM:"), 0)) < 0) /* No From? */
|
||||
conn_write(c, octstr_imm("500 Error. Missing FROM:\r\n"));
|
||||
else {
|
||||
int isphone = 1;
|
||||
Octstr *xproxy = NULL;
|
||||
from = octstr_copy(arg, i+5, octstr_len(arg));
|
||||
|
||||
clean_address(&from, &isphone, &xproxy);
|
||||
|
||||
/* We now have the sender domain and the number. Find a matching MMSC */
|
||||
if (!isphone || xproxy == NULL)
|
||||
mmc = mmsbox_get_mmsc_by_url(octstr_imm("*"));
|
||||
else
|
||||
mmc = mmsbox_get_mmsc_by_url(xproxy);
|
||||
|
||||
/* Check that we have an mmsc and the sender IP is allowed. */
|
||||
if (mmc == NULL || xproxy == NULL ||
|
||||
!is_allowed_ip(mmc->incoming.allow_ip, mmc->incoming.deny_ip, ip)) {
|
||||
conn_write(c, octstr_imm("421 Sender not allowed\r\n"));
|
||||
state = MERROR;
|
||||
} else {
|
||||
|
||||
if (!mmc->strip_domain && isphone)
|
||||
octstr_format_append(from, "@%S", xproxy);
|
||||
conn_write(c, octstr_imm("250 Ok\r\n"));
|
||||
state = MTO;
|
||||
}
|
||||
octstr_destroy(xproxy);
|
||||
}
|
||||
} else
|
||||
conn_write(c, octstr_imm("500 Error.\r\n"));
|
||||
break;
|
||||
|
||||
case MTO:
|
||||
if (octstr_str_case_compare(cmd, "DATA") == 0) {
|
||||
if (gwlist_len(to) == 0) {
|
||||
conn_write(c, octstr_imm("421 No recipients? Go away!\r\n"));
|
||||
state = MERROR;
|
||||
} else {
|
||||
state = MDATA;
|
||||
conn_write(c, octstr_imm("354 Proceed\r\n"));
|
||||
body = octstr_create("");
|
||||
}
|
||||
} else if (octstr_str_case_compare(cmd, "RCPT") != 0) /* recipient */
|
||||
conn_write(c, octstr_imm("500 send recipient please\r\n")); /* ... and stay in same state */
|
||||
else if ((i = octstr_case_search(arg, octstr_imm("TO:"), 0)) < 0) /* No To? */
|
||||
conn_write(c, octstr_imm("500 send TO field\r\n")); /* ... and stay in same state */
|
||||
else { /* Got it. Clean it up */
|
||||
Octstr *xto = octstr_copy(arg, i+3, octstr_len(arg));
|
||||
int isphone = 1;
|
||||
Octstr *xproxy = NULL;
|
||||
|
||||
clean_address(&xto, &isphone, &xproxy);
|
||||
|
||||
if (mmc && !mmc->strip_domain && isphone && xproxy)
|
||||
octstr_format_append(from, "@%S", xproxy);
|
||||
|
||||
if (xproxy == NULL)
|
||||
conn_write(c, octstr_imm("500 send correct recipient please\r\n")); /* ... and stay in same state */
|
||||
else { /* Stay in same state */
|
||||
conn_write(c, octstr_imm("250 Ok\r\n")); /* Accept recipient */
|
||||
if (to == NULL)
|
||||
to = gwlist_create();
|
||||
gwlist_append(to, xto);
|
||||
xto = NULL;
|
||||
}
|
||||
octstr_destroy(xproxy);
|
||||
octstr_destroy(xto);
|
||||
}
|
||||
break;
|
||||
case MDATA:
|
||||
stop = 0;
|
||||
max_size = (mmc ? mmc->max_pkt_size : DEFAULT_MAX_PKT_SIZE);
|
||||
do {
|
||||
if (octstr_get_char(line, 0) == '.') {
|
||||
if (octstr_get_char(line, 1) != '.') {
|
||||
stop = 1;
|
||||
goto end_loop;
|
||||
} else
|
||||
octstr_delete(line, 0, 1); /* Remove period */
|
||||
}
|
||||
|
||||
if (octstr_len(body) < max_size)
|
||||
octstr_format_append(body, "%S\r\n", line);
|
||||
else if (octstr_len(body) == max_size)
|
||||
octstr_append_char(body, ' '); /* So we exceed length */
|
||||
end_loop:
|
||||
octstr_destroy(line);
|
||||
line = NULL; /* So no double free below */
|
||||
} while (!stop && !conn_eof(c) && (line = conn_read_line(c)) != NULL);
|
||||
|
||||
if (octstr_len(body) > max_size) {
|
||||
conn_write(c, octstr_imm("452 Message too large\r\n"));
|
||||
state = MERROR;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* We got message, time to process it */
|
||||
if ((m = mime_octstr_to_entity(body)) == NULL) {
|
||||
conn_write(c, octstr_imm("501 Invalid MIME content\r\n"));
|
||||
state = MERROR;
|
||||
goto loop;
|
||||
} else {
|
||||
octstr_destroy(body); /* Release space */
|
||||
body = NULL;
|
||||
}
|
||||
|
||||
if ((res = handle_msg(m, from, to, mmc)) != NULL) {
|
||||
Octstr *x = octstr_format("250 Ok: %S\r\n", res);
|
||||
|
||||
conn_write(c, x);
|
||||
octstr_destroy(x);
|
||||
octstr_destroy(res);
|
||||
} else
|
||||
conn_write(c, octstr_imm("451 Invalid message content\r\n"));
|
||||
state = MERROR; /* Not really, but we gotta go */
|
||||
break;
|
||||
default:
|
||||
/* Do nothing */
|
||||
break;
|
||||
}
|
||||
|
||||
loop:
|
||||
octstr_destroy(cmd);
|
||||
octstr_destroy(arg);
|
||||
octstr_destroy(line);
|
||||
} while (state != MERROR);
|
||||
|
||||
octstr_destroy(body);
|
||||
octstr_destroy(from);
|
||||
gwlist_destroy(to, (void *)octstr_destroy);
|
||||
if (m)
|
||||
mime_entity_destroy(m);
|
||||
|
||||
conn_destroy(c);
|
||||
if (mmc)
|
||||
return_mmsc_conn(mmc);
|
||||
return ;
|
||||
}
|
||||
|
||||
struct mm4_req_t {
|
||||
Octstr *ip;
|
||||
int fd;
|
||||
};
|
||||
|
||||
static List *slist = NULL; /* Request list */
|
||||
|
||||
static void smtp_thread(void *unused)
|
||||
{
|
||||
struct mm4_req_t *m;
|
||||
|
||||
while ((m = gwlist_consume(slist)) != NULL) {
|
||||
smtp_process(m->fd, m->ip);
|
||||
octstr_destroy(m->ip);
|
||||
gw_free(m);
|
||||
}
|
||||
}
|
||||
|
||||
void mm4_receive_func(int *sock)
|
||||
{
|
||||
int i, fd, tcount = 0;
|
||||
Octstr *ip;
|
||||
/* Start the threads, then receive requests, build, go */
|
||||
slist = gwlist_create();
|
||||
|
||||
gwlist_add_producer(slist);
|
||||
|
||||
for (i = 0; i < maxthreads; i++)
|
||||
if (gwthread_create((void *)smtp_thread, NULL) >= 0)
|
||||
tcount++;
|
||||
if (tcount > 0)
|
||||
while (!rstop && ((fd = gw_accept(*sock, &ip)) >= 0 ||
|
||||
errno == EINTR)) {
|
||||
struct mm4_req_t *m;
|
||||
|
||||
if (fd < 0)
|
||||
continue;
|
||||
|
||||
m = gw_malloc(sizeof *m);
|
||||
m->ip = ip;
|
||||
m->fd = fd;
|
||||
|
||||
gwlist_produce(slist, m);
|
||||
}
|
||||
else
|
||||
mms_error(0, "MM4", NULL, "Failed to start SMTP listener threads: %s!", strerror(errno));
|
||||
gwlist_remove_producer(slist);
|
||||
|
||||
gwthread_join_every((void *)smtp_thread);
|
||||
|
||||
gwlist_destroy(slist, NULL);
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ Octstr *mmsbox_get_report_info(MmsMsg *m, MmscGrp *mmsc, Octstr *out_mmc_id,
|
|||
Octstr *msgid);
|
||||
void mmsc_receive_func(MmscGrp *m);
|
||||
void mmsbox_outgoing_queue_runner(volatile sig_atomic_t *rstop);
|
||||
void mm4_receive_func(int *sock);
|
||||
|
||||
/* Just a convenience, should go away in future! */
|
||||
#define mmsbox_url_fetch_content mms_url_fetch_content
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "mmsbox_cfg.h"
|
||||
#include "mms_queue.h"
|
||||
#include "mmsbox_resolve_shell.h"
|
||||
#include "mmsbox.h"
|
||||
|
||||
#define WAIT_TIME 0.2
|
||||
|
||||
|
@ -54,11 +55,13 @@ static List *mmsc_del_list = NULL; /* List of items to be deleted. */
|
|||
/* admin handler variables. */
|
||||
static long admin_port;
|
||||
static long admin_thread = -1;
|
||||
static long mm4_thread = -1;
|
||||
static Octstr *admin_pass = NULL;
|
||||
static Octstr *admin_allow_ip = NULL;
|
||||
static Octstr *admin_deny_ip = NULL;
|
||||
|
||||
|
||||
static long mm4_port;
|
||||
static int mm4_sock;
|
||||
|
||||
struct SendMmsPortInfo sendmms_port = {-1};
|
||||
|
||||
|
@ -269,6 +272,19 @@ int mms_load_mmsbox_settings(struct mCfgImpFuncs *cfg_funcs, Octstr *init,
|
|||
sendmms_port.allow_ip = mms_cfg_get(cfg, grp, octstr_imm("allow-ip"));
|
||||
sendmms_port.deny_ip = mms_cfg_get(cfg, grp, octstr_imm("deny-ip"));
|
||||
|
||||
|
||||
/* Get MM4 port */
|
||||
mms_cfg_get_int(cfg, grp, octstr_imm("mm4-port"), &mm4_port);
|
||||
if (mm4_port > 0 && (mm4_sock = make_server_socket(mm4_port, NULL)) >= 0 &&
|
||||
(mm4_thread = gwthread_create((void *)mm4_receive_func, &mm4_sock)) < 0) {
|
||||
mms_error(0, "mmsbox", NULL, "Failed to start MM4 server thread: %s", strerror(errno));
|
||||
mm4_port = 0;
|
||||
|
||||
if (mm4_sock >= 0)
|
||||
close(mm4_sock);
|
||||
} else
|
||||
hmon->register_port(mm4_port);
|
||||
|
||||
/* load the filter if any. */
|
||||
if ((mt_filter = _mms_load_module(cfg, grp, "mmsbox-mt-filter-library", "mmsbox_mt_filter", NULL)) != NULL)
|
||||
mms_info(0, "mmsbox", NULL, "Loaded MT Filter [%s]", mt_filter->name);
|
||||
|
@ -525,12 +541,14 @@ static void mmsbox_stop_mmsc_conn_real(MmscGrp *mmc)
|
|||
{
|
||||
|
||||
if (mmc->type == CUSTOM_MMSC && mmc->fns
|
||||
&& mmc->custom_started) {
|
||||
&& mmc->started) {
|
||||
mmc->fns->stop_conn(mmc->data);
|
||||
mmc->custom_started = 0;
|
||||
} else if (mmc->incoming.port > 0) {
|
||||
mmc->started = 0;
|
||||
} else if (mmc->type == MM4_MMSC)
|
||||
mmc->started = 0;
|
||||
else if (mmc->incoming.port > 0) {
|
||||
http_close_port(mmc->incoming.port);
|
||||
hmon->unregister_port(mmc->incoming.port);
|
||||
hmon->unregister_port(mmc->incoming.port);
|
||||
MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_HTTP_DOWN, 1);
|
||||
if (mmc->threadid >= 0)
|
||||
gwthread_join(mmc->threadid);
|
||||
|
@ -546,9 +564,17 @@ static void mmsbox_start_mmsc_conn(MmscGrp *m, List *errors, List *warnings)
|
|||
if (m->fns == NULL ||
|
||||
m->fns->start_conn(m, qfs, unified_prefix, strip_prefixes, &m->data) != 0) {
|
||||
WARNING("MMSBox: Failed to start custom MMSC [%s]", octstr_get_cstr(m->id));
|
||||
m->custom_started = 0;
|
||||
m->started = 0;
|
||||
} else
|
||||
m->custom_started = 1;
|
||||
m->started = 1;
|
||||
} else if (m->type == MM4_MMSC) {
|
||||
if (mm4_port <= 0) /* Can't start */
|
||||
WARNING("MMSBox: Ca not start MM4 MMSC since MM4 port is not open"
|
||||
" MMSC %s: %s!",
|
||||
octstr_get_cstr(m->id),
|
||||
strerror(errno));
|
||||
else
|
||||
m->started = 1;
|
||||
} else {
|
||||
if (m->incoming.port > 0 &&
|
||||
http_open_port(m->incoming.port, m->incoming.ssl) < 0) {
|
||||
|
@ -615,7 +641,14 @@ static MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *warnings, List
|
|||
|
||||
m->incoming.allow_ip = mms_cfg_get(cfg, x, octstr_imm("allow-ip"));
|
||||
m->incoming.deny_ip = mms_cfg_get(cfg, x, octstr_imm("deny-ip"));
|
||||
|
||||
|
||||
if (mms_cfg_get_bool(cfg, x, octstr_imm("strip-domain"), &m->strip_domain) < 0)
|
||||
m->strip_domain = 1;
|
||||
|
||||
if (mms_cfg_get_int(cfg,x, octstr_imm("maximum-request-size"), &m->max_pkt_size) < 0 ||
|
||||
m->max_pkt_size <= 0)
|
||||
m->max_pkt_size = DEFAULT_MAX_PKT_SIZE;
|
||||
mms_info(0, "mmsbox", NULL,"Loaded MMSC[%s], allow=[%s], deny=[%s] group_id=[%s]",
|
||||
octstr_get_cstr(m->id),
|
||||
octstr_get_cstr(m->incoming.allow_ip),
|
||||
|
@ -641,6 +674,8 @@ static MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *warnings, List
|
|||
m->type = EAIF_MMSC;
|
||||
else if (octstr_case_compare(type, octstr_imm("soap")) == 0)
|
||||
m->type = SOAP_MMSC;
|
||||
else if (octstr_case_compare(type, octstr_imm("mm4")) == 0)
|
||||
m->type = MM4_MMSC;
|
||||
else if (octstr_case_compare(type, octstr_imm("http")) == 0)
|
||||
m->type = HTTP_MMSC;
|
||||
else if (octstr_case_compare(type, octstr_imm("custom")) == 0) {
|
||||
|
@ -743,6 +778,29 @@ static void delete_stale_mmsc(int delete_all)
|
|||
}
|
||||
}
|
||||
|
||||
MmscGrp *mmsbox_get_mmsc_by_url(Octstr *mmc_url)
|
||||
{
|
||||
List *l = dict_keys(mmscs);
|
||||
Octstr *key;
|
||||
MmscGrp *mmc = NULL;
|
||||
if (l)
|
||||
while ((key = gwlist_extract_first(l)) != NULL)
|
||||
if ((mmc = dict_get(mmscs, key)) != NULL &&
|
||||
octstr_compare(mmc_url, mmc->mmsc_url) == 0) {
|
||||
|
||||
MMSBOX_MMSC_MARK_INUSE(mmc); /* Vital! */
|
||||
octstr_destroy(key);
|
||||
break;
|
||||
} else {
|
||||
mmc = NULL;
|
||||
octstr_destroy(key);
|
||||
}
|
||||
|
||||
gwlist_destroy(l, (void *)octstr_destroy);
|
||||
|
||||
return mmc;
|
||||
}
|
||||
|
||||
int mmsbox_stop_mmsc(Octstr *mmc_id)
|
||||
{
|
||||
MmscGrp *mmc = dict_remove(mmscs, mmc_id); /* remove it so no one else can get it. */
|
||||
|
@ -762,12 +820,19 @@ int mmsbox_stop_mmsc(Octstr *mmc_id)
|
|||
int mmsbox_start_mmsc(Octstr *mmc_id)
|
||||
{
|
||||
int ret;
|
||||
MmscGrp *mmc = dict_get(mmscs, mmc_id); /* remove it so no one else can get it. */
|
||||
mCfgGrp *m;
|
||||
List *l = gwlist_create(), *r = gwlist_create();
|
||||
if (mmc == NULL)
|
||||
return -1;
|
||||
mmsbox_start_mmsc_conn(mmc, l, r);
|
||||
|
||||
gw_assert(cfg);
|
||||
|
||||
m = mms_get_multi_by_field(cfg,
|
||||
octstr_imm("mmsc"),
|
||||
octstr_imm("id"),
|
||||
mmc_id);
|
||||
if (m == NULL)
|
||||
return -1;
|
||||
|
||||
start_mmsc_from_conf(cfg, m, l, r);
|
||||
ret = gwlist_len(l) > 0 ? -1 : 0;
|
||||
|
||||
gwlist_destroy(l, (void *)octstr_destroy);
|
||||
|
@ -864,6 +929,7 @@ done:
|
|||
|
||||
void mmsbox_settings_cleanup(void)
|
||||
{
|
||||
rstop = 1;
|
||||
delete_stale_mmsc(1);
|
||||
|
||||
/* eventually we will destroy the object. For now, we only cleanup queue module. */
|
||||
|
@ -878,6 +944,15 @@ void mmsbox_settings_cleanup(void)
|
|||
gwthread_join(admin_thread);
|
||||
mms_info(0, "mmsbox", NULL,"Admin port on %d, shutdown", (int)admin_port);
|
||||
}
|
||||
|
||||
if (mm4_port > 0 && mm4_sock >= 0) {
|
||||
close(mm4_sock);
|
||||
|
||||
if (mm4_thread >= 0) {
|
||||
gwthread_wakeup(mm4_thread);
|
||||
gwthread_join(mm4_thread);
|
||||
}
|
||||
}
|
||||
cdrfs->cleanup();
|
||||
mms_event_logger_cleanup();
|
||||
mms_cfg_destroy(cfg); /* only delete at end of session. */
|
||||
|
@ -968,6 +1043,8 @@ static void append_mmsc_status(Octstr *rbody, MmscGrp *m, List *warnings)
|
|||
typ = "SOAP";
|
||||
else if (m->type == EAIF_MMSC)
|
||||
typ = "EAIF";
|
||||
else if (m->type == MM4_MMSC)
|
||||
typ = "MM4";
|
||||
else if (m->type == CUSTOM_MMSC)
|
||||
typ = "CUSTOM";
|
||||
else
|
||||
|
@ -1006,7 +1083,7 @@ static void append_mmsc_status(Octstr *rbody, MmscGrp *m, List *warnings)
|
|||
strcat(ubuf, tmp);
|
||||
}
|
||||
|
||||
if (m->type != CUSTOM_MMSC)
|
||||
if (m->type != CUSTOM_MMSC && m->type != MM4_MMSC)
|
||||
sprintf(xport, "%d", (int)m->incoming.port);
|
||||
else
|
||||
sprintf(xport, "n/a");
|
||||
|
|
|
@ -31,6 +31,7 @@ enum MmsBoxAlarms {
|
|||
MMSBOX_ALARM_MM7_PARSING_FAILURE,
|
||||
MMSBOX_ALARM_MM7_NON_200_RESULT,
|
||||
MMSBOX_ALARM_RETRIEVE_MMS_ERROR,
|
||||
MMSBOX_ALARM_MM4_PARSING_FAILURE,
|
||||
MMSBOX_ALARM_MAX_ALARM /* Must be last one */
|
||||
};
|
||||
|
||||
|
@ -48,7 +49,7 @@ typedef struct MmscGrp {
|
|||
} incoming; /* user, pass, port (and whether SSL) that MMSC uses to connect to us. */
|
||||
Octstr *allowed_prefix, *denied_prefix;
|
||||
Octstr *allowed_sender_prefix, *denied_sender_prefix;
|
||||
enum {UNKNOWN_MMSC = -1, CUSTOM_MMSC, SOAP_MMSC, EAIF_MMSC, HTTP_MMSC} type; /* type of connection. */
|
||||
enum {UNKNOWN_MMSC = -1, CUSTOM_MMSC, SOAP_MMSC, EAIF_MMSC, MM4_MMSC, HTTP_MMSC} type; /* type of connection. */
|
||||
double throughput; /* Max send rate. */
|
||||
long threadid; /* handler thread. */
|
||||
|
||||
|
@ -65,8 +66,7 @@ typedef struct MmscGrp {
|
|||
MmsBoxMmscFuncs *fns; /* pointer to functions for handling this mmsc connection type */
|
||||
Octstr *settings; /* settings for the above module. */
|
||||
void *data; /* data for above module. */
|
||||
int custom_started; /* set to 1 if custom mmc started. */
|
||||
|
||||
int started; /* Whether it is active */
|
||||
unsigned long mt_pdus; /* number of MT PDUs since start. */
|
||||
unsigned long mo_pdus; /* number of MO PDUs since start. */
|
||||
unsigned long mt_errors; /* number of MT errors since start */
|
||||
|
@ -78,8 +78,13 @@ typedef struct MmscGrp {
|
|||
time_t last_alarm[MMSBOX_ALARM_MAX_ALARM];
|
||||
int use_count; /* use counter. */
|
||||
time_t delete_after; /* used to control deletion of object -- not ver clean, but... */
|
||||
|
||||
long max_pkt_size;
|
||||
|
||||
int strip_domain; /* MM4 only */
|
||||
} MmscGrp;
|
||||
|
||||
#define DEFAULT_MAX_PKT_SIZE 1024*1024
|
||||
|
||||
#define MMSBOX_MMSC_MARK_INUSE(mmc) do {\
|
||||
mutex_lock((mmc)->mutex); \
|
||||
|
@ -229,7 +234,7 @@ int mmsbox_stop_mmsc(Octstr *mmc);
|
|||
|
||||
int mmsbox_start_mmsc(Octstr *mmc_id);
|
||||
|
||||
|
||||
MmscGrp *mmsbox_get_mmsc_by_url(Octstr *mmc_url);
|
||||
void mmsbox_stop_all_mmsc_conn(void);
|
||||
typedef struct MmsBoxHTTPClientInfo {
|
||||
HTTPClient *client;
|
||||
|
|
|
@ -22,21 +22,7 @@ static Octstr *xto;
|
|||
static Octstr *xproxy;
|
||||
|
||||
enum {TPLMN, TEMAIL, TOTHER} ttype;
|
||||
/* MM4 message types. */
|
||||
enum {MM4_FORWARD_REQ = 0, MM4_FORWARD_RES, MM4_READ_REPLY_REPORT_REQ,
|
||||
MM4_READ_REPLY_REPORT_RES, MM4_DELIVERY_REPORT_REQ, MM4_DELIVERY_REPORT_RES};
|
||||
static struct {
|
||||
char *mm4str;
|
||||
int mm1_type;
|
||||
} mm4_types[] = {
|
||||
{"MM4_forward.REQ", MMS_MSGTYPE_SEND_REQ},
|
||||
{"MM4_forward.RES",-1},
|
||||
{"MM4_read_reply_report.REQ", MMS_MSGTYPE_READ_REC_IND},
|
||||
{"MM4_read_reply_report.RES",-1},
|
||||
{"MM4_delivery_report.REQ",MMS_MSGTYPE_DELIVERY_IND},
|
||||
{"MM4_delivery_report.RES",-1},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
/* above indexed by types! */
|
||||
|
||||
static int find_own(int i, int argc, char *argv[]);
|
||||
|
@ -45,10 +31,9 @@ static void fixup_recipient(Octstr **host);
|
|||
static void fixup_sender(void);
|
||||
static void fixup_addresses(List *headers);
|
||||
|
||||
static void send_mm4_res(int mtype, Octstr *to, Octstr *sender, Octstr *transid, char *status, Octstr *msgid,
|
||||
Octstr *sendmail_cmd);
|
||||
|
||||
static void strip_quotes(Octstr *s);
|
||||
static void send_mm4_res(int mtype, Octstr *to, Octstr *sender,
|
||||
Octstr *transid, char *status, Octstr *msgid,
|
||||
Octstr *sendmail_cmd);
|
||||
|
||||
static List *proxyrelays;
|
||||
static int no_strip = 0, strip_type = 0;
|
||||
|
@ -619,44 +604,13 @@ static void fixup_sender(void)
|
|||
octstr_format_append(xfrom, "@%S", xproxy);
|
||||
}
|
||||
|
||||
static void fixup_address_type(List *headers, char *hdr)
|
||||
{
|
||||
List *l;
|
||||
int i, n;
|
||||
|
||||
l = http_header_find_all(headers, hdr);
|
||||
|
||||
http_header_remove_all(headers,hdr);
|
||||
for (i = 0, n = gwlist_len(l); i<n; i++) {
|
||||
Octstr *name, *value;
|
||||
int j, k;
|
||||
http_header_get(l, i, &name, &value);
|
||||
|
||||
if (!value || !name ||
|
||||
octstr_case_compare(name, octstr_imm(hdr)) != 0)
|
||||
goto loop;
|
||||
if ((j = octstr_search(value, octstr_imm("/TYPE="), 0))>0) {
|
||||
k = octstr_search_char(value, '@', 0);
|
||||
if (k > j) { /* we have @, after TYPE=PLMN remove it */
|
||||
octstr_delete(value, k, octstr_len(value));
|
||||
}
|
||||
}
|
||||
_mms_fixup_address(&value,
|
||||
octstr_get_cstr(settings->unified_prefix),
|
||||
settings->strip_prefixes, 1);
|
||||
|
||||
http_header_add(headers, octstr_get_cstr(name), octstr_get_cstr(value));
|
||||
loop:
|
||||
octstr_destroy(value);
|
||||
octstr_destroy(name);
|
||||
}
|
||||
http_destroy_headers(l);
|
||||
}
|
||||
|
||||
static void fixup_addresses(List *headers)
|
||||
{
|
||||
fixup_address_type(headers, "To");
|
||||
fixup_address_type(headers, "From");
|
||||
fixup_address_type(headers, "To",
|
||||
octstr_get_cstr(settings->unified_prefix), settings->strip_prefixes);
|
||||
fixup_address_type(headers, "From",
|
||||
octstr_get_cstr(settings->unified_prefix), settings->strip_prefixes);
|
||||
}
|
||||
|
||||
static void send_mm4_res(int mtype, Octstr *to, Octstr *sender, Octstr *transid, char *status, Octstr *msgid,
|
||||
|
@ -692,18 +646,3 @@ static void send_mm4_res(int mtype, Octstr *to, Octstr *sender, Octstr *transid,
|
|||
}
|
||||
mime_entity_destroy(m);
|
||||
}
|
||||
|
||||
static void strip_quotes(Octstr *s)
|
||||
{
|
||||
int l = s ? octstr_len(s) : 0;
|
||||
|
||||
if (l == 0)
|
||||
return;
|
||||
if (octstr_get_char(s, 0) == '"') {
|
||||
octstr_delete(s, 0, 1);
|
||||
l--;
|
||||
}
|
||||
if (octstr_get_char(s, l-1) == '"')
|
||||
octstr_delete(s, l-1, 1);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue