1
0
Fork 0

mmsbox now sends multiple recipients per transaction

master
bagyenda 12 years ago
parent 18dd46568f
commit cdabed7443

@ -1,3 +1,5 @@
2010-12-09 P. A. Bagyenda <bagyenda@dsmagic.com>
* Changes to mmsbox to allow it send multiple recipients per MM7 transaction
2010-11-30 P. A. Bagyenda <bagyenda@dsmagic.com>
* Minor fix in RFC 2047 text handling
2010-11-29 P. A. Bagyenda <bagyenda@dsmagic.com>

@ -2755,6 +2755,22 @@ string
</td>
</tr>
<tr>
<td valign=top >
<tt>max-recipients</tt>
</td>
<td valign=top >
Number
</td>
<td valign=top >
Maximum number of recipients per transaction for this MMSC
(ignored for custom MMSC type). This controls how many <tt>To</tt>
addresses are included in each send transaction. Default is
1. Note that failure of of the MMSC to accept any of the
recipients can result in the entire send request being retried.
</td>
</tr>
<tr>
<td valign=top >
<tt>reroute</tt>

@ -194,6 +194,8 @@ MULTI_GROUP(mmsc,
OCTSTR(default-vasid)
OCTSTR(maximum-request-size)
OCTSTR(strip-domain)
OCTSTR(max-recipients)
)
MULTI_GROUP(mms-service,

@ -529,7 +529,7 @@ static void addmmscname(Octstr *s, Octstr *myhostname)
}
static int send2email(Octstr *to, Octstr *from, Octstr *subject,
static int send2email(List *xto, Octstr *from, Octstr *subject,
Octstr *msgid,
MIMEEntity *m, int append_hostname, Octstr **error,
char *sendmail_cmd, Octstr *myhostname,
@ -543,9 +543,10 @@ static int send2email(Octstr *to, Octstr *from, Octstr *subject,
Octstr *cmd = octstr_create("");
List *headers = mime_entity_headers(m); /* we don't want the mime version header removed. */
Octstr *to = NULL;
fname[0] = 0;
/* Make to address */
if (append_hostname) { /* Add our hostname to all phone numbers. */
List *l = http_create_empty_headers();
Octstr *xfrom = http_header_value(headers, octstr_imm("From"));
@ -607,11 +608,7 @@ static int send2email(Octstr *to, Octstr *from, Octstr *subject,
s = mime_entity_to_octstr(m);
if (relay_host && relay_port > 0) {
List *lto = gwlist_create();
gwlist_append(lto, octstr_duplicate(to));
ret = smtp_send(octstr_get_cstr(relay_host), relay_port, from, lto, s);
gwlist_destroy(lto, (void *)octstr_destroy);
ret = smtp_send(octstr_get_cstr(relay_host), relay_port, from, xto, s);
goto done;
}
/*
@ -621,7 +618,8 @@ static int send2email(Octstr *to, Octstr *from, Octstr *subject,
* s - subject
* m - message id
*/
LINEARISE_STR_LIST(to,xto," ");
i = 0;
for (;;) {
Octstr *tmp;
@ -678,7 +676,8 @@ static int send2email(Octstr *to, Octstr *from, Octstr *subject,
}
i += 2;
}
if ((fd = mkstemp(fname)) < 0) {
*error = octstr_format("mkstemp: Failed to create temporary file: %s",
strerror(errno));
@ -721,6 +720,7 @@ done:
http_destroy_headers(headers);
octstr_destroy(cmd);
octstr_destroy(s);
octstr_destroy(to);
return ret;
}
@ -804,11 +804,14 @@ int mm_send_to_email(Octstr *to, Octstr *from, Octstr *subject,
char *sendmail_cmd, Octstr *myhostname,
Octstr *relay_host, int relay_port)
{
return send2email(to,from,subject,msgid,m,append_hostname,error,sendmail_cmd,myhostname, relay_host, relay_port);
List *lto = gwlist_create_ex(to);
int ret = send2email(lto,from,subject,msgid,m,append_hostname,error,sendmail_cmd,myhostname, relay_host, relay_port);
gwlist_destroy(lto, NULL);
return ret;
}
/* Send this message to email recipient. */
int mms_sendtoemail(Octstr *from, Octstr *to,
int mms_sendtoemail(Octstr *from, List *lto,
Octstr *subject, Octstr *msgid,
MmsMsg *msg, int dlr,
Octstr **error, char *sendmail_cmd,
@ -823,14 +826,19 @@ int mms_sendtoemail(Octstr *from, Octstr *to,
MIMEEntity *m = NULL;
List *headers = NULL;
List *newhdrs = http_create_empty_headers();
int ret = 0, mtype;
int ret = 0, mtype;
Octstr *to;
gw_assert(msg);
mtype = mms_messagetype(msg);
/* Make 'to' header field in case we need it. */
LINEARISE_STR_LIST(to, lto, ", ");
if (!to ||
octstr_search_char(to, '@', 0) < 0) {
*error = octstr_format("Invalid email address %S!", to);
octstr_destroy(to);
return MMS_SEND_ERROR_FATAL;
}
@ -840,6 +848,7 @@ int mms_sendtoemail(Octstr *from, Octstr *to,
m == NULL) {
mms_warning(0, "send2email", NULL, "Failed to format message (msg=%s,ret=%d)",
m ? "OK" : "Not transformed",ret);
octstr_destroy(to);
return -ret;
}
@ -855,8 +864,10 @@ int mms_sendtoemail(Octstr *from, Octstr *to,
http_header_add(newhdrs, "Subject", subject ? octstr_get_cstr(subject) : "MMS Message");
http_header_remove_all(headers, "From");
http_header_add(newhdrs, "From", octstr_get_cstr(from));
#if 0 /* Should we reveal recipients ?? */
http_header_remove_all(headers, "To");
http_header_add(newhdrs, "To", octstr_get_cstr(to));
#endif
http_header_add(newhdrs, "Message-ID", msgid ? octstr_get_cstr(msgid) : "");
http_header_add(newhdrs, "MIME-Version", "1.0");
} else {
@ -947,9 +958,9 @@ int mms_sendtoemail(Octstr *from, Octstr *to,
done:
http_destroy_headers(headers);
http_destroy_headers(newhdrs);
octstr_destroy(to);
if (ret == 0)
ret = send2email(to,
ret = send2email(lto,
from, subject, msgid, m, mm4 == 0, error, sendmail_cmd, myhostname, relay_host, relay_port);
mime_entity_destroy(m);
@ -2535,3 +2546,16 @@ Octstr *pack_rfc2047_text(Octstr *in, int charset_mib_enum)
octstr_append_cstr(xs, "?=");
return xs;
}
List *gwlist_create_ex_real(const char *file, const char *func, int line,...)
{
va_list ap;
List *l = gwlist_create();
void *v;
va_start(ap, line);
while ((v = va_arg(ap, void *)) != NULL)
gwlist_append(l, v);
return l;
}

@ -108,7 +108,7 @@ void base64_mimeparts(MIMEEntity *m, int all);
/* Send this message to email recipient: Returns 0 on success 1 or 2 on profile error
* (negate to get right one), -ve on some other error
*/
int mms_sendtoemail(Octstr *from, Octstr *to,
int mms_sendtoemail(Octstr *from, List *lto,
Octstr *subject, Octstr *msgid,
MmsMsg *msg, int dlr, Octstr **error,
char *sendmail_cmd, Octstr *myhostname,
@ -266,8 +266,24 @@ Octstr *parse_rfc2047_text(Octstr *in, int *mibenum);
#define QUEUERUN_INTERVAL 1*60 /* 1 minutes. */
#define DEFAULT_EXPIRE 3600*24*7 /* One week */
#define DEFAULT_SIMUL_RCPTS 10
#define HTTP_REPLACE_HEADER(hdr, hname, value) do { \
http_header_remove_all((hdr), (hname)); \
http_header_add((hdr), (hname), (value)); \
} while (0)
List *gwlist_create_ex_real(const char *file, const char *func, int line,...);
#define gwlist_create_ex(...) gwlist_create_ex_real(__FILE__,__FUNCTION__,__LINE__, __VA_ARGS__, NULL)
#define LINEARISE_STR_LIST(res,lst,sep) do { \
Octstr *__res; \
int __i; \
for (__res = octstr_create(""), __i = 0; __i < gwlist_len(lst); __i++) \
octstr_format_append(__res, "%s%S", \
octstr_len(__res) == 0 ? "" : (sep), gwlist_get((lst), __i)); \
(res) = __res; \
} while (0)
#endif

@ -555,8 +555,7 @@ static int mm7eaif_receive(MmsBoxHTTPClientInfo *h)
strip_prefixes);
if ((hto = http_header_find_all(h->headers, "X-NOKIA-MMSC-To")) != NULL &&
gwlist_len(hto) > 0) { /* To address is in headers. */
if ((hto = http_header_find_all(h->headers, "X-NOKIA-MMSC-To")) != NULL && gwlist_len(hto) > 0) { /* To address is in headers. */
int i, n;
gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy);
@ -1137,7 +1136,7 @@ void mmsc_receive_func(MmscGrp *m)
* are observed!
* Don't remove from queue on fail, just leave it to expire.
*/
static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to,
static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, List *lto,
Octstr *transid,
Octstr *linkedid,
char *vasid,
@ -1149,14 +1148,16 @@ static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to,
{
List *hdrs = e ? e->hdrs : NULL;
Octstr *ret = NULL;
int mtype = mms_messagetype(m);
int mtype = mms_messagetype(m);
int hstatus = HTTP_OK, tstatus = -1;
List *xto = gwlist_create();
MSoapMsg_t *mreq = NULL, *mresp = NULL;
List *rh = NULL, *ph = NULL;
Octstr *body = NULL, *rbody = NULL, *url = NULL;
Octstr *s, *r, *status_details = NULL;
char *xvasid = vasid ? vasid : (mmc->default_vasid ? octstr_get_cstr(mmc->default_vasid) : NULL);
Octstr *to;
LINEARISE_STR_LIST(to,lto,", ");
if (e == NULL || mmc == NULL)
goto done1;
@ -1165,10 +1166,9 @@ static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to,
mms_message_type_to_cstr(mtype),
octstr_get_cstr(from), octstr_get_cstr(to));
gwlist_append(xto, to);
if ((mreq = mm7_mmsmsg_to_soap(m, (mmc == NULL || mmc->no_senderaddress == 0) ? from : NULL,
xto, transid,
lto, transid,
service_code,
linkedid,
1, octstr_get_cstr(mmc->vasp_id), xvasid, NULL, 0,/* UA N/A on this side. */
@ -1291,13 +1291,13 @@ done1:
http_destroy_headers(ph);
octstr_destroy(rbody);
octstr_destroy(url);
gwlist_destroy(xto, NULL);
octstr_destroy(to);
octstr_destroy(status_details);
return ret;
}
static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to,
static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, List *lto,
Octstr *transid,
char *vasid,
MmsEnvelope *e,
@ -1312,8 +1312,10 @@ static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to,
Octstr *body = NULL, *rbody = NULL, *xver = NULL;
char *msgtype;
MmsMsg *mresp = NULL;
int mresp_type = -1;
int mresp_type = -1, i;
Octstr *to;
LINEARISE_STR_LIST(to,lto,", ");
if (e == NULL || mmc == NULL)
goto done;
@ -1323,7 +1325,10 @@ static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to,
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));
for (i = 0; i < gwlist_len(lto); i++) {
Octstr *to = gwlist_get(lto, i);
http_header_add(rh, "X-NOKIA-MMSC-To", octstr_get_cstr(to));
}
http_header_add(rh, "X-NOKIA-MMSC-From", octstr_get_cstr(from));
xver = octstr_format(EAIF_VERSION, mmc->ver.major, mmc->ver.minor1);
@ -1347,7 +1352,9 @@ static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to,
/* Patch the message FROM and TO fields. */
mms_replace_header_value(m, "From", octstr_get_cstr(from));
#if 0
mms_replace_header_value(m, "To", octstr_get_cstr(to));
#endif
mms_replace_header_value(m,"X-Mms-Transaction-ID",
transid ? octstr_get_cstr(transid) : "000");
body = mms_tobinary(m);
@ -1411,7 +1418,7 @@ done:
octstr_destroy(body);
http_destroy_headers(ph);
octstr_destroy(rbody);
octstr_destroy(to);
octstr_destroy(resp);
octstr_destroy(xver);
return ret;
@ -1420,7 +1427,7 @@ done:
static Octstr *mm7http_send(MmscGrp *mmc,
MmsEnvelope *e,
Octstr *from, Octstr *to,
Octstr *from, List *lto,
MmsMsg *m, Octstr **error,
int *retry)
{
@ -1434,6 +1441,9 @@ static Octstr *mm7http_send(MmscGrp *mmc,
MIMEEntity *form_data = make_multipart_formdata();
Octstr *transid = e ? octstr_create(e->xqfname) : NULL;
int mm7type = mm7_msgtype_to_soaptype(mtype,1);
Octstr *to;
LINEARISE_STR_LIST(to,lto," ");
if (e == NULL || mmc == NULL)
goto done;
@ -1448,7 +1458,6 @@ static Octstr *mm7http_send(MmscGrp *mmc,
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);
@ -1490,14 +1499,15 @@ done:
octstr_destroy(mms);
mime_entity_destroy(form_data);
octstr_destroy(transid);
octstr_destroy(to);
return ret;
}
static int mms_sendtommsc(MmscGrp *mmc, MmsEnvelope *e, Octstr *to,
static int mms_sendtommsc(MmscGrp *mmc, MmsEnvelope *e,
List *lto, /* Of Octstr * */
Octstr *orig_transid,
MmsMsg *m,
Octstr **new_msgid,
List **errhdrs)
@ -1517,15 +1527,17 @@ 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, e, m, &err, errhdrs, &retry);
id = mm7soap_send(mmc, from, lto, transid, linkedid, vasid, service_code, e, m, &err, errhdrs, &retry);
else if (mmc->type == EAIF_MMSC)
id = mm7eaif_send(mmc, from, to, transid, vasid, e, m, &err, &retry);
id = mm7eaif_send(mmc, from, lto, transid, vasid, e, m, &err, &retry);
else if (mmc->type == HTTP_MMSC)
id = mm7http_send(mmc,e, from, to, m, &err, &retry);
else if (mmc->type == CUSTOM_MMSC && mmc->started)
id = mm7http_send(mmc,e, from, lto, m, &err, &retry);
else if (mmc->type == CUSTOM_MMSC && mmc->started) {
Octstr *to = gwlist_get(lto, 0); /* XXX Send one at a time*/
id = mmc->fns->send_msg(mmc->data,
from, to, transid, linkedid, vasid,
service_code, m, hdrs, &err, &retry);
}
#if 0
else if (mmc->type == MM4_MMSC && mmc->started)
(void )0; /* Already sent above */
@ -1562,208 +1574,314 @@ static int mms_sendtommsc(MmscGrp *mmc, MmsEnvelope *e, Octstr *to,
return ret;
}
typedef struct MRcpt_t {
int smtp_flag;
MmscGrp *mmc;
List *rto; /* List of envelope */
} MRcpt_t;
static int cmp_mrcpt(struct MRcpt_t *m, MmscGrp *mmc)
{
if (mmc == NULL && m->smtp_flag)
return 1;
else
return (mmc && mmc->id && m->mmc && m->mmc->id) && (octstr_case_compare(m->mmc->id, mmc->id) == 0);
}
static void process_send_res(MmsEnvelope *e, MmsMsg *msg,
MmsEnvelopeTo *to, MmscGrp *mmc,
int res, Octstr *err, List *errl, Octstr *new_msgid,
int first_one)
{
time_t tnow = time(NULL);
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED) {
to->process = 0;
if (e->msgtype == MMS_MSGTYPE_SEND_REQ ||
e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF) /* queue dlr as needed. */
queue_dlr(mmc, e->from, to->rcpt, new_msgid, octstr_imm("Forwarded"), "MM7-Out", errl);
} else if (res == MMS_SEND_ERROR_FATAL && mmc) {
if (e->msgtype == MMS_MSGTYPE_SEND_REQ ||
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"),
"MM7-Out", errl);
}
if (mmc) {
if (first_one) {
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED)
mmc->mt_pdus++;
else
mmc->mt_errors++;
}
mmc->last_pdu = time(NULL);
return_mmsc_conn(mmc); /* important. */
}
if (res == MMS_SEND_ERROR_FATAL)
to->process = 0; /* No more attempts. */
/* handle CDR */
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED || res == MMS_SEND_ERROR_FATAL) {
Octstr *mclass = mms_get_header_value(msg, octstr_imm("X-Mms-Message-Class"));
Octstr *prio = mms_get_header_value(msg, octstr_imm("X-Mms-Priority"));
Octstr *mstatus = mms_get_header_value(msg, octstr_imm("X-Mms-Status"));
/* Do CDR */
cdrfs->logcdr(e->created,
octstr_get_cstr(e->from),
octstr_get_cstr(to->rcpt),
octstr_get_cstr(e->msgId),
mmc ? octstr_get_cstr(mmc->id) : NULL, /* Should we touch mmc here? XXX */
e->src_interface,
"MM7",
e->msize,
(char *)mms_message_type_to_cstr(e->msgtype),
prio ? octstr_get_cstr(prio) : NULL,
mclass ? octstr_get_cstr(mclass) : NULL,
res == MMS_SEND_ERROR_FATAL ? "dropped" : (mstatus ? octstr_get_cstr(mstatus) : "sent"),
e->dlr,
0);
octstr_destroy(mclass);
octstr_destroy(prio);
octstr_destroy(mstatus);
}
if (err == NULL)
mms_info(0, "MM7", NULL, "%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: msgid=[%s]",
SEND_ERROR_STR(res),
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
new_msgid ? octstr_get_cstr(new_msgid) : "N/A");
else
mms_error_ex("MT", 0,
"MM7", NULL,
"%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: %s",
SEND_ERROR_STR(res),
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize, octstr_get_cstr(err));
}
/* Make a list of recpients up to max_rcpt */
static inline List *make_srcpt_list(List *rto, int max_rcpt)
{
List *l = gwlist_create();
MmsEnvelopeTo *xto;
while ((max_rcpt > 0) && (xto = gwlist_extract_first(rto)) != NULL) {
gwlist_append(l, xto);
max_rcpt--;
}
if (gwlist_len(l) == 0) {
gwlist_destroy(l, NULL);
l = NULL;
}
return l;
}
static int sendMsg(MmsEnvelope *e)
{
MmsMsg *msg = NULL;
int i, n;
Octstr *otransid = e->hdrs ? http_header_value(e->hdrs, octstr_imm("X-Mbuni-TransactionID")) : NULL;
MmscGrp _mmc_smtp = {.max_recipients = DEFAULT_SIMUL_RCPTS, .mutex = mutex_create()};
MRcpt_t smtp_h = {.mmc = &_mmc_smtp, .smtp_flag = 1, .rto = gwlist_create()}; /* Signals that recipient is on other end of smtp pipe */
List *mlist = NULL; /* List of MMScs */
MmsEnvelopeTo *to;
time_t tnow = time(NULL);
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); i<n; i++) {
int res = MMS_SEND_OK;
MmsEnvelopeTo *to = gwlist_get(e->to, i);
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;
if (e->expiryt != 0 && /* Handle message expiry. */
e->expiryt < tnow) {
err = octstr_format("MMSC error: Message expired while sending to %S!", to->rcpt);
res = MMS_SEND_ERROR_FATAL;
goto done;
} else if (e->attempts >= maxsendattempts) {
err = octstr_format("MMSBox error: Failed to deliver to "
"%S after %ld attempts. (max attempts allowed is %ld)!",
to->rcpt, e->attempts,
maxsendattempts);
res = MMS_SEND_ERROR_FATAL;
goto done;
}
is_email = (octstr_search_char(to->rcpt, '@', 0) > 0);
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);
res = MMS_SEND_ERROR_TRANSIENT;
goto done;
}
if (is_email || (mmc->type == MM4_MMSC && mmc->started)) { /* Handle MM4 recipient here as well */
int j = octstr_case_search(e->from, octstr_imm("/TYPE=PLMN"), 0);
int k = octstr_case_search(e->from, octstr_imm("/TYPE=IPv"), 0);
int len = octstr_len(e->from);
Octstr *pfrom, *xto;
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
pfrom = octstr_copy(e->from, 0, j);
else if (k > 0 && k + sizeof "/TYPE=IPv" == len)
pfrom = octstr_copy(e->from, 0, k);
else
pfrom = octstr_duplicate(e->from);
if (!is_email)
xto = octstr_format("%S@%S", to->rcpt,
mmc && octstr_str_compare(mmc->mmsc_url, "*") != 0 ? mmc->mmsc_url :
octstr_imm("unknown"));
else
xto = octstr_duplicate(to->rcpt);
if (octstr_search_char(e->from, '@', 0) < 0)
octstr_format_append(pfrom,"@%S", myhostname);
mlist = gwlist_create_ex(&smtp_h);
/* First split by mmc */
for (i = 0, n = gwlist_len(e->to); i<n; i++)
if ((to = gwlist_get(e->to, i)) != NULL && to->process && to->rcpt) {
Octstr *x, *err = NULL;
int is_email = (octstr_search_char(to->rcpt, '@', 0) > 0);
Octstr *requested_mmsc = NULL;
MmscGrp *mmc = NULL;
int res = MMS_SEND_OK;
MRcpt_t *m;
res = mms_sendtoemail(pfrom, xto,
e->subject ? e->subject : octstr_imm(""),
e->msgId, msg, 0, &err, octstr_get_cstr(sendmail_cmd),
myhostname, 0, 0,
"",
"", 0,
e->xqfname,
e->hdrs, smtp_relay.host, smtp_relay.port);
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED) {
new_msgid = e->msgId ? octstr_duplicate(e->msgId) : octstr_create("00001"); /* Fake it */
mmsbox_event_cb(NULL, MM7_TAG_SubmitReq, 1, octstr_imm("1.0"), 200,
mms_msgsize(msg), e->attempts, pfrom,
to->rcpt,NULL, NULL, e->hdrs, NULL);
}
octstr_destroy(pfrom);
octstr_destroy(xto);
} else {
res = mms_sendtommsc(mmc, e,
to->rcpt,
otransid,
msg,
&new_msgid,
&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));
if (e->expiryt != 0 && /* Handle message expiry. */
e->expiryt < tnow) {
err = octstr_format("MMSC error: Message expired while sending to %S!", to->rcpt);
res = MMS_SEND_ERROR_FATAL;
octstr_destroy(x);
goto done_route;
} else if (e->attempts >= maxsendattempts) {
err = octstr_format("MMSBox error: Failed to deliver to "
"%S after %ld attempts. (max attempts allowed is %ld)!",
to->rcpt, e->attempts,
maxsendattempts);
res = MMS_SEND_ERROR_FATAL;
goto done_route;
}
}
done:
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED) {
to->process = 0;
if (e->msgtype == MMS_MSGTYPE_SEND_REQ ||
e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF) /* queue dlr as needed. */
queue_dlr(mmc, e->from, to->rcpt, new_msgid, octstr_imm("Forwarded"), "MM7-Out", errl);
} else if (res == MMS_SEND_ERROR_FATAL && mmc) {
if (e->msgtype == MMS_MSGTYPE_SEND_REQ ||
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"),
"MM7-Out", errl);
}
x = octstr_format("X-Mbuni-Via-%d", i);
requested_mmsc = e->hdrs ? http_header_value(e->hdrs, x) : NULL;
octstr_destroy(x);
if (mmc) {
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED)
mmc->mt_pdus++;
else
mmc->mt_errors++;
mmc->last_pdu = time(NULL);
return_mmsc_conn(mmc); /* important. */
}
if (res == MMS_SEND_ERROR_FATAL)
to->process = 0; /* No more attempts. */
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);
res = MMS_SEND_ERROR_TRANSIENT;
goto done_route;
}
/* We know how to route: If mmc is null at this point, means mm4 recipient. */
if ((m = gwlist_search(mlist, mmc, (void *)cmp_mrcpt)) == NULL) { /* A new route, add recipient zone */
m = gw_malloc(sizeof *m);
m->smtp_flag = 0;
m->mmc = mmc;
m->rto = gwlist_create();
/* handle CDR */
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED || res == MMS_SEND_ERROR_FATAL) {
Octstr *mclass = mms_get_header_value(msg, octstr_imm("X-Mms-Message-Class"));
Octstr *prio = mms_get_header_value(msg, octstr_imm("X-Mms-Priority"));
Octstr *mstatus = mms_get_header_value(msg, octstr_imm("X-Mms-Status"));
gwlist_append(mlist, m);
}
/* Do CDR */
cdrfs->logcdr(e->created,
octstr_get_cstr(e->from),
octstr_get_cstr(to->rcpt),
octstr_get_cstr(e->msgId),
mmc ? octstr_get_cstr(mmc->id) : NULL, /* Should we touch mmc here? XXX */
e->src_interface,
"MM7",
e->msize,
(char *)mms_message_type_to_cstr(e->msgtype),
prio ? octstr_get_cstr(prio) : NULL,
mclass ? octstr_get_cstr(mclass) : NULL,
res == MMS_SEND_ERROR_FATAL ? "dropped" : (mstatus ? octstr_get_cstr(mstatus) : "sent"),
e->dlr,
0);
gwlist_append(m->rto, to); /* Record route. */
done_route:
if (res != MMS_SEND_OK)
process_send_res(e, msg, to, mmc, res, err, NULL, NULL, 0);
octstr_destroy(err);
octstr_destroy(requested_mmsc);
}
for (i = 0, n = gwlist_len(mlist); i<n && (e != NULL); i++) { /* Pass through MMSCs, delivering to one at a time. */
MRcpt_t *m = gwlist_get(mlist, i);
int maxrcpt = m->mmc->max_recipients;
List *lto;
/* Hive off maxrcpt each time and send. */
while (e != NULL && (lto = make_srcpt_list(m->rto, maxrcpt)) != NULL) {
MmscGrp *mmc = m->mmc;
Octstr *err = NULL;
Octstr *new_msgid = NULL;
List *errl = NULL;
int j, res = MMS_SEND_OK;
int is_email = m->smtp_flag;
int is_mm4 = (mmc && mmc->type == MM4_MMSC && mmc->started);
List *xto = gwlist_create();
Octstr *zto = NULL;
octstr_destroy(mclass);
octstr_destroy(prio);
octstr_destroy(mstatus);
/* Make recipient list */
for (j = 0; j < gwlist_len(lto); j++) {
MmsEnvelopeTo *to = gwlist_get(lto, j);
Octstr *x = octstr_duplicate(to->rcpt);
int is_email = (octstr_search_char(to->rcpt, '@', 0) > 0);
if (is_mm4 && !is_email) /* Add host name of recipient domain */
octstr_format_append(x, "@%S",
mmc && octstr_str_compare(mmc->mmsc_url, "*") != 0 ? mmc->mmsc_url :
octstr_imm("unknown"));
gwlist_append(xto, x);
}
LINEARISE_STR_LIST(zto,xto,", ");
if (is_mm4 || is_email) { /* Handle mm4 as well */
int j = octstr_case_search(e->from, octstr_imm("/TYPE=PLMN"), 0);
int k = octstr_case_search(e->from, octstr_imm("/TYPE=IPv"), 0);
int len = octstr_len(e->from);
Octstr *pfrom;
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
pfrom = octstr_copy(e->from, 0, j);
else if (k > 0 && k + sizeof "/TYPE=IPv" == len)
pfrom = octstr_copy(e->from, 0, k);
else
pfrom = octstr_duplicate(e->from);
if (octstr_search_char(e->from, '@', 0) < 0)
octstr_format_append(pfrom,"@%S", myhostname);
res = mms_sendtoemail(pfrom, xto,
e->subject ? e->subject : octstr_imm(""),
e->msgId, msg, 0, &err, octstr_get_cstr(sendmail_cmd),
myhostname, 0, 0,
"",
"", 0,
e->xqfname,
e->hdrs, smtp_relay.host, smtp_relay.port);
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED) {
new_msgid = e->msgId ? octstr_duplicate(e->msgId) : octstr_create("00001"); /* Fake it */
mmsbox_event_cb(NULL, MM7_TAG_SubmitReq, 1, octstr_imm("1.0"), 200,
mms_msgsize(msg), e->attempts, pfrom,
zto,NULL, NULL, e->hdrs, NULL);
}
octstr_destroy(pfrom);
} else {
res = mms_sendtommsc(mmc, e,
xto,
otransid,
msg,
&new_msgid,
&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);
}
}
/* For each recipient, process result */
for (j = 0; j < gwlist_len(lto); j++) {
MmsEnvelopeTo *to = gwlist_get(lto, j);
process_send_res(e, msg, to, mmc, res, err, errl, new_msgid, j == 0);
}
octstr_destroy(zto);
gwlist_destroy(xto, (void *)octstr_destroy);
octstr_destroy(new_msgid);
octstr_destroy(err);
http_destroy_headers(errl);
e->lasttry = tnow;
if (qfs->mms_queue_update(e) == 1) {
e = NULL;
break; /* Queue entry gone. */
}
gwlist_destroy(lto, NULL);
}
if (err == NULL)
mms_info(0, "MM7", NULL, "%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: msgid=[%s]",
SEND_ERROR_STR(res),
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
new_msgid ? octstr_get_cstr(new_msgid) : "N/A");
else
mms_error_ex("MT", 0,
"MM7", NULL,
"%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: %s",
SEND_ERROR_STR(res),
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize, octstr_get_cstr(err));
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;
break; /* Queue entry gone. */
}
}
done2:
mms_destroy(msg);
octstr_destroy(otransid);
/* Clear out mlist: */
for (i = 0; i < gwlist_len(mlist); i++) {
MRcpt_t *m = gwlist_get(mlist, i);
gwlist_destroy(m->rto, NULL); /* Clear list */
if (m != &smtp_h)
gw_free(m);
else
mutex_destroy(smtp_h.mmc->mutex);
}
gwlist_destroy(mlist, NULL);
if (e) { /* Update the queue if it is still valid (e.g. recipients not handled)
* XXX can this happen here??...
*/

@ -663,6 +663,10 @@ static MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *warnings, List
if (mms_cfg_get_bool(cfg, x, octstr_imm("strip-domain"), &m->strip_domain) < 0)
m->strip_domain = 1;
if (mms_cfg_get_int(cfg,x, octstr_imm("max-recipients"), &m->max_recipients) < 0 ||
m->max_recipients <= 0)
m->max_recipients = 1;
if (mms_cfg_get_int(cfg,x, octstr_imm("maximum-request-size"), &m->max_pkt_size) < 0 ||
m->max_pkt_size <= 0)
m->max_pkt_size = DEFAULT_MAX_PKT_SIZE;
@ -700,9 +704,13 @@ static MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *warnings, List
m->settings = _mms_cfg_getx(cfg, x, octstr_imm("custom-settings"));
/* also load the libary. */
if ((m->fns = _mms_load_module(cfg, x, "mmsc-library", "mmsc_funcs", NULL)) == NULL) {
mms_error(0, "mmsbox", NULL, "failed to load MMSC libary functions from module!");
m->fns = &dummy_mmsc_funcs;
panic(errno, "failed to load MMSC libary functions from module, mmsc id <%s>!",
octstr_get_cstr(m->id));
}
m->max_recipients = 1;
mms_info(0, "mmsbox", NULL,"Loaded MMSC[%s], max recipients per transaction forced to 1",
octstr_get_cstr(m->id));
} else
WARNING("MMSBox: Unknown MMSC type [%s]!",
octstr_get_cstr(type));
@ -977,14 +985,12 @@ void mmsbox_settings_cleanup(void)
}
void return_mmsc_conn(MmscGrp *m)
{
{
if (m)
MMSBOX_MMSC_UNMARK_INUSE(m); /* Vital! */
/* now try and delete as many to-be-deleted mmc as possible */
delete_stale_mmsc(0);
delete_stale_mmsc(0);
}
/* handle message routing. */

@ -82,6 +82,8 @@ typedef struct MmscGrp {
long max_pkt_size;
int strip_domain; /* MM4 only */
long max_recipients; /* Max recpients per transaction */
} MmscGrp;
#define DEFAULT_MAX_PKT_SIZE 1024*1024

@ -181,14 +181,17 @@ static int sendMsg(MmsEnvelope *e)
e->msgId,
e->hdrs,
msg, &err);
else
res = mms_sendtoemail(pfrom, to->rcpt,
else {
List *lto = gwlist_create_ex(to->rcpt);
res = mms_sendtoemail(pfrom, lto,
e->subject ? e->subject : settings->mms_email_subject,
e->msgId, msg, 0, &err, sendmail_cmd,
settings->hostname, 1, 1,
octstr_get_cstr(settings->mms_email_txt),
octstr_get_cstr(settings->mms_email_html), 0, e->xqfname,
e->hdrs, settings->smtp_relay, settings->smtp_port);
gwlist_destroy(lto, NULL);
}
if (res == MMS_SEND_QUEUED)
res = MMS_SEND_OK; /* queued to email treated same as sent.
* XXX - this means DLR requests for emailed messages not supported!
@ -575,6 +578,7 @@ static int mms_sendtoproxy(Octstr *from, Octstr *to,
{
Octstr *pto, *pfrom;
List *lto;
int x = MMS_SEND_ERROR_FATAL;
Octstr *xtransid; /* We make a fake transaction ID that includes 'to' field. */
@ -596,7 +600,8 @@ static int mms_sendtoproxy(Octstr *from, Octstr *to,
pfrom = from;
xtransid = octstr_format("%S-%s", to,transid);
x = mms_sendtoemail(from, pto,
lto = gwlist_create_ex(pto);
x = mms_sendtoemail(from, lto,
subject ? subject : settings->mms_email_subject,
msgid, msg, dlr,
error, proxy_sendmail_cmd ? octstr_get_cstr(proxy_sendmail_cmd) : sendmail_cmd,
@ -612,7 +617,8 @@ static int mms_sendtoproxy(Octstr *from, Octstr *to,
-1, msgid, NULL, proxy, "MM4", NULL,NULL);
octstr_destroy(pto);
if (pfrom != from)
octstr_destroy(pfrom);
octstr_destroy(pfrom);
gwlist_destroy(lto, NULL);
return x;
}

Loading…
Cancel
Save