From b480d170a5b114b0cacecb1383372ecd419ff037 Mon Sep 17 00:00:00 2001 From: bagyenda <> Date: Fri, 12 Sep 2008 12:02:40 +0000 Subject: [PATCH] added cdr stuff for mmsbox --- mbuni/ChangeLog | 1 + mbuni/doc/userguide.shtml | 42 +++++++++++ mbuni/mmlib/mms_cfg.def | 3 + mbuni/mmsbox/Makefile.am | 4 +- mbuni/mmsbox/bearerbox.c | 27 ++++++- mbuni/mmsbox/mmsbox.c | 18 ++++- mbuni/mmsbox/mmsbox_cdr.c | 151 ++++++++++++++++++++++++++++++++++++++ mbuni/mmsbox/mmsbox_cdr.h | 73 ++++++++++++++++++ mbuni/mmsbox/mmsbox_cfg.c | 16 +++- mbuni/mmsbox/mmsbox_cfg.h | 2 + mbuni/mmsc/mms_billing.h | 2 +- 11 files changed, 332 insertions(+), 7 deletions(-) create mode 100644 mbuni/mmsbox/mmsbox_cdr.c create mode 100644 mbuni/mmsbox/mmsbox_cdr.h diff --git a/mbuni/ChangeLog b/mbuni/ChangeLog index 44fa52b..b58eba6 100644 --- a/mbuni/ChangeLog +++ b/mbuni/ChangeLog @@ -1,5 +1,6 @@ 2008-09-12 P. A. Bagyenda * Added facility for appending special response header to each message (mime) part in MM7 response + * Added mmsbox cdr logging 2008-09-11 P. A. Bagyenda * MMSBox HTTP MMSC type added, for inter-mmsbox message relay * MM5 support, basic infrastructure on the MMSC side. diff --git a/mbuni/doc/userguide.shtml b/mbuni/doc/userguide.shtml index 41d5e1b..f1dd374 100644 --- a/mbuni/doc/userguide.shtml +++ b/mbuni/doc/userguide.shtml @@ -1359,6 +1359,48 @@ lists all the configuration directives. The column Mode     + + + + mmsbox-cdr-module +     + + + VAS GW +     + + + + String +     + + Optional + library containing CDR functions for mmsbox. This library is loaded at + runtime and should contain functions to be called to effect CDR + logging for the VAS Gateway. See mmsbox_cdr.h for + details. (Default behaviour is to log CDR to tab-delimited file storage-dir/mmsbox-cdr.asc) +     + + + + mmsbox-module-parameters +     + + + VAS GW +     + + + + String +     + + Parameters to + pass to the mmsbox CDR module specified above when it is loaded. This is a + generic string whose interpretation is entirely up to the module. +     + + resolver-library diff --git a/mbuni/mmlib/mms_cfg.def b/mbuni/mmlib/mms_cfg.def index f72fa29..a2e9df6 100644 --- a/mbuni/mmlib/mms_cfg.def +++ b/mbuni/mmlib/mms_cfg.def @@ -114,6 +114,9 @@ SINGLE_GROUP(mbuni, OCTSTR(mm5-module) OCTSTR(mm5-module-parameters) + + OCTSTR(mmsbox-cdr-module) + OCTSTR(mmsbox-cdr-module-parameters) ) MULTI_GROUP(mmsproxy, diff --git a/mbuni/mmsbox/Makefile.am b/mbuni/mmsbox/Makefile.am index f9ecb88..ddb6f19 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_resolve.c mmsbox_resolve_shell.c +mmsbox_SOURCES = mmsbox.c mmsbox_cdr.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_shell.h mmsbox_resolve.h mmsbox_mmsc.h +EXTRA_DIST = mmsbox_cdr.h mmsbox_cfg.h mmsbox.h mmsbox_mt_filter.h mmsbox_resolve_shell.h mmsbox_resolve.h mmsbox_mmsc.h diff --git a/mbuni/mmsbox/bearerbox.c b/mbuni/mmsbox/bearerbox.c index 7a94f49..160dd60 100644 --- a/mbuni/mmsbox/bearerbox.c +++ b/mbuni/mmsbox/bearerbox.c @@ -221,7 +221,8 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) "MM7/SOAP-IN", NULL); msgid = mms_make_msgid(octstr_get_cstr(qf), NULL); - mms_log("Received", from, to, -1, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL); + mms_log("Received", from, to, -1, msgid, NULL, h->m->id, "MMSBox", + h->ua, NULL); octstr_destroy(linkedid); octstr_destroy(value); @@ -1295,7 +1296,29 @@ static int sendMsg(MmsEnvelope *e) e->msgId, mmc->id, mmc->group_id, otransid, NULL, -1); if (res == MMS_SEND_ERROR_FATAL) to->process = 0; /* No more attempts. */ - + + + /* handle CDR */ + if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED || res == MMS_SEND_ERROR_FATAL) { + MmsBoxCdrStruct cdr; + + /* Do CDR */ + mmsbox_fill_cdr_struct(&cdr, e->created, + octstr_get_cstr(e->from), + octstr_get_cstr(to->rcpt), + octstr_get_cstr(e->msgId), + mmc ? octstr_get_cstr(mmc->id) : NULL, /* Should we touch mmc here? XXX */ + e->src_interface, + "MM7", + e->msize, + (char *)mms_message_type_to_cstr(e->msgtype), + NULL, NULL, /* XXX will add these later. */ + res == MMS_SEND_ERROR_FATAL ? "dropped" : "sent", + e->dlr, + 0); + cdrfs->logcdr(&cdr); + } + if (err == NULL) mms_info(0, "MM7", NULL, "%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: msgid=[%s]", SEND_ERROR_STR(res), diff --git a/mbuni/mmsbox/mmsbox.c b/mbuni/mmsbox/mmsbox.c index ae49add..1dada37 100644 --- a/mbuni/mmsbox/mmsbox.c +++ b/mbuni/mmsbox/mmsbox.c @@ -553,11 +553,27 @@ done: if (err && res != 0) mms_error(0, "mmsbox", NULL, "Error: %s", octstr_get_cstr(err)); - if (res == -1 || res == 0) /* Fatal error, or success delete queue entry. */ + if (res == -1 || res == 0) /* Fatal error, or success delete queue entry. */ for (i = 0, n = gwlist_len(e->to); i < n; i++) { + MmsBoxCdrStruct cdr; MmsEnvelopeTo *r = gwlist_get(e->to,i); if (r) r->process = 0; + /* Do CDR */ + mmsbox_fill_cdr_struct(&cdr, e->created, + octstr_get_cstr(e->from), + octstr_get_cstr(r->rcpt), + octstr_get_cstr(e->msgId), + e->fromproxy ? octstr_get_cstr(e->fromproxy) : NULL, + e->src_interface, + "mms-service", + e->msize, + (char *)mms_message_type_to_cstr(e->msgtype), + NULL, NULL, /* XXX will add these later. */ + res == 0 ? "forwarded" : "dropped", + e->dlr, + 0); + cdrfs->logcdr(&cdr); } else { /* Not succeeded so we need to wait a bit and try later. */ e->lasttry = time(NULL); diff --git a/mbuni/mmsbox/mmsbox_cdr.c b/mbuni/mmsbox/mmsbox_cdr.c new file mode 100644 index 0000000..a17fae0 --- /dev/null +++ b/mbuni/mmsbox/mmsbox_cdr.c @@ -0,0 +1,151 @@ +/* + * Mbuni - Open Source MMS Gateway + * + * Mbuni MMSBOX base CDR handler module (writes to a CVS file) + * + * Copyright (C) 2003 - 2008, 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_cdr.h" + + +static FILE *cdr_file; +static List *req_list; +static long th_id; + + +static void cdr_logger_func(void) +{ + + MmsBoxCdrStruct *cdr; + + while ((cdr = gwlist_consume(req_list)) != NULL) { + char buf[CBUFSIZE]; + struct tm tm; + + localtime_r(&cdr->sdate, &tm); + gw_strftime(buf, sizeof buf, "%Y-%m-%d %H:%M:%S", &tm); + fprintf(cdr_file, "%s", buf); + + /* Print rest of fields one by one. */ +#define PRINTF_STR_FIELD(fld) fprintf(cdr_file, "\t%.*s", (int)(sizeof cdr->fld), cdr->fld) + + PRINTF_STR_FIELD(src_int); + PRINTF_STR_FIELD(dst_int); + PRINTF_STR_FIELD(from); + PRINTF_STR_FIELD(to); + PRINTF_STR_FIELD(msgid); + PRINTF_STR_FIELD(mmsc_id); + PRINTF_STR_FIELD(msgtype); + PRINTF_STR_FIELD(prio); + PRINTF_STR_FIELD(mclass); + PRINTF_STR_FIELD(status); + + fprintf(cdr_file, "\t%ld\t%s\t%s\n", + (long)cdr->msg_size, + cdr->dlr ? "Yes" : "No", + cdr->rr ? "Yes" : "No"); + + fflush(cdr_file); + + gw_free(cdr); + } + +} + +static int cdr_module_init(char *settings) +{ + cdr_file = fopen(settings, "a"); /* Settings is interpreted as a file name. */ + if (cdr_file) { + req_list = gwlist_create(); + + gwlist_add_producer(req_list); + + th_id = gwthread_create((void *)cdr_logger_func, NULL); + return 0; + } else + return -1; +} + + +static int module_fini(void) +{ + gw_assert(req_list); + gw_assert(cdr_file); + + gwlist_remove_producer(req_list); + + if (th_id >= 0) + gwthread_join(th_id); + gwlist_destroy(req_list, NULL); /* there shouldn't be any requests waiting */ + + if (cdr_file) + fclose(cdr_file); + + return 0; +} + +static int cdr_module_logcdr(MmsBoxCdrStruct *cdr) +{ + MmsBoxCdrStruct *xcdr = gw_malloc(sizeof *xcdr); + + gw_assert(req_list); + + *xcdr = *cdr; + + gwlist_produce(req_list, xcdr); + + return 0; + +} + + +/* utility function. */ +void mmsbox_fill_cdr_struct(MmsBoxCdrStruct *cdr, + time_t sdate, char *from, char *to, char *msgid, + char *mmsc_id, char *src_int, char *dst_int, +#if 0 + char *src_ip, char *dst_ip, +#endif + unsigned long msg_size, + char *msgtype, char *prio, char *mclass, + char *status, + int dlr, int rr) +{ + memset(cdr, 0, sizeof cdr[0]); + + cdr->sdate = sdate; + +#define COPY_CDR_FIELD(fld) if (fld) \ + strncpy(cdr->fld, fld, sizeof cdr->fld) + + COPY_CDR_FIELD(from); + COPY_CDR_FIELD(to); + COPY_CDR_FIELD(msgid); + COPY_CDR_FIELD(mmsc_id); + COPY_CDR_FIELD(src_int); + COPY_CDR_FIELD(dst_int); + COPY_CDR_FIELD(msgtype); + COPY_CDR_FIELD(prio); + COPY_CDR_FIELD(mclass); + COPY_CDR_FIELD(status); + + cdr->dlr = dlr; + cdr->rr = rr; + cdr->msg_size = msg_size; +} + + +MmsBoxCdrFuncStruct mmsbox_cdrfuncs = { + cdr_module_init, + cdr_module_logcdr, + module_fini +}; diff --git a/mbuni/mmsbox/mmsbox_cdr.h b/mbuni/mmsbox/mmsbox_cdr.h new file mode 100644 index 0000000..ef51591 --- /dev/null +++ b/mbuni/mmsbox/mmsbox_cdr.h @@ -0,0 +1,73 @@ +/* + * Mbuni - Open Source MMS Gateway + * + * Mbuni billing integration interface + * + * Copyright (C) 2003 - 2008, 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_CDR_INCLUDED__ +#define __MMSBOX_CDR_INCLUDED__ + + +#include +#include "gwlib/gwlib.h" + +/* MMSBOX CDR module. This file provides prototypes for all CDR functions. + * + */ +#define CBUFSIZE 256 +typedef struct MmsBoxCdrStruct { + time_t sdate; + char from[CBUFSIZE]; + char to[CBUFSIZE]; +#if 0 + char src_ip[CBUFSIZE/4]; + char dest_ip[CBUFSIZE/4]; +#endif + char msgid[CBUFSIZE]; + char mmsc_id[CBUFSIZE]; + + char src_int[CBUFSIZE/4]; + char dst_int[CBUFSIZE/4]; + + unsigned long msg_size; + + char msgtype[CBUFSIZE/8]; + char prio[CBUFSIZE/8]; + char mclass[CBUFSIZE/8]; + char status[CBUFSIZE/8]; + unsigned char dlr; + unsigned char rr; +} MmsBoxCdrStruct; + + +typedef struct MmsBoxCdrFuncStruct { +/* This function is called once to initialise the module. Return 0 on success */ + int (*init)(char *settings); + + /* This function logs a cdr to wherever it is logging to. */ + int (*logcdr)(MmsBoxCdrStruct *cdr); + + int (*cleanup)(void); +} MmsBoxCdrFuncStruct; + +extern MmsBoxCdrFuncStruct mmsbox_cdrfuncs; /* The module must expose a symbol 'cdr_funcs' */ + +/* utility function. */ +void mmsbox_fill_cdr_struct(MmsBoxCdrStruct *cdr, + time_t sdate, char *from, char *to, char *msgid, + char *mmsc_id, char *src_int, char *dst_int, +#if 0 + char *src_ip, char *dst_ip, +#endif + unsigned long msg_size, + char *msgtype, char *prio, char *mclass, + char *status, + int dlr, int rr); +#endif diff --git a/mbuni/mmsbox/mmsbox_cfg.c b/mbuni/mmsbox/mmsbox_cfg.c index b631bb7..b9de1c6 100644 --- a/mbuni/mmsbox/mmsbox_cfg.c +++ b/mbuni/mmsbox/mmsbox_cfg.c @@ -43,6 +43,8 @@ MmsBoxResolverFuncStruct *rfs; /* resolver functions. */ void *rfs_data; Octstr *rfs_settings; +MmsBoxCdrFuncStruct *cdrfs; + static mCfg *cfg; /* Config. */ static Dict *mmscs = NULL; /* MMSC's indexed by ID. */ static List *mmsc_del_list = NULL; /* List of items to be deleted. */ @@ -160,6 +162,18 @@ int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func) octstr_destroy(s); } + + if ((cdrfs = _mms_load_module(cfg, grp, "mmsbox-cdr-module", "cdr_funcs", NULL)) == NULL) + cdrfs = &mmsbox_cdrfuncs; /* default CDR handler. */ + + if ((s = mms_cfg_get(cfg, grp, octstr_imm("mmsbox-cdr-module-parameters"))) == NULL) + s = octstr_format("%S/mmsbox-cdr.asc", gdir); + + if (cdrfs->init(octstr_get_cstr(s)) != 0) + panic(0, "Failed to initialised CDR module: %s", strerror(errno)); + octstr_destroy(s); + + if ((incoming_qdir = qfs->mms_init_queue_dir("mmsbox_incoming", &xx)) == NULL || xx != 0) panic(0, "Failed to initialise incoming mmsbox queue directory: %s - %s!", @@ -767,7 +781,7 @@ void mmsbox_settings_cleanup(void) gwthread_join(admin_thread); mms_info(0, "mmsbox", NULL,"Admin port on %d, shutdown", (int)admin_port); } - + cdrfs->cleanup(); mms_event_logger_cleanup(); mms_cfg_destroy(cfg); /* only delete at end of session. */ /* More cleanups to follow. */ diff --git a/mbuni/mmsbox/mmsbox_cfg.h b/mbuni/mmsbox/mmsbox_cfg.h index 915a73c..d2039ef 100644 --- a/mbuni/mmsbox/mmsbox_cfg.h +++ b/mbuni/mmsbox/mmsbox_cfg.h @@ -18,6 +18,7 @@ #include "mmsbox_resolve.h" #include "mmsbox_mmsc.h" +#include "mmsbox_cdr.h" typedef struct MmscGrp { Octstr *id; /* MMSC id (for logging). */ @@ -142,6 +143,7 @@ extern void *rfs_data; extern Octstr *rfs_settings; +extern MmsBoxCdrFuncStruct *cdrfs; extern int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func); extern void mmsbox_settings_cleanup(void); extern MmscGrp *get_handler_mmc(Octstr *id, Octstr *to, Octstr *from); diff --git a/mbuni/mmsc/mms_billing.h b/mbuni/mmsc/mms_billing.h index 8308c1a..8d02a94 100644 --- a/mbuni/mmsc/mms_billing.h +++ b/mbuni/mmsc/mms_billing.h @@ -3,7 +3,7 @@ * * Mbuni billing integration interface * - * Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com + * Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com * * Paul Bagyenda *