1
0
Fork 0

pluggable mmsc types

This commit is contained in:
bagyenda 2007-09-19 13:06:26 +00:00
parent 970badf660
commit e76995ab27
12 changed files with 156 additions and 43 deletions

View File

@ -1,3 +1,5 @@
2007-09-18 P. A. Bagyenda <bagyenda@dsmagic.com>
* Support for custom MM7 MMC types using a loadable module.
2007-09-17 P. A. Bagyenda <bagyenda@dsmagic.com>
* Added pluggable MMSBOX routing using loadable module or shell script (see mmsbox_resolve.h)
2007-09-14 P. A. Bagyenda <bagyenda@dsmagic.com>

View File

@ -2100,8 +2100,10 @@ Supported configuration parameters are:
</td>
<td valign=top >
Mandatory:
Protocol spoken by this MMSC, one of <tt>soap</tt> (for 3GPP MM7
SOAP) or <tt>eaif</tt> for Nokia EAIF protocol.
Protocol spoken by this MMSC, one of <tt>soap</tt> for 3GPP MM7
SOAP, <tt>eaif</tt> for Nokia EAIF protocol or <tt>custom</tt> for
a custom implementation handled by a loadable module (see
<tt>mmsc-library</tt> below)
</td>
</tr>
@ -2315,6 +2317,36 @@ string
</td>
</tr>
<tr>
<td valign=top >
<tt>mmsc-library</tt>
</td>
<td valign=top >
String
</td>
<td valign=top >
If MMC type is <tt>custom</tt>, this parameter provides the dynamic
shared object (DSO) library to be loaded to provide connectivity to
the MMC. (See <tt>mmsbox_mmsc.h</tt> for details on required
exported symbols.)
</td>
</tr>
<tr>
<td valign=top >
<tt>custom-settings</tt>
</td>
<td valign=top >
String
</td>
<td valign=top >
If MMC type is <tt>custom</tt>, this parameter provides settings to
be provided to the dynamic
shared object (DSO) library loaded to provide connectivity to
the MMC. (See <tt>mmsbox_mmsc.h</tt> for details on how this is used.)
</td>
</tr>
</table>

View File

@ -795,17 +795,16 @@ static void pgdeliver(List *item_list)
while ((d = gwlist_consume(item_list)) != NULL) {
MmsEnvelope *e = pgq_queue_readenvelope(d->qf, d->dir, 0);
int res;
time_t tnow = time(NULL);
if (e && e->sendt <= tnow) {
if (e) { /* no need to check time -- it was checked in queue runner, so we know it's time to send.*/
debug("pgqueue_run", 0, "Queued entry %s/%s to thread %ld",
d->dir, d->qf, gwthread_self());
res = d->deliver(e);
if (res != 1)
pgq_free_envelope(e, 0);
} else if (e)
pgq_free_envelope(e, 0);
}
gw_free(d);
}
/* we're done, exit. */

View File

@ -140,6 +140,8 @@ MULTI_GROUP(mmsc,
OCTSTR(mm7-mt-filter-params)
OCTSTR(reroute)
OCTSTR(reroute-mmsc-id)
OCTSTR(mmsc-library)
OCTSTR(custom-settings)
)
MULTI_GROUP(mms-service,

View File

@ -1033,6 +1033,12 @@ static int fixup_msg(MmsMsg *m, Octstr *from)
} else
octstr_destroy(s);
/* check for transaction ID. */
if ((s = http_header_value(m->headers, octstr_imm("X-Mms-Transaction-ID"))) == NULL) {
if (m->message_type != MMS_MSGTYPE_RETRIEVE_CONF)
http_header_add(m->headers, "X-Mms-Transaction-ID", "00001");
octstr_destroy(s);
}
#if 0 /* This will be done elsewhere. */
/* Check for msgid, put in if missing. */
if ((s = http_header_value(m->headers, octstr_imm("Message-ID"))) == NULL)

View File

@ -4,4 +4,4 @@ bin_PROGRAMS = mmsbox
mmsbox_SOURCES = mmsbox.c mmsbox_cfg.c dlr.c bearerbox.c mmsbox_resolve.c mmsbox_resolve_shell.c
mmsbox_LDADD = $(libmms)
EXTRA_DIST = mmsbox_cfg.h mmsbox.h mmsbox_mt_filter.h mmsbox_resolve.h
EXTRA_DIST = mmsbox_cfg.h mmsbox.h mmsbox_mt_filter.h mmsbox_resolve.h mmsbox_mmsc.h

View File

@ -3,7 +3,7 @@
*
* MMSC handler functions: Receive and send MMS messages to MMSCs
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2007, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -74,7 +74,7 @@ done:
return res;
}
static int send_report(Octstr *from, char *report_type,
int mmsbox_send_report(Octstr *from, char *report_type,
Octstr *dlr_url, Octstr *status,
Octstr *msgid, Octstr *mmc_id, Octstr *mmc_gid,
Octstr *orig_transid, Octstr *uaprof,
@ -257,7 +257,7 @@ static void mm7soap_receive(MmsHTTPClientInfo *h)
info(0, "Sending delivery-report [FROM:%s] [VALUE:%s] [DESC:%s] [MSGID:%s]",
octstr_get_cstr(from), octstr_get_cstr(value), octstr_get_cstr(desc),
octstr_get_cstr(h->m->id));
send_report(from, "delivery-report", NULL,
mmsbox_send_report(from, "delivery-report", NULL,
value, msgid, h->m->id, h->m->group_id, NULL, uaprof, uaprof_tstamp);
mms_log("DeliveryReport",
@ -293,7 +293,7 @@ static void mm7soap_receive(MmsHTTPClientInfo *h)
Octstr *value = mm7_soap_header_value(mreq, octstr_imm("MMStatus"));
msgid = mm7_soap_header_value(mreq, octstr_imm("MessageID"));
send_report(from,
mmsbox_send_report(from,
"read-report", NULL, value, msgid,
h->m->id, h->m->group_id, NULL, uaprof, uaprof_tstamp);
@ -475,7 +475,7 @@ static void mm7eaif_receive(MmsHTTPClientInfo *h)
} else {
Octstr *value = http_header_value(mh, octstr_imm("X-Mms-Status"));
Octstr *value2 = http_header_value(mh, octstr_imm("Message-ID"));
send_report(hfrom, "delivery-report", NULL, value, value2, h->m->id, h->m->group_id, NULL, NULL, -1);
mmsbox_send_report(hfrom, "delivery-report", NULL, value, value2, h->m->id, h->m->group_id, NULL, NULL, -1);
octstr_destroy(value);
octstr_destroy(value2);
@ -503,7 +503,7 @@ static void mm7eaif_receive(MmsHTTPClientInfo *h)
} else {
Octstr *value = http_header_value(mh, octstr_imm("X-Mms-Read-Status"));
Octstr *value2 = http_header_value(mh, octstr_imm("Message-ID"));
send_report(hfrom, "read-report", NULL, value, value2, h->m->id,
mmsbox_send_report(hfrom, "read-report", NULL, value, value2, h->m->id,
h->m->group_id, NULL, NULL, -1);
@ -556,7 +556,7 @@ void mmsc_receive_func(MmscGrp *m)
m->incoming.port);
/* Dump headers, url etc. */
#if 1
#if 0
http_header_dump(h.headers);
if (h.body) octstr_dump(h.body, 0);
if (h.ip) octstr_dump(h.ip, 0);
@ -848,6 +848,10 @@ static int mms_sendtommsc(MmscGrp *mmc, Octstr *from, Octstr *to, Octstr *transi
id = mm7soap_send(mmc, from, to, transid, linkedid, vasid, service_code, hdrs, m, err, &retry);
else if (mmc->type == EAIF_MMSC)
id = mm7eaif_send(mmc, from, to, transid, vasid, hdrs, m, err, &retry);
else if (mmc->type == CUSTOM_MMSC && mmc->custom_started)
id = mmc->fns->send_msg(mmc->data,
from, to, transid, linkedid, vasid,
service_code, m, hdrs, err, &retry);
else
error(0, "MMC[%s] of unknown type, can't send!",
mmc->id ? octstr_get_cstr(mmc->id) : "");
@ -931,11 +935,11 @@ static int sendMsg(MmsEnvelope *e)
done:
if (res == MMS_SEND_OK) {
to->process = 0;
send_report(to->rcpt, "delivery-report", e->url1,
mmsbox_send_report(to->rcpt, "delivery-report", e->url1,
octstr_imm("Sent"), new_msgid, mmc->id, mmc->group_id, otransid, NULL, -1);
} else if (res == MMS_SEND_ERROR_FATAL && mmc)
send_report(to->rcpt, "delivery-report",
mmsbox_send_report(to->rcpt, "delivery-report",
e->url1,
(e->expiryt != 0 && e->expiryt < tnow) ?
octstr_imm("Expired") : octstr_imm("Rejected"),

View File

@ -29,15 +29,18 @@ static void quit_now(int notused)
MmscGrp *mmc;
rstop = 1;
/* Close all MMSC http ports, kill all MMSC threads, kill sendmms port... */
/* Close all MMSC http ports, kill all MMSC threads, kill sendmms port... */
if (sendmms_port.port > 0)
http_close_port(sendmms_port.port);
for (i = 0, n = gwlist_len(mmscs); i < n; i++)
if ((mmc = gwlist_get(mmscs, i)) != NULL &&
mmc->incoming.port > 0)
http_close_port(mmc->incoming.port);
if ((mmc = gwlist_get(mmscs, i)) != NULL) {
if (mmc->type == CUSTOM_MMSC && mmc->fns && mmc->custom_started) {
mmc->fns->stop_conn(mmc->data);
mmc->custom_started = 0;
} else if (mmc->incoming.port > 0)
http_close_port(mmc->incoming.port);
}
}
/* manage the SIGHUP signal */

View File

@ -18,6 +18,11 @@ extern int rstop;
void mms_dlr_url_put(Octstr *msgid, char *rtype, Octstr *mmc_gid, Octstr *dlr_url, Octstr *transid);
int mms_dlr_url_get(Octstr *msgid, char *rtype, Octstr *mmc_gid, Octstr **dlr_url, Octstr **transid);
void mms_dlr_url_remove(Octstr *msgid, char *rtype, Octstr *mmc_gid);
int mmsbox_send_report(Octstr *from, char *report_type,
Octstr *dlr_url, Octstr *status,
Octstr *msgid, Octstr *mmc_id, Octstr *mmc_gid,
Octstr *orig_transid, Octstr *uaprof,
time_t uaprof_tstamp);
void mmsc_receive_func(MmscGrp *m);
void mmsbox_outgoing_queue_runner(int *rstop);

View File

@ -215,7 +215,13 @@ int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func)
m->type = EAIF_MMSC;
else if (octstr_case_compare(type, octstr_imm("soap")) == 0)
m->type = SOAP_MMSC;
else
else if (octstr_case_compare(type, octstr_imm("custom")) == 0) {
m->type = CUSTOM_MMSC;
m->settings = _mms_cfg_getx(x, octstr_imm("custom-settings"));
/* also load the libary. */
if ((m->fns = _mms_load_module(x, "mmsc-library", "mmsc_funcs", NULL)) == NULL)
panic(0, "failed to load MMSC libary functions from module!");
} else
warning(0, "MMSBox: Unknown MMSC type [%s]!",
octstr_get_cstr(type));
if ((xver = _mms_cfg_getx(x, octstr_imm("mm7-version"))) != NULL &&
@ -244,22 +250,6 @@ int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func)
octstr_destroy(xver);
octstr_destroy(type);
if (m->incoming.port > 0 &&
http_open_port(m->incoming.port, ssl) < 0) {
warning(0, "MMSBox: Failed to start HTTP server on receive port for "
" MMSC %s, port %ld: %s!",
octstr_get_cstr(m->id), m->incoming.port,
strerror(errno));
m->incoming.port = 0; /* so we don't listen on it. */
}
if (mmsc_handler_func && m->incoming.port > 0) { /* Only start threads if func passed and ... */
if ((m->threadid = gwthread_create(mmsc_handler_func, m)) < 0)
error(0, "MMSBox: Failed to start MMSC handler thread for MMSC[%s]: %s!",
octstr_get_cstr(m->id), strerror(errno));
} else
m->threadid = -1;
/* Init for filter. */
if ((s = mms_cfg_get(x, octstr_imm("mm7-mt-filter-params"))) != NULL) {
if (mt_filter)
@ -281,6 +271,32 @@ int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func)
warning(0, "MMSBox: reroute-mmsc-id parameter set but reroute=false!");
m->mutex = mutex_create();
/* finally start the thingie. */
if (m->type == CUSTOM_MMSC) {
if (m->fns->start_conn(m, qfs, &m->data) != 0) {
warning(0, "MMSBox: Failed to start custom MMSC [%s]", octstr_get_cstr(m->id));
m->custom_started = 0;
} else
m->custom_started = 1;
} else {
if (m->incoming.port > 0 &&
http_open_port(m->incoming.port, ssl) < 0) {
warning(0, "MMSBox: Failed to start HTTP server on receive port for "
" MMSC %s, port %ld: %s!",
octstr_get_cstr(m->id), m->incoming.port,
strerror(errno));
m->incoming.port = 0; /* so we don't listen on it. */
}
if (mmsc_handler_func && m->incoming.port > 0) { /* Only start threads if func passed and ... */
if ((m->threadid = gwthread_create(mmsc_handler_func, m)) < 0)
error(0, "MMSBox: Failed to start MMSC handler thread for MMSC[%s]: %s!",
octstr_get_cstr(m->id), strerror(errno));
} else
m->threadid = -1;
}
gwlist_append(mmscs, m);
}
gwlist_destroy(l, NULL);
@ -468,9 +484,6 @@ MmscGrp *get_handler_mmc(Octstr *id, Octstr *to)
Octstr *get_mmsbox_queue_dir(Octstr *from, List *to, MmscGrp *m,
Octstr **mmc_id) {
*mmc_id = octstr_imm("local");
return outgoing_qdir;
if (m->reroute) {
*mmc_id = octstr_duplicate(m->reroute_mmsc_id);
return outgoing_qdir;

View File

@ -3,7 +3,7 @@
*
* MMSBOX CFG: MMC configuration and misc. functions
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2007, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -17,6 +17,8 @@
#include "mms_queue.h"
#include "mmsbox_resolve.h"
#include "mmsbox_mmsc.h"
typedef struct MmscGrp {
Octstr *id; /* MMSC id (for logging). */
Octstr *group_id; /* GROUP MMSC id (used for qf). */
@ -28,7 +30,7 @@ typedef struct MmscGrp {
long port;
} incoming; /* user, pass, port (and whether SSL) that MMSC uses to connect to us. */
Octstr *allowed_prefix, *denied_prefix;
enum {UNKNOWN_MMSC, SOAP_MMSC, EAIF_MMSC} type; /* type of connection. */
enum {UNKNOWN_MMSC = -1, CUSTOM_MMSC, SOAP_MMSC, EAIF_MMSC} type; /* type of connection. */
long throughput; /* Max send rate. */
long threadid; /* handler thread. */
@ -37,6 +39,11 @@ typedef struct MmscGrp {
MM7Version_t ver; /* supported MM7/SOAP version. */
int use_mt_filter; /* whether to use MT filter on this connection. */
Mutex *mutex;
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. */
} MmscGrp;
typedef struct MmsServiceUrlParam {

View File

@ -0,0 +1,40 @@
/*
* Mbuni - Open Source MMS Gateway
*
* MMSBOX Custom MMSC types: MMC function definitions
*
* Copyright (C) 2003 - 2007, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MMSBOX_MMSC_CFG_INCLUDED__
#define __MMSBOX_MMSC_CFG_INCLUDED__
#include "mms_util.h"
#include "mms_queue.h"
struct MmscGrp; /* so we compile. */
typedef struct MmsBoxMmscFuncs {
/* start_conn: called once with the module settings, ID of the connection
* and a pointer where to store module specific info.
* should return 0 on success, -1 on error.
*/
int (*start_conn)(struct MmscGrp *mmc, MmsQueueHandlerFuncs *qfs, void **data);
/* stop_conn: Called to stop the MMC connection. */
int (*stop_conn)(void *data);
/* send_msg: called to send a message. Should msg ID if any. On error,
* retry can be set to 1 for sending to be retried later.
* Should set err to the error message (if any).
*/
Octstr *(*send_msg)(void *data, Octstr *from, Octstr *to,
Octstr *transid,
Octstr *linkedid, char *vasid, Octstr *service_code,
MmsMsg *m, List *hdrs, Octstr **err, int *retry);
} MmsBoxMmscFuncs;
extern MmsBoxMmscFuncs mmsc_funcs; /* lib should expose this structure. */
#endif