Commit 8a2629fa authored by Martin Karsten's avatar Martin Karsten

- remove local copes of errnoname and picohttpparser

parent b50ebe2e
Pipeline #40124 failed with stage
in 2 seconds
Subproject commit 81fe3d99fd90a55cafb993e53fd3000dbc4d564c
# requires clang-format >= 3.6
BasedOnStyle: "LLVM"
IndentWidth: 4
ColumnLimit: 132
BreakBeforeBraces: Linux
AllowShortFunctionsOnASingleLine: None
SortIncludes: false
language: c
compiler:
- gcc
- clang
script:
- make test
project picohttpparser ;
lib picohttpparser : picohttpparser.c ;
unit-test test
: picohttpparser picotest/picotest.c test.c
: <testing.launcher>prove ;
#
# Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
# Shigeo Mitsunari
#
# The software is licensed under either the MIT License (below) or the Perl
# license.
#
# 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.
CC?=gcc
PROVE?=prove
all:
test: test-bin
$(PROVE) -v ./test-bin
test-bin: picohttpparser.c picotest/picotest.c test.c
$(CC) -Wall $(CFLAGS) $(LDFLAGS) -o $@ $^
clean:
rm -f test-bin
.PHONY: test
PicoHTTPParser
=============
Copyright (c) 2009-2014 [Kazuho Oku](https://github.com/kazuho), [Tokuhiro Matsuno](https://github.com/tokuhirom), [Daisuke Murase](https://github.com/typester), [Shigeo Mitsunari](https://github.com/herumi)
PicoHTTPParser is a tiny, primitive, fast HTTP request/response parser.
Unlike most parsers, it is stateless and does not allocate memory by itself.
All it does is accept pointer to buffer and the output structure, and setups the pointers in the latter to point at the necessary portions of the buffer.
The code is widely deployed within Perl applications through popular modules that use it, including [Plack](https://metacpan.org/pod/Plack), [Starman](https://metacpan.org/pod/Starman), [Starlet](https://metacpan.org/pod/Starlet), [Furl](https://metacpan.org/pod/Furl). It is also the HTTP/1 parser of [H2O](https://github.com/h2o/h2o).
Check out [test.c] to find out how to use the parser.
The software is dual-licensed under the Perl License or the MIT License.
Usage
-----
The library exposes four functions: `phr_parse_request`, `phr_parse_response`, `phr_parse_headers`, `phr_decode_chunked`.
### phr_parse_request
The example below reads an HTTP request from socket `sock` using `read(2)`, parses it using `phr_parse_request`, and prints the details.
```c
char buf[4096], *method, *path;
int pret, minor_version;
struct phr_header headers[100];
size_t buflen = 0, prevbuflen = 0, method_len, path_len, num_headers;
ssize_t rret;
while (1) {
/* read the request */
while ((rret = read(sock, buf + buflen, sizeof(buf) - buflen)) == -1 && errno == EINTR)
;
if (rret <= 0)
return IOError;
prevbuflen = buflen;
buflen += rret;
/* parse the request */
num_headers = sizeof(headers) / sizeof(headers[0]);
pret = phr_parse_request(buf, buflen, &method, &method_len, &path, &path_len,
&minor_version, headers, &num_headers, prevbuflen);
if (pret > 0)
break; /* successfully parsed the request */
else if (pret == -1)
return ParseError;
/* request is incomplete, continue the loop */
assert(pret == -2);
if (buflen == sizeof(buf))
return RequestIsTooLongError;
}
printf("request is %d bytes long\n", pret);
printf("method is %.*s\n", (int)method_len, method);
printf("path is %.*s\n", (int)path_len, path);
printf("HTTP version is 1.%d\n", minor_version);
printf("headers:\n");
for (i = 0; i != num_headers; ++i) {
printf("%.*s: %.*s\n", (int)headers[i].name_len, headers[i].name,
(int)headers[i].value_len, headers[i].value);
}
```
### phr_parse_response, phr_parse_headers
`phr_parse_response` and `phr_parse_headers` provide similar interfaces as `phr_parse_request`. `phr_parse_response` parses an HTTP response, and `phr_parse_headers` parses the headers only.
### phr_decode_chunked
The example below decodes incoming data in chunked-encoding. The data is decoded in-place.
```c
struct phr_chunked_decoder decoder = {}; /* zero-clear */
char *buf = malloc(4096);
size_t size = 0, capacity = 4096, rsize;
ssize_t rret, pret;
/* set consume_trailer to 1 to discard the trailing header, or the application
* should call phr_parse_headers to parse the trailing header */
decoder.consume_trailer = 1;
do {
/* expand the buffer if necessary */
if (size == capacity) {
capacity *= 2;
buf = realloc(buf, capacity);
assert(buf != NULL);
}
/* read */
while ((rret = read(sock, buf + size, capacity - size)) == -1 && errno == EINTR)
;
if (rret <= 0)
return IOError;
/* decode */
rsize = rret;
pret = phr_decode_chunked(&decoder, buf + size, &rsize);
if (pret == -1)
return ParseError;
size += rsize;
} while (pret == -2);
/* successfully decoded the chunked data */
assert(pret >= 0);
printf("decoded data is at %p (%zu bytes)\n", buf, size);
```
Benchmark
---------
![benchmark results](http://i.gyazo.com/a85c18d3162dfb46b485bb41e0ad443a.png)
The benchmark code is from [fukamachi/fast-http@6b91103](https://github.com/fukamachi/fast-http/tree/6b9110347c7a3407310c08979aefd65078518478).
The internals of picohttpparser has been described to some extent in [my blog entry]( http://blog.kazuhooku.com/2014/11/the-internals-h2o-or-how-to-write-fast.html).
/*
* Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
* Shigeo Mitsunari
*
* The software is licensed under either the MIT License (below) or the Perl
* license.
*
* 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 <stdio.h>
#include "picohttpparser.h"
#define REQ \
"GET /wp-content/uploads/2010/03/hello-kitty-darth-vader-pink.jpg HTTP/1.1\r\n" \
"Host: www.kittyhell.com\r\n" \
"User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 " \
"Pathtraq/0.9\r\n" \
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" \
"Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n" \
"Accept-Encoding: gzip,deflate\r\n" \
"Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n" \
"Keep-Alive: 115\r\n" \
"Connection: keep-alive\r\n" \
"Cookie: wp_ozh_wsa_visits=2; wp_ozh_wsa_visit_lasttime=xxxxxxxxxx; " \
"__utma=xxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.x; " \
"__utmz=xxxxxxxxx.xxxxxxxxxx.x.x.utmccn=(referral)|utmcsr=reader.livedoor.com|utmcct=/reader/|utmcmd=referral\r\n" \
"\r\n"
int main(void)
{
const char *method;
size_t method_len;
const char *path;
size_t path_len;
int minor_version;
struct phr_header headers[32];
size_t num_headers;
int i, ret;
for (i = 0; i < 10000000; i++) {
num_headers = sizeof(headers) / sizeof(headers[0]);
ret = phr_parse_request(REQ, sizeof(REQ) - 1, &method, &method_len, &path, &path_len, &minor_version, headers, &num_headers,
0);
assert(ret == sizeof(REQ) - 1);
}
return 0;
}
This diff is collapsed.
/*
* Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
* Shigeo Mitsunari
*
* The software is licensed under either the MIT License (below) or the Perl
* license.
*
* 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 picohttpparser_h
#define picohttpparser_h
#include <sys/types.h>
#ifdef _MSC_VER
#define ssize_t intptr_t
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* contains name and value of a header (name == NULL if is a continuing line
* of a multiline header */
struct phr_header {
const char *name;
size_t name_len;
const char *value;
size_t value_len;
};
/* returns number of bytes consumed if successful, -2 if request is partial,
* -1 if failed */
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);
/* 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);
/* ditto */
int phr_parse_headers(const char *buf, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len);
/* should be zero-filled before start */
struct phr_chunked_decoder {
size_t bytes_left_in_chunk; /* number of bytes left in current chunk */
char consume_trailer; /* if trailing headers should be consumed */
char _hex_count;
char _state;
};
/* the function rewrites the buffer given as (buf, bufsz) removing the chunked-
* encoding headers. When the function returns without an error, bufsz is
* updated to the length of the decoded data available. Applications should
* repeatedly call the function while it returns -2 (incomplete) every time
* supplying newly arrived data. If the end of the chunked-encoded data is
* found, the function returns a non-negative number indicating the number of
* octets left undecoded at the tail of the supplied buffer. Returns -1 on
* error.
*/
ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t *bufsz);
/* returns if the chunked decoder is in middle of chunked data */
int phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder);
#ifdef __cplusplus
}
#endif
#endif
This diff is collapsed.
Subproject commit c8b427a871305e37f826a07231d7b0730fa3b5bf
Copyright 2019 Alexander Kozhevnikov <mentalisttraceur@gmail.com>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# `errnoname` - The `errno` Name Library
Finally, a way to get the symbolic name of `errno`!
`errnoname` is
1. A C library that provides a way to get the symbolic
name string for each `errno` integer value.
2. A list of `errno` names in use on many operating systems.
3. A handful of simple scripts for gathering that list of
`errno` names and generating the library code from it.
# Usage
## API
The library has a single function:
```c
char const * errnoname(int)
```
Pass an `errno` value in, get back a pointer to
a null-terminated string containing the name.
If the `errno` value does not match a known name, a null pointer is
returned. (This includes `errno` value `0` on all modern systems.)
This function is always thread-safe and reentrant.
This function never sets `errno`.
## Example
Here is a "hello world" with error handling:
```c
#include <errno.h> /* errno */
#include <stdio.h> /* EOF, fflush, fprintf, fputs, stderr, stdout */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include "errnoname.h" /* errnoname */
int main(int argc, char * * argv)
{
char const * error_name;
/* `fputs` and `fflush` return `EOF` for all errors: */
if(fputs("Hello world\n", stdout) != EOF
&& fflush(stdout) != EOF)
{
return EXIT_SUCCESS;
}
/* since `fputs` or `fflush` failed, `errno` should be */
/* the error from the underlying `write` on most systems: */
error_name = errnoname(errno);
/* check if null, which means this `errno` value is unknown: */
if(!error_name)
{
fprintf(stderr, "unknown error number: %d\n", errno);
}
else
{
fprintf(stderr, "error: %s\n", error_name);
}
return EXIT_FAILURE;
}
```
## C Name Collisions
The `errnoname.h` header will only ever define identifiers
whose first nine characters are `errnoname` or `ERRNONAME`.
So names like `errno_name`, `errnoName`, `ErrnoName`, or
`ERRNO_NAME` will always remain available for you to use.
## Building
Just compile and link `errnoname.c` as normal.
You can ignore all the other files in here -
they are not needed to use the library.
## Optimization
The *default* implementation in `errnoname.c` might not always produce
the most efficient code, because it is instead optimized to be:
1. Simple - trivial for a human to mentally verify as robustly correct,
with minimal room for edge cases to slip past human thinking.
2. Portable - code as portable as possible, no unportable assumptions
(except perhaps to guide optimizations without changing
correctness or introducing pathological worst-case behavior).
3. Optimizer-friendly - code optimized for optimization eventually
performs as well or better than code optimized for performance.
4. Safe - well-defined and well-bounded worst-case runspace and runtime
even with pathological `errno` values (such as `-1` or `INT_MAX`).
However, if you need better execution speed or code size, and
you understand the downsides relative to the above four points,
`errnoname.c` provides an option you can enable at compile-time:
* If `ERRNONAME_SAFE_TO_USE_ARRAY` is defined, `errnoname.c`
will trust that it is safe to do the name lookups by using
an array of `errno` names indexed by `errno` values.
Note that modern compilers can already do this automatically
in common cases when optimizations are turned up high enough.
# Contributing
The best way to help this library is making sure that
we have the best coverage of `errno` names possible:
* Check if the `gather-errno-names.sh` script has the
most complete and up-to-date sources of information
for `errno` names - maybe you know of a better way
to get the latest ones for some system.
* Check if the errno list file is missing any of the
`errno` names that exist on the systems you use.
* Check if all `errno` names that might be equivalent
on some systems are handled in the generate script.
You can also help by sharing your use-cases, what features you want,
and design suggestions - the `errnoname` function is a good minimal
foundation, but there might be other features or performance
optimizations worth doing.
And finally, this can be more than a C library -
let's expand it to every language that needs it!
E2BIG
EACCES
EADDRINUSE
EADDRNOTAVAIL
EADI
EADV
EAFNOSUPPORT
EAGAIN
EAIO
EALIGN
EALREADY
EASYNC
EAUTH
EBADARCH
EBADE
EBADEXEC
EBADF
EBADFD
EBADMACHO
EBADMSG
EBADR
EBADRPC
EBADRQC
EBADSLT
EBADVER
EBFONT
EBUSY
ECANCELED
ECANCELLED
ECAPMODE
ECASECLASH
ECHILD
ECHRNG
ECICS
ECKPT
ECLONEME
ECOMM
ECONFIG
ECONNABORTED
ECONNREFUSED
ECONNRESET
ECORRUPT
ECVCERORR
ECVPERORR
EDEADLK
EDEADLOCK
EDESTADDREQ
EDESTADDRREQ
EDEVERR
EDIRIOCTL
EDIRTY
EDIST
EDOM
EDOOFUS
EDOTDOT
EDQUOT
EDUPFD
EDUPPKG
EEXIST
EFAIL
EFAULT
EFBIG
EFORMAT
EFSCORRUPTED
EFTYPE
EHOSTDOWN
EHOSTUNREACH
EHWPOISON
EIBMBADCALL
EIBMBADPARM
EIBMCANCELLED
EIBMCONFLICT
EIBMIUCVERR
EIBMSOCKINUSE
EIBMSOCKOUTOFRANGE
EIDRM
EILSEQ
EINIT
EINPROG
EINPROGRESS
EINTEGRITY
EINTR
EINTRNODATA
EINVAL
EIO
EIPSEC
EISCONN
EISDIR
EISNAM
EJUSTRETURN
EKEEPLOOKING
EKEYEXPIRED
EKEYREJECTED
EKEYREVOKED
EL2HLT
EL2NSYNC
EL3HLT
EL3RST
ELBIN
ELEMSGERR
ELEMULTITHREAD
ELEMULTITHREADFORK
ELENOFORK
ELIBACC
ELIBBAD
ELIBEXEC
ELIBMAX
ELIBSCN
ELNRNG
ELOCKUNMAPPED
ELOOP
EMEDIA
EMEDIUMTYPE
EMFILE
EMLINK
EMOUNTEXIT
EMOVEFD
EMSGSIZE
EMTIMERS
EMULTIHOP
EMVSBADCHAR
EMVSCATLG
EMVSCPLERROR
EMVSCVAF
EMVSDYNALC
EMVSERR
EMVSEXPIRE
EMVSINITIAL
EMVSNORTL
EMVSNOTXP
EMVSPARM
EMVSPASSWORD
EMVSPATHOPTS
EMVSPFSFILE
EMVSPFSPERM
EMVSSAF2ERR
EMVSSAFEXTRERR
EMVSTODNOTSET
ENAMETOOLONG
ENAVAIL
ENEEDAUTH
ENETDOWN
ENETRESET
ENETUNREACH
ENFILE
ENFSREMOTE
ENMFILE
ENOANO
ENOATTR
ENOBUFS
ENOCONNECT
ENOCSI
ENODATA
ENODEV
ENOENT
ENOEXEC
ENOIOCTL
ENOKEY
ENOLCK
ENOLINK
ENOLOAD
ENOMATCH
ENOMEDIUM
ENOMEM
ENOMSG
ENONET
ENOPKG
ENOPOLICY
ENOPROTOOPT
ENOREG
ENOREUSE
ENOSHARE
ENOSPC
ENOSR
ENOSTR
ENOSYM
ENOSYS
ENOTACTIVE
ENOTBLK
ENOTCAPABLE
ENOTCONN
ENOTDIR
ENOTEMPTY
ENOTNAM
ENOTREADY
ENOTRECOVERABLE
ENOTRUST
ENOTSOCK
ENOTSUP
ENOTTY
ENOTUNIQ
ENOUNLD
ENOUNREG
ENXIO
EOFFLOADboxDOWN
EOFFLOADboxERROR
EOFFLOADboxRESTART
EOPCOMPLETE
EOPNOTSUPP
EOVERFLOW
EOWNERDEAD
EPASSTHROUGH
EPATHREMOTE