From 0dfdfdc305cf0c67689709a65240a4bc9fcafb3e Mon Sep 17 00:00:00 2001 From: bagyenda <> Date: Sat, 13 Sep 2008 06:37:24 +0000 Subject: [PATCH] DLR relay --- mbuni/ChangeLog | 1 + mbuni/mmlib/mms_mm7soap.c | 2 +- mbuni/mmsbox/bearerbox.c | 157 +++++++++++++++++++++++++++----------- mbuni/mmsbox/dlr.c | 7 +- mbuni/mmsbox/mmsbox.c | 29 ++++--- mbuni/mmsbox/mmsbox_cdr.c | 70 +++++++++++++---- mbuni/mmsbox/mmsbox_cdr.h | 45 +++-------- 7 files changed, 195 insertions(+), 116 deletions(-) diff --git a/mbuni/ChangeLog b/mbuni/ChangeLog index b58eba6..7a88a28 100644 --- a/mbuni/ChangeLog +++ b/mbuni/ChangeLog @@ -1,6 +1,7 @@ 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 + * Improved DLR relay when mmsbox relay used -- msgid rewrite 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/mmlib/mms_mm7soap.c b/mbuni/mmlib/mms_mm7soap.c index cf79b93..fced4cb 100644 --- a/mbuni/mmlib/mms_mm7soap.c +++ b/mbuni/mmlib/mms_mm7soap.c @@ -378,7 +378,7 @@ static int append_address(Octstr *p, Octstr *addr_spec, char *prefix, int add_ty j = octstr_case_search(v, octstr_imm("/TYPE=PLMN"),0); if (j >= 0) { z = octstr_copy(v, 2, j-2); /* skip the initial char that is only for info purposes. */ - typ = "Number"; + typ = octstr_len(z) <= 6 ? "ShortCode" : "Number"; } else { z = octstr_copy(v, 2, octstr_len(v)); typ = "RFC2822Address"; diff --git a/mbuni/mmsbox/bearerbox.c b/mbuni/mmsbox/bearerbox.c index 160dd60..feb1040 100644 --- a/mbuni/mmsbox/bearerbox.c +++ b/mbuni/mmsbox/bearerbox.c @@ -86,7 +86,7 @@ int mmsbox_send_report(Octstr *from, char *report_type, { Octstr *url = NULL; - List *rh, *rph = NULL; + List *rh = NULL, *rph = NULL; Octstr *rb = NULL; Octstr *xtransid = NULL; @@ -95,11 +95,14 @@ int mmsbox_send_report(Octstr *from, char *report_type, else mms_dlr_url_get(msgid, report_type, mmc_gid, &url, &xtransid); - if (!url || octstr_len(url) == 0) { - mms_info(0, "MM7", NULL, "Sending delivery-report skipped: `url' is empty, `group_id'=[%s], `msgid'=[%s]", - octstr_get_cstr(mmc_gid), octstr_get_cstr(msgid)); - return 0; - } + if (octstr_len(url) == 0) { + if (url) + mms_info(0, "MM7", NULL, + "Sending delivery-report skipped: `url' is empty, `group_id'=[%s], `msgid'=[%s]", + octstr_get_cstr(mmc_gid), octstr_get_cstr(msgid)); + goto done; + } else if (octstr_search(url, octstr_imm("msgid:"), 0) == 0) /* a fake one, skip it. */ + goto done; rh = http_create_empty_headers(); @@ -121,13 +124,6 @@ int mmsbox_send_report(Octstr *from, char *report_type, octstr_destroy(sx); } mms_url_fetch_content(HTTP_METHOD_GET, url, rh, octstr_imm(""), &rph, &rb); - - octstr_destroy(rb); - octstr_destroy(url); - octstr_destroy(xtransid); - - http_destroy_headers(rph); - http_destroy_headers(rh); /* At what point do we delete it? For now, when we get a read report, * and also when we get a delivery report that is not 'deferred' or sent @@ -136,9 +132,41 @@ int mmsbox_send_report(Octstr *from, char *report_type, (octstr_case_compare(status, octstr_imm("Deferred")) != 0 && octstr_case_compare(status, octstr_imm("Sent")) != 0)) mms_dlr_url_remove(msgid, report_type, mmc_gid); + +done: + octstr_destroy(rb); + octstr_destroy(url); + octstr_destroy(xtransid); + + http_destroy_headers(rph); + http_destroy_headers(rh); + return 0; } +static void fixup_relayed_report(MmsMsg *m, MmscGrp *mmc, char *rtype) +{ + + Octstr *value = mms_get_header_value(m, octstr_imm("Message-ID")); + Octstr *newmsgid = NULL, *transid = NULL; + + /* Firstly, take care to look for the record we saved, and re-write the MessageID. */ + if (value && + mms_dlr_url_get(value, rtype, mmc->group_id, &newmsgid, &transid) == 0) { + int x = octstr_search_char(newmsgid, ':', 0); + + if (x>=0) + octstr_delete(newmsgid, 0, x+1); + + mms_replace_header_value(m, "Message-ID", octstr_get_cstr(newmsgid)); + + mms_dlr_url_remove(value, "delivery-report", mmc->group_id); + } + octstr_destroy(newmsgid); + octstr_destroy(transid); + octstr_destroy(value); +} + /* These functions are very similar to those in mmsproxy */ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) { @@ -240,7 +268,8 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) case MM7_TAG_DeliveryReportReq: if (mmc_id != NULL) { /* internal routing. */ m = mm7_soap_to_mmsmsg(mreq, from); - if (m) + if (m) { + fixup_relayed_report(m, h->m, "delivery-report"); /* fix it up if it is relayed. */ qf = qfs->mms_queue_add(from, to, NULL, h->m->id, mmc_id, 0, time(NULL) + default_msgexpiry, m, NULL, @@ -251,7 +280,7 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) octstr_get_cstr(qdir), "MM7/SOAP-IN", NULL); - else + } else qf = NULL; if (qf) /* Log to access log */ @@ -282,7 +311,9 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) case MM7_TAG_ReadReplyReq: if (mmc_id != NULL) { /* internal routing. */ m = mm7_soap_to_mmsmsg(mreq, from); - if (m) + + if (m) { + fixup_relayed_report(m, h->m, "read-report"); /* fix it up if it is relayed. */ qf = qfs->mms_queue_add(from, to, NULL, h->m->id, mmc_id, 0, time(NULL) + default_msgexpiry, m, NULL, @@ -293,7 +324,7 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) octstr_get_cstr(qdir), "MM7/SOAP-IN", NULL); - else + } else qf = NULL; if (qf) /* Log to access log */ @@ -475,6 +506,7 @@ static int mm7eaif_receive(MmsBoxHTTPClientInfo *h) break; case MMS_MSGTYPE_DELIVERY_IND: if (mmc_id != NULL) { /* internal routing. */ + fixup_relayed_report(m, h->m, "delivery-report"); /* fix it up if it is relayed. */ qf = qfs->mms_queue_add(hfrom, to, NULL, h->m->id, mmc_id, 0, time(NULL) + default_msgexpiry, m, NULL, @@ -505,6 +537,7 @@ static int mm7eaif_receive(MmsBoxHTTPClientInfo *h) case MMS_MSGTYPE_READ_ORIG_IND: if (mmc_id != NULL) { /* internal routing. */ + fixup_relayed_report(m, h->m, "read-report"); /* fix it up if it is relayed. */ qf = qfs->mms_queue_add(hfrom, to, NULL, h->m->id, mmc_id, 0, time(NULL) + default_msgexpiry, m, NULL, @@ -567,19 +600,20 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) List *to = NULL; Octstr *hto = NULL, *subject = NULL, *msgid = NULL; - Octstr *hfrom = NULL, *body; + Octstr *hfrom = NULL, *body, *rr_uri = NULL, *dlr_uri = NULL; time_t expiryt = -1, deliveryt = -1; Octstr *qf = NULL, *mmc_id = NULL, *qdir = NULL, *s; int msize; - int dlr; + int dlr, rr; int mtype; - List *cgivars_ctypes = NULL; + List *cgivars_ctypes = NULL, *rqh = http_create_empty_headers(); parse_cgivars(h->headers, h->body, &h->cgivars, &cgivars_ctypes); hfrom = http_cgi_variable(h->cgivars, "from"); hto = http_cgi_variable(h->cgivars, "to"); body = http_cgi_variable(h->cgivars, "mms"); + msize = octstr_len(body); debug("mmsbox.mm7http.sendinterface", 0, @@ -638,16 +672,25 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) case MMS_MSGTYPE_SEND_REQ: case MMS_MSGTYPE_RETRIEVE_CONF: - /* Get Message ID */ - if ((msgid = http_cgi_variable(h->cgivars, "message-id")) != NULL) - mms_replace_header_value(m, "Message-ID", octstr_get_cstr(msgid)); - + /* Get/make a Message ID */ + if ((msgid = mms_get_header_value(m, octstr_imm("Message-ID"))) == NULL) { /* Make a message id for it directly. We need it below. */ + msgid = mms_make_msgid(NULL, NULL); + mms_replace_header_value(m, "Message-ID", octstr_get_cstr(msgid)); + } + if ((value = http_header_value(mh, octstr_imm("X-Mms-Delivery-Report"))) != NULL && octstr_case_compare(value, octstr_imm("Yes")) == 0) dlr = 1; else dlr = 0; octstr_destroy(value); + + if ((value = http_header_value(mh, octstr_imm("X-Mms-Read-Report"))) != NULL && + octstr_case_compare(value, octstr_imm("Yes")) == 0) + rr = 1; + else + rr = 0; + octstr_destroy(value); if (deliveryt < 0) deliveryt = time(NULL); @@ -661,14 +704,29 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) mms_remove_headers(m, "X-Mms-Sender-Visibility"); MOD_SUBJECT(m, h->m, hfrom); + + + if (qdir == outgoing_qdir) { /* We need to remember the old message ID so we can re-write it + * if a DLR is relayed backwards. + */ + Octstr *t = mms_maketransid(NULL, octstr_imm(MM_NAME)); /* make a fake transaction id so dlr works*/ + + http_header_add(rqh, "X-Mbuni-TransactionID", octstr_get_cstr(t)); + if (dlr) + dlr_uri = octstr_format("msgid:%S", msgid); + if (rr) + rr_uri = octstr_format("msgid:%S", msgid); + + octstr_destroy(t); + } /* Save it, put message id in header, return. */ qf = qfs->mms_queue_add(hfrom, to, subject, h->m->id, mmc_id, deliveryt, expiryt, m, NULL, NULL, NULL, - NULL, NULL, - NULL, + dlr_uri, rr_uri, + rqh, dlr, octstr_get_cstr(qdir), "MM7/HTTP-IN", @@ -684,12 +742,15 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) break; case MMS_MSGTYPE_DELIVERY_IND: if (mmc_id != NULL) { /* internal routing. */ + + fixup_relayed_report(m, h->m, "delivery-report"); /* fix it up if it is relayed. */ + 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, + rqh, 0, octstr_get_cstr(qdir), "MM7/HTTP-IN", @@ -704,6 +765,7 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) } else { Octstr *value = http_header_value(mh, octstr_imm("X-Mms-Status")); Octstr *value2 = http_header_value(mh, octstr_imm("Message-ID")); + mmsbox_send_report(hfrom, "delivery-report", NULL, value, value2, h->m->id, h->m->group_id, NULL, NULL, -1); @@ -715,12 +777,14 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) case MMS_MSGTYPE_READ_ORIG_IND: if (mmc_id != NULL) { /* internal routing. */ + fixup_relayed_report(m, h->m, "read-report"); /* fix it up if it is relayed. */ + 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, + rqh, 0, octstr_get_cstr(qdir), "MM7/HTTP-IN", @@ -747,7 +811,7 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) http_header_add(rh, "X-Mbuni-Version", VERSION); - http_send_reply(h->client, hstatus, rh, qf ? qf : octstr_imm("")); + http_send_reply(h->client, hstatus, rh, msgid ? msgid : (qf ? qf : octstr_imm(""))); gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy); @@ -755,9 +819,12 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) octstr_destroy(qf); octstr_destroy(mmc_id); - + octstr_destroy(msgid); + http_destroy_headers(mh); http_destroy_headers(rh); + http_destroy_headers(rqh); + if (m) mms_destroy(m); @@ -1112,7 +1179,7 @@ static Octstr *mm7http_send(MmscGrp *mmc, Octstr *from, Octstr *to, add_multipart_form_field(form_data, "to", "text/plain", NULL, to); add_multipart_form_field(form_data, "from", "text/plain", NULL, from); add_multipart_form_field(form_data, "mms", "application/vnd.wap.mms-message", NULL, mms); - + rh = mime_entity_headers(form_data); body = mime_entity_body(form_data); @@ -1300,23 +1367,21 @@ static int sendMsg(MmsEnvelope *e) /* 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); + cdrfs->logcdr(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); } if (err == NULL) diff --git a/mbuni/mmsbox/dlr.c b/mbuni/mmsbox/dlr.c index f7cb211..6e78f81 100644 --- a/mbuni/mmsbox/dlr.c +++ b/mbuni/mmsbox/dlr.c @@ -127,8 +127,11 @@ void mms_dlr_url_remove(Octstr *msgid, char *rtype, Octstr *mmc_gid) Octstr *fname = NULL; int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_gid, &fname); - if (fname) + if (fname) { unlink(octstr_get_cstr(fname)); + octstr_destroy(fname); + } if (fd >= 0) - close(fd); + close(fd); + } diff --git a/mbuni/mmsbox/mmsbox.c b/mbuni/mmsbox/mmsbox.c index 1dada37..21e0ab4 100644 --- a/mbuni/mmsbox/mmsbox.c +++ b/mbuni/mmsbox/mmsbox.c @@ -555,25 +555,24 @@ done: 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); + cdrfs->logcdr(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); } 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 index a17fae0..ec112d2 100644 --- a/mbuni/mmsbox/mmsbox_cdr.c +++ b/mbuni/mmsbox/mmsbox_cdr.c @@ -22,6 +22,32 @@ static List *req_list; static long th_id; +#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; + + static void cdr_logger_func(void) { @@ -93,23 +119,8 @@ static int module_fini(void) 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, +static void 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 @@ -143,6 +154,33 @@ void mmsbox_fill_cdr_struct(MmsBoxCdrStruct *cdr, cdr->msg_size = msg_size; } +static int cdr_module_logcdr(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) +{ + MmsBoxCdrStruct *xcdr = gw_malloc(sizeof *xcdr); + + gw_assert(req_list); + + + fill_cdr_struct(xcdr, sdate, from, to, msgid, mmsc_id, src_int, dst_int, +#if 0 + src_ip, dst_ip, +#endif + msg_size, msgtype, prio, mclass, status, dlr, rr); + + gwlist_produce(req_list, xcdr); + + return 0; + +} + MmsBoxCdrFuncStruct mmsbox_cdrfuncs = { cdr_module_init, diff --git a/mbuni/mmsbox/mmsbox_cdr.h b/mbuni/mmsbox/mmsbox_cdr.h index ef51591..3f655d8 100644 --- a/mbuni/mmsbox/mmsbox_cdr.h +++ b/mbuni/mmsbox/mmsbox_cdr.h @@ -21,30 +21,6 @@ /* 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 { @@ -52,22 +28,19 @@ typedef struct MmsBoxCdrFuncStruct { int (*init)(char *settings); /* This function logs a cdr to wherever it is logging to. */ - int (*logcdr)(MmsBoxCdrStruct *cdr); + int (*logcdr)(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); 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