1
0
Fork 0

MM7/SOAP implementation now tested + misc bug fixes

This commit is contained in:
bagyenda 2005-04-14 11:27:23 +00:00
parent 7967dcc45f
commit 7497919605
18 changed files with 1691 additions and 187 deletions

View File

@ -15,7 +15,7 @@ mm4-queue-directory = /tmp/spool/mm4
mmbox-root-directory = /tmp/spool/mmbox
max-send-threads = 5
send-mail-prog = /usr/sbin/sendmail -f '%f' '%t'
unified-prefix = "+25637,037,77"
unified-prefix = "+25637,037,37"
maximum-send-attempts = 50
default-message-expiry = 360000
queue-run-interval = 0.1
@ -23,8 +23,8 @@ send-attempt-back-off = 300
sendsms-url = http://localhost:13013/cgi-bin/sendsms
sendsms-username = tester
sendsms-password = foobar
#sendsms-global-sender = 198
mms-port = 1981
mm7-port = 1982
#allow-ip = 192.168.129.11
email2mms-relay-prefixes = "037;035;25637"
ua-profile-cache-directory = /tmp/misc/profiles
@ -40,6 +40,16 @@ mms-to-email-txt = "This is a multimedia message (HTML suppressed)"
mms-to-email-html = "This is a multimedia message powered by <emph>Digital Solutions</emph>"
mms-message-too-large-txt = "You have received a multimedia message from %S that is too large for your phone. Go to xxx to view it"
group = mms-vasp
vasp-id = newscorp
type = soap
short-code = 111
vasp-username = newscorp
vasp-password = news123
vasp-url = http://localhost:23535/
mmsc-username = user
mmsc-password = secret
group = mmsproxy
name = "A test mms proxy"
host = ds.co.ug

View File

@ -51,7 +51,9 @@ This document describes the installation and usage of the MMS Gateway.
<LI><A HREF="#Section_.1.2.3">Installing Required Components</A></LI>
</UL></LI>
<LI><A HREF="#Section_.1.3">Chapter 3: Running the Gateway</A><UL>
<LI><A HREF="#Section_.1.3.1">Configuration File</A></LI>
<LI><A HREF="#Section_.1.3.1">General Configuration File</A></LI>
<LI><A HREF="#mm7">MM7 Configuration</A></LI>
<LI><A HREF="#mm4">MM4 Configuration File</A></LI>
</UL></LI>
<LI><A HREF="#Section_.1.4">Chapter 4: Gateway Architecture</A><UL>
<LI><A HREF="#Section_.1.4.1">MMS Proxy</A></LI>
@ -238,8 +240,8 @@ content depending on the capabilities of the receiving terminal
<p>
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.
<br>
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 <tt>mmsc.conf</tt>). The
configuration file controls most aspects of
the operation of the gateway. </p>
<H4><!--TableOfContentsAnchor:Begin--><A NAME="Section_.1.3.1"></A><!--TableOfContentsAnchor:End-->Configuration File</H4>
<H4><!--TableOfContentsAnchor:Begin--><A
NAME="Section_.1.3.1"></A><!--TableOfContentsAnchor:End-->General Configuration File</H4>
<p >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</p>
is 8191).
&nbsp; &nbsp;</td>
</tr>
<tr>
<td valign=top >
<tt>mm7-port</tt>
&nbsp; &nbsp;</td>
<td valign=top >
Integer
&nbsp; &nbsp;</td>
<td valign=top >
Port on which <tt>mmsproxy</tt> listens for MM7 requests from Value
Added Services providers. If this port is not supplied, the MM7
sub-system is not started.
&nbsp; &nbsp;</td>
</tr>
<tr>
<td valign=top >
<tt>allow-ip</tt>
@ -1243,6 +1262,180 @@ lists all the configuration directives</p>
</table>
<br>
<a name="mm7"></a>
<h4>MM7 Configuration</h4>
<!--- MM7 stuff -->
<p >MMS Value-Added Service Providers (VASPs) are configured using
one or more <i>mms-vasp</i> groups:</p>
<br>
<tt>
group =
mms-vasp<br>
vasp-id = newcorp<br>
type =
soap<br>
short-code
= 100<br>
vasp-username
= newscorp<br>
vasp-password
= news123<br>
vasp-url
= http://example.vasp.com:8080/mm7<br>
mmsc-username
= mymmsc<br>
mmsc-password
= mypass<br>
<br>
</tt>
<br>
<table border=0 cellspacing=2 cellpadding=2 >
<tr>
<td valign=top >
<b>Variable</b>
</td>
<td valign=top >
<b>Type</b>
</td>
<td valign=top >
<b>Description</b>
</td>
</tr>
<tr>
<td valign=top >
<tt>group</tt>
</td>
<td valign=top >
String
</td>
<td valign=top >
Mandatory:
<tt>mms-vasp</tt>
</td>
</tr>
<tr>
<td valign=top >
<tt>vasp-id</tt>
</td>
<td valign=top >
String
</td>
<td valign=top >
User friendly
name
</td>
</tr>
<tr>
<td valign=top >
<tt>type</tt>
</td>
<td valign=top >
String
</td>
<td valign=top >
This should be one of: soap, eaif (<i>note: only soap is supported currently</i>)
</td>
</tr>
<tr>
<td valign=top >
<tt>short-code</tt>
</td>
<td valign=top >
Number
</td>
<td valign=top >
Short number for this VASP: Messages received by Mbuni to this
number are routed to the VASP via MM7.
</td>
</tr>
<tr>
<td valign=top >
<tt>vasp-url</tt>
</td>
<td valign=top >
String
</td>
<td valign=top >
Outgoing messages to the VASP are sent via this URL (using HTTP POST)
</td>
</tr>
<tr>
<td valign=top >
<tt>mmsc-username</tt>
</td>
<td valign=top >
String
</td>
<td valign=top >
Outgoing HTTP authentication: The username Mbuni must use when sending data
to the VASP
</td>
</tr>
<tr>
<td valign=top >
<tt>mmsc-password</tt>
</td>
<td valign=top >
String
</td>
<td valign=top >
Outgoing HTTP authentication: password Mbuni must use when sending data
to the VASP
</td>
</tr>
<tr>
<td valign=top >
<tt>vasp-username</tt>
</td>
<td valign=top >
String
</td>
<td valign=top >
Incoming HTTP authentication: The username used by the VASP to
authenticate itself to Mbuni when sending data
</td>
</tr>
<tr>
<td valign=top >
<tt>vasp-password</tt>
</td>
<td valign=top >
String
</td>
<td valign=top >
Incoming HTTP authentication: The password used by the VASP to
authenticate itself to Mbuni when sending data
to the VASP
</td>
</tr>
</table>
Note that currently only HTTP Basic authentication scheme is supported
by Mbuni (for both incoming and out-going requests).
<a name="mm4"></a>
<h4>MM4 Configuration</h4>
<!-- Foreign MMSC stuff -->
<p >Foreign MMS
Gateways are configured using one or more <i>mmsproxy</i> groups:</p>
@ -1481,6 +1674,8 @@ re-formatted as MIME, sender and recipient addresses normalised as RFC
822 addresses, and the message passed to the mailer.
<li> If the message is destined for a foreign gateway, it is coded
as MIME and passed to the mailer for delivery via SMTP
<li>If the the message is destined for a VASP (identified by short
code), then it is sent using MM7 protocols to the relevant VASP.
<li> If the message cannot be delivered, the sender is notified.
</ol>
</ol>

View File

@ -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

View File

@ -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); i<n; i++) {
MIMEEntity *x = list_get(mime->multiparts, 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, "<Number%s>%S</Number>\n", y, z);
octstr_destroy(z);
} else
octstr_format_append(p, "<RFC2822Address%s>%s</RFC2822Address>\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, "<Number%s>%S</Number>\n", y, z);
octstr_destroy(z);
} else
octstr_format_append(p, "<RFC2822Address%s>%s</RFC2822Address>\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("<?xml version=\"1.0\" ?>\n");
Octstr *p, *q, *fault, *mtype;
Octstr *p, *q, *r, *fault, *mtype;
int i, n;
time_t t;
int mtag;
octstr_append_cstr(s,
"<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
"<env:Header>\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, "<SenderIdentification>\n");
if (p)
@ -366,19 +403,33 @@ Octstr *headers_to_soapxml(List *hdrs)
if (q)
octstr_format_append(s, "<VASID>%S</VASID>\n", q);
if (r) {
Octstr *xx = octstr_create("");
append_address(xx, r);
octstr_format_append(s, "<SenderAddress>%S</SenderAddress>\n", xx);
octstr_destroy(xx);
}
octstr_append_cstr(s, "</SenderIdentification>\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, "<Recipients>\n%S</Recipients>\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, "<Recipients>\n%S</Recipients>\n", p);
} else if ((q = http_header_value(hdrs, octstr_imm("To"))) != NULL) {
append_address(p, q);
octstr_format_append(s, "<Recipient>\n%S</Recipient>\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, "<Sender>%S</Sender>\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, "<Status>\n");
if (p) {
octstr_format_append(s, "<StatusCode>%S</StatusCode>\n", p);
@ -446,6 +514,12 @@ Octstr *headers_to_soapxml(List *hdrs)
octstr_format_append(s, "<StatusText>%S</StatusText>\n", q);
octstr_destroy(q);
}
q = http_header_value(hdrs, octstr_imm("Details"));
if (q) {
octstr_format_append(s, "<Details>%S</Details>\n", q);
octstr_destroy(q);
}
octstr_append_cstr(s, "</Status>\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:<c%ld.%d.%c%c.msg>",
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("<s%ld.%d.%c%c.msg>",
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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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.
*/

View File

@ -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

View File

@ -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); i<n; i++) {
CfgGroup *grp = list_get(l, i);
MmsVasp *mv = gw_malloc(sizeof *mv);
Octstr *s;
mv->id = 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;
}

View File

@ -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

View File

@ -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:

View File

@ -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); j<m; j++) {
MmsProxyRelay *mp = list_get(proxyrelays, j);
@ -213,7 +224,17 @@ static int sendMsg(MmsEnvelope *e)
break;
}
}
}
} else /* Search VASP list, see what you can find... */
for (j = 0, m = list_len(settings->vasp_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;
}

View File

@ -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);

View File

@ -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); i<n; i++) {
MmsVasp *x = list_get(vasps, i);
if (octstr_compare(x->vasp_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); i<n; i++) {
MmsEnvelopeTo *xto = list_get(e->to,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...");
}

View File

@ -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),

View File

@ -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)