From e76995ab279d0e1b267b061ad63ef758cd7883c5 Mon Sep 17 00:00:00 2001 From: bagyenda <> Date: Wed, 19 Sep 2007 13:06:26 +0000 Subject: [PATCH] pluggable mmsc types --- mbuni/ChangeLog | 2 + mbuni/doc/userguide.shtml | 36 ++++++++++++++- mbuni/extras/pgsql-queue/mms_pgsql_queue.c | 7 ++- mbuni/mmlib/mms_cfg.def | 2 + mbuni/mmlib/mms_msg.c | 6 +++ mbuni/mmsbox/Makefile.am | 2 +- mbuni/mmsbox/bearerbox.c | 22 +++++---- mbuni/mmsbox/mmsbox.c | 13 ++++-- mbuni/mmsbox/mmsbox.h | 5 ++ mbuni/mmsbox/mmsbox_cfg.c | 53 ++++++++++++++-------- mbuni/mmsbox/mmsbox_cfg.h | 11 ++++- mbuni/mmsbox/mmsbox_mmsc.h | 40 ++++++++++++++++ 12 files changed, 156 insertions(+), 43 deletions(-) create mode 100644 mbuni/mmsbox/mmsbox_mmsc.h diff --git a/mbuni/ChangeLog b/mbuni/ChangeLog index bb574e9..1a33b76 100644 --- a/mbuni/ChangeLog +++ b/mbuni/ChangeLog @@ -1,3 +1,5 @@ +2007-09-18 P. A. Bagyenda + * Support for custom MM7 MMC types using a loadable module. 2007-09-17 P. A. Bagyenda * Added pluggable MMSBOX routing using loadable module or shell script (see mmsbox_resolve.h) 2007-09-14 P. A. Bagyenda diff --git a/mbuni/doc/userguide.shtml b/mbuni/doc/userguide.shtml index f2a9028..9b62112 100644 --- a/mbuni/doc/userguide.shtml +++ b/mbuni/doc/userguide.shtml @@ -2100,8 +2100,10 @@ Supported configuration parameters are: Mandatory: - Protocol spoken by this MMSC, one of soap (for 3GPP MM7 - SOAP) or eaif for Nokia EAIF protocol. + Protocol spoken by this MMSC, one of soap for 3GPP MM7 + SOAP, eaif for Nokia EAIF protocol or custom for + a custom implementation handled by a loadable module (see + mmsc-library below) @@ -2315,6 +2317,36 @@ string + + + mmsc-library + + + String + + + If MMC type is custom, this parameter provides the dynamic + shared object (DSO) library to be loaded to provide connectivity to + the MMC. (See mmsbox_mmsc.h for details on required + exported symbols.) + + + + + + custom-settings + + + String + + + If MMC type is custom, this parameter provides settings to + be provided to the dynamic + shared object (DSO) library loaded to provide connectivity to + the MMC. (See mmsbox_mmsc.h for details on how this is used.) + + + diff --git a/mbuni/extras/pgsql-queue/mms_pgsql_queue.c b/mbuni/extras/pgsql-queue/mms_pgsql_queue.c index 9e4f721..6e9d84e 100644 --- a/mbuni/extras/pgsql-queue/mms_pgsql_queue.c +++ b/mbuni/extras/pgsql-queue/mms_pgsql_queue.c @@ -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. */ diff --git a/mbuni/mmlib/mms_cfg.def b/mbuni/mmlib/mms_cfg.def index 5d98c4a..c68693e 100644 --- a/mbuni/mmlib/mms_cfg.def +++ b/mbuni/mmlib/mms_cfg.def @@ -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, diff --git a/mbuni/mmlib/mms_msg.c b/mbuni/mmlib/mms_msg.c index cf0568c..6eadd42 100644 --- a/mbuni/mmlib/mms_msg.c +++ b/mbuni/mmlib/mms_msg.c @@ -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) diff --git a/mbuni/mmsbox/Makefile.am b/mbuni/mmsbox/Makefile.am index 7556684..7ecbf8d 100644 --- a/mbuni/mmsbox/Makefile.am +++ b/mbuni/mmsbox/Makefile.am @@ -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 diff --git a/mbuni/mmsbox/bearerbox.c b/mbuni/mmsbox/bearerbox.c index a2772af..9015bd9 100644 --- a/mbuni/mmsbox/bearerbox.c +++ b/mbuni/mmsbox/bearerbox.c @@ -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 * @@ -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"), diff --git a/mbuni/mmsbox/mmsbox.c b/mbuni/mmsbox/mmsbox.c index f4150d1..9862a86 100644 --- a/mbuni/mmsbox/mmsbox.c +++ b/mbuni/mmsbox/mmsbox.c @@ -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 */ diff --git a/mbuni/mmsbox/mmsbox.h b/mbuni/mmsbox/mmsbox.h index 340f9e5..279b2db 100644 --- a/mbuni/mmsbox/mmsbox.h +++ b/mbuni/mmsbox/mmsbox.h @@ -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); diff --git a/mbuni/mmsbox/mmsbox_cfg.c b/mbuni/mmsbox/mmsbox_cfg.c index dc2d44b..9208482 100644 --- a/mbuni/mmsbox/mmsbox_cfg.c +++ b/mbuni/mmsbox/mmsbox_cfg.c @@ -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; diff --git a/mbuni/mmsbox/mmsbox_cfg.h b/mbuni/mmsbox/mmsbox_cfg.h index e67c156..b66bfde 100644 --- a/mbuni/mmsbox/mmsbox_cfg.h +++ b/mbuni/mmsbox/mmsbox_cfg.h @@ -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 * @@ -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 { diff --git a/mbuni/mmsbox/mmsbox_mmsc.h b/mbuni/mmsbox/mmsbox_mmsc.h new file mode 100644 index 0000000..49f7f5c --- /dev/null +++ b/mbuni/mmsbox/mmsbox_mmsc.h @@ -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 + * + * 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