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