OSDN Git Service

implement http_defaultheaderparser_t.
authorornse01 <ornse01@users.sourceforge.jp>
Sun, 29 Jan 2012 07:34:40 +0000 (07:34 +0000)
committerornse01 <ornse01@users.sourceforge.jp>
Sun, 29 Jan 2012 07:34:40 +0000 (07:34 +0000)
git-svn-id: http://svn.sourceforge.jp/svnroot/bchan/bchanf/trunk@366 20a0b8eb-f62a-4a12-8fe1-b598822500fb

src/http/http_defaultheaderparser.c [new file with mode: 0644]
src/http/http_defaultheaderparser.h [new file with mode: 0644]
src/http/test_http_defaultheaderparser.c [new file with mode: 0644]

diff --git a/src/http/http_defaultheaderparser.c b/src/http/http_defaultheaderparser.c
new file mode 100644 (file)
index 0000000..655bdd8
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * http_defaultheaderparser.c
+ *
+ * Copyright (c) 2012 project bchan
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ *    distribution.
+ *
+ */
+
+#include "http_defaultheaderparser.h"
+
+#include       <basic.h>
+#include       <bstdio.h>
+#include       <bctype.h>
+
+#include    "http_typedef.h"
+#include    "http_headerlexer.h"
+#include    <parse/tokenchecker.h>
+
+#ifdef BCHAN_CONFIG_DEBUG
+# define DP(arg) printf arg
+# define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
+#else
+# define DP(arg) /**/
+# define DP_ER(msg, err) /**/
+#endif
+
+#if 0
+# define DP_STATE(state) printf("%s\n", state)
+#else
+# define DP_STATE(state) /**/
+#endif
+
+enum {
+       HTTP_DHP_FIELDNAME_CONTENT_ENCODING = 1,
+       HTTP_DHP_FIELDNAME_CONTENT_LENGTH,
+       HTTP_DHP_FIELDNAME_TRANSER_ENCODING,
+       HTTP_DHP_FIELDNAME_CONNECTION,
+};
+
+LOCAL VOID http_defaultheaderparser_inputhlex(http_defaultheaderparser_t *parser, http_headerlexer_result *cmd, HTTP_DEFAULTHEADERPARSER_RESULT *result)
+{
+       TOKENCHECKER_RESULT tchk;
+       W val;
+
+       switch (parser->state) {
+       case HTTP_DEFAULTHEADERPARSER_STATE_FIELDNAME:
+               DP_STATE("FIELDNAME");
+               if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDNAME) {
+                       tchk = tokenchecker_inputchar(&parser->checker.fieldname, cmd->ch, &val);
+                       if (tchk == TOKENCHECKER_RESULT_CONTINUE_NOMATCH) {
+                               parser->state = HTTP_DEFAULTHEADERPARSER_STATE_SKIP_FIELDNAME;
+                       } else if (tchk != TOKENCHECKER_RESULT_CONTINUE) {
+                               /* format error */
+                               DP(("format error 0\n"));
+                       }
+               } else if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDNAME_END) {
+                       tchk = tokenchecker_endinput(&parser->checker.fieldname, &val);
+                       if (tchk == TOKENCHECKER_RESULT_DETERMINE) {
+                               switch (val) {
+                               case HTTP_DHP_FIELDNAME_CONTENT_ENCODING:
+                                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_CONTENT_ENCODING_LWS;
+                                       break;
+                               case HTTP_DHP_FIELDNAME_CONTENT_LENGTH:
+                                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_CONTENT_LENGTH_LWS;
+                                       break;
+                               case HTTP_DHP_FIELDNAME_TRANSER_ENCODING:
+                                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_TRANSFER_ENCODING_LWS;
+                                       break;
+                               case HTTP_DHP_FIELDNAME_CONNECTION:
+                                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_CONNECTION_LWS;
+                                       break;
+                               default:
+                                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_SKIP_FIELDVALUE;
+                                       break;
+                               }
+                       } else if (tchk == TOKENCHECKER_RESULT_NOMATCH) {
+                       } else {
+                               /* format error */
+                               DP(("format error 1\n"));
+                       }
+               } else if (cmd->type == HTTP_HEADERLEXER_RESULT_MESSAGEHEADER_END) { 
+                       *result = HTTP_DEFAULTHEADERPARSER_RESULT_MESSAGE_HEADER_END;
+               } else {
+                       /* format error */
+                       DP(("format error 2\n"));
+               }
+               break;
+       case HTTP_DEFAULTHEADERPARSER_STATE_SKIP_FIELDNAME:
+               DP_STATE("SKIP_FIELDNAME");
+               if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDNAME_END) {
+                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_SKIP_FIELDVALUE;
+               } else if (cmd->type != HTTP_HEADERLEXER_RESULT_FIELDNAME) {
+                       /* format error */
+                       DP(("format error 3\n"));
+               }
+               break;
+       case HTTP_DEFAULTHEADERPARSER_STATE_SKIP_FIELDVALUE:
+               DP_STATE("SKIP_FIELDVALUE");
+               if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDVALUE_END) {
+                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_FIELDNAME;
+                       tokenchecker_clear(&parser->checker.fieldname);                 
+               } else if ((cmd->type != HTTP_HEADERLEXER_RESULT_FIELDCONTENT)&&(cmd->type != HTTP_HEADERLEXER_RESULT_LWS)) {
+                       /* format error */
+                       DP(("format error 4\n"));
+               }
+               break;
+       case HTTP_DEFAULTHEADERPARSER_STATE_CONTENT_ENCODING_LWS:
+               DP_STATE("CONTENT_ENCODING_LWS");
+               if (cmd->type == HTTP_HEADERLEXER_RESULT_LWS) {
+                       break;
+               } else if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDVALUE_END) {
+                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_FIELDNAME;
+                       tokenchecker_clear(&parser->checker.fieldname);
+               } else if (cmd->type != HTTP_HEADERLEXER_RESULT_FIELDCONTENT) {
+                       /* format error */
+                       DP(("format error 5\n"));
+               }
+               parser->state = HTTP_DEFAULTHEADERPARSER_STATE_CONTENT_ENCODING;
+               tokenchecker_clear(&parser->checker.contentcoding);
+       case HTTP_DEFAULTHEADERPARSER_STATE_CONTENT_ENCODING:
+               DP_STATE("CONTENT_ENCODING");
+               if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDCONTENT) {
+                       tchk = tokenchecker_inputchar(&parser->checker.contentcoding, cmd->ch, &val);
+                       if (tchk == TOKENCHECKER_RESULT_CONTINUE_NOMATCH) {
+                               parser->state = HTTP_DEFAULTHEADERPARSER_STATE_SKIP_FIELDVALUE;
+                       } else if (tchk != TOKENCHECKER_RESULT_CONTINUE) {
+                               /* format error */
+                               DP(("format error 6\n"));
+                       }
+               } else if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDVALUE_END) {
+                       tchk = tokenchecker_endinput(&parser->checker.contentcoding, &val);
+                       if (tchk == TOKENCHECKER_RESULT_DETERMINE) {
+                               parser->result.contentcoding = val;
+                       } else if (tchk == TOKENCHECKER_RESULT_NOMATCH) {
+                       } else {
+                               /* format error */
+                               DP(("format error 7\n"));
+                       }
+                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_FIELDNAME;
+                       tokenchecker_clear(&parser->checker.fieldname);
+               } else {
+                       /* format error */
+                       DP(("format error 8\n"));
+               }
+               break;
+       case HTTP_DEFAULTHEADERPARSER_STATE_TRANSFER_ENCODING_LWS:
+               DP_STATE("TRANSFER_ENCODING_LWS");
+               if (cmd->type == HTTP_HEADERLEXER_RESULT_LWS) {
+                       break;
+               } else if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDVALUE_END) {
+                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_FIELDNAME;
+                       tokenchecker_clear(&parser->checker.fieldname);
+               } else if (cmd->type != HTTP_HEADERLEXER_RESULT_FIELDCONTENT) {
+                       /* format error */
+                       DP(("format error 9\n"));
+               }
+               parser->state = HTTP_DEFAULTHEADERPARSER_STATE_TRANSFER_ENCODING;
+               tokenchecker_clear(&parser->checker.transfercoding);
+       case HTTP_DEFAULTHEADERPARSER_STATE_TRANSFER_ENCODING:
+               DP_STATE("TRANSFER_ENCODING");
+               if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDCONTENT) {
+                       tchk = tokenchecker_inputchar(&parser->checker.transfercoding, cmd->ch, &val);
+                       if (tchk == TOKENCHECKER_RESULT_CONTINUE_NOMATCH) {
+                               parser->state = HTTP_DEFAULTHEADERPARSER_STATE_SKIP_FIELDVALUE;
+                       } else if (tchk != TOKENCHECKER_RESULT_CONTINUE) {
+                               /* format error */
+                               DP(("format error 10\n"));
+                       }
+               } else if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDVALUE_END) {
+                       tchk = tokenchecker_endinput(&parser->checker.transfercoding, &val);
+                       if (tchk == TOKENCHECKER_RESULT_DETERMINE) {
+                               parser->result.transfercoding = val;
+                       } else if (tchk == TOKENCHECKER_RESULT_NOMATCH) {
+                       } else {
+                               /* format error */
+                               DP(("format error 11\n"));
+                       }
+                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_FIELDNAME;
+                       tokenchecker_clear(&parser->checker.fieldname);
+               } else {
+                       /* format error */
+                       DP(("format error 12\n"));
+               }
+               break;
+       case HTTP_DEFAULTHEADERPARSER_STATE_CONNECTION_LWS:
+               DP_STATE("CONNECTION_LWS");
+               if (cmd->type == HTTP_HEADERLEXER_RESULT_LWS) {
+                       break;
+               } else if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDVALUE_END) {
+                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_FIELDNAME;
+                       tokenchecker_clear(&parser->checker.fieldname);
+               } else if (cmd->type != HTTP_HEADERLEXER_RESULT_FIELDCONTENT){
+                       /* format error */
+                       DP(("format error 13\n"));
+               }
+               parser->state = HTTP_DEFAULTHEADERPARSER_STATE_CONNECTION;
+               tokenchecker_clear(&parser->checker.connection);
+       case HTTP_DEFAULTHEADERPARSER_STATE_CONNECTION:
+               DP_STATE("CONNECTION");
+               if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDCONTENT) {
+                       tchk = tokenchecker_inputchar(&parser->checker.connection, cmd->ch, &val);
+                       if (tchk == TOKENCHECKER_RESULT_CONTINUE_NOMATCH) {
+                               parser->state = HTTP_DEFAULTHEADERPARSER_STATE_SKIP_FIELDVALUE;
+                       } else if (tchk != TOKENCHECKER_RESULT_CONTINUE) {
+                               /* format error */
+                               DP(("format error 14\n"));
+                       }
+               } else if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDVALUE_END) {
+                       tchk = tokenchecker_endinput(&parser->checker.connection, &val);
+                       if (tchk == TOKENCHECKER_RESULT_DETERMINE) {
+                               if (val == 1) {
+                                       parser->result.connectionclosed = True;
+                               } else {
+                                       /* unexpected token */
+                                       DP(("unexpected token\n"));
+                               }
+                       } else if (tchk == TOKENCHECKER_RESULT_NOMATCH) {
+                       } else {
+                               /* format error */
+                               DP(("format error 15\n"));
+                       }
+                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_FIELDNAME;
+                       tokenchecker_clear(&parser->checker.fieldname);
+               } else {
+                       /* format error */
+                       DP(("format error 16\n"));
+               }
+               break;
+       case HTTP_DEFAULTHEADERPARSER_STATE_CONTENT_LENGTH_LWS:
+               DP_STATE("CONTENT_LENGTH_LWS");
+               if (cmd->type == HTTP_HEADERLEXER_RESULT_LWS) {
+                       break;
+               } else if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDVALUE_END) {
+                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_FIELDNAME;
+                       tokenchecker_clear(&parser->checker.fieldname);
+               } else if (cmd->type != HTTP_HEADERLEXER_RESULT_FIELDCONTENT){
+                       /* format error */
+                       DP(("format error 17\n"));
+               }
+               parser->state = HTTP_DEFAULTHEADERPARSER_STATE_CONTENT_LENGTH;
+               parser->result.contentlength = 0;
+       case HTTP_DEFAULTHEADERPARSER_STATE_CONTENT_LENGTH:
+               DP_STATE("CONTENT_LENGTH");
+               if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDCONTENT) {
+                       if (isdigit(cmd->ch) != 0) {
+                               parser->result.contentlength = parser->result.contentlength * 10 + (cmd->ch - '0');
+                       } else {
+                               parser->state = HTTP_DEFAULTHEADERPARSER_STATE_SKIP_FIELDVALUE;
+                       }
+               } else if (cmd->type == HTTP_HEADERLEXER_RESULT_LWS) { 
+                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_SKIP_FIELDVALUE;
+               } else if (cmd->type == HTTP_HEADERLEXER_RESULT_FIELDVALUE_END) {
+                       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_FIELDNAME;
+                       tokenchecker_clear(&parser->checker.fieldname);
+               } else {
+                       /* format error */
+                       DP(("format error 18\n"));
+               }
+               break;
+       }
+}
+
+EXPORT VOID http_defaultheaderparser_inputchar(http_defaultheaderparser_t *parser, UB ch, HTTP_DEFAULTHEADERPARSER_RESULT *result)
+{
+       http_headerlexer_result *hlex;
+       W i, result_len;
+
+       http_headerlexer_inputchar(&parser->header, ch, &hlex, &result_len);
+
+       for (i = 0; i < result_len; i++) {
+               *result = HTTP_DEFAULTHEADERPARSER_RESULT_NONE;
+               if (hlex[i].type == HTTP_HEADERLEXER_RESULT_NONE) {
+                       continue;
+               }
+               http_defaultheaderparser_inputhlex(parser, hlex+i, result);
+       }
+}
+
+EXPORT W http_defaultheaderparsr_contentlength(http_defaultheaderparser_t *parser)
+{
+       return parser->result.contentlength;
+}
+
+EXPORT HTTP_TRANSFERCODING_TYPE http_defaultheaderparsr_transferencoding(http_defaultheaderparser_t *parser)
+{
+       return parser->result.transfercoding;
+}
+
+EXPORT HTTP_CONTENTCODING_VALUE http_defaultheaderparsr_contentencoding(http_defaultheaderparser_t *parser)
+{
+       return parser->result.contentcoding;
+}
+
+EXPORT Bool http_defaultheaderparser_connectionclosed(http_defaultheaderparser_t *parser)
+{
+       return parser->result.connectionclosed;
+}
+
+LOCAL tokenchecker_valuetuple_t nList_fieldname[] = {
+       {"Connection", HTTP_DHP_FIELDNAME_CONNECTION},
+       {"Content-Encoding", HTTP_DHP_FIELDNAME_CONTENT_ENCODING},
+       {"Content-Length", HTTP_DHP_FIELDNAME_CONTENT_LENGTH},
+       {"Transfer-Encoding", HTTP_DHP_FIELDNAME_TRANSER_ENCODING},
+};
+LOCAL B eToken_fieldname[] = ":";
+
+LOCAL tokenchecker_valuetuple_t nList_transfercoding[] = {
+       {"chunked", HTTP_TRANSFERCODING_TYPE_CHUNKED},
+       {"identity", HTTP_TRANSFERCODING_TYPE_IDENTITY},
+};
+LOCAL B eToken_transfercoding[] = "\r";
+
+LOCAL tokenchecker_valuetuple_t nList_contentcoding[] = {
+       {"compress", HTTP_CONTENTCODING_VALUE_COMPRESS},
+       {"deflate", HTTP_CONTENTCODING_VALUE_DEFLATE},
+       {"gzip", HTTP_CONTENTCODING_VALUE_GZIP},
+       {"identity", HTTP_CONTENTCODING_VALUE_IDENTITY},
+};
+LOCAL B eToken_contentcoding[] = "\r";
+
+LOCAL tokenchecker_valuetuple_t nList_connection[] = {
+       {"close", 1},
+};
+LOCAL B eToken_connection[] = "\r";
+
+EXPORT VOID http_defaultheaderparser_initialize(http_defaultheaderparser_t *parser)
+{
+       parser->state = HTTP_DEFAULTHEADERPARSER_STATE_FIELDNAME;
+       http_headerlexer_initialize(&parser->header);
+       tokenchecker_initialize(&(parser->checker.fieldname), nList_fieldname, 4, eToken_fieldname);
+       tokenchecker_initialize(&(parser->checker.transfercoding), nList_transfercoding, 2, eToken_transfercoding);
+       tokenchecker_initialize(&(parser->checker.contentcoding), nList_contentcoding, 4, eToken_contentcoding);
+       tokenchecker_initialize(&(parser->checker.connection), nList_connection, 1, eToken_connection);
+       parser->result.contentlength = 0;
+       parser->result.transfercoding = HTTP_TRANSFERCODING_TYPE_IDENTITY;
+       parser->result.contentcoding = HTTP_CONTENTCODING_VALUE_IDENTITY;
+       parser->result.connectionclosed = False;
+}
+
+EXPORT VOID http_defaultheaderparser_finalize(http_defaultheaderparser_t *parser)
+{
+       tokenchecker_finalize(&(parser->checker.connection));
+       tokenchecker_finalize(&(parser->checker.contentcoding));
+       tokenchecker_finalize(&(parser->checker.transfercoding));
+       tokenchecker_finalize(&(parser->checker.fieldname));
+       http_headerlexer_finalize(&parser->header);
+}
diff --git a/src/http/http_defaultheaderparser.h b/src/http/http_defaultheaderparser.h
new file mode 100644 (file)
index 0000000..86caaee
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * http_defaultheaderparser.h
+ *
+ * Copyright (c) 2012 project bchan
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ *    distribution.
+ *
+ */
+
+/* Vendor name: */
+/* Functionality name: http */
+/* Detail name: defaultheaderparser */
+
+#include    <basic.h>
+
+#include    "http_typedef.h"
+#include    "http_headerlexer.h"
+#include    <parse/tokenchecker.h>
+
+/* HTTP header parser for using in http_connector_t. */
+/*   Content-Encoding, Content-Length, Transfer-Encoding, Connection */
+
+#ifndef __HTTP_DEFAULTHEADERPARSER_H__
+#define __HTTP_DEFAULTHEADERPARSER_H__
+
+/* Functionality name: http */
+/* Detail name: defaultheaderparser */
+struct http_defaultheaderparser_t_ {
+       enum {
+               HTTP_DEFAULTHEADERPARSER_STATE_FIELDNAME,
+               HTTP_DEFAULTHEADERPARSER_STATE_SKIP_FIELDNAME,
+               HTTP_DEFAULTHEADERPARSER_STATE_SKIP_FIELDVALUE,
+               HTTP_DEFAULTHEADERPARSER_STATE_CONTENT_ENCODING_LWS,
+               HTTP_DEFAULTHEADERPARSER_STATE_CONTENT_ENCODING,
+               HTTP_DEFAULTHEADERPARSER_STATE_CONTENT_LENGTH_LWS,
+               HTTP_DEFAULTHEADERPARSER_STATE_CONTENT_LENGTH,
+               HTTP_DEFAULTHEADERPARSER_STATE_TRANSFER_ENCODING_LWS,
+               HTTP_DEFAULTHEADERPARSER_STATE_TRANSFER_ENCODING,
+               HTTP_DEFAULTHEADERPARSER_STATE_CONNECTION_LWS,
+               HTTP_DEFAULTHEADERPARSER_STATE_CONNECTION,
+       } state;
+       http_headerlexer_t header;
+       struct {
+               tokenchecker_t fieldname;
+               tokenchecker_t transfercoding;
+               tokenchecker_t contentcoding;
+               tokenchecker_t connection;
+       } checker;
+       struct {
+               W contentlength;
+               HTTP_TRANSFERCODING_TYPE transfercoding;
+               HTTP_CONTENTCODING_VALUE contentcoding;
+               Bool connectionclosed;
+       } result;
+};
+typedef struct http_defaultheaderparser_t_ http_defaultheaderparser_t;
+
+/* Functionality name: http */
+/* Detail name: defaultheaderparser */
+/* Data structure identifier: RESULT */
+enum HTTP_DEFAULTHEADERPARSER_RESULT_ {
+       HTTP_DEFAULTHEADERPARSER_RESULT_NONE,
+       /*HTTP_DEFAULTHEADERPARSER_RESULT_FIELD_VALUE_END,*/
+       HTTP_DEFAULTHEADERPARSER_RESULT_MESSAGE_HEADER_END
+};
+typedef enum HTTP_DEFAULTHEADERPARSER_RESULT_ HTTP_DEFAULTHEADERPARSER_RESULT;
+
+IMPORT VOID http_defaultheaderparser_initialize(http_defaultheaderparser_t *parser);
+IMPORT VOID http_defaultheaderparser_finalize(http_defaultheaderparser_t *parser);
+IMPORT VOID http_defaultheaderparser_inputchar(http_defaultheaderparser_t *parser, UB ch, HTTP_DEFAULTHEADERPARSER_RESULT *result);
+IMPORT W http_defaultheaderparsr_contentlength(http_defaultheaderparser_t *parser);
+IMPORT HTTP_TRANSFERCODING_TYPE http_defaultheaderparsr_transferencoding(http_defaultheaderparser_t *parser);
+IMPORT HTTP_CONTENTCODING_VALUE http_defaultheaderparsr_contentencoding(http_defaultheaderparser_t *parser);
+IMPORT Bool http_defaultheaderparser_connectionclosed(http_defaultheaderparser_t *parser);
+
+#endif
diff --git a/src/http/test_http_defaultheaderparser.c b/src/http/test_http_defaultheaderparser.c
new file mode 100644 (file)
index 0000000..2c6a351
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * test_http_defaultheaderparser.c
+ *
+ * Copyright (c) 2012 project bchan
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ *    distribution.
+ *
+ */
+
+#include "test_http.h"
+
+#include "http_defaultheaderparser.h"
+
+#include       <basic.h>
+#include       <bstdio.h>
+#include       <bstdlib.h>
+#include       <bstring.h>
+
+#include    <unittest_driver.h>
+
+#include    "http_typedef.h"
+
+LOCAL UNITTEST_RESULT test_http_defaultheaderparser_common(UB *testdata, W testdata_len, W expected_cl, HTTP_TRANSFERCODING_TYPE expected_tc, HTTP_CONTENTCODING_VALUE expected_cc, Bool expected_connectionclose)
+{
+       http_defaultheaderparser_t parser;
+       HTTP_DEFAULTHEADERPARSER_RESULT result;
+       W i;
+       UNITTEST_RESULT ret = UNITTEST_RESULT_PASS;
+       W cl;
+       HTTP_TRANSFERCODING_TYPE tc;
+       HTTP_CONTENTCODING_VALUE cc;
+       Bool connectionclosed;
+
+       http_defaultheaderparser_initialize(&parser);
+
+       for (i = 0; i < testdata_len; i++) {
+               http_defaultheaderparser_inputchar(&parser, testdata[i], &result);
+               if (result == HTTP_DEFAULTHEADERPARSER_RESULT_MESSAGE_HEADER_END) {
+                       i++;
+                       break;
+               }
+       }
+       if (i != testdata_len) {
+               printf("end before header end\n");
+               ret = UNITTEST_RESULT_FAIL;
+       }
+       if (result != HTTP_DEFAULTHEADERPARSER_RESULT_MESSAGE_HEADER_END) {
+               printf("not return MESSAGE_HEADER_END\n");
+               ret = UNITTEST_RESULT_FAIL;
+       }
+
+       cl = http_defaultheaderparsr_contentlength(&parser);
+       if (expected_cl != cl) {
+               printf("Content-Length is not expected. expected = %d, result = %d\n", expected_cl, cl);
+               ret = UNITTEST_RESULT_FAIL;
+       }
+       tc = http_defaultheaderparsr_transferencoding(&parser);
+       if (expected_tc != tc) {
+               printf("Transfer-Encoding is not expected. expected = %d, result = %d\n", expected_tc, tc);
+               ret = UNITTEST_RESULT_FAIL;
+       }
+       cc = http_defaultheaderparsr_contentencoding(&parser);
+       if (expected_cc != cc) {
+               printf("Content-Encoding is not expected. expected = %d, result = %d\n", expected_cc, cc);
+               ret = UNITTEST_RESULT_FAIL;
+       }
+       connectionclosed = http_defaultheaderparser_connectionclosed(&parser);
+       if (expected_connectionclose != connectionclosed) {
+               printf("Connection is not expected. expected = %d, result = %d\n", expected_connectionclose, connectionclosed);
+               ret = UNITTEST_RESULT_FAIL;
+       }
+
+       http_defaultheaderparser_finalize(&parser);
+
+       return ret;
+}
+
+LOCAL UB testdata_header_01[] = {
+       "Date: Wed, 10 Dec 2008 21:33:30 GMT\r\n"
+       "Server: Apache/2.2.9\r\n"
+       "Vary: User-Agent,Accept-Encoding\r\n"
+       "Last-Modified: Wed, 24 Dec 2008 21:14:12 GMT\r\n"
+       "ETag: \"1a2dd38-446e-45ed15f9ad100\"-gzip\r\n"
+       "Accept-Ranges: bytes\r\n"
+       "Content-Encoding: gzip\r\n"
+       "Content-Length: 3511\r\n"
+       "Connection: close\r\n"
+       "Content-Type: text/plain; charset=Shift_JIS\r\n"
+       "\r\n"
+};
+
+LOCAL UNITTEST_RESULT test_http_defaultheaderparser_1()
+{
+       UB *testdata = testdata_header_01;
+       W testdata_len = strlen(testdata_header_01);
+       W expected_contentlength = 3511;
+       HTTP_TRANSFERCODING_TYPE expected_transfercoding = HTTP_TRANSFERCODING_TYPE_IDENTITY;
+       HTTP_CONTENTCODING_VALUE expected_contentcoding = HTTP_CONTENTCODING_VALUE_GZIP;
+       Bool expected_connectionclose = True;
+       return test_http_defaultheaderparser_common(testdata, testdata_len, expected_contentlength, expected_transfercoding, expected_contentcoding, expected_connectionclose);
+}
+
+LOCAL UB testdata_header_02[] = {
+       "Date: Wed, 10 Dec 2008 21:40:53 GMT\r\n"
+       "Server: Apache/2.2.9\r\n"
+       "Vary: User-Agent,Accept-Encoding\r\n"
+       "Last-Modified: Wed, 24 Dec 2008 21:39:58 GMT\r\n"
+       "ETag: \"1a2dd38-44a7-45ed1bbc0e780\"\r\n"
+       "Accept-Ranges: bytes\r\n"
+       "Content-Range: bytes 17517-17574/17575\r\n"
+       "Content-Length: 58\r\n"
+       "Connection: close\r\n"
+       "Content-Type: text/plain; charset=Shift_JIS\r\n"
+       "\r\n"
+};
+
+LOCAL UNITTEST_RESULT test_http_defaultheaderparser_2()
+{
+       UB *testdata = testdata_header_02;
+       W testdata_len = strlen(testdata_header_02);
+       W expected_contentlength = 58;
+       HTTP_TRANSFERCODING_TYPE expected_transfercoding = HTTP_TRANSFERCODING_TYPE_IDENTITY;
+       HTTP_CONTENTCODING_VALUE expected_contentcoding = HTTP_CONTENTCODING_VALUE_IDENTITY;
+       Bool expected_connectionclose = True;
+       return test_http_defaultheaderparser_common(testdata, testdata_len, expected_contentlength, expected_transfercoding, expected_contentcoding, expected_connectionclose);
+}
+
+LOCAL UB testdata_header_03[] = {
+       "Date: Wed, 10 Dec 2008 21:33:30 GMT\r\n"
+       "Server: Apache/2.2.9\r\n"
+       "Vary: User-Agent,Accept-Encoding\r\n"
+       "Last-Modified: Wed, 24 Dec 2008 21:14:12 GMT\r\n"
+       "ETag: \"1a2dd38-446e-45ed15f9ad100\"-gzip\r\n"
+       "Accept-Ranges: bytes\r\n"
+       "Content-Encoding: compress\r\n"
+       "Content-Length: 0\r\n"
+       "Content-Type: text/plain; charset=Shift_JIS\r\n"
+       "\r\n"
+};
+
+LOCAL UNITTEST_RESULT test_http_defaultheaderparser_3()
+{
+       UB *testdata = testdata_header_03;
+       W testdata_len = strlen(testdata_header_03);
+       W expected_contentlength = 0;
+       HTTP_TRANSFERCODING_TYPE expected_transfercoding = HTTP_TRANSFERCODING_TYPE_IDENTITY;
+       HTTP_CONTENTCODING_VALUE expected_contentcoding = HTTP_CONTENTCODING_VALUE_COMPRESS;
+       Bool expected_connectionclose = False;
+       return test_http_defaultheaderparser_common(testdata, testdata_len, expected_contentlength, expected_transfercoding, expected_contentcoding, expected_connectionclose);
+}
+
+LOCAL UB testdata_header_04[] = {
+       "Date: Wed, 10 Dec 2008 21:33:30 GMT\r\n"
+       "Server: Apache/2.2.9\r\n"
+       "Vary: User-Agent,Accept-Encoding\r\n"
+       "Last-Modified: Wed, 24 Dec 2008 21:14:12 GMT\r\n"
+       "ETag: \"1a2dd38-446e-45ed15f9ad100\"-gzip\r\n"
+       "Accept-Ranges: bytes\r\n"
+       "Content-Encoding: deflate\r\n"
+       "Content-Length: 12340\r\n"
+       "Content-Type: text/plain; charset=Shift_JIS\r\n"
+       "\r\n"
+};
+
+LOCAL UNITTEST_RESULT test_http_defaultheaderparser_4()
+{
+       UB *testdata = testdata_header_04;
+       W testdata_len = strlen(testdata_header_04);
+       W expected_contentlength = 12340;
+       HTTP_TRANSFERCODING_TYPE expected_transfercoding = HTTP_TRANSFERCODING_TYPE_IDENTITY;
+       HTTP_CONTENTCODING_VALUE expected_contentcoding = HTTP_CONTENTCODING_VALUE_DEFLATE;
+       Bool expected_connectionclose = False;
+       return test_http_defaultheaderparser_common(testdata, testdata_len, expected_contentlength, expected_transfercoding, expected_contentcoding, expected_connectionclose);
+}
+
+LOCAL UB testdata_header_05[] = {
+       "Date: Wed, 10 Dec 2008 21:33:30 GMT\r\n"
+       "Server: Apache/2.2.9\r\n"
+       "Vary: User-Agent,Accept-Encoding\r\n"
+       "Last-Modified: Wed, 24 Dec 2008 21:14:12 GMT\r\n"
+       "ETag: \"1a2dd38-446e-45ed15f9ad100\"-gzip\r\n"
+       "Accept-Ranges: bytes\r\n"
+       "Transfer-Encoding: chunked\r\n"
+       "Connection: close"
+       "Content-Type: text/plain; charset=Shift_JIS\r\n"
+       "\r\n"
+};
+
+LOCAL UNITTEST_RESULT test_http_defaultheaderparser_5()
+{
+       UB *testdata = testdata_header_05;
+       W testdata_len = strlen(testdata_header_05);
+       W expected_contentlength = 0;
+       HTTP_TRANSFERCODING_TYPE expected_transfercoding = HTTP_TRANSFERCODING_TYPE_CHUNKED;
+       HTTP_CONTENTCODING_VALUE expected_contentcoding = HTTP_CONTENTCODING_VALUE_IDENTITY;
+       Bool expected_connectionclose = False;
+       return test_http_defaultheaderparser_common(testdata, testdata_len, expected_contentlength, expected_transfercoding, expected_contentcoding, expected_connectionclose);
+}
+
+EXPORT VOID test_http_defaultheaderparser_main(unittest_driver_t *driver)
+{
+       UNITTEST_DRIVER_REGIST(driver, test_http_defaultheaderparser_1);
+       UNITTEST_DRIVER_REGIST(driver, test_http_defaultheaderparser_2);
+       UNITTEST_DRIVER_REGIST(driver, test_http_defaultheaderparser_3);
+       UNITTEST_DRIVER_REGIST(driver, test_http_defaultheaderparser_4);
+       UNITTEST_DRIVER_REGIST(driver, test_http_defaultheaderparser_5);
+}