-Currently there is no support for VAS via MM7 protocols (SOAP or
-EIAF), but this is planned and should be available soon.
+Currently, only the SOAP MM7 requests are supported. Nokia/EAIF is
+planned and should be available soon.
The Gateway is designed and tested to conform to Open Mobile Alliance
(OMA), WAP and 3rd Generation Partnership Project (3GPP) MMS standards
@@ -510,7 +512,8 @@ argument on the command line (default is mmsc.conf). The
configuration file controls most aspects of
the operation of the gateway.
-The configuration file format is the same as that used
by Kannel. The configuration file consists of groups of configuration
@@ -912,6 +915,22 @@ lists all the configuration directives
is 8191).
+
+
allow-ip
@@ -1243,6 +1262,180 @@ lists all the configuration directives
+
+MM7 Configuration
+
+
+MMS Value-Added Service Providers (VASPs) are configured using
+one or more mms-vasp groups:
+
+
+
+group =
+mms-vasp
+
+vasp-id = newcorp
+
+type =
+soap
+
+short-code
+= 100
+vasp-username
+= newscorp
+vasp-password
+= news123
+
+vasp-url
+= http://example.vasp.com:8080/mm7
+mmsc-username
+= mymmsc
+mmsc-password
+= mypass
+
+
+
+
+
+
+
+
+
+
+ Variable
+ |
+
+ Type
+ |
+
+ Description
+ |
+
+
+
+ group
+
+ |
+
+ String
+ |
+
+ Mandatory:
+ mms-vasp
+ |
+
+
+
+ vasp-id
+ |
+
+ String
+ |
+
+ User friendly
+ name
+ |
+
+
+
+ type
+ |
+
+ String
+ |
+
+ This should be one of: soap, eaif (note: only soap is supported currently)
+ |
+
+
+
+ short-code
+ |
+
+ Number
+ |
+
+ Short number for this VASP: Messages received by Mbuni to this
+ number are routed to the VASP via MM7.
+ |
+
+
+
+
+ vasp-url
+ |
+
+ String
+ |
+
+ Outgoing messages to the VASP are sent via this URL (using HTTP POST)
+ |
+
+
+
+ mmsc-username
+ |
+
+ String
+ |
+
+ Outgoing HTTP authentication: The username Mbuni must use when sending data
+ to the VASP
+ |
+
+
+
+
+ mmsc-password
+ |
+
+ String
+ |
+
+ Outgoing HTTP authentication: password Mbuni must use when sending data
+ to the VASP
+ |
+
+
+
+
+ vasp-username
+ |
+
+ String
+ |
+
+ Incoming HTTP authentication: The username used by the VASP to
+ authenticate itself to Mbuni when sending data
+ |
+
+
+
+
+ vasp-password
+ |
+
+ String
+ |
+
+ Incoming HTTP authentication: The password used by the VASP to
+ authenticate itself to Mbuni when sending data
+ to the VASP
+ |
+
+
+
+
+
+Note that currently only HTTP Basic authentication scheme is supported
+by Mbuni (for both incoming and out-going requests).
+
+
+
+MM4 Configuration
+
+
+
Foreign MMS
Gateways are configured using one or more mmsproxy groups:
@@ -1481,6 +1674,8 @@ re-formatted as MIME, sender and recipient addresses normalised as RFC
822 addresses, and the message passed to the mailer.
If the message is destined for a foreign gateway, it is coded
as MIME and passed to the mailer for delivery via SMTP
+If the the message is destined for a VASP (identified by short
+code), then it is sent using MM7 protocols to the relevant VASP.
If the message cannot be delivered, the sender is notified.
diff --git a/mbuni/misc-patches/mbuni-kannel-patch-full b/mbuni/misc-patches/mbuni-kannel-patch-full
index 6075c4e..1fdd1a7 100644
--- a/mbuni/misc-patches/mbuni-kannel-patch-full
+++ b/mbuni/misc-patches/mbuni-kannel-patch-full
@@ -696,12 +696,6 @@ diff -Naur gateway-1.4.0/gw/smsbox.c gateway-1.4.0-patched/gw/smsbox.c
*status = HTTP_BAD_REQUEST;
msg_destroy(msg);
if (r == -2) {
-diff -Naur gateway-1.4.0/gw/smsc/.gdb_history gateway-1.4.0-patched/gw/smsc/.gdb_history
---- gateway-1.4.0/gw/smsc/.gdb_history Thu Jan 1 03:00:00 1970
-+++ gateway-1.4.0-patched/gw/smsc/.gdb_history Thu Feb 10 10:49:06 2005
-@@ -0,0 +1,2 @@
-+p 1<<4
-+q
diff -Naur gateway-1.4.0/gw/xml_shared.h gateway-1.4.0-patched/gw/xml_shared.h
--- gateway-1.4.0/gw/xml_shared.h Thu Jan 22 17:08:24 2004
+++ gateway-1.4.0-patched/gw/xml_shared.h Fri Jan 28 17:23:22 2005
@@ -723,8 +717,8 @@ diff -Naur gateway-1.4.0/gw/xml_shared.h gateway-1.4.0-patched/gw/xml_shared.h
/*
diff -Naur gateway-1.4.0/gwlib/cfg.def gateway-1.4.0-patched/gwlib/cfg.def
--- gateway-1.4.0/gwlib/cfg.def Mon Jun 28 18:18:35 2004
-+++ gateway-1.4.0-patched/gwlib/cfg.def Mon Mar 21 12:12:16 2005
-@@ -544,6 +544,61 @@
++++ gateway-1.4.0-patched/gwlib/cfg.def Tue Apr 12 11:50:00 2005
+@@ -544,6 +544,73 @@
OCTSTR(unified-prefix)
)
@@ -749,6 +743,7 @@ diff -Naur gateway-1.4.0/gwlib/cfg.def gateway-1.4.0-patched/gwlib/cfg.def
+ OCTSTR(sendsms-password)
+ OCTSTR(sendsms-global-sender)
+ OCTSTR(mms-port)
++ OCTSTR(mm7-port)
+ OCTSTR(allow-ip)
+ OCTSTR(deny-ip)
+ OCTSTR(email2mms-relay-prefixes)
@@ -782,10 +777,118 @@ diff -Naur gateway-1.4.0/gwlib/cfg.def gateway-1.4.0-patched/gwlib/cfg.def
+ OCTSTR(allowed-prefix)
+ OCTSTR(denied-prefix)
+)
++
++MULTI_GROUP(mms-vasp,
++ OCTSTR(vasp-id)
++ OCTSTR(type)
++ OCTSTR(short-code)
++ OCTSTR(vasp-username)
++ OCTSTR(vasp-password)
++ OCTSTR(vasp-url)
++ OCTSTR(mmsc-username)
++ OCTSTR(mmsc-password)
++)
+
#undef OCTSTR
#undef SINGLE_GROUP
#undef MULTI_GROUP
+diff -Naur gateway-1.4.0/gwlib/mime.c gateway-1.4.0-patched/gwlib/mime.c
+--- gateway-1.4.0/gwlib/mime.c Wed Aug 11 19:41:29 2004
++++ gateway-1.4.0-patched/gwlib/mime.c Thu Apr 14 08:31:05 2005
+@@ -191,11 +191,11 @@
+ value = http_header_value(headers, octstr_imm("Content-Type"));
+ boundary = http_get_header_parameter(value, octstr_imm("boundary"));
+ if (boundary == NULL) {
+- boundary = octstr_format("_MIME_boundary-%d-%ld_%c_%c_bd%d",
++ boundary = octstr_format("=_MIME_boundary_%d_%ld_%c_%c_bd%d",
+ random(), (long)time(NULL), 'A' + (random()%26),
+ 'a'+(random() % 26), random());
+- octstr_append(value, octstr_imm("; boundary="));
+- octstr_append(value, boundary);
++ octstr_format_append(value, "; boundary=\"%S\"", boundary);
++
+ http_header_remove_all(headers, "Content-Type");
+ http_header_add(headers, "Content-Type", octstr_get_cstr(value));
+ http_header_add(headers, "MIME-Version", "1.0");
+@@ -214,8 +214,8 @@
+ MIMEEntity *e = list_get(m->multiparts, i);
+ Octstr *body;
+
+- if (i != 0)
+- octstr_append(mime, octstr_imm("\r\n"));
++ if (i != 0)
++ octstr_append(mime, octstr_imm("\r\n"));
+ octstr_append(mime, octstr_imm("\r\n--"));
+ octstr_append(mime, boundary);
+ octstr_append(mime, octstr_imm("\r\n"));
+@@ -331,10 +331,13 @@
+ else
+ octstr_delete(entity, 0, 1);
+
+- if (octstr_get_char(entity, octstr_len(entity) - 2) == '\r')
++ if (octstr_get_char(entity, octstr_len(entity) - 2) == '\r' &&
++ octstr_get_char(entity, octstr_len(entity) - 4) == '\r')
+ octstr_delete(entity, octstr_len(entity) - 4, 4);
++ else if (octstr_get_char(entity, octstr_len(entity) - 2) == '\r')
++ octstr_delete(entity, octstr_len(entity) - 2, 2);
+ else
+- octstr_delete(entity, octstr_len(entity) - 2, 2);
++ octstr_delete(entity, octstr_len(entity) - 1, 1);
+
+
+ debug("mime.parse",0,"MIME multipart: Parsing entity:");
+@@ -443,6 +446,34 @@
+ return body;
+ }
+
++int mime_entity_body_and_headers(MIMEEntity *m, Octstr **body, List **headers)
++{
++ Octstr *os;
++ ParseContext *context;
++
++ gw_assert(m != NULL && m->headers != NULL);
++
++ os = mime_entity_to_octstr(m);
++ context = parse_context_create(os);
++
++ *headers = http_create_empty_headers();
++
++ /* parse the headers up to the body */
++ if ((read_mime_headers(context, *headers) != 0) ||*headers == NULL) {
++ debug("mime.parse",0,"Failed to read MIME headers in Octstr block:");
++ octstr_dump(os, 0);
++ parse_context_destroy(context);
++ return -1;
++ }
++
++ /* the rest is the body */
++ *body = parse_get_rest(context);
++
++ octstr_destroy(os);
++
++ parse_context_destroy(context);
++ return 0;
++}
+
+ /********************************************************************
+ * Routines for debugging purposes.
+diff -Naur gateway-1.4.0/gwlib/mime.h gateway-1.4.0-patched/gwlib/mime.h
+--- gateway-1.4.0/gwlib/mime.h Mon Jan 26 18:04:57 2004
++++ gateway-1.4.0-patched/gwlib/mime.h Wed Apr 13 17:59:48 2005
+@@ -141,6 +141,13 @@
+ Octstr *mime_entity_body(MIMEEntity *m);
+
+ /*
++ * Take a MIME multipart representation and return the headers and body as would
++ * result from turning it into a string.
++ * this then serves for http header and body...
++ */
++int mime_entity_body_and_headers(MIMEEntity *m, Octstr **body, List **headers);
++
++/*
+ * Dump the structure (hicharchical view) of the MIME representation
+ * structure into our DEBUG log level facility.
+ */
diff -Naur gateway-1.4.0/wap/wsp_headers.c gateway-1.4.0-patched/wap/wsp_headers.c
--- gateway-1.4.0/wap/wsp_headers.c Sun Aug 8 23:39:56 2004
+++ gateway-1.4.0-patched/wap/wsp_headers.c Tue Mar 15 12:26:43 2005
diff --git a/mbuni/mmlib/mms_mm7soap.c b/mbuni/mmlib/mms_mm7soap.c
index f3eaf4a..5af94d2 100644
--- a/mbuni/mmlib/mms_mm7soap.c
+++ b/mbuni/mmlib/mms_mm7soap.c
@@ -6,6 +6,12 @@
#define content(n) ((n)->xmlChildrenNode ? dfltstr(((n)->xmlChildrenNode)->content) : dfltstr((n)->content))
+struct MSoapMsg_t {
+ List *envelope; /* of http headers. */
+ MIMEEntity *msg; /* XXX - be sure to copy some headers to this from envelope before convert...*/
+};
+
+/* We expect ISO formatted time, or interval. */
static Octstr *parse_time(char *s)
{
@@ -15,9 +21,12 @@ static Octstr *parse_time(char *s)
octstr_strip_blanks(p);
- if (s && s[0] != 'P')
- return p;
- else
+ if (s && s[0] != 'P') {
+ struct universaltime tt;
+ if (date_parse_iso(&tt, p) >= 0)
+ t = date_convert_universal(&tt);
+ goto done;
+ } else
i++;
while (i < octstr_len(p)) {
@@ -59,8 +68,9 @@ static Octstr *parse_time(char *s)
}
}
+ done:
octstr_destroy(p);
- return date_create_iso(t);
+ return date_format_http(t);
}
static int parse_header(xmlNodePtr node, List *headers, int *sigparent)
@@ -108,12 +118,21 @@ static int parse_header(xmlNodePtr node, List *headers, int *sigparent)
break;
case MM7_TAG_SenderIdentification:
case MM7_TAG_Recipients:
+
skip = 1;
break;
+
+ case MM7_TAG_Recipient:
+ *sigparent = MM7_TAG_To; /* make it a To field. */
+
+ break;
case MM7_TAG_To:
case MM7_TAG_Cc:
- case MM7_TAG_Bcc:
+ case MM7_TAG_Bcc:
+ case MM7_TAG_Sender:
+ case MM7_TAG_SenderAddress:
skip = 1;
+
*sigparent = tag; /* We wait for number and stuff below. */
break;
case MM7_TAG_Content:
@@ -123,7 +142,7 @@ static int parse_header(xmlNodePtr node, List *headers, int *sigparent)
}
/* we keep 'cid:' bit. ignore the bit about adaptation. */
break;
-
+ case MM7_TAG_ShortCode:
case MM7_TAG_Number: /* we will not normalise number here, that's for upper level. */
value = octstr_format("%s/TYPE=PLMN", nvalue);
@@ -140,10 +159,12 @@ static int parse_header(xmlNodePtr node, List *headers, int *sigparent)
octstr_insert(value, octstr_imm("+ "), 0);
if (s)
xmlFree(s);
- break;
+ break;
case MM7_TAG_EarliestDeliveryTime:
case MM7_TAG_ExpiryDate:
+ case MM7_TAG_TimeStamp:
+ case MM7_TAG_Date:
value = parse_time(nvalue);
break;
@@ -169,8 +190,12 @@ static int parse_header(xmlNodePtr node, List *headers, int *sigparent)
value = octstr_create(nvalue);
octstr_strip_blanks(value);
- if (!skip && tag >= 0)
+ if (!skip && tag >= 0 && hname != NULL) {
http_header_add(headers, hname, octstr_get_cstr(value));
+#if 1
+ info(0, "parse.soap, h=%s, v=%s!", hname, octstr_get_cstr(value));
+#endif
+ }
octstr_destroy(value);
return 0;
@@ -193,7 +218,7 @@ MSoapMsg_t *mm7_parse_soap(List *headers, Octstr *body)
MIMEEntity *mime = mime_http_to_entity(headers, body);
Octstr *xml = NULL, *cloc;
xmlDocPtr doc;
- MmsMsg *msg = NULL;
+ MIMEEntity *msg = NULL;
List *h;
int s = -1;
MSoapMsg_t *smsg = NULL;
@@ -214,9 +239,12 @@ MSoapMsg_t *mm7_parse_soap(List *headers, Octstr *body)
} else
xml = mime->body;
+ /* Don't free 'xml'! It is part of mime object. */
if (!xml)
goto done;
-
+#if 1
+ info(0, "XML sent is: %s!", octstr_get_cstr(xml));
+#endif
doc = xmlParseMemory(octstr_get_cstr(xml), octstr_len(xml));
if (!doc || !doc->xmlChildrenNode)
goto done;
@@ -239,8 +267,10 @@ MSoapMsg_t *mm7_parse_soap(List *headers, Octstr *body)
for (i = 0, n = list_len(mime->multiparts); imultiparts, i);
Octstr *y = x ? http_header_value(x->headers, octstr_imm("Content-ID")) : NULL;
-
- if (y && octstr_str_compare(y, loc) == 0)
+ char *cid = (y && octstr_get_char(y, 0) == '<') ? octstr_get_cstr(y) + 1 : (y ? octstr_get_cstr(y) : "");
+ int cid_len = (y && octstr_get_char(y, 0) == '<') ? octstr_len(y) - 2 : (y ? octstr_len(y) : 0);
+
+ if (y && strncmp(loc, cid, cid_len) == 0)
c = x;
if (y)
@@ -248,8 +278,9 @@ MSoapMsg_t *mm7_parse_soap(List *headers, Octstr *body)
if (c)
break;
}
- if (c)
- msg = mms_frommime(c);
+
+ if (c)
+ msg = mime_entity_duplicate(c);
octstr_destroy(cloc);
}
@@ -260,11 +291,29 @@ MSoapMsg_t *mm7_parse_soap(List *headers, Octstr *body)
done:
if (mime)
mime_entity_destroy(mime);
- if (xml)
- octstr_destroy(xml);
return smsg;
}
+static int append_address(Octstr *p, Octstr *addr_spec)
+{
+ Octstr *v = addr_spec;
+ char *y;
+ int j, ch = octstr_get_char(v, 0);
+ if (ch == '-')
+ y = " displayOnly=\"true\"";
+ else
+ y = "";
+ j = octstr_case_search(v, octstr_imm("/TYPE=PLMN"),0);
+ if (j >= 0) {
+ Octstr *z = octstr_copy(v, 2, j-2); /* skip the initial char that is only for info purposes. */
+ octstr_format_append(p, "%S\n", y, z);
+ octstr_destroy(z);
+ } else
+ octstr_format_append(p, "%s\n",
+ y, octstr_get_cstr(v) + 2); /* as above... */
+ return 0;
+}
+
static void output_rcpt(char *hdr, List *hdrs, Octstr *p)
{
List *l = http_header_find_all(hdrs, hdr);
@@ -273,8 +322,6 @@ static void output_rcpt(char *hdr, List *hdrs, Octstr *p)
for (i = 0, n = list_len(l), x[0]=0; i < n; i++) {
Octstr *h = NULL, *v = NULL;
- int ch, j;
- char *y;
http_header_get(l, i, &h, &v);
if (octstr_str_compare(h, x) != 0) {
@@ -284,20 +331,7 @@ static void output_rcpt(char *hdr, List *hdrs, Octstr *p)
octstr_format_append(p, "<%S>\n", h);
}
octstr_destroy(h);
-
- ch = octstr_get_char(v, 0);
- if (ch == '-')
- y = " displayOnly=\"true\"";
- else
- y = "";
- j = octstr_case_search(v, octstr_imm("/TYPE=PLMN"),0);
- if (j > 0) {
- Octstr *z = octstr_copy(v, 2, j-2); /* skip the initial char that is only for info purposes. */
- octstr_format_append(p, "%S\n", y, z);
- octstr_destroy(z);
- } else
- octstr_format_append(p, "%s\n",
- y, octstr_get_cstr(v) + 2); /* as above... */
+ append_address(p, v);
octstr_destroy(v);
}
if (x[0]) /* close it off. */
@@ -306,14 +340,16 @@ static void output_rcpt(char *hdr, List *hdrs, Octstr *p)
http_destroy_headers(l);
}
-#define XMLNSMM7 "http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-3"
+#define XMLNSMM7 "http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-0"
/* Construct by hand. */
Octstr *headers_to_soapxml(List *hdrs)
{
Octstr *s = octstr_create("\n");
- Octstr *p, *q, *fault, *mtype;
+ Octstr *p, *q, *r, *fault, *mtype;
int i, n;
-
+ time_t t;
+ int mtag;
+
octstr_append_cstr(s,
"\n"
"\n");
@@ -346,6 +382,7 @@ Octstr *headers_to_soapxml(List *hdrs)
mtype = http_header_value(hdrs, octstr_imm("MessageType"));
+ mtag = mms_string_to_mm7tag(mtype);
octstr_format_append(s, "<%S xmlns=\"%s\">\n", mtype, XMLNSMM7);
@@ -356,8 +393,8 @@ Octstr *headers_to_soapxml(List *hdrs)
p = http_header_value(hdrs, octstr_imm("VASPID"));
q = http_header_value(hdrs, octstr_imm("VASID"));
-
- if (p || q) {
+ r = http_header_value(hdrs, octstr_imm("SenderAddress"));
+ if (p || q || r) {
octstr_append_cstr(s, "\n");
if (p)
@@ -366,19 +403,33 @@ Octstr *headers_to_soapxml(List *hdrs)
if (q)
octstr_format_append(s, "%S\n", q);
+ if (r) {
+ Octstr *xx = octstr_create("");
+ append_address(xx, r);
+ octstr_format_append(s, "%S\n", xx);
+ octstr_destroy(xx);
+ }
+
octstr_append_cstr(s, "\n");
if (p) octstr_destroy(p);
if (q) octstr_destroy(q);
+ if (r) octstr_destroy(r);
}
- p = octstr_create("");
-
- output_rcpt("To", hdrs, p);
- output_rcpt("Cc", hdrs, p);
- output_rcpt("Bcc", hdrs, p);
-
- if (octstr_len(p) > 0)
- octstr_format_append(s, "\n%S\n", p);
+ p = octstr_create("");
+ if (mtag == MM7_TAG_SubmitReq ||
+ mtag == MM7_TAG_DeliverReq) { /* Multiple recipients,... */
+ output_rcpt("To", hdrs, p);
+ output_rcpt("Cc", hdrs, p);
+ output_rcpt("Bcc", hdrs, p);
+
+ if (octstr_len(p) > 0)
+ octstr_format_append(s, "\n%S\n", p);
+ } else if ((q = http_header_value(hdrs, octstr_imm("To"))) != NULL) {
+ append_address(p, q);
+ octstr_format_append(s, "\n%S\n", p);
+ octstr_destroy(q);
+ }
octstr_destroy(p);
@@ -408,8 +459,17 @@ Octstr *headers_to_soapxml(List *hdrs)
case MM7_TAG_replyChargingSize:
case MM7_TAG_replyDeadline:
case MM7_TAG_TransactionID:
- case MM7_TAG_StatusCode:
- case MM7_TAG_StatusText:
+ case MM7_TAG_StatusCode:
+ case MM7_TAG_StatusText:
+ case MM7_TAG_Details:
+ case MM7_TAG_SenderAddress:
+ skip = 1;
+ break;
+ case MM7_TAG_Sender:
+ p = octstr_create("");
+ append_address(p, v);
+ octstr_format_append(s, "%S\n", p);
+ octstr_destroy(p);
skip = 1;
break;
case MM7_TAG_Content:
@@ -432,11 +492,19 @@ Octstr *headers_to_soapxml(List *hdrs)
octstr_append_cstr(s, "/>\n");
skip = 1;
break;
-
+ case MM7_TAG_EarliestDeliveryTime:
+ case MM7_TAG_ExpiryDate:
+ case MM7_TAG_TimeStamp:
+ case MM7_TAG_Date:
+ t = date_parse_http(v);
+ octstr_destroy(v);
+ v = date_create_iso(t); /* format as ISO time... */
+ break;
case MM7_TAG_Status:
p = http_header_value(hdrs, octstr_imm("StatusCode"));
q = http_header_value(hdrs, octstr_imm("StatusText"));
-
+
+
octstr_append_cstr(s, "\n");
if (p) {
octstr_format_append(s, "%S\n", p);
@@ -446,6 +514,12 @@ Octstr *headers_to_soapxml(List *hdrs)
octstr_format_append(s, "%S\n", q);
octstr_destroy(q);
}
+ q = http_header_value(hdrs, octstr_imm("Details"));
+ if (q) {
+ octstr_format_append(s, "%S \n", q);
+ octstr_destroy(q);
+ }
+
octstr_append_cstr(s, "\n");
skip = 1;
break;
@@ -484,11 +558,12 @@ int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, List **hdrs, Octstr **body)
mime = mime_entity_create();
if (m->msg) {
- MIMEEntity *c = mms_tomime(m->msg);
- Octstr *cloc = octstr_format("cid:",
+ MIMEEntity *c = mime_entity_duplicate(m->msg);
+ Octstr *cloc = octstr_format("cid:c%ld.%d.%c%c.msg",
time(NULL), random(),
'A' + random() % 26,
'a' + random() % 26);
+ Octstr *cloc_str = octstr_format("<%s>", octstr_get_cstr(cloc) + 4);
Octstr *envloc = octstr_format("",
time(NULL), random(),
'A' + random() % 26,
@@ -497,14 +572,14 @@ int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, List **hdrs, Octstr **body)
List *hh = http_header_duplicate(m->envelope);
/* Replace in envelope. */
- http_header_remove_all(hh, "Content-ID");
- http_header_add(hh, "Content-ID", octstr_get_cstr(cloc));
+ http_header_remove_all(hh, "Content");
+ http_header_add(hh, "Content", octstr_get_cstr(cloc));
/* Replace content location in msg part. */
http_header_remove_all(c->headers, "Content-ID");
- http_header_add(c->headers, "Content-ID", octstr_get_cstr(cloc) + 4);
+ http_header_add(c->headers, "Content-ID", octstr_get_cstr(cloc_str));
- http_header_add(xml->headers, "Content-Type", "text/xml; charset=\"utf-8\"");
+ http_header_add(xml->headers, "Content-Type", "text/xml");
http_header_add(xml->headers, "Content-ID", octstr_get_cstr(envloc));
xml->body = headers_to_soapxml(hh);
@@ -513,23 +588,395 @@ int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, List **hdrs, Octstr **body)
http_destroy_headers(hh);
- ctype = octstr_format("multipart/related; start=\"%S\"; type=text/xml",
+ ctype = octstr_format("multipart/related"
+
+ "; start=\"%S\""
+#if 0
+ "; type=text/xml"
+#endif
+,
envloc);
octstr_destroy(envloc);
octstr_destroy(cloc);
+ octstr_destroy(cloc_str);
} else {
- ctype = octstr_imm("text/xml; charset=\"utf-8\"");
+ ctype = octstr_imm("text/xml");
mime->body = headers_to_soapxml(m->envelope);
}
http_header_add(mime->headers, "Content-Type", octstr_get_cstr(ctype));
http_header_add(mime->headers, "SOAPAction", "\"\"");
- *hdrs = mime_entity_headers(mime);
- *body = mime_entity_body(mime);
-
+ mime_entity_body_and_headers(mime, body, hdrs);
+
mime_entity_destroy(mime);
return 0;
}
+
+int mm7_msgtype(MSoapMsg_t *m)
+{
+ Octstr *typ = http_header_value(m->envelope, octstr_imm("MessageType"));
+ int ret;
+
+ if (!typ)
+ return -1;
+
+ ret = mms_string_to_mm7tag(typ);
+ octstr_destroy(typ);
+
+ return ret;
+}
+
+static int get_rcptvalues(List *to, List *headers, char *hname)
+{
+ List *l;
+ int i, n;
+
+ l = http_header_find_all(headers, hname);
+
+ for (i = 0, n = (l) ? list_len(l) : 0; i < n; i++) {
+ Octstr *h, *v;
+ int ch;
+ http_header_get(l, i, &h, &v);
+
+ ch = octstr_get_char(v, 0);
+ if (ch == '+')
+ list_append(to, octstr_copy(v, 2, octstr_len(v)));
+ octstr_destroy(h);
+ octstr_destroy(v);
+ }
+ http_destroy_headers(l);
+ return 0;
+}
+
+int mm7_get_envelope(MSoapMsg_t *m,
+ Octstr **sender,
+ List **to, Octstr **subject,
+ Octstr **vasid,
+ time_t *expiry_t,
+ time_t *delivery_t)
+{
+ Octstr *s;
+
+ if (*to == NULL)
+ *to = list_create();
+
+ get_rcptvalues(*to, m->envelope, "To");
+ get_rcptvalues(*to, m->envelope, "Cc");
+ get_rcptvalues(*to, m->envelope, "Bcc");
+
+
+ *subject = http_header_value(m->envelope, octstr_imm("Subject"));
+ *vasid = http_header_value(m->envelope, octstr_imm("VASID"));
+
+ s = http_header_value(m->envelope, octstr_imm("SenderAddress"));
+ if (s && octstr_get_char(s, 0) == '+')
+ octstr_delete(s, 0, 2);
+ else if (s) {
+ octstr_destroy(s);
+ s = NULL;
+ }
+ *sender = s;
+
+ if (expiry_t) {
+ Octstr *s = http_header_value(m->envelope, octstr_imm("ExpiryDate"));
+
+ *expiry_t = -1;
+ if (s) {
+ *expiry_t = date_parse_http(s);
+ octstr_destroy(s);
+ }
+ }
+
+ if (delivery_t) {
+ Octstr *s = http_header_value(m->envelope, octstr_imm("EarliestDeliveryTime"));
+ *delivery_t = -1;
+ if (s) {
+ *delivery_t = date_parse_http(s);
+ octstr_destroy(s);
+ }
+ }
+ return 0;
+}
+
+
+MmsMsg *mm7_soap_to_mmsmsg(MSoapMsg_t *m, Octstr *from)
+{
+
+ int msgtype = mm7_msgtype(m);
+ MmsMsg *msg = NULL;
+ Octstr *s, *f, *p, *q, *r;
+ List *l;
+ time_t t;
+
+ switch(msgtype) {
+ case MM7_TAG_DeliverReq:
+ case MM7_TAG_SubmitReq:
+ case MM7_TAG_ReplaceReq:
+ msg = mms_frommime(m->msg);
+
+ if (!msg)
+ break;
+
+ /* Put in some headers... */
+ if (from)
+ mms_replace_header_value(msg, "From", octstr_get_cstr(from));
+
+ if ((s = http_header_value(m->envelope, octstr_imm("MessageClass"))) != NULL) {
+ if (mms_string_to_message_class(s) >= 0)
+ mms_replace_header_value(msg, "X-Mms-Message-Class", octstr_get_cstr(s));
+ octstr_destroy(s);
+ }
+
+ if ((s = http_header_value(m->envelope, octstr_imm("Priority"))) != NULL) {
+ if (mms_string_to_priority(s) >= 0)
+ mms_replace_header_value(msg, "X-Mms-Priority", octstr_get_cstr(s));
+ octstr_destroy(s);
+ }
+
+ if ((s = http_header_value(m->envelope, octstr_imm("DeliveryReport"))) != NULL) {
+ if (mms_string_to_reports(s) >= 0)
+ mms_replace_header_value(msg, "X-Mms-Delivery-Report", octstr_get_cstr(s));
+ octstr_destroy(s);
+ }
+
+ if ((s = http_header_value(m->envelope, octstr_imm("ReadReply"))) != NULL) {
+ if (mms_string_to_reports(s) >= 0)
+ mms_replace_header_value(msg, "X-Mms-Read-Report", octstr_get_cstr(s));
+ octstr_destroy(s);
+ }
+
+ if ((s = http_header_value(m->envelope, octstr_imm("TimeStamp"))) != NULL) {
+ mms_replace_header_value(msg, "Date", octstr_get_cstr(s));
+ octstr_destroy(s);
+ }
+
+ if ((s = http_header_value(m->envelope, octstr_imm("ExpiryDate"))) != NULL) {
+ mms_replace_header_value(msg, "X-Mms-Expiry", octstr_get_cstr(s));
+ octstr_destroy(s);
+ }
+
+ if ((s = http_header_value(m->envelope, octstr_imm("Subject"))) != NULL) {
+ mms_replace_header_value(msg, "Subject", octstr_get_cstr(s));
+ octstr_destroy(s);
+ }
+
+ /* Put in recipient list. XXX - really?? */
+ l = list_create();
+ get_rcptvalues(l, m->envelope, "To");
+ mms_replace_header_values(msg, "To", l);
+ list_destroy(l, (list_item_destructor_t *)octstr_destroy);
+
+ l = list_create();
+ get_rcptvalues(l, m->envelope, "Cc");
+ mms_replace_header_values(msg, "Cc", l);
+ list_destroy(l, (list_item_destructor_t *)octstr_destroy);
+
+ /* XXX - we ignore reply charging, etc. */
+ break;
+
+ case MM7_TAG_DeliveryReportReq: /* should we bother?? Can these ever be handled here?? */
+ case MM7_TAG_ReadReplyReq:
+ s = http_header_value(m->envelope, octstr_imm("MessageID"));
+ if ((p = http_header_value(m->envelope, octstr_imm("To"))) != NULL &&
+ octstr_get_char(p, 0) == '+')
+ octstr_delete(p, 0, 2);
+ else if (p) {
+ octstr_destroy(p);
+ p = NULL;
+ }
+
+ if ((f = http_header_value(m->envelope, octstr_imm("From"))) != NULL &&
+ octstr_get_char(f, 0) == '+')
+ octstr_delete(f, 0, 2);
+ else if (f) {
+ octstr_destroy(f);
+ f = NULL;
+ }
+
+ if ((q = http_header_value(m->envelope, octstr_imm("Date"))) != NULL)
+ t = date_parse_http(q);
+ else
+ t = time(NULL);
+ r = http_header_value(m->envelope, octstr_imm("MMStatus"));
+
+ if (msgtype == MM7_TAG_DeliveryReportReq &&
+ p && r && mms_string_to_status(r) >= 0)
+ msg = mms_deliveryreport(s ? s : octstr_imm("0000"), p, t, r);
+ else if (msgtype == MM7_TAG_ReadReplyReq &&
+ f && p && r && mms_string_to_read_status(r) >= 0)
+ msg = mms_readreport(s ? s : octstr_imm("0000"),
+ f, p, t, r);
+ if (s)
+ octstr_destroy(s);
+ if (p)
+ octstr_destroy(p);
+ if (r)
+ octstr_destroy(r);
+ if (f)
+ octstr_destroy(f);
+ break;
+ default:
+ break;
+ }
+ return msg;
+}
+
+void mm7_soap_destroy(MSoapMsg_t *m)
+{
+ http_destroy_headers(m->envelope);
+ if (m->msg)
+ mime_entity_destroy(m->msg);
+ gw_free(m);
+}
+
+static MSoapMsg_t *mm7_soap_create(int msgtype, Octstr *otransid)
+{
+ MSoapMsg_t *m = gw_malloc(sizeof *m);
+
+ m->envelope = http_create_empty_headers();
+ m->msg = NULL;
+
+ http_header_add(m->envelope, "MessageType", mms_mm7tag_to_cstr(msgtype));
+ http_header_add(m->envelope, "MM7Version", MM7_DEFAULT_VERSION);
+ http_header_add(m->envelope, "TransactionID",
+ otransid ? octstr_get_cstr(otransid) : "0000");
+ return m;
+}
+
+MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto,
+ Octstr *transid, Octstr *serverID)
+{
+ int mtype = mms_messagetype(msg);
+ MSoapMsg_t *m = NULL;
+ Octstr *s;
+ int i, n;
+ Octstr *xfrom;
+
+ xfrom = octstr_format("+ %S", from ? from : octstr_imm("anon@anon"));
+ switch(mtype) {
+ case MMS_MSGTYPE_SEND_REQ:
+ case MMS_MSGTYPE_RETRIEVE_CONF:
+ m = mm7_soap_create(MM7_TAG_DeliverReq, transid);
+ m->msg = mms_tomime(msg);
+
+ for (i = 0, n = xto ? list_len(xto) : 0; i < n; i++) { /* Add recipients. */
+ Octstr *xx = octstr_format("+ %S", list_get(xto, i));
+ http_header_add(m->envelope, "To",
+ octstr_get_cstr(xx));
+ octstr_destroy(xx);
+ }
+
+ if (serverID)
+ http_header_add(m->envelope, "MMSRelayServerID", octstr_get_cstr(serverID));
+ http_header_add(m->envelope, "LinkedID", octstr_get_cstr(transid));
+ http_header_add(m->envelope, "Sender", octstr_get_cstr(xfrom));
+
+ if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Priority"))) != NULL) {
+ 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));
+ octstr_destroy(s);
+ }
+
+ if ((s = mms_get_header_value(msg, octstr_imm("Date"))) != NULL) {
+ http_header_add(m->envelope, "TimeStamp", octstr_get_cstr(s));
+ octstr_destroy(s);
+ }
+
+ /* Should we bother to strip message part of headers??? */
+ http_header_remove_all(m->msg->headers, "Subject");
+ http_header_remove_all(m->msg->headers, "X-Mms-Message-Type");
+ http_header_remove_all(m->msg->headers, "X-Mms-Message-Version");
+ http_header_remove_all(m->msg->headers, "From");
+ http_header_remove_all(m->msg->headers, "To");
+ http_header_remove_all(m->msg->headers, "Cc");
+ http_header_remove_all(m->msg->headers, "Bcc");
+ 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);
+
+ http_header_add(m->envelope, "Sender", octstr_get_cstr(xfrom));
+
+ if (xto && list_len(xto) > 0) {
+ Octstr *xx = octstr_format("+ %S", list_get(xto, 0));
+ http_header_add(m->envelope, "To",
+ octstr_get_cstr(xx));
+ octstr_destroy(xx);
+ }
+
+ s = mms_get_header_value(msg, octstr_imm("Message-ID"));
+ if (!s)
+ s = octstr_duplicate(transid);
+ http_header_add(m->envelope, "MessageID", octstr_get_cstr(s));
+ octstr_destroy(s);
+
+ if ((s = mms_get_header_value(msg, octstr_imm("Date"))) != NULL) {
+ http_header_add(m->envelope,
+ (mtype == MMS_MSGTYPE_READ_ORIG_IND) ? "TimeStamp" : "Date",
+ octstr_get_cstr(s));
+ octstr_destroy(s);
+ }
+
+ if ((s = mms_get_header_value(msg,
+ (mtype == MMS_MSGTYPE_READ_ORIG_IND) ?
+ octstr_imm("X-Mms-Read-Status") :
+ octstr_imm("X-Mms-Status") )) != NULL) {
+ http_header_add(m->envelope, "MMStatus", octstr_get_cstr(s));
+ octstr_destroy(s);
+ }
+
+ break;
+ default:
+ break;
+ }
+ octstr_destroy(xfrom);
+
+ return m;
+}
+
+MSoapMsg_t *mm7_make_resp(MSoapMsg_t *mreq, int status, Octstr *msgid)
+{
+ int mtype = mreq ? mm7_msgtype(mreq) : -1;
+ Octstr *transid;
+ MSoapMsg_t *mresp;
+ char scode[64];
+ char *statustxt = mms_soap_status_to_cstr(status);
+
+ transid = mreq ? http_header_value(mreq->envelope, octstr_imm("TransactionID")) : NULL;
+
+ if (!MM7_SOAP_STATUS_OK(status) || mtype < 0)
+ mresp = mm7_soap_create(MM7_TAG_RSErrorRsp, transid);
+ else
+ mresp = mm7_soap_create(mtype + 1, transid);
+
+ sprintf(scode, "%d", status);
+ http_header_add(mresp->envelope, "Status", ""); /* So that we get output. */
+ http_header_add(mresp->envelope, "StatusCode", scode);
+ http_header_add(mresp->envelope, "StatusText", statustxt ? statustxt : "Error");
+
+ if (msgid)
+ http_header_add(mresp->envelope, "MessageID", octstr_get_cstr(msgid));
+
+ if (!MM7_SOAP_STATUS_OK(status)) {
+ http_header_add(mresp->envelope, "Fault", ""); /* do we really need these? XXX */
+ http_header_add(mresp->envelope, "faultcode", "env:Server");
+ http_header_add(mresp->envelope, "faultstring", "Server error");
+ }
+
+ octstr_destroy(transid);
+ return mresp;
+}
+
+Octstr *mm7_soap_header_value(MSoapMsg_t *m, Octstr *header)
+{
+ return http_header_value(m->envelope, header);
+}
diff --git a/mbuni/mmlib/mms_mm7soap.h b/mbuni/mmlib/mms_mm7soap.h
index e80ac70..74a5bed 100644
--- a/mbuni/mmlib/mms_mm7soap.h
+++ b/mbuni/mmlib/mms_mm7soap.h
@@ -2,14 +2,44 @@
#define __MMS_MM7SOAP_INCLUDED__
#include "mms_util.h"
-typedef struct MSoapMsg_t {
- List *envelope; /* of http headers. */
- MmsMsg *msg;
-} MSoapMsg_t;
+#define MM7_SOAP_OK 1000
+#define MM7_SOAP_FORMAT_CORRUPT 2007
+#define MM7_SOAP_STATUS_OK(e) ((e) / 1000 == 1)
+#define MM7_DEFAULT_VERSION "5.3.0"
+typedef struct MSoapMsg_t MSoapMsg_t;
+
+/* Parse SOAP message given http headers and body. */
extern MSoapMsg_t *mm7_parse_soap(List *headers, Octstr *body);
+
+/* Convert SOAP message to http headers and body. */
extern int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, List **hdrs, Octstr **body);
-extern MmsMsg *mm7_soapmsg_to_mmsmsg(MSoapMsg_t *m);
+/* Convert SOAP message to an MMS message. */
+extern MmsMsg *mm7_soap_to_mmsmsg(MSoapMsg_t *m, Octstr *from);
+/* Return the message type. */
+extern int mm7_msgtype(MSoapMsg_t *m);
+
+/* Collect and return envelope data:
+ * - to -- list of recipients to send to
+ * - subject -- subject
+ * - msgid -- message id
+ * - vasid/vaspid -- vasid and vaspid
+ */
+extern int mm7_get_envelope(MSoapMsg_t *m, Octstr **sender,
+ List **to, Octstr **subject,
+ Octstr **vasid,
+ time_t *expiry_t,
+ time_t *delivery_t);
+
+/* Delete the thingie... */
+extern void mm7_soap_destroy(MSoapMsg_t *m);
+
+/* Convert a message to a SOAP message. */
+MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto,
+ Octstr *transid, Octstr *serverID);
+MSoapMsg_t *mm7_make_resp(MSoapMsg_t *mreq, int status, Octstr *msgid);
+/* Return the header value for some header. */
+Octstr *mm7_soap_header_value(MSoapMsg_t *m, Octstr *header);
#endif
diff --git a/mbuni/mmlib/mms_msg.c b/mbuni/mmlib/mms_msg.c
index c041f2b..679c344 100644
--- a/mbuni/mmlib/mms_msg.c
+++ b/mbuni/mmlib/mms_msg.c
@@ -911,6 +911,7 @@ static int encode_msgheaders(Octstr *os, List *hdrs)
version = http_header_value(hdrs,
octstr_imm("X-Mms-MMS-Version"));
+
transid = http_header_value(hdrs,
octstr_imm("X-Mms-Transaction-Id"));
msgtype = http_header_value(hdrs,
@@ -980,9 +981,11 @@ static int fixup_msg(MmsMsg *m, Octstr *from)
return -1;
ver = http_header_value(m->headers, octstr_imm("X-Mms-MMS-Version"));
- if (!ver || octstr_str_compare(ver, "1.1") <= 0)
+ if (!ver || octstr_str_compare(ver, "1.1") <= 0) {
m->enc = MS_1_1;
- else if (octstr_str_compare(ver, "1.2") <= 0)
+ if (!ver)
+ http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION);
+ } else if (octstr_str_compare(ver, "1.2") <= 0)
m->enc = MS_1_2;
if (m->message_type == MMS_MSGTYPE_SEND_REQ ||
@@ -1226,27 +1229,6 @@ static void unconvert_mime_msg(MIMEEntity *m)
}
-static MIMEEntity *mime_entity_duplicate(MIMEEntity *m)
-{
- MIMEEntity *mx = gw_malloc(sizeof *mx);
-
- mx->headers = http_header_duplicate(m->headers);
- if (m->multiparts && list_len(m->multiparts) > 0) {
- int i, n;
- mx->multiparts = list_create();
- for (i = 0, n = list_len(m->multiparts); i < n; i++) {
- MIMEEntity *x = mime_entity_duplicate(list_get(m->multiparts, i));
- list_append(mx->multiparts, x);
- }
- mx->body = NULL;
- } else {
- mx->body = m->body ? octstr_duplicate(m->body) : NULL;
- mx->multiparts = NULL;
- }
- mx->start = NULL;
-
- return mx;
-}
MIMEEntity *mms_tomime(MmsMsg *msg)
{
@@ -1269,7 +1251,7 @@ MIMEEntity *mms_tomime(MmsMsg *msg)
}
}
convert_mime_msg(m);
-
+ base64_mimeparts(m);
return m;
}
@@ -1394,6 +1376,40 @@ List *mms_message_headers(MmsMsg *msg)
return http_header_duplicate(msg->headers);
}
+MmsMsg *mms_readreport(Octstr *msgid, Octstr *from, Octstr *to, time_t date, Octstr *status)
+{
+
+ MmsMsg *m = gw_malloc(sizeof *m);
+ Octstr *s;
+
+
+ m->ismultipart = 0;
+ m->headers = http_create_empty_headers();
+
+ m->message_type = MMS_MSGTYPE_READ_ORIG_IND;
+ m->body.s = NULL;
+ m->msgId = octstr_duplicate(msgid ? msgid : octstr_imm("none"));
+
+ /* Now append headers. */
+
+ http_header_add(m->headers, "X-Mms-Message-Type", "m-read-orig-ind");
+ http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION);
+
+ http_header_add(m->headers, "Message-ID", msgid ? octstr_get_cstr(msgid) : "none");
+ http_header_add(m->headers, "To", octstr_get_cstr(to));
+
+ http_header_add(m->headers, "From", octstr_get_cstr(from));
+
+ s = date_format_http(date);
+ http_header_add(m->headers, "Date", octstr_get_cstr(s));
+
+ http_header_add(m->headers, "X-Mms-Status", octstr_get_cstr(status));
+
+ octstr_destroy(s);
+
+ return m;
+}
+
MmsMsg *mms_deliveryreport(Octstr *msgid, Octstr *to, time_t date, Octstr *status)
{
@@ -1406,7 +1422,7 @@ MmsMsg *mms_deliveryreport(Octstr *msgid, Octstr *to, time_t date, Octstr *statu
m->message_type = MMS_MSGTYPE_DELIVERY_IND;
m->body.s = NULL;
- m->msgId = octstr_duplicate(msgid);
+ m->msgId = octstr_duplicate(msgid ? msgid : octstr_imm("none"));
/* Now append headers. */
@@ -1607,6 +1623,16 @@ int mms_replace_header_value(MmsMsg *msg, char *hname, char *value)
return 0;
}
+int mms_add_missing_headers(MmsMsg *msg, List *headers)
+{
+ List *h = http_header_duplicate(headers);
+ http_header_combine(h, msg->headers);
+
+ http_destroy_headers(msg->headers);
+ msg->headers = h;
+ return 0;
+}
+
int mms_replace_header_values(MmsMsg *msg, char *hname, List *value)
{
int i;
@@ -1648,11 +1674,24 @@ List *mms_get_header_values(MmsMsg *msg, Octstr *header)
int mms_convert_readrec2readorig(MmsMsg *msg)
{
+
+ Octstr *s;
+
if (msg->message_type != MMS_MSGTYPE_READ_REC_IND)
return -1;
mms_replace_header_value(msg, "X-Mms-Message-Type", "m-read-orig-ind");
msg->message_type = MMS_MSGTYPE_READ_ORIG_IND;
+
+ if ((s = mms_get_header_value(msg, octstr_imm("Date"))) == NULL) {
+ time_t t = time(NULL);
+ s = date_format_http(t);
+ mms_replace_header_value(msg, "Date", octstr_get_cstr(s));
+ }
+
+ if (s)
+ octstr_destroy(s);
+
return 0;
}
diff --git a/mbuni/mmlib/mms_msg.h b/mbuni/mmlib/mms_msg.h
index 59c7bfe..2190590 100644
--- a/mbuni/mmlib/mms_msg.h
+++ b/mbuni/mmlib/mms_msg.h
@@ -55,6 +55,8 @@ extern void mms_destroy(MmsMsg *msg);
/* Make a delivery report message. */
extern MmsMsg *mms_deliveryreport(Octstr *msgid, Octstr *to, time_t date, Octstr *status);
+MmsMsg *mms_readreport(Octstr *msgid, Octstr *from, Octstr *to, time_t date, Octstr *status);
+
/* Return message headers. */
extern List *mms_message_headers(MmsMsg *msg);
@@ -75,6 +77,9 @@ List *mms_get_header_values(MmsMsg *msg, Octstr *header);
int mms_replace_header_value(MmsMsg *msg, char *hname, char *value);
int mms_replace_header_values(MmsMsg *msg, char *hname, List *values);
+/* Get headers from 'headers' that are not already in message headers and add them. */
+int mms_add_missing_headers(MmsMsg *msg, List *headers);
+
int mms_convert_readrec2readorig(MmsMsg *msg);
diff --git a/mbuni/mmlib/mms_queue.c b/mbuni/mmlib/mms_queue.c
index d6741c3..a912541 100644
--- a/mbuni/mmlib/mms_queue.c
+++ b/mbuni/mmlib/mms_queue.c
@@ -44,7 +44,7 @@ static int free_envelope(MmsEnvelope *e, int removefromqueue);
* X - Time of expiry of message
* N - Number of delivery attempts so far
* P - Proxy who sent it to us
- * V - Proxy through which this message shd be delivered (e.g. delivery report)
+ * p - Proxy through which this message shd be delivered (e.g. delivery report)
* S - Message size
* s - Message subject.
* f - time of last content fetch
@@ -52,6 +52,8 @@ static int free_envelope(MmsEnvelope *e, int removefromqueue);
* b - billed amount.
* r - whether delivery receipts are required or not.
* M - Application specific data (string)
+ * V - VASID -- from VASP
+ * v - vasid -- from VASP
*/
@@ -165,7 +167,7 @@ MmsEnvelope *mms_queue_readenvelope(char *qf, char *mms_queuedir, int shouldbloc
case 'M':
e->mdata = octstr_create(res);
break;
- case 'V':
+ case 'p':
e->viaproxy = octstr_create(res);
break;
case 'S':
@@ -187,6 +189,12 @@ MmsEnvelope *mms_queue_readenvelope(char *qf, char *mms_queuedir, int shouldbloc
case 'r':
e->dlr = 1;
break;
+ case 'V':
+ e->vaspid = octstr_create(res);
+ break;
+ case 'v':
+ e->vasid = octstr_create(res);
+ break;
case '.':
okfile = 1;
break;
@@ -320,12 +328,19 @@ static int writeenvelope(MmsEnvelope *e, int newenv)
if (e->viaproxy)
- _putline(fd, "V", octstr_get_cstr(e->viaproxy));
+ _putline(fd, "p", octstr_get_cstr(e->viaproxy));
if (e->token)
_putline(fd, "t", octstr_get_cstr(e->token));
+ if (e->vaspid)
+ _putline(fd, "V", octstr_get_cstr(e->vaspid));
+
+ if (e->vasid)
+ _putline(fd, "v", octstr_get_cstr(e->vasid));
+
+
if (e->dlr)
_putline(fd, "r", "Yes");
@@ -443,17 +458,18 @@ static int writemmsdata(Octstr *ms, char *df, char *mms_queuedir)
}
-Octstr *mms_queue_add(Octstr *from, List *to, Octstr *msgid,
+Octstr *mms_queue_add(Octstr *from, List *to,
Octstr *subject,
Octstr *fromproxy, Octstr *viaproxy,
time_t senddate, time_t expirydate, MmsMsg *m, Octstr *token,
+ Octstr *vaspid, Octstr *vasid,
int dlr,
- char *directory)
+ char *directory, Octstr *mmscname)
{
char qf[32];
int fd, i, n;
MmsEnvelope *e;
-
+ Octstr *msgid;
Octstr *ms, *res = NULL;
fd = mkqf(qf, directory);
@@ -466,7 +482,8 @@ Octstr *mms_queue_add(Octstr *from, List *to, Octstr *msgid,
res = octstr_create(qf);
ms = mms_tobinary(m); /* Convert message to string. */
-
+ msgid = mms_maketransid(octstr_get_cstr(res), mmscname);
+
e = gw_malloc(sizeof *e); /* Make envelope, clear it. */
memset(e, 0, sizeof *e);
@@ -488,14 +505,17 @@ Octstr *mms_queue_add(Octstr *from, List *to, Octstr *msgid,
e->subject = subject;
e->to = list_create();
e->msize = octstr_len(ms);
- e->msgId = msgid ? msgid : res;
+ e->msgId = msgid;
e->token = token;
+ e->vaspid = vaspid;
+ e->vasid = vasid;
+
e->dlr = dlr;
e->bill.billed = 0;
/* Insert message ID into message if it is missing. */
if (!msgid && mms_messagetype(m) == MMS_MSGTYPE_SEND_REQ)
- mms_replace_header_value(m, "Message-ID", octstr_get_cstr(res));
+ mms_replace_header_value(m, "Message-ID", octstr_get_cstr(msgid));
n = to ? list_len(to) : 0;
@@ -540,7 +560,8 @@ Octstr *mms_queue_add(Octstr *from, List *to, Octstr *msgid,
list_destroy(e->to, NULL);
gw_free(e);
octstr_destroy(ms);
-
+ octstr_destroy(msgid);
+
return res;
}
@@ -617,6 +638,39 @@ int mms_queue_update(MmsEnvelope *e)
return writeenvelope(e, 0);
}
+int mms_queue_replacedata(MmsEnvelope *e, MmsMsg *m)
+{
+ Octstr *tfname;
+ Octstr *ms;
+ int ret = 0;
+
+ if (!e) return -1;
+
+ tfname = octstr_format(".%c%s.%ld.%d", MDF, e->qf.name + 1, time(NULL), random());
+
+ ms = mms_tobinary(m);
+
+ if (writemmsdata(ms, octstr_get_cstr(tfname), e->qf.dir) < 0)
+ ret = -1;
+ else {
+ Octstr *fname = octstr_format("%s/%c%s", e->qf.dir, MDF, e->qf.name + 1);
+ Octstr *tmpf = octstr_format("%s/%S", e->qf.dir, tfname);
+ if (rename(octstr_get_cstr(tmpf), octstr_get_cstr(fname)) < 0) {
+ error(0, "mms_replacedata: Failed to write data file %s: error = %s\n",
+ octstr_get_cstr(tmpf), strerror(errno));
+ ret = -1;
+ unlink(octstr_get_cstr(tmpf)); /* remove it. */
+ }
+
+ octstr_destroy(fname);
+ octstr_destroy(tmpf);
+ }
+ octstr_destroy(ms);
+
+ octstr_destroy(tfname);
+ return ret;
+}
+
MmsMsg *mms_queue_getdata(MmsEnvelope *e)
{
Octstr *fname;
diff --git a/mbuni/mmlib/mms_queue.h b/mbuni/mmlib/mms_queue.h
index cad4479..d41993d 100644
--- a/mbuni/mmlib/mms_queue.h
+++ b/mbuni/mmlib/mms_queue.h
@@ -32,6 +32,9 @@ typedef struct MmsEnvelope {
Octstr *msgId; /* message id (for reference). */
Octstr *token; /* User level token, may be null. */
Octstr *from; /* from address. */
+
+ Octstr *vaspid; /* VASPID (if any) */
+ Octstr *vasid; /* VASID (if any) */
List *to; /* List of recipients: MmsEnvelopeTo */
@@ -71,12 +74,13 @@ typedef struct MmsEnvelope {
* 'to' is a list of Octstr * *.
* Returns a queue file name.
*/
-extern Octstr *mms_queue_add(Octstr *from, List *to, Octstr *msgid,
+extern Octstr *mms_queue_add(Octstr *from, List *to,
Octstr *subject,
Octstr *fromproxy, Octstr *viaproxy,
time_t senddate, time_t expirydate, MmsMsg *m, Octstr *token,
+ Octstr *vaspid, Octstr *vasid,
int dlr,
- char *directory);
+ char *directory, Octstr *mmscname);
/*
* Update queue status. Returns -1 on error, 0 if queue is updated fine and
@@ -89,6 +93,9 @@ extern int mms_queue_update(MmsEnvelope *e);
*/
extern MmsMsg *mms_queue_getdata(MmsEnvelope *e);
+/* Replace data for this queue item -- used by mm7 interface. */
+int mms_queue_replacedata(MmsEnvelope *e, MmsMsg *m);
+
/*
* Reads queue, returns up to lim queue entries that are ready for processing. send 0 for no limit.
*/
diff --git a/mbuni/mmlib/mms_strings.def b/mbuni/mmlib/mms_strings.def
index e7aa19e..66c3a5b 100644
--- a/mbuni/mmlib/mms_strings.def
+++ b/mbuni/mmlib/mms_strings.def
@@ -242,7 +242,7 @@ ASSIGN("Error-permanent-mmbox-full",228)
NUMBERED(descriptor_params,
ASSIGN("type", 130)
)
-
+/* MM7/SOAP stuff -- *** order of these matters wrt Req/Rsp *** */
NAMED(mm7tag,
VNSTRING(MM7_5, "Bcc",MM7_TAG_Bcc)
VNSTRING(MM7_5, "CancelReq",MM7_TAG_CancelReq)
@@ -296,6 +296,7 @@ VNSTRING(MM7_5, "VASID",MM7_TAG_VASID)
VNSTRING(MM7_5, "VASPErrorRsp",MM7_TAG_VASPErrorRsp)
VNSTRING(MM7_5, "VASPID",MM7_TAG_VASPID)
VNSTRING(MM7_5, "Fault",MM7_TAG_Fault)
+VNSTRING(MM7_5, "Details",MM7_TAG_Details)
VNSTRING(MM7_5, "faultcode",MM7_TAG_faultcode)
VNSTRING(MM7_5, "faultstring",MM7_TAG_faultstring)
VNSTRING(MM7_5, "MessageType",MM7_TAG_MessageType)
@@ -303,6 +304,30 @@ VNSTRING(MM7_5, "replyChargingSize", MM7_TAG_replyChargingSize)
VNSTRING(MM7_5, "replyDeadline", MM7_TAG_replyDeadline)
)
+NUMBERED(soap_status,
+ASSIGN("Success", 1000)
+ASSIGN("Partial success", 1100)
+ASSIGN("Client error", 2000)
+ASSIGN("Operation restricted", 2001)
+ASSIGN("Address Error", 2002)
+ASSIGN("Address Not Found", 2003)
+ASSIGN("Multimedia content refused", 2004)
+ASSIGN("Message ID Not found", 2005)
+ASSIGN("LinkedID not found", 2006)
+ASSIGN("Message format corrupt", 2007)
+ASSIGN("Server Error", 3000)
+ASSIGN("Not Possible", 3001)
+ASSIGN("Message rejected", 3002)
+ASSIGN("Multiple addresses not supported", 3003)
+ASSIGN("General service error", 4000)
+ASSIGN("Improper identification", 4001)
+ASSIGN("Unsupported version", 4002)
+ASSIGN("Unsupported operation", 4003)
+ASSIGN("Validation error", 4004)
+ASSIGN("Service error", 4005)
+ASSIGN("Service unavailable", 4006)
+ASSIGN("Service denied", 4007)
+)
#undef LINEAR
#undef STRING
#undef VSTRING
diff --git a/mbuni/mmlib/mms_util.c b/mbuni/mmlib/mms_util.c
index 4d92284..85757a3 100644
--- a/mbuni/mmlib/mms_util.c
+++ b/mbuni/mmlib/mms_util.c
@@ -80,6 +80,7 @@ MmsBoxSettings *mms_load_mmsbox_settings(Cfg *cfg)
MmsBoxSettings *m = gw_malloc(sizeof *m);
long port = -1;
Octstr *user, *pass, *from;
+ int i, n;
memset(m, 0, sizeof *m);
@@ -100,7 +101,7 @@ MmsBoxSettings *mms_load_mmsbox_settings(Cfg *cfg)
m->hostname = cfg_getx(grp, octstr_imm("hostname"));
if (m->hostname == NULL || octstr_len(m->hostname) == 0)
- m->hostname = octstr_create("localhost");
+ m->hostname = octstr_create("localhost");
m->name = cfg_getx(grp, octstr_imm("name"));
m->host_alias = cfg_getx(grp, octstr_imm("host-alias"));
@@ -157,6 +158,9 @@ MmsBoxSettings *mms_load_mmsbox_settings(Cfg *cfg)
m->port = (port > 0) ? port : MMS_PORT;
+ m->mm7port = -1;
+ cfg_get_integer(&m->mm7port, grp, octstr_imm("mm7-port"));
+
m->allow_ip = cfg_getx(grp, octstr_imm("allow-ip"));
m->deny_ip = cfg_getx(grp, octstr_imm("deny-ip"));
@@ -236,6 +240,40 @@ MmsBoxSettings *mms_load_mmsbox_settings(Cfg *cfg)
if (mmbox_root_init(octstr_get_cstr(m->mmbox_rootdir)) != 0)
warning(0, "Failed to initialise mmbox root directory, error: %s!",
strerror(errno));
+
+
+ /* Now load the VASP list. */
+ l = cfg_get_multi_group(cfg, octstr_imm("mms-vasp"));
+ m->vasp_list = list_create();
+ for (i=0, n=list_len(l); iid = cfg_getx(grp, octstr_imm("vasp-id"));
+ mv->short_code = -1;
+ cfg_get_integer(&mv->short_code, grp, octstr_imm("short-code"));
+
+ mv->vasp_username = cfg_getx(grp, octstr_imm("vasp-username"));
+ mv->vasp_password = cfg_getx(grp, octstr_imm("vasp-password"));
+
+ mv->vasp_url = cfg_getx(grp, octstr_imm("vasp-url"));
+
+ mv->mmsc_username = cfg_getx(grp, octstr_imm("mmsc-username"));
+ mv->mmsc_password = cfg_getx(grp, octstr_imm("mmsc-password"));
+
+ s = cfg_getx(grp, octstr_imm("type"));
+
+ if (octstr_case_compare(s, octstr_imm("soap")) == 0)
+ mv->type = SOAP_VASP;
+ else if (octstr_case_compare(s, octstr_imm("eaif")) == 0)
+ mv->type = EAIF_VASP;
+ else
+ mv->type = NONE_VASP;
+ octstr_destroy(s);
+
+ list_append(m->vasp_list, mv);
+ }
+ list_destroy(l, NULL);
return m;
}
@@ -428,7 +466,8 @@ Octstr *mms_maketransid(char *qf, Octstr *mmscname)
extern Octstr *mms_getqf_fromtransid(Octstr *transid)
{
int i = octstr_search_char(transid, '@', 0);
- return octstr_copy(transid, 0, i);
+
+ return (i >= 0) ? octstr_copy(transid, 0, i) : octstr_duplicate(transid);
}
Octstr *mms_isodate(time_t t)
@@ -1051,3 +1090,25 @@ int mm_lockfile(int fd, char *fname, int shouldblock)
return ret;
return 0;
}
+
+MIMEEntity *mime_entity_duplicate(MIMEEntity *m)
+{
+ MIMEEntity *mx = gw_malloc(sizeof *mx);
+
+ mx->headers = http_header_duplicate(m->headers);
+ if (m->multiparts && list_len(m->multiparts) > 0) {
+ int i, n;
+ mx->multiparts = list_create();
+ for (i = 0, n = list_len(m->multiparts); i < n; i++) {
+ MIMEEntity *x = mime_entity_duplicate(list_get(m->multiparts, i));
+ list_append(mx->multiparts, x);
+ }
+ mx->body = NULL;
+ } else {
+ mx->body = m->body ? octstr_duplicate(m->body) : NULL;
+ mx->multiparts = NULL;
+ }
+ mx->start = NULL;
+
+ return mx;
+}
diff --git a/mbuni/mmlib/mms_util.h b/mbuni/mmlib/mms_util.h
index cb7b375..71d5fea 100644
--- a/mbuni/mmlib/mms_util.h
+++ b/mbuni/mmlib/mms_util.h
@@ -33,7 +33,7 @@
/* Useful headers. */
#define XMSISDN_HEADER "X-WAP-Network-Client-MSISDN"
#define XIP_HEADER "X-WAP-Network-Client-IP"
-#define MM_NAME "DS_MM"
+#define MM_NAME "Mbuni"
typedef struct MmsProxyRelay {
Octstr *host;
@@ -42,6 +42,15 @@ typedef struct MmsProxyRelay {
Octstr *denied_prefix;
} MmsProxyRelay;
+typedef struct MmsVasp {
+ Octstr *id;
+ long short_code;
+ enum {SOAP_VASP, EAIF_VASP, NONE_VASP} type;
+ Octstr *vasp_username, *vasp_password;
+ Octstr *vasp_url;
+ Octstr *mmsc_username, *mmsc_password;
+} MmsVasp;
+
typedef struct MmsBoxSettings {
Octstr *system_user;
Octstr *name, *hostname, *host_alias;
@@ -59,7 +68,7 @@ typedef struct MmsBoxSettings {
double queue_interval;
long send_back_off;
- long port;
+ long port, mm7port;
Octstr *allow_ip;
Octstr *deny_ip;
@@ -98,6 +107,8 @@ typedef struct MmsBoxSettings {
Octstr *mms_email_html;
Octstr *wap_gw_msisdn_header;
Octstr *wap_gw_ip_header;
+
+ List *vasp_list; /* of MmsVasp * */
} MmsBoxSettings;
/* Global variables and shared code used by all modules. */
@@ -187,4 +198,6 @@ void mms_log2(char *logmsg, Octstr *from, Octstr *to,
*/
int mm_lockfile(int fd, char *fname, int shouldblock);
+/* This should be elsewhere, but it isn't, so we do it here... */
+extern MIMEEntity *mime_entity_duplicate(MIMEEntity *m);
#endif
diff --git a/mbuni/mmsc/mmsfromemail.c b/mbuni/mmsc/mmsfromemail.c
index ae282c9..ee8c1f9 100644
--- a/mbuni/mmsc/mmsfromemail.c
+++ b/mbuni/mmsc/mmsfromemail.c
@@ -159,9 +159,12 @@ int main(int argc, char *argv[])
else
dlr = 0;
- qf = mms_queue_add(xfrom, lto, msgid, NULL, xproxy, NULL,
- 0, time(NULL) + settings->default_msgexpiry, msg, NULL, dlr,
- octstr_get_cstr(settings->global_queuedir));
+ qf = mms_queue_add(xfrom, lto, NULL, xproxy, NULL,
+ 0, time(NULL) + settings->default_msgexpiry, msg, NULL,
+ NULL, NULL,
+ dlr,
+ octstr_get_cstr(settings->global_queuedir),
+ settings->host_alias);
if (qf) {
info(0, "Email2MMS Queued message to %s from %s (via %s) => %s",
@@ -184,11 +187,14 @@ int main(int argc, char *argv[])
xlto = list_create();
list_append(xlto, rto);
- qf = mms_queue_add(settings->system_user, xlto, msgid, NULL,
+ qf = mms_queue_add(settings->system_user, xlto, NULL,
xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry,
- mresp, NULL, 0,
- octstr_get_cstr(settings->global_queuedir));
+ mresp, NULL,
+ NULL, NULL,
+ 0,
+ octstr_get_cstr(settings->global_queuedir),
+ settings->host_alias);
list_destroy(xlto, (list_item_destructor_t *)octstr_destroy);
mms_destroy(mresp);
@@ -248,14 +254,17 @@ int main(int argc, char *argv[])
} else {
List *lto = list_create();
Octstr *qf;
- Octstr *msgid = mms_get_header_value(msg, octstr_imm("Message-ID"));
+
octstr_format_append(xto, "/TYPE=PLMN");
list_append(lto, xto);
- qf = mms_queue_add(xfrom, lto, msgid, NULL,
+ qf = mms_queue_add(xfrom, lto, NULL,
xproxy, NULL,
- 0, time(NULL) + settings->default_msgexpiry, msg, NULL, 0,
- octstr_get_cstr(settings->global_queuedir));
+ 0, time(NULL) + settings->default_msgexpiry, msg, NULL,
+ NULL, NULL,
+ 0,
+ octstr_get_cstr(settings->global_queuedir),
+ settings->host_alias);
list_destroy(lto, NULL);
if (qf) {
info(0, "Email2MMS Queued DLR from proxy %s to %s from %s => %s",
@@ -265,7 +274,6 @@ int main(int argc, char *argv[])
octstr_destroy(qf);
}
- octstr_destroy(msgid);
list_destroy(lto, NULL);
}
break;
@@ -283,14 +291,16 @@ int main(int argc, char *argv[])
} else {
List *lto = list_create();
Octstr *qf;
- Octstr *msgid = mms_get_header_value(msg, octstr_imm("Message-ID"));
octstr_format_append(xto, "/TYPE=PLMN");
list_append(lto, xto);
- qf = mms_queue_add(xfrom, lto, msgid, NULL,
+ qf = mms_queue_add(xfrom, lto, NULL,
xproxy, NULL,
- 0, time(NULL) + settings->default_msgexpiry, msg, NULL,0,
- octstr_get_cstr(settings->global_queuedir));
+ 0, time(NULL) + settings->default_msgexpiry, msg, NULL,
+ NULL, NULL,
+ 0,
+ octstr_get_cstr(settings->global_queuedir),
+ settings->host_alias);
list_destroy(lto, NULL);
if (qf) {
info(0, "Email2MMS Queued read report from proxy %s to %s from %s => %s",
@@ -300,7 +310,7 @@ int main(int argc, char *argv[])
octstr_destroy(qf);
}
- octstr_destroy(msgid);
+
list_destroy(lto, NULL);
}
default:
diff --git a/mbuni/mmsc/mmsglobalsender.c b/mbuni/mmsc/mmsglobalsender.c
index 2dcf6e5..ee90f2c 100644
--- a/mbuni/mmsc/mmsglobalsender.c
+++ b/mbuni/mmsc/mmsglobalsender.c
@@ -17,6 +17,7 @@
#include "mms_queue.h"
#include "mms_uaprof.h"
#include "mms_util.h"
+#include "mms_mm7soap.h"
#define NMAX 256
static char mobile_qdir[NMAX];
@@ -54,6 +55,10 @@ static int mms_sendtoproxy(Octstr *from, Octstr *to,
Octstr *subject, Octstr *proxy,
Octstr *msgid, time_t expires, MmsMsg *m, int dlr, Octstr **error);
+static int mms_sendtovasp(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
+ MmsMsg *m, Octstr **error);
+
+static int _x_octstr_int_compare(int n, Octstr *s);
/* Send errors */
#define MMS_SEND_OK 0
#define MMS_SEND_ERROR_TRANSIENT -1
@@ -146,7 +151,11 @@ static int sendMsg(MmsEnvelope *e)
goto done;
}
- /* first check if it is an email address */
+ /* - first check if it is an email address.
+ * - Next check if proxy to send through is already set, use it.
+ * - else we have a number of IP, try to deliver...
+ */
+
if (octstr_search_char(to->rcpt, '@', 0) > 0) {
res = mms_sendtoemail(e->from, to->rcpt,
e->subject,
@@ -156,7 +165,7 @@ static int sendMsg(MmsEnvelope *e)
mms_log2("Sent", e->from, to->rcpt,
-1, e->msgId, NULL, NULL, "MM3", NULL,NULL);
- } else if (e->viaproxy && octstr_len(e->viaproxy) > 0) /* If proxy to send through is already set, use it. */
+ } else if (e->viaproxy && octstr_len(e->viaproxy) > 0)
res = mms_sendtoproxy(e->from,
to->rcpt, e->subject, e->viaproxy,
e->msgId, e->expiryt, msg, e->dlr, &err);
@@ -167,8 +176,10 @@ static int sendMsg(MmsEnvelope *e)
Octstr *phonenum = NULL;
Octstr *mmsc;
int sent = 0;
-
- if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len) /* A proper number. */
+ MmsVasp *vasp;
+
+ /* If it is an IP, send to mobile handler, else if number, look for recipient. */
+ if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
phonenum = octstr_copy(to->rcpt, 0, j);
else if (k > 0 && k + sizeof "/TYPE=IPv" == len) {
res = mms_sendtomobile(e->from,
@@ -184,11 +195,12 @@ static int sendMsg(MmsEnvelope *e)
goto done;
}
- /* Normalise the number, then match against local prefixes. */
+ /* Normalise the number, then see if we can resolve home MMSC for this recipient. */
normalize_number(octstr_get_cstr(settings->unified_prefix), &phonenum);
if ((mmsc = settings->mms_resolvefuncs->mms_resolve(phonenum,
- settings->mms_resolver_module_data, settings, proxyrelays))) {
+ settings->mms_resolver_module_data,
+ settings, proxyrelays))) {
info(0, "mmsc for \"%s\" resolved to: \"%s\"",
octstr_get_cstr(phonenum), octstr_get_cstr(mmsc));
@@ -199,8 +211,7 @@ static int sendMsg(MmsEnvelope *e)
e->msgId, e->expiryt, msg, e->dlr,
&err);
sent = 1;
- } else if (proxyrelays && list_len(proxyrelays) > 0)
- /* Step through proxies. */
+ } else if (proxyrelays && list_len(proxyrelays) > 0) /* Step through proxies. */
for (j = 0, m = list_len(proxyrelays); jvasp_list); j < m; j++)
+ if ((vasp = list_get(settings->vasp_list, j)) != NULL &&
+ _x_octstr_int_compare(vasp->short_code, phonenum) == 0) {
+ res = mms_sendtovasp(vasp, e->from, to->rcpt,
+ e->msgId,
+ msg, &err);
+ sent = 1;
+ break;
+ }
+
if (!sent) {
res = MMS_SEND_ERROR_FATAL;
err = octstr_format("MMSC error: Don't know how to deliver to %S !", to->rcpt);
@@ -228,7 +249,7 @@ static int sendMsg(MmsEnvelope *e)
else { /* If there was a report request, queue it. */
if (e->dlr) {
-
+ Octstr *qfs;
MmsMsg *m = mms_deliveryreport(e->msgId, to->rcpt, tnow,
(e->expiryt != 0 && e->expiryt < tnow) ?
octstr_imm("Expired") : octstr_imm("Rejected"));
@@ -239,9 +260,14 @@ static int sendMsg(MmsEnvelope *e)
list_append(l, octstr_duplicate(e->from));
/* Add to queue, switch via proxy to be from proxy. */
- mms_queue_add(settings->system_user, l, e->msgId, err, NULL, e->fromproxy,
- tnow, tnow+settings->default_msgexpiry, m, NULL, 0,
- qdir);
+ qfs = mms_queue_add(settings->system_user, l,
+ err, NULL, e->fromproxy,
+ tnow, tnow+settings->default_msgexpiry, m, NULL,
+ NULL, NULL,
+ 0,
+ qdir,
+ settings->host_alias);
+ octstr_destroy(qfs);
list_destroy(l, NULL);
mms_destroy(m);
@@ -432,8 +458,10 @@ int mms_sendtomobile(Octstr *from, Octstr *to,
x = octstr_create(tokenstr);
- ret = mms_queue_add(from, l, msgid, subject, fromproxy, NULL, 0, expires, m,
- x, dlr, mobile_qdir);
+ ret = mms_queue_add(from, l, subject, fromproxy, NULL, 0, expires, m,
+ x, NULL, NULL,
+ dlr, mobile_qdir,
+ settings->host_alias);
octstr_destroy(x);
list_destroy(l, NULL);
@@ -470,7 +498,10 @@ static int mms_sendtoproxy(Octstr *from, Octstr *to,
List *l = list_create();
Octstr *ret;
list_append(l, to);
- ret = mms_queue_add(from, l, msgid, subject, NULL, proxy, 0, expires, msg,NULL, dlr, mm4_qdir);
+ ret = mms_queue_add(from, l, subject, NULL, proxy, 0, expires, msg,NULL,
+ NULL, NULL,
+ dlr, mm4_qdir,
+ settings->host_alias);
list_destroy(l, NULL);
if (ret == NULL) {
@@ -495,3 +526,116 @@ static int mms_sendtoproxy(Octstr *from, Octstr *to,
return x;
}
+
+static int _x_octstr_int_compare(int n, Octstr *s)
+{
+ char x[64];
+
+ sprintf(x, "%d", n);
+ return octstr_str_compare(s,x);
+}
+
+static int mms_sendtovasp(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
+ MmsMsg *m, Octstr **error)
+{
+ int ret = MMS_SEND_ERROR_TRANSIENT;
+ int mtype = mms_messagetype(m);
+
+ info(0, "MMS Relay: Send to VASP[%s], msg type [%s], from %s, to %s",
+ vasp ? octstr_get_cstr(vasp->id) : "",
+ mms_message_type_to_cstr(mtype), octstr_get_cstr(from), octstr_get_cstr(to));
+
+ if (vasp->type == SOAP_VASP) {
+ int hstatus = HTTP_OK, tstatus;
+ List *xto = list_create();
+ MSoapMsg_t *mreq = NULL, *mresp = NULL;
+ List *rh = NULL, *ph = NULL;
+ Octstr *body = NULL, *rbody = NULL, *url = NULL;
+ HTTPCaller *caller = http_caller_create();
+ void *xx;
+ Octstr *s;
+
+ list_append(xto, to);
+
+
+ if ((mreq = mm7_mmsmsg_to_soap(m, from, xto, msgId, settings->host_alias)) == NULL) {
+ *error = octstr_format("Failed to convert Msg[%s] 2 SOAP message!",
+ mms_message_type_to_cstr(mtype));
+ goto done1;
+ }
+
+ if (mm7_soapmsg_to_httpmsg(mreq, &rh, &body) < 0) {
+ *error = octstr_format("Failed to convert SOAP message 2 HTTP Msg!");
+ goto done1;
+ }
+
+ if (vasp->mmsc_username)
+ http_add_basic_auth(rh, vasp->mmsc_username,
+ vasp->mmsc_password ? vasp->mmsc_password : octstr_imm(""));
+
+ http_start_request(caller, HTTP_METHOD_POST, vasp->vasp_url, rh, body, 1, NULL, NULL);
+
+ if ((xx = http_receive_result(caller, &hstatus, &url, &ph, &rbody)) == NULL ||
+ hstatus != HTTP_OK) {
+ *error = octstr_format("Failed to contact VASP[url=%s] => HTTP returned status = %d, id=%s !",
+ octstr_get_cstr(vasp->vasp_url), hstatus, xx ? "Ok" : "not OK");
+ goto done1;
+ }
+
+ if ((mresp = mm7_parse_soap(ph, rbody)) == NULL) {
+ *error = octstr_format("Failed to parse VASP[url=%s, id=%s] response!",
+ octstr_get_cstr(vasp->vasp_url),
+ octstr_get_cstr(vasp->id));
+ goto done1;
+ }
+
+ /* Now look at response code and use it to tell you what you want. */
+ if ((s = mm7_soap_header_value(mresp, octstr_imm("StatusCode"))) != NULL) {
+ tstatus = atoi(octstr_get_cstr(s));
+ octstr_destroy(s);
+ } else
+ tstatus = MM7_SOAP_FORMAT_CORRUPT;
+
+ if (!MM7_SOAP_STATUS_OK(tstatus)) {
+ Octstr *detail = mm7_soap_header_value(mresp, octstr_imm("Details"));
+ ret = MMS_SEND_ERROR_FATAL;
+ info(0, "Send to VASP[%s], failed, code=[%d=>%s], detail=%s",
+ vasp ? octstr_get_cstr(vasp->id) : "",
+ tstatus, mms_soap_status_to_cstr(tstatus),
+ detail ? octstr_get_cstr(detail) : "");
+ *error = octstr_format("Failed to deliver to VASP[url=%s, id=%s], status=[%d=>%s]!",
+ octstr_get_cstr(vasp->vasp_url),
+ octstr_get_cstr(vasp->id),
+ tstatus, mms_soap_status_to_cstr(tstatus));
+
+ if (detail)
+ octstr_destroy(detail);
+
+ } else
+ ret = MMS_SEND_OK;
+
+ info(0, "Sent to VASP[%s], code=[%d=>%s]", octstr_get_cstr(vasp->id),
+ tstatus, mms_soap_status_to_cstr(tstatus));
+ done1:
+
+ if (mreq)
+ mm7_soap_destroy(mreq);
+ if (mresp)
+ mm7_soap_destroy(mresp);
+ if (rh)
+ http_destroy_headers(rh);
+ if (body)
+ octstr_destroy(body);
+ if (ph)
+ http_destroy_headers(ph);
+ if (rbody)
+ octstr_destroy(rbody);
+ if (url)
+ octstr_destroy(url);
+ http_caller_destroy(caller);
+ list_destroy(xto, NULL);
+ } /* else if EAIF, etc.. */
+
+
+ return ret;
+}
diff --git a/mbuni/mmsc/mmsmobilesender.c b/mbuni/mmsc/mmsmobilesender.c
index 415cc42..dbb4ee6 100644
--- a/mbuni/mmsc/mmsmobilesender.c
+++ b/mbuni/mmsc/mmsmobilesender.c
@@ -206,7 +206,7 @@ static int receive_push_reply(HTTPCaller *caller)
mms_log2("Notify", octstr_imm("system"), to,
-1, env ? env->msgId : NULL, NULL, NULL, "MM1", NULL,NULL);
- if (update_env_success(env, xto) != NULL)
+ if ((env = update_env_success(env, xto)) != NULL)
goto push_free_env;
/* Fall through. */
@@ -411,10 +411,13 @@ static int sendNotify(MmsEnvelope *e)
list_append(l, from);
/* Add to queue, switch via proxy to be from proxy. */
- res = mms_queue_add(settings->system_user, l, msgId, err,
+ res = mms_queue_add(settings->system_user, l, err,
NULL, fromproxy,
- tnow, tnow+settings->default_msgexpiry, m, NULL, 0,
- octstr_get_cstr(settings->mm1_queuedir));
+ tnow, tnow+settings->default_msgexpiry, m, NULL,
+ NULL, NULL,
+ 0,
+ octstr_get_cstr(settings->mm1_queuedir),
+ settings->host_alias);
list_destroy(l, NULL);
mms_destroy(m);
octstr_destroy(res);
diff --git a/mbuni/mmsc/mmsproxy.c b/mbuni/mmsc/mmsproxy.c
index 0ad78df..82eada1 100644
--- a/mbuni/mmsc/mmsproxy.c
+++ b/mbuni/mmsc/mmsproxy.c
@@ -20,6 +20,7 @@
#include "mms_uaprof.h"
#include "mms_util.h"
+#include "mms_mm7soap.h"
static Cfg *cfg;
static List *proxyrelays;
@@ -44,11 +45,13 @@ typedef struct MmsHTTPClientInfo {
MmsUaProfile *prof;
Octstr *base_client_addr;
Octstr *client_addr;
+ MmsVasp *vasp;
} MmsHTTPClientInfo;
static void fetchmms_proxy(MmsHTTPClientInfo *h);
static void sendmms_proxy(MmsHTTPClientInfo *h);
+static void mm7proxy(void *unused);
int main(int argc, char *argv[])
{
int cfidx;
@@ -56,9 +59,11 @@ int main(int argc, char *argv[])
CfgGroup *grp;
Octstr *log, *alog;
long loglevel;
-
+
MmsHTTPClientInfo h;
+ long mm7_thread = -1;
+
mms_lib_init();
srandom(time(NULL));
@@ -111,14 +116,22 @@ int main(int argc, char *argv[])
/* Start cache engine. */
mms_start_profile_engine(octstr_get_cstr(settings->ua_profile_cache_dir));
+ /* If we have mm7 port, start thread for it. */
/* Now open port and start dispatching requests. */
if (http_open_port(settings->port, 0) < 0) {
error(0, "MMS Proxy: Failed to start http server: %d => %s!",
errno, strerror(errno));
- return -1;
+ goto done;
}
+ if (settings->mm7port > 0 &&
+ http_open_port(settings->mm7port, 0) >= 0)
+ mm7_thread = gwthread_create((gwthread_func_t *)mm7proxy, NULL);
+ else
+ warning(0, "MMS Proxy: MM7 interface not open, port=%ld",
+ settings->mm7port);
+
while(rstop == 0 && (h.client = http_accept_request(settings->port,
&h.ip, &h.url, &h.headers,
&h.body, &h.cgivars)) != NULL)
@@ -126,6 +139,8 @@ int main(int argc, char *argv[])
MmsHTTPClientInfo *hx = gw_malloc(sizeof *hx);
Octstr *profile_url;
+ memset(hx, 0, sizeof *hx);
+
h.ua = http_header_value(h.headers, octstr_imm("User-Agent"));
/* Get the profile URL and store it. Has effect of fetching if missing. */
@@ -209,10 +224,14 @@ int main(int argc, char *argv[])
http_close_client(h.client);
}
- debug("proxy", 0, "Shutdown requested");
+ done:
+ debug("proxy", 0, "MM1 Shutting down...");
+ if (mm7_thread >= 0)
+ gwthread_join(mm7_thread);
+ debug("proxy", 0, "Closed mm7 thread");
http_close_all_ports();
debug("proxy", 0, "Port closed");
- sleep(2); /* Give them time to shut down. */
+ sleep(2); /* Give them time to shut down. */
mms_stop_profile_engine();
sleep(2); /* Give them time to shut down. */
return 0;
@@ -556,9 +575,6 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
mms_remove_headers(m, "X-Mms-Store");
- msgid = mms_maketransid(NULL, settings->host_alias);
- mms_replace_header_value(m, "Message-ID", octstr_get_cstr(msgid)); /* Put in message id -- for later. */
-
if (menc >= MS_1_2 &&
x != NULL &&
@@ -596,15 +612,19 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
dlr = 0;
- qf = mms_queue_add(from, to, msgid, subject,
- NULL, NULL, deliveryt, expiryt, m, NULL, dlr,
- octstr_get_cstr(settings->global_queuedir));
+ qf = mms_queue_add(from, to, subject,
+ NULL, NULL, deliveryt, expiryt, m, NULL,
+ NULL, NULL,
+ dlr,
+ octstr_get_cstr(settings->global_queuedir),
+ settings->host_alias);
if (!qf)
mresp = mms_sendconf("Error-transient-failure", "None", octstr_get_cstr(otransid),0,
menc);
else {
-
+ msgid = mms_maketransid(octstr_get_cstr(qf),
+ settings->host_alias);
mresp = mms_sendconf("Ok", octstr_get_cstr(msgid), octstr_get_cstr(otransid),0,
menc);
@@ -731,7 +751,7 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
Octstr *pmsgid = mms_get_header_value(mfwd, octstr_imm("Message-ID"));
Octstr *pdelivery_report = mms_get_header_value(mfwd,
octstr_imm("X-Mms-Delivery-Report"));
- Octstr *msgid = mms_maketransid(NULL, settings->host_alias);
+ Octstr *msgid = NULL;
Octstr *s;
Octstr *qf2;
int n = 0;
@@ -744,7 +764,6 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
/* Modify the message before sending on as per spec. */
mms_replace_header_value(mfwd, "From", octstr_get_cstr(from));
- mms_replace_header_value(mfwd, "Message-ID", octstr_get_cstr(msgid)); /* Put in message id -- for later. */
mms_remove_headers(mfwd, "X-Mms-Read-Report");
if (read_report)
@@ -783,10 +802,12 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
else
dlr = 0;
/* Message to forward is now ready, write it to queue. */
- qf2 = mms_queue_add(from, to, msgid, subject,
- NULL, NULL, deliveryt, expiryt, mfwd, NULL,
- dlr,
- octstr_get_cstr(settings->global_queuedir));
+ qf2 = mms_queue_add(from, to, subject,
+ NULL, NULL, deliveryt, expiryt, mfwd, NULL,
+ NULL, NULL,
+ dlr,
+ octstr_get_cstr(settings->global_queuedir),
+ settings->host_alias);
/* Process any requests for writing to mmbox. */
x = mms_get_header_value(m, octstr_imm("X-Mms-Store"));
@@ -832,6 +853,7 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
mresp = mms_sendconf("Error-transient-failure",
"None", octstr_get_cstr(otransid),1,menc);
else {
+ msgid = mms_maketransid(octstr_get_cstr(qf2), settings->host_alias);
mresp = mms_sendconf("Ok",
octstr_get_cstr(msgid),
octstr_get_cstr(otransid),1,menc);
@@ -866,10 +888,13 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
List *l = list_create();
list_append(l, pfrom);
- x = mms_queue_add(settings->system_user, l, NULL, NULL, NULL, NULL, 0,
+ x = mms_queue_add(settings->system_user, l, NULL, NULL, NULL, 0,
time(NULL) + settings->default_msgexpiry,
- mrep, NULL,0,
- octstr_get_cstr(settings->global_queuedir));
+ mrep, NULL,
+ NULL, NULL,
+ 0,
+ octstr_get_cstr(settings->global_queuedir),
+ settings->host_alias);
octstr_destroy(x);
list_destroy(l, NULL);
@@ -983,9 +1008,12 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
mrpt = mms_deliveryreport(e->msgId, h->client_addr, time(NULL), status);
list_append(l, octstr_duplicate(e->from));
- x = mms_queue_add(settings->system_user, l, NULL, NULL, NULL, NULL, 0,
- time(NULL) + settings->default_msgexpiry, mrpt, NULL, 0,
- octstr_get_cstr(settings->global_queuedir));
+ x = mms_queue_add(settings->system_user, l, NULL, NULL, NULL, 0,
+ time(NULL) + settings->default_msgexpiry, mrpt, NULL,
+ NULL, NULL,
+ 0,
+ octstr_get_cstr(settings->global_queuedir),
+ settings->host_alias);
octstr_destroy(x);
list_destroy(l, (list_item_destructor_t *)octstr_destroy);
@@ -1030,9 +1058,12 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
collect_senddata(mh, &to, NULL, NULL, NULL, NULL);
- x = mms_queue_add(from, to, NULL, NULL, NULL,
- NULL, time(NULL), time(NULL) + settings->default_msgexpiry,
- m, NULL, 0, octstr_get_cstr(settings->global_queuedir));
+ x = mms_queue_add(from, to, NULL, NULL, NULL, time(NULL),
+ time(NULL) + settings->default_msgexpiry,
+ m, NULL, 0,
+ NULL, NULL,
+ octstr_get_cstr(settings->global_queuedir),
+ settings->host_alias);
/* Log to access log */
mms_log("ReadReport", h->client_addr, NULL, msize, NULL, NULL, NULL, "MM1", h->ua,NULL);
@@ -1549,3 +1580,324 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
gw_free(h);
}
+
+/* Find sender credentials: only auth-basic supported for now. */
+static MmsVasp *find_mm7sender(List *headers, List *vasps)
+{
+ Octstr *v = http_header_value(headers, octstr_imm("Authorization"));
+ Octstr *p = NULL, *q = NULL;
+ MmsVasp *m = NULL;
+ int i, n;
+
+#if 0
+ return list_get(vasps,0); /* XXX for testing... */
+#endif
+ if (!v ||
+ octstr_search(v, octstr_imm("Basic "), 0) != 0)
+ goto done;
+ p = octstr_copy(v, sizeof "Basic", octstr_len(v));
+ octstr_base64_to_binary(p);
+
+ i = octstr_search_char(p, ':', 0);
+ q = octstr_copy(p, i+1, octstr_len(p));
+ octstr_delete(p, i, octstr_len(p));
+
+ /* p = user, q = pass. */
+ for (i = 0, n = list_len(vasps); ivasp_username, p) == 0 &&
+ octstr_compare(x->vasp_password, q) == 0) {
+ m = x;
+ break;
+ }
+ }
+
+ /* if it can't authenticate, returns NULL. */
+
+ done:
+ if (v)
+ octstr_destroy(v);
+ if (p)
+ octstr_destroy(p);
+ if (q)
+ octstr_destroy(q);
+ return m;
+}
+
+static void mm7dispatch(MmsHTTPClientInfo *h)
+{
+ /* if no vasp, return 4001 error. */
+ MSoapMsg_t *mreq = NULL, *mresp = NULL;
+ int hstatus = HTTP_OK;
+ List *rh = NULL;
+ Octstr *reply_body = NULL;
+ Octstr *sender = NULL;
+ MmsEnvelope *e = NULL;
+
+ List *to = NULL;
+ Octstr *from = NULL, *subject = NULL, *vasid = NULL, *msgid = NULL;
+ time_t expiryt = -1, delivert = -1;
+ MmsMsg *m = NULL;
+ int status = 1000;
+ char *msgtype = "";
+ Octstr *qf = NULL;
+
+ mreq = mm7_parse_soap(h->headers, h->body);
+ if (mreq)
+ msgtype = mms_mm7tag_to_cstr(mm7_msgtype(mreq));
+ debug("mmsprox.mm7sendinterface", 0,
+ " --> Enterred mm7dispatch interface, mreq=%s mtype = %s <-- ",
+ mreq ? "Ok" : "Null",
+ mreq ? msgtype : "Null");
+
+
+ if (!h->vasp) {
+ /* Ask it to authenticate... */
+ List *hh = http_create_empty_headers();
+ http_header_add(hh, "WWW-Authenticate",
+ "Basic realm=\"" MM_NAME "\"");
+ http_send_reply(h->client, 401, hh, octstr_imm(""));
+ goto done2;
+ } else if (!mreq) {
+ mresp = mm7_make_resp(NULL, 2007, NULL);
+ goto done;
+ }
+
+ sender = octstr_format("%d/TYPE=PLMN", h->vasp->short_code);
+ switch (mm7_msgtype(mreq)) {
+ case MM7_TAG_SubmitReq:
+ mm7_get_envelope(mreq, &from, &to, &subject, &vasid, &expiryt, &delivert);
+ m = mm7_soap_to_mmsmsg(mreq, sender);
+ if (m) {
+ Octstr *value;
+ int dlr;
+
+ value = mms_get_header_value(m, octstr_imm("X-Mms-Delivery-Report"));
+ if (value &&
+ octstr_case_compare(value, octstr_imm("Yes")) == 0)
+ dlr = 1;
+ else
+ dlr = 0;
+
+ if (delivert < 0)
+ delivert = time(NULL);
+
+ if (expiryt < 0)
+ expiryt = time(NULL) + settings->default_msgexpiry;
+
+ qf = mms_queue_add(from ? from : sender, to, subject,
+ NULL, NULL,
+ delivert, expiryt, m, NULL,
+ h->vasp->id, vasid, dlr,
+ octstr_get_cstr(settings->global_queuedir),
+ settings->host_alias);
+ msgid = mms_maketransid(octstr_get_cstr(qf), settings->host_alias);
+ mms_log("Received", sender, to, -1, msgid, h->vasp->id, NULL, "MM7", h->ua, NULL);
+
+ octstr_destroy(value);
+ } else
+ status = 4001;
+ mresp = mm7_make_resp(mreq, status, msgid);
+ break;
+
+ case MM7_TAG_ReplaceReq:
+ msgid = mm7_soap_header_value(mreq, octstr_imm("MessageID"));
+ if (msgid && (qf = mms_getqf_fromtransid(msgid)) != NULL &&
+ (e = mms_queue_readenvelope(octstr_get_cstr(qf),
+ octstr_get_cstr(settings->global_queuedir),
+ 1)) != NULL) {
+ if (!e->vaspid ||
+ octstr_compare(e->vaspid, h->vasp->id) != 0) {
+ status = 2001;
+ error(0, "MMS Proxy(MM7): ReplaceReq: Found message[id=%s]"
+ " but vaspid id=%s does not match!",
+ octstr_get_cstr(msgid), octstr_get_cstr(h->vasp->id));
+ } else { /* get orig message, change headers of new, replace old. */
+ MmsMsg *old = mms_queue_getdata(e);
+ MmsMsg *new = mm7_soap_to_mmsmsg(mreq, sender);
+ List *hh = mms_message_headers(old);
+ Octstr *s;
+
+ if (new) {
+ mms_add_missing_headers(new, hh);
+ if (mms_queue_replacedata(e, new) < 0) {
+ status = 3000;
+ error(0, "MMS Proxy(MM7): ReplaceReq: Failed to change data, "
+ "id=%s, vasp=%s!",
+ msgid ? octstr_get_cstr(msgid) : "NULL",
+ octstr_get_cstr(h->vasp->id));
+ }
+ } else
+ warning(0, "MMS Proxy(MM7): ReplaceReq: No data sent??, "
+ "id=%s, vasp=%s!",
+ msgid ? octstr_get_cstr(msgid) : "NULL",
+ octstr_get_cstr(h->vasp->id));
+
+ if ((s = mm7_soap_header_value(mreq,
+ octstr_imm("EarliestDeliveryTime"))) != NULL) {
+ e->sendt = date_parse_http(s);
+ octstr_destroy(s);
+ }
+
+ if (mms_queue_update(e) != 1)
+ mms_queue_free_env(e);
+ e = NULL;
+ mms_log("Replace",
+ sender, NULL, -1, msgid, h->vasp->id, NULL, "MM7", h->ua, NULL);
+
+ if (new)
+ mms_destroy(new);
+ if (old)
+ mms_destroy(old);
+ http_destroy_headers(hh);
+ }
+ } else {
+ status = 2005;
+ error(0, "MMS Proxy(MM7): ReplaceReq: Failed to find msg, id=%s, vasp=%s!",
+ msgid ? octstr_get_cstr(msgid) : "NULL",
+ octstr_get_cstr(h->vasp->id));
+ }
+
+ mresp = mm7_make_resp(mreq, status, NULL);
+ break;
+
+ case MM7_TAG_CancelReq:
+ msgid = mm7_soap_header_value(mreq, octstr_imm("MessageID"));
+ if (msgid && (qf = mms_getqf_fromtransid(msgid)) != NULL &&
+ (e = mms_queue_readenvelope(octstr_get_cstr(qf),
+ octstr_get_cstr(settings->global_queuedir),
+ 1)) != NULL) {
+ if (!e->vaspid ||
+ octstr_compare(e->vaspid, h->vasp->id) != 0) {
+ status = 2001;
+ error(0, "MMS Proxy(MM7): CancelReq: Found message[id=%s]"
+ " bxut vaspid id=%s does not match!",
+ octstr_get_cstr(msgid), octstr_get_cstr(h->vasp->id));
+ } else { /* Kill it. */
+ int i, n;
+ for (i = 0, n = list_len(e->to); ito,i);
+ xto->process = 0;
+ }
+ mms_queue_update(e); /* Will clear it. */
+ e = NULL;
+ mms_log("Cancel",
+ sender, NULL, -1, msgid, h->vasp->id, NULL, "MM7", h->ua, NULL);
+ }
+ } else {
+ status = 2005;
+ error(0, "MMS Proxy(MM7): CancelReq: Failed to find msg, id=%s, vasp=%s!",
+ msgid ? octstr_get_cstr(msgid) : "NULL",
+ octstr_get_cstr(h->vasp->id));
+ }
+ mresp = mm7_make_resp(mreq, status, NULL);
+ break;
+ default:
+
+ break;
+ }
+
+ done:
+ if (mresp && mm7_soapmsg_to_httpmsg(mresp, &rh, &reply_body) == 0)
+ http_send_reply(h->client, hstatus, rh, reply_body);
+ else
+ http_close_client(h->client);
+
+ done2:
+ if (e)
+ mms_queue_free_env(e);
+
+ if (sender)
+ octstr_destroy(sender);
+
+ if (from)
+ octstr_destroy(from);
+
+ if (subject)
+ octstr_destroy(subject);
+ if (vasid)
+ octstr_destroy(vasid);
+ if (msgid)
+ octstr_destroy(msgid);
+
+ if (qf)
+ octstr_destroy(qf);
+ if (m)
+ mms_destroy(m);
+ if (rh)
+ http_destroy_headers(rh);
+ if (reply_body)
+ octstr_destroy(reply_body);
+
+ if (mresp)
+ mm7_soap_destroy(mresp);
+ if (mreq)
+ mm7_soap_destroy(mreq);
+
+ if (to)
+ list_destroy(to, (list_item_destructor_t *)octstr_destroy);
+
+ octstr_destroy(h->ip);
+ octstr_destroy(h->url);
+
+ if (h->base_client_addr)
+ octstr_destroy(h->base_client_addr);
+ if (h->client_addr)
+ octstr_destroy(h->client_addr);
+
+ if (h->ua) octstr_destroy(h->ua);
+ if (h->body) octstr_destroy(h->body);
+ http_destroy_cgiargs(h->cgivars);
+ http_destroy_headers(h->headers);
+
+ gw_free(h);
+
+
+}
+static void mm7proxy(void *unused)
+{
+ MmsHTTPClientInfo h;
+ while(rstop == 0 &&
+ (h.client = http_accept_request(settings->mm7port,
+ &h.ip, &h.url, &h.headers,
+ &h.body, &h.cgivars)) != NULL)
+ if (is_allowed_ip(settings->deny_ip, settings->allow_ip, h.ip)) {
+ MmsHTTPClientInfo *hx = gw_malloc(sizeof *hx);
+
+ memset(hx, 0, sizeof *hx);
+
+ /* Get the MM7 sender address. */
+
+ h.vasp = find_mm7sender(h.headers, settings->vasp_list);
+ h.ua = http_header_value(h.headers, octstr_imm("User-Agent"));
+ debug("mmsproxy", 0,
+ " MM7 Request, ip=%s, vasp=%s ",
+ h.ip ? octstr_get_cstr(h.ip) : "",
+ h.vasp && h.vasp->id ? octstr_get_cstr(h.vasp->id) : "(null)");
+
+ /* Dump headers, url etc. */
+#if 1
+ http_header_dump(h.headers);
+ if (h.body) octstr_dump(h.body, 0);
+ if (h.ip) octstr_dump(h.ip, 0);
+#endif
+ *hx = h; /* Copy it all over. */
+ gwthread_create((gwthread_func_t *)mm7dispatch, hx);
+
+ } else {
+ octstr_destroy(h.ip);
+ octstr_destroy(h.url);
+
+ if (h.body)
+ octstr_destroy(h.body);
+ if (h.headers)
+ http_destroy_headers(h.headers);
+ if (h.cgivars)
+ http_destroy_headers(h.cgivars);
+
+ http_close_client(h.client);
+ }
+
+ debug("proxy", 0, "MM7 Shutting down...");
+}
diff --git a/mbuni/mmsc/mmssend.c b/mbuni/mmsc/mmssend.c
index 6387d14..9204729 100644
--- a/mbuni/mmsc/mmssend.c
+++ b/mbuni/mmsc/mmssend.c
@@ -159,9 +159,12 @@ int main(int argc, char *argv[])
if (!m)
panic(0, "No Message supplied, or failed to decode binary data!");
- s = mms_queue_add(from, to, NULL, NULL, NULL, NULL, time(NULL),
+ s = mms_queue_add(from, to, NULL, NULL, NULL, time(NULL),
time(NULL) + settings->default_msgexpiry, m,
- NULL, 0, octstr_get_cstr(settings->global_queuedir));
+ NULL, 0,
+ NULL, NULL,
+ octstr_get_cstr(settings->global_queuedir),
+ settings->host_alias);
if (savetommbox)
mmbox = mms_mmbox_addmsg(octstr_get_cstr(settings->mmbox_rootdir),
diff --git a/mbuni/todo b/mbuni/todo
index 2367adb..d3ba44e 100644
--- a/mbuni/todo
+++ b/mbuni/todo
@@ -1,6 +1,9 @@
- correct handling of sender-visibility flag when receiving message (and also use correct address for billing. no spoofing).
-- Sending DLR correctly when sending from/to email.
- In content adaptation: Colour depth adjustment
- Need to parameterise some values: tmp dir, response messages (say on failed content adaptation)
-- Tests
+- Test suite
- Correct handling of unrecognised mms headers. spec says pass them un-changed.
+
+- Queue module needs to be de-coupled slightly from storage, so that mmsproxy can run on a separate box
+ but be able to initiate queue writes/reads over network. Hence pieces can run on separate boxes
+ (with mmsrelay providing network service for queue functions)
|