r63237 - in /branches/upstream/libhttp-parser-xs-perl/current: Changes MANIFEST META.yml XS.xs benchmark/ benchmark/simple.pl lib/HTTP/Parser/XS.pm picohttpparser/picohttpparser.c picohttpparser/picohttpparser.h

jawnsy-guest at users.alioth.debian.org jawnsy-guest at users.alioth.debian.org
Sun Oct 3 18:56:24 UTC 2010


Author: jawnsy-guest
Date: Sun Oct  3 18:56:15 2010
New Revision: 63237

URL: http://svn.debian.org/wsvn/pkg-perl/?sc=1&rev=63237
Log:
[svn-upgrade] new version libhttp-parser-xs-perl (0.09)

Added:
    branches/upstream/libhttp-parser-xs-perl/current/benchmark/
    branches/upstream/libhttp-parser-xs-perl/current/benchmark/simple.pl   (with props)
Modified:
    branches/upstream/libhttp-parser-xs-perl/current/Changes
    branches/upstream/libhttp-parser-xs-perl/current/MANIFEST
    branches/upstream/libhttp-parser-xs-perl/current/META.yml
    branches/upstream/libhttp-parser-xs-perl/current/XS.xs
    branches/upstream/libhttp-parser-xs-perl/current/lib/HTTP/Parser/XS.pm
    branches/upstream/libhttp-parser-xs-perl/current/picohttpparser/picohttpparser.c
    branches/upstream/libhttp-parser-xs-perl/current/picohttpparser/picohttpparser.h

Modified: branches/upstream/libhttp-parser-xs-perl/current/Changes
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libhttp-parser-xs-perl/current/Changes?rev=63237&op=diff
==============================================================================
--- branches/upstream/libhttp-parser-xs-perl/current/Changes (original)
+++ branches/upstream/libhttp-parser-xs-perl/current/Changes Sun Oct  3 18:56:15 2010
@@ -1,4 +1,10 @@
 Revision history for Perl extension HTTP::Parser::XS.
+
+0.09
+	- improve compatibility (mainly Windows, RT #61133, thanks to Taro Nishino)
+
+0.08
+	- improve compatibility (mainly Solaris, thanks to gfx)
 
 0.07  Tue Mar 02 15:40:00 2010
 	- fix build error when using older versions of Pod::Text

Modified: branches/upstream/libhttp-parser-xs-perl/current/MANIFEST
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libhttp-parser-xs-perl/current/MANIFEST?rev=63237&op=diff
==============================================================================
--- branches/upstream/libhttp-parser-xs-perl/current/MANIFEST (original)
+++ branches/upstream/libhttp-parser-xs-perl/current/MANIFEST Sun Oct  3 18:56:15 2010
@@ -1,3 +1,4 @@
+benchmark/simple.pl
 Changes
 lib/HTTP/Parser/XS.pm
 Makefile.PL

Modified: branches/upstream/libhttp-parser-xs-perl/current/META.yml
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libhttp-parser-xs-perl/current/META.yml?rev=63237&op=diff
==============================================================================
--- branches/upstream/libhttp-parser-xs-perl/current/META.yml (original)
+++ branches/upstream/libhttp-parser-xs-perl/current/META.yml Sun Oct  3 18:56:15 2010
@@ -1,6 +1,6 @@
 --- #YAML:1.0
 name:                HTTP-Parser-XS
-version:             0.07
+version:             0.09
 abstract:            a fast, primitive HTTP request parser
 license:             ~
 author:              

Modified: branches/upstream/libhttp-parser-xs-perl/current/XS.xs
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libhttp-parser-xs-perl/current/XS.xs?rev=63237&op=diff
==============================================================================
--- branches/upstream/libhttp-parser-xs-perl/current/XS.xs (original)
+++ branches/upstream/libhttp-parser-xs-perl/current/XS.xs Sun Oct  3 18:56:15 2010
@@ -1,18 +1,29 @@
+#define PERL_NO_GET_CONTEXT
 #include "EXTERN.h"
 #include "perl.h"
 #include "XSUB.h"
 #include "picohttpparser/picohttpparser.c"
 
+#ifndef STATIC_INLINE /* a public perl API from 5.13.4 */
+#   if defined(__GNUC__) || defined(__cplusplus__) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
+#       define STATIC_INLINE static inline
+#   else
+#       define STATIC_INLINE static
+#   endif
+#endif /* STATIC_INLINE */
+
 #define MAX_HEADERS 128
 
-__inline char tou(char ch)
+STATIC_INLINE
+char tou(char ch)
 {
   if ('a' <= ch && ch <= 'z')
     ch -= 'a' - 'A';
   return ch;
 }
 
-static int header_is(const struct phr_header* header, const char* name,
+static
+int header_is(const struct phr_header* header, const char* name,
 		     size_t len)
 {
   const char* x, * y;
@@ -24,7 +35,8 @@
   return 1;
 }
 
-static size_t find_ch(const char* s, size_t len, char ch)
+static
+size_t find_ch(const char* s, size_t len, char ch)
 {
   size_t i;
   for (i = 0; i != len; ++i, ++s)
@@ -33,7 +45,8 @@
   return i;
 }
 
-__inline int hex_decode(const char ch)
+STATIC_INLINE
+int hex_decode(const char ch)
 {
   int r;
   if ('0' <= ch && ch <= '9')
@@ -47,8 +60,10 @@
   return r;
 }
 
-static char* url_decode(const char* s, size_t len)
-{
+static
+char* url_decode(const char* s, size_t len)
+{
+  dTHX;
   char* dbuf, * d;
   size_t i;
   
@@ -79,9 +94,11 @@
   return dbuf;
 }
 
-__inline int store_url_decoded(HV* env, const char* name, size_t name_len,
+STATIC_INLINE
+int store_url_decoded(HV* env, const char* name, size_t name_len,
 			       const char* value, size_t value_len)
 {
+  dTHX;
   char* decoded = url_decode(value, value_len);
   if (decoded == NULL)
     return -1;
@@ -110,7 +127,8 @@
   int minor_version;
   struct phr_header headers[MAX_HEADERS];
   size_t num_headers, question_at;
-  int ret, i;
+  size_t i;
+  int ret;
   HV* env;
   SV* last_value;
   char tmp[1024];

Added: branches/upstream/libhttp-parser-xs-perl/current/benchmark/simple.pl
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libhttp-parser-xs-perl/current/benchmark/simple.pl?rev=63237&op=file
==============================================================================
--- branches/upstream/libhttp-parser-xs-perl/current/benchmark/simple.pl (added)
+++ branches/upstream/libhttp-parser-xs-perl/current/benchmark/simple.pl Sun Oct  3 18:56:15 2010
@@ -1,0 +1,31 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Benchmark qw(cmpthese);
+use HTTP::Parser;
+use HTTP::Parser::XS qw(parse_http_request);
+
+my $req = "GET /foo/bar/baz.html?key=value HTTP/1.0\r\n\r\n";
+
+my $http_parser = HTTP::Parser->new();
+
+cmpthese(-1, {
+    'HTTP::Parser' => sub {
+        my $status = $http_parser->add($req);
+        if ($status == 0) {
+            $http_parser->request();
+        } else {
+            die "oh!\n";
+        }
+    },
+    'HTTP::Parser::XS' => sub {
+        my %env;
+        my $len = parse_http_request($req, \%env);
+        if ($len >= 0) {
+            # ok
+        } else {
+            die "agh!\n";
+        }
+    },
+});

Propchange: branches/upstream/libhttp-parser-xs-perl/current/benchmark/simple.pl
------------------------------------------------------------------------------
    svn:executable = *

Modified: branches/upstream/libhttp-parser-xs-perl/current/lib/HTTP/Parser/XS.pm
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libhttp-parser-xs-perl/current/lib/HTTP/Parser/XS.pm?rev=63237&op=diff
==============================================================================
--- branches/upstream/libhttp-parser-xs-perl/current/lib/HTTP/Parser/XS.pm (original)
+++ branches/upstream/libhttp-parser-xs-perl/current/lib/HTTP/Parser/XS.pm Sun Oct  3 18:56:15 2010
@@ -11,7 +11,7 @@
 our @EXPORT_OK = @{$EXPORT_TAGS{all}};
 our @EXPORT = ();
 
-our $VERSION = '0.07';
+our $VERSION = '0.09';
 
 require XSLoader;
 XSLoader::load('HTTP::Parser::XS', $VERSION);

Modified: branches/upstream/libhttp-parser-xs-perl/current/picohttpparser/picohttpparser.c
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libhttp-parser-xs-perl/current/picohttpparser/picohttpparser.c?rev=63237&op=diff
==============================================================================
--- branches/upstream/libhttp-parser-xs-perl/current/picohttpparser/picohttpparser.c (original)
+++ branches/upstream/libhttp-parser-xs-perl/current/picohttpparser/picohttpparser.c Sun Oct  3 18:56:15 2010
@@ -1,28 +1,83 @@
 #include <stddef.h>
 #include "picohttpparser.h"
 
+#ifdef __GNUC__
+# define likely(x)	__builtin_expect(!!(x), 1)
+# define unlikely(x)	__builtin_expect(!!(x), 0)
+#else
+# define likely(x) (x)
+# define unlikely(x) (x)
+#endif
+
 #define CHECK_EOF()	\
-  if (buf == buf_end) { \
-    return -2;		\
-  }
-
-#define EXPECT_CHAR(ch)    \
-  CHECK_EOF();	      \
-  if (*buf++ != ch) { \
-    return -1;	      \
-  }
-
-#define ADVANCE_TOKEN()			       \
-  for (; ; ++buf) {			       \
-    CHECK_EOF();			       \
-    if (*buf == ' ') {			       \
-      break;				       \
-    } else if (*buf == '\r' || *buf == '\n') { \
-      return -1;			       \
-    }					       \
-  }
-
-static int is_complete(const char* buf, const char* buf_end, size_t last_len)
+  if (buf == buf_end) {	\
+    *ret = -2;		\
+    return NULL;	\
+  }
+
+#define EXPECT_CHAR(ch) \
+  CHECK_EOF();		\
+  if (*buf++ != ch) {	\
+    *ret = -1;		\
+    return NULL;	\
+  }
+
+#define ADVANCE_TOKEN(tok, toklen) do {		       \
+    const char* tok_start = buf; 		       \
+    for (; ; ++buf) {				       \
+      CHECK_EOF();				       \
+      if (*buf == ' ') {			       \
+	break;					       \
+      } else if (*buf == '\r' || *buf == '\n') {       \
+	*ret = -1;				       \
+	return NULL;				       \
+      }						       \
+    }						       \
+    tok = tok_start;				       \
+    toklen = buf - tok_start;			       \
+  } while (0)
+
+static const char* get_token_to_eol(const char* buf, const char* buf_end,
+				    const char** token, size_t* token_len,
+				    int* ret)
+{
+  const char* token_start = buf;
+  
+  while (1) {
+    if (likely(buf_end - buf >= 16)) {
+      unsigned i;
+      for (i = 0; i < 16; i++, ++buf) {
+	if (unlikely((unsigned char)*buf <= '\r')
+	    && (*buf == '\r' || *buf == '\n')) {
+	  goto EOL_FOUND;
+	}
+      }
+    } else {
+      for (; ; ++buf) {
+	CHECK_EOF();
+	if (unlikely((unsigned char)*buf <= '\r')
+	    && (*buf == '\r' || *buf == '\n')) {
+	  goto EOL_FOUND;
+	}
+      }
+    }
+  }
+ EOL_FOUND:
+  if (*buf == '\r') {
+    ++buf;
+    EXPECT_CHAR('\n');
+    *token_len = buf - 2 - token_start;
+  } else { /* should be: *buf == '\n' */
+    *token_len = buf - token_start;
+    ++buf;
+  }
+  *token = token_start;
+  
+  return buf;
+}
+  
+static const char* is_complete(const char* buf, const char* buf_end,
+			       size_t last_len, int* ret)
 {
   int ret_cnt = 0;
   buf = last_len < 3 ? buf : buf + last_len - 3;
@@ -42,71 +97,53 @@
       ret_cnt = 0;
     }
     if (ret_cnt == 2) {
-      return 0;
-    }
-  }
-  
-  return -2;
-}
-
-int phr_parse_request(const char* _buf, size_t len, const char** method,
-		      size_t* method_len, const char** path, size_t* path_len,
-		      int* minor_version, struct phr_header* headers,
-		      size_t* num_headers, size_t last_len)
-{
-  const char * buf = _buf, * buf_end = buf + len;
-  size_t max_headers;
-  
-  /* if last_len != 0, check if the request is complete (a fast countermeasure
-     againt slowloris */
-  if (last_len != 0) {
-    int r = is_complete(buf, buf_end, last_len);
-    if (r != 0) {
-      return r;
-    }
-  }
-  
-  /* skip first empty line (some clients add CRLF after POST content) */
+      return buf;
+    }
+  }
+  
+  *ret = -2;
+  return NULL;
+}
+
+/* *_buf is always within [buf, buf_end) upon success */
+static const char* parse_int(const char* buf, const char* buf_end, int* value,
+			     int* ret)
+{
+  int v;
   CHECK_EOF();
-  if (*buf == '\r') {
-    ++buf;
-    EXPECT_CHAR('\n');
-  } else if (*buf == '\n') {
-    ++buf;
-  }
-  
-  /* parse request line */
-  *method = buf;
-  ADVANCE_TOKEN();
-  *method_len = buf - *method;
-  ++buf;
-  *path = buf;
-  ADVANCE_TOKEN();
-  *path_len = buf - *path;
-  ++buf;
-  EXPECT_CHAR('H'); EXPECT_CHAR('T'); EXPECT_CHAR('T'); EXPECT_CHAR('P'); EXPECT_CHAR('/'); EXPECT_CHAR('1');
-  EXPECT_CHAR('.');
-  *minor_version = 0;
+  if (! ('0' <= *buf && *buf <= '9')) {
+    *ret = -1;
+    return NULL;
+  }
+  v = 0;
   for (; ; ++buf) {
     CHECK_EOF();
     if ('0' <= *buf && *buf <= '9') {
-      *minor_version = *minor_version * 10 + *buf - '0';
+      v = v * 10 + *buf - '0';
     } else {
       break;
     }
   }
-  if (*buf == '\r') {
-    ++buf;
-    EXPECT_CHAR('\n');
-  } else if (*buf == '\n') {
-    ++buf;
-  } else {
-    return -1;
-  }
-
-  /* parse headers */
-  max_headers = *num_headers;
-  for (*num_headers = 0; ; ++*num_headers) {
+  
+  *value = v;
+  return buf;
+}
+
+/* returned pointer is always within [buf, buf_end), or null */
+static const char* parse_http_version(const char* buf, const char* buf_end,
+				      int* minor_version, int* ret)
+{
+  EXPECT_CHAR('H'); EXPECT_CHAR('T'); EXPECT_CHAR('T'); EXPECT_CHAR('P');
+  EXPECT_CHAR('/'); EXPECT_CHAR('1'); EXPECT_CHAR('.');
+  return parse_int(buf, buf_end, minor_version, ret);
+}
+
+static const char* parse_headers(const char* buf, const char* buf_end,
+				 struct phr_header* headers,
+				 size_t* num_headers, size_t max_headers,
+				 int* ret)
+{
+  for (; ; ++*num_headers) {
     CHECK_EOF();
     if (*buf == '\r') {
       ++buf;
@@ -117,17 +154,20 @@
       break;
     }
     if (*num_headers == max_headers) {
-      return -1;
+      *ret = -1;
+      return NULL;
     }
     if (*num_headers == 0 || ! (*buf == ' ' || *buf == '\t')) {
-      /* parsing name */
+      /* parsing name, but do not discard SP before colon, see
+       * http://www.mozilla.org/security/announce/2006/mfsa2006-33.html */
       headers[*num_headers].name = buf;
       for (; ; ++buf) {
 	CHECK_EOF();
 	if (*buf == ':') {
 	  break;
 	} else if (*buf < ' ') {
-	  return -1;
+	  *ret = -1;
+	  return NULL;
 	}
       }
       headers[*num_headers].name_len = buf - headers[*num_headers].name;
@@ -142,25 +182,146 @@
       headers[*num_headers].name = NULL;
       headers[*num_headers].name_len = 0;
     }
-    headers[*num_headers].value = buf;
-    for (; ; ++buf) {
-      CHECK_EOF();
-      if (*buf == '\r') {
-	headers[*num_headers].value_len = buf - headers[*num_headers].value;
-	++buf;
-	EXPECT_CHAR('\n');
-	break;
-      } else if (*buf == '\n') {
-	headers[*num_headers].value_len = buf - headers[*num_headers].value;
-	++buf;
-	break;
-      }
-    }
-  }
-  
-  return buf - _buf;
+    if ((buf = get_token_to_eol(buf, buf_end, &headers[*num_headers].value,
+				&headers[*num_headers].value_len, ret))
+	== NULL) {
+      return NULL;
+    }
+  }
+  return buf;
+}
+
+const char* parse_request(const char* buf, const char* buf_end,
+			  const char** method, size_t* method_len,
+			  const char** path, size_t* path_len,
+			  int* minor_version, struct phr_header* headers,
+			  size_t* num_headers, size_t max_headers, int* ret)
+{
+  /* skip first empty line (some clients add CRLF after POST content) */
+  CHECK_EOF();
+  if (*buf == '\r') {
+    ++buf;
+    EXPECT_CHAR('\n');
+  } else if (*buf == '\n') {
+    ++buf;
+  }
+  
+  /* parse request line */
+  ADVANCE_TOKEN(*method, *method_len);
+  ++buf;
+  ADVANCE_TOKEN(*path, *path_len);
+  ++buf;
+  if ((buf = parse_http_version(buf, buf_end, minor_version, ret)) == NULL) {
+    return NULL;
+  }
+  if (*buf == '\r') {
+    ++buf;
+    EXPECT_CHAR('\n');
+  } else if (*buf == '\n') {
+    ++buf;
+  } else {
+    *ret = -1;
+    return NULL;
+  }
+  
+  return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
+}
+
+int phr_parse_request(const char* buf_start, size_t len, const char** method,
+		      size_t* method_len, const char** path, size_t* path_len,
+		      int* minor_version, struct phr_header* headers,
+		      size_t* num_headers, size_t last_len)
+{
+  const char * buf = buf_start, * buf_end = buf_start + len;
+  size_t max_headers = *num_headers;
+  int r;
+  
+  *method = NULL;
+  *method_len = 0;
+  *path = NULL;
+  *path_len = 0;
+  *minor_version = -1;
+  *num_headers = 0;
+  
+  /* if last_len != 0, check if the request is complete (a fast countermeasure
+     againt slowloris */
+  if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
+    return r;
+  }
+  
+  if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len,
+			   minor_version, headers, num_headers, max_headers,
+			   &r))
+      == NULL) {
+    return r;
+  }
+  
+  return buf - buf_start;
+}
+
+static const char* parse_response(const char* buf, const char* buf_end,
+				  int* minor_version, int* status,
+				  const char** msg, size_t* msg_len,
+				  struct phr_header* headers,
+				  size_t* num_headers, size_t max_headers,
+				  int* ret)
+{
+  /* parse "HTTP/1.x" */
+  if ((buf = parse_http_version(buf, buf_end, minor_version, ret)) == NULL) {
+    return NULL;
+  }
+  /* skip space */
+  if (*buf++ != ' ') {
+    *ret = -1;
+    return NULL;
+  }
+  /* parse status code */
+  if ((buf = parse_int(buf, buf_end, status, ret)) == NULL) {
+    return NULL;
+  }
+  /* skip space */
+  if (*buf++ != ' ') {
+    *ret = -1;
+    return NULL;
+  }
+  /* get message */
+  if ((buf = get_token_to_eol(buf, buf_end, msg, msg_len, ret)) == NULL) {
+    return NULL;
+  }
+  
+  return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
+}
+
+int phr_parse_response(const char* buf_start, size_t len, int* minor_version,
+		       int* status, const char** msg, size_t* msg_len,
+		       struct phr_header* headers, size_t* num_headers,
+		       size_t last_len)
+{
+  const char * buf = buf_start, * buf_end = buf + len;
+  size_t max_headers = *num_headers;
+  int r;
+  
+  *minor_version = -1;
+  *status = 0;
+  *msg = NULL;
+  *msg_len = 0;
+  *num_headers = 0;
+  
+  /* if last_len != 0, check if the response is complete (a fast countermeasure
+     against slowloris */
+  if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
+    return r;
+  }
+  
+  if ((buf = parse_response(buf, buf_end, minor_version, status, msg, msg_len,
+			    headers, num_headers, max_headers, &r))
+      == NULL) {
+    return r;
+  }
+  
+  return buf - buf_start;
 }
 
 #undef CHECK_EOF
 #undef EXPECT_CHAR
-#undef ADVACE_TOKEN
+#undef ADVANCE_TOKEN

Modified: branches/upstream/libhttp-parser-xs-perl/current/picohttpparser/picohttpparser.h
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libhttp-parser-xs-perl/current/picohttpparser/picohttpparser.h?rev=63237&op=diff
==============================================================================
--- branches/upstream/libhttp-parser-xs-perl/current/picohttpparser/picohttpparser.h (original)
+++ branches/upstream/libhttp-parser-xs-perl/current/picohttpparser/picohttpparser.h Sun Oct  3 18:56:15 2010
@@ -1,5 +1,9 @@
 #ifndef picohttpparser_h
 #define picohttpparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /* contains name and value of a header (name == NULL if is a continuing line
  * of a multiline header */
@@ -18,4 +22,14 @@
 		      struct phr_header* headers, size_t* num_headers,
 		      size_t last_len);
 
+/* ditto */
+int phr_parse_response(const char* _buf, size_t len, int *minor_version,
+              int *status, const char **msg, size_t *msg_len,
+              struct phr_header* headers, size_t* num_headers,
+              size_t last_len);
+
+#ifdef __cplusplus
+}
 #endif
+
+#endif




More information about the Pkg-perl-cvs-commits mailing list