From db106357956d84283dc85ea3e47d512da5113db3 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Thu, 14 Mar 2013 12:11:06 +0100 Subject: Thu Mar 14 12:11:06 CET 2013 --- test/bsd_socket.c | 190 ------------------------------------------- test/bsdsocket.c | 190 +++++++++++++++++++++++++++++++++++++++++++ test/bufbsdsocket.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 419 insertions(+), 190 deletions(-) delete mode 100644 test/bsd_socket.c create mode 100644 test/bsdsocket.c create mode 100644 test/bufbsdsocket.c diff --git a/test/bsd_socket.c b/test/bsd_socket.c deleted file mode 100644 index d4bd5a2..0000000 --- a/test/bsd_socket.c +++ /dev/null @@ -1,190 +0,0 @@ -#define _BSD_SOURCE - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "../picohttp.h" - -int bsdsock_read(size_t count, char *buf, void *data) -{ - int fd = *((int*)data); - - ssize_t rb = 0; - ssize_t r = 0; - do { - r = read(fd, buf+rb, count-rb); - if( 0 < r ) { - rb += r; - continue; - } - if( !r ) { - break; - } - - if( EAGAIN == errno || - EWOULDBLOCK == errno ) { - usleep(100); - continue; - } - return -3 + errno; - } while( rb < count ); - return rb; -} - -int bsdsock_write(size_t count, char const *buf, void *data) -{ - int fd = *((int*)data); - - ssize_t wb = 0; - ssize_t w = 0; - do { - w = write(fd, buf+wb, count-wb); - if( 0 < w ) { - wb += w; - continue; - } - if( !w ) { - break; - } - - if( EAGAIN == errno || - EWOULDBLOCK == errno ) { - usleep(100); - continue; - } - return -3 + errno; - } while( wb < count ); - return wb; -} - -int16_t bsdsock_getch(void *data) -{ - char ch; - if( 1 != bsdsock_read(1, &ch, data) ) - return -1; - return ch; -} - -int bsdsock_putch(char ch, void *data) -{ - return bsdsock_write(1, &ch, data); -} - -int sockfd = -1; - -void bye(void) -{ - fputs("exiting\n", stderr); - int const one = 1; - /* allows for immediate reuse of address:port - * after program termination */ - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); - shutdown(sockfd, SHUT_RDWR); - close(sockfd); -} - -void rhRoot(struct picohttpRequest *req) -{ - fprintf(stderr, "handling request /%s\n", req->urltail); - - char http_header[] = "HTTP/x.x 200 OK\r\nServer: picoweb\r\nContent-Type: text/html\r\n\r\n"; - http_header[5] = '0'+req->httpversion.major; - http_header[7] = '0'+req->httpversion.minor; - picohttpIoWrite(req->ioops, sizeof(http_header)-1, http_header); - char http_test[] = "handling request /\n/test\n"; - - picohttpIoWrite(req->ioops, sizeof(http_test)-1, http_test); -} - -void rhTest(struct picohttpRequest *req) -{ - fprintf(stderr, "handling request /test%s\n", req->urltail); - char http_header[] = "HTTP/x.x 200 OK\r\nServer: picoweb\r\nContent-Type: text/text\r\n\r\n"; - http_header[5] = '0'+req->httpversion.major; - http_header[7] = '0'+req->httpversion.minor; - picohttpIoWrite(req->ioops, sizeof(http_header)-1, http_header); - char http_test[] = "handling request /test"; - picohttpIoWrite(req->ioops, sizeof(http_test)-1, http_test); - if(req->urltail) { - picohttpIoWrite(req->ioops, strlen(req->urltail), req->urltail); - } -} - -int main(int argc, char *argv[]) -{ - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if( -1 == sockfd ) { - perror("socket"); - return -1; - } -#if 0 - if( atexit(bye) ) { - return -1; - } -#endif - - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_port = htons(8000), - .sin_addr = 0 - }; - - int const one = 1; - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); - if( -1 == bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) ) { - perror("bind"); - return -1; - } - - if( -1 == listen(sockfd, 2) ) { - perror("listen"); - return -1; - } - - for(;;) { - socklen_t addrlen = 0; - int confd = accept(sockfd, (struct sockaddr*)&addr, &addrlen); - if( -1 == confd ) { - if( EAGAIN == errno || - EWOULDBLOCK == errno ) { - usleep(1000); - continue; - } else { - perror("accept"); - return -1; - } - } - - struct picohttpIoOps ioops = { - .read = bsdsock_read, - .write = bsdsock_write, - .getch = bsdsock_getch, - .putch = bsdsock_putch, - .data = &confd - }; - - struct picohttpURLRoute routes[] = { - { "/test", 0, rhTest, 16, PICOHTTP_METHOD_GET }, - { "/|", 0, rhRoot, 0, PICOHTTP_METHOD_GET }, - { NULL, 0, 0, 0, 0 } - }; - - picohttpProcessRequest(&ioops, routes); - - shutdown(confd, SHUT_RDWR); - close(confd); - } - - return 0; -} - diff --git a/test/bsdsocket.c b/test/bsdsocket.c new file mode 100644 index 0000000..d4bd5a2 --- /dev/null +++ b/test/bsdsocket.c @@ -0,0 +1,190 @@ +#define _BSD_SOURCE + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "../picohttp.h" + +int bsdsock_read(size_t count, char *buf, void *data) +{ + int fd = *((int*)data); + + ssize_t rb = 0; + ssize_t r = 0; + do { + r = read(fd, buf+rb, count-rb); + if( 0 < r ) { + rb += r; + continue; + } + if( !r ) { + break; + } + + if( EAGAIN == errno || + EWOULDBLOCK == errno ) { + usleep(100); + continue; + } + return -3 + errno; + } while( rb < count ); + return rb; +} + +int bsdsock_write(size_t count, char const *buf, void *data) +{ + int fd = *((int*)data); + + ssize_t wb = 0; + ssize_t w = 0; + do { + w = write(fd, buf+wb, count-wb); + if( 0 < w ) { + wb += w; + continue; + } + if( !w ) { + break; + } + + if( EAGAIN == errno || + EWOULDBLOCK == errno ) { + usleep(100); + continue; + } + return -3 + errno; + } while( wb < count ); + return wb; +} + +int16_t bsdsock_getch(void *data) +{ + char ch; + if( 1 != bsdsock_read(1, &ch, data) ) + return -1; + return ch; +} + +int bsdsock_putch(char ch, void *data) +{ + return bsdsock_write(1, &ch, data); +} + +int sockfd = -1; + +void bye(void) +{ + fputs("exiting\n", stderr); + int const one = 1; + /* allows for immediate reuse of address:port + * after program termination */ + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + shutdown(sockfd, SHUT_RDWR); + close(sockfd); +} + +void rhRoot(struct picohttpRequest *req) +{ + fprintf(stderr, "handling request /%s\n", req->urltail); + + char http_header[] = "HTTP/x.x 200 OK\r\nServer: picoweb\r\nContent-Type: text/html\r\n\r\n"; + http_header[5] = '0'+req->httpversion.major; + http_header[7] = '0'+req->httpversion.minor; + picohttpIoWrite(req->ioops, sizeof(http_header)-1, http_header); + char http_test[] = "handling request /\n/test\n"; + + picohttpIoWrite(req->ioops, sizeof(http_test)-1, http_test); +} + +void rhTest(struct picohttpRequest *req) +{ + fprintf(stderr, "handling request /test%s\n", req->urltail); + char http_header[] = "HTTP/x.x 200 OK\r\nServer: picoweb\r\nContent-Type: text/text\r\n\r\n"; + http_header[5] = '0'+req->httpversion.major; + http_header[7] = '0'+req->httpversion.minor; + picohttpIoWrite(req->ioops, sizeof(http_header)-1, http_header); + char http_test[] = "handling request /test"; + picohttpIoWrite(req->ioops, sizeof(http_test)-1, http_test); + if(req->urltail) { + picohttpIoWrite(req->ioops, strlen(req->urltail), req->urltail); + } +} + +int main(int argc, char *argv[]) +{ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if( -1 == sockfd ) { + perror("socket"); + return -1; + } +#if 0 + if( atexit(bye) ) { + return -1; + } +#endif + + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = htons(8000), + .sin_addr = 0 + }; + + int const one = 1; + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + if( -1 == bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) ) { + perror("bind"); + return -1; + } + + if( -1 == listen(sockfd, 2) ) { + perror("listen"); + return -1; + } + + for(;;) { + socklen_t addrlen = 0; + int confd = accept(sockfd, (struct sockaddr*)&addr, &addrlen); + if( -1 == confd ) { + if( EAGAIN == errno || + EWOULDBLOCK == errno ) { + usleep(1000); + continue; + } else { + perror("accept"); + return -1; + } + } + + struct picohttpIoOps ioops = { + .read = bsdsock_read, + .write = bsdsock_write, + .getch = bsdsock_getch, + .putch = bsdsock_putch, + .data = &confd + }; + + struct picohttpURLRoute routes[] = { + { "/test", 0, rhTest, 16, PICOHTTP_METHOD_GET }, + { "/|", 0, rhRoot, 0, PICOHTTP_METHOD_GET }, + { NULL, 0, 0, 0, 0 } + }; + + picohttpProcessRequest(&ioops, routes); + + shutdown(confd, SHUT_RDWR); + close(confd); + } + + return 0; +} + diff --git a/test/bufbsdsocket.c b/test/bufbsdsocket.c new file mode 100644 index 0000000..27ce6ef --- /dev/null +++ b/test/bufbsdsocket.c @@ -0,0 +1,229 @@ +#define _BSD_SOURCE + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "../picohttp.h" + +#define SENDBUF_LEN 256 + +struct bufbsdsockData { + char * recvbuf; + size_t recvbuf_len; + size_t recvbuf_pos; + char sendbuf[SENDBUF_LEN]; + size_t sendbuf_pos; + int fd; +}; + +int bufbsdsock_read(size_t count, char *buf, void *data_) +{ + struct bufbsdsockData *data = data_; + + ssize_t rb = 0; + ssize_t r = 0; + do { + size_t len = 0; + + if( !data->recvbuf || + data->recvbuf_pos >= data->recvbuf_len ) { + if( data->recvbuf ) + free( data->recvbuf ); + data->recvbuf_len = 0; + data->recvbuf_pos = 0; + + int avail = 0; + do { + struct pollfd pfd = { + .fd = data->fd, + .events = POLLIN | POLLPRI, + .revents = 0 + }; + + int const pret = poll(&pfd, 1, -1); + if( 0 >= pret ) { + return -1; + } + + assert(pfd.revents & (POLLIN | POLLPRI)); + + if( -1 == ioctl(fd, FIONREAD, &avail) ) { + perror("ioctl(FIONREAD)"); + return -1; + } + } while( !avail ); + + data->recvbuf = malloc( avail); + + int r; + while( 0 > (r = read(data->fd, data->recvbuf, avail)) ) + if( EINTR == errno ) + continue; + + if( EAGAIN == errno || + EWOULDBLOCK == errno ) { + usleep(200); + continue; + } + + return -1; + } + data->recvbuf_len += r; + } + + len = data->recvbuf_len - data->recvbuf_pos; + if( len > count ) + len = count; + + rb += len; + } while( rb < count ); + return rb; +} + +int bufbsdsock_write(size_t count, char const *buf, void *data) +{ + int fd = *((int*)data); + + ssize_t wb = 0; + ssize_t w = 0; + do { + } while( wb < count ); + return wb; +} + +int16_t bufbsdsock_getch(void *data) +{ + char ch; + if( 1 != bufbsdsock_read(1, &ch, data) ) + return -1; + return ch; +} + +int bufbsdsock_putch(char ch, void *data) +{ + return bufbsdsock_write(1, &ch, data); +} + +int bufbsdsock_flush(void *data) +{ + return 0; +} + +int sockfd = -1; + +void bye(void) +{ + fputs("exiting\n", stderr); + int const one = 1; + /* allows for immediate reuse of address:port + * after program termination */ + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + shutdown(sockfd, SHUT_RDWR); + close(sockfd); +} + +void rhRoot(struct picohttpRequest *req) +{ + fprintf(stderr, "handling request /%s\n", req->urltail); + + char http_header[] = "HTTP/x.x 200 OK\r\nServer: picoweb\r\nContent-Type: text/html\r\n\r\n"; + http_header[5] = '0'+req->httpversion.major; + http_header[7] = '0'+req->httpversion.minor; + picohttpIoWrite(req->ioops, sizeof(http_header)-1, http_header); + char http_test[] = "handling request /\n/test\n"; + + picohttpIoWrite(req->ioops, sizeof(http_test)-1, http_test); +} + +void rhTest(struct picohttpRequest *req) +{ + fprintf(stderr, "handling request /test%s\n", req->urltail); + char http_header[] = "HTTP/x.x 200 OK\r\nServer: picoweb\r\nContent-Type: text/text\r\n\r\n"; + http_header[5] = '0'+req->httpversion.major; + http_header[7] = '0'+req->httpversion.minor; + picohttpIoWrite(req->ioops, sizeof(http_header)-1, http_header); + char http_test[] = "handling request /test"; + picohttpIoWrite(req->ioops, sizeof(http_test)-1, http_test); + if(req->urltail) { + picohttpIoWrite(req->ioops, strlen(req->urltail), req->urltail); + } +} + +int main(int argc, char *argv[]) +{ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if( -1 == sockfd ) { + perror("socket"); + return -1; + } +#if 0 + if( atexit(bye) ) { + return -1; + } +#endif + + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = htons(8000), + .sin_addr = 0 + }; + + int const one = 1; + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + if( -1 == bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) ) { + perror("bind"); + return -1; + } + + if( -1 == listen(sockfd, 2) ) { + perror("listen"); + return -1; + } + + for(;;) { + socklen_t addrlen = 0; + int confd = accept(sockfd, (struct sockaddr*)&addr, &addrlen); + if( -1 == confd ) { + if( EAGAIN == errno || + EWOULDBLOCK == errno ) { + usleep(1000); + continue; + } else { + perror("accept"); + return -1; + } + } + + struct picohttpIoOps ioops = { + .read = bsdsock_read, + .write = bsdsock_write, + .getch = bsdsock_getch, + .putch = bsdsock_putch, + .data = &confd + }; + + struct picohttpURLRoute routes[] = { + { "/test", 0, rhTest, 16, PICOHTTP_METHOD_GET }, + { "/|", 0, rhRoot, 0, PICOHTTP_METHOD_GET }, + { NULL, 0, 0, 0, 0 } + }; + + picohttpProcessRequest(&ioops, routes); + + shutdown(confd, SHUT_RDWR); + close(confd); + } + + return 0; +} + -- cgit v1.2.3 From 7fbc390e87ce671eda9cd756d07c2d81d4b79831 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Thu, 14 Mar 2013 20:11:44 +0100 Subject: Thu Mar 14 20:11:44 CET 2013 --- picohttp.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/picohttp.c b/picohttp.c index e3762f1..1c2a16e 100644 --- a/picohttp.c +++ b/picohttp.c @@ -19,6 +19,9 @@ static char const PICOHTTP_STR__CODING[] = "-Coding"; static char const PICOHTTP_STR_CACHECONTROL[] = "Cache-Control"; +static char const PICOHTTP_STR_CONNECTION[] = "Connection"; +static char const PICOHTTP_STR_CLOSE[] = "close"; + static char const PICOHTTP_STR_DATE[] = "Date"; static char const PICOHTTP_STR_EXPECT[] = "Expect"; @@ -650,6 +653,13 @@ int picohttpResponseSendHeaders ( 0 > (e = picohttpIO_WRITE_STATIC_STR(PICOHTTP_STR_CRLF)) ) return e; + /* Connection header -- for now this is "Connection: close" */ + if( 0 > (e = picohttpIO_WRITE_STATIC_STR(PICOHTTP_STR_CONNECTION)) || + 0 > (e = picohttpIO_WRITE_STATIC_STR(PICOHTTP_STR_CLSP)) || + 0 > (e = picohttpIO_WRITE_STATIC_STR(PICOHTTP_STR_CLOSE)) || + 0 > (e = picohttpIO_WRITE_STATIC_STR(PICOHTTP_STR_CRLF)) ) + return e; + /* Content-Type header */ if( 0 > (e = picohttpIO_WRITE_STATIC_STR(PICOHTTP_STR_CONTENT)) || 0 > (e = picohttpIO_WRITE_STATIC_STR(PICOHTTP_STR__TYPE)) || @@ -660,6 +670,7 @@ int picohttpResponseSendHeaders ( 0 > (e = picohttpIO_WRITE_STATIC_STR(PICOHTTP_STR_CRLF)) ) return e; + /* Content-Length header */ if( req->response.contentlength ){ p = picohttp_fmt_uint(tmp, req->response.contentlength); if( 0 > (e = picohttpIO_WRITE_STATIC_STR(PICOHTTP_STR_CONTENT)) || -- cgit v1.2.3 From 2d980f042719e6971d84c3293438b1416b16ffbe Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Mon, 18 Mar 2013 21:01:31 +0100 Subject: Mon Mar 18 21:01:31 CET 2013 --- coroutine.h | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ picohttp.c | 1 + 2 files changed, 182 insertions(+) create mode 100644 coroutine.h diff --git a/coroutine.h b/coroutine.h new file mode 100644 index 0000000..d54a718 --- /dev/null +++ b/coroutine.h @@ -0,0 +1,181 @@ +/* coroutine.h + * + * Coroutine mechanics, implemented on top of standard ANSI C. See + * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html for + * a full discussion of the theory behind this. + * + * To use these macros to define a coroutine, you need to write a + * function that looks something like this. + * + * [Simple version using static variables (scr macros)] + * int ascending (void) { + * static int i; + * + * scrBegin; + * for (i=0; i<10; i++) { + * scrReturn(i); + * } + * scrFinish(-1); + * } + * + * [Re-entrant version using an explicit context structure (ccr macros)] + * int ascending (ccrContParam) { + * ccrBeginContext; + * int i; + * ccrEndContext(foo); + * + * ccrBegin(foo); + * for (foo->i=0; foo->i<10; foo->i++) { + * ccrReturn(foo->i); + * } + * ccrFinish(-1); + * } + * + * In the static version, you need only surround the function body + * with `scrBegin' and `scrFinish', and then you can do `scrReturn' + * within the function and on the next call control will resume + * just after the scrReturn statement. Any local variables you need + * to be persistent across an `scrReturn' must be declared static. + * + * In the re-entrant version, you need to declare your persistent + * variables between `ccrBeginContext' and `ccrEndContext'. These + * will be members of a structure whose name you specify in the + * parameter to `ccrEndContext'. + * + * The re-entrant macros will malloc() the state structure on first + * call, and free() it when `ccrFinish' is reached. If you want to + * abort in the middle, you can use `ccrStop' to free the state + * structure immediately (equivalent to an explicit return() in a + * caller-type routine). + * + * A coroutine returning void type may call `ccrReturnV', + * `ccrFinishV' and `ccrStopV', or `scrReturnV', to avoid having to + * specify an empty parameter to the ordinary return macros. + * + * Ground rules: + * - never put `ccrReturn' or `scrReturn' within an explicit `switch'. + * - never put two `ccrReturn' or `scrReturn' statements on the same + * source line. + * + * The caller of a static coroutine calls it just as if it were an + * ordinary function: + * + * void main(void) { + * int i; + * do { + * i = ascending(); + * printf("got number %d\n", i); + * } while (i != -1); + * } + * + * The caller of a re-entrant coroutine must provide a context + * variable: + * + * void main(void) { + * ccrContext z = 0; + * do { + * printf("got number %d\n", ascending (&z)); + * } while (z); + * } + * + * Note that the context variable is set back to zero when the + * coroutine terminates (by crStop, or by control reaching + * crFinish). This can make the re-entrant coroutines more useful + * than the static ones, because you can tell when they have + * finished. + * + * If you need to dispose of a crContext when it is non-zero (that + * is, if you want to stop calling a coroutine without suffering a + * memory leak), the caller should call `ccrAbort(ctx)' where `ctx' + * is the context variable. + * + * This mechanism could have been better implemented using GNU C + * and its ability to store pointers to labels, but sadly this is + * not part of the ANSI C standard and so the mechanism is done by + * case statements instead. That's why you can't put a crReturn() + * inside a switch() statement. + */ + +/* + * coroutine.h is copyright 1995,2000 Simon Tatham. + * + * 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 SIMON TATHAM 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. + * + * $Id$ + */ + +#ifndef COROUTINE_H +#define COROUTINE_H + +#include + +/* + * `scr' macros for static coroutines. + */ + +#define scrBegin static int scrLine = 0; switch(scrLine) { case 0:; +#define scrFinish(z) } return (z) +#define scrFinishV } return + +#define scrReturn(z) \ + do {\ + scrLine=__LINE__;\ + return (z); case __LINE__:;\ + } while (0) +#define scrReturnV \ + do {\ + scrLine=__LINE__;\ + return; case __LINE__:;\ + } while (0) + +/* + * `ccr' macros for re-entrant coroutines. + */ + +#define ccrContParam void **ccrParam + +#define ccrBeginContext struct ccrContextTag { int ccrLine +#define ccrEndContext(x) } *x = (struct ccrContextTag *)*ccrParam + +#define ccrBegin(x) if(!x) {x= *ccrParam=malloc(sizeof(*x)); x->ccrLine=0;}\ + if (x) switch(x->ccrLine) { case 0:; +#define ccrFinish(z) } free(*ccrParam); *ccrParam=0; return (z) +#define ccrFinishV } free(*ccrParam); *ccrParam=0; return + +#define ccrReturn(z) \ + do {\ + ((struct ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\ + return (z); case __LINE__:;\ + } while (0) +#define ccrReturnV \ + do {\ + ((struct ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\ + return; case __LINE__:;\ + } while (0) + +#define ccrStop(z) do{ free(*ccrParam); *ccrParam=0; return (z); }while(0) +#define ccrStopV do{ free(*ccrParam); *ccrParam=0; return; }while(0) + +#define ccrContext void * +#define ccrAbort(ctx) do { free (ctx); ctx = 0; } while (0) + +#endif /* COROUTINE_H */ diff --git a/picohttp.c b/picohttp.c index e3762f1..7e56de1 100644 --- a/picohttp.c +++ b/picohttp.c @@ -53,6 +53,7 @@ static size_t picohttp_fmt_int(char *dest,int i) { return picohttp_fmt_uint(dest, i); } #else +#include #define picohttp_fmt_uint fmt_ulong #define picohttp_fmt_int fmt_long #endif -- cgit v1.2.3 From 660e0aaecd654c0ed99001cd765693dc9fb8a66d Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Tue, 23 Apr 2013 17:12:22 +0200 Subject: Tue Apr 23 17:12:22 CEST 2013 --- picohttp.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/picohttp.h b/picohttp.h index 041f124..6041935 100644 --- a/picohttp.h +++ b/picohttp.h @@ -79,6 +79,17 @@ struct picohttpURLRoute { int16_t allowed_methods; }; +#define PICOHTTP_EPOCH_YEAR 1980 + +struct picohttpDateTime { + unsigned int Y:7; /* EPOCH + 127 years */ + unsigned int M:4; + unsigned int D:5; + unsigned int h:5; + unsigned int m:6; + unsigned int s:5; /* seconds / 2 */ +}; + struct picohttpRequest { struct picohttpIoOps const * ioops; struct picohttpURLRoute const * route; @@ -99,9 +110,9 @@ struct picohttpRequest { } query; struct { char const *contenttype; - char const *date; - char const *cachecontrol; char const *disposition; + struct picohttpDateTime lastmodified; + uint16_t max_age; size_t contentlength; uint8_t contentencoding; uint8_t transferencoding; -- cgit v1.2.3 From 813d72a2d1a4305811b39607828a9f49daadb2ab Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Tue, 18 Jun 2013 00:53:25 +0200 Subject: Added API declarations for Chunked Tranfer transport and Multipart Encoding support. --- picohttp.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/picohttp.h b/picohttp.h index 041f124..d94172b 100644 --- a/picohttp.h +++ b/picohttp.h @@ -127,4 +127,15 @@ int picohttpResponseWrite ( size_t len, char const *buf ); +uint16_t picohttpGetch( + struct picohttpRequest * const req, + struct picohttpChunkTransfer * const ct); + +int picohttpMultipartNext( + struct picohttpRequest * const req, + struct picohttpMultiPart * const mp); + +uint16_t picohttpMultipartGetch( + struct picohttpMultiPart * const mp); + #endif/*PICOHTTP_H_HEADERGUARD*/ -- cgit v1.2.3 From fc9f3c0bde26bc882bdfe1ec0435ade8b60172f4 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Tue, 18 Jun 2013 00:55:27 +0200 Subject: Epoch for datetime struct changed to 1970 --- picohttp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/picohttp.h b/picohttp.h index 95ac0e7..803587d 100644 --- a/picohttp.h +++ b/picohttp.h @@ -79,7 +79,7 @@ struct picohttpURLRoute { int16_t allowed_methods; }; -#define PICOHTTP_EPOCH_YEAR 1980 +#define PICOHTTP_EPOCH_YEAR 1970 struct picohttpDateTime { unsigned int Y:7; /* EPOCH + 127 years */ -- cgit v1.2.3