--------------------- PatchSet 8548 Date: 2006/08/25 08:52:19 Author: adri Branch: parserwork Tag: (none) Log: * Few semantic changes to the new request parser * hack something up so it'll parse versions - it expects a http version to be there so http/0.9 is out of scope ATM but it'll be easy to add it back in afterwards * Add in some comments describing what the routines do This code is hackish and definitely not audited but it should be -fast-. Members: src/HttpMsg.c:1.8.8.3->1.8.8.4 src/client_side.c:1.143.2.4->1.143.2.5 src/structs.h:1.128.2.4->1.128.2.5 Index: squid/src/HttpMsg.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpMsg.c,v retrieving revision 1.8.8.3 retrieving revision 1.8.8.4 diff -u -r1.8.8.3 -r1.8.8.4 --- squid/src/HttpMsg.c 24 Aug 2006 13:30:30 -0000 1.8.8.3 +++ squid/src/HttpMsg.c 25 Aug 2006 08:52:19 -0000 1.8.8.4 @@ -1,6 +1,6 @@ /* - * $Id: HttpMsg.c,v 1.8.8.3 2006/08/24 13:30:30 adri Exp $ + * $Id: HttpMsg.c,v 1.8.8.4 2006/08/25 08:52:19 adri Exp $ * * DEBUG: section 74 HTTP Message * AUTHOR: Alex Rousskov @@ -50,11 +50,26 @@ (void) 0; } + +/* + * Attempt to parse the request line. + * + * This will set the values in hmsg that it determines. One may end up + * with a partially-parsed buffer; the return value tells you whether + * the values are valid or not. + * + * @return 1 if parsed correctly, 0 if more is needed, -1 if error + * + * TODO: + * * have it indicate "error" and "not enough" as two separate conditions! + * * audit this code as off-by-one errors are probably everywhere! + */ int httpMsgParseRequestLine(HttpMsgBuf *hmsg) { int i = 0; int retcode = 0; + int maj = -1, min = -1; /* Find \r\n - end of URL+Version (and the request) */ for (i = 0; i < hmsg->size; i++) { @@ -98,7 +113,6 @@ } hmsg->u_start = i; - /* XXX rfc-compliant, but needs to be fixed for production */ /* Find whitespace; end of URL */ for (; i < hmsg->req_end && (! isspace(hmsg->buf[i])); i++); if (i >= hmsg->req_end) { @@ -107,6 +121,8 @@ } hmsg->u_end = i; + /* XXX yes, this doesn't support HTTP/0.9 requests just yet .. */ + /* Find non-whitespace, version */ for (; i < hmsg->req_end && (isspace(hmsg->buf[i])); i++); if (i >= hmsg->req_end) { @@ -115,19 +131,53 @@ } hmsg->v_start = i; - /* Find whitespace, end of version */ - for (; i < hmsg->req_end && (! isspace(hmsg->buf[i])); i++); + /* next five characters should be HTTP/ */ + if (i + 5 >= hmsg->req_end) { + retcode = 0; + goto finish; + } + if (strncasecmp(&hmsg->buf[i], "HTTP/", 5) != 0) { + retcode = -1; + goto finish; + } + i += 5; + + /* next should be 1 or more digits */ + maj = 0; + for (; i < hmsg->req_end && (isdigit(hmsg->buf[i])); i++) { + maj = maj * 10; + maj = maj + (hmsg->buf[i]) - '0'; + + } if (i >= hmsg->req_end) { retcode = 0; goto finish; } + + /* next should be . */ + if (hmsg->buf[i] != '.') { + retcode = -1; + goto finish; + } + if (i + 1 >= hmsg->req_end) { + retcode = 0; + goto finish; + } + + /* next should be one or more digits */ + i++; + min = 0; + for (; i < hmsg->req_end && (isdigit(hmsg->buf[i])); i++) { + min = min * 10; + min = min + (hmsg->buf[i]) - '0'; + + } + + /* Find whitespace, end of version */ hmsg->v_end = i; - /* Rightio - need to determine whether we've got a version or not */ - /* So - from end of line - work backwards until first non-whitespace - version or end of URL */ - /* Find next whitespace - maybe beginning of version */ - /* Is it HTTP/ ? Good, we have a version; else 0.9 */ - /* Parse the http version */ + hmsg->v_maj = maj; + hmsg->v_min = min; /* * Rightio - we have all the schtuff. Return true; we've got enough. @@ -135,11 +185,11 @@ retcode = 1; finish: - debug(1, 2) ("Parser: retval %d: from %d->%d: method %d->%d; url %d->%d; version %d->%d\n", + debug(1, 2) ("Parser: retval %d: from %d->%d: method %d->%d; url %d->%d; version %d->%d (%d/%d)\n", retcode, hmsg->req_start, hmsg->req_end, hmsg->m_start, hmsg->m_end, hmsg->u_start, hmsg->u_end, - hmsg->v_start, hmsg->v_end); + hmsg->v_start, hmsg->v_end, maj, min); return retcode; } Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v retrieving revision 1.143.2.4 retrieving revision 1.143.2.5 diff -u -r1.143.2.4 -r1.143.2.5 --- squid/src/client_side.c 24 Aug 2006 13:30:30 -0000 1.143.2.4 +++ squid/src/client_side.c 25 Aug 2006 08:52:19 -0000 1.143.2.5 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.143.2.4 2006/08/24 13:30:30 adri Exp $ + * $Id: client_side.c,v 1.143.2.5 2006/08/25 08:52:19 adri Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -3503,14 +3503,17 @@ method_t method; clientHttpRequest *http = NULL; int http_version_offset = 0; + int r; /* pre-set these values to make aborting simpler */ *prefix_p = NULL; *method_p = METHOD_NONE; *status = -1; - if (! httpMsgParseRequestLine(hmsg)) { - return NULL; + r = httpMsgParseRequestLine(hmsg); + if (r != 1) { + *status = r; /* XXX these should match! */ + return NULL; }; /* At this point we have a request line but we don't know if we have the full headers */ @@ -4080,6 +4083,7 @@ } /* Process next request */ while (conn->in.offset > 0 && conn->body.size_left == 0) { + debug(1, 2) ("clientParseRequest being called\n"); if (! clientParseRequest(fd, conn)) break; } /* while offset > 0 && conn->body.size_left == 0 */ Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.128.2.4 retrieving revision 1.128.2.5 diff -u -r1.128.2.4 -r1.128.2.5 --- squid/src/structs.h 24 Aug 2006 13:30:32 -0000 1.128.2.4 +++ squid/src/structs.h 25 Aug 2006 08:52:20 -0000 1.128.2.5 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.128.2.4 2006/08/24 13:30:32 adri Exp $ + * $Id: structs.h,v 1.128.2.5 2006/08/25 08:52:20 adri Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -2496,6 +2496,7 @@ int m_start, m_end; int u_start, u_end; int v_start, v_end; + int v_maj, v_min; }; struct _clientCheckHeaderStateData {