diff --git a/mbuni/ChangeLog b/mbuni/ChangeLog index ebdef46..bb574e9 100644 --- a/mbuni/ChangeLog +++ b/mbuni/ChangeLog @@ -1,3 +1,5 @@ +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 * Added http-interface-name config parameter 2007-09-06 P. A. Bagyenda diff --git a/mbuni/doc/userguide.shtml b/mbuni/doc/userguide.shtml index aee9d58..f2a9028 100644 --- a/mbuni/doc/userguide.shtml +++ b/mbuni/doc/userguide.shtml @@ -1281,7 +1281,7 @@ lists all the configuration directives. The column Mode     - MMSC + ALL     @@ -1291,11 +1291,14 @@ lists all the configuration directives. The column Mode Optional library containing functions for resolving recipient MSISDN to hostname - of Proxy-Relay that should handle the message. Supplying this libary + of Proxy-Relay that should handle the message (on the MMC side) or + the connected MMC that should (internally) route an incoming MM7 + message (on the MMSBOX side).
For Mbun MMSC, supplying this libary over-rides the local-prefixes setting given above. If the Proxy-Relay hostname returned by the module is the hostname of the local MMSC, then the recipient is considered local. See - mms_resolve.h for details. (mms_resolve.h for details. (See mmsbox_resolve.h for usage under + mmsbox). (builtin:shell supported as a special built-in library.)     @@ -1306,7 +1309,7 @@ lists all the configuration directives. The column Mode     - MMSC + ALL     @@ -1641,7 +1644,7 @@ Mbuni supports one type of built-in modules: Shell script destination address to determine how to deliver the message. The script is invoked with one command line parameter (the destination address) and should output (on standard output) the hostname of the - home MMSC, to which the message should be routed. + home MMSC (or MM7 connection ID in the case of mmsbox), to which the message should be routed.
  • If detokenizer-library is set to builtin:shell then detokenizer-module-parameters should be set to the script that should be called to resolve the last part of the MM1 diff --git a/mbuni/mmlib/mms_util.c b/mbuni/mmlib/mms_util.c index db55512..e2e2589 100644 --- a/mbuni/mmlib/mms_util.c +++ b/mbuni/mmlib/mms_util.c @@ -1674,3 +1674,45 @@ void strip_non_essential_headers(MIMEEntity *mime) http_destroy_headers(h2); } + +void *_mms_load_module(mCfgGrp *grp, char *config_key, char *symbolname, + void *shell_builtin) +{ + Octstr *s = NULL; + void *retval = NULL; + + s = mms_cfg_get(grp, octstr_imm(config_key)); + + if (s) { + void *x; + void *y = NULL; +#ifdef __APPLE__ + char sbuf[512]; +#endif + /* First look for the builtin: keyword. + * For now only builtin:shell is supported. + */ + if (octstr_case_search(s, octstr_imm("builtin:shell"), 0) >= 0) + retval = shell_builtin; + else { + x = dlopen(octstr_get_cstr(s), RTLD_LAZY); +#ifdef __APPLE__ + sprintf(sbuf, "_%s", symbolname); +#endif + if (x == NULL || ((y = dlsym(x, symbolname)) == NULL +#ifdef __APPLE__ /* fink version of dlsym has issues it seems. */ + && (y = dlsym(x, sbuf)) == NULL +#endif + )) + + panic(0, "Unable to load dynamic libary (%s): %s", + octstr_get_cstr(s), + dlerror()); + else + retval = y; + } + octstr_destroy(s); + } + + return retval; +} diff --git a/mbuni/mmlib/mms_util.h b/mbuni/mmlib/mms_util.h index 0de6761..f563c17 100644 --- a/mbuni/mmlib/mms_util.h +++ b/mbuni/mmlib/mms_util.h @@ -198,6 +198,9 @@ int has_node_children(xmlNodePtr node); /* strip non-essential headers from top-level */ void strip_non_essential_headers(MIMEEntity *mime); +/* load a shared object, then load a symbol from it. */ +void *_mms_load_module(mCfgGrp *grp, char *config_key, char *symbolname, + void *shell_builtin); #define MAXQTRIES 100 #define BACKOFF_FACTOR 5*60 /* In seconds */ #define QUEUERUN_INTERVAL 1*60 /* 1 minutes. */ diff --git a/mbuni/mmsbox/Makefile.am b/mbuni/mmsbox/Makefile.am index 12d8f60..7556684 100644 --- a/mbuni/mmsbox/Makefile.am +++ b/mbuni/mmsbox/Makefile.am @@ -1,7 +1,7 @@ libmms = $(top_builddir)/mmlib/libmms.a bin_PROGRAMS = mmsbox -mmsbox_SOURCES = mmsbox.c mmsbox_cfg.c dlr.c bearerbox.c +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 +EXTRA_DIST = mmsbox_cfg.h mmsbox.h mmsbox_mt_filter.h mmsbox_resolve.h diff --git a/mbuni/mmsbox/bearerbox.c b/mbuni/mmsbox/bearerbox.c index 8ec9d73..a2772af 100644 --- a/mbuni/mmsbox/bearerbox.c +++ b/mbuni/mmsbox/bearerbox.c @@ -142,7 +142,7 @@ static void mm7soap_receive(MmsHTTPClientInfo *h) MSoapMsg_t *mreq = NULL, *mresp = NULL; int hstatus = HTTP_OK; List *rh = NULL; - Octstr *reply_body = NULL, *value, *desc; + Octstr *reply_body = NULL; List *to = NULL; Octstr *from = NULL, *subject = NULL, *vasid = NULL, *msgid = NULL, *uaprof = NULL; @@ -150,8 +150,8 @@ static void mm7soap_receive(MmsHTTPClientInfo *h) MmsMsg *m = NULL; int status = 1000; unsigned char *msgtype = (unsigned char *)""; - Octstr *qf = NULL; - + Octstr *qf = NULL, *mmc_id = NULL, *qdir = NULL; + if (h->body) mreq = mm7_parse_soap(h->headers, h->body); if (mreq) @@ -171,17 +171,18 @@ static void mm7soap_receive(MmsHTTPClientInfo *h) if (!from) from = octstr_imm("anon@anon"); + qdir = get_mmsbox_queue_dir(from, to, h->m, &mmc_id); /* get routing info. */ + switch (mm7_msgtype(mreq)) { case MM7_TAG_DeliverReq: m = mm7_soap_to_mmsmsg(mreq, from); if (m) { - Octstr *value = NULL; /* Store linked id so we use it in response. */ Octstr *linkedid = mm7_soap_header_value(mreq, octstr_imm("LinkedID")); List *qh = http_create_empty_headers(); int dlr; - - value = mms_get_header_value(m, octstr_imm("X-Mms-Delivery-Report")); + Octstr *value = mms_get_header_value(m, octstr_imm("X-Mms-Delivery-Report")); + if (value && octstr_case_compare(value, octstr_imm("Yes")) == 0) dlr = 1; @@ -200,15 +201,16 @@ static void mm7soap_receive(MmsHTTPClientInfo *h) http_header_add(qh, "X-Mbuni-Timestamp", octstr_get_cstr(sx)); octstr_destroy(sx); } + + qf = qfs->mms_queue_add(from, to, subject, - h->m->id, h->m->reroute ? h->m->reroute_mmsc_id : NULL, + h->m->id, mmc_id, delivert, expiryt, m, linkedid, NULL, NULL, NULL, NULL, qh, dlr, - h->m->reroute ? octstr_get_cstr(outgoing_qdir) : - octstr_get_cstr(incoming_qdir), + octstr_get_cstr(qdir), octstr_imm(MM_NAME)); msgid = mms_maketransid(octstr_get_cstr(qf), octstr_imm(MM_NAME)); mms_log("Received", from, to, -1, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL); @@ -227,34 +229,78 @@ static void mm7soap_receive(MmsHTTPClientInfo *h) break; case MM7_TAG_DeliveryReportReq: - desc = mm7_soap_header_value(mreq, octstr_imm("StatusText")); - msgid = mm7_soap_header_value(mreq, octstr_imm("MessageID")); - value = mm7_soap_header_value(mreq, octstr_imm("MMStatus")); - - 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, - value, msgid, h->m->id, h->m->group_id, NULL, uaprof, uaprof_tstamp); + if (mmc_id != NULL) { /* internal routing. */ + m = mm7_soap_to_mmsmsg(mreq, from); + if (m) + qf = qfs->mms_queue_add(from, to, NULL, + h->m->id, mmc_id, + 0, time(NULL) + default_msgexpiry, m, NULL, + NULL, NULL, + NULL, NULL, + NULL, + 0, + octstr_get_cstr(qdir), + octstr_imm(MM_NAME)); + else + qf = NULL; + if (qf) + /* Log to access log */ + mms_log("Received DLR", from, to, -1, NULL, NULL, h->m->id, "MMSBox", h->ua, NULL); + else + status = 4000; + } else { + Octstr *desc = mm7_soap_header_value(mreq, octstr_imm("StatusText")); + Octstr *value = mm7_soap_header_value(mreq, octstr_imm("MMStatus")); - octstr_destroy(desc); - octstr_destroy(value); - mms_log("DeliveryReport", - from, NULL, -1, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL); + msgid = mm7_soap_header_value(mreq, octstr_imm("MessageID")); + + 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, + value, msgid, h->m->id, h->m->group_id, NULL, uaprof, uaprof_tstamp); + + mms_log("DeliveryReport", + from, NULL, -1, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL); + octstr_destroy(desc); + octstr_destroy(value); + + } mresp = mm7_make_resp(mreq, status, NULL,1); break; case MM7_TAG_ReadReplyReq: - msgid = mm7_soap_header_value(mreq, octstr_imm("MessageID")); - value = mm7_soap_header_value(mreq, octstr_imm("MMStatus")); - - send_report(from, - "read-report", NULL, value, msgid, - h->m->id, h->m->group_id, NULL, uaprof, uaprof_tstamp); - - octstr_destroy(value); - mms_log("ReadReport", - from, NULL, -1, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL); + if (mmc_id != NULL) { /* internal routing. */ + m = mm7_soap_to_mmsmsg(mreq, from); + if (m) + qf = qfs->mms_queue_add(from, to, NULL, + h->m->id, mmc_id, + 0, time(NULL) + default_msgexpiry, m, NULL, + NULL, NULL, + NULL, NULL, + NULL, + 0, + octstr_get_cstr(qdir), + octstr_imm(MM_NAME)); + else + qf = NULL; + if (qf) + /* Log to access log */ + mms_log("Received RR", from, to, -1, NULL, NULL, h->m->id, "MMSBox", h->ua, NULL); + else + status = 4000; + } else { + Octstr *value = mm7_soap_header_value(mreq, octstr_imm("MMStatus")); + msgid = mm7_soap_header_value(mreq, octstr_imm("MessageID")); + + send_report(from, + "read-report", NULL, value, msgid, + h->m->id, h->m->group_id, NULL, uaprof, uaprof_tstamp); + + octstr_destroy(value); + mms_log("ReadReport", + from, NULL, -1, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL); + } mresp = mm7_make_resp(mreq, status, NULL,1); break; @@ -264,7 +310,6 @@ static void mm7soap_receive(MmsHTTPClientInfo *h) } done: - if (mresp && mm7_soapmsg_to_httpmsg(mresp, &h->m->ver, &rh, &reply_body) == 0) http_send_reply(h->client, hstatus, rh, reply_body); else @@ -287,6 +332,7 @@ static void mm7soap_receive(MmsHTTPClientInfo *h) mm7_soap_destroy(mresp); mm7_soap_destroy(mreq); gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy); + octstr_destroy(mmc_id); } static void mm7eaif_receive(MmsHTTPClientInfo *h) @@ -295,13 +341,13 @@ static void mm7eaif_receive(MmsHTTPClientInfo *h) List *mh = NULL; int hstatus = HTTP_NO_CONTENT; List *rh = http_create_empty_headers(); - Octstr *reply_body = NULL, *value, *value2; + Octstr *reply_body = NULL, *value; List *to = gwlist_create(), *hto = NULL; Octstr *subject = NULL, *otransid = NULL, *msgid = NULL; Octstr *hfrom = NULL; time_t expiryt = -1, deliveryt = -1; - Octstr *qf = NULL, *xver; + Octstr *qf = NULL, *xver, *mmc_id = NULL, *qdir = NULL; int msize = h->body ? octstr_len(h->body) : 0; int dlr; int mtype; @@ -355,6 +401,8 @@ static void mm7eaif_receive(MmsHTTPClientInfo *h) } + qdir = get_mmsbox_queue_dir(hfrom, to, h->m, &mmc_id); /* get routing info. */ + switch(mtype) { case MMS_MSGTYPE_SEND_REQ: case MMS_MSGTYPE_RETRIEVE_CONF: @@ -389,42 +437,79 @@ static void mm7eaif_receive(MmsHTTPClientInfo *h) /* Save it, put message id in header, return. */ qf = qfs->mms_queue_add(hfrom, to, subject, - h->m->id, h->m->reroute ? h->m->reroute_mmsc_id : NULL, + h->m->id, mmc_id, deliveryt, expiryt, m, NULL, NULL, NULL, NULL, NULL, NULL, dlr, - h->m->reroute ? octstr_get_cstr(outgoing_qdir) : - octstr_get_cstr(incoming_qdir), + octstr_get_cstr(qdir), octstr_imm(MM_NAME)); if (qf) { /* Log to access log */ mms_log("Received", hfrom, to, msize, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL); - octstr_destroy(qf); hstatus = HTTP_NO_CONTENT; } else hstatus = HTTP_INTERNAL_SERVER_ERROR; break; case MMS_MSGTYPE_DELIVERY_IND: - value = http_header_value(mh, octstr_imm("X-Mms-Status")); - 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); - - octstr_destroy(value); - octstr_destroy(value2); + if (mmc_id != NULL) { /* internal routing. */ + qf = qfs->mms_queue_add(hfrom, to, NULL, + h->m->id, mmc_id, + 0, time(NULL) + default_msgexpiry, m, NULL, + NULL, NULL, + NULL, NULL, + NULL, + 0, + octstr_get_cstr(qdir), + octstr_imm(MM_NAME)); + if (qf) { + /* Log to access log */ + mms_log("Received DLR", hfrom, to, -1, NULL, NULL, h->m->id, "MMSBox", h->ua, NULL); + + hstatus = HTTP_NO_CONTENT; + } else + hstatus = HTTP_INTERNAL_SERVER_ERROR; + } 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); + + octstr_destroy(value); + octstr_destroy(value2); + } break; case MMS_MSGTYPE_READ_ORIG_IND: - value = http_header_value(mh, octstr_imm("X-Mms-Read-Status")); - value2 = http_header_value(mh, octstr_imm("Message-ID")); - send_report(hfrom, "read-report", NULL, value, value2, h->m->id, h->m->group_id, NULL, NULL, -1); - - octstr_destroy(value); - octstr_destroy(value2); + if (mmc_id != NULL) { /* internal routing. */ + qf = qfs->mms_queue_add(hfrom, to, NULL, + h->m->id, mmc_id, + 0, time(NULL) + default_msgexpiry, m, NULL, + NULL, NULL, + NULL, NULL, + NULL, + 0, + octstr_get_cstr(qdir), + octstr_imm(MM_NAME)); + if (qf) { + /* Log to access log */ + mms_log("Received RR", hfrom, to, -1, NULL, NULL, h->m->id, "MMSBox", h->ua, NULL); + hstatus = HTTP_NO_CONTENT; + } else + hstatus = HTTP_INTERNAL_SERVER_ERROR; + } 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, + h->m->group_id, NULL, NULL, -1); + + + octstr_destroy(value); + octstr_destroy(value2); + } break; } @@ -442,6 +527,9 @@ static void mm7eaif_receive(MmsHTTPClientInfo *h) octstr_destroy(subject); octstr_destroy(otransid); octstr_destroy(msgid); + octstr_destroy(qf); + octstr_destroy(mmc_id); + http_destroy_headers(mh); mms_destroy(m); } diff --git a/mbuni/mmsbox/mmsbox_cfg.c b/mbuni/mmsbox/mmsbox_cfg.c index 09f684d..dc2d44b 100644 --- a/mbuni/mmsbox/mmsbox_cfg.c +++ b/mbuni/mmsbox/mmsbox_cfg.c @@ -22,57 +22,26 @@ #include #include "mmsbox_cfg.h" #include "mms_queue.h" - +#include "mmsbox_resolve_shell.h" List *sendmms_users = NULL; /* list of SendMmsUser structs */ List *mms_services = NULL; /* list of MMS Services */ List *mmscs = NULL; Octstr *incoming_qdir, *outgoing_qdir, *dlr_dir; -long mmsbox_maxsendattempts, mmsbox_send_back_off; +long mmsbox_maxsendattempts, mmsbox_send_back_off, default_msgexpiry; long maxthreads = 0; double queue_interval = -1; Octstr *unified_prefix; int mt_multipart = 0; MmsQueueHandlerFuncs *qfs; /* queue functions. */ +MmsBoxResolverFuncStruct *rfs; /* resolver functions. */ +void *rfs_data; +Octstr *rfs_settings; struct SendMmsPortInfo sendmms_port; struct MmsBoxMTfilter *mt_filter = NULL; -static void *load_module(mCfgGrp *grp, char *config_key, - char *symbolname) -{ - Octstr *s = NULL; - void *retval = NULL; - - s = mms_cfg_get(grp, octstr_imm(config_key)); - - if (s) { - void *x; - void *y = NULL; -#ifdef __APPLE__ - char sbuf[512]; -#endif - x = dlopen(octstr_get_cstr(s), RTLD_LAZY); -#ifdef __APPLE__ - sprintf(sbuf, "_%s", symbolname); -#endif - if (x == NULL || ((y = dlsym(x, symbolname)) == NULL -#ifdef __APPLE__ /* fink version of dlsym has issues it seems. */ - && (y = dlsym(x, sbuf)) == NULL -#endif - )) - - panic(0, "Unable to load dynamic libary (%s): %s", - octstr_get_cstr(s), dlerror()); - else - retval = y; - octstr_destroy(s); - } - - return retval; -} - int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func) { mCfgGrp *grp = mms_cfg_get_single(cfg, octstr_imm("mbuni")); @@ -103,7 +72,7 @@ int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func) panic(0, "Failed to create MMSBox storage directory: %s - %s!", octstr_get_cstr(gdir), strerror(errno)); - if ((qfs = load_module(grp, "queue-manager-module", "qfuncs")) == NULL) { + if ((qfs = _mms_load_module(grp, "queue-manager-module", "qfuncs", NULL)) == NULL) { qfs = &default_qfuncs; /* default queue handler. */ qfs->mms_init_queue_module(gdir); } else { @@ -140,7 +109,9 @@ int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func) octstr_imm("send-attempt-back-off"), &mmsbox_send_back_off) == -1) mmsbox_send_back_off = BACKOFF_FACTOR; - + if (mms_cfg_get_int(grp, octstr_imm("default-message-expiry"), &default_msgexpiry) == -1) + default_msgexpiry = DEFAULT_EXPIRE; + if (mms_cfg_get_int(grp, octstr_imm("max-send-threads"), &maxthreads) == -1) maxthreads = 10; @@ -169,13 +140,19 @@ int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func) sendmms_port.deny_ip = mms_cfg_get(grp, octstr_imm("deny-ip")); /* load the filter if any. */ - if ((mt_filter = load_module(grp, "mmsbox-mt-filter-library", "mmsbox_mt_filter")) != NULL) + if ((mt_filter = _mms_load_module(grp, "mmsbox-mt-filter-library", "mmsbox_mt_filter", NULL)) != NULL) info(0, "MMSBox: Loaded MT Filter [%s]", mt_filter->name); mms_cfg_get_bool(grp, octstr_imm("mmsbox-mt-always-multipart"), &mt_multipart); - /* Now get sendmms users. */ + /* load the resolver module. */ + if ((rfs = _mms_load_module(grp, "resolver-library", "mmsbox_resolver", &mmsbox_resolvefuncs_shell)) == NULL) + rfs = &mmsbox_resolvefuncs; + + rfs_settings = _mms_cfg_getx(grp, octstr_imm("resolver-module-parameters")); + rfs_data = rfs->mmsbox_resolvermodule_init(rfs_settings ? octstr_get_cstr(rfs_settings) : NULL); + /* Now get sendmms users. */ l = mms_cfg_get_multi(cfg, octstr_imm("send-mms-user")); for (i = 0, n = gwlist_len(l); i < n; i++) { mCfgGrp *x = gwlist_get(l, i); @@ -486,3 +463,37 @@ MmscGrp *get_handler_mmc(Octstr *id, Octstr *to) octstr_destroy(phonenum); return NULL; } + +/* handle message routing. */ +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; + } else { + Octstr *_mcid, *fto = NULL, *qdir = NULL; + + if (gwlist_len(to) > 0) { /* we route based on first recipient XXX */ + Octstr *r = gwlist_get(to, 0); + fto = r ? octstr_duplicate(r) : NULL; + } + + _mcid = rfs->mmsbox_resolve(from,fto,rfs_data, rfs_settings); + + if (_mcid == NULL || octstr_len(_mcid) == 0) { + *mmc_id = NULL; + qdir = incoming_qdir; + } else { + *mmc_id = octstr_duplicate(_mcid); + qdir = outgoing_qdir; + } + octstr_destroy(_mcid); + octstr_destroy(fto); + return qdir; + } + return 0; +} diff --git a/mbuni/mmsbox/mmsbox_cfg.h b/mbuni/mmsbox/mmsbox_cfg.h index 8b35e0f..e67c156 100644 --- a/mbuni/mmsbox/mmsbox_cfg.h +++ b/mbuni/mmsbox/mmsbox_cfg.h @@ -15,6 +15,7 @@ #include "mms_util.h" #include "mmsbox_mt_filter.h" #include "mms_queue.h" +#include "mmsbox_resolve.h" typedef struct MmscGrp { Octstr *id; /* MMSC id (for logging). */ @@ -81,7 +82,7 @@ extern List *mms_services; /* list of MMS Services */ extern List *mmscs; /* MMSC list. Perhaps turn into a Dict instead? */ extern Octstr *incoming_qdir, *outgoing_qdir, *dlr_dir; extern Octstr *unified_prefix; -extern long mmsbox_maxsendattempts, mmsbox_send_back_off; +extern long mmsbox_maxsendattempts, mmsbox_send_back_off, default_msgexpiry; extern long maxthreads; extern double queue_interval; extern struct SendMmsPortInfo { @@ -93,6 +94,15 @@ extern struct SendMmsPortInfo { extern struct MmsBoxMTfilter *mt_filter; extern MmsQueueHandlerFuncs *qfs; extern int mt_multipart; + +extern MmsBoxResolverFuncStruct *rfs; /* resolver functions. */ +extern void *rfs_data; +extern Octstr *rfs_settings; + + extern int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func); extern MmscGrp *get_handler_mmc(Octstr *id, Octstr *to); + +extern Octstr *get_mmsbox_queue_dir(Octstr *from, List *to, MmscGrp *m, + Octstr **mmc_id); #endif diff --git a/mbuni/mmsbox/mmsbox_resolve.c b/mbuni/mmsbox/mmsbox_resolve.c new file mode 100644 index 0000000..ce48832 --- /dev/null +++ b/mbuni/mmsbox/mmsbox_resolve.c @@ -0,0 +1,39 @@ +/* + * Mbuni - Open Source MMS Gateway + * + * Resolving MSISDNs to local/remote MMSBox MMSC - interface + * + * 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) + */ +#include +#include +#include "mmsbox_resolve.h" +#include "mmsbox_cfg.h" + +static void *_resolvermodule_init(char *settings) +{ + return NULL; +} + +static int _resolvermodule_fini(void *module_data) +{ + return 0; +} + +static Octstr *_resolve(Octstr * pfrom, Octstr *pto, void *module_data, void *settings_p) +{ + /* route normally to mms-service. */ + return NULL; +} + +/* The function itself. */ +MmsBoxResolverFuncStruct mmsbox_resolvefuncs = { + _resolvermodule_init, + _resolve, + _resolvermodule_fini +}; diff --git a/mbuni/mmsbox/mmsbox_resolve.h b/mbuni/mmsbox/mmsbox_resolve.h new file mode 100644 index 0000000..5133146 --- /dev/null +++ b/mbuni/mmsbox/mmsbox_resolve.h @@ -0,0 +1,42 @@ +/* + * Mbuni - Open Source MMS Gateway + * + * Resolving MSISDNs to local/remote MMSBox MMSC - interface + * + * 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_RESOLVE_INCLUDED__ +#define __MMSBOX_RESOLVE_INCLUDED__ + +#include +#include "gwlib/gwlib.h" + +/* Resolver module. This file provides prototypes for all resolver functions. + * the module is loaded once and _init is called once at load. + * _resolve is called for each incoming message to determine how to route it. + */ + +typedef struct MmsBoxResolverFuncStruct { +/* This function is called once to initialise the resolver module. Return a generic object, + * which is passed with each resolution request.. + */ + void *(*mmsbox_resolvermodule_init)(char *settings); + +/* Looks up the sender and receiver msisdns and returns the ID of the MMC connection through which + * the received message should be sent. + * + * Return NULL or the empty string to send the message to a service (normal behavior) + */ + Octstr *(*mmsbox_resolve)(Octstr *pfrom, Octstr *pto, void *module_data, void *settings); + + int (*mmsbox_resolvermodule_fini)(void *module_data); +} MmsBoxResolverFuncStruct; + +extern MmsBoxResolverFuncStruct mmsbox_resolvefuncs; /* The module must expose this symbol. */ + +#endif diff --git a/mbuni/mmsbox/mmsbox_resolve_shell.c b/mbuni/mmsbox/mmsbox_resolve_shell.c new file mode 100644 index 0000000..9009df2 --- /dev/null +++ b/mbuni/mmsbox/mmsbox_resolve_shell.c @@ -0,0 +1,66 @@ +/* + * Mbuni - Open Source MMS Gateway + * + * Resolving MSISDNs to local/remote MMSCs - calling shell scripts + * + * Copyright (C) 2003 - 2005, 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) + */ +#include +#include +#include "mmsbox_resolve.h" +#include "mms_util.h" + +static Octstr *script = NULL; + +static void *_shell_resolvermodule_init(char *settings) +{ + script = octstr_imm(settings); + return NULL; +} + +static int _shell_resolvermodule_fini(void *module_data) +{ + octstr_destroy(script); + script = NULL; + return 0; +} + +static Octstr *_shell_resolve(Octstr *pfrom, Octstr *pto, void *module_data, void *settings_p) +{ + Octstr *s; + FILE *fp; + char buf[4096]; + + if (script == NULL || octstr_len(script) == 0) + return 0; + + s = octstr_format("%s '%s' '%s' ", + octstr_get_cstr(script), octstr_get_cstr(pfrom), octstr_get_cstr(pto)); + fp = popen(octstr_get_cstr(s), "r"); + octstr_destroy(s); + + fgets(buf, 4096, fp); + s = octstr_create(buf); + octstr_strip_crlfs(s); + + pclose(fp); + + if (octstr_len(s) == 0) { + octstr_destroy(s); + return NULL; + } + + return s; +} + +/* The function struct itself. */ +MmsBoxResolverFuncStruct mmsbox_resolvefuncs_shell = { + _shell_resolvermodule_init, + _shell_resolve, + _shell_resolvermodule_fini +}; diff --git a/mbuni/mmsbox/mmsbox_resolve_shell.h b/mbuni/mmsbox/mmsbox_resolve_shell.h new file mode 100644 index 0000000..552a47a --- /dev/null +++ b/mbuni/mmsbox/mmsbox_resolve_shell.h @@ -0,0 +1,22 @@ +/* + * Mbuni - Open Source MMS Gateway + * + * Resolving MSISDNs to local/remote MMSCs - interface (shell) + * + * 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_RESOLVE_SHELL_INCLUDED__ +#define __MMSBOX_RESOLVE_SHELL_INCLUDED__ + +#include +#include "gwlib/gwlib.h" +#include "mmsbox_resolve.h" + +extern MmsBoxResolverFuncStruct mmsbox_resolvefuncs_shell; + +#endif diff --git a/mbuni/mmsc/mmsc_cfg.c b/mbuni/mmsc/mmsc_cfg.c index 893a61f..fd511ea 100644 --- a/mbuni/mmsc/mmsc_cfg.c +++ b/mbuni/mmsc/mmsc_cfg.c @@ -28,48 +28,6 @@ -static void *load_module(mCfgGrp *grp, char *config_key, char *symbolname, - void *shell_builtin) -{ - Octstr *s = NULL; - void *retval = NULL; - - s = mms_cfg_get(grp, octstr_imm(config_key)); - - if (s) { - void *x; - void *y = NULL; -#ifdef __APPLE__ - char sbuf[512]; -#endif - /* First look for the builtin: keyword. - * For now only builtin:shell is supported. - */ - if (octstr_case_search(s, octstr_imm("builtin:shell"), 0) >= 0) - retval = shell_builtin; - else { - x = dlopen(octstr_get_cstr(s), RTLD_LAZY); -#ifdef __APPLE__ - sprintf(sbuf, "_%s", symbolname); -#endif - if (x == NULL || ((y = dlsym(x, symbolname)) == NULL -#ifdef __APPLE__ /* fink version of dlsym has issues it seems. */ - && (y = dlsym(x, sbuf)) == NULL -#endif - )) - - panic(0, "Unable to load dynamic libary (%s): %s", - octstr_get_cstr(s), - dlerror()); - else - retval = y; - } - octstr_destroy(s); - } - - return retval; -} - void mms_cleanup_mmsc_settings(MmscSettings *settings) { /* eventually we will destroy the object. For now, we only cleanup queue module. */ @@ -126,7 +84,7 @@ MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays) panic(0, "Failed to create queue directory: %s - %s!", octstr_get_cstr(qdir), strerror(errno)); - if ((m->qfs = load_module(grp, "queue-manager-module", "qfuncs", NULL)) == NULL) { + if ((m->qfs = _mms_load_module(grp, "queue-manager-module", "qfuncs", NULL)) == NULL) { m->qfs = &default_qfuncs; /* default queue handler. */ m->qfs->mms_init_queue_module(qdir); } else { @@ -238,7 +196,7 @@ MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays) octstr_imm("billing-module-parameters")); /* Get and load the billing lib if any. */ - if ((m->mms_billfuncs = load_module(grp, "billing-library", "mms_billfuncs", + if ((m->mms_billfuncs = _mms_load_module(grp, "billing-library", "mms_billfuncs", &mms_billfuncs_shell)) != NULL) { if (m->mms_billfuncs->mms_billingmodule_init == NULL || m->mms_billfuncs->mms_billmsg == NULL || @@ -254,7 +212,7 @@ MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays) octstr_imm("resolver-module-parameters")); /* Get and load the resolver lib if any. */ - if ((m->mms_resolvefuncs = load_module(grp, "resolver-library", + if ((m->mms_resolvefuncs = _mms_load_module(grp, "resolver-library", "mms_resolvefuncs", &mms_resolvefuncs_shell)) != NULL) { if (m->mms_resolvefuncs->mms_resolvermodule_init == NULL || @@ -269,7 +227,7 @@ MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays) m->detokenizer_params = _mms_cfg_getx(grp, octstr_imm("detokenizer-module-parameters")); /* Get and load the detokenizer lib if any. */ - if ((m->mms_detokenizefuncs = load_module(grp, "detokenizer-library", + if ((m->mms_detokenizefuncs = _mms_load_module(grp, "detokenizer-library", "mms_detokenizefuncs", &mms_detokenizefuncs_shell)) != NULL) { if (m->mms_detokenizefuncs->mms_detokenizer_init == NULL ||