Begin refactor of http.cc. Remove libebb add http_parser.
authorRyan <ry@tinyclouds.org>
Sun, 3 May 2009 12:09:16 +0000 (14:09 +0200)
committerRyan <ry@tinyclouds.org>
Sun, 3 May 2009 12:09:16 +0000 (14:09 +0200)
And most of http.cc was deleted.

32 files changed:
deps/http_parser/README.md [new file with mode: 0644]
deps/http_parser/http_parser.c [new file with mode: 0644]
deps/http_parser/http_parser.h [new file with mode: 0644]
deps/http_parser/http_parser.rl [new file with mode: 0644]
deps/http_parser/test.c [new file with mode: 0644]
deps/libebb/.gitignore [deleted file]
deps/libebb/LICENSE [deleted file]
deps/libebb/README [deleted file]
deps/libebb/config.mk [deleted file]
deps/libebb/doc/icon.png [deleted file]
deps/libebb/doc/index.html [deleted file]
deps/libebb/ebb.c [deleted file]
deps/libebb/ebb.h [deleted file]
deps/libebb/ebb_request_parser.h [deleted file]
deps/libebb/ebb_request_parser.rl [deleted file]
deps/libebb/examples/ca-cert.pem [deleted file]
deps/libebb/examples/ca-key.pem [deleted file]
deps/libebb/examples/hello_world.c [deleted file]
deps/libebb/rbtree.c [deleted file]
deps/libebb/rbtree.h [deleted file]
deps/libebb/test_examples.rb [deleted file]
deps/libebb/test_rbtree.c [deleted file]
deps/libebb/test_request_parser.c [deleted file]
ragel.py [deleted file]
src/http.cc
src/http.h
src/net.cc
src/net.h
src/node.cc
src/node.h
test/test-pingpong.js
wscript

diff --git a/deps/http_parser/README.md b/deps/http_parser/README.md
new file mode 100644 (file)
index 0000000..26c3e96
--- /dev/null
@@ -0,0 +1,75 @@
+HTTP Parser
+===========
+
+This is a parser for HTTP messages written in C. It parses both requests
+and responses. The parser is designed to be used in performance HTTP
+applications. It does not make any allocations, it does not buffer data, and
+it can be interrupted at anytime. It only requires about 100 bytes of data
+per message stream (in a web server that is per connection). 
+
+Features:
+
+  * No dependencies 
+  * Parses both requests and responses.
+  * Handles keep-alive streams.
+  * Decodes chunked encoding.
+  * Extracts the following data from a message
+    * header fields and values
+    * content-length
+    * request method
+    * response status code
+    * transfer-encoding
+    * http version
+    * request path, query string, fragment
+    * message body
+
+Usage
+-----
+
+One `http_parser` object is used per TCP connection. Initialize the struct
+using `http_parser_init()` and set the callbacks. That might look something
+like this:
+
+    http_parser *parser = malloc(sizeof(http_parser));
+    http_parser_init(parser, HTTP_REQUEST);
+    parser->on_path = my_path_callback;
+    parser->on_header_field = my_header_field_callback;
+    parser->data = my_socket;
+
+When data is received on the socket execute the parser and check for errors.
+
+    size_t len = 80*1024;
+    char buf[len];
+    ssize_t recved;
+
+    recved = read(fd, buf, len);
+    if (recved != 0) // handle error
+
+    http_parser_execute(parser, buf, recved);
+
+    if (http_parser_has_error(parser)) {
+      // handle error. usually just close the connection
+    }
+
+During the `http_parser_execute()` call, the callbacks set in `http_parser`
+will be executed. The parser maintains state and never looks behind, so
+buffering the data is not necessary. If you need to save certain data for
+later usage, you can do that from the callbacks. (You can also `read()` into
+a heap allocated buffer to avoid copying memory around if this fits your
+application.)
+  
+The parser decodes the transfer-encoding for both requests and responses
+transparently. That is, a chunked encoding is decoded before being sent to
+the on_body callback.
+
+It does not decode the content-encoding (gzip). Not all HTTP applications
+need to inspect the body. Decoding gzip is non-neglagable amount of
+processing (and requires making allocations). HTTP proxies using this
+parser, for example, would not want such a feature.
+
+Releases
+--------
+
+  * [0.1](http://s3.amazonaws.com/four.livejournal/20090427/http_parser-0.1.tar.gz)
+
+The source repo is at [github](http://github.com/ry/http-parser).
diff --git a/deps/http_parser/http_parser.c b/deps/http_parser/http_parser.c
new file mode 100644 (file)
index 0000000..ad11574
--- /dev/null
@@ -0,0 +1,5776 @@
+#line 1 "http_parser.rl"
+/* Copyright (c) 2008, 2009 Ryan Dahl (ry@tinyclouds.org)
+ *
+ * Based on Zed Shaw's Mongrel.
+ * Copyright (c) 2005 Zed A. Shaw
+ *
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ */
+#include "http_parser.h"
+
+#include <assert.h>
+
+static int unhex[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
+                     ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     };
+#define TRUE 1
+#define FALSE 0
+#define MIN(a,b) (a < b ? a : b)
+#define NULL (void*)(0)
+
+#define REMAINING (pe - p)
+#define CALLBACK(FOR)                                                       \
+  if (parser->FOR##_mark && parser->on_##FOR) {                             \
+    callback_return_value =                                                 \
+      parser->on_##FOR(parser, parser->FOR##_mark, p - parser->FOR##_mark); \
+  }
+
+#define RESET_PARSER(parser) \
+    parser->chunk_size = 0; \
+    parser->eating = 0; \
+    parser->header_field_mark = NULL; \
+    parser->header_value_mark = NULL; \
+    parser->query_string_mark = NULL; \
+    parser->path_mark = NULL; \
+    parser->uri_mark = NULL; \
+    parser->fragment_mark = NULL; \
+    parser->status_code = 0; \
+    parser->method = 0; \
+    parser->transfer_encoding = HTTP_IDENTITY; \
+    parser->version_major = 0; \
+    parser->version_minor = 0; \
+    parser->keep_alive = -1; \
+    parser->content_length = 0; \
+    parser->body_read = 0; 
+
+#define END_REQUEST                                \
+do {                                               \
+    if (parser->on_message_complete) {             \
+      callback_return_value =                      \
+        parser->on_message_complete(parser);       \
+    }                                              \
+    RESET_PARSER(parser);                          \
+} while (0)
+
+#define SKIP_BODY(nskip)                                             \
+do {                                                                 \
+  tmp = (nskip);                                                     \
+  if (parser->on_body && tmp > 0) {                                  \
+    callback_return_value = parser->on_body(parser, p, tmp);         \
+  }                                                                  \
+  if (callback_return_value == 0) {                                  \
+    p += tmp;                                                        \
+    parser->body_read += tmp;                                        \
+    parser->chunk_size -= tmp;                                       \
+    if (0 == parser->chunk_size) {                                   \
+      parser->eating = FALSE;                                        \
+      if (parser->transfer_encoding == HTTP_IDENTITY) {              \
+        END_REQUEST;                                                 \
+      }                                                              \
+    } else {                                                         \
+      parser->eating = TRUE;                                         \
+    }                                                                \
+  }                                                                  \
+} while (0)
+
+#line 340 "http_parser.rl"
+
+
+
+#line 106 "http_parser.c"
+static const int http_parser_start = 1;
+static const int http_parser_first_final = 267;
+static const int http_parser_error = 0;
+
+static const int http_parser_en_ChunkedBody = 2;
+static const int http_parser_en_ChunkedBody_chunk_chunk_end = 12;
+static const int http_parser_en_Requests = 269;
+static const int http_parser_en_Responses = 270;
+static const int http_parser_en_main = 1;
+
+#line 343 "http_parser.rl"
+
+void
+http_parser_init (http_parser *parser, enum http_parser_type type) 
+{
+  int cs = 0;
+  
+#line 124 "http_parser.c"
+       {
+       cs = http_parser_start;
+       }
+#line 349 "http_parser.rl"
+  parser->cs = cs;
+  parser->type = type;
+
+  parser->on_message_begin = NULL;
+  parser->on_path = NULL;
+  parser->on_query_string = NULL;
+  parser->on_uri = NULL;
+  parser->on_header_field = NULL;
+  parser->on_header_value = NULL;
+  parser->on_headers_complete = NULL;
+  parser->on_body = NULL;
+  parser->on_message_complete = NULL;
+
+  RESET_PARSER(parser);
+}
+
+/** exec **/
+size_t
+http_parser_execute (http_parser *parser, const char *buffer, size_t len)
+{
+  size_t tmp; // REMOVE ME this is extremely hacky
+  int callback_return_value = 0;
+  const char *p, *pe;
+  int cs = parser->cs;
+
+  p = buffer;
+  pe = buffer+len;
+
+  if (0 < parser->chunk_size && parser->eating) {
+    /* eat body */
+    SKIP_BODY(MIN(len, parser->chunk_size));
+    if (callback_return_value != 0) goto out;
+  }
+
+  if (parser->header_field_mark)   parser->header_field_mark   = buffer;
+  if (parser->header_value_mark)   parser->header_value_mark   = buffer;
+  if (parser->fragment_mark)       parser->fragment_mark       = buffer;
+  if (parser->query_string_mark)   parser->query_string_mark   = buffer;
+  if (parser->path_mark)           parser->path_mark           = buffer;
+  if (parser->uri_mark)            parser->uri_mark            = buffer;
+
+  
+#line 171 "http_parser.c"
+       {
+       if ( p == pe )
+               goto _test_eof;
+       goto _resume;
+
+_again:
+       switch ( cs ) {
+               case 1: goto st1;
+               case 267: goto st267;
+               case 0: goto st0;
+               case 2: goto st2;
+               case 3: goto st3;
+               case 4: goto st4;
+               case 5: goto st5;
+               case 6: goto st6;
+               case 268: goto st268;
+               case 7: goto st7;
+               case 8: goto st8;
+               case 9: goto st9;
+               case 10: goto st10;
+               case 11: goto st11;
+               case 12: goto st12;
+               case 13: goto st13;
+               case 14: goto st14;
+               case 15: goto st15;
+               case 16: goto st16;
+               case 17: goto st17;
+               case 18: goto st18;
+               case 19: goto st19;
+               case 269: goto st269;
+               case 20: goto st20;
+               case 21: goto st21;
+               case 22: goto st22;
+               case 23: goto st23;
+               case 24: goto st24;
+               case 25: goto st25;
+               case 26: goto st26;
+               case 27: goto st27;
+               case 28: goto st28;
+               case 29: goto st29;
+               case 30: goto st30;
+               case 31: goto st31;
+               case 32: goto st32;
+               case 33: goto st33;
+               case 34: goto st34;
+               case 35: goto st35;
+               case 36: goto st36;
+               case 37: goto st37;
+               case 38: goto st38;
+               case 39: goto st39;
+               case 40: goto st40;
+               case 41: goto st41;
+               case 42: goto st42;
+               case 43: goto st43;
+               case 44: goto st44;
+               case 45: goto st45;
+               case 46: goto st46;
+               case 47: goto st47;
+               case 48: goto st48;
+               case 49: goto st49;
+               case 50: goto st50;
+               case 51: goto st51;
+               case 52: goto st52;
+               case 53: goto st53;
+               case 54: goto st54;
+               case 55: goto st55;
+               case 56: goto st56;
+               case 57: goto st57;
+               case 58: goto st58;
+               case 59: goto st59;
+               case 60: goto st60;
+               case 61: goto st61;
+               case 62: goto st62;
+               case 63: goto st63;
+               case 64: goto st64;
+               case 65: goto st65;
+               case 66: goto st66;
+               case 67: goto st67;
+               case 68: goto st68;
+               case 69: goto st69;
+               case 70: goto st70;
+               case 71: goto st71;
+               case 72: goto st72;
+               case 73: goto st73;
+               case 74: goto st74;
+               case 75: goto st75;
+               case 76: goto st76;
+               case 77: goto st77;
+               case 78: goto st78;
+               case 79: goto st79;
+               case 80: goto st80;
+               case 81: goto st81;
+               case 82: goto st82;
+               case 83: goto st83;
+               case 84: goto st84;
+               case 85: goto st85;
+               case 86: goto st86;
+               case 87: goto st87;
+               case 88: goto st88;
+               case 89: goto st89;
+               case 90: goto st90;
+               case 91: goto st91;
+               case 92: goto st92;
+               case 93: goto st93;
+               case 94: goto st94;
+               case 95: goto st95;
+               case 96: goto st96;
+               case 97: goto st97;
+               case 98: goto st98;
+               case 99: goto st99;
+               case 100: goto st100;
+               case 101: goto st101;
+               case 102: goto st102;
+               case 103: goto st103;
+               case 104: goto st104;
+               case 105: goto st105;
+               case 106: goto st106;
+               case 107: goto st107;
+               case 108: goto st108;
+               case 109: goto st109;
+               case 110: goto st110;
+               case 111: goto st111;
+               case 112: goto st112;
+               case 113: goto st113;
+               case 114: goto st114;
+               case 115: goto st115;
+               case 116: goto st116;
+               case 117: goto st117;
+               case 118: goto st118;
+               case 119: goto st119;
+               case 120: goto st120;
+               case 121: goto st121;
+               case 122: goto st122;
+               case 123: goto st123;
+               case 124: goto st124;
+               case 125: goto st125;
+               case 126: goto st126;
+               case 127: goto st127;
+               case 128: goto st128;
+               case 129: goto st129;
+               case 130: goto st130;
+               case 131: goto st131;
+               case 132: goto st132;
+               case 133: goto st133;
+               case 134: goto st134;
+               case 135: goto st135;
+               case 136: goto st136;
+               case 137: goto st137;
+               case 138: goto st138;
+               case 139: goto st139;
+               case 140: goto st140;
+               case 141: goto st141;
+               case 142: goto st142;
+               case 143: goto st143;
+               case 144: goto st144;
+               case 145: goto st145;
+               case 146: goto st146;
+               case 147: goto st147;
+               case 148: goto st148;
+               case 149: goto st149;
+               case 150: goto st150;
+               case 151: goto st151;
+               case 152: goto st152;
+               case 153: goto st153;
+               case 154: goto st154;
+               case 155: goto st155;
+               case 156: goto st156;
+               case 157: goto st157;
+               case 158: goto st158;
+               case 159: goto st159;
+               case 160: goto st160;
+               case 161: goto st161;
+               case 162: goto st162;
+               case 163: goto st163;
+               case 164: goto st164;
+               case 165: goto st165;
+               case 166: goto st166;
+               case 167: goto st167;
+               case 168: goto st168;
+               case 169: goto st169;
+               case 170: goto st170;
+               case 171: goto st171;
+               case 172: goto st172;
+               case 173: goto st173;
+               case 174: goto st174;
+               case 175: goto st175;
+               case 176: goto st176;
+               case 177: goto st177;
+               case 178: goto st178;
+               case 179: goto st179;
+               case 180: goto st180;
+               case 181: goto st181;
+               case 270: goto st270;
+               case 182: goto st182;
+               case 183: goto st183;
+               case 184: goto st184;
+               case 185: goto st185;
+               case 186: goto st186;
+               case 187: goto st187;
+               case 188: goto st188;
+               case 189: goto st189;
+               case 190: goto st190;
+               case 191: goto st191;
+               case 192: goto st192;
+               case 193: goto st193;
+               case 194: goto st194;
+               case 195: goto st195;
+               case 196: goto st196;
+               case 197: goto st197;
+               case 198: goto st198;
+               case 199: goto st199;
+               case 200: goto st200;
+               case 201: goto st201;
+               case 202: goto st202;
+               case 203: goto st203;
+               case 204: goto st204;
+               case 205: goto st205;
+               case 206: goto st206;
+               case 207: goto st207;
+               case 208: goto st208;
+               case 209: goto st209;
+               case 210: goto st210;
+               case 211: goto st211;
+               case 212: goto st212;
+               case 213: goto st213;
+               case 214: goto st214;
+               case 215: goto st215;
+               case 216: goto st216;
+               case 217: goto st217;
+               case 218: goto st218;
+               case 219: goto st219;
+               case 220: goto st220;
+               case 221: goto st221;
+               case 222: goto st222;
+               case 223: goto st223;
+               case 224: goto st224;
+               case 225: goto st225;
+               case 226: goto st226;
+               case 227: goto st227;
+               case 228: goto st228;
+               case 229: goto st229;
+               case 230: goto st230;
+               case 231: goto st231;
+               case 232: goto st232;
+               case 233: goto st233;
+               case 234: goto st234;
+               case 235: goto st235;
+               case 236: goto st236;
+               case 237: goto st237;
+               case 238: goto st238;
+               case 239: goto st239;
+               case 240: goto st240;
+               case 241: goto st241;
+               case 242: goto st242;
+               case 243: goto st243;
+               case 244: goto st244;
+               case 245: goto st245;
+               case 246: goto st246;
+               case 247: goto st247;
+               case 248: goto st248;
+               case 249: goto st249;
+               case 250: goto st250;
+               case 251: goto st251;
+               case 252: goto st252;
+               case 253: goto st253;
+               case 254: goto st254;
+               case 255: goto st255;
+               case 256: goto st256;
+               case 257: goto st257;
+               case 258: goto st258;
+               case 259: goto st259;
+               case 260: goto st260;
+               case 261: goto st261;
+               case 262: goto st262;
+               case 263: goto st263;
+               case 264: goto st264;
+               case 265: goto st265;
+               case 266: goto st266;
+       default: break;
+       }
+
+       if ( ++p == pe )
+               goto _test_eof;
+_resume:
+       switch ( cs )
+       {
+st1:
+       if ( ++p == pe )
+               goto _test_eof1;
+case 1:
+       goto tr0;
+tr0:
+#line 331 "http_parser.rl"
+       {
+    p--;
+    if (parser->type == HTTP_REQUEST) {
+      {goto st269;}
+    } else {
+      {goto st270;}
+    }
+  }
+       goto st267;
+st267:
+       if ( ++p == pe )
+               goto _test_eof267;
+case 267:
+#line 478 "http_parser.c"
+       goto st0;
+st0:
+cs = 0;
+       goto _out;
+st2:
+       if ( ++p == pe )
+               goto _test_eof2;
+case 2:
+       if ( (*p) == 48 )
+               goto tr1;
+       if ( (*p) < 65 ) {
+               if ( 49 <= (*p) && (*p) <= 57 )
+                       goto tr3;
+       } else if ( (*p) > 70 ) {
+               if ( 97 <= (*p) && (*p) <= 102 )
+                       goto tr3;
+       } else
+               goto tr3;
+       goto st0;
+tr1:
+#line 186 "http_parser.rl"
+       {
+    parser->chunk_size *= 16;
+    parser->chunk_size += unhex[(int)*p];
+  }
+       goto st3;
+st3:
+       if ( ++p == pe )
+               goto _test_eof3;
+case 3:
+#line 509 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto st4;
+               case 48: goto tr1;
+               case 59: goto st17;
+       }
+       if ( (*p) < 65 ) {
+               if ( 49 <= (*p) && (*p) <= 57 )
+                       goto tr3;
+       } else if ( (*p) > 70 ) {
+               if ( 97 <= (*p) && (*p) <= 102 )
+                       goto tr3;
+       } else
+               goto tr3;
+       goto st0;
+st4:
+       if ( ++p == pe )
+               goto _test_eof4;
+case 4:
+       if ( (*p) == 10 )
+               goto st5;
+       goto st0;
+st5:
+       if ( ++p == pe )
+               goto _test_eof5;
+case 5:
+       switch( (*p) ) {
+               case 13: goto st6;
+               case 33: goto st7;
+               case 124: goto st7;
+               case 126: goto st7;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st7;
+               } else if ( (*p) >= 35 )
+                       goto st7;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st7;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st7;
+               } else
+                       goto st7;
+       } else
+               goto st7;
+       goto st0;
+st6:
+       if ( ++p == pe )
+               goto _test_eof6;
+case 6:
+       if ( (*p) == 10 )
+               goto tr9;
+       goto st0;
+tr9:
+       cs = 268;
+#line 203 "http_parser.rl"
+       {
+    END_REQUEST;
+    if (parser->type == HTTP_REQUEST) {
+      cs = 269;
+    } else {
+      cs = 270;
+    }
+  }
+       goto _again;
+st268:
+       if ( ++p == pe )
+               goto _test_eof268;
+case 268:
+#line 582 "http_parser.c"
+       goto st0;
+st7:
+       if ( ++p == pe )
+               goto _test_eof7;
+case 7:
+       switch( (*p) ) {
+               case 33: goto st7;
+               case 58: goto st8;
+               case 124: goto st7;
+               case 126: goto st7;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st7;
+               } else if ( (*p) >= 35 )
+                       goto st7;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st7;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st7;
+               } else
+                       goto st7;
+       } else
+               goto st7;
+       goto st0;
+st8:
+       if ( ++p == pe )
+               goto _test_eof8;
+case 8:
+       if ( (*p) == 13 )
+               goto st4;
+       goto st8;
+tr3:
+#line 186 "http_parser.rl"
+       {
+    parser->chunk_size *= 16;
+    parser->chunk_size += unhex[(int)*p];
+  }
+       goto st9;
+st9:
+       if ( ++p == pe )
+               goto _test_eof9;
+case 9:
+#line 630 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto st10;
+               case 59: goto st14;
+       }
+       if ( (*p) < 65 ) {
+               if ( 48 <= (*p) && (*p) <= 57 )
+                       goto tr3;
+       } else if ( (*p) > 70 ) {
+               if ( 97 <= (*p) && (*p) <= 102 )
+                       goto tr3;
+       } else
+               goto tr3;
+       goto st0;
+st10:
+       if ( ++p == pe )
+               goto _test_eof10;
+case 10:
+       if ( (*p) == 10 )
+               goto st11;
+       goto st0;
+st11:
+       if ( ++p == pe )
+               goto _test_eof11;
+case 11:
+       goto tr14;
+tr14:
+#line 191 "http_parser.rl"
+       {
+    SKIP_BODY(MIN(parser->chunk_size, REMAINING));
+    if (callback_return_value != 0) {p++; cs = 12; goto _out;}
+
+    p--; 
+    if (parser->chunk_size > REMAINING) {
+      {p++; cs = 12; goto _out;}
+    } else {
+      {goto st12;} 
+    }
+  }
+       goto st12;
+st12:
+       if ( ++p == pe )
+               goto _test_eof12;
+case 12:
+#line 674 "http_parser.c"
+       if ( (*p) == 13 )
+               goto st13;
+       goto st0;
+st13:
+       if ( ++p == pe )
+               goto _test_eof13;
+case 13:
+       if ( (*p) == 10 )
+               goto st2;
+       goto st0;
+st14:
+       if ( ++p == pe )
+               goto _test_eof14;
+case 14:
+       switch( (*p) ) {
+               case 13: goto st10;
+               case 32: goto st14;
+               case 33: goto st15;
+               case 59: goto st14;
+               case 61: goto st16;
+               case 124: goto st15;
+               case 126: goto st15;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st15;
+               } else if ( (*p) >= 35 )
+                       goto st15;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st15;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st15;
+               } else
+                       goto st15;
+       } else
+               goto st15;
+       goto st0;
+st15:
+       if ( ++p == pe )
+               goto _test_eof15;
+case 15:
+       switch( (*p) ) {
+               case 13: goto st10;
+               case 33: goto st15;
+               case 59: goto st14;
+               case 61: goto st16;
+               case 124: goto st15;
+               case 126: goto st15;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st15;
+               } else if ( (*p) >= 35 )
+                       goto st15;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st15;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st15;
+               } else
+                       goto st15;
+       } else
+               goto st15;
+       goto st0;
+st16:
+       if ( ++p == pe )
+               goto _test_eof16;
+case 16:
+       switch( (*p) ) {
+               case 13: goto st10;
+               case 33: goto st16;
+               case 59: goto st14;
+               case 124: goto st16;
+               case 126: goto st16;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st16;
+               } else if ( (*p) >= 35 )
+                       goto st16;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st16;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st16;
+               } else
+                       goto st16;
+       } else
+               goto st16;
+       goto st0;
+st17:
+       if ( ++p == pe )
+               goto _test_eof17;
+case 17:
+       switch( (*p) ) {
+               case 13: goto st4;
+               case 32: goto st17;
+               case 33: goto st18;
+               case 59: goto st17;
+               case 61: goto st19;
+               case 124: goto st18;
+               case 126: goto st18;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st18;
+               } else if ( (*p) >= 35 )
+                       goto st18;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st18;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st18;
+               } else
+                       goto st18;
+       } else
+               goto st18;
+       goto st0;
+st18:
+       if ( ++p == pe )
+               goto _test_eof18;
+case 18:
+       switch( (*p) ) {
+               case 13: goto st4;
+               case 33: goto st18;
+               case 59: goto st17;
+               case 61: goto st19;
+               case 124: goto st18;
+               case 126: goto st18;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st18;
+               } else if ( (*p) >= 35 )
+                       goto st18;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st18;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st18;
+               } else
+                       goto st18;
+       } else
+               goto st18;
+       goto st0;
+st19:
+       if ( ++p == pe )
+               goto _test_eof19;
+case 19:
+       switch( (*p) ) {
+               case 13: goto st4;
+               case 33: goto st19;
+               case 59: goto st17;
+               case 124: goto st19;
+               case 126: goto st19;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st19;
+               } else if ( (*p) >= 35 )
+                       goto st19;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st19;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st19;
+               } else
+                       goto st19;
+       } else
+               goto st19;
+       goto st0;
+tr45:
+       cs = 269;
+#line 146 "http_parser.rl"
+       {
+    if(parser->on_headers_complete) {
+      callback_return_value = parser->on_headers_complete(parser);
+      if (callback_return_value != 0) {p++; goto _out;}
+    }
+  }
+#line 212 "http_parser.rl"
+       {
+    if (parser->transfer_encoding == HTTP_CHUNKED) {
+      cs = 2;
+    } else {
+      /* this is pretty stupid. i'd prefer to combine this with skip_chunk_data */
+      parser->chunk_size = parser->content_length;
+      p += 1;  
+
+      SKIP_BODY(MIN(REMAINING, parser->content_length));
+      if (callback_return_value != 0) {p++; goto _out;}
+
+      p--;
+      if(parser->chunk_size > REMAINING) {
+        {p++; goto _out;}
+      }
+    }
+  }
+       goto _again;
+st269:
+       if ( ++p == pe )
+               goto _test_eof269;
+case 269:
+#line 897 "http_parser.c"
+       switch( (*p) ) {
+               case 67: goto tr311;
+               case 68: goto tr312;
+               case 71: goto tr313;
+               case 72: goto tr314;
+               case 76: goto tr315;
+               case 77: goto tr316;
+               case 79: goto tr317;
+               case 80: goto tr318;
+               case 84: goto tr319;
+               case 85: goto tr320;
+       }
+       goto st0;
+tr311:
+#line 153 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {p++; cs = 20; goto _out;}
+    }
+  }
+       goto st20;
+st20:
+       if ( ++p == pe )
+               goto _test_eof20;
+case 20:
+#line 924 "http_parser.c"
+       if ( (*p) == 79 )
+               goto st21;
+       goto st0;
+st21:
+       if ( ++p == pe )
+               goto _test_eof21;
+case 21:
+       if ( (*p) == 80 )
+               goto st22;
+       goto st0;
+st22:
+       if ( ++p == pe )
+               goto _test_eof22;
+case 22:
+       if ( (*p) == 89 )
+               goto st23;
+       goto st0;
+st23:
+       if ( ++p == pe )
+               goto _test_eof23;
+case 23:
+       if ( (*p) == 32 )
+               goto tr24;
+       goto st0;
+tr24:
+#line 256 "http_parser.rl"
+       { parser->method = HTTP_COPY;      }
+       goto st24;
+tr154:
+#line 257 "http_parser.rl"
+       { parser->method = HTTP_DELETE;    }
+       goto st24;
+tr157:
+#line 258 "http_parser.rl"
+       { parser->method = HTTP_GET;       }
+       goto st24;
+tr161:
+#line 259 "http_parser.rl"
+       { parser->method = HTTP_HEAD;      }
+       goto st24;
+tr165:
+#line 260 "http_parser.rl"
+       { parser->method = HTTP_LOCK;      }
+       goto st24;
+tr171:
+#line 261 "http_parser.rl"
+       { parser->method = HTTP_MKCOL;     }
+       goto st24;
+tr174:
+#line 262 "http_parser.rl"
+       { parser->method = HTTP_MOVE;      }
+       goto st24;
+tr181:
+#line 263 "http_parser.rl"
+       { parser->method = HTTP_OPTIONS;   }
+       goto st24;
+tr187:
+#line 264 "http_parser.rl"
+       { parser->method = HTTP_POST;      }
+       goto st24;
+tr195:
+#line 265 "http_parser.rl"
+       { parser->method = HTTP_PROPFIND;  }
+       goto st24;
+tr200:
+#line 266 "http_parser.rl"
+       { parser->method = HTTP_PROPPATCH; }
+       goto st24;
+tr202:
+#line 267 "http_parser.rl"
+       { parser->method = HTTP_PUT;       }
+       goto st24;
+tr207:
+#line 268 "http_parser.rl"
+       { parser->method = HTTP_TRACE;     }
+       goto st24;
+tr213:
+#line 269 "http_parser.rl"
+       { parser->method = HTTP_UNLOCK;    }
+       goto st24;
+st24:
+       if ( ++p == pe )
+               goto _test_eof24;
+case 24:
+#line 1009 "http_parser.c"
+       switch( (*p) ) {
+               case 42: goto tr25;
+               case 43: goto tr26;
+               case 47: goto tr27;
+               case 58: goto tr28;
+       }
+       if ( (*p) < 65 ) {
+               if ( 45 <= (*p) && (*p) <= 57 )
+                       goto tr26;
+       } else if ( (*p) > 90 ) {
+               if ( 97 <= (*p) && (*p) <= 122 )
+                       goto tr26;
+       } else
+               goto tr26;
+       goto st0;
+tr25:
+#line 108 "http_parser.rl"
+       { parser->uri_mark            = p; }
+       goto st25;
+st25:
+       if ( ++p == pe )
+               goto _test_eof25;
+case 25:
+#line 1033 "http_parser.c"
+       switch( (*p) ) {
+               case 32: goto tr29;
+               case 35: goto tr30;
+       }
+       goto st0;
+tr29:
+#line 122 "http_parser.rl"
+       { 
+    CALLBACK(uri);
+    if (callback_return_value != 0) {p++; cs = 26; goto _out;}
+    parser->uri_mark = NULL;
+  }
+       goto st26;
+tr124:
+#line 105 "http_parser.rl"
+       { parser->fragment_mark       = p; }
+#line 128 "http_parser.rl"
+       { 
+    CALLBACK(fragment);
+    if (callback_return_value != 0) {p++; cs = 26; goto _out;}
+    parser->fragment_mark = NULL;
+  }
+       goto st26;
+tr127:
+#line 128 "http_parser.rl"
+       { 
+    CALLBACK(fragment);
+    if (callback_return_value != 0) {p++; cs = 26; goto _out;}
+    parser->fragment_mark = NULL;
+  }
+       goto st26;
+tr135:
+#line 140 "http_parser.rl"
+       {
+    CALLBACK(path);
+    if (callback_return_value != 0) {p++; cs = 26; goto _out;}
+    parser->path_mark = NULL;
+  }
+#line 122 "http_parser.rl"
+       { 
+    CALLBACK(uri);
+    if (callback_return_value != 0) {p++; cs = 26; goto _out;}
+    parser->uri_mark = NULL;
+  }
+       goto st26;
+tr141:
+#line 106 "http_parser.rl"
+       { parser->query_string_mark   = p; }
+#line 134 "http_parser.rl"
+       { 
+    CALLBACK(query_string);
+    if (callback_return_value != 0) {p++; cs = 26; goto _out;}
+    parser->query_string_mark = NULL;
+  }
+#line 122 "http_parser.rl"
+       { 
+    CALLBACK(uri);
+    if (callback_return_value != 0) {p++; cs = 26; goto _out;}
+    parser->uri_mark = NULL;
+  }
+       goto st26;
+tr145:
+#line 134 "http_parser.rl"
+       { 
+    CALLBACK(query_string);
+    if (callback_return_value != 0) {p++; cs = 26; goto _out;}
+    parser->query_string_mark = NULL;
+  }
+#line 122 "http_parser.rl"
+       { 
+    CALLBACK(uri);
+    if (callback_return_value != 0) {p++; cs = 26; goto _out;}
+    parser->uri_mark = NULL;
+  }
+       goto st26;
+st26:
+       if ( ++p == pe )
+               goto _test_eof26;
+case 26:
+#line 1113 "http_parser.c"
+       if ( (*p) == 72 )
+               goto st27;
+       goto st0;
+st27:
+       if ( ++p == pe )
+               goto _test_eof27;
+case 27:
+       if ( (*p) == 84 )
+               goto st28;
+       goto st0;
+st28:
+       if ( ++p == pe )
+               goto _test_eof28;
+case 28:
+       if ( (*p) == 84 )
+               goto st29;
+       goto st0;
+st29:
+       if ( ++p == pe )
+               goto _test_eof29;
+case 29:
+       if ( (*p) == 80 )
+               goto st30;
+       goto st0;
+st30:
+       if ( ++p == pe )
+               goto _test_eof30;
+case 30:
+       if ( (*p) == 47 )
+               goto st31;
+       goto st0;
+st31:
+       if ( ++p == pe )
+               goto _test_eof31;
+case 31:
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr36;
+       goto st0;
+tr36:
+#line 176 "http_parser.rl"
+       {
+    parser->version_major *= 10;
+    parser->version_major += *p - '0';
+  }
+       goto st32;
+st32:
+       if ( ++p == pe )
+               goto _test_eof32;
+case 32:
+#line 1163 "http_parser.c"
+       if ( (*p) == 46 )
+               goto st33;
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr36;
+       goto st0;
+st33:
+       if ( ++p == pe )
+               goto _test_eof33;
+case 33:
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr38;
+       goto st0;
+tr38:
+#line 181 "http_parser.rl"
+       {
+    parser->version_minor *= 10;
+    parser->version_minor += *p - '0';
+  }
+       goto st34;
+st34:
+       if ( ++p == pe )
+               goto _test_eof34;
+case 34:
+#line 1187 "http_parser.c"
+       if ( (*p) == 13 )
+               goto st35;
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr38;
+       goto st0;
+tr49:
+#line 104 "http_parser.rl"
+       { parser->header_value_mark   = p; }
+#line 116 "http_parser.rl"
+       {
+    CALLBACK(header_value);
+    if (callback_return_value != 0) {p++; cs = 35; goto _out;}
+    parser->header_value_mark = NULL;
+  }
+       goto st35;
+tr52:
+#line 116 "http_parser.rl"
+       {
+    CALLBACK(header_value);
+    if (callback_return_value != 0) {p++; cs = 35; goto _out;}
+    parser->header_value_mark = NULL;
+  }
+       goto st35;
+tr71:
+#line 174 "http_parser.rl"
+       { parser->keep_alive = FALSE; }
+#line 116 "http_parser.rl"
+       {
+    CALLBACK(header_value);
+    if (callback_return_value != 0) {p++; cs = 35; goto _out;}
+    parser->header_value_mark = NULL;
+  }
+       goto st35;
+tr81:
+#line 173 "http_parser.rl"
+       { parser->keep_alive = TRUE; }
+#line 116 "http_parser.rl"
+       {
+    CALLBACK(header_value);
+    if (callback_return_value != 0) {p++; cs = 35; goto _out;}
+    parser->header_value_mark = NULL;
+  }
+       goto st35;
+tr122:
+#line 170 "http_parser.rl"
+       { parser->transfer_encoding = HTTP_IDENTITY; }
+#line 116 "http_parser.rl"
+       {
+    CALLBACK(header_value);
+    if (callback_return_value != 0) {p++; cs = 35; goto _out;}
+    parser->header_value_mark = NULL;
+  }
+       goto st35;
+st35:
+       if ( ++p == pe )
+               goto _test_eof35;
+case 35:
+#line 1245 "http_parser.c"
+       if ( (*p) == 10 )
+               goto st36;
+       goto st0;
+st36:
+       if ( ++p == pe )
+               goto _test_eof36;
+case 36:
+       switch( (*p) ) {
+               case 13: goto st37;
+               case 33: goto tr42;
+               case 67: goto tr43;
+               case 84: goto tr44;
+               case 99: goto tr43;
+               case 116: goto tr44;
+               case 124: goto tr42;
+               case 126: goto tr42;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto tr42;
+               } else if ( (*p) >= 35 )
+                       goto tr42;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto tr42;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto tr42;
+               } else
+                       goto tr42;
+       } else
+               goto tr42;
+       goto st0;
+st37:
+       if ( ++p == pe )
+               goto _test_eof37;
+case 37:
+       if ( (*p) == 10 )
+               goto tr45;
+       goto st0;
+tr42:
+#line 103 "http_parser.rl"
+       { parser->header_field_mark   = p; }
+       goto st38;
+st38:
+       if ( ++p == pe )
+               goto _test_eof38;
+case 38:
+#line 1296 "http_parser.c"
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+tr47:
+#line 110 "http_parser.rl"
+       {
+    CALLBACK(header_field);
+    if (callback_return_value != 0) {p++; cs = 39; goto _out;}
+    parser->header_field_mark = NULL;
+  }
+       goto st39;
+st39:
+       if ( ++p == pe )
+               goto _test_eof39;
+case 39:
+#line 1333 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr49;
+               case 32: goto st39;
+       }
+       goto tr48;
+tr48:
+#line 104 "http_parser.rl"
+       { parser->header_value_mark   = p; }
+       goto st40;
+st40:
+       if ( ++p == pe )
+               goto _test_eof40;
+case 40:
+#line 1347 "http_parser.c"
+       if ( (*p) == 13 )
+               goto tr52;
+       goto st40;
+tr43:
+#line 103 "http_parser.rl"
+       { parser->header_field_mark   = p; }
+       goto st41;
+st41:
+       if ( ++p == pe )
+               goto _test_eof41;
+case 41:
+#line 1359 "http_parser.c"
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 79: goto st42;
+               case 111: goto st42;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st42:
+       if ( ++p == pe )
+               goto _test_eof42;
+case 42:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 78: goto st43;
+               case 110: goto st43;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st43:
+       if ( ++p == pe )
+               goto _test_eof43;
+case 43:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 78: goto st44;
+               case 84: goto st67;
+               case 110: goto st44;
+               case 116: goto st67;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st44:
+       if ( ++p == pe )
+               goto _test_eof44;
+case 44:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 69: goto st45;
+               case 101: goto st45;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st45:
+       if ( ++p == pe )
+               goto _test_eof45;
+case 45:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 67: goto st46;
+               case 99: goto st46;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st46:
+       if ( ++p == pe )
+               goto _test_eof46;
+case 46:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 84: goto st47;
+               case 116: goto st47;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st47:
+       if ( ++p == pe )
+               goto _test_eof47;
+case 47:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 73: goto st48;
+               case 105: goto st48;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st48:
+       if ( ++p == pe )
+               goto _test_eof48;
+case 48:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 79: goto st49;
+               case 111: goto st49;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st49:
+       if ( ++p == pe )
+               goto _test_eof49;
+case 49:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 78: goto st50;
+               case 110: goto st50;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st50:
+       if ( ++p == pe )
+               goto _test_eof50;
+case 50:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr63;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+tr63:
+#line 110 "http_parser.rl"
+       {
+    CALLBACK(header_field);
+    if (callback_return_value != 0) {p++; cs = 51; goto _out;}
+    parser->header_field_mark = NULL;
+  }
+       goto st51;
+st51:
+       if ( ++p == pe )
+               goto _test_eof51;
+case 51:
+#line 1668 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr49;
+               case 32: goto st51;
+               case 67: goto tr65;
+               case 75: goto tr66;
+               case 99: goto tr65;
+               case 107: goto tr66;
+       }
+       goto tr48;
+tr65:
+#line 104 "http_parser.rl"
+       { parser->header_value_mark   = p; }
+       goto st52;
+st52:
+       if ( ++p == pe )
+               goto _test_eof52;
+case 52:
+#line 1686 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 76: goto st53;
+               case 108: goto st53;
+       }
+       goto st40;
+st53:
+       if ( ++p == pe )
+               goto _test_eof53;
+case 53:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 79: goto st54;
+               case 111: goto st54;
+       }
+       goto st40;
+st54:
+       if ( ++p == pe )
+               goto _test_eof54;
+case 54:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 83: goto st55;
+               case 115: goto st55;
+       }
+       goto st40;
+st55:
+       if ( ++p == pe )
+               goto _test_eof55;
+case 55:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 69: goto st56;
+               case 101: goto st56;
+       }
+       goto st40;
+st56:
+       if ( ++p == pe )
+               goto _test_eof56;
+case 56:
+       if ( (*p) == 13 )
+               goto tr71;
+       goto st40;
+tr66:
+#line 104 "http_parser.rl"
+       { parser->header_value_mark   = p; }
+       goto st57;
+st57:
+       if ( ++p == pe )
+               goto _test_eof57;
+case 57:
+#line 1738 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 69: goto st58;
+               case 101: goto st58;
+       }
+       goto st40;
+st58:
+       if ( ++p == pe )
+               goto _test_eof58;
+case 58:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 69: goto st59;
+               case 101: goto st59;
+       }
+       goto st40;
+st59:
+       if ( ++p == pe )
+               goto _test_eof59;
+case 59:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 80: goto st60;
+               case 112: goto st60;
+       }
+       goto st40;
+st60:
+       if ( ++p == pe )
+               goto _test_eof60;
+case 60:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 45: goto st61;
+       }
+       goto st40;
+st61:
+       if ( ++p == pe )
+               goto _test_eof61;
+case 61:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 65: goto st62;
+               case 97: goto st62;
+       }
+       goto st40;
+st62:
+       if ( ++p == pe )
+               goto _test_eof62;
+case 62:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 76: goto st63;
+               case 108: goto st63;
+       }
+       goto st40;
+st63:
+       if ( ++p == pe )
+               goto _test_eof63;
+case 63:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 73: goto st64;
+               case 105: goto st64;
+       }
+       goto st40;
+st64:
+       if ( ++p == pe )
+               goto _test_eof64;
+case 64:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 86: goto st65;
+               case 118: goto st65;
+       }
+       goto st40;
+st65:
+       if ( ++p == pe )
+               goto _test_eof65;
+case 65:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 69: goto st66;
+               case 101: goto st66;
+       }
+       goto st40;
+st66:
+       if ( ++p == pe )
+               goto _test_eof66;
+case 66:
+       if ( (*p) == 13 )
+               goto tr81;
+       goto st40;
+st67:
+       if ( ++p == pe )
+               goto _test_eof67;
+case 67:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 69: goto st68;
+               case 101: goto st68;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st68:
+       if ( ++p == pe )
+               goto _test_eof68;
+case 68:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 78: goto st69;
+               case 110: goto st69;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st69:
+       if ( ++p == pe )
+               goto _test_eof69;
+case 69:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 84: goto st70;
+               case 116: goto st70;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st70:
+       if ( ++p == pe )
+               goto _test_eof70;
+case 70:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 45: goto st71;
+               case 46: goto st38;
+               case 58: goto tr47;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 48 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 57 ) {
+               if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else if ( (*p) >= 65 )
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st71:
+       if ( ++p == pe )
+               goto _test_eof71;
+case 71:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 76: goto st72;
+               case 108: goto st72;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st72:
+       if ( ++p == pe )
+               goto _test_eof72;
+case 72:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 69: goto st73;
+               case 101: goto st73;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st73:
+       if ( ++p == pe )
+               goto _test_eof73;
+case 73:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 78: goto st74;
+               case 110: goto st74;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st74:
+       if ( ++p == pe )
+               goto _test_eof74;
+case 74:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 71: goto st75;
+               case 103: goto st75;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st75:
+       if ( ++p == pe )
+               goto _test_eof75;
+case 75:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 84: goto st76;
+               case 116: goto st76;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st76:
+       if ( ++p == pe )
+               goto _test_eof76;
+case 76:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 72: goto st77;
+               case 104: goto st77;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st77:
+       if ( ++p == pe )
+               goto _test_eof77;
+case 77:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr92;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+tr92:
+#line 110 "http_parser.rl"
+       {
+    CALLBACK(header_field);
+    if (callback_return_value != 0) {p++; cs = 78; goto _out;}
+    parser->header_field_mark = NULL;
+  }
+       goto st78;
+st78:
+       if ( ++p == pe )
+               goto _test_eof78;
+case 78:
+#line 2168 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr49;
+               case 32: goto st78;
+       }
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr94;
+       goto tr48;
+tr94:
+#line 160 "http_parser.rl"
+       {
+    parser->content_length *= 10;
+    parser->content_length += *p - '0';
+  }
+#line 104 "http_parser.rl"
+       { parser->header_value_mark   = p; }
+       goto st79;
+tr95:
+#line 160 "http_parser.rl"
+       {
+    parser->content_length *= 10;
+    parser->content_length += *p - '0';
+  }
+       goto st79;
+st79:
+       if ( ++p == pe )
+               goto _test_eof79;
+case 79:
+#line 2196 "http_parser.c"
+       if ( (*p) == 13 )
+               goto tr52;
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr95;
+       goto st40;
+tr44:
+#line 103 "http_parser.rl"
+       { parser->header_field_mark   = p; }
+       goto st80;
+st80:
+       if ( ++p == pe )
+               goto _test_eof80;
+case 80:
+#line 2210 "http_parser.c"
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 82: goto st81;
+               case 114: goto st81;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st81:
+       if ( ++p == pe )
+               goto _test_eof81;
+case 81:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 65: goto st82;
+               case 97: goto st82;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 66 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st82:
+       if ( ++p == pe )
+               goto _test_eof82;
+case 82:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 78: goto st83;
+               case 110: goto st83;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st83:
+       if ( ++p == pe )
+               goto _test_eof83;
+case 83:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 83: goto st84;
+               case 115: goto st84;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st84:
+       if ( ++p == pe )
+               goto _test_eof84;
+case 84:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 70: goto st85;
+               case 102: goto st85;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st85:
+       if ( ++p == pe )
+               goto _test_eof85;
+case 85:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 69: goto st86;
+               case 101: goto st86;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st86:
+       if ( ++p == pe )
+               goto _test_eof86;
+case 86:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 82: goto st87;
+               case 114: goto st87;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st87:
+       if ( ++p == pe )
+               goto _test_eof87;
+case 87:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 45: goto st88;
+               case 46: goto st38;
+               case 58: goto tr47;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 48 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 57 ) {
+               if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else if ( (*p) >= 65 )
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st88:
+       if ( ++p == pe )
+               goto _test_eof88;
+case 88:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 69: goto st89;
+               case 101: goto st89;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st89:
+       if ( ++p == pe )
+               goto _test_eof89;
+case 89:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 78: goto st90;
+               case 110: goto st90;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st90:
+       if ( ++p == pe )
+               goto _test_eof90;
+case 90:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 67: goto st91;
+               case 99: goto st91;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st91:
+       if ( ++p == pe )
+               goto _test_eof91;
+case 91:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 79: goto st92;
+               case 111: goto st92;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st92:
+       if ( ++p == pe )
+               goto _test_eof92;
+case 92:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 68: goto st93;
+               case 100: goto st93;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st93:
+       if ( ++p == pe )
+               goto _test_eof93;
+case 93:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 73: goto st94;
+               case 105: goto st94;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st94:
+       if ( ++p == pe )
+               goto _test_eof94;
+case 94:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 78: goto st95;
+               case 110: goto st95;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st95:
+       if ( ++p == pe )
+               goto _test_eof95;
+case 95:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr47;
+               case 71: goto st96;
+               case 103: goto st96;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+st96:
+       if ( ++p == pe )
+               goto _test_eof96;
+case 96:
+       switch( (*p) ) {
+               case 33: goto st38;
+               case 58: goto tr112;
+               case 124: goto st38;
+               case 126: goto st38;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st38;
+               } else if ( (*p) >= 35 )
+                       goto st38;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st38;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st38;
+               } else
+                       goto st38;
+       } else
+               goto st38;
+       goto st0;
+tr112:
+#line 171 "http_parser.rl"
+       { parser->transfer_encoding = HTTP_CHUNKED;  }
+#line 110 "http_parser.rl"
+       {
+    CALLBACK(header_field);
+    if (callback_return_value != 0) {p++; cs = 97; goto _out;}
+    parser->header_field_mark = NULL;
+  }
+       goto st97;
+st97:
+       if ( ++p == pe )
+               goto _test_eof97;
+case 97:
+#line 2726 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr49;
+               case 32: goto st97;
+               case 105: goto tr114;
+       }
+       goto tr48;
+tr114:
+#line 104 "http_parser.rl"
+       { parser->header_value_mark   = p; }
+       goto st98;
+st98:
+       if ( ++p == pe )
+               goto _test_eof98;
+case 98:
+#line 2741 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 100: goto st99;
+       }
+       goto st40;
+st99:
+       if ( ++p == pe )
+               goto _test_eof99;
+case 99:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 101: goto st100;
+       }
+       goto st40;
+st100:
+       if ( ++p == pe )
+               goto _test_eof100;
+case 100:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 110: goto st101;
+       }
+       goto st40;
+st101:
+       if ( ++p == pe )
+               goto _test_eof101;
+case 101:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 116: goto st102;
+       }
+       goto st40;
+st102:
+       if ( ++p == pe )
+               goto _test_eof102;
+case 102:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 105: goto st103;
+       }
+       goto st40;
+st103:
+       if ( ++p == pe )
+               goto _test_eof103;
+case 103:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 116: goto st104;
+       }
+       goto st40;
+st104:
+       if ( ++p == pe )
+               goto _test_eof104;
+case 104:
+       switch( (*p) ) {
+               case 13: goto tr52;
+               case 121: goto st105;
+       }
+       goto st40;
+st105:
+       if ( ++p == pe )
+               goto _test_eof105;
+case 105:
+       if ( (*p) == 13 )
+               goto tr122;
+       goto st40;
+tr30:
+#line 122 "http_parser.rl"
+       { 
+    CALLBACK(uri);
+    if (callback_return_value != 0) {p++; cs = 106; goto _out;}
+    parser->uri_mark = NULL;
+  }
+       goto st106;
+tr136:
+#line 140 "http_parser.rl"
+       {
+    CALLBACK(path);
+    if (callback_return_value != 0) {p++; cs = 106; goto _out;}
+    parser->path_mark = NULL;
+  }
+#line 122 "http_parser.rl"
+       { 
+    CALLBACK(uri);
+    if (callback_return_value != 0) {p++; cs = 106; goto _out;}
+    parser->uri_mark = NULL;
+  }
+       goto st106;
+tr142:
+#line 106 "http_parser.rl"
+       { parser->query_string_mark   = p; }
+#line 134 "http_parser.rl"
+       { 
+    CALLBACK(query_string);
+    if (callback_return_value != 0) {p++; cs = 106; goto _out;}
+    parser->query_string_mark = NULL;
+  }
+#line 122 "http_parser.rl"
+       { 
+    CALLBACK(uri);
+    if (callback_return_value != 0) {p++; cs = 106; goto _out;}
+    parser->uri_mark = NULL;
+  }
+       goto st106;
+tr146:
+#line 134 "http_parser.rl"
+       { 
+    CALLBACK(query_string);
+    if (callback_return_value != 0) {p++; cs = 106; goto _out;}
+    parser->query_string_mark = NULL;
+  }
+#line 122 "http_parser.rl"
+       { 
+    CALLBACK(uri);
+    if (callback_return_value != 0) {p++; cs = 106; goto _out;}
+    parser->uri_mark = NULL;
+  }
+       goto st106;
+st106:
+       if ( ++p == pe )
+               goto _test_eof106;
+case 106:
+#line 2864 "http_parser.c"
+       switch( (*p) ) {
+               case 32: goto tr124;
+               case 37: goto tr125;
+               case 60: goto st0;
+               case 62: goto st0;
+               case 127: goto st0;
+       }
+       if ( (*p) > 31 ) {
+               if ( 34 <= (*p) && (*p) <= 35 )
+                       goto st0;
+       } else if ( (*p) >= 0 )
+               goto st0;
+       goto tr123;
+tr123:
+#line 105 "http_parser.rl"
+       { parser->fragment_mark       = p; }
+       goto st107;
+st107:
+       if ( ++p == pe )
+               goto _test_eof107;
+case 107:
+#line 2886 "http_parser.c"
+       switch( (*p) ) {
+               case 32: goto tr127;
+               case 37: goto st108;
+               case 60: goto st0;
+               case 62: goto st0;
+               case 127: goto st0;
+       }
+       if ( (*p) > 31 ) {
+               if ( 34 <= (*p) && (*p) <= 35 )
+                       goto st0;
+       } else if ( (*p) >= 0 )
+               goto st0;
+       goto st107;
+tr125:
+#line 105 "http_parser.rl"
+       { parser->fragment_mark       = p; }
+       goto st108;
+st108:
+       if ( ++p == pe )
+               goto _test_eof108;
+case 108:
+#line 2908 "http_parser.c"
+       if ( (*p) < 65 ) {
+               if ( 48 <= (*p) && (*p) <= 57 )
+                       goto st109;
+       } else if ( (*p) > 70 ) {
+               if ( 97 <= (*p) && (*p) <= 102 )
+                       goto st109;
+       } else
+               goto st109;
+       goto st0;
+st109:
+       if ( ++p == pe )
+               goto _test_eof109;
+case 109:
+       if ( (*p) < 65 ) {
+               if ( 48 <= (*p) && (*p) <= 57 )
+                       goto st107;
+       } else if ( (*p) > 70 ) {
+               if ( 97 <= (*p) && (*p) <= 102 )
+                       goto st107;
+       } else
+               goto st107;
+       goto st0;
+tr26:
+#line 108 "http_parser.rl"
+       { parser->uri_mark            = p; }
+       goto st110;
+st110:
+       if ( ++p == pe )
+               goto _test_eof110;
+case 110:
+#line 2939 "http_parser.c"
+       switch( (*p) ) {
+               case 43: goto st110;
+               case 58: goto st111;
+       }
+       if ( (*p) < 48 ) {
+               if ( 45 <= (*p) && (*p) <= 46 )
+                       goto st110;
+       } else if ( (*p) > 57 ) {
+               if ( (*p) > 90 ) {
+                       if ( 97 <= (*p) && (*p) <= 122 )
+                               goto st110;
+               } else if ( (*p) >= 65 )
+                       goto st110;
+       } else
+               goto st110;
+       goto st0;
+tr28:
+#line 108 "http_parser.rl"
+       { parser->uri_mark            = p; }
+       goto st111;
+st111:
+       if ( ++p == pe )
+               goto _test_eof111;
+case 111:
+#line 2964 "http_parser.c"
+       switch( (*p) ) {
+               case 32: goto tr29;
+               case 34: goto st0;
+               case 35: goto tr30;
+               case 37: goto st112;
+               case 60: goto st0;
+               case 62: goto st0;
+               case 127: goto st0;
+       }
+       if ( 0 <= (*p) && (*p) <= 31 )
+               goto st0;
+       goto st111;
+st112:
+       if ( ++p == pe )
+               goto _test_eof112;
+case 112:
+       if ( (*p) < 65 ) {
+               if ( 48 <= (*p) && (*p) <= 57 )
+                       goto st113;
+       } else if ( (*p) > 70 ) {
+               if ( 97 <= (*p) && (*p) <= 102 )
+                       goto st113;
+       } else
+               goto st113;
+       goto st0;
+st113:
+       if ( ++p == pe )
+               goto _test_eof113;
+case 113:
+       if ( (*p) < 65 ) {
+               if ( 48 <= (*p) && (*p) <= 57 )
+                       goto st111;
+       } else if ( (*p) > 70 ) {
+               if ( 97 <= (*p) && (*p) <= 102 )
+                       goto st111;
+       } else
+               goto st111;
+       goto st0;
+tr27:
+#line 108 "http_parser.rl"
+       { parser->uri_mark            = p; }
+#line 107 "http_parser.rl"
+       { parser->path_mark           = p; }
+       goto st114;
+st114:
+       if ( ++p == pe )
+               goto _test_eof114;
+case 114:
+#line 3013 "http_parser.c"
+       switch( (*p) ) {
+               case 32: goto tr135;
+               case 34: goto st0;
+               case 35: goto tr136;
+               case 37: goto st115;
+               case 60: goto st0;
+               case 62: goto st0;
+               case 63: goto tr138;
+               case 127: goto st0;
+       }
+       if ( 0 <= (*p) && (*p) <= 31 )
+               goto st0;
+       goto st114;
+st115:
+       if ( ++p == pe )
+               goto _test_eof115;
+case 115:
+       if ( (*p) < 65 ) {
+               if ( 48 <= (*p) && (*p) <= 57 )
+                       goto st116;
+       } else if ( (*p) > 70 ) {
+               if ( 97 <= (*p) && (*p) <= 102 )
+                       goto st116;
+       } else
+               goto st116;
+       goto st0;
+st116:
+       if ( ++p == pe )
+               goto _test_eof116;
+case 116:
+       if ( (*p) < 65 ) {
+               if ( 48 <= (*p) && (*p) <= 57 )
+                       goto st114;
+       } else if ( (*p) > 70 ) {
+               if ( 97 <= (*p) && (*p) <= 102 )
+                       goto st114;
+       } else
+               goto st114;
+       goto st0;
+tr138:
+#line 140 "http_parser.rl"
+       {
+    CALLBACK(path);
+    if (callback_return_value != 0) {p++; cs = 117; goto _out;}
+    parser->path_mark = NULL;
+  }
+       goto st117;
+st117:
+       if ( ++p == pe )
+               goto _test_eof117;
+case 117:
+#line 3065 "http_parser.c"
+       switch( (*p) ) {
+               case 32: goto tr141;
+               case 34: goto st0;
+               case 35: goto tr142;
+               case 37: goto tr143;
+               case 60: goto st0;
+               case 62: goto st0;
+               case 127: goto st0;
+       }
+       if ( 0 <= (*p) && (*p) <= 31 )
+               goto st0;
+       goto tr140;
+tr140:
+#line 106 "http_parser.rl"
+       { parser->query_string_mark   = p; }
+       goto st118;
+st118:
+       if ( ++p == pe )
+               goto _test_eof118;
+case 118:
+#line 3086 "http_parser.c"
+       switch( (*p) ) {
+               case 32: goto tr145;
+               case 34: goto st0;
+               case 35: goto tr146;
+               case 37: goto st119;
+               case 60: goto st0;
+               case 62: goto st0;
+               case 127: goto st0;
+       }
+       if ( 0 <= (*p) && (*p) <= 31 )
+               goto st0;
+       goto st118;
+tr143:
+#line 106 "http_parser.rl"
+       { parser->query_string_mark   = p; }
+       goto st119;
+st119:
+       if ( ++p == pe )
+               goto _test_eof119;
+case 119:
+#line 3107 "http_parser.c"
+       if ( (*p) < 65 ) {
+               if ( 48 <= (*p) && (*p) <= 57 )
+                       goto st120;
+       } else if ( (*p) > 70 ) {
+               if ( 97 <= (*p) && (*p) <= 102 )
+                       goto st120;
+       } else
+               goto st120;
+       goto st0;
+st120:
+       if ( ++p == pe )
+               goto _test_eof120;
+case 120:
+       if ( (*p) < 65 ) {
+               if ( 48 <= (*p) && (*p) <= 57 )
+                       goto st118;
+       } else if ( (*p) > 70 ) {
+               if ( 97 <= (*p) && (*p) <= 102 )
+                       goto st118;
+       } else
+               goto st118;
+       goto st0;
+tr312:
+#line 153 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {p++; cs = 121; goto _out;}
+    }
+  }
+       goto st121;
+st121:
+       if ( ++p == pe )
+               goto _test_eof121;
+case 121:
+#line 3143 "http_parser.c"
+       if ( (*p) == 69 )
+               goto st122;
+       goto st0;
+st122:
+       if ( ++p == pe )
+               goto _test_eof122;
+case 122:
+       if ( (*p) == 76 )
+               goto st123;
+       goto st0;
+st123:
+       if ( ++p == pe )
+               goto _test_eof123;
+case 123:
+       if ( (*p) == 69 )
+               goto st124;
+       goto st0;
+st124:
+       if ( ++p == pe )
+               goto _test_eof124;
+case 124:
+       if ( (*p) == 84 )
+               goto st125;
+       goto st0;
+st125:
+       if ( ++p == pe )
+               goto _test_eof125;
+case 125:
+       if ( (*p) == 69 )
+               goto st126;
+       goto st0;
+st126:
+       if ( ++p == pe )
+               goto _test_eof126;
+case 126:
+       if ( (*p) == 32 )
+               goto tr154;
+       goto st0;
+tr313:
+#line 153 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {p++; cs = 127; goto _out;}
+    }
+  }
+       goto st127;
+st127:
+       if ( ++p == pe )
+               goto _test_eof127;
+case 127:
+#line 3195 "http_parser.c"
+       if ( (*p) == 69 )
+               goto st128;
+       goto st0;
+st128:
+       if ( ++p == pe )
+               goto _test_eof128;
+case 128:
+       if ( (*p) == 84 )
+               goto st129;
+       goto st0;
+st129:
+       if ( ++p == pe )
+               goto _test_eof129;
+case 129:
+       if ( (*p) == 32 )
+               goto tr157;
+       goto st0;
+tr314:
+#line 153 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {p++; cs = 130; goto _out;}
+    }
+  }
+       goto st130;
+st130:
+       if ( ++p == pe )
+               goto _test_eof130;
+case 130:
+#line 3226 "http_parser.c"
+       if ( (*p) == 69 )
+               goto st131;
+       goto st0;
+st131:
+       if ( ++p == pe )
+               goto _test_eof131;
+case 131:
+       if ( (*p) == 65 )
+               goto st132;
+       goto st0;
+st132:
+       if ( ++p == pe )
+               goto _test_eof132;
+case 132:
+       if ( (*p) == 68 )
+               goto st133;
+       goto st0;
+st133:
+       if ( ++p == pe )
+               goto _test_eof133;
+case 133:
+       if ( (*p) == 32 )
+               goto tr161;
+       goto st0;
+tr315:
+#line 153 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {p++; cs = 134; goto _out;}
+    }
+  }
+       goto st134;
+st134:
+       if ( ++p == pe )
+               goto _test_eof134;
+case 134:
+#line 3264 "http_parser.c"
+       if ( (*p) == 79 )
+               goto st135;
+       goto st0;
+st135:
+       if ( ++p == pe )
+               goto _test_eof135;
+case 135:
+       if ( (*p) == 67 )
+               goto st136;
+       goto st0;
+st136:
+       if ( ++p == pe )
+               goto _test_eof136;
+case 136:
+       if ( (*p) == 75 )
+               goto st137;
+       goto st0;
+st137:
+       if ( ++p == pe )
+               goto _test_eof137;
+case 137:
+       if ( (*p) == 32 )
+               goto tr165;
+       goto st0;
+tr316:
+#line 153 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {p++; cs = 138; goto _out;}
+    }
+  }
+       goto st138;
+st138:
+       if ( ++p == pe )
+               goto _test_eof138;
+case 138:
+#line 3302 "http_parser.c"
+       switch( (*p) ) {
+               case 75: goto st139;
+               case 79: goto st143;
+       }
+       goto st0;
+st139:
+       if ( ++p == pe )
+               goto _test_eof139;
+case 139:
+       if ( (*p) == 67 )
+               goto st140;
+       goto st0;
+st140:
+       if ( ++p == pe )
+               goto _test_eof140;
+case 140:
+       if ( (*p) == 79 )
+               goto st141;
+       goto st0;
+st141:
+       if ( ++p == pe )
+               goto _test_eof141;
+case 141:
+       if ( (*p) == 76 )
+               goto st142;
+       goto st0;
+st142:
+       if ( ++p == pe )
+               goto _test_eof142;
+case 142:
+       if ( (*p) == 32 )
+               goto tr171;
+       goto st0;
+st143:
+       if ( ++p == pe )
+               goto _test_eof143;
+case 143:
+       if ( (*p) == 86 )
+               goto st144;
+       goto st0;
+st144:
+       if ( ++p == pe )
+               goto _test_eof144;
+case 144:
+       if ( (*p) == 69 )
+               goto st145;
+       goto st0;
+st145:
+       if ( ++p == pe )
+               goto _test_eof145;
+case 145:
+       if ( (*p) == 32 )
+               goto tr174;
+       goto st0;
+tr317:
+#line 153 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {p++; cs = 146; goto _out;}
+    }
+  }
+       goto st146;
+st146:
+       if ( ++p == pe )
+               goto _test_eof146;
+case 146:
+#line 3370 "http_parser.c"
+       if ( (*p) == 80 )
+               goto st147;
+       goto st0;
+st147:
+       if ( ++p == pe )
+               goto _test_eof147;
+case 147:
+       if ( (*p) == 84 )
+               goto st148;
+       goto st0;
+st148:
+       if ( ++p == pe )
+               goto _test_eof148;
+case 148:
+       if ( (*p) == 73 )
+               goto st149;
+       goto st0;
+st149:
+       if ( ++p == pe )
+               goto _test_eof149;
+case 149:
+       if ( (*p) == 79 )
+               goto st150;
+       goto st0;
+st150:
+       if ( ++p == pe )
+               goto _test_eof150;
+case 150:
+       if ( (*p) == 78 )
+               goto st151;
+       goto st0;
+st151:
+       if ( ++p == pe )
+               goto _test_eof151;
+case 151:
+       if ( (*p) == 83 )
+               goto st152;
+       goto st0;
+st152:
+       if ( ++p == pe )
+               goto _test_eof152;
+case 152:
+       if ( (*p) == 32 )
+               goto tr181;
+       goto st0;
+tr318:
+#line 153 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {p++; cs = 153; goto _out;}
+    }
+  }
+       goto st153;
+st153:
+       if ( ++p == pe )
+               goto _test_eof153;
+case 153:
+#line 3429 "http_parser.c"
+       switch( (*p) ) {
+               case 79: goto st154;
+               case 82: goto st157;
+               case 85: goto st169;
+       }
+       goto st0;
+st154:
+       if ( ++p == pe )
+               goto _test_eof154;
+case 154:
+       if ( (*p) == 83 )
+               goto st155;
+       goto st0;
+st155:
+       if ( ++p == pe )
+               goto _test_eof155;
+case 155:
+       if ( (*p) == 84 )
+               goto st156;
+       goto st0;
+st156:
+       if ( ++p == pe )
+               goto _test_eof156;
+case 156:
+       if ( (*p) == 32 )
+               goto tr187;
+       goto st0;
+st157:
+       if ( ++p == pe )
+               goto _test_eof157;
+case 157:
+       if ( (*p) == 79 )
+               goto st158;
+       goto st0;
+st158:
+       if ( ++p == pe )
+               goto _test_eof158;
+case 158:
+       if ( (*p) == 80 )
+               goto st159;
+       goto st0;
+st159:
+       if ( ++p == pe )
+               goto _test_eof159;
+case 159:
+       switch( (*p) ) {
+               case 70: goto st160;
+               case 80: goto st164;
+       }
+       goto st0;
+st160:
+       if ( ++p == pe )
+               goto _test_eof160;
+case 160:
+       if ( (*p) == 73 )
+               goto st161;
+       goto st0;
+st161:
+       if ( ++p == pe )
+               goto _test_eof161;
+case 161:
+       if ( (*p) == 78 )
+               goto st162;
+       goto st0;
+st162:
+       if ( ++p == pe )
+               goto _test_eof162;
+case 162:
+       if ( (*p) == 68 )
+               goto st163;
+       goto st0;
+st163:
+       if ( ++p == pe )
+               goto _test_eof163;
+case 163:
+       if ( (*p) == 32 )
+               goto tr195;
+       goto st0;
+st164:
+       if ( ++p == pe )
+               goto _test_eof164;
+case 164:
+       if ( (*p) == 65 )
+               goto st165;
+       goto st0;
+st165:
+       if ( ++p == pe )
+               goto _test_eof165;
+case 165:
+       if ( (*p) == 84 )
+               goto st166;
+       goto st0;
+st166:
+       if ( ++p == pe )
+               goto _test_eof166;
+case 166:
+       if ( (*p) == 67 )
+               goto st167;
+       goto st0;
+st167:
+       if ( ++p == pe )
+               goto _test_eof167;
+case 167:
+       if ( (*p) == 72 )
+               goto st168;
+       goto st0;
+st168:
+       if ( ++p == pe )
+               goto _test_eof168;
+case 168:
+       if ( (*p) == 32 )
+               goto tr200;
+       goto st0;
+st169:
+       if ( ++p == pe )
+               goto _test_eof169;
+case 169:
+       if ( (*p) == 84 )
+               goto st170;
+       goto st0;
+st170:
+       if ( ++p == pe )
+               goto _test_eof170;
+case 170:
+       if ( (*p) == 32 )
+               goto tr202;
+       goto st0;
+tr319:
+#line 153 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {p++; cs = 171; goto _out;}
+    }
+  }
+       goto st171;
+st171:
+       if ( ++p == pe )
+               goto _test_eof171;
+case 171:
+#line 3570 "http_parser.c"
+       if ( (*p) == 82 )
+               goto st172;
+       goto st0;
+st172:
+       if ( ++p == pe )
+               goto _test_eof172;
+case 172:
+       if ( (*p) == 65 )
+               goto st173;
+       goto st0;
+st173:
+       if ( ++p == pe )
+               goto _test_eof173;
+case 173:
+       if ( (*p) == 67 )
+               goto st174;
+       goto st0;
+st174:
+       if ( ++p == pe )
+               goto _test_eof174;
+case 174:
+       if ( (*p) == 69 )
+               goto st175;
+       goto st0;
+st175:
+       if ( ++p == pe )
+               goto _test_eof175;
+case 175:
+       if ( (*p) == 32 )
+               goto tr207;
+       goto st0;
+tr320:
+#line 153 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {p++; cs = 176; goto _out;}
+    }
+  }
+       goto st176;
+st176:
+       if ( ++p == pe )
+               goto _test_eof176;
+case 176:
+#line 3615 "http_parser.c"
+       if ( (*p) == 78 )
+               goto st177;
+       goto st0;
+st177:
+       if ( ++p == pe )
+               goto _test_eof177;
+case 177:
+       if ( (*p) == 76 )
+               goto st178;
+       goto st0;
+st178:
+       if ( ++p == pe )
+               goto _test_eof178;
+case 178:
+       if ( (*p) == 79 )
+               goto st179;
+       goto st0;
+st179:
+       if ( ++p == pe )
+               goto _test_eof179;
+case 179:
+       if ( (*p) == 67 )
+               goto st180;
+       goto st0;
+st180:
+       if ( ++p == pe )
+               goto _test_eof180;
+case 180:
+       if ( (*p) == 75 )
+               goto st181;
+       goto st0;
+st181:
+       if ( ++p == pe )
+               goto _test_eof181;
+case 181:
+       if ( (*p) == 32 )
+               goto tr213;
+       goto st0;
+tr233:
+       cs = 270;
+#line 146 "http_parser.rl"
+       {
+    if(parser->on_headers_complete) {
+      callback_return_value = parser->on_headers_complete(parser);
+      if (callback_return_value != 0) {p++; goto _out;}
+    }
+  }
+#line 212 "http_parser.rl"
+       {
+    if (parser->transfer_encoding == HTTP_CHUNKED) {
+      cs = 2;
+    } else {
+      /* this is pretty stupid. i'd prefer to combine this with skip_chunk_data */
+      parser->chunk_size = parser->content_length;
+      p += 1;  
+
+      SKIP_BODY(MIN(REMAINING, parser->content_length));
+      if (callback_return_value != 0) {p++; goto _out;}
+
+      p--;
+      if(parser->chunk_size > REMAINING) {
+        {p++; goto _out;}
+      }
+    }
+  }
+       goto _again;
+st270:
+       if ( ++p == pe )
+               goto _test_eof270;
+case 270:
+#line 3686 "http_parser.c"
+       if ( (*p) == 72 )
+               goto tr321;
+       goto st0;
+tr321:
+#line 153 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {p++; cs = 182; goto _out;}
+    }
+  }
+       goto st182;
+st182:
+       if ( ++p == pe )
+               goto _test_eof182;
+case 182:
+#line 3703 "http_parser.c"
+       if ( (*p) == 84 )
+               goto st183;
+       goto st0;
+st183:
+       if ( ++p == pe )
+               goto _test_eof183;
+case 183:
+       if ( (*p) == 84 )
+               goto st184;
+       goto st0;
+st184:
+       if ( ++p == pe )
+               goto _test_eof184;
+case 184:
+       if ( (*p) == 80 )
+               goto st185;
+       goto st0;
+st185:
+       if ( ++p == pe )
+               goto _test_eof185;
+case 185:
+       if ( (*p) == 47 )
+               goto st186;
+       goto st0;
+st186:
+       if ( ++p == pe )
+               goto _test_eof186;
+case 186:
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr218;
+       goto st0;
+tr218:
+#line 176 "http_parser.rl"
+       {
+    parser->version_major *= 10;
+    parser->version_major += *p - '0';
+  }
+       goto st187;
+st187:
+       if ( ++p == pe )
+               goto _test_eof187;
+case 187:
+#line 3746 "http_parser.c"
+       if ( (*p) == 46 )
+               goto st188;
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr218;
+       goto st0;
+st188:
+       if ( ++p == pe )
+               goto _test_eof188;
+case 188:
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr220;
+       goto st0;
+tr220:
+#line 181 "http_parser.rl"
+       {
+    parser->version_minor *= 10;
+    parser->version_minor += *p - '0';
+  }
+       goto st189;
+st189:
+       if ( ++p == pe )
+               goto _test_eof189;
+case 189:
+#line 3770 "http_parser.c"
+       if ( (*p) == 32 )
+               goto st190;
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr220;
+       goto st0;
+st190:
+       if ( ++p == pe )
+               goto _test_eof190;
+case 190:
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr222;
+       goto st0;
+tr222:
+#line 165 "http_parser.rl"
+       {
+    parser->status_code *= 10;
+    parser->status_code += *p - '0';
+  }
+       goto st191;
+st191:
+       if ( ++p == pe )
+               goto _test_eof191;
+case 191:
+#line 3794 "http_parser.c"
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr223;
+       goto st0;
+tr223:
+#line 165 "http_parser.rl"
+       {
+    parser->status_code *= 10;
+    parser->status_code += *p - '0';
+  }
+       goto st192;
+st192:
+       if ( ++p == pe )
+               goto _test_eof192;
+case 192:
+#line 3809 "http_parser.c"
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr224;
+       goto st0;
+tr224:
+#line 165 "http_parser.rl"
+       {
+    parser->status_code *= 10;
+    parser->status_code += *p - '0';
+  }
+       goto st193;
+st193:
+       if ( ++p == pe )
+               goto _test_eof193;
+case 193:
+#line 3824 "http_parser.c"
+       if ( (*p) == 32 )
+               goto st194;
+       goto st0;
+st194:
+       if ( ++p == pe )
+               goto _test_eof194;
+case 194:
+       if ( (*p) < 11 ) {
+               if ( 0 <= (*p) && (*p) <= 9 )
+                       goto st195;
+       } else if ( (*p) > 12 ) {
+               if ( 14 <= (*p) )
+                       goto st195;
+       } else
+               goto st195;
+       goto st0;
+st195:
+       if ( ++p == pe )
+               goto _test_eof195;
+case 195:
+       if ( (*p) == 13 )
+               goto st196;
+       if ( (*p) > 9 ) {
+               if ( 11 <= (*p) )
+                       goto st195;
+       } else if ( (*p) >= 0 )
+               goto st195;
+       goto st0;
+tr237:
+#line 104 "http_parser.rl"
+       { parser->header_value_mark   = p; }
+#line 116 "http_parser.rl"
+       {
+    CALLBACK(header_value);
+    if (callback_return_value != 0) {p++; cs = 196; goto _out;}
+    parser->header_value_mark = NULL;
+  }
+       goto st196;
+tr240:
+#line 116 "http_parser.rl"
+       {
+    CALLBACK(header_value);
+    if (callback_return_value != 0) {p++; cs = 196; goto _out;}
+    parser->header_value_mark = NULL;
+  }
+       goto st196;
+tr259:
+#line 174 "http_parser.rl"
+       { parser->keep_alive = FALSE; }
+#line 116 "http_parser.rl"
+       {
+    CALLBACK(header_value);
+    if (callback_return_value != 0) {p++; cs = 196; goto _out;}
+    parser->header_value_mark = NULL;
+  }
+       goto st196;
+tr269:
+#line 173 "http_parser.rl"
+       { parser->keep_alive = TRUE; }
+#line 116 "http_parser.rl"
+       {
+    CALLBACK(header_value);
+    if (callback_return_value != 0) {p++; cs = 196; goto _out;}
+    parser->header_value_mark = NULL;
+  }
+       goto st196;
+tr310:
+#line 170 "http_parser.rl"
+       { parser->transfer_encoding = HTTP_IDENTITY; }
+#line 116 "http_parser.rl"
+       {
+    CALLBACK(header_value);
+    if (callback_return_value != 0) {p++; cs = 196; goto _out;}
+    parser->header_value_mark = NULL;
+  }
+       goto st196;
+st196:
+       if ( ++p == pe )
+               goto _test_eof196;
+case 196:
+#line 3905 "http_parser.c"
+       if ( (*p) == 10 )
+               goto st197;
+       goto st0;
+st197:
+       if ( ++p == pe )
+               goto _test_eof197;
+case 197:
+       switch( (*p) ) {
+               case 13: goto st198;
+               case 33: goto tr230;
+               case 67: goto tr231;
+               case 84: goto tr232;
+               case 99: goto tr231;
+               case 116: goto tr232;
+               case 124: goto tr230;
+               case 126: goto tr230;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto tr230;
+               } else if ( (*p) >= 35 )
+                       goto tr230;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto tr230;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto tr230;
+               } else
+                       goto tr230;
+       } else
+               goto tr230;
+       goto st0;
+st198:
+       if ( ++p == pe )
+               goto _test_eof198;
+case 198:
+       if ( (*p) == 10 )
+               goto tr233;
+       goto st0;
+tr230:
+#line 103 "http_parser.rl"
+       { parser->header_field_mark   = p; }
+       goto st199;
+st199:
+       if ( ++p == pe )
+               goto _test_eof199;
+case 199:
+#line 3956 "http_parser.c"
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+tr235:
+#line 110 "http_parser.rl"
+       {
+    CALLBACK(header_field);
+    if (callback_return_value != 0) {p++; cs = 200; goto _out;}
+    parser->header_field_mark = NULL;
+  }
+       goto st200;
+st200:
+       if ( ++p == pe )
+               goto _test_eof200;
+case 200:
+#line 3993 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr237;
+               case 32: goto st200;
+       }
+       goto tr236;
+tr236:
+#line 104 "http_parser.rl"
+       { parser->header_value_mark   = p; }
+       goto st201;
+st201:
+       if ( ++p == pe )
+               goto _test_eof201;
+case 201:
+#line 4007 "http_parser.c"
+       if ( (*p) == 13 )
+               goto tr240;
+       goto st201;
+tr231:
+#line 103 "http_parser.rl"
+       { parser->header_field_mark   = p; }
+       goto st202;
+st202:
+       if ( ++p == pe )
+               goto _test_eof202;
+case 202:
+#line 4019 "http_parser.c"
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 79: goto st203;
+               case 111: goto st203;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st203:
+       if ( ++p == pe )
+               goto _test_eof203;
+case 203:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 78: goto st204;
+               case 110: goto st204;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st204:
+       if ( ++p == pe )
+               goto _test_eof204;
+case 204:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 78: goto st205;
+               case 84: goto st228;
+               case 110: goto st205;
+               case 116: goto st228;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st205:
+       if ( ++p == pe )
+               goto _test_eof205;
+case 205:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 69: goto st206;
+               case 101: goto st206;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st206:
+       if ( ++p == pe )
+               goto _test_eof206;
+case 206:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 67: goto st207;
+               case 99: goto st207;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st207:
+       if ( ++p == pe )
+               goto _test_eof207;
+case 207:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 84: goto st208;
+               case 116: goto st208;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st208:
+       if ( ++p == pe )
+               goto _test_eof208;
+case 208:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 73: goto st209;
+               case 105: goto st209;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st209:
+       if ( ++p == pe )
+               goto _test_eof209;
+case 209:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 79: goto st210;
+               case 111: goto st210;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st210:
+       if ( ++p == pe )
+               goto _test_eof210;
+case 210:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 78: goto st211;
+               case 110: goto st211;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st211:
+       if ( ++p == pe )
+               goto _test_eof211;
+case 211:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr251;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+tr251:
+#line 110 "http_parser.rl"
+       {
+    CALLBACK(header_field);
+    if (callback_return_value != 0) {p++; cs = 212; goto _out;}
+    parser->header_field_mark = NULL;
+  }
+       goto st212;
+st212:
+       if ( ++p == pe )
+               goto _test_eof212;
+case 212:
+#line 4328 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr237;
+               case 32: goto st212;
+               case 67: goto tr253;
+               case 75: goto tr254;
+               case 99: goto tr253;
+               case 107: goto tr254;
+       }
+       goto tr236;
+tr253:
+#line 104 "http_parser.rl"
+       { parser->header_value_mark   = p; }
+       goto st213;
+st213:
+       if ( ++p == pe )
+               goto _test_eof213;
+case 213:
+#line 4346 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 76: goto st214;
+               case 108: goto st214;
+       }
+       goto st201;
+st214:
+       if ( ++p == pe )
+               goto _test_eof214;
+case 214:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 79: goto st215;
+               case 111: goto st215;
+       }
+       goto st201;
+st215:
+       if ( ++p == pe )
+               goto _test_eof215;
+case 215:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 83: goto st216;
+               case 115: goto st216;
+       }
+       goto st201;
+st216:
+       if ( ++p == pe )
+               goto _test_eof216;
+case 216:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 69: goto st217;
+               case 101: goto st217;
+       }
+       goto st201;
+st217:
+       if ( ++p == pe )
+               goto _test_eof217;
+case 217:
+       if ( (*p) == 13 )
+               goto tr259;
+       goto st201;
+tr254:
+#line 104 "http_parser.rl"
+       { parser->header_value_mark   = p; }
+       goto st218;
+st218:
+       if ( ++p == pe )
+               goto _test_eof218;
+case 218:
+#line 4398 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 69: goto st219;
+               case 101: goto st219;
+       }
+       goto st201;
+st219:
+       if ( ++p == pe )
+               goto _test_eof219;
+case 219:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 69: goto st220;
+               case 101: goto st220;
+       }
+       goto st201;
+st220:
+       if ( ++p == pe )
+               goto _test_eof220;
+case 220:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 80: goto st221;
+               case 112: goto st221;
+       }
+       goto st201;
+st221:
+       if ( ++p == pe )
+               goto _test_eof221;
+case 221:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 45: goto st222;
+       }
+       goto st201;
+st222:
+       if ( ++p == pe )
+               goto _test_eof222;
+case 222:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 65: goto st223;
+               case 97: goto st223;
+       }
+       goto st201;
+st223:
+       if ( ++p == pe )
+               goto _test_eof223;
+case 223:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 76: goto st224;
+               case 108: goto st224;
+       }
+       goto st201;
+st224:
+       if ( ++p == pe )
+               goto _test_eof224;
+case 224:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 73: goto st225;
+               case 105: goto st225;
+       }
+       goto st201;
+st225:
+       if ( ++p == pe )
+               goto _test_eof225;
+case 225:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 86: goto st226;
+               case 118: goto st226;
+       }
+       goto st201;
+st226:
+       if ( ++p == pe )
+               goto _test_eof226;
+case 226:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 69: goto st227;
+               case 101: goto st227;
+       }
+       goto st201;
+st227:
+       if ( ++p == pe )
+               goto _test_eof227;
+case 227:
+       if ( (*p) == 13 )
+               goto tr269;
+       goto st201;
+st228:
+       if ( ++p == pe )
+               goto _test_eof228;
+case 228:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 69: goto st229;
+               case 101: goto st229;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st229:
+       if ( ++p == pe )
+               goto _test_eof229;
+case 229:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 78: goto st230;
+               case 110: goto st230;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st230:
+       if ( ++p == pe )
+               goto _test_eof230;
+case 230:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 84: goto st231;
+               case 116: goto st231;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st231:
+       if ( ++p == pe )
+               goto _test_eof231;
+case 231:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 45: goto st232;
+               case 46: goto st199;
+               case 58: goto tr235;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 48 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 57 ) {
+               if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else if ( (*p) >= 65 )
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st232:
+       if ( ++p == pe )
+               goto _test_eof232;
+case 232:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 76: goto st233;
+               case 108: goto st233;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st233:
+       if ( ++p == pe )
+               goto _test_eof233;
+case 233:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 69: goto st234;
+               case 101: goto st234;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st234:
+       if ( ++p == pe )
+               goto _test_eof234;
+case 234:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 78: goto st235;
+               case 110: goto st235;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st235:
+       if ( ++p == pe )
+               goto _test_eof235;
+case 235:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 71: goto st236;
+               case 103: goto st236;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st236:
+       if ( ++p == pe )
+               goto _test_eof236;
+case 236:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 84: goto st237;
+               case 116: goto st237;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st237:
+       if ( ++p == pe )
+               goto _test_eof237;
+case 237:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 72: goto st238;
+               case 104: goto st238;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st238:
+       if ( ++p == pe )
+               goto _test_eof238;
+case 238:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr280;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+tr280:
+#line 110 "http_parser.rl"
+       {
+    CALLBACK(header_field);
+    if (callback_return_value != 0) {p++; cs = 239; goto _out;}
+    parser->header_field_mark = NULL;
+  }
+       goto st239;
+st239:
+       if ( ++p == pe )
+               goto _test_eof239;
+case 239:
+#line 4828 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr237;
+               case 32: goto st239;
+       }
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr282;
+       goto tr236;
+tr282:
+#line 160 "http_parser.rl"
+       {
+    parser->content_length *= 10;
+    parser->content_length += *p - '0';
+  }
+#line 104 "http_parser.rl"
+       { parser->header_value_mark   = p; }
+       goto st240;
+tr283:
+#line 160 "http_parser.rl"
+       {
+    parser->content_length *= 10;
+    parser->content_length += *p - '0';
+  }
+       goto st240;
+st240:
+       if ( ++p == pe )
+               goto _test_eof240;
+case 240:
+#line 4856 "http_parser.c"
+       if ( (*p) == 13 )
+               goto tr240;
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr283;
+       goto st201;
+tr232:
+#line 103 "http_parser.rl"
+       { parser->header_field_mark   = p; }
+       goto st241;
+st241:
+       if ( ++p == pe )
+               goto _test_eof241;
+case 241:
+#line 4870 "http_parser.c"
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 82: goto st242;
+               case 114: goto st242;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st242:
+       if ( ++p == pe )
+               goto _test_eof242;
+case 242:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 65: goto st243;
+               case 97: goto st243;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 66 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st243:
+       if ( ++p == pe )
+               goto _test_eof243;
+case 243:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 78: goto st244;
+               case 110: goto st244;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st244:
+       if ( ++p == pe )
+               goto _test_eof244;
+case 244:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 83: goto st245;
+               case 115: goto st245;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st245:
+       if ( ++p == pe )
+               goto _test_eof245;
+case 245:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 70: goto st246;
+               case 102: goto st246;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st246:
+       if ( ++p == pe )
+               goto _test_eof246;
+case 246:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 69: goto st247;
+               case 101: goto st247;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st247:
+       if ( ++p == pe )
+               goto _test_eof247;
+case 247:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 82: goto st248;
+               case 114: goto st248;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st248:
+       if ( ++p == pe )
+               goto _test_eof248;
+case 248:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 45: goto st249;
+               case 46: goto st199;
+               case 58: goto tr235;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 48 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 57 ) {
+               if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else if ( (*p) >= 65 )
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st249:
+       if ( ++p == pe )
+               goto _test_eof249;
+case 249:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 69: goto st250;
+               case 101: goto st250;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st250:
+       if ( ++p == pe )
+               goto _test_eof250;
+case 250:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 78: goto st251;
+               case 110: goto st251;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st251:
+       if ( ++p == pe )
+               goto _test_eof251;
+case 251:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 67: goto st252;
+               case 99: goto st252;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st252:
+       if ( ++p == pe )
+               goto _test_eof252;
+case 252:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 79: goto st253;
+               case 111: goto st253;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st253:
+       if ( ++p == pe )
+               goto _test_eof253;
+case 253:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 68: goto st254;
+               case 100: goto st254;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st254:
+       if ( ++p == pe )
+               goto _test_eof254;
+case 254:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 73: goto st255;
+               case 105: goto st255;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st255:
+       if ( ++p == pe )
+               goto _test_eof255;
+case 255:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 78: goto st256;
+               case 110: goto st256;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st256:
+       if ( ++p == pe )
+               goto _test_eof256;
+case 256:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr235;
+               case 71: goto st257;
+               case 103: goto st257;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+st257:
+       if ( ++p == pe )
+               goto _test_eof257;
+case 257:
+       switch( (*p) ) {
+               case 33: goto st199;
+               case 58: goto tr300;
+               case 124: goto st199;
+               case 126: goto st199;
+       }
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st199;
+               } else if ( (*p) >= 35 )
+                       goto st199;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st199;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st199;
+               } else
+                       goto st199;
+       } else
+               goto st199;
+       goto st0;
+tr300:
+#line 171 "http_parser.rl"
+       { parser->transfer_encoding = HTTP_CHUNKED;  }
+#line 110 "http_parser.rl"
+       {
+    CALLBACK(header_field);
+    if (callback_return_value != 0) {p++; cs = 258; goto _out;}
+    parser->header_field_mark = NULL;
+  }
+       goto st258;
+st258:
+       if ( ++p == pe )
+               goto _test_eof258;
+case 258:
+#line 5386 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr237;
+               case 32: goto st258;
+               case 105: goto tr302;
+       }
+       goto tr236;
+tr302:
+#line 104 "http_parser.rl"
+       { parser->header_value_mark   = p; }
+       goto st259;
+st259:
+       if ( ++p == pe )
+               goto _test_eof259;
+case 259:
+#line 5401 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 100: goto st260;
+       }
+       goto st201;
+st260:
+       if ( ++p == pe )
+               goto _test_eof260;
+case 260:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 101: goto st261;
+       }
+       goto st201;
+st261:
+       if ( ++p == pe )
+               goto _test_eof261;
+case 261:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 110: goto st262;
+       }
+       goto st201;
+st262:
+       if ( ++p == pe )
+               goto _test_eof262;
+case 262:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 116: goto st263;
+       }
+       goto st201;
+st263:
+       if ( ++p == pe )
+               goto _test_eof263;
+case 263:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 105: goto st264;
+       }
+       goto st201;
+st264:
+       if ( ++p == pe )
+               goto _test_eof264;
+case 264:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 116: goto st265;
+       }
+       goto st201;
+st265:
+       if ( ++p == pe )
+               goto _test_eof265;
+case 265:
+       switch( (*p) ) {
+               case 13: goto tr240;
+               case 121: goto st266;
+       }
+       goto st201;
+st266:
+       if ( ++p == pe )
+               goto _test_eof266;
+case 266:
+       if ( (*p) == 13 )
+               goto tr310;
+       goto st201;
+       }
+       _test_eof1: cs = 1; goto _test_eof; 
+       _test_eof267: cs = 267; goto _test_eof; 
+       _test_eof2: cs = 2; goto _test_eof; 
+       _test_eof3: cs = 3; goto _test_eof; 
+       _test_eof4: cs = 4; goto _test_eof; 
+       _test_eof5: cs = 5; goto _test_eof; 
+       _test_eof6: cs = 6; goto _test_eof; 
+       _test_eof268: cs = 268; goto _test_eof; 
+       _test_eof7: cs = 7; goto _test_eof; 
+       _test_eof8: cs = 8; goto _test_eof; 
+       _test_eof9: cs = 9; goto _test_eof; 
+       _test_eof10: cs = 10; goto _test_eof; 
+       _test_eof11: cs = 11; goto _test_eof; 
+       _test_eof12: cs = 12; goto _test_eof; 
+       _test_eof13: cs = 13; goto _test_eof; 
+       _test_eof14: cs = 14; goto _test_eof; 
+       _test_eof15: cs = 15; goto _test_eof; 
+       _test_eof16: cs = 16; goto _test_eof; 
+       _test_eof17: cs = 17; goto _test_eof; 
+       _test_eof18: cs = 18; goto _test_eof; 
+       _test_eof19: cs = 19; goto _test_eof; 
+       _test_eof269: cs = 269; goto _test_eof; 
+       _test_eof20: cs = 20; goto _test_eof; 
+       _test_eof21: cs = 21; goto _test_eof; 
+       _test_eof22: cs = 22; goto _test_eof; 
+       _test_eof23: cs = 23; goto _test_eof; 
+       _test_eof24: cs = 24; goto _test_eof; 
+       _test_eof25: cs = 25; goto _test_eof; 
+       _test_eof26: cs = 26; goto _test_eof; 
+       _test_eof27: cs = 27; goto _test_eof; 
+       _test_eof28: cs = 28; goto _test_eof; 
+       _test_eof29: cs = 29; goto _test_eof; 
+       _test_eof30: cs = 30; goto _test_eof; 
+       _test_eof31: cs = 31; goto _test_eof; 
+       _test_eof32: cs = 32; goto _test_eof; 
+       _test_eof33: cs = 33; goto _test_eof; 
+       _test_eof34: cs = 34; goto _test_eof; 
+       _test_eof35: cs = 35; goto _test_eof; 
+       _test_eof36: cs = 36; goto _test_eof; 
+       _test_eof37: cs = 37; goto _test_eof; 
+       _test_eof38: cs = 38; goto _test_eof; 
+       _test_eof39: cs = 39; goto _test_eof; 
+       _test_eof40: cs = 40; goto _test_eof; 
+       _test_eof41: cs = 41; goto _test_eof; 
+       _test_eof42: cs = 42; goto _test_eof; 
+       _test_eof43: cs = 43; goto _test_eof; 
+       _test_eof44: cs = 44; goto _test_eof; 
+       _test_eof45: cs = 45; goto _test_eof; 
+       _test_eof46: cs = 46; goto _test_eof; 
+       _test_eof47: cs = 47; goto _test_eof; 
+       _test_eof48: cs = 48; goto _test_eof; 
+       _test_eof49: cs = 49; goto _test_eof; 
+       _test_eof50: cs = 50; goto _test_eof; 
+       _test_eof51: cs = 51; goto _test_eof; 
+       _test_eof52: cs = 52; goto _test_eof; 
+       _test_eof53: cs = 53; goto _test_eof; 
+       _test_eof54: cs = 54; goto _test_eof; 
+       _test_eof55: cs = 55; goto _test_eof; 
+       _test_eof56: cs = 56; goto _test_eof; 
+       _test_eof57: cs = 57; goto _test_eof; 
+       _test_eof58: cs = 58; goto _test_eof; 
+       _test_eof59: cs = 59; goto _test_eof; 
+       _test_eof60: cs = 60; goto _test_eof; 
+       _test_eof61: cs = 61; goto _test_eof; 
+       _test_eof62: cs = 62; goto _test_eof; 
+       _test_eof63: cs = 63; goto _test_eof; 
+       _test_eof64: cs = 64; goto _test_eof; 
+       _test_eof65: cs = 65; goto _test_eof; 
+       _test_eof66: cs = 66; goto _test_eof; 
+       _test_eof67: cs = 67; goto _test_eof; 
+       _test_eof68: cs = 68; goto _test_eof; 
+       _test_eof69: cs = 69; goto _test_eof; 
+       _test_eof70: cs = 70; goto _test_eof; 
+       _test_eof71: cs = 71; goto _test_eof; 
+       _test_eof72: cs = 72; goto _test_eof; 
+       _test_eof73: cs = 73; goto _test_eof; 
+       _test_eof74: cs = 74; goto _test_eof; 
+       _test_eof75: cs = 75; goto _test_eof; 
+       _test_eof76: cs = 76; goto _test_eof; 
+       _test_eof77: cs = 77; goto _test_eof; 
+       _test_eof78: cs = 78; goto _test_eof; 
+       _test_eof79: cs = 79; goto _test_eof; 
+       _test_eof80: cs = 80; goto _test_eof; 
+       _test_eof81: cs = 81; goto _test_eof; 
+       _test_eof82: cs = 82; goto _test_eof; 
+       _test_eof83: cs = 83; goto _test_eof; 
+       _test_eof84: cs = 84; goto _test_eof; 
+       _test_eof85: cs = 85; goto _test_eof; 
+       _test_eof86: cs = 86; goto _test_eof; 
+       _test_eof87: cs = 87; goto _test_eof; 
+       _test_eof88: cs = 88; goto _test_eof; 
+       _test_eof89: cs = 89; goto _test_eof; 
+       _test_eof90: cs = 90; goto _test_eof; 
+       _test_eof91: cs = 91; goto _test_eof; 
+       _test_eof92: cs = 92; goto _test_eof; 
+       _test_eof93: cs = 93; goto _test_eof; 
+       _test_eof94: cs = 94; goto _test_eof; 
+       _test_eof95: cs = 95; goto _test_eof; 
+       _test_eof96: cs = 96; goto _test_eof; 
+       _test_eof97: cs = 97; goto _test_eof; 
+       _test_eof98: cs = 98; goto _test_eof; 
+       _test_eof99: cs = 99; goto _test_eof; 
+       _test_eof100: cs = 100; goto _test_eof; 
+       _test_eof101: cs = 101; goto _test_eof; 
+       _test_eof102: cs = 102; goto _test_eof; 
+       _test_eof103: cs = 103; goto _test_eof; 
+       _test_eof104: cs = 104; goto _test_eof; 
+       _test_eof105: cs = 105; goto _test_eof; 
+       _test_eof106: cs = 106; goto _test_eof; 
+       _test_eof107: cs = 107; goto _test_eof; 
+       _test_eof108: cs = 108; goto _test_eof; 
+       _test_eof109: cs = 109; goto _test_eof; 
+       _test_eof110: cs = 110; goto _test_eof; 
+       _test_eof111: cs = 111; goto _test_eof; 
+       _test_eof112: cs = 112; goto _test_eof; 
+       _test_eof113: cs = 113; goto _test_eof; 
+       _test_eof114: cs = 114; goto _test_eof; 
+       _test_eof115: cs = 115; goto _test_eof; 
+       _test_eof116: cs = 116; goto _test_eof; 
+       _test_eof117: cs = 117; goto _test_eof; 
+       _test_eof118: cs = 118; goto _test_eof; 
+       _test_eof119: cs = 119; goto _test_eof; 
+       _test_eof120: cs = 120; goto _test_eof; 
+       _test_eof121: cs = 121; goto _test_eof; 
+       _test_eof122: cs = 122; goto _test_eof; 
+       _test_eof123: cs = 123; goto _test_eof; 
+       _test_eof124: cs = 124; goto _test_eof; 
+       _test_eof125: cs = 125; goto _test_eof; 
+       _test_eof126: cs = 126; goto _test_eof; 
+       _test_eof127: cs = 127; goto _test_eof; 
+       _test_eof128: cs = 128; goto _test_eof; 
+       _test_eof129: cs = 129; goto _test_eof; 
+       _test_eof130: cs = 130; goto _test_eof; 
+       _test_eof131: cs = 131; goto _test_eof; 
+       _test_eof132: cs = 132; goto _test_eof; 
+       _test_eof133: cs = 133; goto _test_eof; 
+       _test_eof134: cs = 134; goto _test_eof; 
+       _test_eof135: cs = 135; goto _test_eof; 
+       _test_eof136: cs = 136; goto _test_eof; 
+       _test_eof137: cs = 137; goto _test_eof; 
+       _test_eof138: cs = 138; goto _test_eof; 
+       _test_eof139: cs = 139; goto _test_eof; 
+       _test_eof140: cs = 140; goto _test_eof; 
+       _test_eof141: cs = 141; goto _test_eof; 
+       _test_eof142: cs = 142; goto _test_eof; 
+       _test_eof143: cs = 143; goto _test_eof; 
+       _test_eof144: cs = 144; goto _test_eof; 
+       _test_eof145: cs = 145; goto _test_eof; 
+       _test_eof146: cs = 146; goto _test_eof; 
+       _test_eof147: cs = 147; goto _test_eof; 
+       _test_eof148: cs = 148; goto _test_eof; 
+       _test_eof149: cs = 149; goto _test_eof; 
+       _test_eof150: cs = 150; goto _test_eof; 
+       _test_eof151: cs = 151; goto _test_eof; 
+       _test_eof152: cs = 152; goto _test_eof; 
+       _test_eof153: cs = 153; goto _test_eof; 
+       _test_eof154: cs = 154; goto _test_eof; 
+       _test_eof155: cs = 155; goto _test_eof; 
+       _test_eof156: cs = 156; goto _test_eof; 
+       _test_eof157: cs = 157; goto _test_eof; 
+       _test_eof158: cs = 158; goto _test_eof; 
+       _test_eof159: cs = 159; goto _test_eof; 
+       _test_eof160: cs = 160; goto _test_eof; 
+       _test_eof161: cs = 161; goto _test_eof; 
+       _test_eof162: cs = 162; goto _test_eof; 
+       _test_eof163: cs = 163; goto _test_eof; 
+       _test_eof164: cs = 164; goto _test_eof; 
+       _test_eof165: cs = 165; goto _test_eof; 
+       _test_eof166: cs = 166; goto _test_eof; 
+       _test_eof167: cs = 167; goto _test_eof; 
+       _test_eof168: cs = 168; goto _test_eof; 
+       _test_eof169: cs = 169; goto _test_eof; 
+       _test_eof170: cs = 170; goto _test_eof; 
+       _test_eof171: cs = 171; goto _test_eof; 
+       _test_eof172: cs = 172; goto _test_eof; 
+       _test_eof173: cs = 173; goto _test_eof; 
+       _test_eof174: cs = 174; goto _test_eof; 
+       _test_eof175: cs = 175; goto _test_eof; 
+       _test_eof176: cs = 176; goto _test_eof; 
+       _test_eof177: cs = 177; goto _test_eof; 
+       _test_eof178: cs = 178; goto _test_eof; 
+       _test_eof179: cs = 179; goto _test_eof; 
+       _test_eof180: cs = 180; goto _test_eof; 
+       _test_eof181: cs = 181; goto _test_eof; 
+       _test_eof270: cs = 270; goto _test_eof; 
+       _test_eof182: cs = 182; goto _test_eof; 
+       _test_eof183: cs = 183; goto _test_eof; 
+       _test_eof184: cs = 184; goto _test_eof; 
+       _test_eof185: cs = 185; goto _test_eof; 
+       _test_eof186: cs = 186; goto _test_eof; 
+       _test_eof187: cs = 187; goto _test_eof; 
+       _test_eof188: cs = 188; goto _test_eof; 
+       _test_eof189: cs = 189; goto _test_eof; 
+       _test_eof190: cs = 190; goto _test_eof; 
+       _test_eof191: cs = 191; goto _test_eof; 
+       _test_eof192: cs = 192; goto _test_eof; 
+       _test_eof193: cs = 193; goto _test_eof; 
+       _test_eof194: cs = 194; goto _test_eof; 
+       _test_eof195: cs = 195; goto _test_eof; 
+       _test_eof196: cs = 196; goto _test_eof; 
+       _test_eof197: cs = 197; goto _test_eof; 
+       _test_eof198: cs = 198; goto _test_eof; 
+       _test_eof199: cs = 199; goto _test_eof; 
+       _test_eof200: cs = 200; goto _test_eof; 
+       _test_eof201: cs = 201; goto _test_eof; 
+       _test_eof202: cs = 202; goto _test_eof; 
+       _test_eof203: cs = 203; goto _test_eof; 
+       _test_eof204: cs = 204; goto _test_eof; 
+       _test_eof205: cs = 205; goto _test_eof; 
+       _test_eof206: cs = 206; goto _test_eof; 
+       _test_eof207: cs = 207; goto _test_eof; 
+       _test_eof208: cs = 208; goto _test_eof; 
+       _test_eof209: cs = 209; goto _test_eof; 
+       _test_eof210: cs = 210; goto _test_eof; 
+       _test_eof211: cs = 211; goto _test_eof; 
+       _test_eof212: cs = 212; goto _test_eof; 
+       _test_eof213: cs = 213; goto _test_eof; 
+       _test_eof214: cs = 214; goto _test_eof; 
+       _test_eof215: cs = 215; goto _test_eof; 
+       _test_eof216: cs = 216; goto _test_eof; 
+       _test_eof217: cs = 217; goto _test_eof; 
+       _test_eof218: cs = 218; goto _test_eof; 
+       _test_eof219: cs = 219; goto _test_eof; 
+       _test_eof220: cs = 220; goto _test_eof; 
+       _test_eof221: cs = 221; goto _test_eof; 
+       _test_eof222: cs = 222; goto _test_eof; 
+       _test_eof223: cs = 223; goto _test_eof; 
+       _test_eof224: cs = 224; goto _test_eof; 
+       _test_eof225: cs = 225; goto _test_eof; 
+       _test_eof226: cs = 226; goto _test_eof; 
+       _test_eof227: cs = 227; goto _test_eof; 
+       _test_eof228: cs = 228; goto _test_eof; 
+       _test_eof229: cs = 229; goto _test_eof; 
+       _test_eof230: cs = 230; goto _test_eof; 
+       _test_eof231: cs = 231; goto _test_eof; 
+       _test_eof232: cs = 232; goto _test_eof; 
+       _test_eof233: cs = 233; goto _test_eof; 
+       _test_eof234: cs = 234; goto _test_eof; 
+       _test_eof235: cs = 235; goto _test_eof; 
+       _test_eof236: cs = 236; goto _test_eof; 
+       _test_eof237: cs = 237; goto _test_eof; 
+       _test_eof238: cs = 238; goto _test_eof; 
+       _test_eof239: cs = 239; goto _test_eof; 
+       _test_eof240: cs = 240; goto _test_eof; 
+       _test_eof241: cs = 241; goto _test_eof; 
+       _test_eof242: cs = 242; goto _test_eof; 
+       _test_eof243: cs = 243; goto _test_eof; 
+       _test_eof244: cs = 244; goto _test_eof; 
+       _test_eof245: cs = 245; goto _test_eof; 
+       _test_eof246: cs = 246; goto _test_eof; 
+       _test_eof247: cs = 247; goto _test_eof; 
+       _test_eof248: cs = 248; goto _test_eof; 
+       _test_eof249: cs = 249; goto _test_eof; 
+       _test_eof250: cs = 250; goto _test_eof; 
+       _test_eof251: cs = 251; goto _test_eof; 
+       _test_eof252: cs = 252; goto _test_eof; 
+       _test_eof253: cs = 253; goto _test_eof; 
+       _test_eof254: cs = 254; goto _test_eof; 
+       _test_eof255: cs = 255; goto _test_eof; 
+       _test_eof256: cs = 256; goto _test_eof; 
+       _test_eof257: cs = 257; goto _test_eof; 
+       _test_eof258: cs = 258; goto _test_eof; 
+       _test_eof259: cs = 259; goto _test_eof; 
+       _test_eof260: cs = 260; goto _test_eof; 
+       _test_eof261: cs = 261; goto _test_eof; 
+       _test_eof262: cs = 262; goto _test_eof; 
+       _test_eof263: cs = 263; goto _test_eof; 
+       _test_eof264: cs = 264; goto _test_eof; 
+       _test_eof265: cs = 265; goto _test_eof; 
+       _test_eof266: cs = 266; goto _test_eof; 
+
+       _test_eof: {}
+       _out: {}
+       }
+#line 391 "http_parser.rl"
+
+  parser->cs = cs;
+
+  CALLBACK(header_field);
+  CALLBACK(header_value);
+  CALLBACK(fragment);
+  CALLBACK(query_string);
+  CALLBACK(path);
+  CALLBACK(uri);
+
+out:
+  assert(p <= pe && "buffer overflow after parsing execute");
+  return(p - buffer);
+}
+
+int
+http_parser_has_error (http_parser *parser) 
+{
+  return parser->cs == http_parser_error;
+}
+
+int
+http_parser_should_keep_alive (http_parser *parser)
+{
+  if (parser->keep_alive == -1)
+    if (parser->version_major == 1)
+      return (parser->version_minor != 0);
+    else if (parser->version_major == 0)
+      return FALSE;
+    else
+      return TRUE;
+  else
+    return parser->keep_alive;
+}
diff --git a/deps/http_parser/http_parser.h b/deps/http_parser/http_parser.h
new file mode 100644 (file)
index 0000000..d41580e
--- /dev/null
@@ -0,0 +1,127 @@
+/* Copyright (c) 2008 Ryan Dahl (ry@tinyclouds.org)
+ * All rights reserved.
+ *
+ * This parser is based on code from Zed Shaw's Mongrel.
+ * Copyright (c) 2005 Zed A. Shaw
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ */
+#ifndef http_parser_h
+#define http_parser_h
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+#include <sys/types.h> 
+
+typedef struct http_parser http_parser;
+
+/* Callbacks should return non-zero to indicate an error. The parse will
+ * then halt execution. 
+ * 
+ * http_data_cb does not return data chunks. It will be call arbitrarally
+ * many times for each string. E.G. you might get 10 callbacks for "on_path"
+ * each providing just a few characters more data.
+ */
+typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
+typedef int (*http_cb) (http_parser*);
+
+/* Request Methods */
+#define HTTP_COPY       0x0001
+#define HTTP_DELETE     0x0002
+#define HTTP_GET        0x0004
+#define HTTP_HEAD       0x0008
+#define HTTP_LOCK       0x0010
+#define HTTP_MKCOL      0x0020
+#define HTTP_MOVE       0x0040
+#define HTTP_OPTIONS    0x0080
+#define HTTP_POST       0x0100
+#define HTTP_PROPFIND   0x0200
+#define HTTP_PROPPATCH  0x0400
+#define HTTP_PUT        0x0800
+#define HTTP_TRACE      0x1000
+#define HTTP_UNLOCK     0x2000
+
+/* Transfer Encodings */
+#define HTTP_IDENTITY   0x01
+#define HTTP_CHUNKED    0x02
+
+enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE };
+
+struct http_parser {
+  /** PRIVATE **/
+  int cs;
+  enum http_parser_type type;
+
+  size_t chunk_size;
+  unsigned eating:1;
+  size_t body_read;
+
+  const char *header_field_mark; 
+  const char *header_value_mark; 
+  const char *query_string_mark; 
+  const char *path_mark; 
+  const char *uri_mark; 
+  const char *fragment_mark; 
+
+  /** READ-ONLY **/
+  unsigned short status_code; /* responses only */
+  unsigned short method;      /* requests only */
+  short transfer_encoding;
+  unsigned short version_major;
+  unsigned short version_minor;
+  short keep_alive;
+  size_t content_length;
+
+  /** PUBLIC **/
+  void *data; /* A pointer to get hook to the "connection" or "socket" object */
+
+  /* an ordered list of callbacks */
+
+  http_cb      on_message_begin;
+
+  /* requests only */
+  http_data_cb on_path;
+  http_data_cb on_query_string;
+  http_data_cb on_uri;
+  http_data_cb on_fragment;
+
+  http_data_cb on_header_field;
+  http_data_cb on_header_value;
+  http_cb      on_headers_complete;
+  http_data_cb on_body;
+  http_cb      on_message_complete;
+};
+
+/* Initializes an http_parser structure.  The second argument specifies if
+ * it will be parsing requests or responses. 
+ */
+void http_parser_init (http_parser *parser, enum http_parser_type);
+
+size_t http_parser_execute (http_parser *parser, const char *data, size_t len);
+
+int http_parser_has_error (http_parser *parser);
+
+int http_parser_should_keep_alive (http_parser *parser);
+
+#ifdef __cplusplus
+}
+#endif 
+#endif
diff --git a/deps/http_parser/http_parser.rl b/deps/http_parser/http_parser.rl
new file mode 100644 (file)
index 0000000..3b4700f
--- /dev/null
@@ -0,0 +1,424 @@
+/* Copyright (c) 2008, 2009 Ryan Dahl (ry@tinyclouds.org)
+ *
+ * Based on Zed Shaw's Mongrel.
+ * Copyright (c) 2005 Zed A. Shaw
+ *
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ */
+#include "http_parser.h"
+
+#include <assert.h>
+
+static int unhex[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
+                     ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     };
+#define TRUE 1
+#define FALSE 0
+#define MIN(a,b) (a < b ? a : b)
+#define NULL (void*)(0)
+
+#define REMAINING (pe - p)
+#define CALLBACK(FOR)                                                       \
+  if (parser->FOR##_mark && parser->on_##FOR) {                             \
+    callback_return_value =                                                 \
+      parser->on_##FOR(parser, parser->FOR##_mark, p - parser->FOR##_mark); \
+  }
+
+#define RESET_PARSER(parser) \
+    parser->chunk_size = 0; \
+    parser->eating = 0; \
+    parser->header_field_mark = NULL; \
+    parser->header_value_mark = NULL; \
+    parser->query_string_mark = NULL; \
+    parser->path_mark = NULL; \
+    parser->uri_mark = NULL; \
+    parser->fragment_mark = NULL; \
+    parser->status_code = 0; \
+    parser->method = 0; \
+    parser->transfer_encoding = HTTP_IDENTITY; \
+    parser->version_major = 0; \
+    parser->version_minor = 0; \
+    parser->keep_alive = -1; \
+    parser->content_length = 0; \
+    parser->body_read = 0; 
+
+#define END_REQUEST                                \
+do {                                               \
+    if (parser->on_message_complete) {             \
+      callback_return_value =                      \
+        parser->on_message_complete(parser);       \
+    }                                              \
+    RESET_PARSER(parser);                          \
+} while (0)
+
+#define SKIP_BODY(nskip)                                             \
+do {                                                                 \
+  tmp = (nskip);                                                     \
+  if (parser->on_body && tmp > 0) {                                  \
+    callback_return_value = parser->on_body(parser, p, tmp);         \
+  }                                                                  \
+  if (callback_return_value == 0) {                                  \
+    p += tmp;                                                        \
+    parser->body_read += tmp;                                        \
+    parser->chunk_size -= tmp;                                       \
+    if (0 == parser->chunk_size) {                                   \
+      parser->eating = FALSE;                                        \
+      if (parser->transfer_encoding == HTTP_IDENTITY) {              \
+        END_REQUEST;                                                 \
+      }                                                              \
+    } else {                                                         \
+      parser->eating = TRUE;                                         \
+    }                                                                \
+  }                                                                  \
+} while (0)
+
+%%{
+  machine http_parser;
+
+  action mark_header_field   { parser->header_field_mark   = p; }
+  action mark_header_value   { parser->header_value_mark   = p; }
+  action mark_fragment       { parser->fragment_mark       = p; }
+  action mark_query_string   { parser->query_string_mark   = p; }
+  action mark_request_path   { parser->path_mark           = p; }
+  action mark_request_uri    { parser->uri_mark            = p; }
+
+  action header_field {
+    CALLBACK(header_field);
+    if (callback_return_value != 0) fbreak;
+    parser->header_field_mark = NULL;
+  }
+
+  action header_value {
+    CALLBACK(header_value);
+    if (callback_return_value != 0) fbreak;
+    parser->header_value_mark = NULL;
+  }
+
+  action request_uri { 
+    CALLBACK(uri);
+    if (callback_return_value != 0) fbreak;
+    parser->uri_mark = NULL;
+  }
+
+  action fragment { 
+    CALLBACK(fragment);
+    if (callback_return_value != 0) fbreak;
+    parser->fragment_mark = NULL;
+  }
+
+  action query_string { 
+    CALLBACK(query_string);
+    if (callback_return_value != 0) fbreak;
+    parser->query_string_mark = NULL;
+  }
+
+  action request_path {
+    CALLBACK(path);
+    if (callback_return_value != 0) fbreak;
+    parser->path_mark = NULL;
+  }
+
+  action headers_complete {
+    if(parser->on_headers_complete) {
+      callback_return_value = parser->on_headers_complete(parser);
+      if (callback_return_value != 0) fbreak;
+    }
+  }
+
+  action begin_message {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) fbreak;
+    }
+  }
+
+  action content_length {
+    parser->content_length *= 10;
+    parser->content_length += *p - '0';
+  }
+
+  action status_code {
+    parser->status_code *= 10;
+    parser->status_code += *p - '0';
+  }
+
+  action use_identity_encoding { parser->transfer_encoding = HTTP_IDENTITY; }
+  action use_chunked_encoding  { parser->transfer_encoding = HTTP_CHUNKED;  }
+
+  action set_keep_alive { parser->keep_alive = TRUE; }
+  action set_not_keep_alive { parser->keep_alive = FALSE; }
+
+  action version_major {
+    parser->version_major *= 10;
+    parser->version_major += *p - '0';
+  }
+
+  action version_minor {
+    parser->version_minor *= 10;
+    parser->version_minor += *p - '0';
+  }
+
+  action add_to_chunk_size {
+    parser->chunk_size *= 16;
+    parser->chunk_size += unhex[(int)*p];
+  }
+
+  action skip_chunk_data {
+    SKIP_BODY(MIN(parser->chunk_size, REMAINING));
+    if (callback_return_value != 0) fbreak;
+
+    fhold; 
+    if (parser->chunk_size > REMAINING) {
+      fbreak;
+    } else {
+      fgoto chunk_end; 
+    }
+  }
+
+  action end_chunked_body {
+    END_REQUEST;
+    if (parser->type == HTTP_REQUEST) {
+      fnext Requests;
+    } else {
+      fnext Responses;
+    }
+  }
+
+  action body_logic {
+    if (parser->transfer_encoding == HTTP_CHUNKED) {
+      fnext ChunkedBody;
+    } else {
+      /* this is pretty stupid. i'd prefer to combine this with skip_chunk_data */
+      parser->chunk_size = parser->content_length;
+      p += 1;  
+
+      SKIP_BODY(MIN(REMAINING, parser->content_length));
+      if (callback_return_value != 0) fbreak;
+
+      fhold;
+      if(parser->chunk_size > REMAINING) {
+        fbreak;
+      }
+    }
+  }
+
+
+  CRLF = "\r\n";
+
+# character types
+  CTL = (cntrl | 127);
+  safe = ("$" | "-" | "_" | ".");
+  extra = ("!" | "*" | "'" | "(" | ")" | ",");
+  reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
+  unsafe = (CTL | " " | "\"" | "#" | "%" | "<" | ">");
+  national = any -- (alpha | digit | reserved | extra | safe | unsafe);
+  unreserved = (alpha | digit | safe | extra | national);
+  escape = ("%" xdigit xdigit);
+  uchar = (unreserved | escape);
+  pchar = (uchar | ":" | "@" | "&" | "=" | "+");
+  tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" 
+              | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
+
+# elements
+  token = (ascii -- (CTL | tspecials));
+  quote = "\"";
+#  qdtext = token -- "\""; 
+#  quoted_pair = "\" ascii;
+#  quoted_string = "\"" (qdtext | quoted_pair )* "\"";
+
+#  headers
+
+  Method = ( "COPY"      %{ parser->method = HTTP_COPY;      }
+           | "DELETE"    %{ parser->method = HTTP_DELETE;    }
+           | "GET"       %{ parser->method = HTTP_GET;       }
+           | "HEAD"      %{ parser->method = HTTP_HEAD;      }
+           | "LOCK"      %{ parser->method = HTTP_LOCK;      }
+           | "MKCOL"     %{ parser->method = HTTP_MKCOL;     }
+           | "MOVE"      %{ parser->method = HTTP_MOVE;      }
+           | "OPTIONS"   %{ parser->method = HTTP_OPTIONS;   }
+           | "POST"      %{ parser->method = HTTP_POST;      }
+           | "PROPFIND"  %{ parser->method = HTTP_PROPFIND;  }
+           | "PROPPATCH" %{ parser->method = HTTP_PROPPATCH; }
+           | "PUT"       %{ parser->method = HTTP_PUT;       }
+           | "TRACE"     %{ parser->method = HTTP_TRACE;     }
+           | "UNLOCK"    %{ parser->method = HTTP_UNLOCK;    }
+           ); # Not allowing extension methods
+
+  HTTP_Version = "HTTP/" digit+ $version_major "." digit+ $version_minor;
+
+  scheme = ( alpha | digit | "+" | "-" | "." )* ;
+  absolute_uri = (scheme ":" (uchar | reserved )*);
+  path = ( pchar+ ( "/" pchar* )* ) ;
+  query = ( uchar | reserved )* >mark_query_string %query_string ;
+  param = ( pchar | "/" )* ;
+  params = ( param ( ";" param )* ) ;
+  rel_path = ( path? (";" params)? ) ;
+  absolute_path = ( "/"+ rel_path ) >mark_request_path %request_path ("?" query)?;
+  Request_URI = ( "*" | absolute_uri | absolute_path ) >mark_request_uri %request_uri;
+  Fragment = ( uchar | reserved )* >mark_fragment %fragment;
+
+  field_name = ( token -- ":" )+;
+  Field_Name = field_name >mark_header_field %header_field;
+
+  field_value = ((any - " ") any*)?;
+  Field_Value = field_value >mark_header_value %header_value;
+
+  hsep = ":" " "*;
+  header = (field_name hsep field_value) :> CRLF;
+  Header = ( ("Content-Length"i hsep digit+ $content_length)
+           | ("Connection"i hsep 
+               ( "Keep-Alive"i %set_keep_alive
+               | "close"i %set_not_keep_alive
+               )
+             )
+           | ("Transfer-Encoding"i %use_chunked_encoding hsep "identity" %use_identity_encoding)
+           | (Field_Name hsep Field_Value)
+           ) :> CRLF;
+
+  Headers = (Header)* :> CRLF @headers_complete;
+
+  Request_Line = ( Method " " Request_URI ("#" Fragment)? " " HTTP_Version CRLF ) ;
+
+  StatusCode = (digit digit digit) $status_code;
+  ReasonPhrase =  ascii+ -- ("\r" | "\n");
+  StatusLine = HTTP_Version  " " StatusCode " " ReasonPhrase CRLF;
+
+# chunked message
+  trailing_headers = header*;
+  #chunk_ext_val   = token | quoted_string;
+  chunk_ext_val = token*;
+  chunk_ext_name = token*;
+  chunk_extension = ( ";" " "* chunk_ext_name ("=" chunk_ext_val)? )*;
+  last_chunk = "0"+ chunk_extension CRLF;
+  chunk_size = (xdigit* [1-9a-fA-F] xdigit*) $add_to_chunk_size;
+  chunk_end  = CRLF;
+  chunk_body = any >skip_chunk_data;
+  chunk_begin = chunk_size chunk_extension CRLF;
+  chunk = chunk_begin chunk_body chunk_end;
+  ChunkedBody := chunk* last_chunk trailing_headers CRLF @end_chunked_body;
+
+  Request = (Request_Line Headers) >begin_message @body_logic;
+  Response = (StatusLine Headers) >begin_message @body_logic;
+
+  Requests := Request*;
+  Responses := Response*;
+
+  main := any >{
+    fhold;
+    if (parser->type == HTTP_REQUEST) {
+      fgoto Requests;
+    } else {
+      fgoto Responses;
+    }
+  };
+
+}%%
+
+%% write data;
+
+void
+http_parser_init (http_parser *parser, enum http_parser_type type) 
+{
+  int cs = 0;
+  %% write init;
+  parser->cs = cs;
+  parser->type = type;
+
+  parser->on_message_begin = NULL;
+  parser->on_path = NULL;
+  parser->on_query_string = NULL;
+  parser->on_uri = NULL;
+  parser->on_header_field = NULL;
+  parser->on_header_value = NULL;
+  parser->on_headers_complete = NULL;
+  parser->on_body = NULL;
+  parser->on_message_complete = NULL;
+
+  RESET_PARSER(parser);
+}
+
+/** exec **/
+size_t
+http_parser_execute (http_parser *parser, const char *buffer, size_t len)
+{
+  size_t tmp; // REMOVE ME this is extremely hacky
+  int callback_return_value = 0;
+  const char *p, *pe;
+  int cs = parser->cs;
+
+  p = buffer;
+  pe = buffer+len;
+
+  if (0 < parser->chunk_size && parser->eating) {
+    /* eat body */
+    SKIP_BODY(MIN(len, parser->chunk_size));
+    if (callback_return_value != 0) goto out;
+  }
+
+  if (parser->header_field_mark)   parser->header_field_mark   = buffer;
+  if (parser->header_value_mark)   parser->header_value_mark   = buffer;
+  if (parser->fragment_mark)       parser->fragment_mark       = buffer;
+  if (parser->query_string_mark)   parser->query_string_mark   = buffer;
+  if (parser->path_mark)           parser->path_mark           = buffer;
+  if (parser->uri_mark)            parser->uri_mark            = buffer;
+
+  %% write exec;
+
+  parser->cs = cs;
+
+  CALLBACK(header_field);
+  CALLBACK(header_value);
+  CALLBACK(fragment);
+  CALLBACK(query_string);
+  CALLBACK(path);
+  CALLBACK(uri);
+
+out:
+  assert(p <= pe && "buffer overflow after parsing execute");
+  return(p - buffer);
+}
+
+int
+http_parser_has_error (http_parser *parser) 
+{
+  return parser->cs == http_parser_error;
+}
+
+int
+http_parser_should_keep_alive (http_parser *parser)
+{
+  if (parser->keep_alive == -1)
+    if (parser->version_major == 1)
+      return (parser->version_minor != 0);
+    else if (parser->version_major == 0)
+      return FALSE;
+    else
+      return TRUE;
+  else
+    return parser->keep_alive;
+}
diff --git a/deps/http_parser/test.c b/deps/http_parser/test.c
new file mode 100644 (file)
index 0000000..e1d1031
--- /dev/null
@@ -0,0 +1,748 @@
+#include "http_parser.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#undef TRUE
+#define TRUE 1
+#undef FALSE
+#define FALSE 0
+
+#define MAX_HEADERS 10
+#define MAX_ELEMENT_SIZE 500
+
+static http_parser parser;
+struct message {
+  const char *name; // for debugging purposes
+  const char *raw;
+  enum http_parser_type type;
+  int method;
+  int status_code;
+  char request_path[MAX_ELEMENT_SIZE];
+  char request_uri[MAX_ELEMENT_SIZE];
+  char fragment[MAX_ELEMENT_SIZE];
+  char query_string[MAX_ELEMENT_SIZE];
+  char body[MAX_ELEMENT_SIZE];
+  int num_headers;
+  enum { NONE=0, FIELD, VALUE } last_header_element;
+  char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE];
+  int should_keep_alive;
+};
+
+static struct message messages[5];
+static int num_messages;
+
+/* * R E Q U E S T S * */ 
+const struct message requests[] =
+#define CURL_GET 0
+{ {.name= "curl get"
+  ,.type= HTTP_REQUEST
+  ,.raw= "GET /test HTTP/1.1\r\n"
+         "User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n"
+         "Host: 0.0.0.0=5000\r\n"
+         "Accept: */*\r\n"
+         "\r\n"
+  ,.should_keep_alive= TRUE
+  ,.method= HTTP_GET
+  ,.query_string= ""
+  ,.fragment= ""
+  ,.request_path= "/test"
+  ,.request_uri= "/test"
+  ,.num_headers= 3
+  ,.headers= 
+    { { "User-Agent", "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1" }
+    , { "Host", "0.0.0.0=5000" }
+    , { "Accept", "*/*" }
+    }
+  ,.body= ""
+  }
+
+#define FIREFOX_GET 1
+, {.name= "firefox get"
+  ,.type= HTTP_REQUEST
+  ,.raw= "GET /favicon.ico HTTP/1.1\r\n"
+         "Host: 0.0.0.0=5000\r\n"
+         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n"
+         "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
+         "Accept-Language: en-us,en;q=0.5\r\n"
+         "Accept-Encoding: gzip,deflate\r\n"
+         "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
+         "Keep-Alive: 300\r\n"
+         "Connection: keep-alive\r\n"
+         "\r\n"
+  ,.should_keep_alive= TRUE
+  ,.method= HTTP_GET
+  ,.query_string= ""
+  ,.fragment= ""
+  ,.request_path= "/favicon.ico"
+  ,.request_uri= "/favicon.ico"
+  ,.num_headers= 8
+  ,.headers= 
+    { { "Host", "0.0.0.0=5000" }
+    , { "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0" }
+    , { "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" }
+    , { "Accept-Language", "en-us,en;q=0.5" }
+    , { "Accept-Encoding", "gzip,deflate" }
+    , { "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7" }
+    , { "Keep-Alive", "300" }
+    , { "Connection", "keep-alive" }
+    }
+  ,.body= ""
+  }
+
+#define DUMBFUCK 2
+, {.name= "dumbfuck"
+  ,.type= HTTP_REQUEST
+  ,.raw= "GET /dumbfuck HTTP/1.1\r\n"
+         "aaaaaaaaaaaaa:++++++++++\r\n"
+         "\r\n"
+  ,.should_keep_alive= TRUE
+  ,.method= HTTP_GET
+  ,.query_string= ""
+  ,.fragment= ""
+  ,.request_path= "/dumbfuck"
+  ,.request_uri= "/dumbfuck"
+  ,.num_headers= 1
+  ,.headers= 
+    { { "aaaaaaaaaaaaa",  "++++++++++" }
+    }
+  ,.body= ""
+  }
+
+#define FRAGMENT_IN_URI 3
+, {.name= "fragment in uri"
+  ,.type= HTTP_REQUEST
+  ,.raw= "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n"
+         "\r\n"
+  ,.should_keep_alive= TRUE
+  ,.method= HTTP_GET
+  ,.query_string= "page=1"
+  ,.fragment= "posts-17408"
+  ,.request_path= "/forums/1/topics/2375"
+  /* XXX request uri does not include fragment? */
+  ,.request_uri= "/forums/1/topics/2375?page=1" 
+  ,.num_headers= 0
+  ,.body= ""
+  }
+
+#define GET_NO_HEADERS_NO_BODY 4
+, {.name= "get no headers no body"
+  ,.type= HTTP_REQUEST
+  ,.raw= "GET /get_no_headers_no_body/world HTTP/1.1\r\n"
+         "\r\n"
+  ,.should_keep_alive= TRUE
+  ,.method= HTTP_GET
+  ,.query_string= ""
+  ,.fragment= ""
+  ,.request_path= "/get_no_headers_no_body/world"
+  ,.request_uri= "/get_no_headers_no_body/world"
+  ,.num_headers= 0
+  ,.body= ""
+  }
+
+#define GET_ONE_HEADER_NO_BODY 5
+, {.name= "get one header no body"
+  ,.type= HTTP_REQUEST
+  ,.raw= "GET /get_one_header_no_body HTTP/1.1\r\n"
+         "Accept: */*\r\n"
+         "\r\n"
+  ,.should_keep_alive= TRUE
+  ,.method= HTTP_GET
+  ,.query_string= ""
+  ,.fragment= ""
+  ,.request_path= "/get_one_header_no_body"
+  ,.request_uri= "/get_one_header_no_body"
+  ,.num_headers= 1
+  ,.headers= 
+    { { "Accept" , "*/*" }
+    }
+  ,.body= ""
+  }
+
+#define GET_FUNKY_CONTENT_LENGTH 6
+, {.name= "get funky content length body hello"
+  ,.type= HTTP_REQUEST
+  ,.raw= "GET /get_funky_content_length_body_hello HTTP/1.0\r\n"
+         "conTENT-Length: 5\r\n"
+         "\r\n"
+         "HELLO"
+  ,.should_keep_alive= FALSE
+  ,.method= HTTP_GET
+  ,.query_string= ""
+  ,.fragment= ""
+  ,.request_path= "/get_funky_content_length_body_hello"
+  ,.request_uri= "/get_funky_content_length_body_hello"
+  ,.num_headers= 1
+  ,.headers= 
+    { { "conTENT-Length" , "5" }
+    }
+  ,.body= "HELLO"
+  }
+
+#define POST_IDENTITY_BODY_WORLD 7
+, {.name= "post identity body world"
+  ,.type= HTTP_REQUEST
+  ,.raw= "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n"
+         "Accept: */*\r\n"
+         "Transfer-Encoding: identity\r\n"
+         "Content-Length: 5\r\n"
+         "\r\n"
+         "World"
+  ,.should_keep_alive= TRUE
+  ,.method= HTTP_POST
+  ,.query_string= "q=search"
+  ,.fragment= "hey"
+  ,.request_path= "/post_identity_body_world"
+  ,.request_uri= "/post_identity_body_world?q=search"
+  ,.num_headers= 3
+  ,.headers= 
+    { { "Accept", "*/*" }
+    , { "Transfer-Encoding", "identity" }
+    , { "Content-Length", "5" } 
+    }
+  ,.body= "World"
+  }
+
+#define POST_CHUNKED_ALL_YOUR_BASE 8
+, {.name= "post - chunked body: all your base are belong to us"
+  ,.type= HTTP_REQUEST
+  ,.raw= "POST /post_chunked_all_your_base HTTP/1.1\r\n"
+         "Transfer-Encoding: chunked\r\n"
+         "\r\n"
+         "1e\r\nall your base are belong to us\r\n"
+         "0\r\n"
+         "\r\n"
+  ,.should_keep_alive= TRUE
+  ,.method= HTTP_POST
+  ,.query_string= ""
+  ,.fragment= ""
+  ,.request_path= "/post_chunked_all_your_base"
+  ,.request_uri= "/post_chunked_all_your_base"
+  ,.num_headers= 1
+  ,.headers= 
+    { { "Transfer-Encoding" , "chunked" }
+    }
+  ,.body= "all your base are belong to us"
+  }
+
+#define TWO_CHUNKS_MULT_ZERO_END 9
+, {.name= "two chunks ; triple zero ending"
+  ,.type= HTTP_REQUEST
+  ,.raw= "POST /two_chunks_mult_zero_end HTTP/1.1\r\n"
+         "Transfer-Encoding: chunked\r\n"
+         "\r\n"
+         "5\r\nhello\r\n"
+         "6\r\n world\r\n"
+         "000\r\n"
+         "\r\n"
+  ,.should_keep_alive= TRUE
+  ,.method= HTTP_POST
+  ,.query_string= ""
+  ,.fragment= ""
+  ,.request_path= "/two_chunks_mult_zero_end"
+  ,.request_uri= "/two_chunks_mult_zero_end"
+  ,.num_headers= 1
+  ,.headers= 
+    { { "Transfer-Encoding", "chunked" }
+    }
+  ,.body= "hello world"
+  }
+
+#define CHUNKED_W_TRAILING_HEADERS 10 
+, {.name= "chunked with trailing headers. blech."
+  ,.type= HTTP_REQUEST
+  ,.raw= "POST /chunked_w_trailing_headers HTTP/1.1\r\n"
+         "Transfer-Encoding: chunked\r\n"
+         "\r\n"
+         "5\r\nhello\r\n"
+         "6\r\n world\r\n"
+         "0\r\n"
+         "Vary: *\r\n"
+         "Content-Type: text/plain\r\n"
+         "\r\n"
+  ,.should_keep_alive= TRUE
+  ,.method= HTTP_POST
+  ,.query_string= ""
+  ,.fragment= ""
+  ,.request_path= "/chunked_w_trailing_headers"
+  ,.request_uri= "/chunked_w_trailing_headers"
+  ,.num_headers= 1
+  ,.headers= 
+    { { "Transfer-Encoding",  "chunked" }
+    }
+  ,.body= "hello world"
+  }
+
+#define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11 
+, {.name= "with bullshit after the length"
+  ,.type= HTTP_REQUEST
+  ,.raw= "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n"
+         "Transfer-Encoding: chunked\r\n"
+         "\r\n"
+         "5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n"
+         "6; blahblah; blah\r\n world\r\n"
+         "0\r\n"
+         "\r\n"
+  ,.should_keep_alive= TRUE
+  ,.method= HTTP_POST
+  ,.query_string= ""
+  ,.fragment= ""
+  ,.request_path= "/chunked_w_bullshit_after_length"
+  ,.request_uri= "/chunked_w_bullshit_after_length"
+  ,.num_headers= 1
+  ,.headers= 
+    { { "Transfer-Encoding", "chunked" }
+    }
+  ,.body= "hello world"
+  }
+
+, {.name= NULL } /* sentinel */
+};
+
+/* * R E S P O N S E S * */ 
+const struct message responses[] = 
+{ {.name= "google 301"
+  ,.type= HTTP_RESPONSE
+  ,.raw= "HTTP/1.1 301 Moved Permanently\r\n"
+         "Location: http://www.google.com/\r\n"
+         "Content-Type: text/html; charset=UTF-8\r\n"
+         "Date: Sun, 26 Apr 2009 11:11:49 GMT\r\n"
+         "Expires: Tue, 26 May 2009 11:11:49 GMT\r\n"
+         "Cache-Control: public, max-age=2592000\r\n"
+         "Server: gws\r\n"
+         "Content-Length: 219\r\n"
+         "\r\n"
+         "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n"
+         "<TITLE>301 Moved</TITLE></HEAD><BODY>\n"
+         "<H1>301 Moved</H1>\n"
+         "The document has moved\n"
+         "<A HREF=\"http://www.google.com/\">here</A>.\r\n"
+         "</BODY></HTML>\r\n"
+  ,.should_keep_alive= TRUE
+  ,.status_code= 301
+  ,.num_headers= 7
+  ,.headers= 
+    { { "Location", "http://www.google.com/" }
+    , { "Content-Type", "text/html; charset=UTF-8" }
+    , { "Date", "Sun, 26 Apr 2009 11:11:49 GMT" }
+    , { "Expires", "Tue, 26 May 2009 11:11:49 GMT" }
+    , { "Cache-Control", "public, max-age=2592000" }
+    , { "Server", "gws" }
+    , { "Content-Length", "219" }
+    }
+  ,.body= "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n"
+          "<TITLE>301 Moved</TITLE></HEAD><BODY>\n"
+          "<H1>301 Moved</H1>\n"
+          "The document has moved\n"
+          "<A HREF=\"http://www.google.com/\">here</A>.\r\n"
+          "</BODY></HTML>\r\n"
+  }
+
+, {.name= "404 no headers no body"
+  ,.type= HTTP_RESPONSE
+  ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n"
+  ,.should_keep_alive= TRUE
+  ,.status_code= 404
+  ,.num_headers= 0
+  ,.headers= {}
+  ,.body= ""
+  }
+
+, {.name= NULL } /* sentinel */
+};
+
+int
+request_path_cb (http_parser *_, const char *p, size_t len)
+{
+  strncat(messages[num_messages].request_path, p, len);
+  return 0;
+}
+
+int
+request_uri_cb (http_parser *_, const char *p, size_t len)
+{
+  strncat(messages[num_messages].request_uri, p, len);
+  return 0;
+}
+
+int
+query_string_cb (http_parser *_, const char *p, size_t len)
+{
+  strncat(messages[num_messages].query_string, p, len);
+  return 0;
+}
+
+int
+fragment_cb (http_parser *_, const char *p, size_t len)
+{
+  strncat(messages[num_messages].fragment, p, len);
+  return 0;
+}
+
+int
+header_field_cb (http_parser *_, const char *p, size_t len)
+{
+  struct message *m = &messages[num_messages];
+
+  if (m->last_header_element != FIELD)
+    m->num_headers++;
+
+  strncat(m->headers[m->num_headers-1][0], p, len);
+
+  m->last_header_element = FIELD;
+
+  return 0;
+}
+
+int
+header_value_cb (http_parser *_, const char *p, size_t len)
+{
+  struct message *m = &messages[num_messages];
+
+  strncat(m->headers[m->num_headers-1][1], p, len);
+
+  m->last_header_element = VALUE;
+
+  return 0;
+}
+
+int
+body_cb (http_parser *_, const char *p, size_t len)
+{
+  strncat(messages[num_messages].body, p, len);
+ // printf("body_cb: '%s'\n", requests[num_messages].body);
+  return 0;
+}
+
+int
+message_complete_cb (http_parser *parser)
+{
+  messages[num_messages].method = parser->method;
+  messages[num_messages].status_code = parser->status_code;
+
+  num_messages++;
+  return 0;
+}
+
+int
+message_begin_cb (http_parser *_)
+{
+  return 0;
+}
+
+void
+parser_init (enum http_parser_type type)
+{
+  num_messages = 0;
+
+  http_parser_init(&parser, type);
+
+  memset(&messages, 0, sizeof messages);
+
+  parser.on_message_begin     = message_begin_cb;
+  parser.on_header_field      = header_field_cb;
+  parser.on_header_value      = header_value_cb;
+  parser.on_path              = request_path_cb;
+  parser.on_uri               = request_uri_cb;
+  parser.on_fragment          = fragment_cb;
+  parser.on_query_string      = query_string_cb;
+  parser.on_body              = body_cb;
+  parser.on_headers_complete  = NULL;
+  parser.on_message_complete  = message_complete_cb;
+}
+
+void
+message_eq (int index, const struct message *expected)
+{
+  int i;
+  struct message *m = &messages[index];
+
+  assert(m->method == expected->method);
+  assert(m->status_code == expected->status_code);
+
+  assert(0 == strcmp(m->body, expected->body));
+  assert(0 == strcmp(m->fragment, expected->fragment));
+  assert(0 == strcmp(m->query_string, expected->query_string));
+  assert(0 == strcmp(m->request_path, expected->request_path));
+  assert(0 == strcmp(m->request_uri, expected->request_uri));
+  assert(m->num_headers == expected->num_headers);
+  for (i = 0; i < m->num_headers; i++) {
+    assert(0 == strcmp(m->headers[i][0], expected->headers[i][0]));
+    assert(0 == strcmp(m->headers[i][1], expected->headers[i][1]));
+  }
+}
+
+void
+parse_messages (int message_count, const struct message *input_messages[])
+{
+  // Concat the input messages
+  size_t length = 0;
+  int i;
+  for (i = 0; i < message_count; i++) {
+    length += strlen(input_messages[i]->raw);
+  }
+  char total[length + 1];
+  total[0] = '\0';
+
+  for (i = 0; i < message_count; i++) {
+    strcat(total, input_messages[i]->raw);
+  }
+
+  // Parse the stream
+  size_t traversed = 0;
+  parser_init(HTTP_REQUEST);
+
+  traversed = http_parser_execute(&parser, total, length);
+
+  assert(!http_parser_has_error(&parser));
+  assert(num_messages == message_count);
+
+  for (i = 0; i < message_count; i++) {
+    message_eq(i, input_messages[i]);
+  }
+}
+
+
+void
+test_message (const struct message *message)
+{
+  size_t traversed = 0;
+  parser_init(message->type);
+
+  traversed = http_parser_execute(&parser, message->raw, strlen(message->raw));
+  assert(!http_parser_has_error(&parser));
+  assert(num_messages == 1);
+
+  message_eq(0, message);
+}
+
+void
+test_error (const char *buf)
+{
+  size_t traversed = 0;
+  parser_init(HTTP_REQUEST);
+
+  traversed = http_parser_execute(&parser, buf, strlen(buf));
+
+  assert(http_parser_has_error(&parser));
+}
+
+void
+test_multiple3 (const struct message *r1, const struct message *r2, const struct message *r3)
+{
+  char total[ strlen(r1->raw) 
+            + strlen(r2->raw) 
+            + strlen(r3->raw) 
+            + 1
+            ];
+  total[0] = '\0';
+
+  strcat(total, r1->raw); 
+  strcat(total, r2->raw); 
+  strcat(total, r3->raw); 
+
+  size_t traversed = 0;
+  parser_init(HTTP_REQUEST);
+
+  traversed = http_parser_execute(&parser, total, strlen(total));
+
+  assert(! http_parser_has_error(&parser) );
+  assert(num_messages == 3);
+  message_eq(0, r1);
+  message_eq(1, r2);
+  message_eq(2, r3);
+}
+
+/* SCAN through every possible breaking to make sure the 
+ * parser can handle getting the content in any chunks that
+ * might come from the socket
+ */
+void
+test_scan (const struct message *r1, const struct message *r2, const struct message *r3)
+{
+  char total[80*1024] = "\0";
+  char buf1[80*1024] = "\0";
+  char buf2[80*1024] = "\0";
+  char buf3[80*1024] = "\0";
+
+  strcat(total, r1->raw); 
+  strcat(total, r2->raw); 
+  strcat(total, r3->raw); 
+
+  int total_len = strlen(total);
+
+  int total_ops = (total_len - 1) * (total_len - 2) / 2; 
+  int ops = 0 ;
+
+  int i,j;
+  for (j = 2; j < total_len; j ++ ) {
+    for (i = 1; i < j; i ++ ) {
+
+      if (ops % 1000 == 0)  {
+        printf("\b\b\b\b%3.0f%%", 100 * (float)ops /(float)total_ops);
+        fflush(stdout);
+      }
+      ops += 1;
+
+      parser_init(HTTP_REQUEST);
+
+      int buf1_len = i;
+      strncpy(buf1, total, buf1_len);
+      buf1[buf1_len] = 0;
+
+      int buf2_len = j - i;
+      strncpy(buf2, total+i, buf2_len);
+      buf2[buf2_len] = 0;
+
+      int buf3_len = total_len - j;
+      strncpy(buf3, total+j, buf3_len);
+      buf3[buf3_len] = 0;
+
+      /*
+      printf("buf1: %s - %d\n", buf1, buf1_len);
+      printf("buf2: %s - %d \n", buf2, buf2_len );
+      printf("buf3: %s - %d\n\n", buf3, buf3_len);
+      */
+
+      http_parser_execute(&parser, buf1, buf1_len);
+
+      assert(!http_parser_has_error(&parser));
+
+      http_parser_execute(&parser, buf2, buf2_len);
+
+      assert(!http_parser_has_error(&parser));
+
+      http_parser_execute(&parser, buf3, buf3_len);
+
+      assert(! http_parser_has_error(&parser));
+
+      assert(3 == num_messages);
+
+      message_eq(0, r1);
+      message_eq(1, r2);
+      message_eq(2, r3);
+    }
+  }
+  printf("\b\b\b\b100%\n");
+}
+
+int
+main (void)
+{
+  int i, j, k;
+
+  printf("sizeof(http_parser) = %d\n", sizeof(http_parser));
+
+  int request_count; 
+  for (request_count = 0; requests[request_count].name; request_count++);
+
+  int response_count; 
+  for (response_count = 0; responses[response_count].name; response_count++);
+
+
+  //// RESPONSES  
+
+  for (i = 0; i < response_count; i++) {
+    test_message(&responses[i]);
+  }
+
+
+
+  puts("responses okay");
+
+
+
+  /// REQUESTS
+
+
+  test_error("hello world");
+  test_error("GET / HTP/1.1\r\n\r\n");
+
+  const char *dumbfuck2 =
+    "GET / HTTP/1.1\r\n"
+    "X-SSL-Bullshit:   -----BEGIN CERTIFICATE-----\r\n"
+    "\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n"
+    "\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n"
+    "\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n"
+    "\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n"
+    "\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n"
+    "\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n"
+    "\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n"
+    "\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n"
+    "\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n"
+    "\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n"
+    "\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n"
+    "\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n"
+    "\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgHTTPAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n"
+    "\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n"
+    "\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n"
+    "\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n"
+    "\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n"
+    "\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n"
+    "\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n"
+    "\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n"
+    "\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n"
+    "\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n"
+    "\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n"
+    "\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n"
+    "\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n"
+    "\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n"
+    "\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n"
+    "\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n"
+    "\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n"
+    "\tRA==\r\n"
+    "\t-----END CERTIFICATE-----\r\n"
+    "\r\n";
+  test_error(dumbfuck2);
+
+  // no content-length
+  // error if there is a body without content length
+  const char *bad_get_no_headers_no_body = "GET /bad_get_no_headers_no_body/world HTTP/1.1\r\n"
+                                           "Accept: */*\r\n"
+                                           "\r\n"
+                                           "HELLO";
+  test_error(bad_get_no_headers_no_body); 
+
+
+  /* TODO sending junk and large headers gets rejected */
+
+
+  /* check to make sure our predefined requests are okay */
+  for (i = 0; requests[i].name; i++) {
+    test_message(&requests[i]);
+  }
+
+  for (i = 0; i < request_count; i++) {
+    for (j = 0; j < request_count; j++) {
+      for (k = 0; k < request_count; k++) {
+        //printf("%d %d %d\n", i, j, k);
+        test_multiple3(&requests[i], &requests[j], &requests[k]);
+      }
+    }
+  }
+
+  printf("request scan 1/3      ");
+  test_scan( &requests[GET_NO_HEADERS_NO_BODY]
+           , &requests[GET_ONE_HEADER_NO_BODY]
+           , &requests[GET_NO_HEADERS_NO_BODY]
+           );
+
+  printf("request scan 2/3      ");
+  test_scan( &requests[GET_FUNKY_CONTENT_LENGTH]
+           , &requests[POST_IDENTITY_BODY_WORLD]
+           , &requests[POST_CHUNKED_ALL_YOUR_BASE]
+           );
+
+  printf("request scan 3/3      ");
+  test_scan( &requests[TWO_CHUNKS_MULT_ZERO_END]
+           , &requests[CHUNKED_W_TRAILING_HEADERS]
+           , &requests[CHUNKED_W_BULLSHIT_AFTER_LENGTH]
+           );
+
+  puts("requests okay");
+
+
+  return 0;
+}
diff --git a/deps/libebb/.gitignore b/deps/libebb/.gitignore
deleted file mode 100644 (file)
index f65038b..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-*.o
-examples/hello_world
-test_request_parser
-ebb_request_parser.c
-tags
diff --git a/deps/libebb/LICENSE b/deps/libebb/LICENSE
deleted file mode 100644 (file)
index 91b52e6..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-Copyright (c) 2008 Ryan Dahl (ry@ndahl.us)
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
-
diff --git a/deps/libebb/README b/deps/libebb/README
deleted file mode 100644 (file)
index d5b7ce3..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-see doc/index.html and examples/hello_world.c for explanation
-
-webpage: http://tinyclouds.org/libebb/
-git repository: http://github.com/ry/libebb/tree/master
-
-To build libebb please edit config.mk to reflect your system's parameters.
-
diff --git a/deps/libebb/config.mk b/deps/libebb/config.mk
deleted file mode 100644 (file)
index 5564bdd..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-PREFIX = $(HOME)/local/libebb
-
-# libev
-EVINC  = $(HOME)/local/libev/include
-EVLIB  = $(HOME)/local/libev/lib
-EVLIBS = -L${EVLIB} -lev
-
-# GnuTLS, comment if you don't want it (necessary for HTTPS)
-GNUTLSLIB   = /usr/lib
-GNUTLSINC   = /usr/include
-GNUTLSLIBS  = -L${GNUTLSLIB} -lgnutls
-GNUTLSFLAGS = -DHAVE_GNUTLS
-
-# includes and libs
-INCS = -I${EVINC} -I${GNUTLSINC}
-LIBS = ${EVLIBS} ${GNUTLSLIBS} -lefence
-
-# flags
-CPPFLAGS = -DVERSION=\"$(VERSION)\" ${GNUTLSFLAGS}
-CFLAGS   = -O2 -g -Wall ${INCS} ${CPPFLAGS} -fPIC
-LDFLAGS  = -s ${LIBS}
-LDOPT    = -shared
-SUFFIX   = so
-SONAME   = -Wl,-soname,$(OUTPUT_LIB)
-
-# Solaris
-#CFLAGS  = -fast ${INCS} -DVERSION=\"$(VERSION)\" -fPIC
-#LDFLAGS = ${LIBS}
-#SONAME  = 
-
-# Darwin
-# LDOPT  = -dynamiclib 
-# SUFFIX = dylib
-# SONAME = -current_version $(VERSION) -compatibility_version $(VERSION)
-
-# compiler and linker
-CC = cc
-RANLIB = ranlib
diff --git a/deps/libebb/doc/icon.png b/deps/libebb/doc/icon.png
deleted file mode 100644 (file)
index 702f4b5..0000000
Binary files a/deps/libebb/doc/icon.png and /dev/null differ
diff --git a/deps/libebb/doc/index.html b/deps/libebb/doc/index.html
deleted file mode 100644 (file)
index 612c9e9..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-
-<html>
-  <style>
-    body {
-      background: #fff;
-      color: #2e3436;
-      font-size: 12pt;
-      line-height: 16pt;
-  /*  font-family: Palatino;  */
-      margin: 3em 0 3em 3em; 
-    }
-
-    code, pre {
-    }
-
-    #contents {
-      max-width: 40em;
-    }
-
-    ul {
-      padding-left: 0;
-    }
-
-    li {
-      margin-top: 0.5em;
-      margin-bottom: 0.5em;
-    }
-
-    p {
-      text-align: left;
-    }
-
-
-    img {
-      float: left;
-      margin: 0 1em 1em 0;
-    }
-
-    p { clear: both; }
-  </style>
-  <body> <div id="contents">
-    <img src="icon.png"/>
-    <h1>libebb</h1>
-
-    <p>
-      libebb is a lightweight HTTP server library for C.  It lays the
-      foundation for writing a web server by providing the socket juggling
-      and request parsing. By implementing the HTTP/1.1 grammar provided in
-      RFC2612,  libebb understands most most valid HTTP/1.1 connections
-      (persistent, pipelined, and chunked requests included) and rejects
-      invalid or malicious requests.  libebb supports SSL over HTTP.  
-    </p>
-
-    <p>
-      The library embraces a minimalistic single-threaded evented design.
-      No control is removed from the user. For example, all allocations are
-      done through callbacks so that the user might implement in optimal
-      ways for their specific application.  By design libebb is not
-      thread-safe and all provided callbacks must not block.  libebb uses
-      the <a href="http://libev.schmorp.de/bench.html">high-performance</a>
-      libev event loop, but does not control it. The user of the library may
-      start and stop the loop at will, they may attach thier own watchers. 
-    </p>
-
-    <p>
-      libebb depends on POSIX sockets, libev, and optionally GnuTLS. 
-    </p>
-
-    <p>
-      libebb is in the early stages of development and probably contains
-      many bugs. The API is subject to radical changes.  If you're
-      interested <a href="http://github.com/ry/libebb/tree/master">checkout
-        the source code</a> and <a
-        href="http://groups.google.com/group/ebbebb">join the mailing
-        list</a>.  A release will be made when it proves stable.
-    </p>
-
-    <p>libebb is released under <a
-      href="http://www.gnu.org/licenses/license-list.html#X11License">the
-      X11 license</a>.</p>
-
-    <h2>Usage</h2>
-
-    <p>
-      libebb is a simple API, mostly it is providing callbacks.  There are
-      two types of callbacks that one will work with: 
-    </p>
-
-    <ul>
-      <li>callbacks to allocate and initialize data for libebb. These are
-      named <code>new_*</code> like <code>new_connection</code> and
-      <code>new_request</code></li>
-      <li>callbacks which happen on an event and might provide a pointer to
-      a chunk of data. These are named <code>on_*</code> like
-      <code>on_body</code> and <code>on_close</code>.</li>
-    </ul>
-
-    <p>
-      In libebb there are three important classes: <code>ebb_server</code>,
-      <code>ebb_connection</code>, and <code>ebb_request</code>. 
-      Each server has many peer connections. Each peer connection may have many
-      requests.
-      There are two additional classes <code>ebb_buf</code> and <code>ebb_request_parser</code>
-      which may or may not be useful.
-    </p>
-
-    <h3><code>ebb_server</code></h3>
-    <p>
-      <code>ebb_server</code> represents a single web server listening on a
-      single port. The user must allocate the structure themselves, then
-      call <code>ebb_server_init()</code> and provide a libev event loop.
-      <code>ebb_server_set_secure()</code> will make the server understand
-      HTTPS connections.
-    </p>
-
-    <p>
-      After initialized the <code>ebb_server_listen_on_port()</code> can be
-      called to open the server up to new connections. libebb does not
-      control the event loop, it is the user's responsibility to start the
-      event loop  (using <code>ev_loop()</code>) after
-      <code>ebb_server_listen_on_port()</code> is called.
-    </p>
-
-    <p>
-      To accept connections you must provide the new server with a callback
-      called <code>new_connection</code>. This callback must return an allocated
-      and initialized <code>ebb_connection</code> structure.     
-      To set this callback do
-    </p>
-
-    <pre>my_server-&gt;new_connection = my_new_connection_callback;</pre>
-
-    <p>
-      Additional documentation can be found in <code>ebb.h</code>
-    </p>
-
-    <h3><code>ebb_connection</code></h3>
-
-    <p>
-      This structure contains information and callbacks for a single client
-      connection. It is allocated and initialized through the
-      <code>new_connection</code> callback in <code>ebb_server</code>.
-      To initialize a newly allocated <code>ebb_connection</code> use
-      <code>ebb_connection_init()</code>.
-    </p>
-
-    <p>
-      After <code>ebb_connection_init()</code> is called a number of
-      callbacks can be set: <code>new_request</code>, <code>new_buf</code>,
-      <code>on_timeout</code>, and <code>on_close</code>.
-    </p>
-
-    <p>
-      When an <code>ebb_connection</code> is returned to an
-      <code>ebb_server</code>, data is immediately data is read from the
-      socket.  This data must be stored somewhere. Because libebb is
-      agnostic about allocation decisions, it passes this off to the user in
-      the form of a callback: <code>connection-&gt;new_buf</code>.  This
-      callback returns a newly allocated and initialized
-      <code>ebb_buf</code> structure.  How much libebb attempts to read from
-      the socket is determined by how large the returned
-      <code>ebb_buf</code> structure is.  Using <code>new_buf</code> is
-      optional.  By default libebb reads data into a static buffer
-      (allocated at compile time), writing over it on each read. In many
-      web server using the static buffer will be sufficent because callbacks
-      made during the parsing will buffer the data elsewhere. Providing a
-      <code>new_buf</code> callback is necessary only if you want to save
-      the raw data coming from the socket.
-    </p>
-
-    <p>
-      The <code>new_request</code> callback is called at the beginning of a
-      request. It must return a newly allocated and initialized
-      <code>ebb_request</code> structure. Because HTTP/1.1 supports <a
-        href="http://en.wikipedia.org/wiki/HTTP_persistent_connection">peristant</a>
-      connections, there may be many requests per connection.
-    </p>
-
-    <p>
-      You may access the file descriptor for the client socket inside the
-      <code>ebb_connection</code> structure. Writing the response, in valid
-      HTTP, is the user's responsibility.  Remember, requests must be
-      returned to client in the same order that they were received.
-    </p>
-
-    <p>
-      A convience function, <coe>ebb_connection_write</code>, is provided
-      which will write a single string to the peer. You may use
-      this function or you may write to the file descriptor directly.
-    </p>
-
-    <p>
-      To close a peer connection use
-      <code>ebb_connnection_schedule_close()</code>. Because SSL may require
-      some additional communication to close the connection properly, the
-      file descriptor cannot be closed immediately. The
-      <code>on_close</code> callback will be made when the peer socket is
-      finally closed. 
-      <em>Only once <code>on_close</code> is called may the
-        user free the <code>ebb_connection</code> structure.</em> 
-    </p>
-
-
-    <h3><code>ebb_request</code></h3>
-
-    <p>
-      This structure provides information about a request. For example,
-      <code>request-&gt;method == EBB_POST</code> would mean the method of
-      the request is <code>POST</code>. There are also many callbacks
-      which can be set to handle data from a request as it is parsed.
-    </p>
-
-    <p>
-      The <code>on_uri</code> callback and all other
-      <code>ebb_element_cb</code> callbacks provide pointers to request
-      data.  The annoying thing is they do not necessarily provide a
-      complete string.  This is because the reads from the socket may not
-      contain an entire request and for efficency libebb does not attempt to
-      buffer the data.  Theoretically, one might receive an
-      <code>on_uri</code> callback 10 times, each providing just a single
-      character of the request's URI.  See <code>ebb_request_parser.h</code> for
-      a full list of callbacks that you may provide. (If you don't set them,
-      they are ignored.)
-    </p>
-
-    <p>
-      The <code>on_complete</code> callback is called at the end of
-      each request.
-      <em>Only once <code>on_complete</code> is called may the
-        user free the <code>ebb_request</code> structure.</em> 
-    </p>
-
-    <h2>Example</h2>
-
-    <p>
-      A simple example is provided in <code>examples/hello_world.c</code>.
-    </p>
-    
-  </div></body>
-</html>
diff --git a/deps/libebb/ebb.c b/deps/libebb/ebb.c
deleted file mode 100644 (file)
index a4c5e78..0000000
+++ /dev/null
@@ -1,798 +0,0 @@
-/* This file is part of libebb.
- *
- * Copyright (c) 2008 Ryan Dahl (ry@ndahl.us)
- * All rights reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
- */
-#include <assert.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/tcp.h> /* TCP_NODELAY */
-#include <netinet/in.h>  /* inet_ntoa */
-#include <arpa/inet.h>   /* inet_ntoa */
-#include <unistd.h>
-#include <stdio.h>      /* perror */
-#include <errno.h>      /* perror */
-#include <stdlib.h> /* for the default methods */
-#include <ev.h>
-
-#include "ebb.h"
-#include "ebb_request_parser.h"
-#ifdef HAVE_GNUTLS
-# include <gnutls/gnutls.h>
-# include "rbtree.h" /* for session_cache */
-#endif
-
-#ifndef TRUE
-# define TRUE 1
-#endif
-#ifndef FALSE
-# define FALSE 0
-#endif 
-#ifndef MIN
-# define MIN(a,b) (a < b ? a : b)
-#endif
-
-#define error(FORMAT, ...) fprintf(stderr, "error: " FORMAT "\n", ##__VA_ARGS__)
-
-#define CONNECTION_HAS_SOMETHING_TO_WRITE (connection->to_write != NULL)
-
-static void 
-set_nonblock (int fd)
-{
-  int flags = fcntl(fd, F_GETFL, 0);
-  int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-  assert(0 <= r && "Setting socket non-block failed!");
-}
-
-static ssize_t 
-nosigpipe_push(void *data, const void *buf, size_t len)
-{
-  int fd = (int)data;
-  int flags = 0;
-#ifdef MSG_NOSIGNAL
-  flags = MSG_NOSIGNAL;
-#endif
-  return send(fd, buf, len, flags);
-}
-
-static void 
-close_connection(ebb_connection *connection)
-{
-#ifdef HAVE_GNUTLS
-  if(connection->server->secure)
-    ev_io_stop(connection->server->loop, &connection->handshake_watcher);
-#endif
-  ev_io_stop(connection->server->loop, &connection->read_watcher);
-  ev_io_stop(connection->server->loop, &connection->write_watcher);
-  ev_timer_stop(connection->server->loop, &connection->timeout_watcher);
-
-  if(0 > close(connection->fd))
-    error("problem closing connection fd");
-
-  connection->open = FALSE;
-
-  if(connection->on_close)
-    connection->on_close(connection);
-  /* No access to the connection past this point! 
-   * The user is allowed to free in the callback
-   */
-}
-
-#ifdef HAVE_GNUTLS
-#define GNUTLS_NEED_WRITE (gnutls_record_get_direction(connection->session) == 1)
-#define GNUTLS_NEED_READ (gnutls_record_get_direction(connection->session) == 0)
-
-#define EBB_MAX_SESSION_KEY 32
-#define EBB_MAX_SESSION_VALUE 512
-
-struct session_cache {
-  struct rbtree_node_t node;
-
-  gnutls_datum_t key;
-  gnutls_datum_t value;
-
-  char key_storage[EBB_MAX_SESSION_KEY];
-  char value_storage[EBB_MAX_SESSION_VALUE];
-};
-
-static int 
-session_cache_compare (void *left, void *right) 
-{
-  gnutls_datum_t *left_key = left;
-  gnutls_datum_t *right_key = right;
-  if(left_key->size < right_key->size)
-    return -1;
-  else if(left_key->size > right_key->size)
-    return 1;
-  else
-    return memcmp( left_key->data
-                 , right_key->data
-                 , MIN(left_key->size, right_key->size)
-                 );
-}
-
-static int
-session_cache_store(void *data, gnutls_datum_t key, gnutls_datum_t value)
-{
-  rbtree tree = data;
-
-  if( tree == NULL
-   || key.size > EBB_MAX_SESSION_KEY
-   || value.size > EBB_MAX_SESSION_VALUE
-    ) return -1;
-
-  struct session_cache *cache = gnutls_malloc(sizeof(struct session_cache));
-
-  memcpy (cache->key_storage, key.data, key.size);
-  cache->key.size = key.size;
-  cache->key.data = (void*)cache->key_storage;
-
-  memcpy (cache->value_storage, value.data, value.size);
-  cache->value.size = value.size;
-  cache->value.data = (void*)cache->value_storage;
-
-  cache->node.key = &cache->key;
-  cache->node.value = &cache;
-
-  rbtree_insert(tree, (rbtree_node)cache);
-
-  //printf("session_cache_store\n");
-
-  return 0;
-}
-
-static gnutls_datum_t
-session_cache_retrieve (void *data, gnutls_datum_t key)
-{
-  rbtree tree = data;
-  gnutls_datum_t res = { NULL, 0 };
-  struct session_cache *cache = rbtree_lookup(tree, &key);
-
-  if(cache == NULL)
-    return res;
-
-  res.size = cache->value.size;
-  res.data = gnutls_malloc (res.size);
-  if(res.data == NULL)
-    return res;
-
-  memcpy(res.data, cache->value.data, res.size);
-
-  //printf("session_cache_retrieve\n");
-
-  return res;
-}
-
-static int
-session_cache_remove (void *data, gnutls_datum_t key)
-{
-  rbtree tree = data;
-
-  if(tree == NULL)
-    return -1;
-
-  struct session_cache *cache = (struct session_cache *)rbtree_delete(tree, &key);
-  if(cache == NULL)
-    return -1;
-
-  gnutls_free(cache);
-
-  //printf("session_cache_remove\n");
-
-  return 0;
-}
-
-static void 
-on_handshake(struct ev_loop *loop ,ev_io *watcher, int revents)
-{
-  ebb_connection *connection = watcher->data;
-
-  //printf("on_handshake\n");
-
-  assert(ev_is_active(&connection->timeout_watcher));
-  assert(!ev_is_active(&connection->read_watcher));
-  assert(!ev_is_active(&connection->write_watcher));
-
-  if(EV_ERROR & revents) {
-    error("on_handshake() got error event, closing connection.n");
-    goto error;
-  }
-
-  int r = gnutls_handshake(connection->session);
-  if(r < 0) {
-    if(gnutls_error_is_fatal(r)) goto error;
-    if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN)
-      ev_io_set( watcher
-               , connection->fd
-               , (GNUTLS_NEED_WRITE ? EV_WRITE : EV_READ)
-               );
-    return;
-  }
-
-  ebb_connection_reset_timeout(connection);
-  ev_io_stop(loop, watcher);
-
-  ev_io_start(loop, &connection->read_watcher);
-  if(CONNECTION_HAS_SOMETHING_TO_WRITE)
-    ev_io_start(loop, &connection->write_watcher);
-
-  return;
-error:
-  close_connection(connection);
-}
-
-#endif /* HAVE_GNUTLS */
-
-
-/* Internal callback 
- * called by connection->timeout_watcher
- */
-static void 
-on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
-{
-  ebb_connection *connection = watcher->data;
-
-  assert(watcher == &connection->timeout_watcher);
-
-  //printf("on_timeout\n");
-
-  /* if on_timeout returns true, we don't time out */
-  if(connection->on_timeout) {
-    int r = connection->on_timeout(connection);
-
-    if(r == EBB_AGAIN) {
-      ebb_connection_reset_timeout(connection);
-      return;
-    }
-  }
-
-  ebb_connection_schedule_close(connection);
-}
-
-/* Internal callback 
- * called by connection->read_watcher
- */
-static void 
-on_readable(struct ev_loop *loop, ev_io *watcher, int revents)
-{
-  ebb_connection *connection = watcher->data;
-  char recv_buffer[TCP_MAXWIN];
-  ssize_t recved;
-
-  //printf("on_readable\n");
-  // TODO -- why is this broken?
-  //assert(ev_is_active(&connection->timeout_watcher));
-  assert(watcher == &connection->read_watcher);
-
-  if(EV_ERROR & revents) {
-    error("on_readable() got error event, closing connection.");
-    goto error;
-  }
-
-#ifdef HAVE_GNUTLS
-  assert(!ev_is_active(&connection->handshake_watcher));
-
-  if(connection->server->secure) {
-    recved = gnutls_record_recv( connection->session
-                               , recv_buffer
-                               , TCP_MAXWIN
-                               );
-    if(recved <= 0) {
-      if(gnutls_error_is_fatal(recved)) goto error;
-      if( (recved == GNUTLS_E_INTERRUPTED || recved == GNUTLS_E_AGAIN)
-       && GNUTLS_NEED_WRITE
-        ) ev_io_start(loop, &connection->write_watcher);
-      return; 
-    } 
-  } else {
-#endif /* HAVE_GNUTLS */
-
-    recved = recv(connection->fd, recv_buffer, TCP_MAXWIN, 0);
-    if(recved <= 0) goto error;
-
-#ifdef HAVE_GNUTLS
-  }
-#endif /* HAVE_GNUTLS */
-
-  ebb_connection_reset_timeout(connection);
-
-  ebb_request_parser_execute(&connection->parser, recv_buffer, recved);
-
-  /* parse error? just drop the client. screw the 400 response */
-  if(ebb_request_parser_has_error(&connection->parser)) goto error;
-  return;
-error:
-  ebb_connection_schedule_close(connection);
-}
-
-/* Internal callback 
- * called by connection->write_watcher
- */
-static void 
-on_writable(struct ev_loop *loop, ev_io *watcher, int revents)
-{
-  ebb_connection *connection = watcher->data;
-  ssize_t sent;
-  
-  //printf("on_writable\n");
-
-  assert(CONNECTION_HAS_SOMETHING_TO_WRITE);
-  assert(connection->written <= connection->to_write_len);
-  // TODO -- why is this broken?
-  //assert(ev_is_active(&connection->timeout_watcher));
-  assert(watcher == &connection->write_watcher);
-
-  if(connection->to_write == 0)
-    goto stop_writing;
-
-#ifdef HAVE_GNUTLS
-  assert(!ev_is_active(&connection->handshake_watcher));
-
-  if(connection->server->secure) {
-    sent = gnutls_record_send( connection->session
-                             , connection->to_write + connection->written
-                             , connection->to_write_len - connection->written
-                             ); 
-    if(sent < 0) {
-      if(gnutls_error_is_fatal(sent)) goto error;
-      if( (sent == GNUTLS_E_INTERRUPTED || sent == GNUTLS_E_AGAIN)
-       && GNUTLS_NEED_READ
-        ) ev_io_stop(loop, watcher);
-      return; 
-    }
-  } else {
-#endif /* HAVE_GNUTLS */
-
-    sent = nosigpipe_push( (void*)connection->fd
-                         , connection->to_write + connection->written
-                         , connection->to_write_len - connection->written
-                         );
-    if(sent < 0) goto error;
-    if(sent == 0) return;
-
-#ifdef HAVE_GNUTLS
-  }
-#endif /* HAVE_GNUTLS */
-
-  ebb_connection_reset_timeout(connection);
-
-  connection->written += sent;
-
-  if(connection->written == connection->to_write_len) {
-    goto stop_writing;
-  }
-  return;
-stop_writing:
-  ev_io_stop(loop, watcher);
-  connection->to_write = NULL;
-
-  if(connection->after_write_cb)
-    connection->after_write_cb(connection);
-  return;
-error:
-  error("close connection on write.");
-  ebb_connection_schedule_close(connection);
-}
-
-#ifdef HAVE_GNUTLS
-
-static void 
-on_goodbye_tls(struct ev_loop *loop, ev_io *watcher, int revents)
-{
-  ebb_connection *connection = watcher->data;
-  assert(watcher == &connection->goodbye_tls_watcher);
-
-  if(EV_ERROR & revents) {
-    error("on_goodbye() got error event, closing connection.");
-    goto die;
-  }
-
-  int r = gnutls_bye(connection->session, GNUTLS_SHUT_RDWR);
-  if(r < 0) {
-    if(gnutls_error_is_fatal(r)) goto die;
-    if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN)
-      ev_io_set( watcher
-               , connection->fd
-               , (GNUTLS_NEED_WRITE ? EV_WRITE : EV_READ)
-               );
-    return;
-  }
-
-die:
-  ev_io_stop(loop, watcher);
-  if(connection->session) 
-    gnutls_deinit(connection->session);
-  close_connection(connection);
-}
-#endif /* HAVE_GNUTLS*/
-
-static void 
-on_goodbye(struct ev_loop *loop, ev_timer *watcher, int revents)
-{
-  ebb_connection *connection = watcher->data;
-  assert(watcher == &connection->goodbye_watcher);
-
-  close_connection(connection);
-}
-
-
-static ebb_request* 
-new_request_wrapper(void *data)
-{
-  ebb_connection *connection = data;
-  if(connection->new_request)
-    return connection->new_request(connection);
-  return NULL;
-}
-
-/* Internal callback 
- * Called by server->connection_watcher.
- */
-static void 
-on_connection(struct ev_loop *loop, ev_io *watcher, int revents)
-{
-  ebb_server *server = watcher->data;
-
-  //printf("on connection!\n");
-
-  assert(server->listening);
-  assert(server->loop == loop);
-  assert(&server->connection_watcher == watcher);
-  
-  if(EV_ERROR & revents) {
-    error("on_connection() got error event, closing server.");
-    ebb_server_unlisten(server);
-    return;
-  }
-  
-  struct sockaddr_in addr; // connector's address information
-  socklen_t addr_len = sizeof(addr); 
-  int fd = accept( server->fd
-                 , (struct sockaddr*) & addr
-                 , & addr_len
-                 );
-  if(fd < 0) {
-    perror("accept()");
-    return;
-  }
-
-  ebb_connection *connection = NULL;
-  if(server->new_connection)
-    connection = server->new_connection(server, &addr);
-  if(connection == NULL) {
-    close(fd);
-    return;
-  } 
-  
-  set_nonblock(fd);
-  connection->fd = fd;
-  connection->open = TRUE;
-  connection->server = server;
-  memcpy(&connection->sockaddr, &addr, addr_len);
-  if(server->port[0] != '\0')
-    connection->ip = inet_ntoa(connection->sockaddr.sin_addr);  
-
-#ifdef SO_NOSIGPIPE
-  int arg = 1;
-  setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &arg, sizeof(int));
-#endif
-
-#ifdef HAVE_GNUTLS
-  if(server->secure) {
-    gnutls_init(&connection->session, GNUTLS_SERVER);
-    gnutls_transport_set_lowat(connection->session, 0); 
-    gnutls_set_default_priority(connection->session);
-    gnutls_credentials_set(connection->session, GNUTLS_CRD_CERTIFICATE, connection->server->credentials);
-
-    gnutls_transport_set_ptr(connection->session, (gnutls_transport_ptr) fd); 
-    gnutls_transport_set_push_function(connection->session, nosigpipe_push);
-
-    gnutls_db_set_ptr (connection->session, &server->session_cache);
-    gnutls_db_set_store_function (connection->session, session_cache_store);
-    gnutls_db_set_retrieve_function (connection->session, session_cache_retrieve);
-    gnutls_db_set_remove_function (connection->session, session_cache_remove);
-  }
-
-  ev_io_set(&connection->handshake_watcher, connection->fd, EV_READ | EV_WRITE);
-#endif /* HAVE_GNUTLS */
-
-  /* Note: not starting the write watcher until there is data to be written */
-  ev_io_set(&connection->write_watcher, connection->fd, EV_WRITE);
-  ev_io_set(&connection->read_watcher, connection->fd, EV_READ);
-  /* XXX: seperate error watcher? */
-
-  ev_timer_again(loop, &connection->timeout_watcher);
-
-#ifdef HAVE_GNUTLS
-  if(server->secure) {
-    ev_io_start(loop, &connection->handshake_watcher);
-    return;
-  }
-#endif
-
-  ev_io_start(loop, &connection->read_watcher);
-}
-
-/**
- * Begin the server listening on a file descriptor.  This DOES NOT start the
- * event loop.  Start the event loop after making this call.
- */
-int 
-ebb_server_listen_on_fd(ebb_server *server, const int fd)
-{
-  assert(server->listening == FALSE);
-
-  if (listen(fd, EBB_MAX_CONNECTIONS) < 0) {
-    perror("listen()");
-    return -1;
-  }
-  
-  set_nonblock(fd); /* XXX superfluous? */
-  
-  server->fd = fd;
-  server->listening = TRUE;
-  
-  ev_io_set (&server->connection_watcher, server->fd, EV_READ);
-  ev_io_start (server->loop, &server->connection_watcher);
-  
-  return server->fd;
-}
-
-
-/**
- * Begin the server listening on a file descriptor This DOES NOT start the
- * event loop. Start the event loop after making this call.
- */
-int 
-ebb_server_listen_on_port(ebb_server *server, const int port)
-{
-  int fd = -1;
-  struct linger ling = {0, 0};
-  struct sockaddr_in addr;
-  int flags = 1;
-  
-  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
-    perror("socket()");
-    goto error;
-  }
-  
-  flags = 1;
-  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
-  setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
-  setsockopt(fd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
-
-  /* XXX: Sending single byte chunks in a response body? Perhaps there is a
-   * need to enable the Nagel algorithm dynamically. For now disabling.
-   */
-  setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
-  
-  /* the memset call clears nonstandard fields in some impementations that
-   * otherwise mess things up.
-   */
-  memset(&addr, 0, sizeof(addr));
-  
-  addr.sin_family = AF_INET;
-  addr.sin_port = htons(port);
-  addr.sin_addr.s_addr = htonl(INADDR_ANY);
-  
-  if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-    perror("bind()");
-    goto error;
-  }
-  
-  int ret = ebb_server_listen_on_fd(server, fd);
-  if (ret >= 0) {
-    sprintf(server->port, "%d", port);
-  }
-  return ret;
-error:
-  if(fd > 0) close(fd);
-  return -1;
-}
-
-/**
- * Stops the server. Will not accept new connections.  Does not drop
- * existing connections.
- */
-void 
-ebb_server_unlisten(ebb_server *server)
-{
-  if(server->listening) {
-    ev_io_stop(server->loop, &server->connection_watcher);
-    close(server->fd);
-    server->port[0] = '\0';
-    server->listening = FALSE;
-  }
-}
-
-/**
- * Initialize an ebb_server structure.  After calling ebb_server_init set
- * the callback server->new_connection and, optionally, callback data
- * server->data.  The new connection MUST be initialized with
- * ebb_connection_init before returning it to the server.
- *
- * @param server the server to initialize
- * @param loop a libev loop
- */
-void 
-ebb_server_init(ebb_server *server, struct ev_loop *loop)
-{
-  server->loop = loop;
-  server->listening = FALSE;
-  server->port[0] = '\0';
-  server->fd = -1;
-  server->connection_watcher.data = server;
-  ev_init (&server->connection_watcher, on_connection);
-  server->secure = FALSE;
-
-#ifdef HAVE_GNUTLS
-  rbtree_init(&server->session_cache, session_cache_compare);
-  server->credentials = NULL;
-#endif
-
-  server->new_connection = NULL;
-  server->data = NULL;
-}
-
-
-#ifdef HAVE_GNUTLS
-/* similar to server_init. 
- *
- * the user of secure server might want to set additional callbacks from
- * GNUTLS. In particular 
- * gnutls_global_set_mem_functions() 
- * gnutls_global_set_log_function()
- * Also see the note above ebb_connection_init() about setting gnutls cache
- * access functions
- *
- * cert_file: the filename of a PEM certificate file
- *
- * key_file: the filename of a private key. Currently only PKCS-1 encoded
- * RSA and DSA private keys are accepted. 
- */
-int 
-ebb_server_set_secure (ebb_server *server, const char *cert_file, const char *key_file)
-{
-  server->secure = TRUE;
-  gnutls_global_init();
-  gnutls_certificate_allocate_credentials(&server->credentials);
-  /* todo gnutls_certificate_free_credentials */
-  int r = gnutls_certificate_set_x509_key_file( server->credentials
-                                              , cert_file
-                                              , key_file
-                                              , GNUTLS_X509_FMT_PEM
-                                              );
-  if(r < 0) {
-    error("loading certificates");
-    return -1;
-  }
-  return 1;
-}
-#endif /* HAVE_GNUTLS */
-
-/**
- * Initialize an ebb_connection structure. After calling this function you
- * must setup callbacks for the different actions the server can take. See
- * server.h for which callbacks are availible. 
- * 
- * This should be called immediately after allocating space for a new
- * ebb_connection structure. Most likely, this will only be called within
- * the ebb_server->new_connection callback which you supply. 
- *
- * If using SSL do consider setting
- *   gnutls_db_set_retrieve_function (connection->session, _);
- *   gnutls_db_set_remove_function (connection->session, _);
- *   gnutls_db_set_store_function (connection->session, _);
- *   gnutls_db_set_ptr (connection->session, _);
- * To provide a better means of storing SSL session caches. libebb provides
- * only a simple default implementation. 
- *
- * @param connection the connection to initialize
- * @param timeout    the timeout in seconds
- */
-void 
-ebb_connection_init(ebb_connection *connection)
-{
-  connection->fd = -1;
-  connection->server = NULL;
-  connection->ip = NULL;
-  connection->open = FALSE;
-
-  ebb_request_parser_init( &connection->parser );
-  connection->parser.data = connection;
-  connection->parser.new_request = new_request_wrapper;
-  
-  ev_init (&connection->write_watcher, on_writable);
-  connection->write_watcher.data = connection;
-  connection->to_write = NULL;
-
-  ev_init(&connection->read_watcher, on_readable);
-  connection->read_watcher.data = connection;
-
-#ifdef HAVE_GNUTLS
-  connection->handshake_watcher.data = connection;
-  ev_init(&connection->handshake_watcher, on_handshake);
-
-  ev_init(&connection->goodbye_tls_watcher, on_goodbye_tls);
-  connection->goodbye_tls_watcher.data = connection;
-
-  connection->session = NULL;
-#endif /* HAVE_GNUTLS */
-
-  ev_timer_init(&connection->goodbye_watcher, on_goodbye, 0., 0.);
-  connection->goodbye_watcher.data = connection;  
-
-  ev_timer_init(&connection->timeout_watcher, on_timeout, 0., EBB_DEFAULT_TIMEOUT);
-  connection->timeout_watcher.data = connection;  
-
-  connection->new_request = NULL;
-  connection->on_timeout = NULL;
-  connection->on_close = NULL;
-  connection->data = NULL;
-}
-
-void 
-ebb_connection_schedule_close (ebb_connection *connection)
-{
-#ifdef HAVE_GNUTLS
-  if(connection->server->secure) {
-    ev_io_set(&connection->goodbye_tls_watcher, connection->fd, EV_READ | EV_WRITE);
-    ev_io_start(connection->server->loop, &connection->goodbye_tls_watcher);
-    return;
-  }
-#endif
-  ev_timer_start(connection->server->loop, &connection->goodbye_watcher);
-}
-
-/* 
- * Resets the timeout to stay alive for another connection->timeout seconds
- */
-void 
-ebb_connection_reset_timeout(ebb_connection *connection)
-{
-  ev_timer_again(connection->server->loop, &connection->timeout_watcher);
-}
-
-/**
- * Writes a string to the socket. This is actually sets a watcher
- * which may take multiple iterations to write the entire string.
- *
- * This can only be called once at a time. If you call it again
- * while the connection is writing another buffer the ebb_connection_write
- * will return FALSE and ignore the request.
- */
-int 
-ebb_connection_write (ebb_connection *connection, const char *buf, size_t len, ebb_after_write_cb cb)
-{
-  if(ev_is_active(&connection->write_watcher))
-    return FALSE;
-  assert(!CONNECTION_HAS_SOMETHING_TO_WRITE);
-  connection->to_write = buf;
-  connection->to_write_len = len;
-  connection->written = 0;
-  connection->after_write_cb = cb;
-  ev_io_start(connection->server->loop, &connection->write_watcher);
-  return TRUE;
-}
-
diff --git a/deps/libebb/ebb.h b/deps/libebb/ebb.h
deleted file mode 100644 (file)
index e5e90b4..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/* This file is part of libebb.
- *
- * Copyright (c) 2008 Ryan Dahl (ry@ndahl.us)
- * All rights reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
- */
-#ifndef EBB_H
-#define EBB_H
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <ev.h>
-#ifdef HAVE_GNUTLS
-# include <gnutls/gnutls.h>
-# include "rbtree.h" /* for ebb_server.session_cache */
-#endif 
-#include "ebb_request_parser.h"
-
-#define EBB_MAX_CONNECTIONS 1024
-#define EBB_DEFAULT_TIMEOUT 30.0
-
-#define EBB_AGAIN 0
-#define EBB_STOP 1
-
-typedef struct ebb_server     ebb_server;
-typedef struct ebb_connection ebb_connection;
-typedef void (*ebb_after_write_cb) (ebb_connection *connection); 
-typedef void (*ebb_connection_cb)(ebb_connection *connection, void *data);
-
-struct ebb_server {
-  int fd;                                       /* ro */
-  struct sockaddr_in sockaddr;                  /* ro */
-  socklen_t socklen;                            /* ro */
-  char port[6];                                 /* ro */
-  struct ev_loop *loop;                         /* ro */
-  unsigned listening:1;                         /* ro */
-  unsigned secure:1;                            /* ro */
-#ifdef HAVE_GNUTLS
-  gnutls_certificate_credentials_t credentials; /* private */
-  struct rbtree_t session_cache;                /* private */
-#endif
-  ev_io connection_watcher;                     /* private */
-
-  /* Public */
-
-  /* Allocates and initializes an ebb_connection.  NULL by default. */
-  ebb_connection* (*new_connection) (ebb_server*, struct sockaddr_in*);
-
-  void *data;
-};
-
-struct ebb_connection {
-  int fd;                      /* ro */
-  struct sockaddr_in sockaddr; /* ro */
-  socklen_t socklen;           /* ro */ 
-  ebb_server *server;          /* ro */
-  char *ip;                    /* ro */
-  unsigned open:1;             /* ro */
-
-  const char *to_write;              /* ro */
-  size_t to_write_len;               /* ro */
-  size_t written;                    /* ro */ 
-  ebb_after_write_cb after_write_cb; /* ro */
-
-  ebb_request_parser parser;   /* private */
-  ev_io write_watcher;         /* private */
-  ev_io read_watcher;          /* private */
-  ev_timer timeout_watcher;    /* private */
-  ev_timer goodbye_watcher;    /* private */
-#ifdef HAVE_GNUTLS
-  ev_io handshake_watcher;     /* private */
-  gnutls_session_t session;    /* private */
-  ev_io goodbye_tls_watcher;       /* private */
-#endif
-
-  /* Public */
-
-  ebb_request* (*new_request) (ebb_connection*); 
-
-  /* Returns EBB_STOP or EBB_AGAIN. NULL by default.  */
-  int (*on_timeout) (ebb_connection*); 
-
-  void (*on_close) (ebb_connection*); 
-
-  void *data;
-};
-
-void ebb_server_init (ebb_server *server, struct ev_loop *loop);
-#ifdef HAVE_GNUTLS
-int ebb_server_set_secure (ebb_server *server, const char *cert_file, 
-                           const char *key_file);
-#endif
-int ebb_server_listen_on_port (ebb_server *server, const int port);
-int ebb_server_listen_on_fd (ebb_server *server, const int sfd);
-void ebb_server_unlisten (ebb_server *server);
-
-void ebb_connection_init (ebb_connection *);
-void ebb_connection_schedule_close (ebb_connection *);
-void ebb_connection_reset_timeout (ebb_connection *);
-int ebb_connection_write (ebb_connection *, const char *buf, size_t len, ebb_after_write_cb);
-
-#endif
diff --git a/deps/libebb/ebb_request_parser.h b/deps/libebb/ebb_request_parser.h
deleted file mode 100644 (file)
index 93d502f..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/* This file is part of the libebb web server library
- *
- * Copyright (c) 2008 Ryan Dahl (ry@ndahl.us)
- * All rights reserved.
- *
- * This parser is based on code from Zed Shaw's Mongrel.
- * Copyright (c) 2005 Zed A. Shaw
- * 
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
- */
-#ifndef ebb_request_parser_h
-#define ebb_request_parser_h
-#ifdef __cplusplus
-extern "C" {
-#endif 
-
-
-#include <sys/types.h> 
-
-typedef struct ebb_request ebb_request;
-typedef struct ebb_request_parser  ebb_request_parser;
-typedef void (*ebb_header_cb)(ebb_request*, const char *at, size_t length, int header_index);
-typedef void (*ebb_element_cb)(ebb_request*, const char *at, size_t length);
-
-#define EBB_MAX_MULTIPART_BOUNDARY_LEN 20
-
-/* HTTP Methods */
-#define EBB_COPY       0x00000001
-#define EBB_DELETE     0x00000002
-#define EBB_GET        0x00000004
-#define EBB_HEAD       0x00000008
-#define EBB_LOCK       0x00000010
-#define EBB_MKCOL      0x00000020
-#define EBB_MOVE       0x00000040
-#define EBB_OPTIONS    0x00000080
-#define EBB_POST       0x00000100
-#define EBB_PROPFIND   0x00000200
-#define EBB_PROPPATCH  0x00000400
-#define EBB_PUT        0x00000800
-#define EBB_TRACE      0x00001000
-#define EBB_UNLOCK     0x00002000
-
-/* Transfer Encodings */
-#define EBB_IDENTITY   0x00000001
-#define EBB_CHUNKED    0x00000002
-
-struct ebb_request {
-  int method;
-  int transfer_encoding;         /* ro */
-  int expect_continue;               /* ro */
-  unsigned int version_major;        /* ro */
-  unsigned int version_minor;        /* ro */
-  int number_of_headers;             /* ro */
-  int keep_alive;                    /* private - use ebb_request_should_keep_alive */
-  size_t content_length;             /* ro - 0 if unknown */
-  size_t body_read;                  /* ro */
-
-  /* Public  - ordered list of callbacks */
-  ebb_element_cb on_path;
-  ebb_element_cb on_query_string;
-  ebb_element_cb on_uri;
-  ebb_element_cb on_fragment;
-  ebb_header_cb  on_header_field;
-  ebb_header_cb  on_header_value;
-  void (*on_headers_complete)(ebb_request *);
-  ebb_element_cb on_body;
-  void (*on_complete)(ebb_request *);
-  void *data;
-};
-
-struct ebb_request_parser {
-  int cs;                           /* private */
-  size_t chunk_size;                /* private */
-  unsigned eating:1;                /* private */
-  ebb_request *current_request;     /* ro */
-  const char *header_field_mark; 
-  const char *header_value_mark; 
-  const char *query_string_mark; 
-  const char *path_mark; 
-  const char *uri_mark; 
-  const char *fragment_mark; 
-
-  /* Public */
-  ebb_request* (*new_request)(void*);
-  void *data;
-};
-
-void ebb_request_parser_init(ebb_request_parser *parser);
-size_t ebb_request_parser_execute(ebb_request_parser *parser, const char *data, size_t len);
-int ebb_request_parser_has_error(ebb_request_parser *parser);
-int ebb_request_parser_is_finished(ebb_request_parser *parser);
-void ebb_request_init(ebb_request *);
-int ebb_request_should_keep_alive(ebb_request *request);
-#define ebb_request_has_body(request) \
-  (request->transfer_encoding == EBB_CHUNKED || request->content_length > 0 )
-
-#ifdef __cplusplus
-}
-#endif 
-#endif
diff --git a/deps/libebb/ebb_request_parser.rl b/deps/libebb/ebb_request_parser.rl
deleted file mode 100644 (file)
index 63e36a8..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-/* This file is part of the libebb web server library
- *
- * Copyright (c) 2008 Ryan Dahl (ry@ndahl.us)
- * All rights reserved.
- *
- * This parser is based on code from Zed Shaw's Mongrel.
- * Copyright (c) 2005 Zed A. Shaw
- * 
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
- */
-#include "ebb_request_parser.h"
-
-#include <stdio.h>
-#include <assert.h>
-
-static int unhex[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-                     , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
-                     ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
-                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-                     ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
-                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-                     };
-#define TRUE 1
-#define FALSE 0
-#define MIN(a,b) (a < b ? a : b)
-
-#define REMAINING (pe - p)
-#define CURRENT (parser->current_request)
-#define CONTENT_LENGTH (parser->current_request->content_length)
-#define CALLBACK(FOR)                               \
-  if(parser->FOR##_mark && CURRENT->on_##FOR) {     \
-    CURRENT->on_##FOR( CURRENT                      \
-                , parser->FOR##_mark                \
-                , p - parser->FOR##_mark            \
-                );                                  \
- }
-#define HEADER_CALLBACK(FOR)                        \
-  if(parser->FOR##_mark && CURRENT->on_##FOR) {     \
-    CURRENT->on_##FOR( CURRENT                      \
-                , parser->FOR##_mark                \
-                , p - parser->FOR##_mark            \
-                , CURRENT->number_of_headers        \
-                );                                  \
- }
-#define END_REQUEST                        \
-    if(CURRENT->on_complete)               \
-      CURRENT->on_complete(CURRENT);       \
-    CURRENT = NULL;
-
-
-%%{
-  machine ebb_request_parser;
-
-  action mark_header_field   { parser->header_field_mark   = p; }
-  action mark_header_value   { parser->header_value_mark   = p; }
-  action mark_fragment       { parser->fragment_mark       = p; }
-  action mark_query_string   { parser->query_string_mark   = p; }
-  action mark_request_path   { parser->path_mark           = p; }
-  action mark_request_uri    { parser->uri_mark            = p; }
-
-  action write_field { 
-    HEADER_CALLBACK(header_field);
-    parser->header_field_mark = NULL;
-  }
-
-  action write_value {
-    HEADER_CALLBACK(header_value);
-    parser->header_value_mark = NULL;
-  }
-
-  action request_uri { 
-    CALLBACK(uri);
-    parser->uri_mark = NULL;
-  }
-
-  action fragment { 
-    CALLBACK(fragment);
-    parser->fragment_mark = NULL;
-  }
-
-  action query_string { 
-    CALLBACK(query_string);
-    parser->query_string_mark = NULL;
-  }
-
-  action request_path {
-    CALLBACK(path);
-    parser->path_mark = NULL;
-  }
-
-  action content_length {
-    CURRENT->content_length *= 10;
-    CURRENT->content_length += *p - '0';
-  }
-
-  action use_identity_encoding { CURRENT->transfer_encoding = EBB_IDENTITY; }
-  action use_chunked_encoding { CURRENT->transfer_encoding = EBB_CHUNKED; }
-
-  action set_keep_alive { CURRENT->keep_alive = TRUE; }
-  action set_not_keep_alive { CURRENT->keep_alive = FALSE; }
-
-  action expect_continue {
-    CURRENT->expect_continue = TRUE;
-  }
-
-  action trailer {
-    /* not implemenetd yet. (do requests even have trailing headers?) */
-  }
-
-  action version_major {
-    CURRENT->version_major *= 10;
-    CURRENT->version_major += *p - '0';
-  }
-
-  action version_minor {
-    CURRENT->version_minor *= 10;
-    CURRENT->version_minor += *p - '0';
-  }
-
-  action end_header_line {
-    CURRENT->number_of_headers++;
-  }
-
-  action end_headers {
-    if(CURRENT->on_headers_complete)
-      CURRENT->on_headers_complete(CURRENT);
-  }
-
-  action add_to_chunk_size {
-    parser->chunk_size *= 16;
-    parser->chunk_size += unhex[(int)*p];
-  }
-
-  action skip_chunk_data {
-    skip_body(&p, parser, MIN(parser->chunk_size, REMAINING));
-    fhold; 
-    if(parser->chunk_size > REMAINING) {
-      fbreak;
-    } else {
-      fgoto chunk_end; 
-    }
-  }
-
-  action end_chunked_body {
-    END_REQUEST;
-    fnext main;
-  }
-
-  action start_req {
-    assert(CURRENT == NULL);
-    CURRENT = parser->new_request(parser->data);
-  }
-
-  action body_logic {
-    if(CURRENT->transfer_encoding == EBB_CHUNKED) {
-      fnext ChunkedBody;
-    } else {
-      /* this is pretty stupid. i'd prefer to combine this with skip_chunk_data */
-      parser->chunk_size = CURRENT->content_length;
-      p += 1;  
-      skip_body(&p, parser, MIN(REMAINING, CURRENT->content_length));
-      fhold;
-      if(parser->chunk_size > REMAINING) {
-        fbreak;
-      } 
-    }
-  }
-
-#
-##
-###
-#### HTTP/1.1 STATE MACHINE
-###
-##   RequestHeaders and character types are from
-#    Zed Shaw's beautiful Mongrel parser.
-
-  CRLF = "\r\n";
-
-# character types
-  CTL = (cntrl | 127);
-  safe = ("$" | "-" | "_" | ".");
-  extra = ("!" | "*" | "'" | "(" | ")" | ",");
-  reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
-  unsafe = (CTL | " " | "\"" | "#" | "%" | "<" | ">");
-  national = any -- (alpha | digit | reserved | extra | safe | unsafe);
-  unreserved = (alpha | digit | safe | extra | national);
-  escape = ("%" xdigit xdigit);
-  uchar = (unreserved | escape);
-  pchar = (uchar | ":" | "@" | "&" | "=" | "+");
-  tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
-
-# elements
-  token = (ascii -- (CTL | tspecials));
-  quote = "\"";
-#  qdtext = token -- "\""; 
-#  quoted_pair = "\" ascii;
-#  quoted_string = "\"" (qdtext | quoted_pair )* "\"";
-
-#  headers
-
-  Method = ( "COPY"      %{ CURRENT->method = EBB_COPY;      }
-           | "DELETE"    %{ CURRENT->method = EBB_DELETE;    }
-           | "GET"       %{ CURRENT->method = EBB_GET;       }
-           | "HEAD"      %{ CURRENT->method = EBB_HEAD;      }
-           | "LOCK"      %{ CURRENT->method = EBB_LOCK;      }
-           | "MKCOL"     %{ CURRENT->method = EBB_MKCOL;     }
-           | "MOVE"      %{ CURRENT->method = EBB_MOVE;      }
-           | "OPTIONS"   %{ CURRENT->method = EBB_OPTIONS;   }
-           | "POST"      %{ CURRENT->method = EBB_POST;      }
-           | "PROPFIND"  %{ CURRENT->method = EBB_PROPFIND;  }
-           | "PROPPATCH" %{ CURRENT->method = EBB_PROPPATCH; }
-           | "PUT"       %{ CURRENT->method = EBB_PUT;       }
-           | "TRACE"     %{ CURRENT->method = EBB_TRACE;     }
-           | "UNLOCK"    %{ CURRENT->method = EBB_UNLOCK;    }
-           ); # Not allowing extension methods
-
-  HTTP_Version = "HTTP/" digit+ $version_major "." digit+ $version_minor;
-
-  scheme = ( alpha | digit | "+" | "-" | "." )* ;
-  absolute_uri = (scheme ":" (uchar | reserved )*);
-  path = ( pchar+ ( "/" pchar* )* ) ;
-  query = ( uchar | reserved )* >mark_query_string %query_string ;
-  param = ( pchar | "/" )* ;
-  params = ( param ( ";" param )* ) ;
-  rel_path = ( path? (";" params)? ) ;
-  absolute_path = ( "/"+ rel_path ) >mark_request_path %request_path ("?" query)?;
-  Request_URI = ( "*" | absolute_uri | absolute_path ) >mark_request_uri %request_uri;
-  Fragment = ( uchar | reserved )* >mark_fragment %fragment;
-
-  field_name = ( token -- ":" )+;
-  Field_Name = field_name >mark_header_field %write_field;
-
-  field_value = ((any - " ") any*)?;
-  Field_Value = field_value >mark_header_value %write_value;
-
-  hsep = ":" " "*;
-  header = (field_name hsep field_value) :> CRLF;
-  Header = ( ("Content-Length"i hsep digit+ $content_length)
-           | ("Connection"i hsep 
-               ( "Keep-Alive"i %set_keep_alive
-               | "close"i %set_not_keep_alive
-               )
-             )
-           | ("Transfer-Encoding"i %use_chunked_encoding hsep "identity" %use_identity_encoding)
-         # | ("Expect"i hsep "100-continue"i %expect_continue)
-         # | ("Trailer"i hsep field_value %trailer)
-           | (Field_Name hsep Field_Value)
-           ) :> CRLF;
-
-  Request_Line = ( Method " " Request_URI ("#" Fragment)? " " HTTP_Version CRLF ) ;
-  RequestHeader = Request_Line (Header %end_header_line)* :> CRLF @end_headers;
-
-# chunked message
-  trailing_headers = header*;
-  #chunk_ext_val   = token | quoted_string;
-  chunk_ext_val = token*;
-  chunk_ext_name = token*;
-  chunk_extension = ( ";" " "* chunk_ext_name ("=" chunk_ext_val)? )*;
-  last_chunk = "0"+ chunk_extension CRLF;
-  chunk_size = (xdigit* [1-9a-fA-F] xdigit*) $add_to_chunk_size;
-  chunk_end  = CRLF;
-  chunk_body = any >skip_chunk_data;
-  chunk_begin = chunk_size chunk_extension CRLF;
-  chunk = chunk_begin chunk_body chunk_end;
-  ChunkedBody := chunk* last_chunk trailing_headers CRLF @end_chunked_body;
-
-  Request = RequestHeader >start_req @body_logic;
-
-  main := Request*; # sequence of requests (for keep-alive)
-}%%
-
-%% write data;
-
-static void
-skip_body(const char **p, ebb_request_parser *parser, size_t nskip) {
-  if(CURRENT->on_body && nskip > 0) {
-    CURRENT->on_body(CURRENT, *p, nskip);
-  }
-  CURRENT->body_read += nskip;
-  parser->chunk_size -= nskip;
-  *p += nskip;
-  if(0 == parser->chunk_size) {
-    parser->eating = FALSE;
-    if(CURRENT->transfer_encoding == EBB_IDENTITY) {
-      END_REQUEST;
-    }
-  } else {
-    parser->eating = TRUE;
-  }
-}
-
-void ebb_request_parser_init(ebb_request_parser *parser) 
-{
-  int cs = 0;
-  %% write init;
-  parser->cs = cs;
-
-  parser->chunk_size = 0;
-  parser->eating = 0;
-  
-  parser->current_request = NULL;
-
-  parser->header_field_mark = parser->header_value_mark   = 
-  parser->query_string_mark = parser->path_mark           = 
-  parser->uri_mark          = parser->fragment_mark       = NULL;
-
-  parser->new_request = NULL;
-}
-
-
-/** exec **/
-size_t ebb_request_parser_execute(ebb_request_parser *parser, const char *buffer, size_t len)
-{
-  const char *p, *pe;
-  int cs = parser->cs;
-
-  assert(parser->new_request && "undefined callback");
-
-  p = buffer;
-  pe = buffer+len;
-
-  if(0 < parser->chunk_size && parser->eating) {
-    /* eat body */
-    size_t eat = MIN(len, parser->chunk_size);
-    skip_body(&p, parser, eat);
-  } 
-
-  if(parser->header_field_mark)   parser->header_field_mark   = buffer;
-  if(parser->header_value_mark)   parser->header_value_mark   = buffer;
-  if(parser->fragment_mark)       parser->fragment_mark       = buffer;
-  if(parser->query_string_mark)   parser->query_string_mark   = buffer;
-  if(parser->path_mark)           parser->path_mark           = buffer;
-  if(parser->uri_mark)            parser->uri_mark            = buffer;
-
-  %% write exec;
-
-  parser->cs = cs;
-
-  HEADER_CALLBACK(header_field);
-  HEADER_CALLBACK(header_value);
-  CALLBACK(fragment);
-  CALLBACK(query_string);
-  CALLBACK(path);
-  CALLBACK(uri);
-
-  assert(p <= pe && "buffer overflow after parsing execute");
-
-  return(p - buffer);
-}
-
-int ebb_request_parser_has_error(ebb_request_parser *parser) 
-{
-  return parser->cs == ebb_request_parser_error;
-}
-
-int ebb_request_parser_is_finished(ebb_request_parser *parser) 
-{
-  return parser->cs == ebb_request_parser_first_final;
-}
-
-void ebb_request_init(ebb_request *request)
-{
-  request->expect_continue = FALSE;
-  request->body_read = 0;
-  request->content_length = 0;
-  request->version_major = 0;
-  request->version_minor = 0;
-  request->number_of_headers = 0;
-  request->transfer_encoding = EBB_IDENTITY;
-  request->keep_alive = -1;
-
-  request->on_complete = NULL;
-  request->on_headers_complete = NULL;
-  request->on_body = NULL;
-  request->on_header_field = NULL;
-  request->on_header_value = NULL;
-  request->on_uri = NULL;
-  request->on_fragment = NULL;
-  request->on_path = NULL;
-  request->on_query_string = NULL;
-}
-
-int ebb_request_should_keep_alive(ebb_request *request)
-{
-  if(request->keep_alive == -1)
-    if(request->version_major == 1)
-      return (request->version_minor != 0);
-    else if(request->version_major == 0)
-      return FALSE;
-    else
-      return TRUE;
-  else
-    return request->keep_alive;
-}
diff --git a/deps/libebb/examples/ca-cert.pem b/deps/libebb/examples/ca-cert.pem
deleted file mode 100644 (file)
index 606283b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIBzDCCATegAwIBAgIESIuNVTALBgkqhkiG9w0BAQUwADAeFw0wODA3MjYyMDQ3
-MTlaFw0xMTA0MjIyMDQ3MjVaMAAwgZwwCwYJKoZIhvcNAQEBA4GMADCBiAKBgOm9
-l/FoXbTIcEusk/QlS5YrlR04+oWIbSdZIf3GJBEWEUPljDxAX96qHsTcaVnGK+EP
-keU4cIZvdY+hzbqa5cc1j2/9IeJNejL8gpQ/ocyMM69yq5Ib2F8K4mGWm1xr30hU
-bYpY5D0MrZ1b0HtYFVc8KVAr0ADGG+pye0P9c3B/AgMBAAGjWjBYMAwGA1UdEwEB
-/wQCMAAwFAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsGAQUFBwMB
-MB0GA1UdDgQWBBTYgVB7kJnnm+jgX9DgrapzGfUmxjALBgkqhkiG9w0BAQUDgYEA
-GkadA2H8CAzU3w4oCGZu9Ry9Tj/9Agw1XMFKvoJuG7VLPk7+B25JvNFVsmpROLxO
-0TJ6mIU2hz5/rLvEfTBGQ+DYtbsjIxCz1fD7R5c1kKBtA0d0u8mY8pTlPNlxFPSW
-3ymx5DB2zyDa/HuX6m6/VmzMYmA0vp7Dp1cl+pA9Nhs=
------END CERTIFICATE-----
diff --git a/deps/libebb/examples/ca-key.pem b/deps/libebb/examples/ca-key.pem
deleted file mode 100644 (file)
index afb953d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQDpvZfxaF20yHBLrJP0JUuWK5UdOPqFiG0nWSH9xiQRFhFD5Yw8
-QF/eqh7E3GlZxivhD5HlOHCGb3WPoc26muXHNY9v/SHiTXoy/IKUP6HMjDOvcquS
-G9hfCuJhlptca99IVG2KWOQ9DK2dW9B7WBVXPClQK9AAxhvqcntD/XNwfwIDAQAB
-AoGAJqo3LTbfcV1KvinhG5zjwQaalwfq4RXtQHoNFmalZrIozvt01C6t7S5lApmX
-T8NpVMR3lNxeOM7NOqJAXuLqqVVqk81YEYuMx6E4gB/Ifl7jVZk1jstmLILhh59D
-pXrlpzvvm5X2hVsI7lp/YGAvtdLS1iVy37bGgmQWfCeeZiECQQDtZLfcJb4oE1yR
-ZfLOcPDlBCw02wGMNFpAjwbspf/du3Yn3ONWHVfhSCCcCe262h9PLblL97LoB+gF
-OHOlM9JvAkEA/A+U3/p9pwL4L742pxZP62/rmk6p5mZFIykk2jIUTpdilXBWBlcT
-OjgjnpquZpwnaClmvgFpkzdhIPF7Nq4K8QJBAITVKagOmnOUOeTF1fI78h9DkXTV
-4uzP0nxzS52ZWS16Gqg9ihuCecz97flB+Prn2EMWw6tFY58/5U0ehF85OxMCQQDF
-08TYdVSg+6emcPeb89sNwW18UjjuZ13j1qrhxWRCunXZK62YlEa27tCl7mjqh6w2
-CChm/9zIejJ1FJHLvJVBAkBj63ZbwggMYkxuj60jIBbNrEtDx9y7zM0sXkiJqcKp
-5uGtJNafG+yZrLAHE6/b4aqUOtGsCGsiZpT9ms7CoaVr
------END RSA PRIVATE KEY-----
diff --git a/deps/libebb/examples/hello_world.c b/deps/libebb/examples/hello_world.c
deleted file mode 100644 (file)
index bec0070..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <assert.h>
-
-#include <ev.h>
-#include "ebb.h"
-
-#define MSG ("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nhello world\n")
-static int c = 0;
-
-struct hello_connection {
-  unsigned int responses_to_write;
-};
-
-void on_close(ebb_connection *connection)
-{
-  free(connection->data);
-  free(connection);
-}
-
-static void continue_responding(ebb_connection *connection)
-{
-  int r;
-  struct hello_connection *connection_data = connection->data;
-  //printf("response complete \n");
-  if(--connection_data->responses_to_write > 0) {
-    /* write another response */
-    r = ebb_connection_write(connection, MSG, sizeof MSG, continue_responding);
-    assert(r);
-  } else {
-    ebb_connection_schedule_close(connection);
-  }
-}
-
-static void request_complete(ebb_request *request)
-{
-  //printf("request complete \n");
-  ebb_connection *connection = request->data;
-  struct hello_connection *connection_data = connection->data;
-
-  if(ebb_request_should_keep_alive(request))
-    connection_data->responses_to_write++;
-  else
-    connection_data->responses_to_write = 1;
-
-  ebb_connection_write(connection, MSG, sizeof MSG, continue_responding);
-  free(request);
-}
-
-static ebb_request* new_request(ebb_connection *connection)
-{
-  //printf("request %d\n", ++c);
-  ebb_request *request = malloc(sizeof(ebb_request));
-  ebb_request_init(request);
-  request->data = connection;
-  request->on_complete = request_complete;
-  return request;
-}
-
-ebb_connection* new_connection(ebb_server *server, struct sockaddr_in *addr)
-{
-  struct hello_connection *connection_data = malloc(sizeof(struct hello_connection));
-  if(connection_data == NULL)
-    return NULL;
-  connection_data->responses_to_write = 0;
-
-  ebb_connection *connection = malloc(sizeof(ebb_connection));
-  if(connection == NULL) {
-    free(connection_data);
-    return NULL;
-  }
-
-  ebb_connection_init(connection);
-  connection->data = connection_data;
-  connection->new_request = new_request;
-  connection->on_close = on_close;
-  
-  printf("connection: %d\n", c++);
-  return connection;
-}
-
-int main(int argc, char **_) 
-{
-  struct ev_loop *loop = ev_default_loop(0);
-  ebb_server server;
-
-  ebb_server_init(&server, loop);
-  if(argc > 1) {
-    printf("using SSL\n");
-    ebb_server_set_secure(&server, "ca-cert.pem", "ca-key.pem");
-  }
-  server.new_connection = new_connection;
-
-  printf("hello_world listening on port 5000\n");
-  ebb_server_listen_on_port(&server, 5000);
-  ev_loop(loop, 0);
-
-  return 0;
-}
diff --git a/deps/libebb/rbtree.c b/deps/libebb/rbtree.c
deleted file mode 100644 (file)
index 4a66972..0000000
+++ /dev/null
@@ -1,412 +0,0 @@
-/* Copyright (c) 2008 Derrick Coetzee
- * http://en.literateprograms.org/Red-black_tree_(C)?oldid=7982
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to permit
- * persons to whom the Software is furnished to do so, subject to the
- * following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
- * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
- * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "rbtree.h"
-#include <assert.h>
-
-#ifndef NULL
-# define NULL ((void*)0)
-#endif
-
-
-typedef rbtree_node node;
-typedef enum rbtree_node_color color;
-
-
-static node grandparent(node n);
-static node sibling(node n);
-static node uncle(node n);
-static void verify_properties(rbtree t);
-static void verify_property_1(node root);
-/* static void verify_property_2(node root); */
-static color node_color(node n);
-static void verify_property_4(node root);
-/* static void verify_property_5(node root); */
-static void verify_property_5_helper(node n, int black_count, int* black_count_path);
-
-static node lookup_node(rbtree t, void* key);
-static void rotate_left(rbtree t, node n);
-static void rotate_right(rbtree t, node n);
-
-static void replace_node(rbtree t, node oldn, node newn);
-static void insert_case1(rbtree t, node n);
-static void insert_case2(rbtree t, node n);
-static void insert_case3(rbtree t, node n);
-static void insert_case4(rbtree t, node n);
-static void insert_case5(rbtree t, node n);
-static node maximum_node(node root);
-static void delete_case1(rbtree t, node n);
-static void delete_case2(rbtree t, node n);
-static void delete_case3(rbtree t, node n);
-static void delete_case4(rbtree t, node n);
-static void delete_case5(rbtree t, node n);
-static void delete_case6(rbtree t, node n);
-
-node grandparent(node n) {
-    assert (n != NULL);
-    assert (n->parent != NULL); /* Not the root node */
-    assert (n->parent->parent != NULL); /* Not child of root */
-    return n->parent->parent;
-}
-
-node sibling(node n) {
-    assert (n != NULL);
-    assert (n->parent != NULL); /* Root node has no sibling */
-    if (n == n->parent->left)
-        return n->parent->right;
-    else
-        return n->parent->left;
-}
-
-node uncle(node n) {
-    assert (n != NULL);
-    assert (n->parent != NULL); /* Root node has no uncle */
-    assert (n->parent->parent != NULL); /* Children of root have no uncle */
-    return sibling(n->parent);
-}
-
-void verify_properties(rbtree t) {
-#ifdef VERIFY_RBTREE
-    verify_property_1(t->root);
-    verify_property_2(t->root);
-    /* Property 3 is implicit */
-    verify_property_4(t->root);
-    verify_property_5(t->root);
-#endif
-}
-
-void verify_property_1(node n) {
-    assert(node_color(n) == RED || node_color(n) == BLACK);
-    if (n == NULL) return;
-    verify_property_1(n->left);
-    verify_property_1(n->right);
-}
-
-/*
-void verify_property_2(node root) {
-    assert(node_color(root) == BLACK);
-}
-*/
-
-color node_color(node n) {
-    return n == NULL ? BLACK : n->color;
-}
-
-void verify_property_4(node n) {
-    if (node_color(n) == RED) {
-        assert (node_color(n->left)   == BLACK);
-        assert (node_color(n->right)  == BLACK);
-        assert (node_color(n->parent) == BLACK);
-    }
-    if (n == NULL) return;
-    verify_property_4(n->left);
-    verify_property_4(n->right);
-}
-
-/*
-void verify_property_5(node root) {
-    int black_count_path = -1;
-    verify_property_5_helper(root, 0, &black_count_path);
-}
-*/
-
-void verify_property_5_helper(node n, int black_count, int* path_black_count) {
-    if (node_color(n) == BLACK) {
-        black_count++;
-    }
-    if (n == NULL) {
-        if (*path_black_count == -1) {
-            *path_black_count = black_count;
-        } else {
-            assert (black_count == *path_black_count);
-        }
-        return;
-    }
-    verify_property_5_helper(n->left,  black_count, path_black_count);
-    verify_property_5_helper(n->right, black_count, path_black_count);
-}
-
-void rbtree_init(rbtree t, rbtree_compare_func compare) {
-    t->root = NULL;
-    t->compare = compare;
-    verify_properties(t);
-}
-
-node lookup_node(rbtree t, void* key) {
-    node n = t->root;
-    while (n != NULL) {
-        int comp_result = t->compare(key, n->key);
-        if (comp_result == 0) {
-            return n;
-        } else if (comp_result < 0) {
-            n = n->left;
-        } else {
-            assert(comp_result > 0);
-            n = n->right;
-        }
-    }
-    return n;
-}
-
-void* rbtree_lookup(rbtree t, void* key) {
-    node n = lookup_node(t, key);
-    return n == NULL ? NULL : n->value;
-}
-
-void rotate_left(rbtree t, node n) {
-    node r = n->right;
-    replace_node(t, n, r);
-    n->right = r->left;
-    if (r->left != NULL) {
-        r->left->parent = n;
-    }
-    r->left = n;
-    n->parent = r;
-}
-
-void rotate_right(rbtree t, node n) {
-    node L = n->left;
-    replace_node(t, n, L);
-    n->left = L->right;
-    if (L->right != NULL) {
-        L->right->parent = n;
-    }
-    L->right = n;
-    n->parent = L;
-}
-
-void replace_node(rbtree t, node oldn, node newn) {
-    if (oldn->parent == NULL) {
-        t->root = newn;
-    } else {
-        if (oldn == oldn->parent->left)
-            oldn->parent->left = newn;
-        else
-            oldn->parent->right = newn;
-    }
-    if (newn != NULL) {
-        newn->parent = oldn->parent;
-    }
-}
-
-void rbtree_insert(rbtree t, rbtree_node inserted_node) {
-    inserted_node->color = RED;
-    inserted_node->left = NULL;
-    inserted_node->right = NULL;
-    inserted_node->parent = NULL;
-
-    if (t->root == NULL) {
-        t->root = inserted_node;
-    } else {
-        node n = t->root;
-        while (1) {
-            int comp_result = t->compare(inserted_node->key, n->key);
-            if (comp_result == 0) {
-                n->value = inserted_node->value;
-                return;
-            } else if (comp_result < 0) {
-                if (n->left == NULL) {
-                    n->left = inserted_node;
-                    break;
-                } else {
-                    n = n->left;
-                }
-            } else {
-                assert (comp_result > 0);
-                if (n->right == NULL) {
-                    n->right = inserted_node;
-                    break;
-                } else {
-                    n = n->right;
-                }
-            }
-        }
-        inserted_node->parent = n;
-    }
-    insert_case1(t, inserted_node);
-    verify_properties(t);
-}
-
-void insert_case1(rbtree t, node n) {
-    if (n->parent == NULL)
-        n->color = BLACK;
-    else
-        insert_case2(t, n);
-}
-
-void insert_case2(rbtree t, node n) {
-    if (node_color(n->parent) == BLACK)
-        return; /* Tree is still valid */
-    else
-        insert_case3(t, n);
-}
-
-void insert_case3(rbtree t, node n) {
-    if (node_color(uncle(n)) == RED) {
-        n->parent->color = BLACK;
-        uncle(n)->color = BLACK;
-        grandparent(n)->color = RED;
-        insert_case1(t, grandparent(n));
-    } else {
-        insert_case4(t, n);
-    }
-}
-
-void insert_case4(rbtree t, node n) {
-    if (n == n->parent->right && n->parent == grandparent(n)->left) {
-        rotate_left(t, n->parent);
-        n = n->left;
-    } else if (n == n->parent->left && n->parent == grandparent(n)->right) {
-        rotate_right(t, n->parent);
-        n = n->right;
-    }
-    insert_case5(t, n);
-}
-
-void insert_case5(rbtree t, node n) {
-    n->parent->color = BLACK;
-    grandparent(n)->color = RED;
-    if (n == n->parent->left && n->parent == grandparent(n)->left) {
-        rotate_right(t, grandparent(n));
-    } else {
-        assert (n == n->parent->right && n->parent == grandparent(n)->right);
-        rotate_left(t, grandparent(n));
-    }
-}
-
-rbtree_node rbtree_delete(rbtree t, void* key) {
-    node child;
-    node n = lookup_node(t, key);
-    if (n == NULL) return NULL;  /* Key not found, do nothing */
-    if (n->left != NULL && n->right != NULL) {
-        /* Copy key/value from predecessor and then delete it instead */
-        node pred = maximum_node(n->left);
-        n->key   = pred->key;
-        n->value = pred->value;
-        n = pred;
-    }
-
-    assert(n->left == NULL || n->right == NULL);
-    child = n->right == NULL ? n->left  : n->right;
-    if (node_color(n) == BLACK) {
-        n->color = node_color(child);
-        delete_case1(t, n);
-    }
-    replace_node(t, n, child);
-
-    verify_properties(t);
-    return n;
-}
-
-static node maximum_node(node n) {
-    assert (n != NULL);
-    while (n->right != NULL) {
-        n = n->right;
-    }
-    return n;
-}
-
-void delete_case1(rbtree t, node n) {
-    if (n->parent == NULL)
-        return;
-    else
-        delete_case2(t, n);
-}
-
-void delete_case2(rbtree t, node n) {
-    if (node_color(sibling(n)) == RED) {
-        n->parent->color = RED;
-        sibling(n)->color = BLACK;
-        if (n == n->parent->left)
-            rotate_left(t, n->parent);
-        else
-            rotate_right(t, n->parent);
-    }
-    delete_case3(t, n);
-}
-
-void delete_case3(rbtree t, node n) {
-    if (node_color(n->parent) == BLACK &&
-        node_color(sibling(n)) == BLACK &&
-        node_color(sibling(n)->left) == BLACK &&
-        node_color(sibling(n)->right) == BLACK)
-    {
-        sibling(n)->color = RED;
-        delete_case1(t, n->parent);
-    }
-    else
-        delete_case4(t, n);
-}
-
-void delete_case4(rbtree t, node n) {
-    if (node_color(n->parent) == RED &&
-        node_color(sibling(n)) == BLACK &&
-        node_color(sibling(n)->left) == BLACK &&
-        node_color(sibling(n)->right) == BLACK)
-    {
-        sibling(n)->color = RED;
-        n->parent->color = BLACK;
-    }
-    else
-        delete_case5(t, n);
-}
-
-void delete_case5(rbtree t, node n) {
-    if (n == n->parent->left &&
-        node_color(sibling(n)) == BLACK &&
-        node_color(sibling(n)->left) == RED &&
-        node_color(sibling(n)->right) == BLACK)
-    {
-        sibling(n)->color = RED;
-        sibling(n)->left->color = BLACK;
-        rotate_right(t, sibling(n));
-    }
-    else if (n == n->parent->right &&
-             node_color(sibling(n)) == BLACK &&
-             node_color(sibling(n)->right) == RED &&
-             node_color(sibling(n)->left) == BLACK)
-    {
-        sibling(n)->color = RED;
-        sibling(n)->right->color = BLACK;
-        rotate_left(t, sibling(n));
-    }
-    delete_case6(t, n);
-}
-
-void delete_case6(rbtree t, node n) {
-    sibling(n)->color = node_color(n->parent);
-    n->parent->color = BLACK;
-    if (n == n->parent->left) {
-        assert (node_color(sibling(n)->right) == RED);
-        sibling(n)->right->color = BLACK;
-        rotate_left(t, n->parent);
-    }
-    else
-    {
-        assert (node_color(sibling(n)->left) == RED);
-        sibling(n)->left->color = BLACK;
-        rotate_right(t, n->parent);
-    }
-}
-
-
diff --git a/deps/libebb/rbtree.h b/deps/libebb/rbtree.h
deleted file mode 100644 (file)
index 5962a3c..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright (c) 2008 Derrick Coetzee
- * http://en.literateprograms.org/Red-black_tree_(C)?oldid=7982
- * Small changes by Ryah Dahl
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to permit
- * persons to whom the Software is furnished to do so, subject to the
- * following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
- * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
- * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _RBTREE_H_
-#define _RBTREE_H_
-
-enum rbtree_node_color { RED, BLACK };
-
-typedef int (*rbtree_compare_func)(void* left_key, void* right_key);
-
-typedef struct rbtree_node_t {
-    struct rbtree_node_t* left;    /* private */
-    struct rbtree_node_t* right;   /* private */
-    struct rbtree_node_t* parent;  /* private */
-    enum rbtree_node_color color;  /* private */
-    void* key;   /* public */
-    void* value; /* public */
-} *rbtree_node;
-
-typedef struct rbtree_t {
-    rbtree_node root;             /* private */
-    rbtree_compare_func compare;  /* private */
-} *rbtree;
-
-
-void rbtree_init(rbtree t, rbtree_compare_func);
-void* rbtree_lookup(rbtree t, void* key);
-void rbtree_insert(rbtree t, rbtree_node);
-/* you must free the returned node */
-rbtree_node rbtree_delete(rbtree t, void* key);
-
-#endif
-
diff --git a/deps/libebb/test_examples.rb b/deps/libebb/test_examples.rb
deleted file mode 100644 (file)
index 2af658c..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-require 'test/unit'
-require 'socket'
-
-REQ = "GET /hello/%d HTTP/1.1\r\n\r\n"
-HOST = '0.0.0.0'
-PORT = 5000
-
-class TCPSocket
-  def full_send(string)
-    written = 0
-    while(written < string.length) 
-      sent = write(string)
-      string = string.slice(sent, 10000)
-    end
-    written
-  end
-
-  def full_read
-    response = ""
-    while chunk = read(10000)
-      response += chunk
-    end
-    response
-  end
-
-end
-
-class EbbTest < Test::Unit::TestCase
-
-  def setup
-    @socket = TCPSocket.new(HOST, PORT)
-  end
-
-  def test_bad_req
-    @socket.full_send("hello")
-    assert_equal "", @socket.full_read
-    #assert @socket.closed?
-  end
-  
-  def test_single
-    written = 0
-    req = REQ % 1
-    @socket.full_send(req)
-    response = @socket.full_read()
-    count = 0
-    response.scan("hello world") { count += 1 }
-
-    assert_equal 1, count
-  end
-
-  def test_pipeline
-    written = 0
-    req = (REQ % 1) + (REQ % 2) + (REQ % 3) + (REQ % 4)
-    @socket.full_send(req)
-    response = @socket.full_read()
-    count = 0
-    response.scan("hello world") { count += 1 }
-    assert_equal 4, count
-  end
-end
diff --git a/deps/libebb/test_rbtree.c b/deps/libebb/test_rbtree.c
deleted file mode 100644 (file)
index f5ee1d6..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/* Copyright (c) 2008 Derrick Coetzee
- * http://en.literateprograms.org/Red-black_tree_(C)?oldid=7982
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to permit
- * persons to whom the Software is furnished to do so, subject to the
- * following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
- * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
- * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "rbtree.h"
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h> /* rand(), malloc(), free() */
-
-static int compare_int(void* left, void* right);
-static void print_tree(rbtree t);
-static void print_tree_helper(rbtree_node n, int indent);
-
-int compare_int(void* leftp, void* rightp) {
-    int left = (int)leftp;
-    int right = (int)rightp;
-    if (left < right) 
-        return -1;
-    else if (left > right)
-        return 1;
-    else {
-        assert (left == right);
-        return 0;
-    }
-}
-
-#define INDENT_STEP  4
-
-void print_tree_helper(rbtree_node n, int indent);
-
-void print_tree(rbtree t) {
-    print_tree_helper(t->root, 0);
-    puts("");
-}
-
-void print_tree_helper(rbtree_node n, int indent) {
-    int i;
-    if (n == NULL) {
-        fputs("<empty tree>", stdout);
-        return;
-    }
-    if (n->right != NULL) {
-        print_tree_helper(n->right, indent + INDENT_STEP);
-    }
-    for(i=0; i<indent; i++)
-        fputs(" ", stdout);
-    if (n->color == BLACK)
-        printf("%d\n", (int)n->key);
-    else
-        printf("<%d>\n", (int)n->key);
-    if (n->left != NULL) {
-        print_tree_helper(n->left, indent + INDENT_STEP);
-    }
-}
-
-int main() {
-    int i;
-    struct rbtree_t t;
-    rbtree_init(&t, compare_int); 
-    print_tree(&t);
-
-    for(i=0; i<5000; i++) {
-        int x = rand() % 10000;
-        int y = rand() % 10000;
-#ifdef TRACE
-        print_tree(&t);
-        printf("Inserting %d -> %d\n\n", x, y);
-#endif
-        rbtree_node node = (rbtree_node) malloc(sizeof(struct rbtree_node_t));
-        node->key = (void*)x;
-        node->value = (void*)y;
-        rbtree_insert(&t, node);
-        assert(rbtree_lookup(&t, (void*)x) == (void*)y);
-    }
-    for(i=0; i<60000; i++) {
-        int x = rand() % 10000;
-#ifdef TRACE
-        print_tree(&t);
-        printf("Deleting key %d\n\n", x);
-#endif
-        rbtree_node n = rbtree_delete(&t, (void*)x);
-        if(n != NULL) {
-            free(n);
-        }
-    }
-    printf("Okay\n");
-    return 0;
-}
-
diff --git a/deps/libebb/test_request_parser.c b/deps/libebb/test_request_parser.c
deleted file mode 100644 (file)
index 5a5dca3..0000000
+++ /dev/null
@@ -1,746 +0,0 @@
-/* unit tests for request parser
- * Copyright 2008 ryah dahl, ry@ndahl.us
- *
- * This software may be distributed under the "MIT" license included in the
- * README
- */
-#include "ebb_request_parser.h"
-#include <stdlib.h>
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#define TRUE 1
-#define FALSE 0
-
-#define MAX_HEADERS 500
-#define MAX_ELEMENT_SIZE 500
-
-static ebb_request_parser parser;
-struct request_data {
-  const char *raw;
-  int request_method;
-  char request_path[MAX_ELEMENT_SIZE];
-  char request_uri[MAX_ELEMENT_SIZE];
-  char fragment[MAX_ELEMENT_SIZE];
-  char query_string[MAX_ELEMENT_SIZE];
-  char body[MAX_ELEMENT_SIZE];
-  int num_headers;
-  char header_fields[MAX_HEADERS][MAX_ELEMENT_SIZE];
-  char header_values[MAX_HEADERS][MAX_ELEMENT_SIZE];
-  int should_keep_alive;
-  ebb_request request;
-};
-static struct request_data requests[5];
-static int num_requests;
-
-const struct request_data curl_get = 
-  { raw: "GET /test HTTP/1.1\r\n"
-         "User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n"
-         "Host: 0.0.0.0:5000\r\n"
-         "Accept: */*\r\n"
-         "\r\n"
-  , should_keep_alive: TRUE
-  , request_method: EBB_GET
-  , query_string: ""
-  , fragment: ""
-  , request_path: "/test"
-  , request_uri: "/test"
-  , num_headers: 3
-  , header_fields: { "User-Agent", "Host", "Accept" }
-  , header_values: { "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1", "0.0.0.0:5000", "*/*" }
-  , body: ""
-  };
-
-const struct request_data firefox_get = 
-  { raw: "GET /favicon.ico HTTP/1.1\r\n"
-         "Host: 0.0.0.0:5000\r\n"
-         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n"
-         "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
-         "Accept-Language: en-us,en;q=0.5\r\n"
-         "Accept-Encoding: gzip,deflate\r\n"
-         "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
-         "Keep-Alive: 300\r\n"
-         "Connection: keep-alive\r\n"
-         "\r\n"
-  , should_keep_alive: TRUE
-  , request_method: EBB_GET
-  , query_string: ""
-  , fragment: ""
-  , request_path: "/favicon.ico"
-  , request_uri: "/favicon.ico"
-  , num_headers: 8
-  , header_fields: 
-    { "Host"
-    , "User-Agent"
-    , "Accept"
-    , "Accept-Language"
-    , "Accept-Encoding"
-    , "Accept-Charset"
-    , "Keep-Alive"
-    , "Connection" 
-    }
-  , header_values: 
-    { "0.0.0.0:5000"
-    , "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0"
-    , "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
-    , "en-us,en;q=0.5"
-    , "gzip,deflate"
-    , "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
-    , "300"
-    , "keep-alive"
-    }
-  , body: ""
-  };
-
-const struct request_data dumbfuck =
-  { raw: "GET /dumbfuck HTTP/1.1\r\n"
-         "aaaaaaaaaaaaa:++++++++++\r\n"
-         "\r\n"
-  , should_keep_alive: TRUE
-  , request_method: EBB_GET
-  , query_string: ""
-  , fragment: ""
-  , request_path: "/dumbfuck"
-  , request_uri: "/dumbfuck"
-  , num_headers: 1
-  , header_fields: { "aaaaaaaaaaaaa" }
-  , header_values: {  "++++++++++" }
-  , body: ""
-  };
-
-const struct request_data fragment_in_uri = 
-  { raw: "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n"
-         "\r\n"
-  , should_keep_alive: TRUE
-  , request_method: EBB_GET
-  , query_string: "page=1"
-  , fragment: "posts-17408"
-  , request_path: "/forums/1/topics/2375"
-  /* XXX request uri does not include fragment? */
-  , request_uri: "/forums/1/topics/2375?page=1" 
-  , num_headers: 0
-  , body: ""
-  };
-
-
-// get - no headers - no body
-const struct request_data get_no_headers_no_body =  
-  { raw: "GET /get_no_headers_no_body/world HTTP/1.1\r\n"
-         "\r\n"
-  , should_keep_alive: TRUE
-  , request_method: EBB_GET
-  , query_string: ""
-  , fragment: ""
-  , request_path: "/get_no_headers_no_body/world"
-  , request_uri: "/get_no_headers_no_body/world"
-  , num_headers: 0
-  , body: ""
-  };
-
-// get - one header - no body
-const struct request_data get_one_header_no_body =  
-  { raw: "GET /get_one_header_no_body HTTP/1.1\r\n"
-         "Accept: */*\r\n"
-         "\r\n"
-  , should_keep_alive: TRUE
-  , request_method: EBB_GET
-  , query_string: ""
-  , fragment: ""
-  , request_path: "/get_one_header_no_body"
-  , request_uri: "/get_one_header_no_body"
-  , num_headers: 1
-  , header_fields: { "Accept" }
-  , header_values: { "*/*" }
-  , body: ""
-  };
-
-// get - no headers - body "HELLO"
-const struct request_data get_funky_content_length_body_hello =  
-  { raw: "GET /get_funky_content_length_body_hello HTTP/1.0\r\n"
-         "conTENT-Length: 5\r\n"
-         "\r\n"
-         "HELLO"
-  , should_keep_alive: FALSE
-  , request_method: EBB_GET
-  , query_string: ""
-  , fragment: ""
-  , request_path: "/get_funky_content_length_body_hello"
-  , request_uri: "/get_funky_content_length_body_hello"
-  , num_headers: 1
-  , header_fields: { "conTENT-Length" }
-  , header_values: { "5" }
-  , body: "HELLO"
-  };
-
-// post - one header - body "World"
-const struct request_data post_identity_body_world =  
-  { raw: "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n"
-         "Accept: */*\r\n"
-         "Transfer-Encoding: identity\r\n"
-         "Content-Length: 5\r\n"
-         "\r\n"
-         "World"
-  , should_keep_alive: TRUE
-  , request_method: EBB_POST
-  , query_string: "q=search"
-  , fragment: "hey"
-  , request_path: "/post_identity_body_world"
-  , request_uri: "/post_identity_body_world?q=search"
-  , num_headers: 3
-  , header_fields: { "Accept", "Transfer-Encoding", "Content-Length" }
-  , header_values: { "*/*", "identity", "5" }
-  , body: "World"
-  };
-
-// post - no headers - chunked body "all your base are belong to us"
-const struct request_data post_chunked_all_your_base =  
-  { raw: "POST /post_chunked_all_your_base HTTP/1.1\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "1e\r\nall your base are belong to us\r\n"
-         "0\r\n"
-         "\r\n"
-  , should_keep_alive: TRUE
-  , request_method: EBB_POST
-  , query_string: ""
-  , fragment: ""
-  , request_path: "/post_chunked_all_your_base"
-  , request_uri: "/post_chunked_all_your_base"
-  , num_headers: 1
-  , header_fields: { "Transfer-Encoding" }
-  , header_values: { "chunked" }
-  , body: "all your base are belong to us"
-  };
-
-// two chunks ; triple zero ending
-const struct request_data two_chunks_mult_zero_end =  
-  { raw: "POST /two_chunks_mult_zero_end HTTP/1.1\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "5\r\nhello\r\n"
-         "6\r\n world\r\n"
-         "000\r\n"
-         "\r\n"
-  , should_keep_alive: TRUE
-  , request_method: EBB_POST
-  , query_string: ""
-  , fragment: ""
-  , request_path: "/two_chunks_mult_zero_end"
-  , request_uri: "/two_chunks_mult_zero_end"
-  , num_headers: 1
-  , header_fields: { "Transfer-Encoding" }
-  , header_values: { "chunked" }
-  , body: "hello world"
-  };
-
-
-// chunked with trailing headers. blech.
-const struct request_data chunked_w_trailing_headers =  
-  { raw: "POST /chunked_w_trailing_headers HTTP/1.1\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "5\r\nhello\r\n"
-         "6\r\n world\r\n"
-         "0\r\n"
-         "Vary: *\r\n"
-         "Content-Type: text/plain\r\n"
-         "\r\n"
-  , should_keep_alive: TRUE
-  , request_method: EBB_POST
-  , query_string: ""
-  , fragment: ""
-  , request_path: "/chunked_w_trailing_headers"
-  , request_uri: "/chunked_w_trailing_headers"
-  , num_headers: 1
-  , header_fields: { "Transfer-Encoding" }
-  , header_values: { "chunked" }
-  , body: "hello world"
-  };
-
-// with bullshit after the length
-const struct request_data chunked_w_bullshit_after_length =  
-  { raw: "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n"
-         "6; blahblah; blah\r\n world\r\n"
-         "0\r\n"
-         "\r\n"
-  , should_keep_alive: TRUE
-  , request_method: EBB_POST
-  , query_string: ""
-  , fragment: ""
-  , request_path: "/chunked_w_bullshit_after_length"
-  , request_uri: "/chunked_w_bullshit_after_length"
-  , num_headers: 1
-  , header_fields: { "Transfer-Encoding" }
-  , header_values: { "chunked" }
-  , body: "hello world"
-  };
-
-const struct request_data *fixtures[] =
-  { &curl_get 
-  , &firefox_get 
-  , &dumbfuck
-  , &fragment_in_uri 
-  , &get_no_headers_no_body  
-  , &get_one_header_no_body  
-  , &get_funky_content_length_body_hello  
-  , &post_identity_body_world  
-  , &post_chunked_all_your_base  
-  , &two_chunks_mult_zero_end  
-  , &chunked_w_trailing_headers  
-  , &chunked_w_bullshit_after_length  
-  , NULL
-  };
-
-
-int request_data_eq
-  ( struct request_data *r1
-  , const struct request_data *r2
-  )
-{ 
-  if(ebb_request_should_keep_alive(&r1->request) != r2->should_keep_alive) {
-    printf("requests disagree on keep-alive");
-    return FALSE;
-  }
-
-  if(0 != strcmp(r1->body, r2->body)) {
-    printf("body '%s' != '%s'\n", r1->body, r2->body);
-    return FALSE;
-  }
-  if(0 != strcmp(r1->fragment, r2->fragment)) {
-    printf("fragment '%s' != '%s'\n", r1->fragment, r2->fragment);
-    return FALSE;
-  }
-  if(0 != strcmp(r1->query_string, r2->query_string)) {
-    printf("query_string '%s' != '%s'\n", r1->query_string, r2->query_string);
-    return FALSE;
-  }
-  if(r1->request.method != r2->request_method) {
-    printf("request_method '%d' != '%d'\n", r1->request.method, r2->request_method);
-    return FALSE;
-  }
-  if(0 != strcmp(r1->request_path, r2->request_path)) {
-    printf("request_path '%s' != '%s'\n", r1->request_path, r2->request_path);
-    return FALSE;
-  }
-  if(0 != strcmp(r1->request_uri, r2->request_uri)) {
-    printf("request_uri '%s' != '%s'\n", r1->request_uri, r2->request_uri);
-    return FALSE;
-  }
-  if(r1->num_headers != r2->num_headers) {
-    printf("num_headers '%d' != '%d'\n", r1->num_headers, r2->num_headers);
-    return FALSE;
-  }
-  int i;
-  for(i = 0; i < r1->num_headers; i++) {
-    if(0 != strcmp(r1->header_fields[i], r2->header_fields[i])) {
-      printf("header field '%s' != '%s'\n", r1->header_fields[i], r2->header_fields[i]);
-      return FALSE;
-    }
-    if(0 != strcmp(r1->header_values[i], r2->header_values[i])) {
-      printf("header field '%s' != '%s'\n", r1->header_values[i], r2->header_values[i]);
-      return FALSE;
-    }
-  }
-  return TRUE;
-}
-
-int request_eq
-  ( int index
-  , const struct request_data *expected
-  )
-{
-  return request_data_eq(&requests[index], expected);
-}
-
-void request_complete(ebb_request *info)
-{
-  num_requests++;
-}
-
-void request_path_cb(ebb_request *request, const char *p, size_t len)
-{
-  strncat(requests[num_requests].request_path, p, len);
-}
-
-void request_uri_cb(ebb_request *request, const char *p, size_t len)
-{
-  strncat(requests[num_requests].request_uri, p, len);
-}
-
-void query_string_cb(ebb_request *request, const char *p, size_t len)
-{
-  strncat(requests[num_requests].query_string, p, len);
-}
-
-void fragment_cb(ebb_request *request, const char *p, size_t len)
-{
-  strncat(requests[num_requests].fragment, p, len);
-}
-
-void header_field_cb(ebb_request *request, const char *p, size_t len, int header_index)
-{
-  strncat(requests[num_requests].header_fields[header_index], p, len);
-}
-
-void header_value_cb(ebb_request *request, const char *p, size_t len, int header_index)
-{
-  strncat(requests[num_requests].header_values[header_index], p, len);
-  requests[num_requests].num_headers = header_index + 1;
-}
-
-void body_handler(ebb_request *request, const char *p, size_t len)
-{
-  strncat(requests[num_requests].body, p, len);
- // printf("body_handler: '%s'\n", requests[num_requests].body);
-}
-
-ebb_request* new_request ()
-{
-  requests[num_requests].num_headers = 0;
-  requests[num_requests].request_method = -1;
-  requests[num_requests].request_path[0] = 0;
-  requests[num_requests].request_uri[0] = 0;
-  requests[num_requests].fragment[0] = 0;
-  requests[num_requests].query_string[0] = 0;
-  requests[num_requests].body[0] = 0;
-  int i; 
-  for(i = 0; i < MAX_HEADERS; i++) {
-    requests[num_requests].header_fields[i][0] = 0;
-    requests[num_requests].header_values[i][0] = 0;
-  }
-    
-  ebb_request *r = &requests[num_requests].request;
-  ebb_request_init(r);
-
-  r->on_complete = request_complete;
-  r->on_header_field = header_field_cb;
-  r->on_header_value = header_value_cb;
-  r->on_path = request_path_cb;
-  r->on_uri = request_uri_cb;
-  r->on_fragment = fragment_cb;
-  r->on_query_string = query_string_cb;
-  r->on_body = body_handler;
-  r->on_headers_complete = NULL;
-
-  r->data = &requests[num_requests];
- // printf("new request %d\n", num_requests);
-  return r;
-}
-
-void parser_init()
-{
-  num_requests = 0;
-
-  ebb_request_parser_init(&parser);
-
-  parser.new_request = new_request;
-}
-
-int test_request
-  ( const struct request_data *request_data
-  )
-{
-  size_t traversed = 0;
-  parser_init();
-
-  traversed = ebb_request_parser_execute( &parser
-                                        , request_data->raw 
-                                        , strlen(request_data->raw)
-                                        );
-  if( ebb_request_parser_has_error(&parser) )
-    return FALSE;
-  if(! ebb_request_parser_is_finished(&parser) )
-    return FALSE;
-  if(num_requests != 1)
-    return FALSE;
-
-  return request_eq(0, request_data);
-}
-
-int test_error
-  ( const char *buf
-  )
-{
-  size_t traversed = 0;
-  parser_init();
-
-  traversed = ebb_request_parser_execute(&parser, buf, strlen(buf));
-
-  return ebb_request_parser_has_error(&parser);
-}
-
-
-int test_multiple3
-  ( const struct request_data *r1
-  , const struct request_data *r2
-  , const struct request_data *r3
-  )
-{
-  char total[80*1024] = "\0";
-
-  strcat(total, r1->raw); 
-  strcat(total, r2->raw); 
-  strcat(total, r3->raw); 
-
-  size_t traversed = 0;
-  parser_init();
-
-  traversed = ebb_request_parser_execute(&parser, total, strlen(total));
-
-
-  if( ebb_request_parser_has_error(&parser) )
-    return FALSE;
-  if(! ebb_request_parser_is_finished(&parser) )
-    return FALSE;
-  if(num_requests != 3)
-    return FALSE;
-
-  if(!request_eq(0, r1)){
-    printf("request 1 error.\n");
-    return FALSE;
-  }
-  if(!request_eq(1, r2)){
-    printf("request 2 error.\n");
-    return FALSE;
-  }
-  if(!request_eq(2, r3)){
-    printf("request 3 error.\n");
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-/**
- * SCAN through every possible breaking to make sure the 
- * parser can handle getting the content in any chunks that
- * might come from the socket
- */
-int test_scan2
-  ( const struct request_data *r1
-  , const struct request_data *r2
-  , const struct request_data *r3
-  )
-{
-  char total[80*1024] = "\0";
-  char buf1[80*1024] = "\0";
-  char buf2[80*1024] = "\0";
-
-  strcat(total, r1->raw); 
-  strcat(total, r2->raw); 
-  strcat(total, r3->raw); 
-
-  int total_len = strlen(total);
-
-  //printf("total_len = %d\n", total_len);
-  int i;
-  for(i = 1; i < total_len - 1; i ++ ) {
-
-    parser_init();
-
-    int buf1_len = i;
-    strncpy(buf1, total, buf1_len);
-    buf1[buf1_len] = 0;
-
-    int buf2_len = total_len - i;
-    strncpy(buf2, total+i, buf2_len);
-    buf2[buf2_len] = 0;
-
-    ebb_request_parser_execute(&parser, buf1, buf1_len);
-
-    if( ebb_request_parser_has_error(&parser) ) {
-      return FALSE;
-    }
-    /*
-    if(ebb_request_parser_is_finished(&parser)) 
-      return FALSE;
-    */
-
-    ebb_request_parser_execute(&parser, buf2, buf2_len);
-
-    if( ebb_request_parser_has_error(&parser))
-      return FALSE;
-    if(!ebb_request_parser_is_finished(&parser)) 
-      return FALSE;
-
-    if(3 != num_requests) {
-      printf("scan error: got %d requests in iteration %d\n", num_requests, i);
-      return FALSE;
-    }
-
-    if(!request_eq(0, r1)) {
-      printf("not maching r1\n");
-      return FALSE;
-    }
-    if(!request_eq(1, r2)) {
-      printf("not maching r2\n");
-      return FALSE;
-    }
-    if(!request_eq(2, r3)) {
-      printf("not maching r3\n");
-      return FALSE;
-    }
-  }
-  return TRUE;
-}
-
-int test_scan3
-  ( const struct request_data *r1
-  , const struct request_data *r2
-  , const struct request_data *r3
-  )
-{
-  char total[80*1024] = "\0";
-  char buf1[80*1024] = "\0";
-  char buf2[80*1024] = "\0";
-  char buf3[80*1024] = "\0";
-
-  strcat(total, r1->raw); 
-  strcat(total, r2->raw); 
-  strcat(total, r3->raw); 
-
-  int total_len = strlen(total);
-
-  //printf("total_len = %d\n", total_len);
-  int i,j;
-  for(j = 2; j < total_len - 1; j ++ ) {
-    for(i = 1; i < j; i ++ ) {
-
-      parser_init();
-
-
-
-
-      int buf1_len = i;
-      strncpy(buf1, total, buf1_len);
-      buf1[buf1_len] = 0;
-
-      int buf2_len = j - i;
-      strncpy(buf2, total+i, buf2_len);
-      buf2[buf2_len] = 0;
-
-      int buf3_len = total_len - j;
-      strncpy(buf3, total+j, buf3_len);
-      buf3[buf3_len] = 0;
-
-      /*
-      printf("buf1: %s - %d\n", buf1, buf1_len);
-      printf("buf2: %s - %d \n", buf2, buf2_len );
-      printf("buf3: %s - %d\n\n", buf3, buf3_len);
-      */
-
-      ebb_request_parser_execute(&parser, buf1, buf1_len);
-
-      if( ebb_request_parser_has_error(&parser) ) {
-        return FALSE;
-      }
-
-      ebb_request_parser_execute(&parser, buf2, buf2_len);
-
-      if( ebb_request_parser_has_error(&parser) ) {
-        return FALSE;
-      }
-
-      ebb_request_parser_execute(&parser, buf3, buf3_len);
-
-      if( ebb_request_parser_has_error(&parser))
-        return FALSE;
-      if(!ebb_request_parser_is_finished(&parser)) 
-        return FALSE;
-
-      if(3 != num_requests) {
-        printf("scan error: only got %d requests in iteration %d\n", num_requests, i);
-        return FALSE;
-      }
-
-      if(!request_eq(0, r1)) {
-        printf("not maching r1\n");
-        return FALSE;
-      }
-      if(!request_eq(1, r2)) {
-        printf("not maching r2\n");
-        return FALSE;
-      }
-      if(!request_eq(2, r3)) {
-        printf("not maching r3\n");
-        return FALSE;
-      }
-    }
-  }
-  return TRUE;
-}
-
-int main() 
-{
-
-  assert(test_error("hello world"));
-  assert(test_error("GET / HTP/1.1\r\n\r\n"));
-
-  assert(test_request(&curl_get));
-  assert(test_request(&firefox_get));
-
-  // Zed's header tests
-
-  assert(test_request(&dumbfuck));
-
-  const char *dumbfuck2 = "GET / HTTP/1.1\r\nX-SSL-Bullshit:   -----BEGIN CERTIFICATE-----\r\n\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgEBBAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n\tRA==\r\n\t-----END CERTIFICATE-----\r\n\r\n";
-  assert(test_error(dumbfuck2));
-
-  assert(test_request(&fragment_in_uri));
-
-  /* TODO sending junk and large headers gets rejected */
-
-
-  /* check to make sure our predefined requests are okay */
-
-  assert(test_request(&get_no_headers_no_body));
-  assert(test_request(&get_one_header_no_body));
-  assert(test_request(&get_no_headers_no_body));
-
-  // no content-length
-  const char *bad_get_no_headers_no_body = "GET /bad_get_no_headers_no_body/world HTTP/1.1\r\nAccept: */*\r\nHELLO\r\n";
-  assert(test_error(bad_get_no_headers_no_body)); // error if there is a body without content length
-
-  assert(test_request(&get_funky_content_length_body_hello));
-  assert(test_request(&post_identity_body_world));
-  assert(test_request(&post_chunked_all_your_base));
-  assert(test_request(&two_chunks_mult_zero_end));
-  assert(test_request(&chunked_w_trailing_headers));
-
-  assert(test_request(&chunked_w_bullshit_after_length));
-  assert(1 == requests[0].request.version_major); 
-  assert(1 == requests[0].request.version_minor);
-
-  // three requests - no bodies
-  assert( test_multiple3( &get_no_headers_no_body
-                        , &get_one_header_no_body
-                        , &get_no_headers_no_body
-                        ));
-
-  // three requests - one body
-  assert( test_multiple3(&get_no_headers_no_body, &get_funky_content_length_body_hello, &get_no_headers_no_body));
-
-  // three requests with bodies -- last is chunked
-  assert( test_multiple3(&get_funky_content_length_body_hello, &post_identity_body_world, &post_chunked_all_your_base));
-
-  // three chunked requests
-  assert( test_multiple3(&two_chunks_mult_zero_end, &post_chunked_all_your_base, &chunked_w_trailing_headers));
-
-
-  assert(test_scan2(&get_no_headers_no_body, &get_one_header_no_body, &get_no_headers_no_body));
-  assert(test_scan2(&get_funky_content_length_body_hello, &post_identity_body_world, &post_chunked_all_your_base));
-  assert(test_scan2(&two_chunks_mult_zero_end, &chunked_w_trailing_headers, &chunked_w_bullshit_after_length));
-
-  assert(test_scan3(&get_no_headers_no_body, &get_one_header_no_body, &get_no_headers_no_body));
-  assert(test_scan3(&get_funky_content_length_body_hello, &post_identity_body_world, &post_chunked_all_your_base));
-  assert(test_scan3(&two_chunks_mult_zero_end, &chunked_w_trailing_headers, &chunked_w_bullshit_after_length));
-
-
-  printf("okay\n");
-  return 0;
-}
-
diff --git a/ragel.py b/ragel.py
deleted file mode 100644 (file)
index 3bb96ac..0000000
--- a/ragel.py
+++ /dev/null
@@ -1,35 +0,0 @@
-#! /usr/bin/env python
-# encoding: utf-8
-
-"Ragel: '.rl' files are converted into .c files using 'ragel': {.rl -> .c -> .o}"
-
-import TaskGen, Task, Runner
-
-
-def rageltaskfun(task):
-       env = task.env
-       ragelbin = env.get_flat('RAGEL')
-       if ragelbin:
-               if task.inputs[0].srcpath(env) == '../src/config_parser.rl':
-                       cmd = '%s -o %s -C -T0 %s' % (ragelbin, task.outputs[0].bldpath(env), task.inputs[0].srcpath(env))
-               else:
-                       cmd = '%s -o %s -C -T1 %s' % (ragelbin, task.outputs[0].bldpath(env), task.inputs[0].srcpath(env))
-       else:
-               src = task.inputs[0].srcpath(env)
-               src = src[:src.rfind('.')] + '.c'
-               cmd = 'cp %s %s' % (src, task.outputs[0].bldpath(env))
-       return task.generator.bld.exec_command(cmd)
-
-rageltask = Task.task_type_from_func('ragel', rageltaskfun, vars = ['RAGEL'], color = 'BLUE', ext_in = '.rl', ext_out = '.c', before = 'c')
-
-@TaskGen.extension('.rl')
-@TaskGen.before('apply_core')
-def ragel(self, node):
-       out = node.change_ext('.c')
-       self.allnodes.append(out)
-       tsk = self.create_task('ragel')
-       tsk.set_inputs(node)
-       tsk.set_outputs(out)
-
-def detect(conf):
-       dang = conf.find_program('ragel', var='RAGEL')
index a162fa05fff0f6558a6c3dd16da5bfcbaecdab29..6c699b3fb9d6a071fbc769a6e35f798496b2829f 100644 (file)
 #include "node.h"
 #include "http.h"
-
-#include <oi_socket.h>
-#include <ebb_request_parser.h>
-
-#include <string>
-#include <list>
+#include <http_parser.h>
 
 #include <assert.h>
+#include <stdio.h>
 
 using namespace v8;
+using namespace node;
 using namespace std;
 
-static Persistent<ObjectTemplate> request_template;
-
-// globals
-static Persistent<String> path_str; 
-static Persistent<String> uri_str; 
-static Persistent<String> query_string_str; 
-static Persistent<String> fragment_str; 
-static Persistent<String> method_str; 
-static Persistent<String> http_version_str; 
-static Persistent<String> headers_str; 
-
-static Persistent<String> on_request_str; 
-static Persistent<String> on_body_str; 
-static Persistent<String> respond_str; 
-
-static Persistent<String> copy_str;
-static Persistent<String> delete_str;
-static Persistent<String> get_str;
-static Persistent<String> head_str;
-static Persistent<String> lock_str;
-static Persistent<String> mkcol_str;
-static Persistent<String> move_str;
-static Persistent<String> options_str;
-static Persistent<String> post_str;
-static Persistent<String> propfind_str;
-static Persistent<String> proppatch_str;
-static Persistent<String> put_str;
-static Persistent<String> trace_str;
-static Persistent<String> unlock_str;
-
-#define INVALID_STATE_ERR 1
-
-class HttpServer {
-public:
-  HttpServer (Handle<Object> _js_server);
-  ~HttpServer ();
-
-  int Start(struct addrinfo *servinfo);
-  void Stop();
-
-  Handle<Value> Callback()
-  {
-    HandleScope scope;
-    Handle<Value> value = js_server->Get(on_request_str);
-    return scope.Close(value);
-  }
-
-private:
-  oi_server server;
-  Persistent<Object> js_server;
-};
-
-class HttpRequest;
-
-class Connection {
-public:
-  Connection();
-  ~Connection();
-
-  void Parse(const void *buf, size_t count);
-  void Write();
-  void Close();
-  void AddRequest (HttpRequest *request);
-
-  oi_socket socket;
-  Persistent<Function> js_onrequest;
-
-private:
-  ebb_request_parser parser;
-  list<HttpRequest*> requests;
-  list<HttpRequest*> finished_requests;
-  friend class HttpServer;
-};
-
-class HttpRequest {
- public:
-  HttpRequest (Connection &c);
-  /* Deleted from C++ as soon as possible.
-   * Javascript object might linger. This is okay
-   */
-  ~HttpRequest();
-
-  void MakeBodyCallback (const char *base, size_t length);
-  Local<Object> CreateJSObject ();
-  void Respond (Handle<Value> data);
-
-  string path;
-  string query_string;
-  string fragment;
-  string uri;
-
-  list<string> header_fields;
-  list<string> header_values;
-
-  Connection &connection;
-  ebb_request parser_info;
-
-  list<oi_buf*> output;
-  bool done;
-  Persistent<Object> js_object;
-};
-
-static Handle<Value>
-GetMethodString (int method)
-{
-  switch(method) {
-    case EBB_COPY:      return copy_str;
-    case EBB_DELETE:    return delete_str;
-    case EBB_GET:       return get_str;
-    case EBB_HEAD:      return head_str;
-    case EBB_LOCK:      return lock_str;
-    case EBB_MKCOL:     return mkcol_str;
-    case EBB_MOVE:      return move_str;
-    case EBB_OPTIONS:   return options_str;
-    case EBB_POST:      return post_str;
-    case EBB_PROPFIND:  return propfind_str;
-    case EBB_PROPPATCH: return proppatch_str;
-    case EBB_PUT:       return put_str;
-    case EBB_TRACE:     return trace_str;
-    case EBB_UNLOCK:    return unlock_str;
-  }
-  return Null();
-}
-
-static Handle<Value>
-RespondCallback (const Arguments& args) 
-{
-  HandleScope scope;
-
-  Handle<Value> v = args.Holder()->GetInternalField(0);
-  if(v->IsUndefined()) {
-    // check that args.Holder()->GetInternalField(0)
-    // is not NULL if so raise INVALID_STATE_ERR
-    printf("null request external\n");
-    ThrowException(Integer::New(INVALID_STATE_ERR)); 
-    return Undefined();
-  }
-  Handle<External> field = Handle<External>::Cast(v);
-  HttpRequest* request = static_cast<HttpRequest*>(field->Value());
-  request->Respond(args[0]);
-  return Undefined();
-}
-
 void
-HttpRequest::Respond (Handle<Value> data)
-{
-  if(data == Null()) {
-    done = true;
-  } else {
-    Handle<String> s = data->ToString();
-
-    size_t l1 = s->Utf8Length(), l2;
-    oi_buf *buf = oi_buf_new2(l1);
-    l2 = s->WriteUtf8(buf->base, l1);
-    assert(l1 == l2);
-
-    output.push_back(buf);
-  }
-  connection.Write();
-}
-
-
-static void
-on_path (ebb_request *req, const char *buf, size_t len)
-{
-  HttpRequest *request = static_cast<HttpRequest*> (req->data);
-  request->path.append(buf, len);
-}
-
-static void
-on_uri (ebb_request *req, const char *buf, size_t len)
-{
-  HttpRequest *request = static_cast<HttpRequest*> (req->data);
-  request->uri.append(buf, len);
-}
-
-static void
-on_query_string (ebb_request *req, const char *buf, size_t len)
-{
-  HttpRequest *request = static_cast<HttpRequest*> (req->data);
-  request->query_string.append(buf, len);
-}
-
-static void
-on_fragment (ebb_request *req, const char *buf, size_t len)
-{
-  HttpRequest *request = static_cast<HttpRequest*> (req->data);
-  request->fragment.append(buf, len);
-}
-
-static const char upcase[] =
-  "\0______________________________"
-  "_________________0123456789_____"
-  "__ABCDEFGHIJKLMNOPQRSTUVWXYZ____"
-  "__ABCDEFGHIJKLMNOPQRSTUVWXYZ____"
-  "________________________________"
-  "________________________________"
-  "________________________________"
-  "________________________________";
-
-static void
-on_header_field (ebb_request *req, const char *buf, size_t len, int header_index)
+HTTPClient::Initialize (Handle<Object> target)
 {
-  HttpRequest *request = static_cast<HttpRequest*> (req->data);
-
-  char upbuf[len];
-
-  for(int i = 0; i < len; i++) 
-    upbuf[i] = upcase[buf[i]];
-
-  if( request->header_fields.size() == header_index - 1) {
-    request->header_fields.back().append(upbuf, len);
-  } else { 
-    request->header_fields.push_back( string(upbuf, len) );
-  }
-}
-
-static void
-on_header_value (ebb_request *req, const char *buf, size_t len, int header_index)
-{
-  HttpRequest *request = static_cast<HttpRequest*> (req->data);
-
-  if( request->header_values.size() == header_index - 1) {
-    request->header_values.back().append(buf, len);
-  } else { 
-    request->header_values.push_back( string(buf, len) );
-  }
-}
-
-static void
-on_headers_complete (ebb_request *req)
-{
-  HttpRequest *request = static_cast<HttpRequest*> (req->data);
-
   HandleScope scope;
 
-  Handle<Object> js_request = request->CreateJSObject();
-
-  // Set up an exception handler before calling the Process function
-  TryCatch try_catch;
-
-  // Invoke the process function, giving the global object as 'this'
-  // and one argument, the request.
-  const int argc = 1;
-  Handle<Value> argv[argc] = { js_request };
-  Handle<Value> r = request->connection.js_onrequest->Call(Context::GetCurrent()->Global(), argc, argv);
-
-  if(try_catch.HasCaught())
-    node::fatal_exception(try_catch);
-}
-
-static void
-on_request_complete (ebb_request *req)
-{
-  HttpRequest *request = static_cast<HttpRequest*> (req->data);
-  request->MakeBodyCallback(NULL, 0); // EOF
-}
-
-static void
-on_body (ebb_request *req, const char *base, size_t length)
-{
-  HttpRequest *request = static_cast<HttpRequest*> (req->data);
-
-  if(length)
-    request->MakeBodyCallback(base, length);
-}
-
-static ebb_request * on_request
-  ( void *data
-  ) 
-{
-  Connection *connection = static_cast<Connection*> (data);
+  Local<FunctionTemplate> t = FunctionTemplate::New(HTTPClient::v8New);
+  t->InstanceTemplate()->SetInternalFieldCount(1);
+  target->Set(String::NewSymbol("HTTPClient"), t->GetFunction());
 
-  HttpRequest *request = new HttpRequest(*connection);
-  connection->AddRequest(request);
-  
-  return &request->parser_info;
+  NODE_SET_METHOD(t->InstanceTemplate(), "connect", Connection::v8Connect);
+  NODE_SET_METHOD(t->InstanceTemplate(), "close", Connection::v8Close);
+  NODE_SET_METHOD(t->InstanceTemplate(), "send", Connection::v8Send);
+  NODE_SET_METHOD(t->InstanceTemplate(), "sendEOF", Connection::v8SendEOF);
 }
 
-static void on_read 
-  ( oi_socket *socket
-  , const void *buf
-  , size_t count
-  )
-{
-  Connection *connection = static_cast<Connection*> (socket->data);
-  if(count == 0) {
-    connection->Close();
-  } else {
-    //write(1, buf, count);
-    connection->Parse(buf, count);  
-  }
-}
-
-static void on_close 
-  ( oi_socket *socket
-  )
-{
-  Connection *connection = static_cast<Connection*> (socket->data);
-  delete connection;
-}
-
-HttpRequest::~HttpRequest ()
-{
-  HandleScope scope; // needed?
-  // delete a reference c++ HttpRequest
-  js_object->SetInternalField(0, Undefined());
-  js_object->Delete(respond_str);
-  // dispose of Persistent handle so that 
-  // it can be GC'd normally.
-  js_object.Dispose();
-}
-
-HttpRequest::HttpRequest (Connection &c) : connection(c)
-{
-  ebb_request_init(&parser_info); 
-  parser_info.on_path             = on_path;
-  parser_info.on_query_string     = on_query_string;
-  parser_info.on_uri              = on_uri;
-  parser_info.on_fragment         = on_fragment;
-  parser_info.on_header_field     = on_header_field;
-  parser_info.on_header_value     = on_header_value;
-  parser_info.on_headers_complete = on_headers_complete;
-  parser_info.on_body             = on_body;
-  parser_info.on_complete         = on_request_complete;
-  parser_info.data                = this;
-
-  done = false;
-}
-
-void
-HttpRequest::MakeBodyCallback (const char *base, size_t length)
-{
-  HandleScope handle_scope;
-
-  Handle<Value> onbody_val = js_object->Get(on_body_str);  
-  if (!onbody_val->IsFunction()) return;
-  Handle<Function> onbody = Handle<Function>::Cast(onbody_val);
-
-  TryCatch try_catch;
-  const int argc = 1;
-  Handle<Value> argv[argc];
-  
-  if(length) {
-    // TODO ByteArray?
-    //
-    
-    uint16_t expanded_base[length];
-    for(int i = 0; i < length; i++) {
-      expanded_base[i] = base[i];
-    }
-
-    Handle<String> chunk = String::New(expanded_base, length);
-    argv[0] = chunk;
-  } else {
-    argv[0] = Null();
-  }
-
-  Handle<Value> result = onbody->Call(js_object, argc, argv);
-
-  if(try_catch.HasCaught())
-    node::fatal_exception(try_catch);
-}
-
-Local<Object>
-HttpRequest::CreateJSObject ()
+Handle<Value>
+HTTPClient::v8New (const Arguments& args)
 {
   HandleScope scope;
 
-  if (request_template.IsEmpty()) {
-    Handle<ObjectTemplate> raw_template = ObjectTemplate::New();
-    raw_template->SetInternalFieldCount(1);
-    raw_template->Set(respond_str, FunctionTemplate::New(RespondCallback));
-
-    request_template = Persistent<ObjectTemplate>::New(raw_template);
-  }
-
-  // Create an empty http request wrapper.
-  Handle<Object> result = request_template->NewInstance();
-
-  // Wrap the raw C++ pointer in an External so it can be referenced
-  // from within JavaScript.
-  Handle<External> request_ptr = External::New(this);
-
-  // Store the request pointer in the JavaScript wrapper.
-  result->SetInternalField(0, request_ptr);
-
-  result->Set ( path_str
-              , String::New(path.c_str(), path.length())
-              );
-
-  result->Set ( uri_str
-              , String::New(uri.c_str(), uri.length())
-              );
+  if (args[0]->IsFunction() == false)
+    return ThrowException(String::New("Must pass a class as the first argument."));
 
-  result->Set ( query_string_str
-              , String::New(query_string.c_str(), query_string.length())
-              );
-
-  result->Set ( fragment_str
-              , String::New(fragment.c_str(), fragment.length())
-              );
-
-  result->Set ( method_str
-              , GetMethodString(parser_info.method)
-              );
-
-  char version[10];
-  snprintf ( version
-           , 10 // big enough? :)
-           , "%d.%d"
-           , parser_info.version_major
-           , parser_info.version_minor
-           ); 
-  result->Set ( http_version_str
-              , String::New(version)
-              );
+  Handle<Function> protocol = Handle<Function>::Cast(args[0]);
 
+  int argc = args.Length();
+  Handle<Value> argv[argc];
   
-  Handle<Object> headers = Object::New();
-  list<string>::iterator field_iterator = header_fields.begin();
-  list<string>::iterator value_iterator = header_values.begin();
-  while( value_iterator != header_values.end() ) {
-    string &f = *field_iterator;
-    string &v = *value_iterator;
-    
-    headers->Set( String::NewSymbol(f.c_str(), f.length())
-                , String::New(v.c_str(), v.length() ) 
-                );
-
-    field_iterator++;
-    value_iterator++;
+  argv[0] = args.This();
+  for (int i = 1; i < args.Length(); i++) {
+    argv[i] = args[i];
   }
-  result->Set(headers_str, headers);
-
-  js_object = Persistent<Object>::New(result);
-  // XXX does the request's js_object need a MakeWeak callback?
-  // i dont think so because at some point the connection closes
-  // and we're going to delete the request. 
-  
-  return scope.Close(result);
-}
-
-
-static oi_socket*
-on_connection (oi_server *_server, struct sockaddr *addr, socklen_t len)
-{
-  HandleScope scope;
 
-  HttpServer *server = static_cast<HttpServer*> (_server->data);
+  Local<Object> protocol_instance = protocol->NewInstance(argc, argv);
 
-  Handle<Value> callback_v = server->Callback();
+  new HTTPClient(args.This(), protocol_instance);
 
-  if(callback_v == Undefined())
-    return NULL;
-
-  Connection *connection = new Connection();
-
-  Handle<Function> f = Handle<Function>::Cast(callback_v);
-  connection->js_onrequest = Persistent<Function>::New(f);
-
-  return &connection->socket;
-}
-
-Connection::Connection ()
-{
-  oi_socket_init (&socket, 30.0); // TODO make timeout adjustable
-  socket.on_read    = on_read;
-  socket.on_error   = NULL;
-  socket.on_close   = on_close;
-  socket.on_timeout = NULL;
-  socket.on_drain   = NULL;
-  socket.data       = this;
-
-  ebb_request_parser_init (&parser);
-  parser.new_request = on_request;
-  parser.data        = this;
-}
-
-Connection::~Connection ()
-{
-  list<HttpRequest*>::iterator it = requests.begin();
-
-  // delete all the requests
-
-  for(it = requests.begin(); it != requests.end(); it++)
-    delete *it;
-
-  for(it = finished_requests.begin(); it != finished_requests.end(); it++)
-    delete *it;
-}
-
-void
-Connection::Parse(const void *buf, size_t count)
-{
-  // FIXME change ebb_request_parser to have void* arg
-  ebb_request_parser_execute ( &parser
-                             , static_cast<const char*> (buf) 
-                             , count
-                             );
-
-  if(ebb_request_parser_has_error(&parser)) {
-    fprintf(stderr, "parse error closing connection\n");
-    oi_socket_close(&socket);
-  }
-}
-
-void 
-Connection::AddRequest(HttpRequest *request)
-{
-  requests.push_back(request);
-}
-
-void
-Connection::Write ( ) 
-{
-  if(requests.size() == 0)
-    return;
-
-  HttpRequest *request = requests.front(); 
-
-  while(request->output.size() > 0) {
-    oi_buf *buf = request->output.front();
-    oi_socket_write(&socket, buf);
-    request->output.pop_front();
-  }
-
-  if(request->done) {
-    if(!ebb_request_should_keep_alive(&request->parser_info)) {
-      socket.on_drain = oi_socket_close;
-    } 
-
-    requests.pop_front();
-    finished_requests.push_back(request);
-
-    Write();
-  }
-}
-
-void
-Connection::Close ( ) 
-{
-  oi_socket_close(&socket);
-}
-
-static void
-server_destroy (Persistent<Value> _, void *data)
-{
-  HttpServer *server = static_cast<HttpServer *> (data);
-  delete server;
-}
-
-HttpServer::HttpServer (Handle<Object> _js_server)
-{
-  oi_server_init(&server, 1024);
-  server.on_connection = on_connection;
-  server.data = this;
-  HandleScope scope;
-  js_server = Persistent<Object>::New (_js_server);
-  // are we ever going to need this external?
-  js_server->SetInternalField (0, External::New(this));
-  js_server.MakeWeak (this, server_destroy);
-}
-
-HttpServer::~HttpServer ()
-{
-  Stop();
-  js_server.Dispose();
-  js_server.Clear(); // necessary? 
-}
-
-int
-HttpServer::Start(struct addrinfo *servinfo) 
-{
-  int r = oi_server_listen(&server, servinfo);
-  if(r == 0)
-    oi_server_attach(EV_DEFAULT_UC_ &server);
-  return r;
+  return args.This();
 }
 
 void
-HttpServer::Stop() 
-{
-  oi_server_close (&server);
-  oi_server_detach (&server);
-}
-
-/* This constructor takes 2 arguments: host, port. */
-static Handle<Value>
-newHTTPHttpServer (const Arguments& args) 
+HTTPClient::OnReceive (const void *buf, size_t len)
 {
-  if (args.Length() < 3)
-    return Undefined();
-
-  HandleScope scope;
-
-  char *host = NULL; 
-  String::AsciiValue host_v(args[0]->ToString());
-  if(args[0]->IsString()) {
-    host = *host_v;
-  }
-  String::AsciiValue port(args[1]->ToString());
-
-  Handle<Function> onrequest = Handle<Function>::Cast(args[2]);
-  args.This()->Set(on_request_str, onrequest);
-
-  // get addrinfo for localhost, PORT
-  struct addrinfo *servinfo;
-  struct addrinfo hints;
-  memset(&hints, 0, sizeof hints);
-  hints.ai_family = AF_UNSPEC;
-  hints.ai_socktype = SOCK_STREAM;
-  hints.ai_flags = AI_PASSIVE;
-  // FIXME BLOCKING
-  int r = getaddrinfo(host, *port, &hints, &servinfo);
-  if (r != 0)
-    return Undefined(); // XXX raise error?
-
-  //
-  //
-  //
-  // TODO host is ignored for now assumed localhost
-  //
-  //
-  //
-  //
-
-  HttpServer *server = new HttpServer(args.This());
-  if(server == NULL)
-    return Undefined(); // XXX raise error?
-
-  r = server->Start(servinfo);
-  if (r != 0)
-    return Undefined(); // XXX raise error?
-
-  return args.This();
+  printf("http client got data!\n");
 }
 
-void
-node::Init_http (Handle<Object> target)
+HTTPClient::HTTPClient (Handle<Object> handle, Handle<Object> protocol) 
+  : Connection(handle, protocol) 
 {
-  HandleScope scope;
-
-  Local<FunctionTemplate> server_t = FunctionTemplate::New(newHTTPHttpServer);
-  server_t->InstanceTemplate()->SetInternalFieldCount(1);
-  
-  server_t->Set("INVALID_STATE_ERR", Integer::New(INVALID_STATE_ERR));
-
-  target->Set(String::New("HTTPServer"), server_t->GetFunction());
-
-  path_str         = Persistent<String>::New( String::NewSymbol("path") );
-  uri_str          = Persistent<String>::New( String::NewSymbol("uri") );
-  query_string_str = Persistent<String>::New( String::NewSymbol("query_string") );
-  fragment_str     = Persistent<String>::New( String::NewSymbol("fragment") );
-  method_str       = Persistent<String>::New( String::NewSymbol("method") );
-  http_version_str = Persistent<String>::New( String::NewSymbol("http_version") );
-  headers_str      = Persistent<String>::New( String::NewSymbol("headers") );
-
-  on_request_str = Persistent<String>::New( String::NewSymbol("onrequest") );
-  on_body_str    = Persistent<String>::New( String::NewSymbol("onbody") );
-  respond_str    = Persistent<String>::New( String::NewSymbol("respond") );
-
-  copy_str      = Persistent<String>::New( String::New("COPY") );
-  delete_str    = Persistent<String>::New( String::New("DELETE") );
-  get_str       = Persistent<String>::New( String::New("GET") );
-  head_str      = Persistent<String>::New( String::New("HEAD") );
-  lock_str      = Persistent<String>::New( String::New("LOCK") );
-  mkcol_str     = Persistent<String>::New( String::New("MKCOL") );
-  move_str      = Persistent<String>::New( String::New("MOVE") );
-  options_str   = Persistent<String>::New( String::New("OPTIONS") );
-  post_str      = Persistent<String>::New( String::New("POST") );
-  propfind_str  = Persistent<String>::New( String::New("PROPFIND") );
-  proppatch_str = Persistent<String>::New( String::New("PROPPATCH") );
-  put_str       = Persistent<String>::New( String::New("PUT") );
-  trace_str     = Persistent<String>::New( String::New("TRACE") );
-  unlock_str    = Persistent<String>::New( String::New("UNLOCK") );
-}
+} 
index 69e5f09f6cf14e609eca46ee51fb0698ce7d469f..db9a6a992bd1c97677e92953453364c07afef4ba 100644 (file)
@@ -2,10 +2,21 @@
 #define node_http_h
 
 #include <v8.h>
+#include "net.h"
 
 namespace node {
 
-void Init_http (v8::Handle<v8::Object> target);
+class HTTPClient : public node::Connection {
+public:
+  static void Initialize (v8::Handle<v8::Object> target);
+
+  HTTPClient (v8::Handle<v8::Object> handle, v8::Handle<v8::Object> protocol);
+
+  static v8::Handle<v8::Value> v8New (const v8::Arguments& args);
+protected:
+  void OnReceive (const void *buf, size_t len);
+
+};
 
 } // namespace node
 #endif
index 47b1aaa71be8524441d341d55149c32e50133402..dc81a61e3c6cc630dd65e20533f6f9d91ef6e1fb 100644 (file)
@@ -59,21 +59,12 @@ Connection::Initialize (v8::Handle<v8::Object> target)
   NODE_SET_METHOD(t->InstanceTemplate(), "sendEOF", Connection::v8SendEOF);
 }
 
-Local<Object>
-Connection::NewServerSideInstance (Local<Function> protocol, Handle<Object> server)
-{
-  HandleScope scope;
-  Handle<Value> argv[] = { protocol, server };
-  Local<Object> instance = tcp_connection_constructor->NewInstance(2, argv);
-  return scope.Close(instance);
-}
-
-Connection::Connection (Handle<Object> handle)
+Connection::Connection (Handle<Object> handle, Handle<Object> protocol)
   : ObjectWrap(handle) 
 {
   HandleScope scope;
 
-  Local<Object> protocol = GetProtocol();
+  handle_->Set(PROTOCOL_SYMBOL, protocol);
 
   encoding_ = RAW;
   Local<Value> encoding_v = protocol->Get(ENCODING_SYMBOL);
@@ -136,9 +127,8 @@ Connection::v8New (const Arguments& args)
   }
 
   Local<Object> protocol_instance = protocol->NewInstance(argc, argv);
-  args.This()->Set(PROTOCOL_SYMBOL, protocol_instance);
 
-  new Connection(args.This());
+  new Connection(args.This(), protocol_instance);
 
   return args.This();
 }
@@ -387,10 +377,11 @@ Acceptor::OnConnection (struct sockaddr *addr, socklen_t len)
   }
   Local<Function> protocol = Local<Function>::Cast(protocol_v);
 
-  Local<Object> connection_handle = 
-    Connection::NewServerSideInstance(protocol, handle_);
+  Handle<Value> argv[] = { protocol, handle_ };
+  Local<Object> connection_handle = tcp_connection_constructor->NewInstance(2, argv);
+
+  Connection *connection = NODE_UNWRAP(Connection, connection_handle);
 
-  Connection *connection = new Connection(connection_handle);
   return connection;
 }
 
index 45586971b51f4ad526a5d36e0a53a1c8d9125460..60cad4ae6421758dd62625590613143096f46d74 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -11,10 +11,8 @@ class Connection : public ObjectWrap {
 public:
   static void Initialize (v8::Handle<v8::Object> target);
 
-  Connection (v8::Handle<v8::Object> handle); 
-  ~Connection () {
-    Close();
-  }
+  Connection (v8::Handle<v8::Object> handle, v8::Handle<v8::Object> protocol); 
+  virtual ~Connection () { Close(); }
 
   int Connect (struct addrinfo *address) {
     return oi_socket_connect (&socket_, address);
@@ -39,20 +37,17 @@ protected:
   static v8::Handle<v8::Value> v8SendEOF (const v8::Arguments& args);
   static v8::Handle<v8::Value> v8Close (const v8::Arguments& args);
 
-  void OnConnect (void);
-  void OnReceive (const void *buf, size_t len);
-  void OnDrain (void);
-  void OnEOF (void);
-  void OnDisconnect (void);
-  void OnError (oi_error e);
-  void OnTimeout (void);
+  virtual void OnConnect (void);
+  virtual void OnReceive (const void *buf, size_t len);
+  virtual void OnDrain (void);
+  virtual void OnEOF (void);
+  virtual void OnDisconnect (void);
+  virtual void OnError (oi_error e);
+  virtual void OnTimeout (void);
 
   v8::Local<v8::Object> GetProtocol (void);
-  static v8::Local<v8::Object> NewServerSideInstance ( 
-      v8::Local<v8::Function> protocol, 
-      v8::Handle<v8::Object> server);
 
-private:
+//private:
   /* liboi callbacks */
   static void on_connect (oi_socket *s) {
     Connection *connection = static_cast<Connection*> (s->data);
index b328737a1b8e0bd27be03b268ecb09843a7b85ae..081ce0e6da229cc8753c7e227eb62670e9cfb66f 100644 (file)
@@ -252,7 +252,7 @@ main (int argc, char *argv[])
   Connection::Initialize(g);
   node::Init_timer(g);
   node::Init_file(g);
-  node::Init_http(g);
+  HTTPClient::Initialize(g);
 
   // NATIVE JAVASCRIPT MODULES
   TryCatch try_catch;
index 959175253a5f23afb9e0918747ac93047a6fd750..d7e79e9c9abd6838d3c812ae79f3ddd958beacbf 100644 (file)
@@ -20,7 +20,7 @@ void eio_warmup (void); // call this before creating a new eio event.
 class ObjectWrap {
 public:
   ObjectWrap (v8::Handle<v8::Object> handle);
-  ~ObjectWrap ( );
+  virtual ~ObjectWrap ( );
 
 protected:
   static void* Unwrap (v8::Handle<v8::Object> handle);
index 8ad2cf2500e9cf58c26d33082e98a6ee25fca544..8cc46541432754cdad6d2a1dc46cc2312a146049 100644 (file)
@@ -14,7 +14,7 @@ function Ponger (socket, server) {
 
   this.onReceive = function (data) {
     assertTrue(count <= N);
-    stdout.print ("-");
+    stdout.print("-");
     if (/PING/.exec(data)) {
       socket.send("PONG");
     }
diff --git a/wscript b/wscript
index ccf20f9f9cee086fdbd9736c13e5c731f01089d7..f1ec621aa88dff85bf5f9ce015fa3e66b52d23b1 100644 (file)
--- a/wscript
+++ b/wscript
@@ -18,7 +18,6 @@ def set_options(opt):
   # the gcc module provides a --debug-level option
   opt.tool_options('compiler_cxx')
   opt.tool_options('compiler_cc')
-  opt.tool_options('ragel', tdir=".")
   opt.add_option( '--debug'
                 , action='store_true'
                 , default=False
@@ -29,10 +28,6 @@ def set_options(opt):
 def configure(conf):
   conf.check_tool('compiler_cxx')
   conf.check_tool('compiler_cc')
-  conf.check_tool('ragel', tooldir=".")
-  if not conf.env['RAGEL']:
-    fatal('ragel not found')
-    exit(1)
 
   conf.env["USE_DEBUG"] = Options.options.debug
 
@@ -124,15 +119,15 @@ def build(bld):
   if bld.env["USE_DEBUG"]:
     oi.clone("debug")
 
-  ### ebb
-  ebb = bld.new_task_gen("cc", "staticlib")
-  ebb.source = "deps/libebb/ebb_request_parser.rl"
-  ebb.includes = "deps/libebb/"
-  ebb.name = "ebb"
-  ebb.target = "ebb"
-  ebb.install_path = None
+  ### http_parser
+  http_parser = bld.new_task_gen("cc", "staticlib")
+  http_parser.source = "deps/http_parser/http_parser.c"
+  http_parser.includes = "deps/http_parser/"
+  http_parser.name = "http_parser"
+  http_parser.target = "http_parser"
+  http_parser.install_path = None
   if bld.env["USE_DEBUG"]:
-    ebb.clone("debug")
+    http_parser.clone("debug")
 
   ### src/native.cc
   def javascript_in_c(task):
@@ -167,9 +162,9 @@ def build(bld):
     deps/libev
     deps/libeio
     deps/liboi 
-    deps/libebb
+    deps/http_parser
   """
-  node.uselib_local = "oi ev eio ebb"
+  node.uselib_local = "oi ev eio http_parser"
   node.uselib = "V8 RT"
   node.install_path = '${PREFIX}/bin'
   node.chmod = 0755