Skip to content

Commit d8ee64d

Browse files
author
Sergey Pariev
committed
added reexecute_byte simulation through a flag, other fixes; got a few tests passing
1 parent 79b495a commit d8ee64d

1 file changed

Lines changed: 101 additions & 93 deletions

File tree

src/impl/http_parser/lolevel/HTTPParser.java

Lines changed: 101 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ public HTTPParser(ParserType type) {
102102
* URL and non-URL states by looking for these.
103103
*/
104104
public State parse_url_char(byte ch) {
105+
106+
int chi = ch & 0xff; // utility, ch without signedness for table lookups.
107+
105108
if(SPACE == ch){
106109
throw new HTTPException("space as url char");
107110
}
@@ -190,7 +193,7 @@ public State parse_url_char(byte ch) {
190193
break;
191194

192195
case req_path:
193-
if (isNormalUrlChar(ch)) {
196+
if (isNormalUrlChar(chi)) {
194197
return req_path;
195198
}
196199
switch (ch) {
@@ -204,7 +207,7 @@ public State parse_url_char(byte ch) {
204207

205208
case req_query_string_start:
206209
case req_query_string:
207-
if (isNormalUrlChar(ch)) {
210+
if (isNormalUrlChar(chi)) {
208211
return req_query_string;
209212
}
210213

@@ -220,7 +223,7 @@ public State parse_url_char(byte ch) {
220223
break;
221224

222225
case req_fragment_start:
223-
if (isNormalUrlChar(ch)) {
226+
if (isNormalUrlChar(chi)) {
224227
return req_fragment;
225228
}
226229
switch (ch) {
@@ -319,24 +322,35 @@ public int execute(ParserSettings settings, ByteBuffer data) {
319322
url_mark = p;
320323
break;
321324
}
322-
// this is where the work gets done, traverse the available data...
323-
while (data.position() != data.limit()) {
324-
325-
p = data.position();
326-
int pe = data.limit();
325+
boolean reexecute = false;
326+
int pe = 0;
327+
byte ch = 0;
328+
int chi = 0;
329+
byte c = -1;
330+
int to_read = 0;
327331

328-
byte ch = data.get(); // the current character to process.
329-
int chi = ch & 0xff; // utility, ch without signedness for table lookups.
330-
byte c = -1; // utility variably used for up- and downcasing etc.
331-
int to_read = 0; // used to keep track of how much of body, etc. is left to read
332-
333-
if (parsing_header(state)) {
334-
++nread;
335-
if (nread > HTTP_MAX_HEADER_SIZE) {
336-
return error(settings, "possible buffer overflow", data);
332+
// this is where the work gets done, traverse the available data...
333+
while (data.position() != data.limit() || reexecute) {
334+
// p(state + ": r: " + reexecute + " :: " +p );
335+
336+
if(!reexecute){
337+
p = data.position();
338+
pe = data.limit();
339+
ch = data.get(); // the current character to process.
340+
chi = ch & 0xff; // utility, ch without signedness for table lookups.
341+
c = -1; // utility variably used for up- and downcasing etc.
342+
to_read = 0; // used to keep track of how much of body, etc. is left to read
343+
344+
if (parsing_header(state)) {
345+
++nread;
346+
if (nread > HTTP_MAX_HEADER_SIZE) {
347+
return error(settings, "possible buffer overflow", data);
348+
}
337349
}
338350
}
339-
// p(state + ":" + (char)ch +":"+p);
351+
reexecute = false;
352+
// p(state + " ::: " + ch + " : " + (((CR == ch) || (LF == ch)) ? ch : ("'" + (char)ch + "'")) +": "+p );
353+
340354
switch (state) {
341355
/*
342356
* this state is used after a 'Connection: close' message
@@ -676,16 +690,18 @@ public int execute(ParserSettings settings, ByteBuffer data) {
676690
switch (ch) {
677691
case SPACE:
678692
settings.call_on_url(this, data, url_mark, p-url_mark);
693+
settings.call_on_path(this, data, url_mark, p - url_mark);
679694
url_mark = -1;
680695
state = State.req_http_start;
681696
break;
682697
case CR:
683698
case LF:
684-
url_mark = -1;
685699
http_major = 0;
686700
http_minor = 9;
687701
state = (CR == ch) ? req_line_almost_done : header_field_start;
688702
settings.call_on_url(this, data, url_mark, p-url_mark); //TODO check params!!!
703+
settings.call_on_path(this, data, url_mark, p-url_mark);
704+
url_mark = -1;
689705
break;
690706
default:
691707
state = parse_url_char(ch);
@@ -829,12 +845,7 @@ public int execute(ParserSettings settings, ByteBuffer data) {
829845
/* they might be just sending \n instead of \r\n so this would be
830846
* the second \n to denote the end of headers*/
831847
state = State.headers_almost_done;
832-
if (!headers_almost_done(ch, settings)) {
833-
return error(settings, "header not properly completed", data);
834-
}
835-
if (upgrade) {
836-
return data.position() - this.p_start;
837-
}
848+
reexecute = true;
838849
break;
839850
}
840851

@@ -1092,10 +1103,8 @@ public int execute(ParserSettings settings, ByteBuffer data) {
10921103
if (LF == ch) {
10931104
settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
10941105
header_value_mark = -1;
1095-
1096-
if (!header_almost_done(ch)) {
1097-
return error(settings, "incorrect header ending, expection LF", data);
1098-
}
1106+
state = header_almost_done;
1107+
reexecute = true;
10991108
break;
11001109
}
11011110

@@ -1185,13 +1194,69 @@ public int execute(ParserSettings settings, ByteBuffer data) {
11851194
state = header_value_start;
11861195
} else {
11871196
state = header_field_start;
1197+
reexecute = true;
11881198
}
11891199
break;
11901200

11911201
case headers_almost_done:
1192-
if (!headers_almost_done(ch, settings)) {
1202+
if (LF != ch) {
11931203
return error(settings, "header not properly completed", data);
11941204
}
1205+
if (0 != (flags & F_TRAILING)) {
1206+
/* End of a chunked request */
1207+
state = new_message();
1208+
1209+
settings.call_on_message_complete(this);
1210+
break;
1211+
}
1212+
1213+
state = headers_done;
1214+
1215+
if (0 != (flags & F_UPGRADE) || HTTPMethod.HTTP_CONNECT == method) {
1216+
upgrade = true;
1217+
}
1218+
1219+
/* Here we call the headers_complete callback. This is somewhat
1220+
* different than other callbacks because if the user returns 1, we
1221+
* will interpret that as saying that this message has no body. This
1222+
* is needed for the annoying case of recieving a response to a HEAD
1223+
* request.
1224+
*/
1225+
1226+
/* (responses to HEAD request contain a CONTENT-LENGTH header
1227+
* but no content)
1228+
*
1229+
* Consider what to do here: I don't like the idea of the callback
1230+
* interface having a different contract in the case of HEAD
1231+
* responses. The alternatives would be either to:
1232+
*
1233+
* a.) require the header_complete callback to implement a different
1234+
* interface or
1235+
*
1236+
* b.) provide an overridden execute(bla, bla, boolean
1237+
* parsingHeader) implementation ...
1238+
*/
1239+
1240+
/*TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO */
1241+
if (null != settings.on_headers_complete) {
1242+
settings.call_on_headers_complete(this);
1243+
//return;
1244+
}
1245+
1246+
// if (null != settings.on_headers_complete) {
1247+
// switch (settings.on_headers_complete.cb(parser)) {
1248+
// case 0:
1249+
// break;
1250+
//
1251+
// case 1:
1252+
// flags |= F_SKIPBODY;
1253+
// break;
1254+
//
1255+
// default:
1256+
// return p - data; /* Error */ // TODO // RuntimeException ?
1257+
// }
1258+
// }
1259+
reexecute = true;
11951260
break;
11961261

11971262
case headers_done:
@@ -1233,6 +1298,8 @@ public int execute(ParserSettings settings, ByteBuffer data) {
12331298
}
12341299
}
12351300
}
1301+
1302+
break;
12361303
/******************* Header *******************/
12371304

12381305

@@ -1253,6 +1320,7 @@ public int execute(ParserSettings settings, ByteBuffer data) {
12531320
}
12541321
}
12551322

1323+
reexecute = true;
12561324
break;
12571325

12581326

@@ -1420,6 +1488,7 @@ public int execute(ParserSettings settings, ByteBuffer data) {
14201488
settings.call_on_header_field(this, data, header_field_mark, p-header_field_mark);
14211489
settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
14221490
settings.call_on_url (this, data, url_mark, p-url_mark);
1491+
settings.call_on_path (this, data, url_mark, p-url_mark);
14231492

14241493
return data.position()-this.p_start;
14251494
} // execute
@@ -1563,69 +1632,8 @@ boolean header_almost_done(byte ch) {
15631632
return true;
15641633
}
15651634

1566-
boolean headers_almost_done (byte ch, ParserSettings settings) {
1567-
if (LF != ch) {
1568-
return false;
1569-
}
1570-
if (0 != (flags & F_TRAILING)) {
1571-
/* End of a chunked request */
1572-
state = new_message();
1573-
1574-
settings.call_on_headers_complete(this);
1575-
settings.call_on_message_complete(this);
1576-
1577-
return true;
1578-
}
1579-
1580-
state = headers_done;
1581-
1582-
if (0 != (flags & F_UPGRADE) || HTTPMethod.HTTP_CONNECT == method) {
1583-
upgrade = true;
1584-
}
1585-
1586-
1587-
/* Here we call the headers_complete callback. This is somewhat
1588-
* different than other callbacks because if the user returns 1, we
1589-
* will interpret that as saying that this message has no body. This
1590-
* is needed for the annoying case of recieving a response to a HEAD
1591-
* request.
1592-
*/
1593-
1594-
/* (responses to HEAD request contain a CONTENT-LENGTH header
1595-
* but no content)
1596-
*
1597-
* Consider what to do here: I don't like the idea of the callback
1598-
* interface having a different contract in the case of HEAD
1599-
* responses. The alternatives would be either to:
1600-
*
1601-
* a.) require the header_complete callback to implement a different
1602-
* interface or
1603-
*
1604-
* b.) provide an overridden execute(bla, bla, boolean
1605-
* parsingHeader) implementation ...
1606-
*/
1607-
1608-
/*TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO */
1609-
if (null != settings.on_headers_complete) {
1610-
settings.call_on_headers_complete(this);
1611-
//return;
1612-
}
1613-
1614-
// if (null != settings.on_headers_complete) {
1615-
// switch (settings.on_headers_complete.cb(parser)) {
1616-
// case 0:
1617-
// break;
1618-
//
1619-
// case 1:
1620-
// flags |= F_SKIPBODY;
1621-
// break;
1622-
//
1623-
// default:
1624-
// return p - data; /* Error */ // TODO // RuntimeException ?
1625-
// }
1626-
// }
1627-
return true;
1628-
} // headers_almost_done
1635+
// boolean headers_almost_done (byte ch, ParserSettings settings) {
1636+
// } // headers_almost_done
16291637

16301638

16311639
final int min (int a, int b) {

0 commit comments

Comments
 (0)