diff --git a/mbuni/ChangeLog b/mbuni/ChangeLog index e614699..9be5022 100644 --- a/mbuni/ChangeLog +++ b/mbuni/ChangeLog @@ -1,3 +1,7 @@ +2010-10-19 P. A. Bagyenda + * Added new func to mms_cfg -- make it easier to implement module-based configuration + * Extended mmsbox_cfg load functions to make it easier to configure using modules + * Added alarm callback, event logging. 2010-09-21 P. A. Bagyenda * Patch to allow compilation under FreeBSD 8.1 (thanks to Piotr Isajew ) 2010-08-09 P. A. Bagyenda diff --git a/mbuni/mmlib/mms_cfg.c b/mbuni/mmlib/mms_cfg.c index 9501f25..609717f 100644 --- a/mbuni/mmlib/mms_cfg.c +++ b/mbuni/mmlib/mms_cfg.c @@ -123,6 +123,19 @@ static void check_and_add_field(mCfgGrp *grp, Octstr *field, Octstr *value, int octstr_get_cstr(field), lineno); } +static mCfg *make_cfg(Octstr *file) +{ + mCfg *cfg; + + cfg = gw_malloc(sizeof *cfg); + cfg->file = file ? octstr_duplicate(file) : NULL; + cfg->grps = dict_create(7, NULL); + + cfg->xcfg = NULL; + cfg->cfg_funcs = NULL; + return cfg; +} + mCfg *mms_cfg_read(Octstr *file) { Octstr *sf; @@ -139,12 +152,7 @@ mCfg *mms_cfg_read(Octstr *file) return NULL; } - cfg = gw_malloc(sizeof *cfg); - cfg->file = octstr_duplicate(file); - cfg->grps = dict_create(7, NULL); - - cfg->xcfg = NULL; - cfg->cfg_funcs = NULL; + cfg = make_cfg(file); lines = octstr_split(sf, octstr_imm("\n")); for (i = 0, n = gwlist_len(lines); i < n; i++) { @@ -236,6 +244,26 @@ mCfg *mms_cfg_read(Octstr *file) return cfg; } +mCfg *mms_cfg_read2(mCfgImpFuncs *cfgfuncs, Octstr *init) +{ + mCfg *cfg; + + gw_assert(cfgfuncs); + + cfg = make_cfg(NULL); + + + cfg->cfg_funcs = cfgfuncs; + + if (cfg->cfg_funcs->read == NULL || + (cfg->xcfg = cfg->cfg_funcs->read(init)) == NULL) { + mms_error(0, "mms_cfg", NULL, "Failed to load cfg reader: read failed in cfg_read2!"); + mms_cfg_destroy(cfg); + cfg = NULL; + } + return cfg; +} + static void mGrp_destroy(mCfgGrp *grp) { octstr_destroy(grp->name); diff --git a/mbuni/mmlib/mms_cfg.h b/mbuni/mmlib/mms_cfg.h index ff7ef9f..6455f15 100644 --- a/mbuni/mmlib/mms_cfg.h +++ b/mbuni/mmlib/mms_cfg.h @@ -20,11 +20,14 @@ typedef struct mCfg mCfg; /* config file structure. */ typedef struct mCfgGrp mCfgGrp; /* A config group. */ - +struct mCfgImpFuncs; /* Defined in mms_cfg-impl.h */ /* Read a config file, return the structure. */ mCfg *mms_cfg_read(Octstr *file); +/* Read conf from a module */ +mCfg *mms_cfg_read2(struct mCfgImpFuncs *cfgfuncs, Octstr *init); + /* Destroy it all . */ void mms_cfg_destroy(mCfg *cfg); diff --git a/mbuni/mmlib/mms_mm7soap.c b/mbuni/mmlib/mms_mm7soap.c index b4f51d7..0bf0409 100644 --- a/mbuni/mmlib/mms_mm7soap.c +++ b/mbuni/mmlib/mms_mm7soap.c @@ -755,7 +755,7 @@ int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, MM7Version_t *ver, List **hdrs, Octstr int mm7_msgtype(MSoapMsg_t *m) { - Octstr *typ = http_header_value(m->envelope, octstr_imm("MessageType")); + Octstr *typ = m != NULL ? http_header_value(m->envelope, octstr_imm("MessageType")) : NULL; int ret; if (!typ) @@ -1011,6 +1011,30 @@ static MSoapMsg_t *mm7_soap_create(int msgtype, Octstr *otransid) return m; } +int mm7_msgtype_to_soaptype(int mtype, int isclientside) +{ + int t; + switch (mtype) { + case MMS_MSGTYPE_SEND_REQ: + case MMS_MSGTYPE_RETRIEVE_CONF: + t = isclientside ? MM7_TAG_SubmitReq : MM7_TAG_DeliverReq; + break; + case MMS_MSGTYPE_READ_ORIG_IND: + t = MM7_TAG_ReadReplyReq; + break; + case MMS_MSGTYPE_DELIVERY_IND: + t = MM7_TAG_DeliveryReportReq; + break; + case -1: + t = isclientside ? MM7_TAG_RSErrorRsp : MM7_TAG_VASPErrorRsp; + break; + default: + t = 0; + break; + } + return t; +} + MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto, Octstr *transid, Octstr *srvcode, Octstr *linkedid, int isclientside, @@ -1019,33 +1043,47 @@ MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto, time_t uaprof_tstamp, List *hdrs) { - int i, n, mtype = mms_messagetype(msg); + int i, n, mtype = mms_messagetype(msg), mm7type = mm7_msgtype_to_soaptype(mtype, isclientside); MSoapMsg_t *m = NULL; Octstr *xfrom = (from != NULL) ? octstr_format("+ %S", from) : NULL, *s; Octstr *xuaprof_val = (uaprof) ? octstr_format("%S,%ld", uaprof, uaprof_tstamp) : NULL; - + int tchanged = 0; + switch(mtype) { case MMS_MSGTYPE_SEND_REQ: case MMS_MSGTYPE_RETRIEVE_CONF: - m = mm7_soap_create(isclientside ? MM7_TAG_SubmitReq : MM7_TAG_DeliverReq, - transid); - m->msg = mms_tomime(msg,1); + + s = hdrs ? http_header_value(hdrs, octstr_imm("X-Mbuni-MM7-Type")) : NULL; + if (s) { /* Might be Cancel or Replace instead of Send */ + mm7type = mms_string_to_mm7tag(s); + gw_assert(mm7type >= 0); + octstr_destroy(s); + tchanged = 1; + } + m = mm7_soap_create(mm7type, transid); + if (mm7type != MM7_TAG_CancelReq) /* No body for cancel */ + m->msg = mms_tomime(msg,1); strip_non_essential_headers(m->msg); - for (i = 0, n = xto ? gwlist_len(xto) : 0; i < n; i++) { /* Add recipients. */ - Octstr *xx = octstr_format("+ %S", gwlist_get(xto, i)); - http_header_add(m->envelope, "To", - octstr_get_cstr(xx)); - octstr_destroy(xx); + if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq) /* No recipients for replace and cancel*/ + for (i = 0, n = xto ? gwlist_len(xto) : 0; i < n; i++) { /* Add recipients. */ + Octstr *xx = octstr_format("+ %S", gwlist_get(xto, i)); + http_header_add(m->envelope, "To", + octstr_get_cstr(xx)); + octstr_destroy(xx); + } + else if ((s = http_header_value(hdrs, /* For replace and cancel, add message id */ + octstr_imm("X-Mbuni-Message-ID"))) != NULL) { + http_header_add(m->envelope, "MessageID", octstr_get_cstr(s)); + octstr_destroy(s); } - - if (srvcode) + if (srvcode && mm7type != MM7_TAG_CancelReq) http_header_add(m->envelope, isclientside ? "ServiceCode" : "MMSRelayServerID", octstr_get_cstr(srvcode)); - if (linkedid) + if (linkedid && mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq) http_header_add(m->envelope, "LinkedID", octstr_get_cstr(linkedid)); if (xfrom) http_header_add(m->envelope, @@ -1062,7 +1100,8 @@ MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto, http_header_add(m->envelope, "VASID", vasid); if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Message-Class"))) != NULL) { - http_header_add(m->envelope, "MessageClass", octstr_get_cstr(s)); + if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq) + http_header_add(m->envelope, "MessageClass", octstr_get_cstr(s)); octstr_destroy(s); } @@ -1070,26 +1109,28 @@ MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto, if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Allow-Adaptations"))) != NULL) { char *val = (octstr_case_compare(s, octstr_imm("true")) == 0) ? "true" : "false"; - http_header_add(m->envelope, "allowAdaptations", val); + if (mm7type != MM7_TAG_CancelReq) + http_header_add(m->envelope, "allowAdaptations", val); octstr_destroy(s); } - if (distrib_indicator) + if (distrib_indicator && mm7type != MM7_TAG_CancelReq) http_header_add(m->envelope, "DistributionIndicator", octstr_str_case_compare(distrib_indicator, "true") == 0 ? "true" : "false"); - if (cparty) + if (cparty && mm7type != MM7_TAG_CancelReq) http_header_add(m->envelope, "ChargedParty", octstr_get_cstr(cparty)); octstr_destroy(distrib_indicator); octstr_destroy(cparty); } else { /* not clientside. */ - if (xuaprof_val) /* only on DeliverReq. */ + if (xuaprof_val && mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq) /* only on DeliverReq. */ http_header_add(m->envelope, "UACapabilities", octstr_get_cstr(xuaprof_val)); } if ((s = mms_get_header_value(msg, octstr_imm("Date"))) != NULL) { - http_header_add(m->envelope, "TimeStamp", octstr_get_cstr(s)); + if (mm7type != MM7_TAG_CancelReq) + http_header_add(m->envelope, "TimeStamp", octstr_get_cstr(s)); octstr_destroy(s); } @@ -1097,36 +1138,41 @@ MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto, * care about the order of XML fields. */ if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Expiry"))) != NULL) { - http_header_add(m->envelope, "ExpiryDate", octstr_get_cstr(s)); + if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq) + http_header_add(m->envelope, "ExpiryDate", octstr_get_cstr(s)); octstr_destroy(s); } if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Delivery-Report"))) != NULL) { char *val = (octstr_case_compare(s, octstr_imm("Yes")) == 0) ? "true" : "false"; - http_header_add(m->envelope, "DeliveryReport", val); + if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq) + http_header_add(m->envelope, "DeliveryReport", val); octstr_destroy(s); } if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Read-Report"))) != NULL) { char *val = (octstr_case_compare(s, octstr_imm("Yes")) == 0) ? "true" : "false"; - http_header_add(m->envelope, "ReadReply", val); + if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq) + http_header_add(m->envelope, "ReadReply", val); octstr_destroy(s); } } if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Priority"))) != NULL) { - http_header_add(m->envelope, "Priority", octstr_get_cstr(s)); + if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq) + http_header_add(m->envelope, "Priority", octstr_get_cstr(s)); octstr_destroy(s); } if ((s = mms_get_header_value(msg, octstr_imm("Subject"))) != NULL) { - http_header_add(m->envelope, "Subject", octstr_get_cstr(s)); + if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq) + http_header_add(m->envelope, "Subject", octstr_get_cstr(s)); octstr_destroy(s); } - + #if 0 /* handled above. */ /* Should we bother to strip message part of headers??? */ headers = mime_entity_headers(m->msg); @@ -1144,9 +1190,7 @@ MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto, break; case MMS_MSGTYPE_READ_ORIG_IND: case MMS_MSGTYPE_DELIVERY_IND: - m = mm7_soap_create((mtype == MMS_MSGTYPE_READ_ORIG_IND) ? - MM7_TAG_ReadReplyReq : MM7_TAG_DeliveryReportReq, - transid); + m = mm7_soap_create(mm7type, transid); if (xfrom) http_header_add(m->envelope, "Sender", octstr_get_cstr(xfrom)); @@ -1188,10 +1232,37 @@ MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto, break; } + if (m) { /* Add custom headers, hope caller knows what they are doing */ + List *l = http_header_find_all(hdrs, "X-Mbuni-MM7-Headers"); + int i, n; + + + for (i = 0, n = gwlist_len(l); i 0) { + Octstr *h = octstr_copy(value, 0, j - 1); + Octstr *v = octstr_copy(value, j+1, octstr_len(value)); + + octstr_strip_blanks(h); + octstr_strip_blanks(v); + + http_header_add(m->envelope, octstr_get_cstr(h), octstr_get_cstr(v)); + + octstr_destroy(h); + octstr_destroy(v); + } + octstr_destroy(name); + octstr_destroy(value); + } + http_destroy_headers(l); + } octstr_destroy(xfrom); octstr_destroy(xuaprof_val); - return m; } diff --git a/mbuni/mmlib/mms_mm7soap.h b/mbuni/mmlib/mms_mm7soap.h index b591a28..7264c76 100644 --- a/mbuni/mmlib/mms_mm7soap.h +++ b/mbuni/mmlib/mms_mm7soap.h @@ -39,6 +39,9 @@ typedef struct MM7Version_t { /* Parse SOAP message given http headers and body. */ extern MSoapMsg_t *mm7_parse_soap(List *headers, Octstr *body); +/* Convert message type to mm7 type code */ +extern int mm7_msgtype_to_soaptype(int mtype, int isclientside); + /* Convert SOAP message to http headers and body. */ extern int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, MM7Version_t *ver, List **hdrs, Octstr **body); diff --git a/mbuni/mmlib/mms_msg.c b/mbuni/mmlib/mms_msg.c index 9b4102f..e50e7a3 100644 --- a/mbuni/mmlib/mms_msg.c +++ b/mbuni/mmlib/mms_msg.c @@ -1955,7 +1955,7 @@ MmsMsg *mms_deleteconf(int menc, char *transid) return m; } -static int mms_msgsize(MmsMsg *m) +int mms_msgsize(MmsMsg *m) { Octstr *s; int n; diff --git a/mbuni/mmlib/mms_msg.h b/mbuni/mmlib/mms_msg.h index 513dcc7..c9c236a 100644 --- a/mbuni/mmlib/mms_msg.h +++ b/mbuni/mmlib/mms_msg.h @@ -130,4 +130,7 @@ int mms_putbody(MmsMsg *msg, void *body, int ismultipart); * returns 0 on success. */ int mms_make_sendreq(MmsMsg *retrieveconf); + +/* Compute message size -- not altogether efficiently */ +int mms_msgsize(MmsMsg *m); #endif diff --git a/mbuni/mmlib/mms_util.c b/mbuni/mmlib/mms_util.c index de9c312..97b3dcb 100644 --- a/mbuni/mmlib/mms_util.c +++ b/mbuni/mmlib/mms_util.c @@ -1171,77 +1171,80 @@ void mms_collect_envdata_from_msgheaders(List *mh, List **xto, { Octstr *s; - List *l = http_header_find_all(mh, "To"); - if (l) { - int i, n; - for (i = 0, n = gwlist_len(l); i 0 - && (*expiryt - time(NULL)) > max_msgexpiry) - *expiryt = time(NULL) + max_msgexpiry; + s = http_header_value(mh, octstr_imm("X-Mms-Expiry")); + if (s) { + *expiryt = date_parse_http(s); + octstr_destroy(s); + } else + *expiryt = time(NULL) + default_msgexpiry; + + if (max_msgexpiry > 0 + && (*expiryt - time(NULL)) > max_msgexpiry) + *expiryt = time(NULL) + max_msgexpiry; } - + if (deliveryt) { - s = http_header_value(mh, octstr_imm("X-Mms-Delivery-Time")); - if (s) { - *deliveryt = date_parse_http(s); - octstr_destroy(s); - } else - *deliveryt = 0; + s = http_header_value(mh, octstr_imm("X-Mms-Delivery-Time")); + if (s) { + *deliveryt = date_parse_http(s); + octstr_destroy(s); + } else + *deliveryt = 0; } if (subject) - *subject = http_header_value(mh, octstr_imm("Subject")); - + *subject = http_header_value(mh, octstr_imm("Subject")); + if (otransid) - *otransid = http_header_value(mh, octstr_imm("X-Mms-Transaction-ID")); - + *otransid = http_header_value(mh, octstr_imm("X-Mms-Transaction-ID")); } unsigned long _mshash(char *s) @@ -2155,41 +2158,41 @@ MIMEEntity *multipart_from_urls(List *url_list) http_header_add(rh, "User-Agent", MM_NAME "/" VERSION); for (i = 0, n = gwlist_len(url_list); igroup_id); /* only remove if not - * interim status - */ + * interim status + */ #endif } octstr_destroy(newmsgid); @@ -208,11 +206,16 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) unsigned char *msgtype = (unsigned char *)""; Octstr *qf = NULL, *mmc_id = NULL, *qdir = NULL; List *qhdr = http_create_empty_headers(); - + Octstr *r, *s, *transid = NULL, *value = NULL; + if (h->body) mreq = mm7_parse_soap(h->headers, h->body); - if (mreq) + if (mreq) { msgtype = mms_mm7tag_to_cstr(mm7_msgtype(mreq)); + MMSC_CLEAR_ALARM(h->m, MMSBOX_ALARM_MM7_PARSING_FAILURE); + } else + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_MM7_PARSING_FAILURE, 3); + debug("mmsbox.mm7sendinterface", 0, " --> Enterred mm7dispatch interface, mreq=[%s] mtype=[%s] <-- ", mreq ? "Ok" : "Null", @@ -230,10 +233,11 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) if (!from) from = octstr_create("anon@anon"); + qdir = get_mmsbox_queue_dir(from, to, h->m, &mmc_id); /* get routing info. */ switch (mm7_msgtype(mreq)) { - Octstr *value, *value2; + Octstr *value2; case MM7_TAG_DeliverReq: m = mm7_soap_to_mmsmsg(mreq, from); @@ -282,20 +286,23 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) mms_error(0, "MM7", h->m->id, "Failed to write queue entry for received MM7/SOAP DeliverReq message from mmc=%s to MMS Message!", octstr_get_cstr(h->m->id)); - } else { + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4); + } else { + MMSC_CLEAR_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR); + msgid = mms_make_msgid(octstr_get_cstr(qf), NULL); mms_log("Received", from, to, -1, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL); } octstr_destroy(linkedid); - octstr_destroy(value); + http_destroy_headers(qh); } else { mms_error(0, "MM7", h->m->id, - "Failed to convert received MM7/SOAP DeliverReq message from mmc=%s to MMS Message!", - octstr_get_cstr(h->m->id)); + "Failed to convert received MM7/SOAP DeliverReq message from mmc=%s to MMS Message!", + octstr_get_cstr(h->m->id)); status = 4000; } mresp = mm7_make_resp(mreq, status, NULL,1); @@ -333,14 +340,17 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) octstr_get_cstr(qdir), "MM7/SOAP-IN", NULL); - if (qf) + if (qf) { /* Log to access log */ mms_log("Received DLR", from, to, -1, msgid, value, h->m->id, "MMSBox", h->ua, NULL); - else - status = 4000; + MMSC_CLEAR_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR); + } else { + status = 4000; + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR,3); + } mresp = mm7_make_resp(mreq, status, NULL,1); - octstr_destroy(value); + octstr_destroy(value2); break; @@ -362,15 +372,16 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) octstr_get_cstr(qdir), "MM7/SOAP-IN", NULL); - if (qf) + if (qf) { + MMSC_CLEAR_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR); /* Log to access log */ mms_log("Received RR", from, to, -1, msgid, value, h->m->id, "MMSBox", h->ua, NULL); - else + } else { + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4); status = 4000; - + } mresp = mm7_make_resp(mreq, status, NULL,1); - octstr_destroy(value); octstr_destroy(value2); break; @@ -380,12 +391,34 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) break; } - done: + + /* Invoke call back */ + s = mm7_soap_header_value(mreq, octstr_imm("MM7Version")); + r = mm7_soap_header_value(mreq, octstr_imm("MessageID")); + transid = mm7_soap_header_value(mreq, octstr_imm("TransactionID")); + mmsbox_event_cb(h->m->id, mm7_msgtype(mreq), 0, s, 0, + octstr_len(h->body), 0, from, + to && gwlist_len(to) > 0 ? gwlist_get(to,0) : NULL, r, transid, NULL, value); + octstr_destroy(s); + octstr_destroy(r); + +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 http_close_client(h->client); + if (mresp) { + Octstr *s = octstr_format("%d.%d.%d", h->m->ver.major, h->m->ver.minor1, h->m->ver.minor2); + Octstr *r = mm7_soap_header_value(mresp, octstr_imm("MessageID")); + mmsbox_event_cb(h->m->id, mm7_msgtype(mresp), 0, s, status, + octstr_len(reply_body), 0, to && gwlist_len(to) > 0 ? gwlist_get(to,0) : NULL, + from, r, transid, NULL, NULL); + octstr_destroy(s); + octstr_destroy(r); + } else + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_MM7_PARSING_FAILURE, 2); + debug("mmsbox.mm7sendinterface", 0, " --> leaving mm7dispatch interface, mresp=[%s], body=[%s], mm7_status=[%d] <-- ", mresp ? "ok" : "(null)", @@ -405,6 +438,8 @@ static int mm7soap_receive(MmsBoxHTTPClientInfo *h) gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy); octstr_destroy(mmc_id); http_destroy_headers(qhdr); + octstr_destroy(value); + octstr_destroy(transid); return MM7_SOAP_STATUS_OK(status) ? 0 : -1; } @@ -446,9 +481,12 @@ static int queue_dlr(MmscGrp *mmc, Octstr *from, Octstr *to, Octstr *msgid, Octs /* Log to access log */ mms_log("Received DLR", from, lto, -1, msgid, status, mmc ? mmc->id : NULL, "MMSBox", NULL, NULL); ret = 0; - } else + MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_QUEUE_WRITE_ERROR); + } else { + MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4); ret = -1; - + } + octstr_destroy(qf); http_destroy_headers(rqh); octstr_destroy(rr_uri); @@ -470,13 +508,13 @@ static int mm7eaif_receive(MmsBoxHTTPClientInfo *h) Octstr *reply_body = NULL, *value = NULL, *value2 = NULL; List *to = gwlist_create(), *hto = NULL; - Octstr *subject = NULL, *otransid = NULL, *msgid = NULL; + Octstr *subject = NULL, *otransid = NULL, *msgid = NULL, *s; Octstr *hfrom = NULL, *rr_uri = NULL; time_t expiryt = -1, deliveryt = -1; Octstr *qf = NULL, *xver = NULL, *mmc_id = NULL, *qdir = NULL; int msize = h->body ? octstr_len(h->body) : 0; int dlr; - int mtype; + int mtype = -1, mm7type = -1; debug("mmsbox.mm7eaif.sendinterface", 0, " --> Enterred eaif send interface, blen=[%d] <--- ", @@ -488,12 +526,15 @@ static int mm7eaif_receive(MmsBoxHTTPClientInfo *h) http_header_add(rh, "Content-Type", "text/plain"); hstatus = HTTP_BAD_REQUEST; reply_body = octstr_format("Unexpected MMS message, no body?"); - + + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_MM7_PARSING_FAILURE,2); goto done; - } + } else + MMSC_CLEAR_ALARM(h->m, MMSBOX_ALARM_MM7_PARSING_FAILURE); /* XXXX handle delivery reports differently. */ mtype = mms_messagetype(m); + mm7type = mm7_msgtype_to_soaptype(mtype, 1); mh = mms_message_headers(m); /* Now get sender and receiver data. * for now we ignore adaptation flags. @@ -581,12 +622,13 @@ static int mm7eaif_receive(MmsBoxHTTPClientInfo *h) if (qf) { /* Log to access log */ mms_log("Received", hfrom, to, msize, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL); - - hstatus = HTTP_NO_CONTENT; - } else - hstatus = HTTP_INTERNAL_SERVER_ERROR; - octstr_destroy(value); + hstatus = HTTP_NO_CONTENT; + MMSC_CLEAR_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR); + } else { + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4); + hstatus = HTTP_INTERNAL_SERVER_ERROR; + } octstr_destroy(value2); break; case MMS_MSGTYPE_DELIVERY_IND: @@ -613,11 +655,12 @@ static int mm7eaif_receive(MmsBoxHTTPClientInfo *h) if (qf) { /* Log to access log */ mms_log("DeliveryReport", hfrom, to, -1, msgid, value, h->m->id, "MMSBox", h->ua, NULL); - + MMSC_CLEAR_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR); hstatus = HTTP_NO_CONTENT; - } else + } else { hstatus = HTTP_INTERNAL_SERVER_ERROR; - octstr_destroy(value); + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4); + } octstr_destroy(value2); break; @@ -645,22 +688,37 @@ static int mm7eaif_receive(MmsBoxHTTPClientInfo *h) /* Log to access log */ mms_log("Received RR", hfrom, to, -1, msgid, value, h->m->id, "MMSBox", h->ua, NULL); hstatus = HTTP_NO_CONTENT; - } else + MMSC_CLEAR_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR); + } else { + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4); hstatus = HTTP_INTERNAL_SERVER_ERROR; - - octstr_destroy(value); + } octstr_destroy(value2); break; } - done: + + s = http_header_value(h->headers, octstr_imm("X-NOKIA-MMSC-Version")); + mmsbox_event_cb(h->m->id, mm7type, 0, s, 0, + msize, 0, hfrom, + to && gwlist_len(to) > 0 ? gwlist_get(to,0) : NULL, + msgid, otransid, NULL, value); + octstr_destroy(s); +done: xver = octstr_format(EAIF_VERSION, h->m->ver.major, h->m->ver.minor1); http_header_add(rh, "X-NOKIA-MMSC-Version", octstr_get_cstr(xver)); + + + mmsbox_event_cb(h->m->id, mm7type >= 0 ? mm7type + 1 : MM7_TAG_VASPErrorRsp, 0, + xver, hstatus, + 0, 0, to && gwlist_len(to) > 0 ? gwlist_get(to,0) : NULL, + hfrom, + msgid, otransid, NULL, reply_body); + + http_send_reply(h->client, hstatus, rh, reply_body ? reply_body : octstr_imm("")); + octstr_destroy(xver); - - http_send_reply(h->client, hstatus, rh, octstr_imm("")); - http_destroy_headers(hto); http_destroy_headers(rqh); gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy); @@ -671,7 +729,8 @@ static int mm7eaif_receive(MmsBoxHTTPClientInfo *h) octstr_destroy(qf); octstr_destroy(mmc_id); octstr_destroy(rr_uri); - + octstr_destroy(value); + http_destroy_headers(mh); mms_destroy(m); @@ -690,10 +749,10 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) Octstr *hto = NULL, *subject = NULL, *msgid = NULL; 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; + Octstr *qf = NULL, *mmc_id = NULL, *qdir = NULL, *value = NULL, *s; int msize; int dlr, rr; - int mtype; + int mtype = -1, mm7type = -1; List *cgivars_ctypes = NULL, *rqh = http_create_empty_headers(); parse_cgivars(h->headers, h->body, &h->cgivars, &cgivars_ctypes); @@ -712,7 +771,8 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) http_header_add(rh, "Content-Type", "text/plain"); hstatus = HTTP_BAD_REQUEST; reply_body = octstr_format("Missing 'to' argument"); - + + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_MM7_PARSING_FAILURE, 3); goto done; } else if (hfrom == NULL) { @@ -720,6 +780,7 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) hstatus = HTTP_BAD_REQUEST; reply_body = octstr_format("Missing 'from' argument"); + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_MM7_PARSING_FAILURE, 3); goto done; } else if (body == NULL || /* A message is required, and must parse */ @@ -728,13 +789,16 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) hstatus = HTTP_BAD_REQUEST; reply_body = octstr_format("Unexpected MMS message, no content?"); + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_MM7_PARSING_FAILURE, 3); goto done; - } + } else + MMSC_CLEAR_ALARM(h->m, MMSBOX_ALARM_MM7_PARSING_FAILURE); to = octstr_split_words(hto); mtype = mms_messagetype(m); + mm7type = mm7_msgtype_to_soaptype(mtype, 1); mh = mms_message_headers(m); /* find interesting headers. */ @@ -757,7 +821,7 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) qdir = get_mmsbox_queue_dir(hfrom, to, h->m, &mmc_id); /* get routing info. */ switch(mtype) { - Octstr *value, *value2; + Octstr *value2; case MMS_MSGTYPE_SEND_REQ: case MMS_MSGTYPE_RETRIEVE_CONF: @@ -779,7 +843,7 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) rr = 1; else rr = 0; - octstr_destroy(value); + if (deliveryt < 0) deliveryt = time(NULL); @@ -796,8 +860,8 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) if (qdir == outgoing_qdir) { /* We need to remember the old message ID so we can re-write it - * if a DLR is relayed backwards. - */ + * 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)); @@ -823,11 +887,14 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) if (qf) { /* Log to access log */ + MMSC_CLEAR_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR); mms_log("Received", hfrom, to, msize, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL); hstatus = HTTP_OK; - } else + } else { hstatus = HTTP_INTERNAL_SERVER_ERROR; + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4); + } break; case MMS_MSGTYPE_DELIVERY_IND: msgid = mms_get_header_value(m, octstr_imm("Message-ID")); @@ -854,9 +921,11 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) mms_log("DeliveryReport", hfrom, to, -1, msgid,value, h->m->id, "MMSBox", h->ua, NULL); hstatus = HTTP_OK; - } else + MMSC_CLEAR_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR); + } else { hstatus = HTTP_INTERNAL_SERVER_ERROR; - octstr_destroy(value); + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4); + } octstr_destroy(value2); break; @@ -884,18 +953,32 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) /* Log to access log */ mms_log("Received RR", hfrom, to, -1, msgid, value, h->m->id, "MMSBox", h->ua, NULL); hstatus = HTTP_NO_CONTENT; - } else + MMSC_CLEAR_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR); + } else { hstatus = HTTP_INTERNAL_SERVER_ERROR; - octstr_destroy(value); + MMSC_ISSUE_ALARM(h->m, MMSBOX_ALARM_QUEUE_WRITE_ERROR, 4); + } octstr_destroy(value2); break; } - - done: + + + mmsbox_event_cb(h->m->id, mm7type, 0, octstr_imm("1.0"), 0, + msize, 0, hfrom, + to && gwlist_len(to) > 0 ? gwlist_get(to,0) : NULL, + msgid, octstr_imm("0000"), NULL, value); +done: + + + mmsbox_event_cb(h->m->id, mm7type >= 0 ? mm7type + 1 : MM7_TAG_VASPErrorRsp, 0, + octstr_imm("1.0"), hstatus, + 0, 0, to && gwlist_len(to) > 0 ? gwlist_get(to,0) : NULL, + hfrom, + msgid, octstr_imm("0001"), NULL, reply_body); http_header_add(rh, "X-Mbuni-Version", VERSION); - http_send_reply(h->client, hstatus, rh, msgid ? msgid : (qf ? qf : octstr_imm(""))); + http_send_reply(h->client, hstatus, rh, msgid ? msgid : reply_body ? reply_body : qf ? qf : octstr_imm("")); gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy); @@ -904,13 +987,14 @@ static int mm7http_receive(MmsBoxHTTPClientInfo *h) octstr_destroy(qf); octstr_destroy(mmc_id); octstr_destroy(msgid); - + octstr_destroy(reply_body); http_destroy_headers(mh); http_destroy_headers(rh); http_destroy_headers(rqh); + octstr_destroy(value); + octstr_destroy(hfrom); - if (m) - mms_destroy(m); + mms_destroy(m); http_destroy_cgiargs(cgivars_ctypes); @@ -923,6 +1007,7 @@ static void dispatch_mm7_recv(List *rl) MmsBoxHTTPClientInfo *h; + hmon->register_thread(); while ((h = gwlist_consume(rl)) != NULL) { int ret = -1, has_auth = 0; MmscGrp *m = h->m; @@ -956,6 +1041,7 @@ static void dispatch_mm7_recv(List *rl) h->m->mo_errors++; free_mmsbox_http_clientInfo(h, 1); } + hmon->unregister_thread(); } void mmsc_receive_func(MmscGrp *m) @@ -967,6 +1053,8 @@ void mmsc_receive_func(MmscGrp *m) gwlist_add_producer(mmsc_incoming_reqs); + hmon->register_thread(); + for (i = 0; iid, "HTTP: Incoming IP denied MMSC[%s] ip=[%s], ua=[%s], disconnected", - m->id ? octstr_get_cstr(m->id) : "(none)", - h.ip ? octstr_get_cstr(h.ip) : "(none)", - h.ua ? octstr_get_cstr(h.ua) : "(none)"); + m->id ? octstr_get_cstr(m->id) : "(none)", + h.ip ? octstr_get_cstr(h.ip) : "(none)", + h.ua ? octstr_get_cstr(h.ua) : "(none)"); http_send_reply(h.client, HTTP_FORBIDDEN, NULL, octstr_imm("Access denied.")); @@ -1019,6 +1107,7 @@ void mmsc_receive_func(MmscGrp *m) gwlist_destroy(mmsc_incoming_reqs, NULL); gw_free(thids); + hmon->unregister_thread(); debug("proxy", 0, "MMSBox: MM7 receiver [mmc=%s] Shutting down complete.", octstr_get_cstr(m->id)); } @@ -1033,11 +1122,12 @@ static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to, Octstr *linkedid, char *vasid, Octstr *service_code, - List *hdrs, + MmsEnvelope *e, MmsMsg *m, Octstr **error, List **errl, int *retry) { + List *hdrs = e ? e->hdrs : NULL; Octstr *ret = NULL; int mtype = mms_messagetype(m); int hstatus = HTTP_OK, tstatus = -1; @@ -1045,13 +1135,15 @@ static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to, MSoapMsg_t *mreq = NULL, *mresp = NULL; List *rh = NULL, *ph = NULL; Octstr *body = NULL, *rbody = NULL, *url = NULL; - Octstr *s; + Octstr *s, *r, *status_details = NULL; char *xvasid = vasid ? vasid : (mmc->default_vasid ? octstr_get_cstr(mmc->default_vasid) : NULL); + if (e == NULL || mmc == NULL) + goto done1; mms_info(0, "MM7", mmc->id, "MMSBox: Send[soap] to MMSC[%s], msg type [%s], from %s, to %s", - mmc->id ? octstr_get_cstr(mmc->id) : "", - mms_message_type_to_cstr(mtype), - octstr_get_cstr(from), octstr_get_cstr(to)); + mmc->id ? octstr_get_cstr(mmc->id) : "", + mms_message_type_to_cstr(mtype), + octstr_get_cstr(from), octstr_get_cstr(to)); gwlist_append(xto, to); @@ -1078,14 +1170,30 @@ static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to, if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) { *error = octstr_format("Failed to contact MMC[url=%S] => HTTP returned status=[%d]!", mmc->mmsc_url, hstatus); + if (hstatus < 0) + MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_SOCKET_CONNECT_FAILED, 3); + MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_MM7_NON_200_RESULT, 3); goto done1; + } else { + MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_MM7_NON_200_RESULT); + MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_SOCKET_CONNECT_FAILED); } - + /* Invoke call back */ + s = mm7_soap_header_value(mreq, octstr_imm("MM7Version")); + r = mm7_soap_header_value(mreq, octstr_imm("MessageID")); + mmsbox_event_cb(mmc->id, mm7_msgtype(mreq), 0, s, 0, + mms_msgsize(m), e->attempts, e->from, + to,r, transid, hdrs, NULL); + octstr_destroy(s); + octstr_destroy(r); if ((mresp = mm7_parse_soap(ph, rbody)) == NULL) { *error = octstr_format("Failed to parse MMSC[url=%S, id=%S] response!", mmc->mmsc_url, mmc->id); + + MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_MM7_PARSING_FAILURE, 3); goto done1; - } + } else + MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_MM7_PARSING_FAILURE); if (errl) { /* Pick up status stuff -- for DLR */ if (*errl == NULL) @@ -1105,36 +1213,46 @@ static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to, if ((s = mm7_soap_header_value(mresp, octstr_imm("StatusCode"))) != NULL) { tstatus = atoi(octstr_get_cstr(s)); octstr_destroy(s); + MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_MM7_PARSING_FAILURE); } else if ((s = mm7_soap_header_value(mresp, octstr_imm("faultstring"))) != NULL) { tstatus = atoi(octstr_get_cstr(s)); octstr_destroy(s); - } else + MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_MM7_PARSING_FAILURE); + } else { + MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_MM7_PARSING_FAILURE, 3); tstatus = MM7_SOAP_FORMAT_CORRUPT; + } - if (!MM7_SOAP_STATUS_OK(tstatus) && tstatus != MM7_SOAP_COMMAND_REJECTED) { - Octstr *detail = mm7_soap_header_value(mresp, octstr_imm("Details")); char *tmp = (char *)mms_soap_status_to_cstr(tstatus); + + Octstr *detail = mm7_soap_header_value(mresp, octstr_imm("Details")); if (detail == NULL) detail = mm7_soap_header_value(mresp, octstr_imm("faultcode")); ret = NULL; mms_info(0, "MM7", mmc->id, "Send to MMSC[%s], failed, code=[%d=>%s], detail=[%s]", - mmc ? octstr_get_cstr(mmc->id) : "", - tstatus, tmp ? tmp : "", - detail ? octstr_get_cstr(detail) : ""); + mmc ? octstr_get_cstr(mmc->id) : "", + tstatus, tmp ? tmp : "", + detail ? octstr_get_cstr(detail) : ""); *error = octstr_format("Failed to deliver to MMC[url=%S, id=%S], status=[%d=>%s]!", mmc->mmsc_url, mmc->id, tstatus, - tmp ? tmp : ""); - octstr_destroy(detail); + tmp ? tmp : ""); + status_details = detail ? octstr_duplicate(detail) : tmp ? octstr_create(tmp) : octstr_imm(""); + octstr_destroy(detail); } else { ret = mm7_soap_header_value(mresp, octstr_imm("MessageID")); mms_info(0, "MM7", NULL, "Sent to MMC[%s], code=[%d=>%s], msgid=[%s]", octstr_get_cstr(mmc->id), - tstatus, mms_soap_status_to_cstr(tstatus), ret ? octstr_get_cstr(ret) : "(none)"); + tstatus, mms_soap_status_to_cstr(tstatus), ret ? octstr_get_cstr(ret) : "(none)"); } + s = mm7_soap_header_value(mresp, octstr_imm("MM7Version")); + mmsbox_event_cb(mmc->id, mm7_msgtype(mresp), 0, s, tstatus, + 0, e->attempts, e->from, + to, ret, transid, hdrs, status_details); + octstr_destroy(s); if (ret) mms_log2("Sent", from, to, -1, ret, NULL, mmc->id, "MMSBox", NULL, NULL); @@ -1148,31 +1266,36 @@ done1: http_destroy_headers(ph); octstr_destroy(rbody); octstr_destroy(url); - gwlist_destroy(xto, NULL); - + octstr_destroy(status_details); + return ret; } static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to, Octstr *transid, char *vasid, - List *hdrs, + MmsEnvelope *e, MmsMsg *m, Octstr **error, int *retry) { + List *hdrs = e ? e->hdrs : NULL; Octstr *ret = NULL, *resp = NULL; int mtype = mms_messagetype(m); int hstatus = HTTP_OK; List *rh = http_create_empty_headers(), *ph = NULL; Octstr *body = NULL, *rbody = NULL, *xver = NULL; char *msgtype; + MmsMsg *mresp = NULL; + int mresp_type = -1; - + + if (e == NULL || mmc == NULL) + goto done; mms_info(0, "MM7", mmc->id, "MMSBox: Send [eaif] to MMC[%s], msg type [%s], from %s, to %s", - mmc ? octstr_get_cstr(mmc->id) : "", - mms_message_type_to_cstr(mtype), - octstr_get_cstr(from), octstr_get_cstr(to)); + mmc && mmc->id ? octstr_get_cstr(mmc->id) : "", + mms_message_type_to_cstr(mtype), + octstr_get_cstr(from), octstr_get_cstr(to)); http_header_remove_all(rh, "X-Mms-Allow-Adaptations"); http_header_add(rh, "X-NOKIA-MMSC-To", octstr_get_cstr(to)); @@ -1180,7 +1303,7 @@ static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to, xver = octstr_format(EAIF_VERSION, mmc->ver.major, mmc->ver.minor1); http_header_add(rh, "X-NOKIA-MMSC-Version", octstr_get_cstr(xver)); - octstr_destroy(xver); + if (mtype == MMS_MSGTYPE_SEND_REQ || mtype == MMS_MSGTYPE_RETRIEVE_CONF) { @@ -1203,24 +1326,32 @@ static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to, mms_replace_header_value(m,"X-Mms-Transaction-ID", transid ? octstr_get_cstr(transid) : "000"); body = mms_tobinary(m); + + mmsbox_event_cb(mmc->id, mm7_msgtype_to_soaptype(mtype,1), 0, xver, 0, + octstr_len(body), e->attempts, e->from, + to, NULL, transid, hdrs, NULL); hstatus = mmsbox_url_fetch_content(HTTP_METHOD_POST, mmc->mmsc_url, rh, body, &ph, &rbody); if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) { *error = octstr_format("Failed to contact MMC[url=%S] => HTTP returned status = %d !", mmc->mmsc_url, hstatus); + if (hstatus < 0) + MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_SOCKET_CONNECT_FAILED, 3); + MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_MM7_NON_200_RESULT, 3); } else { - MmsMsg *mresp = rbody ? mms_frombinary(rbody, octstr_imm("anon@anon")) : NULL; - + MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_MM7_NON_200_RESULT); + MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_SOCKET_CONNECT_FAILED); + + mresp = rbody ? mms_frombinary(rbody, octstr_imm("anon@anon")) : NULL; + mresp_type = mresp ? mms_messagetype(mresp) : -1; resp = octstr_imm("Ok"); - if (mresp && mms_messagetype(mresp) == MMS_MSGTYPE_SEND_CONF) + if (mresp_type == MMS_MSGTYPE_SEND_CONF) resp = mms_get_header_value(mresp, octstr_imm("X-Mms-Response-Status")); if (octstr_case_compare(resp, octstr_imm("ok")) != 0) hstatus = HTTP_STATUS_SERVER_ERROR; /* error. */ else if (mresp) ret = mms_get_header_value(mresp, octstr_imm("Message-ID")); - - mms_destroy(mresp); } if (hstatus < 0) @@ -1234,42 +1365,57 @@ static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to, ret = http_header_value(ph, octstr_imm("X-Nokia-MMSC-Message-Id")); } *retry = (ret == NULL && (hstatus == HTTP_STATUS_SERVER_ERROR || hstatus < 0)); - + + mmsbox_event_cb(mmc->id, + mm7_msgtype_to_soaptype(mresp_type,1), 0, xver, hstatus, + 0, e->attempts, e->from, + to, ret, transid, hdrs, resp); + if (ret) mms_log2("Sent", from, to, -1, ret, NULL, mmc->id, "MMSBox", NULL, NULL); #if 0 mms_info(0, "MM7", mmc->id,"Sent to MMC[%s], code=[%d], resp=[%s] msgid [%s]", - octstr_get_cstr(mmc->id), - hstatus, resp ? octstr_get_cstr(resp) : "(none)", ret ? octstr_get_cstr(ret) : "(none)"); + octstr_get_cstr(mmc->id), + hstatus, resp ? octstr_get_cstr(resp) : "(none)", ret ? octstr_get_cstr(ret) : "(none)"); #endif +done: + mms_destroy(mresp); http_destroy_headers(rh); octstr_destroy(body); http_destroy_headers(ph); octstr_destroy(rbody); octstr_destroy(resp); + octstr_destroy(xver); return ret; } -static Octstr *mm7http_send(MmscGrp *mmc, Octstr *from, Octstr *to, +static Octstr *mm7http_send(MmscGrp *mmc, + MmsEnvelope *e, + Octstr *from, Octstr *to, MmsMsg *m, Octstr **error, int *retry) { + List *hdrs = e ? e->hdrs : NULL; Octstr *ret = NULL; int mtype = mms_messagetype(m); int hstatus = HTTP_OK; - List *rh, *ph = NULL; + List *rh = NULL, *ph = NULL; Octstr *body = NULL, *rbody = NULL; - Octstr *mms; + Octstr *mms = NULL; MIMEEntity *form_data = make_multipart_formdata(); - + Octstr *transid = e ? octstr_create(e->xqfname) : NULL; + int mm7type = mm7_msgtype_to_soaptype(mtype,1); + + if (e == NULL || mmc == NULL) + goto done; mms_info(0, "MM7", mmc->id, "MMSBox: Send [http] to MMC[%s], msg type [%s], from %s, to %s", - mmc ? octstr_get_cstr(mmc->id) : "", - mms_message_type_to_cstr(mtype), - octstr_get_cstr(from), octstr_get_cstr(to)); + mmc && mmc->id ? octstr_get_cstr(mmc->id) : "", + mms_message_type_to_cstr(mtype), + octstr_get_cstr(from), octstr_get_cstr(to)); mms = mms_tobinary(m); @@ -1277,7 +1423,11 @@ static Octstr *mm7http_send(MmscGrp *mmc, Octstr *from, Octstr *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); - + + mmsbox_event_cb(mmc->id, mm7type, 0, octstr_imm("1.0"), 0, + octstr_len(mms), e->attempts, from, + to, NULL, transid, hdrs, NULL); + rh = mime_entity_headers(form_data); body = mime_entity_body(form_data); @@ -1286,23 +1436,35 @@ static Octstr *mm7http_send(MmscGrp *mmc, Octstr *from, Octstr *to, if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) { *error = octstr_format("Failed to contact MMC[url=%S] => HTTP returned status = %d !", mmc->mmsc_url, hstatus); + if (hstatus < 0) + MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_SOCKET_CONNECT_FAILED, 3); + MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_MM7_NON_200_RESULT, 3); } else { ret = rbody ? octstr_duplicate(rbody) : NULL; if (ret) octstr_strip_blanks(ret); + MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_MM7_NON_200_RESULT); + MMSC_CLEAR_ALARM(mmc, MMSBOX_ALARM_SOCKET_CONNECT_FAILED); } + mmsbox_event_cb(mmc->id, mm7type + 1, /* Always represents response type */ + 0, octstr_imm("1.0"), hstatus, + 0, e->attempts, e->from, + to, ret, transid, hdrs, NULL); + *retry = (ret == NULL && (http_status_class(hstatus) == HTTP_STATUS_SERVER_ERROR || hstatus < 0)); if (ret) mms_log2("Sent", from, to, -1, ret, NULL, mmc->id, "MMSBox", NULL, NULL); +done: http_destroy_headers(rh); octstr_destroy(body); http_destroy_headers(ph); octstr_destroy(rbody); octstr_destroy(mms); mime_entity_destroy(form_data); + octstr_destroy(transid); return ret; } @@ -1330,18 +1492,18 @@ static int mms_sendtommsc(MmscGrp *mmc, MmsEnvelope *e, Octstr *to, mutex_lock(mmc->mutex); { /* Grab a lock on it. */ Octstr *err = NULL; if (mmc->type == SOAP_MMSC) - id = mm7soap_send(mmc, from, to, transid, linkedid, vasid, service_code, hdrs, m, &err, errhdrs, &retry); + id = mm7soap_send(mmc, from, to, transid, linkedid, vasid, service_code, e, m, &err, errhdrs, &retry); else if (mmc->type == EAIF_MMSC) - id = mm7eaif_send(mmc, from, to, transid, vasid, hdrs, m, &err, &retry); + id = mm7eaif_send(mmc, from, to, transid, vasid, e, m, &err, &retry); else if (mmc->type == HTTP_MMSC) - id = mm7http_send(mmc, from, to, m, &err, &retry); + id = mm7http_send(mmc,e, from, to, 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 mms_error_ex("MT", 0, "MM7", mmc->id, "MMC[%s] of unknown type, can't send!", - mmc->id ? octstr_get_cstr(mmc->id) : ""); + mmc->id ? octstr_get_cstr(mmc->id) : ""); throughput = mmc->throughput; groupid = mmc->group_id ? octstr_duplicate(mmc->group_id) : NULL; @@ -1380,19 +1542,23 @@ static int sendMsg(MmsEnvelope *e) if ((msg = qfs->mms_queue_getdata(e)) == NULL) { mms_error(0, "MM7", NULL, "MMSBox queue error: Failed to load message for queue id [%s]!", e->xqfname); + MMSC_ISSUE_ALARM(NULL, MMSBOX_ALARM_RETRIEVE_MMS_ERROR, 4); goto done2; - } + } else + MMSC_CLEAR_ALARM(NULL, MMSBOX_ALARM_RETRIEVE_MMS_ERROR); for (i = 0, n = gwlist_len(e->to); ito, i); - Octstr *err = NULL; + Octstr *err = NULL, *x; time_t tnow = time(NULL); MmscGrp *mmc = NULL; Octstr *new_msgid = NULL; List *errl = NULL; int is_email = 0; - + Octstr *requested_mmsc = NULL; + + if (!to || !to->process) continue; @@ -1413,7 +1579,11 @@ static int sendMsg(MmsEnvelope *e) is_email = (octstr_search_char(to->rcpt, '@', 0) > 0); - if ((mmc = get_handler_mmc(e->viaproxy, to->rcpt, e->from)) == NULL && !is_email) { + x = octstr_format("X-Mbuni-Via-%d", i); + requested_mmsc = e->hdrs ? http_header_value(e->hdrs, x) : NULL; + octstr_destroy(x); + if ((mmc = get_handler_mmc(requested_mmsc ? requested_mmsc : e->viaproxy, to->rcpt, e->from)) == NULL && + !is_email) { err = octstr_format("MMSBox error: Failed to deliver to " "%S. Don't know how to route!", to->rcpt); @@ -1456,6 +1626,14 @@ static int sendMsg(MmsEnvelope *e) &errl); if (errl) err = http_header_value(errl, octstr_imm("X-Mbuni-Error")); + if (new_msgid && e->hdrs) { /* Record it */ + Octstr *x = octstr_format("X-Mbuni-Received-Message-Id-%d", i); + + http_header_remove_all(e->hdrs, octstr_get_cstr(x)); + http_header_add(e->hdrs, octstr_get_cstr(x), octstr_get_cstr(new_msgid)); + + octstr_destroy(x); + } } if (mmc) { if (res == MMS_SEND_OK) @@ -1477,7 +1655,7 @@ static int sendMsg(MmsEnvelope *e) e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF) /* queue dlr as needed. */ queue_dlr(mmc, e->from, to->rcpt, e->msgId, (e->expiryt != 0 && e->expiryt < tnow) ? - octstr_imm("Expired") : octstr_imm("Rejected"), + octstr_imm("Expired") : octstr_imm("Rejected"), "MM7-Out", errl); } if (res == MMS_SEND_ERROR_FATAL) @@ -1527,7 +1705,8 @@ static int sendMsg(MmsEnvelope *e) octstr_destroy(new_msgid); octstr_destroy(err); http_destroy_headers(errl); - + + octstr_destroy(requested_mmsc); e->lasttry = tnow; if (qfs->mms_queue_update(e) == 1) { e = NULL; @@ -1538,7 +1717,7 @@ static int sendMsg(MmsEnvelope *e) done2: mms_destroy(msg); octstr_destroy(otransid); - + if (e) { /* Update the queue if it is still valid (e.g. recipients not handled) * XXX can this happen here??... */ @@ -1556,6 +1735,8 @@ done2: void mmsbox_outgoing_queue_runner(volatile sig_atomic_t *rstop) { + hmon->register_thread(); qfs->mms_queue_run(octstr_get_cstr(outgoing_qdir), - sendMsg, queue_interval, maxthreads, rstop); + sendMsg, queue_interval, maxthreads, rstop); + hmon->unregister_thread(); } diff --git a/mbuni/mmsbox/mmsbox.c b/mbuni/mmsbox/mmsbox.c index 218ec92..cdfc317 100644 --- a/mbuni/mmsbox/mmsbox.c +++ b/mbuni/mmsbox/mmsbox.c @@ -28,81 +28,80 @@ /* XXX warning, do not octstr_destroy strings in HTTPCGIVar struct. They are destroyed by the http module! */ -volatile sig_atomic_t rstop = 0; static void quit_now(int notused) { - rstop = 1; + rstop = 1; - mms_info(0, "mmsbox", NULL, "shutdown in progress..."); - /* Close all MMSC http ports, kill all MMSC threads, kill sendmms port... */ - if (sendmms_port.port > 0) - http_close_port(sendmms_port.port); + mms_info(0, "mmsbox", NULL, "shutdown in progress..."); + /* Close all MMSC http ports, kill all MMSC threads, kill sendmms port... */ + if (sendmms_port.port > 0) + http_close_port(sendmms_port.port); - mmsbox_stop_all_mmsc_conn(); + mmsbox_stop_all_mmsc_conn(); } /* manage the SIGHUP signal */ static void relog_now(int notused) { - mms_warning(0, "mmsbox", NULL, "SIGHUP received, catching and re-opening logs"); - log_reopen(); - alog_reopen(); + mms_warning(0, "mmsbox", NULL, "SIGHUP received, catching and re-opening logs"); + log_reopen(); + alog_reopen(); } /* Finds text part, returns copy. */ static MIMEEntity *find_textpart(MIMEEntity *m) { - Octstr *ctype = NULL, *params = NULL; - MIMEEntity *res = NULL; - List *headers; - int i, n; + Octstr *ctype = NULL, *params = NULL; + MIMEEntity *res = NULL; + List *headers; + int i, n; - if (!m) return NULL; + if (!m) return NULL; - headers = mime_entity_headers(m); - get_content_type(headers, &ctype, ¶ms); - http_destroy_headers(headers); + headers = mime_entity_headers(m); + get_content_type(headers, &ctype, ¶ms); + http_destroy_headers(headers); - if (ctype && octstr_str_compare(ctype, "text/plain") == 0) { - res = mime_entity_duplicate(m); - goto done; - } + if (ctype && octstr_str_compare(ctype, "text/plain") == 0) { + res = mime_entity_duplicate(m); + goto done; + } - if ((n = mime_entity_num_parts(m)) > 0) { - for (i = 0; i < n; i++) { - MIMEEntity *x = mime_entity_get_part(m, i); - res = find_textpart(x); - mime_entity_destroy(x); + if ((n = mime_entity_num_parts(m)) > 0) { + for (i = 0; i < n; i++) { + MIMEEntity *x = mime_entity_get_part(m, i); + res = find_textpart(x); + mime_entity_destroy(x); - if (res != NULL) - goto done2; - } - } - done: - if (res) { /* We got it! Convert charset if needed. */ - List *params_h = get_value_parameters(params); - Octstr *charset = http_header_value(params_h, octstr_imm("charset")); - Octstr *body = mime_entity_body(res); - if (charset == NULL || - octstr_str_compare(charset, "unknown") == 0) { - octstr_destroy(charset); - charset = octstr_create(DEFAULT_CHARSET); - } + if (res != NULL) + goto done2; + } + } +done: + if (res) { /* We got it! Convert charset if needed. */ + List *params_h = get_value_parameters(params); + Octstr *charset = http_header_value(params_h, octstr_imm("charset")); + Octstr *body = mime_entity_body(res); + if (charset == NULL || + octstr_str_compare(charset, "unknown") == 0) { + octstr_destroy(charset); + charset = octstr_create(DEFAULT_CHARSET); + } - if (octstr_str_case_compare(charset, DEFAULT_CHARSET) != 0) { - charset_convert(body, DEFAULT_CHARSET, octstr_get_cstr(charset)); /* XXX error ignored? */ - mime_entity_set_body(res, body); - } - octstr_destroy(body); - http_destroy_headers(params_h); - octstr_destroy(charset); - } + if (octstr_str_case_compare(charset, DEFAULT_CHARSET) != 0) { + charset_convert(body, DEFAULT_CHARSET, octstr_get_cstr(charset)); /* XXX error ignored? */ + mime_entity_set_body(res, body); + } + octstr_destroy(body); + http_destroy_headers(params_h); + octstr_destroy(charset); + } - done2: +done2: - octstr_destroy(ctype); - octstr_destroy(params); - return res; + octstr_destroy(ctype); + octstr_destroy(params); + return res; } @@ -112,66 +111,66 @@ static MIMEEntity *find_textpart(MIMEEntity *m) static Octstr *get_keyword(MIMEEntity *me) { - MIMEEntity *t = find_textpart(me); - Octstr *txt = t ? mime_entity_body(t) : NULL; - List *l = t ? octstr_split_words(txt) : NULL; - Octstr *keyword = l ? gwlist_extract_first(l) : NULL; + MIMEEntity *t = find_textpart(me); + Octstr *txt = t ? mime_entity_body(t) : NULL; + List *l = t ? octstr_split_words(txt) : NULL; + Octstr *keyword = l ? gwlist_extract_first(l) : NULL; - if (t) - mime_entity_destroy(t); - gwlist_destroy(l, (gwlist_item_destructor_t *)octstr_destroy); - octstr_destroy(txt); + if (t) + mime_entity_destroy(t); + gwlist_destroy(l, (gwlist_item_destructor_t *)octstr_destroy); + octstr_destroy(txt); - return keyword; + return keyword; } static int _x_octstr_comp(Octstr *x, Octstr *y) { - return (octstr_case_compare(x,y) == 0); + return (octstr_case_compare(x,y) == 0); } static MmsService *get_service(Octstr *keyword, Octstr *mmc_id, Octstr *receiver) { - int i, n; - MmsService *catch_all = NULL; - Octstr *phonenum = receiver ? extract_phonenum(receiver, NULL) : NULL; + int i, n; + MmsService *catch_all = NULL; + Octstr *phonenum = receiver ? extract_phonenum(receiver, NULL) : NULL; - for (i = 0, n = gwlist_len(mms_services); i < n; i++) { - MmsService *ms = gwlist_get(mms_services,i); + for (i = 0, n = gwlist_len(mms_services); i < n; i++) { + MmsService *ms = gwlist_get(mms_services,i); - /* Check that mmc_id is allowed: - * denied list is not null and we are on it, or allowed list is not null and we - * are *not* on it. - */ - if (ms->denied_mmscs && - gwlist_search(ms->denied_mmscs, mmc_id, (gwlist_item_matches_t *)_x_octstr_comp) != NULL) - continue; + /* Check that mmc_id is allowed: + * denied list is not null and we are on it, or allowed list is not null and we + * are *not* on it. + */ + if (ms->denied_mmscs && + gwlist_search(ms->denied_mmscs, mmc_id, (gwlist_item_matches_t *)_x_octstr_comp) != NULL) + continue; - if (ms->allowed_mmscs && - gwlist_search(ms->allowed_mmscs, mmc_id, (gwlist_item_matches_t *)_x_octstr_comp) == NULL) - continue; + if (ms->allowed_mmscs && + gwlist_search(ms->allowed_mmscs, mmc_id, (gwlist_item_matches_t *)_x_octstr_comp) == NULL) + continue; - if (ms->denied_receiver_prefix && phonenum && - does_prefix_match(ms->denied_receiver_prefix, phonenum) != 0) - continue; + if (ms->denied_receiver_prefix && phonenum && + does_prefix_match(ms->denied_receiver_prefix, phonenum) != 0) + continue; - if (ms->allowed_receiver_prefix && phonenum && - does_prefix_match(ms->allowed_receiver_prefix, phonenum) == 0) - continue; + if (ms->allowed_receiver_prefix && phonenum && + does_prefix_match(ms->allowed_receiver_prefix, phonenum) == 0) + continue; - if (keyword && - gwlist_search(ms->keywords, keyword, - (gwlist_item_matches_t *)_x_octstr_comp) != NULL) { - octstr_destroy(phonenum); - return ms; - } + if (keyword && + gwlist_search(ms->keywords, keyword, + (gwlist_item_matches_t *)_x_octstr_comp) != NULL) { + octstr_destroy(phonenum); + return ms; + } - if (ms->isdefault && catch_all == NULL) /* We also find the catch-all for this sender. */ - catch_all = ms; - } + if (ms->isdefault && catch_all == NULL) /* We also find the catch-all for this sender. */ + catch_all = ms; + } - octstr_destroy(phonenum); - return catch_all; + octstr_destroy(phonenum); + return catch_all; } static void add_all_matching_parts(MIMEEntity *plist, MmsServiceUrlParam *pm, @@ -179,129 +178,129 @@ static void add_all_matching_parts(MIMEEntity *plist, MmsServiceUrlParam *pm, MIMEEntity *me, MmsMsg *msg, int lev, int count) { - int i, n; - List *headers = NULL; - Octstr *data = NULL, *ctype = NULL, *xctype = NULL, *params = NULL; - Octstr *s; + int i, n; + List *headers = NULL; + Octstr *data = NULL, *ctype = NULL, *xctype = NULL, *params = NULL; + Octstr *s; - headers = mime_entity_headers(me); - if (pm->type == WHOLE_BINARY && lev == 0) { - data = mms_tobinary(msg); - ctype = octstr_create("application/vnd.wap.mms-message"); - } else if (pm->type == NO_PART && lev == 0) { - data = octstr_create(""); /* We'll add value below. */ - goto done; - } else if (pm->type == KEYWORD_PART && lev == 0) { - data = keyword ? octstr_duplicate(keyword) : octstr_create(""); - ctype = octstr_create("text/plain"); - goto done; - } + headers = mime_entity_headers(me); + if (pm->type == WHOLE_BINARY && lev == 0) { + data = mms_tobinary(msg); + ctype = octstr_create("application/vnd.wap.mms-message"); + } else if (pm->type == NO_PART && lev == 0) { + data = octstr_create(""); /* We'll add value below. */ + goto done; + } else if (pm->type == KEYWORD_PART && lev == 0) { + data = keyword ? octstr_duplicate(keyword) : octstr_create(""); + ctype = octstr_create("text/plain"); + goto done; + } - if ((n = mime_entity_num_parts(me)) > 0) { /* Recurse over multi-parts. */ - for (i = 0; i < n; i++) { - MIMEEntity *x = mime_entity_get_part(me,i); - add_all_matching_parts(plist, pm, NULL, x, msg, lev+1,i); - mime_entity_destroy(x); - } - goto done; - } + if ((n = mime_entity_num_parts(me)) > 0) { /* Recurse over multi-parts. */ + for (i = 0; i < n; i++) { + MIMEEntity *x = mime_entity_get_part(me,i); + add_all_matching_parts(plist, pm, NULL, x, msg, lev+1,i); + mime_entity_destroy(x); + } + goto done; + } - get_content_type(headers, &xctype, ¶ms); + get_content_type(headers, &xctype, ¶ms); #define BEGINSWITH(s, prefix) (octstr_case_search(s, octstr_imm(prefix),0) == 0) #define TYPE_MATCH(typ, prefix) ((pm->type) == (typ) && \ BEGINSWITH(xctype, prefix)) - if (xctype) - if (TYPE_MATCH(IMAGE_PART,"image/") || - TYPE_MATCH(AUDIO_PART,"audio/") || - TYPE_MATCH(VIDEO_PART,"video/") || - TYPE_MATCH(TEXT_PART,"text/") || - TYPE_MATCH(SMIL_PART,"application/smil") || - pm->type == ANY_PART || /* Skip top-level for 'any' parts. */ - (pm->type == OTHER_PART && - (!BEGINSWITH(xctype, "text/") && - !BEGINSWITH(xctype, "video/") && - !BEGINSWITH(xctype, "image/") && - !BEGINSWITH(xctype, "application/smil")))) { + if (xctype) + if (TYPE_MATCH(IMAGE_PART,"image/") || + TYPE_MATCH(AUDIO_PART,"audio/") || + TYPE_MATCH(VIDEO_PART,"video/") || + TYPE_MATCH(TEXT_PART,"text/") || + TYPE_MATCH(SMIL_PART,"application/smil") || + pm->type == ANY_PART || /* Skip top-level for 'any' parts. */ + (pm->type == OTHER_PART && + (!BEGINSWITH(xctype, "text/") && + !BEGINSWITH(xctype, "video/") && + !BEGINSWITH(xctype, "image/") && + !BEGINSWITH(xctype, "application/smil")))) { - ctype = http_header_value(headers, octstr_imm("Content-Type")); - data = mime_entity_body(me); - } + ctype = http_header_value(headers, octstr_imm("Content-Type")); + data = mime_entity_body(me); + } - done: - if (data) { - MIMEEntity *p = mime_entity_create(); - Octstr *cd = octstr_format("form-data; name=\"%S\"", pm->name); - List *xh; +done: + if (data) { + MIMEEntity *p = mime_entity_create(); + Octstr *cd = octstr_format("form-data; name=\"%S\"", pm->name); + List *xh; - if (ctype && pm->type != KEYWORD_PART) { - /* If Content-Location header or name (content-type) parameter given, pass it as filename. */ - Octstr *c = NULL, *q = NULL; - Octstr *cloc = http_header_value(headers, - octstr_imm("Content-Location")); - split_header_value(ctype, &c, &q); + if (ctype && pm->type != KEYWORD_PART) { + /* If Content-Location header or name (content-type) parameter given, pass it as filename. */ + Octstr *c = NULL, *q = NULL; + Octstr *cloc = http_header_value(headers, + octstr_imm("Content-Location")); + split_header_value(ctype, &c, &q); - if (q || cloc) { - List *ph = q ? get_value_parameters(q) : http_create_empty_headers(); - Octstr *v = cloc ? cloc : http_header_value(ph, octstr_imm("name")); + if (q || cloc) { + List *ph = q ? get_value_parameters(q) : http_create_empty_headers(); + Octstr *v = cloc ? cloc : http_header_value(ph, octstr_imm("name")); - if (!v) /* make up a fake name if none is given */ - v = octstr_format("part-%d-%d", lev, count); + if (!v) /* make up a fake name if none is given */ + v = octstr_format("part-%d-%d", lev, count); - octstr_format_append(cd, "; filename=\"%S\"", v); - http_header_remove_all(ph, "name"); + octstr_format_append(cd, "; filename=\"%S\"", v); + http_header_remove_all(ph, "name"); - if (v != cloc) - octstr_destroy(v); - octstr_destroy(ctype); + if (v != cloc) + octstr_destroy(v); + octstr_destroy(ctype); - v = make_value_parameters(ph); - if (v && octstr_len(v) > 0) - ctype = octstr_format("%S; %S", c, v); - else - ctype = octstr_duplicate(c); + v = make_value_parameters(ph); + if (v && octstr_len(v) > 0) + ctype = octstr_format("%S; %S", c, v); + else + ctype = octstr_duplicate(c); - octstr_destroy(v); + octstr_destroy(v); - http_destroy_headers(ph); + http_destroy_headers(ph); - octstr_destroy(q); - } + octstr_destroy(q); + } - octstr_destroy(c); - octstr_destroy(cloc); - } + octstr_destroy(c); + octstr_destroy(cloc); + } - xh = http_create_empty_headers(); - http_header_add(xh, "Content-Disposition", octstr_get_cstr(cd)); - if (ctype) /* This header must come after the above it seems. */ - http_header_add(xh, "Content-Type", octstr_get_cstr(ctype)); + xh = http_create_empty_headers(); + http_header_add(xh, "Content-Disposition", octstr_get_cstr(cd)); + if (ctype) /* This header must come after the above it seems. */ + http_header_add(xh, "Content-Type", octstr_get_cstr(ctype)); - mime_replace_headers(p, xh); - http_destroy_headers(xh); + mime_replace_headers(p, xh); + http_destroy_headers(xh); - s = octstr_duplicate(data); /* data for the parameter */ - if (pm->value) /* add value part as needed. */ - octstr_append(s, pm->value); - mime_entity_set_body(p, s); - octstr_destroy(s); + s = octstr_duplicate(data); /* data for the parameter */ + if (pm->value) /* add value part as needed. */ + octstr_append(s, pm->value); + mime_entity_set_body(p, s); + octstr_destroy(s); #if 0 - base64_mimeparts(p); + base64_mimeparts(p); #endif - mime_entity_add_part(plist, p); /* add it to list so far. */ - mime_entity_destroy(p); + mime_entity_add_part(plist, p); /* add it to list so far. */ + mime_entity_destroy(p); - octstr_destroy(cd); - } + octstr_destroy(cd); + } - octstr_destroy(xctype); - octstr_destroy(params); - octstr_destroy(ctype); - octstr_destroy(data); + octstr_destroy(xctype); + octstr_destroy(params); + octstr_destroy(ctype); + octstr_destroy(data); - http_destroy_headers(headers); + http_destroy_headers(headers); } enum _xurltype {FILE_TYPE, URL_TYPE}; @@ -322,186 +321,186 @@ static int fetch_serviceurl(MmsEnvelope *e, Octstr *keyword, Octstr **err) { - List *rh, *rph = NULL; - Octstr *body = NULL, *rb = NULL, *transid; - Octstr *ctype = NULL, *params = NULL; - Octstr *s; - int i, n, method, typ = FILE_TYPE; - FILE *fp = NULL; + List *rh, *rph = NULL; + Octstr *body = NULL, *rb = NULL, *transid; + Octstr *ctype = NULL, *params = NULL; + Octstr *s; + int i, n, method, typ = FILE_TYPE; + FILE *fp = NULL; - int res = -1; + int res = -1; - transid = mms_maketransid(e->xqfname, octstr_imm(MM_NAME)); - switch (ms->type) { - case TRANS_TYPE_GET_URL: - case TRANS_TYPE_POST_URL: - rh = http_create_empty_headers(); + transid = mms_maketransid(e->xqfname, octstr_imm(MM_NAME)); + switch (ms->type) { + case TRANS_TYPE_GET_URL: + case TRANS_TYPE_POST_URL: + rh = http_create_empty_headers(); - http_header_add(rh, "User-Agent", MM_NAME "/" VERSION); - /* Put in some useful headers. */ - if (e->msgId) - http_header_add(rh, "X-Mbuni-Message-ID", octstr_get_cstr(e->msgId)); - if (e->fromproxy) - http_header_add(rh, "X-Mbuni-MMSC-ID", octstr_get_cstr(e->fromproxy)); - if (e->token) - http_header_add(rh, "X-Mbuni-LinkedID", octstr_get_cstr(e->token)); - if (e->from) { - Octstr *xfrom = octstr_duplicate(e->from); + http_header_add(rh, "User-Agent", MM_NAME "/" VERSION); + /* Put in some useful headers. */ + if (e->msgId) + http_header_add(rh, "X-Mbuni-Message-ID", octstr_get_cstr(e->msgId)); + if (e->fromproxy) + http_header_add(rh, "X-Mbuni-MMSC-ID", octstr_get_cstr(e->fromproxy)); + if (e->token) + http_header_add(rh, "X-Mbuni-LinkedID", octstr_get_cstr(e->token)); + if (e->from) { + Octstr *xfrom = octstr_duplicate(e->from); - _mms_fixup_address(&xfrom, unified_prefix ? octstr_get_cstr(unified_prefix) : NULL, - strip_prefixes, 0); - http_header_add(rh, "X-Mbuni-From", octstr_get_cstr(xfrom)); - octstr_destroy(xfrom); - } - if (e->subject) - http_header_add(rh, "X-Mbuni-Subject", octstr_get_cstr(e->subject)); + _mms_fixup_address(&xfrom, unified_prefix ? octstr_get_cstr(unified_prefix) : NULL, + strip_prefixes, 0); + http_header_add(rh, "X-Mbuni-From", octstr_get_cstr(xfrom)); + octstr_destroy(xfrom); + } + if (e->subject) + http_header_add(rh, "X-Mbuni-Subject", octstr_get_cstr(e->subject)); - /* Put in a transaction ID. */ - http_header_add(rh, "X-Mbuni-TransactionID", octstr_get_cstr(transid)); + /* Put in a transaction ID. */ + http_header_add(rh, "X-Mbuni-TransactionID", octstr_get_cstr(transid)); - for (i = 0, n = gwlist_len(e->to); i < n; i++) { - MmsEnvelopeTo *r = gwlist_get(e->to, i); - if (r && r->rcpt) { - Octstr *xto = octstr_duplicate(r->rcpt); - _mms_fixup_address(&xto, unified_prefix ? octstr_get_cstr(unified_prefix) : NULL, - strip_prefixes, 0); - http_header_add(rh, "X-Mbuni-To", octstr_get_cstr(xto)); - octstr_destroy(xto); - } - } + for (i = 0, n = gwlist_len(e->to); i < n; i++) { + MmsEnvelopeTo *r = gwlist_get(e->to, i); + if (r && r->rcpt) { + Octstr *xto = octstr_duplicate(r->rcpt); + _mms_fixup_address(&xto, unified_prefix ? octstr_get_cstr(unified_prefix) : NULL, + strip_prefixes, 0); + http_header_add(rh, "X-Mbuni-To", octstr_get_cstr(xto)); + octstr_destroy(xto); + } + } - if ((s = http_header_value(e->hdrs, octstr_imm("X-Mbuni-UAProf"))) != NULL) { /* add UAProf info, if any. */ - Octstr *sx = http_header_value(e->hdrs,octstr_imm("X-Mbuni-Timestamp")); - http_header_add(rh, "X-Mbuni-UAProf", octstr_get_cstr(s)); - if (sx) - http_header_add(rh, "X-Mbuni-Timestamp", octstr_get_cstr(sx)); - octstr_destroy(sx); - octstr_destroy(s); - } + if ((s = http_header_value(e->hdrs, octstr_imm("X-Mbuni-UAProf"))) != NULL) { /* add UAProf info, if any. */ + Octstr *sx = http_header_value(e->hdrs,octstr_imm("X-Mbuni-Timestamp")); + http_header_add(rh, "X-Mbuni-UAProf", octstr_get_cstr(s)); + if (sx) + http_header_add(rh, "X-Mbuni-Timestamp", octstr_get_cstr(sx)); + octstr_destroy(sx); + octstr_destroy(s); + } - if ((s = mms_get_header_value(m, octstr_imm("Date"))) != NULL) { - http_header_add(rh, "X-Mbuni-Message-Date", octstr_get_cstr(s)); - octstr_destroy(s); - } + if ((s = mms_get_header_value(m, octstr_imm("Date"))) != NULL) { + http_header_add(rh, "X-Mbuni-Message-Date", octstr_get_cstr(s)); + octstr_destroy(s); + } - s = date_format_http(e->created); - http_header_add(rh, "X-Mbuni-Received-Date", octstr_get_cstr(s)); - octstr_destroy(s); + s = date_format_http(e->created); + http_header_add(rh, "X-Mbuni-Received-Date", octstr_get_cstr(s)); + octstr_destroy(s); - if (ms->type == TRANS_TYPE_POST_URL) { /* Put in the parameters. */ - MIMEEntity *x = mime_entity_create(); + if (ms->type == TRANS_TYPE_POST_URL) { /* Put in the parameters. */ + MIMEEntity *x = mime_entity_create(); - http_header_add(rh, "Content-Type", "multipart/form-data"); - mime_replace_headers(x, rh); - http_destroy_headers(rh); + http_header_add(rh, "Content-Type", "multipart/form-data"); + mime_replace_headers(x, rh); + http_destroy_headers(rh); - for (i = 0, n = gwlist_len(ms->params); i < n; i++) { - MmsServiceUrlParam *p = gwlist_get(ms->params, i); - add_all_matching_parts(x, p, keyword, msg, m, 0, i); - } + for (i = 0, n = gwlist_len(ms->params); i < n; i++) { + MmsServiceUrlParam *p = gwlist_get(ms->params, i); + add_all_matching_parts(x, p, keyword, msg, m, 0, i); + } - body = mime_entity_body(x); - rh = mime_entity_headers(x); + body = mime_entity_body(x); + rh = mime_entity_headers(x); - mime_entity_destroy(x); + mime_entity_destroy(x); - method = HTTP_METHOD_POST; - } else - method = HTTP_METHOD_GET; + method = HTTP_METHOD_POST; + } else + method = HTTP_METHOD_GET; - typ = URL_TYPE; - if (mmsbox_url_fetch_content(method, ms->url, rh, body, &rph, &rb) == HTTP_OK) { - get_content_type(rph, &ctype, ¶ms); - /* add transaction id back.*/ - http_header_remove_all(rph, "X-Mbuni-TransactionID"); - http_header_add(rph, "X-Mbuni-TransactionID", octstr_get_cstr(transid)); - } else - *err = octstr_format("MMSBox: Failed to fetch content for Service %S, url %S!", - ms->name, ms->url); - http_destroy_headers(rh); - octstr_destroy(body); - break; - case TRANS_TYPE_FILE: - if ((fp = fopen(octstr_get_cstr(ms->url), "r")) != NULL) { - rb = octstr_read_pipe(fp); - fclose(fp); - ctype = filename2content_type(octstr_get_cstr(ms->url)); - } + typ = URL_TYPE; + if (mmsbox_url_fetch_content(method, ms->url, rh, body, &rph, &rb) == HTTP_OK) { + get_content_type(rph, &ctype, ¶ms); + /* add transaction id back.*/ + http_header_remove_all(rph, "X-Mbuni-TransactionID"); + http_header_add(rph, "X-Mbuni-TransactionID", octstr_get_cstr(transid)); + } else + *err = octstr_format("MMSBox: Failed to fetch content for Service %S, url %S!", + ms->name, ms->url); + http_destroy_headers(rh); + octstr_destroy(body); + break; + case TRANS_TYPE_FILE: + if ((fp = fopen(octstr_get_cstr(ms->url), "r")) != NULL) { + rb = octstr_read_pipe(fp); + fclose(fp); + ctype = filename2content_type(octstr_get_cstr(ms->url)); + } - if (!rb) - *err = octstr_format("MMSBox: Failed to open file %S for service %S!", - ms->url, ms->name); - typ = FILE_TYPE; - break; - case TRANS_TYPE_EXEC: - if ((fp = popen(octstr_get_cstr(ms->url), "r+")) != NULL) { - Octstr *s = mime_entity_to_octstr(msg); - if (s) { /* Send the MMS to the exec program */ - octstr_print(fp, s); - fflush(fp); - octstr_destroy(s); - } - rb = octstr_read_pipe(fp); - ctype = octstr_create("application/smil"); - pclose(fp); - } - if (!rb) - *err = octstr_format("MMSBox: Failed to fetch content for Service %S, exec path = %S!", - ms->name, ms->url); - typ = FILE_TYPE; - break; - case TRANS_TYPE_TEXT: - rb = octstr_duplicate(ms->url); - ctype = octstr_create("text/plain"); - typ = URL_TYPE; - break; + if (!rb) + *err = octstr_format("MMSBox: Failed to open file %S for service %S!", + ms->url, ms->name); + typ = FILE_TYPE; + break; + case TRANS_TYPE_EXEC: + if ((fp = popen(octstr_get_cstr(ms->url), "r+")) != NULL) { + Octstr *s = mime_entity_to_octstr(msg); + if (s) { /* Send the MMS to the exec program */ + octstr_print(fp, s); + fflush(fp); + octstr_destroy(s); + } + rb = octstr_read_pipe(fp); + ctype = octstr_create("application/smil"); + pclose(fp); + } + if (!rb) + *err = octstr_format("MMSBox: Failed to fetch content for Service %S, exec path = %S!", + ms->name, ms->url); + typ = FILE_TYPE; + break; + case TRANS_TYPE_TEXT: + rb = octstr_duplicate(ms->url); + ctype = octstr_create("text/plain"); + typ = URL_TYPE; + break; - default: - *err = octstr_format(0, "MMSBOX: Unknown Service type for service %S!", ms->name); - break; - } + default: + *err = octstr_format(0, "MMSBOX: Unknown Service type for service %S!", ms->name); + break; + } - /* If we have the content, make the message and write it to out-going. - * if we have no content, or we have been told to suppress the reply, then we suppress - */ - if (!ctype || !rb || - (octstr_len(rb) == 0 && ms->omitempty) || - ms->noreply) { - mms_info(0, "mmsbox", NULL, "MMSBox.service_request: Suppressed reply for service %s, " - "suppress-reply=%s, omit-empty=%s, reply-len=%ld, content-type=%s", - octstr_get_cstr(ms->name), ms->noreply ? "true" : "false", - ms->omitempty ? "true" : "false", - rb ? octstr_len(rb) : 0, - ctype ? octstr_get_cstr(ctype) : ""); - goto done; - } else { - Octstr *base_url = url_path_prefix(ms->url, typ); + /* If we have the content, make the message and write it to out-going. + * if we have no content, or we have been told to suppress the reply, then we suppress + */ + if (!ctype || !rb || + (octstr_len(rb) == 0 && ms->omitempty) || + ms->noreply) { + mms_info(0, "mmsbox", NULL, "MMSBox.service_request: Suppressed reply for service %s, " + "suppress-reply=%s, omit-empty=%s, reply-len=%ld, content-type=%s", + octstr_get_cstr(ms->name), ms->noreply ? "true" : "false", + ms->omitempty ? "true" : "false", + rb ? octstr_len(rb) : 0, + ctype ? octstr_get_cstr(ctype) : ""); + goto done; + } else { + Octstr *base_url = url_path_prefix(ms->url, typ); - if (ms->special_header) { - if (rph == NULL) - rph = http_create_empty_headers(); - http_header_remove_all(rph, "X-Mbuni-Content-Header"); - http_header_add(rph, "X-Mbuni-Content-Header", octstr_get_cstr(ms->special_header)); - } - res = make_and_queue_msg(rb, ctype, rph, - ms->url, - base_url, - typ, e, ms->name, ms->faked_sender, ms->service_code, - ms->accept_x_headers, ms->passthro_headers, - outgoing_qdir, - err); + if (ms->special_header) { + if (rph == NULL) + rph = http_create_empty_headers(); + http_header_remove_all(rph, "X-Mbuni-Content-Header"); + http_header_add(rph, "X-Mbuni-Content-Header", octstr_get_cstr(ms->special_header)); + } + res = make_and_queue_msg(rb, ctype, rph, + ms->url, + base_url, + typ, e, ms->name, ms->faked_sender, ms->service_code, + ms->accept_x_headers, ms->passthro_headers, + outgoing_qdir, + err); - octstr_destroy(base_url); - } + octstr_destroy(base_url); + } - done: - octstr_destroy(ctype); - octstr_destroy(rb); - http_destroy_headers(rph); - octstr_destroy(params); - octstr_destroy(transid); +done: + octstr_destroy(ctype); + octstr_destroy(rb); + http_destroy_headers(rph); + octstr_destroy(params); + octstr_destroy(transid); - return res; + return res; } @@ -514,294 +513,294 @@ static int mmsbox_send_report(Octstr *from, char *report_type, Octstr *err, Octstr *statustxt, Octstr *details) { - List *rh = NULL, *rph = NULL; - Octstr *rb = NULL, *xfrom = from ? octstr_duplicate(from) : NULL; - int ret = HTTP_NOT_FOUND; + List *rh = NULL, *rph = NULL; + Octstr *rb = NULL, *xfrom = from ? octstr_duplicate(from) : NULL; + int ret = HTTP_NOT_FOUND; - if (xfrom) - _mms_fixup_address(&xfrom, unified_prefix ? octstr_get_cstr(unified_prefix) : NULL, - strip_prefixes, 0); + if (xfrom) + _mms_fixup_address(&xfrom, unified_prefix ? octstr_get_cstr(unified_prefix) : NULL, + strip_prefixes, 0); - rh = http_create_empty_headers(); + rh = http_create_empty_headers(); - http_header_add(rh, "X-Mbuni-Report-Type", report_type); - http_header_add(rh, "X-Mbuni-MM-Status", octstr_get_cstr(status)); - if (mmc_gid) - http_header_add(rh, "X-Mbuni-MMSC-GID", octstr_get_cstr(mmc_gid)); - http_header_add(rh, "X-Mbuni-MMSC-ID", octstr_get_cstr(mmc_id)); - if (xfrom) - http_header_add(rh, "X-Mbuni-From", octstr_get_cstr(xfrom)); + http_header_add(rh, "X-Mbuni-Report-Type", report_type); + http_header_add(rh, "X-Mbuni-MM-Status", octstr_get_cstr(status)); + if (mmc_gid) + http_header_add(rh, "X-Mbuni-MMSC-GID", octstr_get_cstr(mmc_gid)); + http_header_add(rh, "X-Mbuni-MMSC-ID", octstr_get_cstr(mmc_id)); + if (xfrom) + http_header_add(rh, "X-Mbuni-From", octstr_get_cstr(xfrom)); - if (orig_transid) - http_header_add(rh, "X-Mbuni-TransactionID", - octstr_get_cstr(orig_transid)); - if (msgid) - http_header_add(rh, "X-Mbuni-Message-ID", octstr_get_cstr(msgid)); + if (orig_transid) + http_header_add(rh, "X-Mbuni-TransactionID", + octstr_get_cstr(orig_transid)); + if (msgid) + http_header_add(rh, "X-Mbuni-Message-ID", octstr_get_cstr(msgid)); - if (orig_msgid) - http_header_add(rh, "X-Mbuni-Orig-Message-ID", octstr_get_cstr(orig_msgid)); + if (orig_msgid) + http_header_add(rh, "X-Mbuni-Orig-Message-ID", octstr_get_cstr(orig_msgid)); - if (err) - http_header_add(rh, "X-Mbuni-MM-Error", octstr_get_cstr(err)); + if (err) + http_header_add(rh, "X-Mbuni-MM-Error", octstr_get_cstr(err)); - if (statustxt) - http_header_add(rh, "X-Mbuni-MM-StatusText", octstr_get_cstr(statustxt)); + if (statustxt) + http_header_add(rh, "X-Mbuni-MM-StatusText", octstr_get_cstr(statustxt)); - if (details) - http_header_add(rh, "X-Mbuni-MM-StatusDetails", octstr_get_cstr(details)); + if (details) + http_header_add(rh, "X-Mbuni-MM-StatusDetails", octstr_get_cstr(details)); - if (uaprof) { - http_header_add(rh, "X-Mbuni-UAProf", octstr_get_cstr(uaprof)); - http_header_add(rh, "X-Mbuni-Timestamp", octstr_get_cstr(uaprof_tstamp)); - } - ret = mms_url_fetch_content(HTTP_METHOD_GET, dlr_url, rh, NULL, &rph, &rb); + if (uaprof) { + http_header_add(rh, "X-Mbuni-UAProf", octstr_get_cstr(uaprof)); + http_header_add(rh, "X-Mbuni-Timestamp", octstr_get_cstr(uaprof_tstamp)); + } + ret = mms_url_fetch_content(HTTP_METHOD_GET, dlr_url, rh, NULL, &rph, &rb); - octstr_destroy(rb); - octstr_destroy(xfrom); + octstr_destroy(rb); + octstr_destroy(xfrom); - http_destroy_headers(rph); - http_destroy_headers(rh); + http_destroy_headers(rph); + http_destroy_headers(rh); - return http_status_class(ret) == HTTP_STATUS_SUCCESSFUL ? 0 : -1; + return http_status_class(ret) == HTTP_STATUS_SUCCESSFUL ? 0 : -1; } static int mmsbox_service_dispatch(MmsEnvelope *e) { - MmsMsg *msg = NULL; - MIMEEntity *me = NULL; - int i, n, res = 0; - time_t tnow = time(NULL); - Octstr *err = NULL, *keyword = NULL; - MmsService *ms; - MmsEnvelopeTo *xto; - Octstr *prio = NULL, *mclass = NULL, *mstatus = NULL; + MmsMsg *msg = NULL; + MIMEEntity *me = NULL; + int i, n, res = 0; + time_t tnow = time(NULL); + Octstr *err = NULL, *keyword = NULL; + MmsService *ms; + MmsEnvelopeTo *xto; + Octstr *prio = NULL, *mclass = NULL, *mstatus = NULL; - gw_assert(e->msgtype == MMS_MSGTYPE_SEND_REQ || - e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF || - e->msgtype == MMS_MSGTYPE_DELIVERY_IND || - e->msgtype == MMS_MSGTYPE_READ_ORIG_IND); + gw_assert(e->msgtype == MMS_MSGTYPE_SEND_REQ || + e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF || + e->msgtype == MMS_MSGTYPE_DELIVERY_IND || + e->msgtype == MMS_MSGTYPE_READ_ORIG_IND); - if ((msg = qfs->mms_queue_getdata(e)) == NULL) { - err = octstr_format("Failed to read message for queue entry %s!", - e->xqfname); - res = -1; - goto done; - } else if (e->expiryt != 0 && /* Handle message expiry. */ - e->expiryt < tnow) { - err = octstr_format("Queue entry [msgid=%S,mmc_id=%S] " - "expired while sending to service!", e->msgId, e->fromproxy); - res = -1; + if ((msg = qfs->mms_queue_getdata(e)) == NULL) { + err = octstr_format("Failed to read message for queue entry %s!", + e->xqfname); + res = -1; + goto done; + } else if (e->expiryt != 0 && /* Handle message expiry. */ + e->expiryt < tnow) { + err = octstr_format("Queue entry [msgid=%S,mmc_id=%S] " + "expired while sending to service!", e->msgId, e->fromproxy); + res = -1; - goto done; - } else if (e->attempts >= svc_maxsendattempts) { - err = octstr_format("Failed to deliver [msgid=%S,mmc_id=%S] " - "after %ld attempts. (max attempts allowed is %ld)!", - e->msgId, e->fromproxy, e->attempts, - svc_maxsendattempts); - res = -1; - goto done; - } + goto done; + } else if (e->attempts >= svc_maxsendattempts) { + err = octstr_format("Failed to deliver [msgid=%S,mmc_id=%S] " + "after %ld attempts. (max attempts allowed is %ld)!", + e->msgId, e->fromproxy, e->attempts, + svc_maxsendattempts); + res = -1; + goto done; + } - mclass = mms_get_header_value(msg, octstr_imm("X-Mms-Message-Class")); - prio = mms_get_header_value(msg, octstr_imm("X-Mms-Priority")); - mstatus = mms_get_header_value(msg, octstr_imm("X-Mms-Status")); + mclass = mms_get_header_value(msg, octstr_imm("X-Mms-Message-Class")); + prio = mms_get_header_value(msg, octstr_imm("X-Mms-Priority")); + mstatus = mms_get_header_value(msg, octstr_imm("X-Mms-Status")); - if (e->msgtype == MMS_MSGTYPE_DELIVERY_IND || - e->msgtype == MMS_MSGTYPE_READ_ORIG_IND) { - char *report_type = (e->msgtype == MMS_MSGTYPE_DELIVERY_IND) ? "delivery-report" : "read-report"; - Octstr *msgid = mms_get_header_value(msg, octstr_imm("Message-ID")); - Octstr *orig_msgid = e->hdrs ? - http_header_value(e->hdrs, octstr_imm("X-Mbuni-Orig-Message-ID")) : NULL; - Octstr *status = mms_get_header_value(msg, - e->msgtype == MMS_MSGTYPE_DELIVERY_IND ? - octstr_imm("X-Mms-Status") : - octstr_imm("X-Mms-Read-Status")); - Octstr *orig_transid = e->hdrs ? - http_header_value(e->hdrs, octstr_imm("X-Mbuni-TransactionID")) : NULL; - Octstr *uaprof = e->hdrs ? - http_header_value(e->hdrs, octstr_imm("X-Mbuni-UAProf")) : NULL; + if (e->msgtype == MMS_MSGTYPE_DELIVERY_IND || + e->msgtype == MMS_MSGTYPE_READ_ORIG_IND) { + char *report_type = (e->msgtype == MMS_MSGTYPE_DELIVERY_IND) ? "delivery-report" : "read-report"; + Octstr *msgid = mms_get_header_value(msg, octstr_imm("Message-ID")); + Octstr *orig_msgid = e->hdrs ? + http_header_value(e->hdrs, octstr_imm("X-Mbuni-Orig-Message-ID")) : NULL; + Octstr *status = mms_get_header_value(msg, + e->msgtype == MMS_MSGTYPE_DELIVERY_IND ? + octstr_imm("X-Mms-Status") : + octstr_imm("X-Mms-Read-Status")); + Octstr *orig_transid = e->hdrs ? + http_header_value(e->hdrs, octstr_imm("X-Mbuni-TransactionID")) : NULL; + Octstr *uaprof = e->hdrs ? + http_header_value(e->hdrs, octstr_imm("X-Mbuni-UAProf")) : NULL; - Octstr *tstamp = e->hdrs ? - http_header_value(e->hdrs, octstr_imm("X-Mbuni-Timestamp")) : NULL; - Octstr *gid = e->hdrs ? - http_header_value(e->hdrs, octstr_imm("X-Mbuni-Mmsc-GroupID")) : NULL; + Octstr *tstamp = e->hdrs ? + http_header_value(e->hdrs, octstr_imm("X-Mbuni-Timestamp")) : NULL; + Octstr *gid = e->hdrs ? + http_header_value(e->hdrs, octstr_imm("X-Mbuni-Mmsc-GroupID")) : NULL; - Octstr *err = e->hdrs ? - http_header_value(e->hdrs, octstr_imm("X-Mbuni-Error")) : NULL; - Octstr *statustxt = e->hdrs ? - http_header_value(e->hdrs, octstr_imm("X-Mbuni-StatusText")) : NULL; - Octstr *details = e->hdrs ? - http_header_value(e->hdrs, octstr_imm("X-Mbuni-StatusDetails")) : NULL; + Octstr *err = e->hdrs ? + http_header_value(e->hdrs, octstr_imm("X-Mbuni-Error")) : NULL; + Octstr *statustxt = e->hdrs ? + http_header_value(e->hdrs, octstr_imm("X-Mbuni-StatusText")) : NULL; + Octstr *details = e->hdrs ? + http_header_value(e->hdrs, octstr_imm("X-Mbuni-StatusDetails")) : NULL; - if (e->url1) - res = mmsbox_send_report(e->from, report_type, - e->url1, status, msgid, orig_msgid, - e->fromproxy, gid, orig_transid, - uaprof,tstamp, err, statustxt, details); - else { - mms_info(0, "MM7", e->fromproxy, "MMSBox: Skipped %s URL call for [%s]. Empty URL, from [%s]", - report_type, octstr_get_cstr(msgid), octstr_get_cstr(e->from)); - res = 0; - } + if (e->url1) + res = mmsbox_send_report(e->from, report_type, + e->url1, status, msgid, orig_msgid, + e->fromproxy, gid, orig_transid, + uaprof,tstamp, err, statustxt, details); + else { + mms_info(0, "MM7", e->fromproxy, "MMSBox: Skipped %s URL call for [%s]. Empty URL, from [%s]", + report_type, octstr_get_cstr(msgid), octstr_get_cstr(e->from)); + res = 0; + } - octstr_destroy(msgid); - octstr_destroy(orig_msgid); - octstr_destroy(status); - octstr_destroy(orig_transid); - octstr_destroy(uaprof); - octstr_destroy(tstamp); - octstr_destroy(gid); - octstr_destroy(err); - octstr_destroy(statustxt); - octstr_destroy(details); - goto done; /* No more processing. */ - } + octstr_destroy(msgid); + octstr_destroy(orig_msgid); + octstr_destroy(status); + octstr_destroy(orig_transid); + octstr_destroy(uaprof); + octstr_destroy(tstamp); + octstr_destroy(gid); + octstr_destroy(err); + octstr_destroy(statustxt); + octstr_destroy(details); + goto done; /* No more processing. */ + } - if (gwlist_len(e->to) == 0) { /* nothing to do. odd XXX */ - res = 0; - goto done; - } + if (gwlist_len(e->to) == 0) { /* nothing to do. odd XXX */ + res = 0; + goto done; + } - me = mms_tomime(msg, 0); - keyword = get_keyword(me); + me = mms_tomime(msg, 0); + keyword = get_keyword(me); - xto = gwlist_get(e->to, 0); - ms = get_service(keyword, e->fromproxy, xto ? xto->rcpt : NULL); + xto = gwlist_get(e->to, 0); + ms = get_service(keyword, e->fromproxy, xto ? xto->rcpt : NULL); - if (!ms) { - err = octstr_format("No Service to handle %S (keyword %S)!", - e->msgId, keyword ? octstr_imm("") : keyword); - res = -1; - goto done; - } + if (!ms) { + err = octstr_format("No Service to handle %S (keyword %S)!", + e->msgId, keyword ? octstr_imm("") : keyword); + res = -1; + goto done; + } - e->_x = ms; /* Remember it for later. */ + e->_x = ms; /* Remember it for later. */ - res = fetch_serviceurl(e, ms, msg, me, keyword, &err); - done: + res = fetch_serviceurl(e, ms, msg, me, keyword, &err); +done: - if (err && res != 0) - mms_error(0, "mmsbox", NULL, "Error: %s", octstr_get_cstr(err)); + 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. */ - for (i = 0, n = gwlist_len(e->to); i < n; i++) { + if (res == -1 || res == 0) /* Fatal error, or success delete queue entry. */ + for (i = 0, n = gwlist_len(e->to); i < n; i++) { - MmsEnvelopeTo *r = gwlist_get(e->to,i); - if (r) - r->process = 0; - /* Do 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), - prio ? octstr_get_cstr(prio) : NULL, - mclass ? octstr_get_cstr(mclass) : NULL, - mstatus ? octstr_get_cstr(mstatus) : - (res == 0 ? "forwarded" : "dropped"), - e->dlr, - 0); - } - else { /* Not succeeded so we need to wait a bit and try later. */ - e->lasttry = time(NULL); - e->attempts++; /* Update count of number of delivery attempts. */ - e->sendt = e->lasttry + mmsbox_send_back_off * e->attempts; - } + MmsEnvelopeTo *r = gwlist_get(e->to,i); + if (r) + r->process = 0; + /* Do 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), + prio ? octstr_get_cstr(prio) : NULL, + mclass ? octstr_get_cstr(mclass) : NULL, + mstatus ? octstr_get_cstr(mstatus) : + (res == 0 ? "forwarded" : "dropped"), + e->dlr, + 0); + } + else { /* Not succeeded so we need to wait a bit and try later. */ + e->lasttry = time(NULL); + e->attempts++; /* Update count of number of delivery attempts. */ + e->sendt = e->lasttry + mmsbox_send_back_off * e->attempts; + } - if (qfs->mms_queue_update(e) != 1) - qfs->mms_queue_free_env(e); + if (qfs->mms_queue_update(e) != 1) + qfs->mms_queue_free_env(e); - octstr_destroy(err); - octstr_destroy(keyword); - mms_destroy(msg); + octstr_destroy(err); + octstr_destroy(keyword); + mms_destroy(msg); - octstr_destroy(prio); - octstr_destroy(mclass); - octstr_destroy(mstatus); + octstr_destroy(prio); + octstr_destroy(mclass); + octstr_destroy(mstatus); - if (me) - mime_entity_destroy(me); - return 1; + if (me) + mime_entity_destroy(me); + return 1; } static void sendmms_func(void *unused); int main(int argc, char *argv[]) { - Octstr *fname; - int cfidx; + Octstr *fname; + int cfidx; - long qthread = 0, sthread = 0; + long qthread = 0, sthread = 0; - mms_lib_init(); + mms_lib_init(); - srandom(time(NULL)); + srandom(time(NULL)); - cfidx = get_and_set_debugs(argc, argv, NULL); + cfidx = get_and_set_debugs(argc, argv, NULL); - if (argv[cfidx] == NULL) - fname = octstr_create("mbuni.conf"); - else - fname = octstr_create(argv[cfidx]); + if (argv[cfidx] == NULL) + fname = octstr_create("mbuni.conf"); + else + fname = octstr_create(argv[cfidx]); - if (mms_load_mmsbox_settings(fname,(gwthread_func_t *)mmsc_receive_func) < 0) - panic(0, "Configuration file loading failed, file: %s", octstr_get_cstr(fname)); + if (mms_load_mmsbox_settings(NULL, fname,(gwthread_func_t *)mmsc_receive_func, NULL, NULL) < 0) + panic(0, "Configuration file loading failed, file: %s", octstr_get_cstr(fname)); - octstr_destroy(fname); + octstr_destroy(fname); - mms_info(0, "mmsbox", NULL,"----------------------------------------"); - mms_info(0, "mmsbox", NULL," " MM_NAME " MMSBox version %s starting", MMSC_VERSION); + mms_info(0, "mmsbox", NULL,"----------------------------------------"); + mms_info(0, "mmsbox", NULL," " MM_NAME " MMSBox version %s starting", MMSC_VERSION); #ifdef SA_RESTART - { - struct sigaction nact; + { + struct sigaction nact; - memset(&nact, 0, sizeof(nact)); - nact.sa_handler = relog_now; - nact.sa_flags = SA_RESTART; - sigaction(SIGHUP, &nact, (struct sigaction *)0); - } + memset(&nact, 0, sizeof(nact)); + nact.sa_handler = relog_now; + nact.sa_flags = SA_RESTART; + sigaction(SIGHUP, &nact, (struct sigaction *)0); + } #else - signal(SIGHUP, relog_now); + signal(SIGHUP, relog_now); #endif - signal(SIGTERM, quit_now); - signal(SIGINT, quit_now); - signal(SIGPIPE,SIG_IGN); /* Ignore pipe errors. They kill us sometimes for nothing*/ + signal(SIGTERM, quit_now); + signal(SIGINT, quit_now); + signal(SIGPIPE,SIG_IGN); /* Ignore pipe errors. They kill us sometimes for nothing*/ + + /* Start sendmms port */ + if (sendmms_port.port > 0) + sthread = gwthread_create((gwthread_func_t *)sendmms_func, NULL); + + + /* Start out-going queue thread. */ + qthread = gwthread_create((gwthread_func_t *)mmsbox_outgoing_queue_runner, (void *)&rstop); + + qfs->mms_queue_run(octstr_get_cstr(incoming_qdir), + mmsbox_service_dispatch, + queue_interval, maxthreads, &rstop); - /* Start sendmms port */ - if (sendmms_port.port > 0) - sthread = gwthread_create((gwthread_func_t *)sendmms_func, NULL); + mms_info(0, "mmsbox", NULL,"Shutdown started.."); - - /* Start out-going queue thread. */ - qthread = gwthread_create((gwthread_func_t *)mmsbox_outgoing_queue_runner, &rstop); - - qfs->mms_queue_run(octstr_get_cstr(incoming_qdir), - mmsbox_service_dispatch, - queue_interval, maxthreads, &rstop); + sleep(2); + /* Wait for the sender thread, then quit. */ + if (qthread >= 0) + gwthread_join(qthread); /* Wait for it to die... */ - mms_info(0, "mmsbox", NULL,"Shutdown started.."); - - sleep(2); - /* Wait for the sender thread, then quit. */ - if (qthread >= 0) - gwthread_join(qthread); /* Wait for it to die... */ + if (sendmms_port.port > 0 && sthread >= 0) + gwthread_join(sthread); - if (sendmms_port.port > 0 && sthread >= 0) - gwthread_join(sthread); - - mmsbox_settings_cleanup(); - mms_info(0, "mmsbox", NULL, "Shutdown complete.."); + mmsbox_settings_cleanup(); + mms_info(0, "mmsbox", NULL, "Shutdown complete.."); - mms_lib_shutdown(); - return 0; + mms_lib_shutdown(); + return 0; } @@ -809,88 +808,88 @@ int main(int argc, char *argv[]) /* Return the prefix part of a url or file. */ static Octstr *url_path_prefix(Octstr *url, int type) { - int i, j, len = octstr_len(url); - char *p = octstr_get_cstr(url); + int i, j, len = octstr_len(url); + char *p = octstr_get_cstr(url); - /* Set lower/upper limit of search. */ - if (type == URL_TYPE) { /* then skip first slashes. */ - char *x; - i = octstr_search(url, octstr_imm("://"),0); - if (i > 0) - i += 3; - else - i = 0; - x = rindex(p, '#'); /* look for fragment if any. */ + /* Set lower/upper limit of search. */ + if (type == URL_TYPE) { /* then skip first slashes. */ + char *x; + i = octstr_search(url, octstr_imm("://"),0); + if (i > 0) + i += 3; + else + i = 0; + x = rindex(p, '#'); /* look for fragment if any. */ - if (x) - j = x - p - 1; - else - j = len - 1; - } else { - i = 0; - j = len - 1; - } + if (x) + j = x - p - 1; + else + j = len - 1; + } else { + i = 0; + j = len - 1; + } - /* Now search backwards for the last '/'. - * if you don't find one, set to end of string. - */ + /* Now search backwards for the last '/'. + * if you don't find one, set to end of string. + */ - for (;j > i; j--) - if (p[j] == '/') - break; - if (j <= i) - j = len; + for (;j > i; j--) + if (p[j] == '/') + break; + if (j <= i) + j = len; - return octstr_copy(url, 0, j); + return octstr_copy(url, 0, j); } /* Get's just the host:port part, leaving out UrI */ static Octstr *get_toplevel_url(Octstr *url) { - int i, len = octstr_len(url); - char *p = octstr_get_cstr(url); + int i, len = octstr_len(url); + char *p = octstr_get_cstr(url); - i = octstr_search(url, octstr_imm("://"),0); + i = octstr_search(url, octstr_imm("://"),0); - if (i > 0) - i += 3; - else - i = 0; + if (i > 0) + i += 3; + else + i = 0; - for ( ; i < len; i++) - if (p[i] == '/') - break; + for ( ; i < len; i++) + if (p[i] == '/') + break; - return octstr_copy(url, 0, i); + return octstr_copy(url, 0, i); } /* little dirty method to see if file begins with url scheme. */ static int has_url_scheme(char *url, int *supported_scheme) { - char *p = strstr(url, "://"); + char *p = strstr(url, "://"); - *supported_scheme = 1; + *supported_scheme = 1; - if (strstr(url, "data:") == url || /* data: url scheme */ - strstr(url, "http://") == url || + if (strstr(url, "data:") == url || /* data: url scheme */ + strstr(url, "http://") == url || #ifdef HAVE_LIBSSL - strstr(url, "https://") == url || + strstr(url, "https://") == url || #endif - strstr(url, "file://") == url) - return 1; + strstr(url, "file://") == url) + return 1; - if (p) { + if (p) { - for (p--; p >= url; p--) - if (!isalpha(*p)) - break; - if (p < url) { - *supported_scheme = 0; /* we don't support this one. */ - return 1; - } else - return 0; - } else - return 0; + for (p--; p >= url; p--) + if (!isalpha(*p)) + break; + if (p < url) { + *supported_scheme = 0; /* we don't support this one. */ + return 1; + } else + return 0; + } else + return 0; } static int add_msg_part(MIMEEntity *res, xmlNodePtr node, Octstr *base_url, @@ -899,114 +898,114 @@ static int add_msg_part(MIMEEntity *res, xmlNodePtr node, Octstr *base_url, Octstr *mmc_id, Dict *url_map, Octstr *xmhdr, Octstr *xmhdr_val) { - Octstr *curl = NULL, *ctype = NULL, *body = NULL, *xcid = NULL; - char *src = NULL; - int isurl, slash_prefix; - Octstr *cid = NULL; - int supported_url_scheme = 0; + Octstr *curl = NULL, *ctype = NULL, *body = NULL, *xcid = NULL; + char *src = NULL; + int isurl, slash_prefix; + Octstr *cid = NULL; + int supported_url_scheme = 0; - /* For each node in the smil doc, if it has an src attribute, then: - * - if our type of base_url is FILE *and the src attribute does not look - * like a url, then file the file referenced, load it into the message and go - * - if our type is URL and the url scheme is http/https (or has no scheme) - * then fetch it and put into message. - */ + /* For each node in the smil doc, if it has an src attribute, then: + * - if our type of base_url is FILE *and the src attribute does not look + * like a url, then file the file referenced, load it into the message and go + * - if our type is URL and the url scheme is http/https (or has no scheme) + * then fetch it and put into message. + */ - if (!node || node->type != XML_ELEMENT_NODE || - (src = (char *)xmlGetProp(node, (unsigned char *)"src")) == NULL) - return 0; /* Nothing to do. */ + if (!node || node->type != XML_ELEMENT_NODE || + (src = (char *)xmlGetProp(node, (unsigned char *)"src")) == NULL) + return 0; /* Nothing to do. */ - if (src[0] == '\\') { /* User can escape url to prevent substitution. */ - xmlSetProp(node, (xmlChar *)"src", (xmlChar *)(src + 1)); - goto done; - } + if (src[0] == '\\') { /* User can escape url to prevent substitution. */ + xmlSetProp(node, (xmlChar *)"src", (xmlChar *)(src + 1)); + goto done; + } - isurl = has_url_scheme(src, &supported_url_scheme); - slash_prefix = (src[0] == '/'); + isurl = has_url_scheme(src, &supported_url_scheme); + slash_prefix = (src[0] == '/'); - if (isurl && !supported_url_scheme) - goto done; - else if (isurl) - curl = octstr_create(src); - else if (slash_prefix) { - if (type == URL_TYPE) - curl = octstr_format("%S%s", - top_url, src); - else - curl = octstr_create(src); - } else - curl = octstr_format("%S/%s",base_url, src); + if (isurl && !supported_url_scheme) + goto done; + else if (isurl) + curl = octstr_create(src); + else if (slash_prefix) { + if (type == URL_TYPE) + curl = octstr_format("%S%s", + top_url, src); + else + curl = octstr_create(src); + } else + curl = octstr_format("%S/%s",base_url, src); - if ((cid = dict_get(url_map, curl)) != NULL) { /* We've seen it before. */ - xmlSetProp(node, (xmlChar *)"src", (xmlChar *)octstr_get_cstr(cid)); - /* Don't delete cid! */ - goto done; - } + if ((cid = dict_get(url_map, curl)) != NULL) { /* We've seen it before. */ + xmlSetProp(node, (xmlChar *)"src", (xmlChar *)octstr_get_cstr(cid)); + /* Don't delete cid! */ + goto done; + } - isurl |= (type == URL_TYPE); /* From now on, this flag tells us whether we are fetching a url.*/ + isurl |= (type == URL_TYPE); /* From now on, this flag tells us whether we are fetching a url.*/ - if (isurl) { - List *rh = http_create_empty_headers(), *rph = NULL; + if (isurl) { + List *rh = http_create_empty_headers(), *rph = NULL; - http_header_add(rh, "User-Agent", MM_NAME "/" VERSION); - if (mmsbox_url_fetch_content(HTTP_METHOD_GET, curl, rh, NULL, &rph, &body) == HTTP_OK) { - ctype = http_header_value(rph, octstr_imm("Content-Type")); - xcid = http_header_value(rph, octstr_imm("Content-ID")); - } else - mms_error(0, "mmsbox", NULL, "Failed to load url %s within SMIL content from service %s!", - octstr_get_cstr(curl), - svc_name ? octstr_get_cstr(svc_name) : "unknown"); - if (rph) - http_destroy_headers(rph); - http_destroy_headers(rh); - } else { - body = octstr_read_file(octstr_get_cstr(curl)); - ctype = filename2content_type(src); - } + http_header_add(rh, "User-Agent", MM_NAME "/" VERSION); + if (mmsbox_url_fetch_content(HTTP_METHOD_GET, curl, rh, NULL, &rph, &body) == HTTP_OK) { + ctype = http_header_value(rph, octstr_imm("Content-Type")); + xcid = http_header_value(rph, octstr_imm("Content-ID")); + } else + mms_error(0, "mmsbox", NULL, "Failed to load url %s within SMIL content from service %s!", + octstr_get_cstr(curl), + svc_name ? octstr_get_cstr(svc_name) : "unknown"); + if (rph) + http_destroy_headers(rph); + http_destroy_headers(rh); + } else { + body = octstr_read_file(octstr_get_cstr(curl)); + ctype = filename2content_type(src); + } - if (ctype && body) { /* If we got it, put it in. */ - static int cntr; /* For generating cids */ - char _fext[5] = {0}, *fext = make_file_ext(curl, ctype, _fext); - Octstr *attr = xcid ? octstr_format("cid:%S", xcid) : octstr_format("cid:%06d.%s", ++cntr,fext); - char *p = octstr_get_cstr(attr) + 4; - Octstr *cid_header_val = octstr_format("<%s>", p); - MIMEEntity *x = mime_entity_create(); - List *headers = http_create_empty_headers(); + if (ctype && body) { /* If we got it, put it in. */ + static int cntr; /* For generating cids */ + char _fext[5] = {0}, *fext = make_file_ext(curl, ctype, _fext); + Octstr *attr = xcid ? octstr_format("cid:%S", xcid) : octstr_format("cid:%06d.%s", ++cntr,fext); + char *p = octstr_get_cstr(attr) + 4; + Octstr *cid_header_val = octstr_format("<%s>", p); + MIMEEntity *x = mime_entity_create(); + List *headers = http_create_empty_headers(); - http_header_add(headers, "Content-Type", octstr_get_cstr(ctype)); - http_header_add(headers, "Content-ID", octstr_get_cstr(cid_header_val)); - http_header_add(headers, "Content-Location", p); + http_header_add(headers, "Content-Type", octstr_get_cstr(ctype)); + http_header_add(headers, "Content-ID", octstr_get_cstr(cid_header_val)); + http_header_add(headers, "Content-Location", p); - if (xmhdr) - http_header_add(headers, octstr_get_cstr(xmhdr), octstr_get_cstr(xmhdr_val)); + if (xmhdr) + http_header_add(headers, octstr_get_cstr(xmhdr), octstr_get_cstr(xmhdr_val)); - mime_replace_headers(x, headers); - mime_entity_set_body(x, body); + mime_replace_headers(x, headers); + mime_entity_set_body(x, body); - if (mt_filter && mmc_id) - mt_filter->filter(&x, curl, mmc_id); + if (mt_filter && mmc_id) + mt_filter->filter(&x, curl, mmc_id); - mime_entity_add_part(res, x); - mime_entity_destroy(x); + mime_entity_add_part(res, x); + mime_entity_destroy(x); - dict_put_once(url_map, curl, octstr_duplicate(attr)); /* Store the cid. */ + dict_put_once(url_map, curl, octstr_duplicate(attr)); /* Store the cid. */ - xmlSetProp(node, (xmlChar *)"src", (xmlChar *)octstr_get_cstr(attr)); + xmlSetProp(node, (xmlChar *)"src", (xmlChar *)octstr_get_cstr(attr)); - octstr_destroy(attr); - octstr_destroy(cid_header_val); - http_destroy_headers(headers); - } + octstr_destroy(attr); + octstr_destroy(cid_header_val); + http_destroy_headers(headers); + } - done: +done: - octstr_destroy(curl); - octstr_destroy(ctype); - octstr_destroy(body); - octstr_destroy(xcid); - xmlFree(src); - return 0; + octstr_destroy(curl); + octstr_destroy(ctype); + octstr_destroy(body); + octstr_destroy(xcid); + xmlFree(src); + return 0; } /* Traverse the tree doing the above. */ @@ -1016,14 +1015,14 @@ static void add_msg_parts(MIMEEntity *res, xmlNodePtr node, Octstr *base_url, Octstr *mmc_id, Dict *url_map, Octstr *xmhdr, Octstr *xmhdr_val) { - xmlNodePtr n; - /* Do all the children recursively, then come back and do parent. */ - for (n = node; n; n = n->next) - if (n->type != XML_COMMENT_NODE) { - add_msg_part(res, n, base_url, top_url, type, svc_name, mmc_id, url_map, xmhdr, xmhdr_val); - add_msg_parts(res, n->xmlChildrenNode, base_url, top_url, type, - svc_name, mmc_id, url_map, xmhdr, xmhdr_val); - } + xmlNodePtr n; + /* Do all the children recursively, then come back and do parent. */ + for (n = node; n; n = n->next) + if (n->type != XML_COMMENT_NODE) { + add_msg_part(res, n, base_url, top_url, type, svc_name, mmc_id, url_map, xmhdr, xmhdr_val); + add_msg_parts(res, n->xmlChildrenNode, base_url, top_url, type, + svc_name, mmc_id, url_map, xmhdr, xmhdr_val); + } } /* Given content, make a message. We'll also use this for send-mms-user! */ @@ -1035,640 +1034,645 @@ static int make_and_queue_msg(Octstr *data, Octstr *ctype, List *reply_headers, Octstr *qdir, Octstr **err) { - Octstr *from = NULL, *xfrom = NULL, *subject = NULL, *turl = get_toplevel_url(base_url); - Octstr *dlr_url = NULL, *rr_url = NULL, *mmc = NULL, *xservice_code = NULL, *hsvc_code = NULL; - Octstr *allow_adaptations = NULL, *mclass = NULL, *prio = NULL, *distro = NULL, *chargedparty = NULL; - MmsMsg *m = NULL; - MIMEEntity *me = mime_entity_create(); - List *xheaders = NULL; - List *hdrs = http_create_empty_headers(); - Octstr *otransid = NULL; - Octstr *xmhdr = NULL, *xmhdr_val = NULL; + Octstr *from = NULL, *xfrom = NULL, *subject = NULL, *turl = get_toplevel_url(base_url); + Octstr *dlr_url = NULL, *rr_url = NULL, *mmc = NULL, *xservice_code = NULL, *hsvc_code = NULL; + Octstr *allow_adaptations = NULL, *mclass = NULL, *prio = NULL, *distro = NULL, *chargedparty = NULL; + MmsMsg *m = NULL; + MIMEEntity *me = mime_entity_create(); + List *xheaders = NULL; + List *hdrs = http_create_empty_headers(); + Octstr *otransid = NULL; + Octstr *xmhdr = NULL, *xmhdr_val = NULL; - time_t expiryt = time(NULL) + DEFAULT_EXPIRE; - Octstr *x; - List *xto = gwlist_create(); - int i, n, res = -1; + time_t expiryt = time(NULL) + DEFAULT_EXPIRE; + Octstr *x; + List *xto = gwlist_create(); + int i, n, res = -1; - gw_assert(svc_name); + gw_assert(svc_name); - /* Get headers needed, if we are allowed to do so. */ - if (accept_x_headers && reply_headers) { - Octstr *x = NULL; - List *l = NULL; - subject = http_header_value(reply_headers, octstr_imm("X-Mbuni-Subject")); + /* Get headers needed, if we are allowed to do so. */ + if (accept_x_headers && reply_headers) { + Octstr *x = NULL; + List *l = NULL; + subject = http_header_value(reply_headers, octstr_imm("X-Mbuni-Subject")); - if ((x = http_header_value(reply_headers, octstr_imm("X-Mbuni-Expiry"))) != NULL) - expiryt = date_parse_http(x); + if ((x = http_header_value(reply_headers, octstr_imm("X-Mbuni-Expiry"))) != NULL) + expiryt = date_parse_http(x); - if ((l = http_header_find_all(reply_headers, "X-Mbuni-To")) != NULL) { - int i, n; - for (i = 0, n = gwlist_len(l); ifrom) - gwlist_append(xto, octstr_duplicate(e->from)); + if (reply_headers) { + /* always capture transid and distro */ + otransid = http_header_value(reply_headers, octstr_imm("X-Mbuni-TransactionID")); + distro = http_header_value(reply_headers, octstr_imm("X-Mbuni-DistributionIndicator")); + } + if (gwlist_len(xto) == 0 && e && e->from) + gwlist_append(xto, octstr_duplicate(e->from)); - if (!subject && e && e->subject) - subject = octstr_duplicate(e->subject); + if (!subject && e && e->subject) + subject = octstr_duplicate(e->subject); - /* Look for special header name/value to be inserted on all objects. */ - if (reply_headers && - (xmhdr = http_header_value(reply_headers, octstr_imm("X-Mbuni-Content-Header"))) != NULL) { - int x = octstr_search_char(xmhdr,':', 0); + /* Look for special header name/value to be inserted on all objects. */ + if (reply_headers && + (xmhdr = http_header_value(reply_headers, octstr_imm("X-Mbuni-Content-Header"))) != NULL) { + int x = octstr_search_char(xmhdr,':', 0); - if (x > 0) { - xmhdr_val = octstr_copy(xmhdr, x+1, octstr_len(xmhdr)); - octstr_delete(xmhdr, x, octstr_len(xmhdr)); - } else - xmhdr_val = octstr_create(""); + if (x > 0) { + xmhdr_val = octstr_copy(xmhdr, x+1, octstr_len(xmhdr)); + octstr_delete(xmhdr, x, octstr_len(xmhdr)); + } else + xmhdr_val = octstr_create(""); - octstr_strip_blanks(xmhdr_val); - octstr_strip_blanks(xmhdr); - } + octstr_strip_blanks(xmhdr_val); + octstr_strip_blanks(xmhdr); + } #if 0 /* don't route via sender, instead use allow/deny settings. */ - if (!mmc && e) - mmc = octstr_duplicate(e->fromproxy); + if (!mmc && e) + mmc = octstr_duplicate(e->fromproxy); #endif - /* Get the from address. */ - if (faked_sender) - from = octstr_duplicate(faked_sender); - else if (xfrom != NULL) - from = octstr_duplicate(xfrom); /* all done above. */ - else { - /* get first recipient, set that as sender. */ - MmsEnvelopeTo *r = (e) ? gwlist_get(e->to, 0) : NULL; - if (r) - from = octstr_duplicate(r->rcpt); - else - from = octstr_create("anon@anon"); - } + /* Get the from address. */ + if (faked_sender) + from = octstr_duplicate(faked_sender); + else if (xfrom != NULL) + from = octstr_duplicate(xfrom); /* all done above. */ + else { + /* get first recipient, set that as sender. */ + MmsEnvelopeTo *r = (e) ? gwlist_get(e->to, 0) : NULL; + if (r) + from = octstr_duplicate(r->rcpt); + else + from = octstr_create("anon@anon"); + } - /* Get service code. */ - if (service_code) - xservice_code = octstr_duplicate(service_code); - else if (hsvc_code) - xservice_code = octstr_duplicate(hsvc_code); + /* Get service code. */ + if (service_code) + xservice_code = octstr_duplicate(service_code); + else if (hsvc_code) + xservice_code = octstr_duplicate(hsvc_code); - if (from) - _mms_fixup_address(&from, NULL, NULL, 1); /* Don't normalise. */ + if (from) + _mms_fixup_address(&from, NULL, NULL, 1); /* Don't normalise. */ - /* Now get the data. */ - if (octstr_str_case_compare(ctype, "application/vnd.wap.mms-message") == 0) - m = mms_frombinary(data, from); - else if (octstr_case_search(ctype, octstr_imm("multipart/"), 0) == 0) { /* treat it differently. */ - MIMEEntity *mime = mime_http_to_entity(reply_headers, data); - if (mime) { - mime_entity_destroy(me); - me = mime; - } - } else if (octstr_case_search(ctype, - octstr_imm(MBUNI_MULTIPART_TYPE), 0) == 0) { /* Mbuni multipart.*/ - List *l = octstr_split_words(data); - MIMEEntity *mime = multipart_from_urls(l); + /* Now get the data. */ + if (octstr_str_case_compare(ctype, "application/vnd.wap.mms-message") == 0) + m = mms_frombinary(data, from); + else if (octstr_case_search(ctype, octstr_imm("multipart/"), 0) == 0) { /* treat it differently. */ + MIMEEntity *mime = mime_http_to_entity(reply_headers, data); + if (mime) { + mime_entity_destroy(me); + me = mime; + } + } else if (octstr_case_search(ctype, + octstr_imm(MBUNI_MULTIPART_TYPE), 0) == 0) { /* Mbuni multipart.*/ + List *l = octstr_split_words(data); + MIMEEntity *mime = multipart_from_urls(l); - if (mime) { - mime_entity_destroy(me); - me = mime; - } - gwlist_destroy(l, (void *)octstr_destroy); - } else if (octstr_case_search(ctype, octstr_imm("application/smil"), 0) == 0) { - xmlDocPtr smil; - xmlChar *buf = NULL; - int bsize = 0; - Dict *url_map = dict_create(97, (void (*)(void *))octstr_destroy); - List *xh = http_create_empty_headers(); + if (mime) { + mime_entity_destroy(me); + me = mime; + } + gwlist_destroy(l, (void *)octstr_destroy); + } else if (octstr_case_search(ctype, octstr_imm("application/smil"), 0) == 0) { + xmlDocPtr smil; + xmlChar *buf = NULL; + int bsize = 0; + Dict *url_map = dict_create(97, (void (*)(void *))octstr_destroy); + List *xh = http_create_empty_headers(); - /* This is the hard bit: Fetch each external reference in smil, add it to message! */ - http_header_add(xh, "Content-Type", "multipart/related; " - "type=\"application/smil\"; start=\"\""); - mime_replace_headers(me,xh); - http_destroy_headers(xh); + /* This is the hard bit: Fetch each external reference in smil, add it to message! */ + http_header_add(xh, "Content-Type", "multipart/related; " + "type=\"application/smil\"; start=\"\""); + mime_replace_headers(me,xh); + http_destroy_headers(xh); - /* Parse the smil as XML. */ - smil = xmlParseMemory(octstr_get_cstr(data), octstr_len(data)); - if (!smil || !smil->xmlChildrenNode) { - *err = octstr_format("MMSBox: Error parsing SMIL response from service[%s], " - " msgid %s!", octstr_get_cstr(svc_name), - (e && e->msgId) ? octstr_get_cstr(e->msgId) : "(none)"); - dict_destroy(url_map); - goto done; - } + /* Parse the smil as XML. */ + smil = xmlParseMemory(octstr_get_cstr(data), octstr_len(data)); + if (!smil || !smil->xmlChildrenNode) { + *err = octstr_format("MMSBox: Error parsing SMIL response from service[%s], " + " msgid %s!", octstr_get_cstr(svc_name), + (e && e->msgId) ? octstr_get_cstr(e->msgId) : "(none)"); + dict_destroy(url_map); + goto done; + } - add_msg_parts(me, smil->xmlChildrenNode, - base_url, turl, type, svc_name, - mmc, url_map, xmhdr, xmhdr_val); + add_msg_parts(me, smil->xmlChildrenNode, + base_url, turl, type, svc_name, + mmc, url_map, xmhdr, xmhdr_val); - dict_destroy(url_map); - /* SMIL has been modified, convert it to text, put it in. */ - xmlDocDumpFormatMemory(smil, &buf, &bsize, 1); - xmlFreeDoc(smil); - if (buf) { - MIMEEntity *sm = mime_entity_create(); - List *xh = http_create_empty_headers(); - Octstr *s; + dict_destroy(url_map); + /* SMIL has been modified, convert it to text, put it in. */ + xmlDocDumpFormatMemory(smil, &buf, &bsize, 1); + xmlFreeDoc(smil); + if (buf) { + MIMEEntity *sm = mime_entity_create(); + List *xh = http_create_empty_headers(); + Octstr *s; - http_header_add(xh, "Content-Type", "application/smil"); - http_header_add(xh, "Content-ID", ""); /* identify it as start element. */ - if (xmhdr) - http_header_add(xh, octstr_get_cstr(xmhdr), octstr_get_cstr(xmhdr_val)); - s = octstr_create_from_data((char *)buf, bsize); + http_header_add(xh, "Content-Type", "application/smil"); + http_header_add(xh, "Content-ID", ""); /* identify it as start element. */ + if (xmhdr) + http_header_add(xh, octstr_get_cstr(xmhdr), octstr_get_cstr(xmhdr_val)); + s = octstr_create_from_data((char *)buf, bsize); - mime_replace_headers(sm, xh); - mime_entity_set_body(sm, s); + mime_replace_headers(sm, xh); + mime_entity_set_body(sm, s); - mime_entity_add_part(me, sm); + mime_entity_add_part(me, sm); - mime_entity_destroy(sm); - http_destroy_headers(xh); - octstr_destroy(s); + mime_entity_destroy(sm); + http_destroy_headers(xh); + octstr_destroy(s); - xmlFree(buf); - } else { - *err = octstr_format("MMSBox: Error writing converted SMIL " - "for response from service[%s], " - " msgid %s!", - octstr_get_cstr(svc_name), - (e && e->msgId) ? octstr_get_cstr(e->msgId) : "(none)"); - goto done; - } - } else { /* all others, make the message as-is and hope for the best! */ - List *xh = http_create_empty_headers(); + xmlFree(buf); + } else { + *err = octstr_format("MMSBox: Error writing converted SMIL " + "for response from service[%s], " + " msgid %s!", + octstr_get_cstr(svc_name), + (e && e->msgId) ? octstr_get_cstr(e->msgId) : "(none)"); + goto done; + } + } else { /* all others, make the message as-is and hope for the best! */ + List *xh = http_create_empty_headers(); - if (mt_multipart) { /* if it's going to be multi-part, add some headers. */ - static int cntr = 0; - char _fext[5] = {0}, *fext = make_file_ext(msg_url, ctype, _fext); - Octstr *attr = octstr_format("%06d.%s", ++cntr,fext); - Octstr *cid_header_val = octstr_format("<%S>", attr); + if (mt_multipart) { /* if it's going to be multi-part, add some headers. */ + static int cntr = 0; + char _fext[5] = {0}, *fext = make_file_ext(msg_url, ctype, _fext); + Octstr *attr = octstr_format("%06d.%s", ++cntr,fext); + Octstr *cid_header_val = octstr_format("<%S>", attr); - http_header_add(xh, "Content-ID", octstr_get_cstr(cid_header_val)); - http_header_add(xh, "Content-Location", octstr_get_cstr(attr)); + http_header_add(xh, "Content-ID", octstr_get_cstr(cid_header_val)); + http_header_add(xh, "Content-Location", octstr_get_cstr(attr)); - octstr_destroy(attr); - octstr_destroy(cid_header_val); - } + octstr_destroy(attr); + octstr_destroy(cid_header_val); + } - http_header_add(xh, "Content-Type", octstr_get_cstr(ctype)); - if (xmhdr) - http_header_add(xh, octstr_get_cstr(xmhdr), octstr_get_cstr(xmhdr_val)); + http_header_add(xh, "Content-Type", octstr_get_cstr(ctype)); + if (xmhdr) + http_header_add(xh, octstr_get_cstr(xmhdr), octstr_get_cstr(xmhdr_val)); - mime_replace_headers(me, xh); + mime_replace_headers(me, xh); - http_destroy_headers(xh); - mime_entity_set_body(me, data); + http_destroy_headers(xh); + mime_entity_set_body(me, data); - if (mt_filter && mmc) /* filter it too. */ - mt_filter->filter(&me, msg_url, mmc); + if (mt_filter && mmc) /* filter it too. */ + mt_filter->filter(&me, msg_url, mmc); - if (mt_multipart && - octstr_case_search(ctype, octstr_imm("multipart/"), 0) != 0) { /* requires multipart but this one is not, wrap it */ - MIMEEntity *xm = mime_entity_create(); - List *h1 = http_create_empty_headers(); + if (mt_multipart && + octstr_case_search(ctype, octstr_imm("multipart/"), 0) != 0) { /* requires multipart but this one is not, wrap it */ + MIMEEntity *xm = mime_entity_create(); + List *h1 = http_create_empty_headers(); - http_header_add(h1, "Content-Type", "multipart/related"); - mime_replace_headers(xm, h1); - mime_entity_add_part(xm, me); + http_header_add(h1, "Content-Type", "multipart/related"); + mime_replace_headers(xm, h1); + mime_entity_add_part(xm, me); - http_destroy_headers(h1); + http_destroy_headers(h1); - me = xm; - } - } + me = xm; + } + } - /* Add some nice headers. */ - xheaders = mime_entity_headers(me); - http_header_add(xheaders, "From", octstr_get_cstr(from)); + /* Add some nice headers. */ + xheaders = mime_entity_headers(me); + http_header_add(xheaders, "From", octstr_get_cstr(from)); - for (i = 0, n = gwlist_len(xto); i < n; i++) { - Octstr *v; - v = gwlist_get(xto, i); - http_header_add(xheaders, "To", octstr_get_cstr(v)); - } + for (i = 0, n = gwlist_len(xto); i < n; i++) { + Octstr *v; + v = gwlist_get(xto, i); + http_header_add(xheaders, "To", octstr_get_cstr(v)); + } - if (dlr_url) - http_header_add(xheaders, "X-Mms-Delivery-Report", "Yes"); - if (rr_url) - http_header_add(xheaders, "X-Mms-Read-Report", "Yes"); - if (allow_adaptations) - http_header_add(xheaders, "X-Mms-Allow-Adaptations", - (octstr_str_compare(allow_adaptations, "true") == 0) ? "true" : "false"); + if (dlr_url) + http_header_add(xheaders, "X-Mms-Delivery-Report", "Yes"); + if (rr_url) + http_header_add(xheaders, "X-Mms-Read-Report", "Yes"); + if (allow_adaptations) + http_header_add(xheaders, "X-Mms-Allow-Adaptations", + (octstr_str_compare(allow_adaptations, "true") == 0) ? "true" : "false"); - if (mclass) - http_header_add(xheaders, "X-Mms-Message-Class", octstr_get_cstr(mclass)); + if (mclass) + http_header_add(xheaders, "X-Mms-Message-Class", octstr_get_cstr(mclass)); - if (prio) - http_header_add(xheaders, "X-Mms-Priority", octstr_get_cstr(prio)); + if (prio) + http_header_add(xheaders, "X-Mms-Priority", octstr_get_cstr(prio)); - if (subject) - http_header_add(xheaders, "Subject", octstr_get_cstr(subject)); - if (expiryt > 0) { - Octstr *x = date_format_http(expiryt); - http_header_add(xheaders, "X-Mms-Expiry", octstr_get_cstr(x)); - octstr_destroy(x); - } - mime_replace_headers(me, xheaders); - http_destroy_headers(xheaders); + if (subject) + http_header_add(xheaders, "Subject", octstr_get_cstr(subject)); + if (expiryt > 0) { + Octstr *x = date_format_http(expiryt); + http_header_add(xheaders, "X-Mms-Expiry", octstr_get_cstr(x)); + octstr_destroy(x); + } + mime_replace_headers(me, xheaders); + http_destroy_headers(xheaders); - if (me && !m) /* Set m if it hasn't been set yet. */ - m = mms_frommime(me); - if (!m) { - *err = octstr_format("MMSBox: Failed to convert Mms Message from service %s!", - octstr_get_cstr(svc_name)); - goto done; - } + if (me && !m) /* Set m if it hasn't been set yet. */ + m = mms_frommime(me); + if (!m) { + *err = octstr_format("MMSBox: Failed to convert Mms Message from service %s!", + octstr_get_cstr(svc_name)); + goto done; + } - if (otransid) /* always add transid */ - http_header_add(hdrs, "X-Mbuni-TransactionID", octstr_get_cstr(otransid)); + if (otransid) /* always add transid */ + http_header_add(hdrs, "X-Mbuni-TransactionID", octstr_get_cstr(otransid)); - if (distro) /* always add distrib */ - http_header_add(hdrs, "X-Mbuni-DistributionIndicator", - (octstr_str_case_compare(distro, "true") == 0) ? "true" : "false"); + if (distro) /* always add distrib */ + http_header_add(hdrs, "X-Mbuni-DistributionIndicator", + (octstr_str_case_compare(distro, "true") == 0) ? "true" : "false"); - if (chargedparty) - http_header_add(hdrs, "X-Mbuni-Charged-Party", octstr_get_cstr(chargedparty)); - if (passthro_headers && reply_headers) { /* if user wants passthro headers, get them and add them. */ - int n = gwlist_len(reply_headers); - int i; - for (i = 0; i < n; i++) { - Octstr *h = NULL, *v = NULL; - int j; - http_header_get(reply_headers, i, &h, &v); - if (h == NULL || v == NULL) - goto loop; + if (chargedparty) + http_header_add(hdrs, "X-Mbuni-Charged-Party", octstr_get_cstr(chargedparty)); + if (passthro_headers && reply_headers) { /* if user wants passthro headers, get them and add them. */ + int n = gwlist_len(reply_headers); + int i; + for (i = 0; i < n; i++) { + Octstr *h = NULL, *v = NULL; + int j; + http_header_get(reply_headers, i, &h, &v); + if (h == NULL || v == NULL) + goto loop; - /* Check for this header in - * pass thro list. - */ - for (j = 0; j < gwlist_len(passthro_headers); j++) - if (octstr_case_compare(h, gwlist_get(passthro_headers, j)) == 0) { - http_header_add(hdrs, octstr_get_cstr(h), octstr_get_cstr(v)); - break; - } - loop: - octstr_destroy(h); - octstr_destroy(v); - } - } + /* Check for this header in + * pass thro list. + */ + for (j = 0; j < gwlist_len(passthro_headers); j++) + if (octstr_case_compare(h, gwlist_get(passthro_headers, j)) == 0) { + http_header_add(hdrs, octstr_get_cstr(h), octstr_get_cstr(v)); + break; + } + loop: + octstr_destroy(h); + octstr_destroy(v); + } + } - /* Write to queue. */ - x = qfs->mms_queue_add(from, xto, subject, - e ? e->fromproxy : NULL, - mmc, - time(NULL), expiryt, m, NULL, - xservice_code, /* Send service code as vasp id XXX - not very nice, but */ - svc_name, - dlr_url, rr_url, - hdrs, - (dlr_url != NULL), - octstr_get_cstr(qdir), - "MMSBox", - NULL); - mms_info(0, "mmsbox", NULL,"MMSBox: Queued message from service [%s], [transid [%s]: %s", - octstr_get_cstr(svc_name), - otransid ? octstr_get_cstr(otransid) : "", - octstr_get_cstr(x)); - *err = x; - res = 0; - done: + /* Write to queue. */ + x = qfs->mms_queue_add(from, xto, subject, + e ? e->fromproxy : NULL, + mmc, + time(NULL), expiryt, m, NULL, + xservice_code, /* Send service code as vasp id XXX - not very nice, but */ + svc_name, + dlr_url, rr_url, + hdrs, + (dlr_url != NULL), + octstr_get_cstr(qdir), + "MMSBox", + NULL); + mms_info(0, "mmsbox", NULL,"MMSBox: Queued message from service [%s], [transid [%s]: %s", + octstr_get_cstr(svc_name), + otransid ? octstr_get_cstr(otransid) : "", + octstr_get_cstr(x)); + *err = x; + res = 0; +done: - octstr_destroy(dlr_url); - octstr_destroy(rr_url); - octstr_destroy(mclass); - octstr_destroy(prio); - octstr_destroy(mmc); - octstr_destroy(allow_adaptations); - octstr_destroy(from); - octstr_destroy(xfrom); - octstr_destroy(subject); - octstr_destroy(otransid); - octstr_destroy(turl); - octstr_destroy(chargedparty); + octstr_destroy(dlr_url); + octstr_destroy(rr_url); + octstr_destroy(mclass); + octstr_destroy(prio); + octstr_destroy(mmc); + octstr_destroy(allow_adaptations); + octstr_destroy(from); + octstr_destroy(xfrom); + octstr_destroy(subject); + octstr_destroy(otransid); + octstr_destroy(turl); + octstr_destroy(chargedparty); - octstr_destroy(xmhdr); - octstr_destroy(xmhdr_val); - if (me) - mime_entity_destroy(me); + octstr_destroy(xmhdr); + octstr_destroy(xmhdr_val); + if (me) + mime_entity_destroy(me); - mms_destroy(m); - gwlist_destroy(xto, (void *)octstr_destroy); - http_destroy_headers(hdrs); - octstr_destroy(xservice_code); - octstr_destroy(hsvc_code); + mms_destroy(m); + gwlist_destroy(xto, (void *)octstr_destroy); + http_destroy_headers(hdrs); + octstr_destroy(xservice_code); + octstr_destroy(hsvc_code); - return res; + return res; } static SendMmsUser *auth_user(Octstr *user, Octstr *pass) { - int i, n; - SendMmsUser *u = NULL; + int i, n; + SendMmsUser *u = NULL; - if (!user || !pass) - return NULL; - for (i = 0, n = gwlist_len(sendmms_users); i < n; i++) - if ((u = gwlist_get(sendmms_users, i)) != NULL && - octstr_compare(u->user, user) == 0 && - octstr_compare(u->pass, pass) == 0) - return u; - return NULL; + if (!user || !pass) + return NULL; + for (i = 0, n = gwlist_len(sendmms_users); i < n; i++) + if ((u = gwlist_get(sendmms_users, i)) != NULL && + octstr_compare(u->user, user) == 0 && + octstr_compare(u->pass, pass) == 0) + return u; + return NULL; } static void dispatch_sendmms_recv(List *rl) { - MmsBoxHTTPClientInfo *h; + MmsBoxHTTPClientInfo *h; - while ((h = gwlist_consume(rl)) != NULL) { - SendMmsUser *u = NULL; - List *hh = http_create_empty_headers(); - Octstr *username; - Octstr *password; - Octstr *err = NULL; - List *cgivar_ctypes = NULL; - char *etype = NULL; - - int res = 0, tparse = parse_cgivars(h->headers, h->body, &h->cgivars, &cgivar_ctypes); + hmon->register_thread(); + while ((h = gwlist_consume(rl)) != NULL) { + SendMmsUser *u = NULL; + List *hh = http_create_empty_headers(); + Octstr *username; + Octstr *password; + Octstr *err = NULL; + List *cgivar_ctypes = NULL; + char *etype = NULL; - username = http_cgi_variable(h->cgivars, "username"); - password = http_cgi_variable(h->cgivars, "password"); - if (username) - octstr_strip_blanks(username); - if (password) - octstr_strip_blanks(password); - if ((u = auth_user(username, password)) != NULL && - is_allowed_ip(sendmms_port.allow_ip, sendmms_port.deny_ip, h->ip)) { - Octstr *data, *external_data = NULL, *ctype = NULL, *mmc, *to, *from, *dlr_url; - Octstr *rr_url, *allow_adaptations, *subject = NULL; - List *lto = NULL, *rh = http_create_empty_headers(); - Octstr *rb = NULL, *base_url; - int i, n, skip_ctype = 0; - Octstr *vasid = http_cgi_variable(h->cgivars, "vasid"); - Octstr *service_code = http_cgi_variable(h->cgivars, "servicecode"); - Octstr *mclass = http_cgi_variable(h->cgivars, "mclass"); - Octstr *prio = http_cgi_variable(h->cgivars, "priority"); - Octstr *distro = http_cgi_variable(h->cgivars, "distribution"); - Octstr *send_type = http_cgi_variable(h->cgivars, "mms-direction"); - Octstr *sheader = http_cgi_variable(h->cgivars, "extra-content-header"); - Octstr *validity = http_cgi_variable(h->cgivars, "validityperiod"); - Octstr *chargedparty = http_cgi_variable(h->cgivars, "charged-party"); - Octstr *data_url = NULL; + int res = 0, tparse = parse_cgivars(h->headers, h->body, &h->cgivars, &cgivar_ctypes); + + username = http_cgi_variable(h->cgivars, "username"); + password = http_cgi_variable(h->cgivars, "password"); + if (username) + octstr_strip_blanks(username); + if (password) + octstr_strip_blanks(password); + if ((u = auth_user(username, password)) != NULL && + is_allowed_ip(sendmms_port.allow_ip, sendmms_port.deny_ip, h->ip)) { + Octstr *data, *external_data = NULL, *ctype = NULL, *mmc, *to, *from, *dlr_url; + Octstr *rr_url, *allow_adaptations, *subject = NULL; + List *lto = NULL, *rh = http_create_empty_headers(); + Octstr *rb = NULL, *base_url; + int i, n, skip_ctype = 0; + Octstr *vasid = http_cgi_variable(h->cgivars, "vasid"); + Octstr *service_code = http_cgi_variable(h->cgivars, "servicecode"); + Octstr *mclass = http_cgi_variable(h->cgivars, "mclass"); + Octstr *prio = http_cgi_variable(h->cgivars, "priority"); + Octstr *distro = http_cgi_variable(h->cgivars, "distribution"); + Octstr *send_type = http_cgi_variable(h->cgivars, "mms-direction"); + Octstr *sheader = http_cgi_variable(h->cgivars, "extra-content-header"); + Octstr *validity = http_cgi_variable(h->cgivars, "validityperiod"); + Octstr *chargedparty = http_cgi_variable(h->cgivars, "charged-party"); + Octstr *data_url = NULL; - dlr_url = http_cgi_variable(h->cgivars, "dlr-url"); - rr_url = http_cgi_variable(h->cgivars, "rr-url"); - allow_adaptations = http_cgi_variable(h->cgivars, "allow-adaptations"); - + dlr_url = http_cgi_variable(h->cgivars, "dlr-url"); + rr_url = http_cgi_variable(h->cgivars, "rr-url"); + allow_adaptations = http_cgi_variable(h->cgivars, "allow-adaptations"); - if ((mmc = http_cgi_variable(h->cgivars, "mmsc")) == NULL) { - mmc = octstr_duplicate(u->mmsc); /* could still be NULL */ - } - subject = http_cgi_variable(h->cgivars, "subject"); - if ((base_url = http_cgi_variable(h->cgivars, "base-url")) == NULL) - base_url = octstr_create("http://localhost"); - else - base_url = octstr_duplicate(base_url); /* because we need to delete it below. */ + if ((mmc = http_cgi_variable(h->cgivars, "mmsc")) == NULL) { + mmc = octstr_duplicate(u->mmsc); /* could still be NULL */ + } + subject = http_cgi_variable(h->cgivars, "subject"); + + if ((base_url = http_cgi_variable(h->cgivars, "base-url")) == NULL) + base_url = octstr_create("http://localhost"); + else + base_url = octstr_duplicate(base_url); /* because we need to delete it below. */ + + /* Now get the data. */ + if ((data = http_cgi_variable(h->cgivars, "text")) != NULL) { /* text. */ + Octstr *charset = http_cgi_variable(h->cgivars, "charset"); + + ctype = octstr_format("text/plain"); + if (charset) + octstr_format_append(ctype, "; charset=%S", charset); + } else if ((data = http_cgi_variable(h->cgivars, "smil")) != NULL) /* smil. */ + ctype = octstr_create("application/smil"); + else if ((data = http_cgi_variable(h->cgivars, "content-url")) != NULL) { /* arbitrary content. */ + List *reqh = http_create_empty_headers(), *rph = NULL; + Octstr *reply = NULL, *params = NULL; + + http_header_add(reqh, "User-Agent", MM_NAME "/" VERSION); + + if (mmsbox_url_fetch_content(HTTP_METHOD_GET, data, reqh, NULL, &rph, &reply) == HTTP_OK) + get_content_type(rph, &ctype, ¶ms); + else + rb = octstr_format("failed to fetch content from url [%S]!", data); + base_url = url_path_prefix(data, URL_TYPE); + + data_url = octstr_duplicate(data); /* the URL of the message. */ + data = external_data = reply; /* We record it separately for deletion below. */ - /* Now get the data. */ - if ((data = http_cgi_variable(h->cgivars, "text")) != NULL) { /* text. */ - Octstr *charset = http_cgi_variable(h->cgivars, "charset"); + http_destroy_headers(reqh); + http_destroy_headers(rh); + rh = rph ? rph : http_create_empty_headers(); /* replace as real reply headers. */ + skip_ctype = 1; + octstr_destroy(params); + } else if ((data = http_cgi_variable(h->cgivars, "content")) != NULL) { /* any content. */ + Octstr *_xctype = NULL; /* ... because cgi var stuff is destroyed elsewhere, we must dup it !! */ - ctype = octstr_format("text/plain"); - if (charset) - octstr_format_append(ctype, "; charset=%S", charset); - } else if ((data = http_cgi_variable(h->cgivars, "smil")) != NULL) /* smil. */ - ctype = octstr_create("application/smil"); - else if ((data = http_cgi_variable(h->cgivars, "content-url")) != NULL) { /* arbitrary content. */ - List *reqh = http_create_empty_headers(), *rph = NULL; - Octstr *reply = NULL, *params = NULL; - - http_header_add(reqh, "User-Agent", MM_NAME "/" VERSION); - - if (mmsbox_url_fetch_content(HTTP_METHOD_GET, data, reqh, NULL, &rph, &reply) == HTTP_OK) - get_content_type(rph, &ctype, ¶ms); - else - rb = octstr_format("failed to fetch content from url [%S]!", data); - base_url = url_path_prefix(data, URL_TYPE); - - data_url = octstr_duplicate(data); /* the URL of the message. */ - data = external_data = reply; /* We record it separately for deletion below. */ - - http_destroy_headers(reqh); - http_destroy_headers(rh); - rh = rph ? rph : http_create_empty_headers(); /* replace as real reply headers. */ - skip_ctype = 1; - octstr_destroy(params); - } else if ((data = http_cgi_variable(h->cgivars, "content")) != NULL) { /* any content. */ - Octstr *_xctype = NULL; /* ... because cgi var stuff is destroyed elsewhere, we must dup it !! */ - - /* If the user sent us a content element, then they should have - * sent us its type either as part of the HTTP POST (multipart/form-data) - * or as CGI VAR called content_type - */ - if ((_xctype = http_cgi_variable(h->cgivars, "content_type")) == NULL) - if (cgivar_ctypes) - _xctype = http_cgi_variable(cgivar_ctypes, "content"); - if (_xctype) - ctype = octstr_duplicate(_xctype); - else - ctype = octstr_create("application/octet-stream"); - } else if (h->body && tparse != 0) { /* if all above fails, - use send-mms msg body if any. */ - data = octstr_duplicate(h->body); - ctype = http_header_value(h->headers, octstr_imm("Content-Type")); - } else - rb = octstr_create("Missing content"); + /* If the user sent us a content element, then they should have + * sent us its type either as part of the HTTP POST (multipart/form-data) + * or as CGI VAR called content_type + */ + if ((_xctype = http_cgi_variable(h->cgivars, "content_type")) == NULL) + if (cgivar_ctypes) + _xctype = http_cgi_variable(cgivar_ctypes, "content"); + if (_xctype) + ctype = octstr_duplicate(_xctype); + else + ctype = octstr_create("application/octet-stream"); + } else if (h->body && tparse != 0) { /* if all above fails, + use send-mms msg body if any. */ + data = octstr_duplicate(h->body); + ctype = http_header_value(h->headers, octstr_imm("Content-Type")); + } else + rb = octstr_create("Missing content"); - if ((to = http_cgi_variable(h->cgivars, "to")) == NULL) - rb = octstr_create("Missing recipient!"); - else - lto = octstr_split_words(to); + if ((to = http_cgi_variable(h->cgivars, "to")) == NULL) + rb = octstr_create("Missing recipient!"); + else + lto = octstr_split_words(to); - /* Build the fake reply headers. */ - if (ctype && !skip_ctype) - http_header_add(rh, "Content-Type", octstr_get_cstr(ctype)); + /* Build the fake reply headers. */ + if (ctype && !skip_ctype) + http_header_add(rh, "Content-Type", octstr_get_cstr(ctype)); - if ((from = http_cgi_variable(h->cgivars, "from")) != NULL) { - from = octstr_duplicate(from); - _mms_fixup_address(&from, NULL, NULL, 1); - if (from) - HTTP_REPLACE_HEADER(rh, "X-Mbuni-From", octstr_get_cstr(from)); - octstr_destroy(from); - } else if (!u->faked_sender) - rb = octstr_create("Missing Sender address"); + if ((from = http_cgi_variable(h->cgivars, "from")) != NULL) { + from = octstr_duplicate(from); + _mms_fixup_address(&from, NULL, NULL, 1); + if (from) + HTTP_REPLACE_HEADER(rh, "X-Mbuni-From", octstr_get_cstr(from)); + octstr_destroy(from); + } else if (!u->faked_sender) + rb = octstr_create("Missing Sender address"); - if (lto) { - for (i = 0, n = gwlist_len(lto); i < n; i++) { - Octstr *x = gwlist_get(lto, i); - http_header_add(rh, "X-Mbuni-To", octstr_get_cstr(x)); - } - gwlist_destroy(lto, (gwlist_item_destructor_t *)octstr_destroy); - } - if (dlr_url) - HTTP_REPLACE_HEADER(rh, "X-Mbuni-DLR-Url", octstr_get_cstr(dlr_url)); + if (lto) { + for (i = 0, n = gwlist_len(lto); i < n; i++) { + Octstr *x = gwlist_get(lto, i); + http_header_add(rh, "X-Mbuni-To", octstr_get_cstr(x)); + } + gwlist_destroy(lto, (gwlist_item_destructor_t *)octstr_destroy); + } + if (dlr_url) + HTTP_REPLACE_HEADER(rh, "X-Mbuni-DLR-Url", octstr_get_cstr(dlr_url)); - if (rr_url) - HTTP_REPLACE_HEADER(rh, "X-Mbuni-RR-Url", octstr_get_cstr(rr_url)); + if (rr_url) + HTTP_REPLACE_HEADER(rh, "X-Mbuni-RR-Url", octstr_get_cstr(rr_url)); - if (allow_adaptations) - HTTP_REPLACE_HEADER(rh, "X-Mbuni-Allow-Adaptations", - (octstr_str_compare(allow_adaptations, "1") == 0) ? - "true" : "false"); - if (mmc) - HTTP_REPLACE_HEADER(rh, "X-Mbuni-MMSC", octstr_get_cstr(mmc)); + if (allow_adaptations) + HTTP_REPLACE_HEADER(rh, "X-Mbuni-Allow-Adaptations", + (octstr_str_compare(allow_adaptations, "1") == 0) ? + "true" : "false"); + if (mmc) + HTTP_REPLACE_HEADER(rh, "X-Mbuni-MMSC", octstr_get_cstr(mmc)); - if (subject) - HTTP_REPLACE_HEADER(rh, "X-Mbuni-Subject", octstr_get_cstr(subject)); + if (subject) + HTTP_REPLACE_HEADER(rh, "X-Mbuni-Subject", octstr_get_cstr(subject)); - if (mclass) - HTTP_REPLACE_HEADER(rh, "X-Mbuni-MessageClass", octstr_get_cstr(mclass)); - if (prio) - HTTP_REPLACE_HEADER(rh, "X-Mbuni-Priority", octstr_get_cstr(prio)); - if (distro) - HTTP_REPLACE_HEADER(rh, "X-Mbuni-DistributionIndicator", octstr_get_cstr(distro)); + if (mclass) + HTTP_REPLACE_HEADER(rh, "X-Mbuni-MessageClass", octstr_get_cstr(mclass)); + if (prio) + HTTP_REPLACE_HEADER(rh, "X-Mbuni-Priority", octstr_get_cstr(prio)); + if (distro) + HTTP_REPLACE_HEADER(rh, "X-Mbuni-DistributionIndicator", octstr_get_cstr(distro)); - if (sheader) - HTTP_REPLACE_HEADER(rh, "X-Mbuni-Content-Header", octstr_get_cstr(sheader)); + if (sheader) + HTTP_REPLACE_HEADER(rh, "X-Mbuni-Content-Header", octstr_get_cstr(sheader)); - if (chargedparty) - HTTP_REPLACE_HEADER(rh, "X-Mbuni-Charged-Party", octstr_get_cstr(chargedparty)); + if (chargedparty) + HTTP_REPLACE_HEADER(rh, "X-Mbuni-Charged-Party", octstr_get_cstr(chargedparty)); - if (validity) { - int diff = atoi(octstr_get_cstr(validity)); - time_t t = time(NULL) + (diff *60); - Octstr *xt = date_format_http(t); + if (validity) { + int diff = atoi(octstr_get_cstr(validity)); + time_t t = time(NULL) + (diff *60); + Octstr *xt = date_format_http(t); - HTTP_REPLACE_HEADER(rh, "X-Mbuni-Expiry", octstr_get_cstr(xt)); + HTTP_REPLACE_HEADER(rh, "X-Mbuni-Expiry", octstr_get_cstr(xt)); - octstr_destroy(xt); - } + octstr_destroy(xt); + } - /* Requests to make_and_queue below can block, but for now we don't care. */ - if (ctype && data && !rb) { /* only send if no error. */ - int send_as_incoming = (send_type && - octstr_str_case_compare(send_type, "mo") == 0); - Octstr *transid = NULL; - if (!send_as_incoming) { /* for outgoing, track TransactionID for DLR. */ - transid = mms_maketransid(NULL, octstr_imm(MM_NAME)); - HTTP_REPLACE_HEADER(rh, "X-Mbuni-TransactionID", octstr_get_cstr(transid)); - } - res = make_and_queue_msg(data, ctype, rh, - data_url ? data_url : base_url, - base_url, URL_TYPE, NULL, - vasid ? vasid : octstr_imm("sendmms-user"), - u->faked_sender, service_code, - 1, NULL, - send_as_incoming ? incoming_qdir : outgoing_qdir, - &err); - if (res < 0) - rb = octstr_format("Error in message conversion: %S", err); - else - rb = octstr_format("Accepted: %S", /* repeat transid. */ - send_as_incoming ? err : transid); - octstr_destroy(transid); - } else if (!rb) - rb = octstr_create("Failed to send message"); - http_send_reply(h->client, (res == 0) ? HTTP_OK : HTTP_BAD_REQUEST, hh, - rb ? rb : octstr_imm("Sent")); - mms_info(0, "mmsbox", NULL,"MMSBox.mmssend: u=%s, %s [%s]", - u ? octstr_get_cstr(u->user) : "none", - (res == 0) ? "Queued" : "Not Queued", - rb ? octstr_get_cstr(rb) : ""); + /* Requests to make_and_queue below can block, but for now we don't care. */ + if (ctype && data && !rb) { /* only send if no error. */ + int send_as_incoming = (send_type && + octstr_str_case_compare(send_type, "mo") == 0); + Octstr *transid = NULL; + if (!send_as_incoming) { /* for outgoing, track TransactionID for DLR. */ + transid = mms_maketransid(NULL, octstr_imm(MM_NAME)); + HTTP_REPLACE_HEADER(rh, "X-Mbuni-TransactionID", octstr_get_cstr(transid)); + } + res = make_and_queue_msg(data, ctype, rh, + data_url ? data_url : base_url, + base_url, URL_TYPE, NULL, + vasid ? vasid : octstr_imm("sendmms-user"), + u->faked_sender, service_code, + 1, NULL, + send_as_incoming ? incoming_qdir : outgoing_qdir, + &err); + if (res < 0) + rb = octstr_format("Error in message conversion: %S", err); + else + rb = octstr_format("Accepted: %S", /* repeat transid. */ + send_as_incoming ? err : transid); + octstr_destroy(transid); + } else if (!rb) + rb = octstr_create("Failed to send message"); + http_send_reply(h->client, (res == 0) ? HTTP_OK : HTTP_BAD_REQUEST, hh, + rb ? rb : octstr_imm("Sent")); + mms_info(0, "mmsbox", NULL,"MMSBox.mmssend: u=%s, %s [%s]", + u ? octstr_get_cstr(u->user) : "none", + (res == 0) ? "Queued" : "Not Queued", + rb ? octstr_get_cstr(rb) : ""); - http_destroy_headers(rh); - octstr_destroy(ctype); - octstr_destroy(rb); - octstr_destroy(base_url); - octstr_destroy(data_url); - octstr_destroy(external_data); - } else { - http_send_reply(h->client, HTTP_UNAUTHORIZED, hh, - octstr_imm("Authentication failed")); - err = octstr_format("MMSBox: SendMMS, Authentication failed, " - "username=%s, password=%s!", - username ? octstr_get_cstr(username) : "(null)", - password ? octstr_get_cstr(password) : "(null)"); - etype = "auth"; - } + http_destroy_headers(rh); + octstr_destroy(ctype); + octstr_destroy(rb); + octstr_destroy(base_url); + octstr_destroy(data_url); + octstr_destroy(external_data); + } else { + http_send_reply(h->client, HTTP_UNAUTHORIZED, hh, + octstr_imm("Authentication failed")); + err = octstr_format("MMSBox: SendMMS, Authentication failed, " + "username=%s, password=%s!", + username ? octstr_get_cstr(username) : "(null)", + password ? octstr_get_cstr(password) : "(null)"); + etype = "auth"; + } - if (err && res != 0) - mms_error_ex(etype, 0, "mmsbox", NULL, "%s", octstr_get_cstr(err)); - octstr_destroy(err); - /* Free the ip and other stuff here. */ + if (err && res != 0) + mms_error_ex(etype, 0, "mmsbox", NULL, "%s", octstr_get_cstr(err)); + octstr_destroy(err); + /* Free the ip and other stuff here. */ - http_destroy_cgiargs(cgivar_ctypes); + http_destroy_cgiargs(cgivar_ctypes); - http_destroy_headers(hh); - free_mmsbox_http_clientInfo(h, 1); - } + http_destroy_headers(hh); + free_mmsbox_http_clientInfo(h, 1); + } + + hmon->unregister_thread(); } static void sendmms_func(void *unused) { - MmsBoxHTTPClientInfo h = {NULL}; - int i; - List *rl = gwlist_create(); + MmsBoxHTTPClientInfo h = {NULL}; + int i; + List *rl = gwlist_create(); - gwlist_add_producer(rl); + hmon->register_thread(); + gwlist_add_producer(rl); - for (i = 0; iua = http_header_value(h.headers, octstr_imm("User-Agent")); + *hx = h; + hx->ua = http_header_value(h.headers, octstr_imm("User-Agent")); - gwlist_produce(rl, hx); - } + gwlist_produce(rl, hx); + } - debug("proxy", 0, "MMSBox: MMS-Send Interface shutting down ... "); - gwlist_remove_producer(rl); - gwthread_join_every((void *)dispatch_sendmms_recv); - gwlist_destroy(rl, NULL); - debug("proxy", 0, "MMSBox: MMS-Send Interface shutdown complete. "); + debug("proxy", 0, "MMSBox: MMS-Send Interface shutting down ... "); + gwlist_remove_producer(rl); + gwthread_join_every((void *)dispatch_sendmms_recv); + gwlist_destroy(rl, NULL); + debug("proxy", 0, "MMSBox: MMS-Send Interface shutdown complete. "); + hmon->unregister_thread(); } diff --git a/mbuni/mmsbox/mmsbox.h b/mbuni/mmsbox/mmsbox.h index 31280f3..8ff9be5 100644 --- a/mbuni/mmsbox/mmsbox.h +++ b/mbuni/mmsbox/mmsbox.h @@ -14,7 +14,6 @@ #define __MMSBOX_INCLUDED__ #include "mmsbox_cfg.h" -extern volatile sig_atomic_t 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); diff --git a/mbuni/mmsbox/mmsbox_cdr.c b/mbuni/mmsbox/mmsbox_cdr.c index ec112d2..844c98c 100644 --- a/mbuni/mmsbox/mmsbox_cdr.c +++ b/mbuni/mmsbox/mmsbox_cdr.c @@ -15,7 +15,7 @@ #include #include "mmsbox_cdr.h" - +#include "mmsbox_cfg.h" static FILE *cdr_file; static List *req_list; @@ -52,7 +52,7 @@ static void cdr_logger_func(void) { MmsBoxCdrStruct *cdr; - + hmon->register_thread(); while ((cdr = gwlist_consume(req_list)) != NULL) { char buf[CBUFSIZE]; struct tm tm; @@ -84,7 +84,7 @@ static void cdr_logger_func(void) gw_free(cdr); } - + hmon->unregister_thread(); } static int cdr_module_init(char *settings) diff --git a/mbuni/mmsbox/mmsbox_cfg.c b/mbuni/mmsbox/mmsbox_cfg.c index c5b7ef4..5ba1691 100644 --- a/mbuni/mmsbox/mmsbox_cfg.c +++ b/mbuni/mmsbox/mmsbox_cfg.c @@ -37,6 +37,8 @@ List *strip_prefixes = NULL; Octstr *sendmail_cmd = NULL; Octstr *myhostname = NULL; +volatile sig_atomic_t rstop = 0; + int mt_multipart = 0; MmsQueueHandlerFuncs *qfs; /* queue functions. */ MmsBoxResolverFuncStruct *rfs; /* resolver functions. */ @@ -56,17 +58,42 @@ static Octstr *admin_pass = NULL; static Octstr *admin_allow_ip = NULL; static Octstr *admin_deny_ip = NULL; -static gwthread_func_t *mmsc_receiver_func; + struct SendMmsPortInfo sendmms_port = {-1}; struct MmsBoxMTfilter *mt_filter = NULL; -static void free_mmsc_struct (MmscGrp *m); +/* do nothing func: Vital it returns 0! */ +static int do_nothing_func (void) {return 0;} +static gwthread_func_t *mmsc_receiver_func = (void *)do_nothing_func; +static struct MmsBoxHealthMonitors _hmon = { + .register_thread = (void*)do_nothing_func, + .unregister_thread = (void*)do_nothing_func, + .register_port = (void*)do_nothing_func, + .unregister_port = (void*)do_nothing_func}; + +struct MmsBoxHealthMonitors *hmon = &_hmon; /* Set to useful defaults */ + +/* Event call back. By default, set to do nothing function */ +void (*mmsbox_event_cb)(Octstr *mmsc, int mm7_pkt_type, + int is_mm4, + Octstr *mm7_ver, int status, + int msg_size, int num_retries, + Octstr *from, Octstr *to, Octstr *message_id, Octstr *transid, + List *hdrs, Octstr *value) = (void *)do_nothing_func; + +void (*mmsbox_alarm_cb)(Octstr*mmsc, enum MmsBoxAlarms alarm, int alarm_state, int lev) = (void *)do_nothing_func; + +static void free_mmsc_struct (MmscGrp *m); static void admin_handler(void *unused); -int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func) +static MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *errors, List *warnings); +int mms_load_mmsbox_settings(struct mCfgImpFuncs *cfg_funcs, Octstr *init, + gwthread_func_t *x_mmsc_handler_func, + MmsQueueHandlerFuncs *_qfs, + MmsEventLoggerFuncs *_ev) { mCfgGrp *grp; mCfgGrp *cgrp; @@ -78,11 +105,17 @@ int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func) void *catchall = NULL, *x; - if ((cfg = mms_cfg_read(fname)) == NULL) { - mms_error(0, "mmsbox", NULL, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname)); + if (cfg_funcs == NULL) + cfg = mms_cfg_read(init); + else + cfg = mms_cfg_read2(cfg_funcs, init); + + if (cfg == NULL) { + mms_error(0, "mmsbox", NULL, "Couldn't read configuration from '%s'.", octstr_get_cstr(init)); return -1; } + grp = mms_cfg_get_single(cfg, octstr_imm("mbuni")); cgrp = mms_cfg_get_single(cfg, octstr_imm("core")); @@ -99,7 +132,9 @@ int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func) mmsc_del_list = gwlist_create(); - if ((x = _mms_load_module(cfg, grp, "event-logger-module", "event_logger", NULL)) != NULL) { + if (_ev != NULL) + mms_event_logger_init(_ev, NULL); + else if ((x = _mms_load_module(cfg, grp, "event-logger-module", "event_logger", NULL)) != NULL) { Octstr *s = mms_cfg_get(cfg, grp, octstr_imm("event-logger-module")); if (mms_event_logger_init(x, s) != 0) @@ -156,7 +191,9 @@ int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func) panic(0, "Failed to create MMSBox storage directory: %s - %s!", octstr_get_cstr(gdir), strerror(errno)); - if ((qfs = _mms_load_module(cfg, grp, "queue-manager-module", "qfuncs", NULL)) == NULL) { + if (_qfs != NULL) + qfs = _qfs; + else if ((qfs = _mms_load_module(cfg, grp, "queue-manager-module", "qfuncs", NULL)) == NULL) { qfs = &default_qfuncs; /* default queue handler. */ qfs->mms_init_queue_module(gdir, octstr_get_cstr(gdir), @@ -221,11 +258,13 @@ int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func) if (sendmms_port.port > 0 && http_open_port(sendmms_port.port, send_port_ssl) < 0) { + MMSC_ISSUE_ALARM(NULL, MMSBOX_ALARM_SOCKET_CONNECT_FAILED, 3); mms_error(0, "mmsbox", NULL, "Failed to start sendmms HTTP server on %ld: %s!", sendmms_port.port, strerror(errno)); sendmms_port.port = -1; - } + } else + hmon->register_port(sendmms_port.port); sendmms_port.allow_ip = mms_cfg_get(cfg, grp, octstr_imm("allow-ip")); sendmms_port.deny_ip = mms_cfg_get(cfg, grp, octstr_imm("deny-ip")); @@ -263,7 +302,7 @@ int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func) } gwlist_destroy(l, NULL); - mmsc_receiver_func = mmsc_handler_func; /* save it. */ + mmsc_receiver_func = x_mmsc_handler_func; /* save it. */ /* Start MMSCs. */ l = mms_cfg_get_multi(cfg, octstr_imm("mmsc")); @@ -273,7 +312,7 @@ int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func) Octstr *x; mCfgGrp *xgrp = gwlist_get(l, i); - start_mmsc_from_conf(cfg, xgrp, mmsc_handler_func, errors, warnings); + start_mmsc_from_conf(cfg, xgrp, errors, warnings); while ((x = gwlist_extract_first(errors)) != NULL) { mms_error(0, "mmsbox", NULL, "%s", octstr_get_cstr(x)); @@ -447,17 +486,21 @@ int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func) admin_deny_ip = mms_cfg_get(cfg, grp, octstr_imm("admin-deny-ip")); if (admin_port > 0 && - http_open_port(admin_port, admin_port_ssl)< 0) + http_open_port(admin_port, admin_port_ssl)< 0) { mms_error(0, "mmsbox", NULL, "Failed to start admin server on port %d: %s", (int)admin_port, strerror(errno)); - else if (admin_port > 0 && + MMSC_ISSUE_ALARM(NULL, MMSBOX_ALARM_HTTP_DOWN, 1); + } else if (admin_port > 0 && (admin_thread = gwthread_create((gwthread_func_t *)admin_handler, NULL)) < 0) { mms_error(0, "mmsbox", NULL, "Failed to start admin server thread: %s", strerror(errno)); http_close_port(admin_port); + admin_port = 0; } else if (admin_pass == NULL) mms_warning(0, "mmsbox", NULL, "Empty or no password supplied for admin port. All requests will be allowed!"); + if (admin_port > 0) + hmon->register_port(admin_port); gwlist_destroy(l, NULL); octstr_destroy(gdir); @@ -466,8 +509,6 @@ int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func) return 0; } -/* do nothing func: Vital it returns 0! */ -static int do_nothing_func (void) {return 0;} static MmsBoxMmscFuncs dummy_mmsc_funcs = { (void *)do_nothing_func, @@ -488,7 +529,9 @@ static void mmsbox_stop_mmsc_conn_real(MmscGrp *mmc) mmc->fns->stop_conn(mmc->data); mmc->custom_started = 0; } else if (mmc->incoming.port > 0) { - http_close_port(mmc->incoming.port); + http_close_port(mmc->incoming.port); + hmon->unregister_port(mmc->incoming.port); + MMSC_ISSUE_ALARM(mmc, MMSBOX_ALARM_HTTP_DOWN, 1); if (mmc->threadid >= 0) gwthread_join(mmc->threadid); mmc->threadid = -1; @@ -497,8 +540,7 @@ static void mmsbox_stop_mmsc_conn_real(MmscGrp *mmc) } -static void mmsbox_start_mmsc_conn(MmscGrp *m, gwthread_func_t *mmsc_handler_func, - List *errors, List *warnings) +static void mmsbox_start_mmsc_conn(MmscGrp *m, List *errors, List *warnings) { if (m->type == CUSTOM_MMSC) { if (m->fns == NULL || @@ -506,20 +548,24 @@ static void mmsbox_start_mmsc_conn(MmscGrp *m, gwthread_func_t *mmsc_handler_fun WARNING("MMSBox: Failed to start custom MMSC [%s]", octstr_get_cstr(m->id)); m->custom_started = 0; } else - m->custom_started = 1; + m->custom_started = 1; } else { if (m->incoming.port > 0 && http_open_port(m->incoming.port, m->incoming.ssl) < 0) { WARNING("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)); + strerror(errno)); + MMSC_ISSUE_ALARM(m, MMSBOX_ALARM_SOCKET_CONNECT_FAILED, 3); m->incoming.port = 0; /* so we don't listen on it. */ + } else { + hmon->register_port(m->incoming.port); + MMSC_CLEAR_ALARM(m, MMSBOX_ALARM_HTTP_DOWN); + MMSC_CLEAR_ALARM(m, MMSBOX_ALARM_SOCKET_CONNECT_FAILED); } - - if (mmsc_handler_func && + if (mmsc_receiver_func && m->incoming.port > 0) { /* Only start threads if func passed and ... */ - if ((m->threadid = gwthread_create(mmsc_handler_func, m)) < 0) + if ((m->threadid = gwthread_create(mmsc_receiver_func, m)) < 0) ERROR("MMSBox: Failed to start MMSC handler thread for MMSC[%s]: %s!", octstr_get_cstr(m->id), strerror(errno)); } else @@ -531,8 +577,7 @@ static void mmsbox_start_mmsc_conn(MmscGrp *m, gwthread_func_t *mmsc_handler_fun -MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, gwthread_func_t *mmsc_handler_func, - List *warnings, List *errors) +static MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *warnings, List *errors) { MmscGrp *m = gw_malloc(sizeof *m); @@ -667,7 +712,7 @@ MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, gwthread_func_t *mmsc_handl m->start_time = time(NULL); /* finally start the thingie. */ - mmsbox_start_mmsc_conn(m, mmsc_handler_func, errors, warnings); + mmsbox_start_mmsc_conn(m, errors, warnings); if (dict_put_once(mmscs, m->id, m) == 0) { WARNING("Failed to load mmsc [%s]. ID is not unique!", octstr_get_cstr(m->id)); mmsbox_stop_mmsc_conn_real(m); @@ -698,7 +743,7 @@ static void delete_stale_mmsc(int delete_all) } } -int mmsbox_stop_mmsc_conn(Octstr *mmc_id) +int mmsbox_stop_mmsc(Octstr *mmc_id) { MmscGrp *mmc = dict_remove(mmscs, mmc_id); /* remove it so no one else can get it. */ @@ -714,6 +759,23 @@ int mmsbox_stop_mmsc_conn(Octstr *mmc_id) return 0; } +int mmsbox_start_mmsc(Octstr *mmc_id) +{ + int ret; + MmscGrp *mmc = dict_get(mmscs, mmc_id); /* remove it so no one else can get it. */ + List *l = gwlist_create(), *r = gwlist_create(); + if (mmc == NULL) + return -1; + mmsbox_start_mmsc_conn(mmc, l, r); + + ret = gwlist_len(l) > 0 ? -1 : 0; + + gwlist_destroy(l, (void *)octstr_destroy); + gwlist_destroy(r, (void *)octstr_destroy); + + return ret; +} + void mmsbox_stop_all_mmsc_conn(void) { Octstr *mmc; @@ -722,7 +784,7 @@ void mmsbox_stop_all_mmsc_conn(void) if (l) { while ((mmc = gwlist_extract_first(l)) != NULL) { mms_info(0, "mmsbox", NULL,"Stopping MMSC [%s]", octstr_get_cstr(mmc)); - mmsbox_stop_mmsc_conn(mmc); + mmsbox_stop_mmsc(mmc); octstr_destroy(mmc); } gwlist_destroy(l, NULL); @@ -810,6 +872,8 @@ void mmsbox_settings_cleanup(void) if (admin_port > 0) { http_close_port(admin_port); + hmon->unregister_port(admin_port); + MMSC_ISSUE_ALARM(NULL, MMSBOX_ALARM_HTTP_DOWN,1); if (admin_thread >= 0) gwthread_join(admin_thread); mms_info(0, "mmsbox", NULL,"Admin port on %d, shutdown", (int)admin_port); @@ -987,7 +1051,7 @@ static void admin_handler(void *unused) List *cgivars; Octstr *pass; - + hmon->register_thread(); mms_info(0, "mmsbox", NULL,"Admin Interface -- startup on port %d", (int)admin_port); while((client = http_accept_request(admin_port, @@ -1033,7 +1097,7 @@ static void admin_handler(void *unused) List *e = gwlist_create(); List *w = gwlist_create(); Octstr *x; - MmscGrp *mc = start_mmsc_from_conf(cfg, m, mmsc_receiver_func, e, w); + MmscGrp *mc = start_mmsc_from_conf(cfg, m, e, w); if (mc != NULL) append_mmsc_status(rbody, mc, w); @@ -1060,7 +1124,7 @@ static void admin_handler(void *unused) if (l) while ((x = gwlist_extract_first(l)) != NULL) { - int ret = mmsbox_stop_mmsc_conn(x); + int ret = mmsbox_stop_mmsc(x); octstr_format_append(rbody, "<%s/>\n", ret == 0 ? "Success" : "Failed"); @@ -1107,7 +1171,7 @@ static void admin_handler(void *unused) http_destroy_cgiargs(cgivars); http_destroy_headers(headers); } - + hmon->unregister_thread(); mms_info(0, "mmsbox", NULL,"Admin Interface -- shuttind down on port %d", (int)admin_port); } diff --git a/mbuni/mmsbox/mmsbox_cfg.h b/mbuni/mmsbox/mmsbox_cfg.h index 77c1300..22b0de6 100644 --- a/mbuni/mmsbox/mmsbox_cfg.h +++ b/mbuni/mmsbox/mmsbox_cfg.h @@ -19,6 +19,20 @@ #include "mmsbox_mmsc.h" #include "mmsbox_cdr.h" +#include "mms_cfg.h" + +/* Alarm callback mechanism */ +enum MmsBoxAlarms { + MMSBOX_ALARM_HTTP_DOWN = 0, + MMSBOX_ALARM_FILE_WRITE_ERROR, + MMSBOX_ALARM_SOCKET_CONNECT_FAILED, + MMSBOX_ALARM_QUEUE_WRITE_ERROR, + MMSBOX_ALARM_STORAGE_API_ERROR, + MMSBOX_ALARM_MM7_PARSING_FAILURE, + MMSBOX_ALARM_MM7_NON_200_RESULT, + MMSBOX_ALARM_RETRIEVE_MMS_ERROR, + MMSBOX_ALARM_MAX_ALARM /* Must be last one */ +}; typedef struct MmscGrp { Octstr *id; /* MMSC id (for logging). */ @@ -61,10 +75,12 @@ typedef struct MmscGrp { time_t last_pdu; /* time of last PDU */ time_t start_time; /* when was this connection started */ + time_t last_alarm[MMSBOX_ALARM_MAX_ALARM]; int use_count; /* use counter. */ time_t delete_after; /* used to control deletion of object -- not ver clean, but... */ } MmscGrp; + #define MMSBOX_MMSC_MARK_INUSE(mmc) do {\ mutex_lock((mmc)->mutex); \ (mmc)->use_count++; \ @@ -145,16 +161,75 @@ extern Octstr *rfs_settings; extern MmsBoxCdrFuncStruct *cdrfs; -extern int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func); + + +extern struct MmsBoxHealthMonitors { + void (*register_thread)(void); /* Called by each thread to register itself with the health monitor */ + void (*unregister_thread)(void); /* Called by each thread to unregister itself with the health monitor */ + void (*register_port)(short port); /* Called to register each port on which we listen */ + void (*unregister_port)(short port); /* Called to unregister each port on which we listen */ +} *hmon; /* This should be set if you want to do any thread and port monitoring */ + +/* mmsbox_event_cb: Called with each mmsc event. + * mmsc - mmsc ID + * mm7_pkt_type - MM7 packet type (using MM7/SOAP codes) + * mm7_ver - value for SOAP or EAIF only + * status - 0 for Ok, -1 if failed (e.g. for submitack + * msg_size - size of mms + * num_retries - number of retries so far + * from - sender (can be NULL) + * to - recipient (can be NULL) + * transid - transaction ID + * message_id - Message ID (for submitack, deliverreq, deliveryreport or readreport) + * hdrs - List of envelope headers + * value - value associated with pkt type: e.g. for deliveryreport, report type + */ +extern void (*mmsbox_event_cb)(Octstr *mmsc, int mm7_pkt_type, + int is_mm4, + Octstr *mm7_ver, int status, + int msg_size, int num_retries, + Octstr *from, Octstr *to, Octstr *message_id, Octstr *transid, + List *hdrs, Octstr *value); + +/* mmsbox_alarm_cb: Called when an alarm is raised or cleared + * mmsc - MMSC ID + * alarm - alarm type + * alarm_state - 0 = alarm cleared, 1 = alarm raised + * lev = severity level, 1 = warning, 2 = minor, 3 = major, 4+ = critical + */ +extern void (*mmsbox_alarm_cb)(Octstr*mmsc, enum MmsBoxAlarms alarm, int alarm_state, int lev); + +#define MMSC_ISSUE_ALARM(mmc,alarm,lev) do { \ + MmscGrp *_mmc = (mmc); \ + if (_mmc) \ + _mmc->last_alarm[(alarm)] = time(NULL); \ + mmsbox_alarm_cb(_mmc ? _mmc->id : NULL, (alarm), 1, (lev)); \ + } while (0) +#define MMSC_CLEAR_ALARM(mmc,alarm) do { \ + MmscGrp *_mmc = (mmc); \ + if (_mmc && _mmc->last_alarm[(alarm)] > 0 ) { \ + mmsbox_alarm_cb(_mmc->id, (alarm), 0, 0); \ + _mmc->last_alarm[(alarm)] = 0; \ + } \ + } while (0) + +extern int mms_load_mmsbox_settings(struct mCfgImpFuncs *cfg_funcs, Octstr *init, + gwthread_func_t *mmsc_handler_func, + MmsQueueHandlerFuncs *, + MmsEventLoggerFuncs *); extern void mmsbox_settings_cleanup(void); extern MmscGrp *get_handler_mmc(Octstr *id, Octstr *to, Octstr *from); extern void return_mmsc_conn(MmscGrp *m); -extern Octstr *get_mmsbox_queue_dir(Octstr *from, List *to, MmscGrp *m, - Octstr **mmc_id); -MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, gwthread_func_t *mmsc_handler_func, - List *errors, List *warnings); -int mmsbox_stop_mmsc_conn(Octstr *mmc); +extern Octstr *get_mmsbox_queue_dir(Octstr *from, List *to, MmscGrp *m, Octstr **mmc_id); +#if 0 +MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *errors, List *warnings); +#endif +int mmsbox_stop_mmsc(Octstr *mmc); + +int mmsbox_start_mmsc(Octstr *mmc_id); + + void mmsbox_stop_all_mmsc_conn(void); typedef struct MmsBoxHTTPClientInfo { HTTPClient *client; @@ -167,4 +242,6 @@ typedef struct MmsBoxHTTPClientInfo { MmscGrp *m; } MmsBoxHTTPClientInfo; void free_mmsbox_http_clientInfo(MmsBoxHTTPClientInfo *h, int freeh); + +extern volatile sig_atomic_t rstop; #endif diff --git a/mbuni/mmsc/mmsrelay.c b/mbuni/mmsc/mmsrelay.c index 8a1e069..e960620 100644 --- a/mbuni/mmsc/mmsrelay.c +++ b/mbuni/mmsc/mmsrelay.c @@ -29,7 +29,7 @@ int mmsrelay() /* Start global queue runner. */ if (settings->svc_list & SvcRelay) { mms_info(0, "mmsrelay", NULL, "Starting Global Queue Runner..."); - qthread = gwthread_create((gwthread_func_t *)mbuni_global_queue_runner, &rstop); + qthread = gwthread_create((gwthread_func_t *)mbuni_global_queue_runner, (void *)&rstop); } if (settings->svc_list & SvcMM1) {