[FYI] more bugfixes to ppg
Aarno Syvänen <[email protected]>
| Newsgroups | gmane.comp.mobile.kannel.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi List, there is a new cvs diff fixing bugs Ritesh noticed: a) CRLF is needed after MIME close delimiter only when there is an epilogue. b) WAP-209, chapter 8 states that with a phone number address, one should use only specifier of type /TYPE=PLMN, without ppg part. So now push address specifier can be either like /TYPE=PLMN or /[email protected]. (But if there is ppg specifier, there must be separator '@', too.) c) Still more command line options for test_ppg (adding preamble and epilogue). But Yury's bug is still problematic :( Aarno
cvs.diff
(application/octet-stream, 40 KB)
Index: gw/wap_push_ota.c
===================================================================
RCS file: /home/cvs/gateway/gw/wap_push_ota.c,v
retrieving revision 1.17
diff -B -b -u -r1.17 wap_push_ota.c
--- gw/wap_push_ota.c 13 Feb 2003 10:32:01 -0000 1.17
+++ gw/wap_push_ota.c 28 May 2003 10:20:29 -0000
@@ -332,7 +332,8 @@
}
/*
- * Add push flag into push headers. Push flag is defined in otaa, p. 17-18.
+ * Add push flag into push headers. Push flag is defined in ota, p. 17-18.
+ * If there is no flags set, no Push-Flag header is added.
*/
static List *add_push_flag(WAPEvent *e)
{
@@ -377,9 +378,11 @@
push_flag = 0;
push_flag = push_flag | authenticated | trusted | last;
+ if (push_flag) {
buf = octstr_format("%d", push_flag);
http_header_add(headers, "Push-Flag", octstr_get_cstr(buf));
octstr_destroy(buf);
+ }
return headers;
}
Index: gw/wap_push_pap_compiler.c
===================================================================
RCS file: /home/cvs/gateway/gw/wap_push_pap_compiler.c,v
retrieving revision 1.28
diff -B -b -u -r1.28 wap_push_pap_compiler.c
--- gw/wap_push_pap_compiler.c 28 Mar 2003 13:03:49 -0000 1.28
+++ gw/wap_push_pap_compiler.c 28 May 2003 10:20:29 -0000
@@ -757,8 +757,9 @@
}
if (i == NUM_ELEMENTS) {
+ debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown element:");
+ octstr_dump(name, 0);
octstr_destroy(name);
- debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown element");
return -2;
}
@@ -1444,8 +1445,14 @@
if (octstr_get_char(*address, 0) == '/')
octstr_delete(*address, 0, 1);
- if ((pos = parse_ppg_specifier(address, pos)) < 0) {
- warning(0, "illegal ppg specifier");
+/*
+ * WAP-209, chapter 8 states that addresses with telephone numbers
+ * should not have a ppg specifier. WAP-151 grammar, however, makes it
+ * mandatory. Best way to solve this contradiction seems to be regarding
+ * ppg specifier optional - MMSC is very important type of pi.
+ */
+ if (octstr_search_char(*address, '@', 0) >= 0) {
+ if ((pos = parse_ppg_specifier(address, pos)) < 0)
return -2;
}
@@ -1481,7 +1488,8 @@
}
/*
- * We are not interested of ppg specifier, but we must check its format.
+ * We are not interested of ppg specifier, but we must check its format,
+ * if we find it - it is optional.
*/
static long parse_ppg_specifier(Octstr **address, long pos)
{
@@ -1494,8 +1502,6 @@
octstr_delete(*address, pos, 1);
--pos;
} else {
- debug("wap.push.pap.compiler", 0, "PAP COMPILER: missing"
- " separator .");
return -2;
}
@@ -1511,8 +1517,6 @@
}
if (pos < 0) {
- debug("wap.push.pap.compiler", 0, "PAP COMPILER: missing separator /"
- " or @");
return -2;
}
Index: gw/wap_push_pap_mime.c
===================================================================
RCS file: /home/cvs/gateway/gw/wap_push_pap_mime.c,v
retrieving revision 1.5
diff -B -b -u -r1.5 wap_push_pap_mime.c
--- gw/wap_push_pap_mime.c 4 Sep 2002 09:05:06 -0000 1.5
+++ gw/wap_push_pap_mime.c 28 May 2003 10:20:29 -0000
@@ -2,7 +2,7 @@
* Implementation of a gateway oriented mime parser for pap module. This
* parser follows proxy rules stated in Push Message, chapter 7.
*
- * By Aarno Syvänen for Wiral Ltd
+ * By Aarno Syvänen for Wiral Ltd and Global Networks Inc.
*/
#include "wap_push_pap_mime.h"
@@ -47,7 +47,7 @@
long pos);
static long pass_field_value(Octstr **body_part, Octstr **content_header,
long pos);
-static void parse_epilogue(Octstr **mime_content);
+static int parse_epilogue(Octstr **mime_content);
static int parse_tail(Octstr **multipart, Octstr *part_delimiter,
long boundary_pos, long *next_part_pos);
@@ -103,8 +103,8 @@
return 0;
} else if (ret == 0) {
gw_assert(*rdf_content == NULL);
+ if (octstr_len(mime_content) != 0)
parse_epilogue(&mime_content);
- gw_assert(octstr_len(mime_content) == 0);
return 1;
}
@@ -112,6 +112,7 @@
warning(0, "erroneous capacity (rdf) headers");
return 0;
}
+ if (octstr_len(mime_content) != 0)
parse_epilogue(&mime_content);
gw_assert(octstr_len(mime_content) == 0);
@@ -141,6 +142,7 @@
return c == '\t' || c == ' ';
}
+/* These thingies we after normally have after delimiters. */
static int parse_tail(Octstr **multipart, Octstr *delimiter,
long boundary_pos, long *next_part_pos)
{
@@ -153,6 +155,16 @@
return 0;
}
+/* But if we have no epilogue, we do not have crlf after close delimiter either.*/
+static int parse_short_tail(Octstr **multipart, Octstr *delimiter, long boundary_pos,
+ long *next_part_pos)
+{
+ *next_part_pos = parse_transport_padding(*multipart,
+ boundary_pos + octstr_len(delimiter));
+
+ return 0;
+}
+
/*
* Boundary misses crlf here. This is intentional: Kannel header parsing pro-
* cess drops this terminator.
@@ -200,18 +212,28 @@
static long parse_transport_padding(Octstr *mime_content, long pos)
{
- while (islwspchar(octstr_get_char(mime_content, 0)))
+ while (islwspchar(octstr_get_char(mime_content, pos)))
++pos;
return pos;
}
+static long parse_close_delimiter(Octstr *close_delimiter, Octstr *mime_content,
+ long pos)
+{
+ if (octstr_ncompare(close_delimiter, mime_content,
+ octstr_len(close_delimiter)) != 0)
+ return -1;
+ pos += octstr_len(close_delimiter);
+
+ return pos;
+}
+
/*
- * Splits the first body part away from the multipart message, if there is
- * more than one left. A body part end with either with another body or with
- * a close delimiter. If there is more than one body part left, we first split
- * the first one and then remove the stuff separating bodies from the remaind-
- * er. If there is none just remove the ending stuff.
+ * Splits the first body part away from the multipart message. A body part end with
+ * either with another body or with a close delimiter. We first split the body and
+ * then remove the separating stuff from the remainder. If we have the last body
+ * part, we must parse all closing stuff.
* Returns 1, there is still another body part in the multipart message
* 0, if there is none
* -1, when parsing error.
@@ -224,7 +246,8 @@
long boundary_pos, /* start of the boundary */
close_delimiter_pos, /* start of the close delimiter */
end_pos, /* end of the message */
- next_part_pos; /* start of the next part */
+ next_part_pos, /* start of the next part */
+ epilogue_pos; /* start of the epilogue */
part_delimiter = make_part_delimiter(boundary);
close_delimiter = make_close_delimiter(boundary);
@@ -235,17 +258,15 @@
boundary_pos = octstr_search(*multipart, part_delimiter, 0);
if (boundary_pos == close_delimiter_pos) {
- if (parse_tail(multipart, close_delimiter, close_delimiter_pos,
- &end_pos) < 0) {
+ *body_part = octstr_create("");
+ octstr_split_by_pos(multipart, body_part, close_delimiter_pos);
+ if ((epilogue_pos =
+ parse_close_delimiter(close_delimiter, *multipart, 0)) < 0)
goto error;
- } else {
- octstr_delete(*multipart, close_delimiter_pos,
- end_pos - close_delimiter_pos);
- *body_part = octstr_duplicate(*multipart);
- octstr_delete(*multipart, 0, end_pos);
+ epilogue_pos = parse_transport_padding(*multipart, epilogue_pos);
+ octstr_delete(*multipart, 0, epilogue_pos);
goto last_part;
}
- }
*body_part = octstr_create("");
octstr_split_by_pos(multipart, body_part, boundary_pos);
@@ -727,13 +748,17 @@
return pos;
}
-static void parse_epilogue(Octstr **mime_content)
+/* This is actually CRLF epilogue. */
+static int parse_epilogue(Octstr **mime_content)
{
+ long pos;
+
if (octstr_len(*mime_content) == 0)
- return;
+ return 0;
+
+ if ((pos = parse_terminator(*mime_content, 0)) < 0)
+ return -1;
- debug("wap.push.pap.mime", 0, "our epilogue was");
- octstr_dump(*mime_content, 0);
octstr_delete(*mime_content, 0, octstr_len(*mime_content));
}
Index: gw/wap_push_ppg.c
===================================================================
RCS file: /home/cvs/gateway/gw/wap_push_ppg.c,v
retrieving revision 1.53
diff -B -b -u -r1.53 wap_push_ppg.c
--- gw/wap_push_ppg.c 20 Mar 2003 14:11:49 -0000 1.53
+++ gw/wap_push_ppg.c 28 May 2003 10:20:29 -0000
@@ -266,6 +266,7 @@
Octstr **boundary);
static void change_header_value(List **push_headers, char *name, char *value);
static void remove_mime_headers(List **push_headers);
+static void remove_link_headers(List **push_headers);
/*
* Communicating with pi.
@@ -374,6 +375,7 @@
octstr_destroy(ppg_deny_ip);
octstr_destroy(ppg_allow_ip);
octstr_destroy(global_sender);
+ octstr_destroy(ppg_default_smsc);
gwthread_join_every(http_read_thread);
#ifdef HAVE_LIBSSL
@@ -745,6 +747,7 @@
http_remove_hop_headers(push_headers);
remove_mime_headers(&push_headers);
+ remove_link_headers(&push_headers);
if (!headers_acceptable(push_headers, &content_header)) {
warning(0, "PPG: Unparsable push headers, the request"
@@ -2670,7 +2673,23 @@
"wta.ua",
"mms.ua",
"push.syncml",
- "loc.ua"
+ "loc.ua",
+ "syncml.dm",
+ "drm.ua",
+ "emn.ua",
+ "wv.ua",
+ "x-wap-microsoft:localcontent.ua",
+ "x-wap-microsoft:IMclient.ua",
+ "x-wap-docomo:imode.mail.ua",
+ "x-wap-docomo:imode.mr.ua",
+ "x-wap-docomo:imode.mf.ua",
+ "x-motorola:location.ua",
+ "x-motorola:now.ua",
+ "x-motorola:otaprov.ua",
+ "x-motorola:browser.ua",
+ "x-motorola:splash.ua",
+ "x-wap-nai:mvsw.command",
+ "x-wap-openwave:iota.ua"
};
#define NUMBER_OF_WINA_URIS sizeof(wina_uri)/sizeof(wina_uri[0])
@@ -2680,14 +2699,9 @@
* First check do we a header with an app-encoding field and a coded value.
* If not, try to find push application id from table of wina approved values.
* Return coded value value of application id in question, or an error code:
- * -1, error
+ * -1, no coded value (but defaults may be applied)
* 0, * (meaning any application acceptable)
- * 1, push.sia
- * 2, wml.ua
- * 3, wta.ua
- * 4, mms.ua
- * 5, push.syncml
- * 6, loc.ua
+ * greater or equal as 1: code for this application id
*/
static long parse_appid_header(Octstr **appid_content)
{
@@ -2844,12 +2858,21 @@
/*
* Some application level protocols may use MIME headers. This may cause problems
- * to them.
+ * to them. (MIME version is a mandatory header).
*/
static void remove_mime_headers(List **push_headers)
{
http_header_remove_all(*push_headers, "MIME-Version");
}
+
+/*
+ * There are headers used only for HTTP POST pi->ppg. (For debugging, mainly.)
+ */
+static void remove_link_headers(List **push_headers)
+{
+ http_header_remove_all(*push_headers, "Host");
+}
+
/*
* Badmessage-response element is redefined in pap, implementation note,
Index: gw/wapbox.c
===================================================================
RCS file: /home/cvs/gateway/gw/wapbox.c,v
retrieving revision 1.157
diff -B -b -u -r1.157 wapbox.c
--- gw/wapbox.c 27 Mar 2003 08:55:01 -0000 1.157
+++ gw/wapbox.c 28 May 2003 10:20:30 -0000
@@ -49,6 +49,10 @@
int wsp_smart_errors = 0;
Octstr *device_home = NULL;
+/* Controlling segmentation of sms messages sent by wapbox (push related).*/
+int concatenation = 0;
+long max_messages = 10;
+
#ifdef HAVE_WTLS_OPENSSL
RSA* private_key = NULL;
X509* x509_cert = NULL;
@@ -176,6 +180,8 @@
* error information instread of signaling using the HTTP reply codes
*/
cfg_get_bool(&wsp_smart_errors, grp, octstr_imm("smart-errors"));
+ cfg_get_bool(&concatenation, grp, octstr_imm("concatenation"));
+ cfg_get_integer(&max_messages, grp, octstr_imm("max-messages"));
/* configure the 'wtls' group */
#if (HAVE_WTLS_OPENSSL)
@@ -396,13 +402,13 @@
} else {
msg = pack_sms_datagram(dgram);
msg_sequence = counter_increase(sequence_counter) & 0xff;
- msg_len = octstr_len(msg->sms.msgdata);
- max_msgs = (msg_len / MAX_SMS_OCTETS) + 1;
- sms_datagrams = sms_split(msg, NULL, NULL, NULL, NULL, 1,
- msg_sequence, max_msgs, MAX_SMS_OCTETS);
-
- while ((part = list_extract_first(sms_datagrams)) != NULL)
+ /*msg_len = octstr_len(msg->sms.msgdata);
+ max_msgs = (msg_len / MAX_SMS_OCTETS) + 1;*/
+ sms_datagrams = sms_split(msg, NULL, NULL, NULL, NULL, concatenation,
+ msg_sequence, max_messages, MAX_SMS_OCTETS);
+ while ((part = list_extract_first(sms_datagrams)) != NULL) {
write_to_bearerbox(part);
+ }
list_destroy(sms_datagrams, NULL);
msg_destroy(msg);
Index: gw/smsc/smsc_http.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_http.c,v
retrieving revision 1.18
diff -B -b -u -r1.18 smsc_http.c
--- gw/smsc/smsc_http.c 19 May 2003 07:35:58 -0000 1.18
+++ gw/smsc/smsc_http.c 28 May 2003 10:20:30 -0000
@@ -297,7 +297,8 @@
octstr_format_append(url, "&account=%E:%E", sms->sms.service, sms->sms.account);
if (sms->sms.smsc_id) /* proxy the smsc-id to the next instance */
octstr_format_append(url, "&smsc=%S", sms->sms.smsc_id);
-
headers = list_create();
debug("smsc.http.kannel", 0, "HTTP[%s]: Start request",
octstr_get_cstr(conn->id));
Index: gwlib/cfg.def
===================================================================
RCS file: /home/cvs/gateway/gwlib/cfg.def,v
retrieving revision 1.85
diff -B -b -u -r1.85 cfg.def
--- gwlib/cfg.def 3 Apr 2003 12:18:18 -0000 1.85
+++ gwlib/cfg.def 28 May 2003 10:20:30 -0000
@@ -77,6 +77,8 @@
OCTSTR(syslog-level)
OCTSTR(smart-errors)
OCTSTR(access-log)
+ OCTSTR(concatenation)
+ OCTSTR(max-messages)
)
@@ -245,6 +247,7 @@
OCTSTR(notification-addr)
OCTSTR(msg-id-type)
OCTSTR(no-dlr)
)
Index: gwlib/http.c
===================================================================
RCS file: /home/cvs/gateway/gwlib/http.c,v
retrieving revision 1.190
diff -B -b -u -r1.190 http.c
--- gwlib/http.c 3 Apr 2003 12:18:36 -0000 1.190
+++ gwlib/http.c 28 May 2003 10:20:30 -0000
@@ -2374,12 +2374,14 @@
if (octstr_case_compare(current_name, name) == 0) {
value = octstr_copy(os, colon + 1, octstr_len(os));
octstr_strip_blanks(value);
+ octstr_destroy(current_name);
return value;
}
+ octstr_destroy(current_name);
++i;
}
- return value;
+ return NULL;
}
List *http_header_duplicate(List *headers)
Index: test/test_ppg.c
===================================================================
RCS file: /home/cvs/gateway/test/test_ppg.c,v
retrieving revision 1.23
diff -B -b -u -r1.23 test_ppg.c
--- test/test_ppg.c 19 May 2003 07:37:52 -0000 1.23
+++ test/test_ppg.c 28 May 2003 10:20:31 -0000
@@ -27,15 +27,22 @@
num_urls = 0,
wait = 0,
use_headers = 0,
- use_config = 0;
+ use_config = 0,
+ accept_binary = 0,
+ use_numeric = 0,
+ use_string = 0,
+ add_epilogue = 0,
+ add_preamble = 0;
static double wait_seconds = 0.0;
static Counter *counter = NULL;
static char **push_data = NULL;
static char *boundary = NULL;
static Octstr *content_flag = NULL;
static Octstr *appid_flag = NULL;
+static Octstr *appid_string = NULL;
static Octstr *content_transfer_encoding = NULL;
static Octstr *connection = NULL;
+static Octstr *delimiter = NULL;
enum { SSL_CONNECTION_OFF = 0,
DEFAULT_NUMBER_OF_RELOGS = 2};
@@ -90,43 +97,74 @@
cfg_destroy(cfg);
}
-static void add_push_application_id(List **push_headers, Octstr *appid_flag)
+static void add_delimiter(Octstr **content)
+{
+ if (octstr_compare(delimiter, octstr_imm("crlf")) == 0) {
+ octstr_format_append(*content, "%c", '\r');
+ }
+
+ octstr_format_append(*content, "%c", '\n');
+}
+
+static void add_push_application_id(List **push_headers, Octstr *appid_flag,
+ int use_string)
{
- if (octstr_compare(appid_flag, octstr_imm("any")) == 0)
+ if (use_string) {
+ list_append(*push_headers, appid_string);
+ return;
+ }
+
+ if (octstr_compare(appid_flag, octstr_imm("any")) == 0) {
+ if (!use_numeric)
http_header_add(*push_headers, "X-WAP-Application-Id",
"http://www.wiral.com:*");
- else if (octstr_compare(appid_flag, octstr_imm("ua")) == 0)
+ else
+ http_header_add(*push_headers, "X-WAP-Application-Id", "0");
+ } else if (octstr_compare(appid_flag, octstr_imm("ua")) == 0) {
+ if (!use_numeric)
http_header_add(*push_headers, "X-WAP-Application-Id",
"http://www.wiral.com:wml.ua");
- else if (octstr_compare(appid_flag, octstr_imm("mms")) == 0)
+ else
+ http_header_add(*push_headers, "X-WAP-Application-Id", "2");
+ } else if (octstr_compare(appid_flag, octstr_imm("mms")) == 0) {
+ if (!use_numeric)
http_header_add(*push_headers, "X-WAP-Application-Id",
"mms.ua");
- else if (octstr_compare(appid_flag, octstr_imm("scrap")) == 0)
+ else
+ http_header_add(*push_headers, "X-WAP-Application-Id", "4");
+ } else if (octstr_compare(appid_flag, octstr_imm("scrap")) == 0) {
+ if (!use_numeric)
http_header_add(*push_headers, "X-WAP-Application-Id",
"no appid at all");
+ else
+ http_header_add(*push_headers, "X-WAP-Application-Id",
+ "this is not a numeric header");
+ }
}
static void add_content_type(Octstr *content_flag, Octstr **wap_content)
{
if (octstr_compare(content_flag, octstr_imm("wml")) == 0)
*wap_content = octstr_format("%s",
- "Content-Type: text/vnd.wap.wml\r\n");
+ "Content-Type: text/vnd.wap.wml");
else if (octstr_compare(content_flag, octstr_imm("si")) == 0)
*wap_content = octstr_format("%s",
- "Content-Type: text/vnd.wap.si\r\n");
+ "Content-Type: text/vnd.wap.si");
else if (octstr_compare(content_flag, octstr_imm("sl")) == 0)
*wap_content = octstr_format("%s",
- "Content-Type: text/vnd.wap.sl\r\n");
+ "Content-Type: text/vnd.wap.sl");
else if (octstr_compare(content_flag, octstr_imm("multipart")) == 0)
*wap_content = octstr_format("%s",
"Content-Type: multipart/related; boundary=fsahgwruijkfldsa\r\n");
else if (octstr_compare(content_flag, octstr_imm("mms")) == 0)
*wap_content = octstr_format("%s",
- "Content-Type: application/vnd.wap.mms-message\r\n");
+ "Content-Type: application/vnd.wap.mms-message");
else if (octstr_compare(content_flag, octstr_imm("scrap")) == 0)
- *wap_content = octstr_format("%s", "no type at all\r\n");
+ *wap_content = octstr_format("%s", "no type at all");
else if (octstr_compare(content_flag, octstr_imm("nil")) == 0)
*wap_content = octstr_create("");
+ if (octstr_len(*wap_content) > 0)
+ add_delimiter(wap_content);
}
static void add_content_transfer_encoding_type(Octstr *content_flag,
@@ -136,7 +174,9 @@
return;
if (octstr_compare(content_flag, octstr_imm("base64")) == 0)
- octstr_append_cstr(wap_content, "Content-transfer-encoding: base64\r\n");
+ octstr_append_cstr(wap_content, "Content-transfer-encoding: base64");
+
+ add_delimiter(&wap_content);
}
static void add_connection_header(Octstr *connection, Octstr *wap_content)
@@ -145,9 +185,11 @@
return;
if (octstr_compare(connection, octstr_imm("close")) == 0)
- octstr_format_append(wap_content, "%s", "Connection: close\r\n");
+ octstr_format_append(wap_content, "%s", "Connection: close");
else if (octstr_compare(connection, octstr_imm("keep-alive")) == 0)
- octstr_format_append(wap_content, "%s", "Connection: keep-alive\r\n");
+ octstr_format_append(wap_content, "%s", "Connection: keep-alive");
+
+ add_delimiter(&wap_content);
}
static void transfer_encode (Octstr *cte, Octstr *content)
@@ -180,12 +222,10 @@
Octstr *part_delimiter;
part_delimiter = octstr_create("");
- octstr_format_append(part_delimiter, "%c", '\r');
- octstr_format_append(part_delimiter, "%c", '\n');
+ add_delimiter(&part_delimiter);
octstr_format_append(part_delimiter, "%s", "--");
octstr_append(part_delimiter, boundary);
- octstr_format_append(part_delimiter, "%c", '\r');
- octstr_format_append(part_delimiter, "%c", '\n');
+ add_delimiter(&part_delimiter);
return part_delimiter;
}
@@ -195,14 +235,11 @@
Octstr *close_delimiter;
close_delimiter = octstr_create("");
- octstr_format_append(close_delimiter, "%c", '\r');
- octstr_format_append(close_delimiter, "%c", '\n');
+ add_delimiter(&close_delimiter);
octstr_format_append(close_delimiter, "%s", "--");
octstr_append(close_delimiter, boundary);
octstr_format_append(close_delimiter, "%s", "--");
- octstr_format_append(close_delimiter, "%c", '\r');
- octstr_format_append(close_delimiter, "%c", '\n');
-
+ /*add_delimiter(&close_delimiter);*/
return close_delimiter;
}
@@ -222,7 +259,7 @@
octstr_get_cstr(mos = make_multipart_value(boundary)));
if (use_headers)
http_add_basic_auth(push_headers, username, password);
- add_push_application_id(&push_headers, appid_flag);
+ add_push_application_id(&push_headers, appid_flag, use_string);
octstr_destroy(mos);
@@ -288,18 +325,30 @@
wap_content);
add_connection_header(connection, wap_content);
+ /* Read the content file. (To be pushed)*/
if ((wap_file_content =
octstr_read_file(octstr_get_cstr(content_file))) == NULL)
panic(0, "Stopping");
+ if (accept_binary) {
+ octstr_delete_matching(wap_file_content, octstr_imm(" "));
+ octstr_delete_matching(wap_file_content, octstr_imm("\n"));
+ octstr_delete_matching(wap_file_content, octstr_imm("\r"));
+ if (!octstr_is_all_hex(wap_file_content))
+ panic(0, "non-hex chars in the content file, cannot continue");
+ octstr_hex_to_binary(wap_file_content);
+ }
transfer_encode (content_transfer_encoding, wap_file_content);
octstr_append(wap_content, wap_file_content);
octstr_destroy(wap_file_content);
- pap_content = octstr_format("%s", "Content-Type: application/xml\r\n");
+ /* Read the control file. (To control pushing)*/
+ pap_content = octstr_format("%s", "Content-Type: application/xml");
+ add_delimiter(&pap_content);
if ((pap_file_content =
octstr_read_file(octstr_get_cstr(pap_file))) == NULL)
panic(0, "Stopping");
+
octstr_append(pap_content, pap_file_content);
octstr_destroy(pap_file_content);
@@ -307,14 +356,22 @@
panic(0, "Cannot open the push content files");
push_content = octstr_create("");
+ if (add_preamble)
+ octstr_append(push_content, octstr_imm("the parser should discard this"));
octstr_append(push_content,
bpos = make_part_delimiter(octstr_imm(boundary)));
+ /*octstr_append(push_content, octstr_imm("\r\n"));*/ /* Do we accept an additional
+ * clrf ? */
octstr_append(push_content, pap_content);
octstr_append(push_content, bpos);
octstr_destroy(bpos);
octstr_append(push_content, wap_content);
octstr_append(push_content,
bcos = make_close_delimiter(octstr_imm(boundary)));
+ if (add_epilogue) {
+ octstr_append(push_content, octstr_imm("\r\n"));
+ octstr_append(push_content, octstr_imm("the parser should discard this"));
+ }
octstr_destroy(bcos);
octstr_destroy(pap_content);
octstr_destroy(wap_content);
@@ -574,6 +631,13 @@
info(0, "-a application id");
info(0, "Define the client application that will handle the push. Any,");
info(0, "ua, mms, nil and scrap accepted, default ua.");
+ info(0, "-n");
+ info(0, "if set, use numeric appid values instead of string ones. For");
+ info(0, "instance, '4' instead of 'mms.ua'. Default is off.");
+ info(0, "-s string");
+ info(0, "supply application id as a plain string. For instance");
+ info(0, "-s x-wap-application-id:mms.ua equals -a ua. Default is");
+ info(0, "x-wap-application-id:mms.ua.");
info(0, "-b");
info(0, "If true, send username/password in headers. Default false");
info(0, "-v number");
@@ -598,6 +662,17 @@
info(0, "Default: read components from files");
info(0, "-t");
info(0, "number of threads, maximum 1024, default 1");
+ info(0, "-B");
+ info(0, "accept binary push content. Default: off.");
+ info(0, "Binary content consist of hex numbers. In addition, crs, lfs and");
+ info(0, "spaces are accepted, and ignored.");
+ info(0, "-d value");
+ info(0, "set delimiter to be used. Accepted values crlf and lf. Default crlf.");
+ info(0, "-E");
+ info(0, "If set, add a hardcoded epilogue (epilogue is to be discarded anyway).");
+ info(0, "Default off.");
+ info(0, "-p");
+ info(0, "If set, add hardcoded preamble. Default is off.");
}
int main(int argc, char **argv)
@@ -614,7 +689,7 @@
gwlib_init();
num_threads = 1;
- while ((opt = getopt(argc, argv, "Hhbv:qr:t:c:a:i:e:k:")) != EOF) {
+ while ((opt = getopt(argc, argv, "HhBbnEpv:qr:t:c:a:i:e:k:d:s:")) != EOF) {
switch(opt) {
case 'v':
log_set_output_level(atoi(optarg));
@@ -652,7 +727,7 @@
octstr_compare(content_flag, octstr_imm("mms")) != 0 &&
octstr_compare(content_flag, octstr_imm("scrap")) != 0 &&
octstr_compare(content_flag,
- octstr_imm("multipart")) != 0){
+ octstr_imm("multipart")) != 0) {
octstr_destroy(content_flag);
error(0, "TEST_PPG: Content type not known");
help();
@@ -674,14 +749,21 @@
}
break;
+ case 'n':
+ use_numeric = 1;
+ break;
+
+ case 's':
+ appid_string = octstr_create(optarg);
+ use_string = 1;
+ break;
+
case 'e':
content_transfer_encoding = octstr_create(optarg);
- if (octstr_compare(content_transfer_encoding,
- octstr_imm("base64")) != 0) {
+ if (octstr_compare(content_transfer_encoding, octstr_imm("base64")) != 0) {
octstr_destroy(content_transfer_encoding);
error(0, "TEST_PPG: unknown content transfer"
- " encoding \"%s\"",
- octstr_get_cstr(content_transfer_encoding));
+ " encoding \"%s\"", octstr_get_cstr(content_transfer_encoding));
help();
exit(1);
}
@@ -690,8 +772,7 @@
case 'k':
connection = octstr_create(optarg);
if (octstr_compare(connection, octstr_imm("close")) != 0 &&
- octstr_compare(connection,
- octstr_imm("keep-alive")) != 0) {
+ octstr_compare(connection, octstr_imm("keep-alive")) != 0) {
octstr_destroy(connection);
error(0, "TEST_PPG: Connection-header unacceptable");
help();
@@ -707,6 +788,29 @@
use_headers = 1;
break;
+ case 'B':
+ accept_binary = 1;
+ break;
+
+ case 'd':
+ delimiter = octstr_create(optarg);
+ if (octstr_compare(delimiter, octstr_imm("crlf")) != 0 &&
+ octstr_compare(delimiter, octstr_imm("lf")) != 0) {
+ octstr_destroy(delimiter);
+ error(0, "illegal d value");
+ help();
+ exit(1);
+ }
+ break;
+
+ case 'E':
+ add_epilogue = 1;
+ break;
+
+ case 'p':
+ add_preamble = 1;
+ break;
+
case '?':
default:
error(0, "TEST_PPG: Invalid option %c", opt);
@@ -730,6 +834,12 @@
if (appid_flag == NULL)
appid_flag = octstr_imm("ua");
+ if (appid_string == NULL)
+ appid_string = octstr_imm("x-wap-application-id: wml.ua");
+
+ if (delimiter == NULL)
+ delimiter = octstr_imm("crlf");
+
if (use_hardcoded) {
username = octstr_imm("troo");
password = octstr_imm("far");
@@ -792,6 +902,7 @@
octstr_destroy(password);
octstr_destroy(push_url);
octstr_destroy(connection);
+ octstr_destroy(delimiter);;
counter_destroy(counter);
gwlib_shutdown();
Index: wap/wsp_headers.c
===================================================================
RCS file: /home/cvs/gateway/wap/wsp_headers.c,v
retrieving revision 1.6
diff -B -b -u -r1.6 wsp_headers.c
--- wap/wsp_headers.c 19 Oct 2002 10:07:39 -0000 1.6
+++ wap/wsp_headers.c 28 May 2003 10:20:31 -0000
@@ -250,7 +250,8 @@
return convert_q_value(c);
}
-/* Version-value is defined in 8.4.2.3 */
+/* Version-value is defined in 8.4.2.3. Encoding-Version uses coding
+ * defined in this chapter, see 8.4.2.70. */
static Octstr *unpack_version_value(long value)
{
Octstr *result;
@@ -269,6 +270,19 @@
return result;
}
+static Octstr *unpack_encoding_version(ParseContext *context)
+{
+ int ch;
+
+ ch = parse_get_char(context);
+ if (ch < 128) {
+ warning(0, "WSP: bad Encoding-Version value");
+ return NULL;
+ }
+
+ return unpack_version_value(((long) ch) - 128);
+}
+
/* Called with the parse limit set to the end of the parameter data,
* and decoded containing the unpacked header line so far.
* Parameter is defined in 8.4.2.4. */
@@ -1155,6 +1169,10 @@
decoded = unpack_disposition(context);
break;
+ case WSP_HEADER_ENCODING_VERSION:
+ decoded = unpack_encoding_version(context);
+ break;
+
default:
if (headername) {
warning(0, "Did not expect value-length with "
@@ -1331,6 +1349,7 @@
static int pack_transfer_encoding(Octstr *packet, Octstr *value);
static int pack_uri(Octstr *packet, Octstr *value);
static int pack_warning(Octstr *packet, Octstr *value);
+static int pack_version_value(Octstr *packet, Octstr *value);
/* LIST is a comma-separated list such as is described in the "#rule"
* entry of RFC2616 section 2.1. */
@@ -1396,10 +1415,11 @@
{ WSP_HEADER_WARNING, pack_warning, LIST },
{ WSP_HEADER_WWW_AUTHENTICATE, pack_challenge, BROKEN_LIST },
{ WSP_HEADER_CONTENT_DISPOSITION, pack_content_disposition, 0 },
- { WSP_HEADER_PUSH_FLAG, pack_integer_string, 0},
- { WSP_HEADER_X_WAP_CONTENT_URI, pack_uri, 0},
- { WSP_HEADER_X_WAP_INITIATOR_URI, pack_uri, 0},
- { WSP_HEADER_X_WAP_APPLICATION_ID, pack_integer_string, 0}
+ { WSP_HEADER_PUSH_FLAG, pack_integer_string, 0 },
+ { WSP_HEADER_X_WAP_CONTENT_URI, pack_uri, 0 },
+ { WSP_HEADER_X_WAP_INITIATOR_URI, pack_uri, 0 },
+ { WSP_HEADER_X_WAP_APPLICATION_ID, pack_integer_string, 0 },
+ { WSP_HEADER_ENCODING_VERSION, pack_version_value, 0 }
};
static Parameter *parm_create(Octstr *key, Octstr *value)
@@ -1743,7 +1763,7 @@
return -1;
}
-static void pack_version_value(Octstr *packed, Octstr *version)
+static int pack_version_value(Octstr *packed, Octstr *version)
{
long major, minor;
long pos;
@@ -1763,10 +1783,11 @@
}
pack_short_integer(packed, major << 4 | minor);
- return;
+ return 0;
usetext:
pack_text(packed, version);
+ return 0;
}
static int pack_constrained_value(Octstr *packed, Octstr *text, long value)
Index: wap/wsp_session.c
===================================================================
RCS file: /home/cvs/gateway/wap/wsp_session.c,v
retrieving revision 1.13
diff -B -b -u -r1.13 wsp_session.c
--- wap/wsp_session.c 14 May 2002 11:05:08 -0000 1.13
+++ wap/wsp_session.c 28 May 2003 10:20:31 -0000
@@ -87,6 +87,10 @@
static unsigned long next_wsp_session_id(void);
static List *make_capabilities_reply(WSPMachine *m);
+static List *make_reply_headers(WSPMachine *m);
+static int is_default_version(WSPMachine *m);
+static int is_higher_version(WSPMachine *m);
+static int is_lower_version(WSPMachine *m);
static Octstr *make_connectreply_pdu(WSPMachine *m);
static Octstr *make_resume_reply_pdu(WSPMachine *m, List *headers);
static WSP_PDU *make_confirmedpush_pdu(WAPEvent *e);
@@ -946,11 +950,91 @@
return caps;
}
+static int is_default_version(WSPMachine *m)
+{
+ Octstr *request_version;
+
+ request_version = http_header_value(m->http_headers, octstr_imm("Encoding-Version"));
+ if (request_version == NULL) {
+ return 1;
+ } else {
+ octstr_destroy(request_version);
+ return 0;
+ }
+}
+
+static int is_higher_version(WSPMachine *m)
+{
+ Octstr *request_version;
+
+ request_version = http_header_value(m->http_headers, octstr_imm("Encoding-Version"));
+ if (request_version && octstr_compare(request_version, octstr_imm("1.1")) != 0 &&
+ octstr_compare(request_version, octstr_imm("1.2")) != 0 &&
+ octstr_compare(request_version, octstr_imm("1.3")) != 0) {
+ octstr_destroy(request_version);
+ return 1;
+ } else {
+ octstr_destroy(request_version);
+ return 0;
+ }
+}
+
+static int is_lower_version(WSPMachine *m)
+{
+ Octstr *request_version;
+
+ request_version = http_header_value(m->http_headers, octstr_imm("Encoding-Version"));
+ if (request_version && (octstr_compare(request_version, octstr_imm("1.1")) == 0 ||
+ octstr_compare(request_version, octstr_imm("1.2")) == 0)) {
+ octstr_destroy(request_version);
+ return 1;
+ } else {
+ octstr_destroy(request_version);
+ return 0;
+ }
+}
+
+static List *make_reply_headers(WSPMachine *m)
+{
+ List *headers;
+ Octstr *encoding_version;
+ Octstr *request_version;
+
+ /* Add all server wsp level hop-by-hop headers. Currently only
+ * Encoding-Version, as defined by wsp, chapter 8.4.2.70.
+ * What headers belong to which version is defined in appendix A,
+ * table 39..
+ encoding_version = request_version = NULL;
+ * Essentially, if the client sends us an Encoding-Version
+ * higher than ours (1.3) we send our version number to it,
+ * if it is lower, we left version number intact. */
+ /* First the case that we have no Encoding-Version header at all.
+ * This case we must assume that the client supports version 1.2
+ * or lower. */
+ if (is_default_version(m)) {
+ encoding_version = octstr_create("1.2");
+ } else if (is_higher_version(m)) {
+ encoding_version = octstr_create("1.3");
+ } else if (is_lower_version(m)) {
+ request_version = http_header_value(m->http_headers, octstr_imm("Encoding-Version"));
+ encoding_version = octstr_duplicate(request_version);
+ octstr_destroy(request_version);
+ } else {
+ encoding_version = octstr_create("1.3");
+ }
+
+ headers = http_create_empty_headers();
+ http_header_add(headers, "Encoding-Version", octstr_get_cstr(encoding_version));
+ octstr_destroy(encoding_version);
+
+ return headers;
+}
static Octstr *make_connectreply_pdu(WSPMachine *m) {
WSP_PDU *pdu;
Octstr *os;
List *caps;
+ List *reply_headers;
pdu = wsp_pdu_create(ConnectReply);
@@ -959,7 +1043,10 @@
caps = make_capabilities_reply(m);
pdu->u.ConnectReply.capabilities = wsp_cap_pack_list(caps);
wsp_cap_destroy_list(caps);
- pdu->u.ConnectReply.headers = NULL;
+
+ reply_headers = make_reply_headers(m);
+ pdu->u.ConnectReply.headers = wsp_headers_pack(reply_headers, 0);
+ http_destroy_headers(reply_headers);
os = wsp_pdu_pack(pdu);
wsp_pdu_destroy(pdu);
Index: wap/wsp_strings.def
===================================================================
RCS file: /home/cvs/gateway/wap/wsp_strings.def,v
retrieving revision 1.6
diff -B -b -u -r1.6 wsp_strings.def
--- wap/wsp_strings.def 4 Sep 2002 09:16:31 -0000 1.6
+++ wap/wsp_strings.def 28 May 2003 10:20:31 -0000
@@ -109,7 +109,7 @@
NSTRING("Encoding-Version", WSP_HEADER_ENCODING_VERSION)
)
-/* Table 40. Content Type Assignments */
+/* Table 40. Content Type Assignments. Only to wsp version 1.3. */
LINEAR(content_type,
STRING("*/*")
STRING("text/*")
@@ -166,14 +166,14 @@
STRING("application/vnd.wap.sia")
STRING("text/vnd.wap.connectivity-xml")
STRING("application/vnd.wap.connectivity-wbxml")
-STRING("application/pkcs7-mime")
+/*STRING("application/pkcs7-mime")
STRING("application/vnd.wap.hashed-certificate")
STRING("application/vnd.wap.signed-certificate")
STRING("application/vnd.wap.cert-response")
STRING("application/xhtml+xml")
STRING("application/wml+xml")
STRING("text/css")
-STRING("application/vnd.wap.mms-message")
+STRING("application/vnd.wap.mms-message")*/
)
/* Table 42, Character Set Assignment (partial) */
@@ -465,6 +465,22 @@
ASSIGN("mms.ua", 0x04)
ASSIGN("push.syncml", 0x05)
ASSIGN("loc.ua", 0x06)
+ASSIGN("syncml.dm", 0x07)
+ASSIGN("drm.ua", 0x08)
+ASSIGN("emn.ua", 0x09)
+ASSIGN("wv.ua", 0x0A)
+ASSIGN("x-wap-microsoft:localcontent.ua", 0x8000)
+ASSIGN("x-wap-microsoft:IMclient.ua", 0x8001)
+ASSIGN("x-wap-docomo:imode.mail.ua", 0x8002)
+ASSIGN("x-wap-docomo:imode.mr.ua", 0x8003)
+ASSIGN("x-wap-docomo:imode.mf.ua", 0x8004)
+ASSIGN("x-motorola:location.ua", 0x8005)
+ASSIGN("x-motorola:now.ua", 0x8006)
+ASSIGN("x-motorola:otaprov.ua", 0x8007)
+ASSIGN("x-motorola:browser.ua", 0x8008)
+ASSIGN("x-motorola:splash.ua", 0x8009)
+ASSIGN("x-wap-nai:mvsw.command", 0x800B)
+ASSIGN("x-wap-openvawe:iota.ua", 0x8010)
)
/**** More preprocessor magic ****/
Index: wap/wsp_unit.c
===================================================================
RCS file: /home/cvs/gateway/wap/wsp_unit.c,v
retrieving revision 1.12
diff -B -b -u -r1.12 wsp_unit.c
--- wap/wsp_unit.c 13 Feb 2003 10:34:09 -0000 1.12
+++ wap/wsp_unit.c 28 May 2003 10:20:31 -0000
@@ -192,7 +192,10 @@
/*
* We do not set TUnitData.ind's SMS-specific fields here, because we do not
- * support sending results to the phone over SMS.
+ * support sending results to the phone over SMS. Wsp, chapter 8.4.1 states
+ * that "that each peer entity is always associated with an encoding version.".
+ * So we add Encoding-Version when we are sending something to the client.
+ * (This includes push, which is not directly mentioned in chapter 8.4.2.70).
*/
static WAPEvent *pack_into_result_datagram(WAPEvent *event) {
WAPEvent *datagram;
@@ -204,6 +207,8 @@
gw_assert(event->type == S_Unit_MethodResult_Req);
p = &event->u.S_Unit_MethodResult_Req;
+ http_header_add(p->response_headers, "Encoding-Version", "1.3");
+
pdu = wsp_pdu_create(Reply);
pdu->u.Reply.status = wsp_convert_http_status_to_wsp_status(p->status);
pdu->u.Reply.headers = wsp_headers_pack(p->response_headers, 1);
@@ -236,6 +241,10 @@
gw_assert(event->type == S_Unit_Push_Req);
debug("wap.wsp.unit", 0, "WSP_UNIT: Connectionless push accepted");
+
+ http_header_add(event->u.S_Unit_Push_Req.push_headers,
+ "Encoding-Version", "1.3");
+
pdu = wsp_pdu_create(Push);
pdu->u.Push.headers = wsp_headers_pack(
event->u.S_Unit_Push_Req.push_headers, 1);