# HG changeset patch # User Olaf Wintermann # Date 1321188181 -3600 # Node ID 998844b5ed25678e81b014c51bf6cfaa5370cf34 # Parent 1371978313065145c6743245a80925d5d31d7768 Added some protocol functions diff -r 137197831306 -r 998844b5ed25 src/server/httplistener.c --- a/src/server/httplistener.c Sun Oct 30 16:26:57 2011 +0100 +++ b/src/server/httplistener.c Sun Nov 13 13:43:01 2011 +0100 @@ -150,7 +150,7 @@ for (;;) { /* accept connections */ struct sockaddr_in ca; - int length = sizeof(ca); + socklen_t length = sizeof(ca); int clientfd; /* accept a connection */ diff -r 137197831306 -r 998844b5ed25 src/server/io.c --- a/src/server/io.c Sun Oct 30 16:26:57 2011 +0100 +++ b/src/server/io.c Sun Nov 13 13:43:01 2011 +0100 @@ -28,8 +28,10 @@ #include #include +#include #include "io.h" +#include "pool.h" IOStream native_io_funcs = { system_write, @@ -51,3 +53,33 @@ ssize_t system_read(IOStream *st, void *buf, size_t nbytes) { return read(((SystemIOStream*)st)->fd, buf, nbytes); } + + +/* iovec buffer */ +iovec_buf_t *iovec_buf_create(pool_handle_t *pool) { + iovec_buf_t *buf = pool_malloc(pool, sizeof(iovec_buf_t)); + + buf->pool = pool; + buf->iov = pool_calloc(pool, 32, sizeof(struct iovec)); + buf->maxiovec = 32; + buf->iovctn = 0; + + return buf; +} + +void iovec_buf_write(iovec_buf_t *io, void *buf, size_t nbyte) { + if(io->iovctn >= io->maxiovec) { + io->iov = pool_realloc( + io->pool, + io->iov, + (io->maxiovec + 16) * sizeof(struct iovec)); + } + + io->iov[io->iovctn].iov_base = buf; + io->iov[io->iovctn].iov_len = nbyte; + io->iovctn++; +} + +ssize_t iovec_buf_flush(iovec_buf_t *io, int fd) { + return writev(fd, io->iov, io->iovctn); +} diff -r 137197831306 -r 998844b5ed25 src/server/io.h --- a/src/server/io.h Sun Oct 30 16:26:57 2011 +0100 +++ b/src/server/io.h Sun Nov 13 13:43:01 2011 +0100 @@ -29,6 +29,8 @@ #ifndef IOSTREAM_H #define IOSTREAM_H +#include "nsapi.h" + #ifdef __cplusplus extern "C" { #endif @@ -49,12 +51,28 @@ } SystemIOStream; +/* iovec buffer */ +typedef struct iovec_buf{ + struct iovec *iov; + int iovctn; + int maxiovec; + pool_handle_t *pool; +} iovec_buf_t; + + +/* system stream */ IOStream* stream_new_from_fd(int fd); - ssize_t system_write(IOStream *st, void *buf, size_t nbytes); ssize_t system_read(IOStream *st, void *buf, size_t nbytes); + +/* iovec buffer */ +iovec_buf_t *iovec_buf_create(pool_handle_t *pool); +void iovec_buf_write(iovec_buf_t *io, void *buf, size_t nbyte); +ssize_t iovec_buf_flush(iovec_buf_t *io, int fd); + + #ifdef __cplusplus } #endif diff -r 137197831306 -r 998844b5ed25 src/server/main.c --- a/src/server/main.c Sun Oct 30 16:26:57 2011 +0100 +++ b/src/server/main.c Sun Nov 13 13:43:01 2011 +0100 @@ -39,7 +39,8 @@ #include "httprequest.h" void test() { - exit(0); + pool_handle_t *pool = pool_create(); + } int main(int argc, char **argv) { diff -r 137197831306 -r 998844b5ed25 src/server/objs.mk --- a/src/server/objs.mk Sun Oct 30 16:26:57 2011 +0100 +++ b/src/server/objs.mk Sun Nov 13 13:43:01 2011 +0100 @@ -57,7 +57,7 @@ MOBJ += object.o MOBJ += nametrans.o MOBJ += service.o - +MOBJ += protocol.o MAINOBJS = $(MOBJ:%=$(OBJPRE)%) diff -r 137197831306 -r 998844b5ed25 src/server/protocol.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/protocol.c Sun Nov 13 13:43:01 2011 +0100 @@ -0,0 +1,268 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "protocol.h" + +#include "pblock.h" +#include "pool.h" +#include "session.h" +#include "io.h" + + + + +void protocol_status(Session *sn, Request *rq, int n, const char *m) { + rq->status_num = n; + + const char *msg = m ? m : protocol_status_message(n); + + pb_param *pp = pblock_removekey(pb_key_status, rq->srvhdrs); + if (pp != NULL) { + param_free(pp); + } + + pp = pblock_key_param_create(rq->srvhdrs, pb_key_status, msg, strlen(msg)); + pblock_kpinsert(pb_key_status, pp, rq->srvhdrs); +} + + +/* + * http_status_message from Open Webserver (frame/http.cpp) + * TODO: replace, use sstr_t + */ +NSAPI_PUBLIC const char * protocol_status_message (int code) +{ + const char *r; + + switch (code) + { + case PROTOCOL_CONTINUE : // 100 + r = "Continue"; + break; + case PROTOCOL_SWITCHING: //101 + r = "Switching Protocols"; + break; + case PROTOCOL_OK: // 200 + r = "OK"; + break; + case PROTOCOL_CREATED: // 201 + r = "Created"; + break; + case PROTOCOL_ACCEPTED: // 202 + r = "Accepted"; + break; + case PROTOCOL_NONAUTHORITATIVE: // 203 + r = "Non-Authoritative Information"; + break; + case PROTOCOL_NO_CONTENT: //204 + /* There is another define to PROTOCOL_NO_RESPONSE for 204 in nsapi.h + The spec maps this to No Content. + Hence cahnging this to No Content + */ + r = "No Content"; + break; + case PROTOCOL_RESET_CONTENT: // 205 + r = "Reset Content"; + break; + case PROTOCOL_PARTIAL_CONTENT: // 206 + r = "Partial Content"; + break; + case PROTOCOL_MULTI_STATUS: // 207 + r = "Multi Status"; + break; + case PROTOCOL_MULTIPLE_CHOICES: // 300 + r = "Multiple Choices"; + break; + case PROTOCOL_MOVED_PERMANENTLY: // 301 + r = "Moved Permanently"; + break; + case PROTOCOL_REDIRECT: // 302 + r = "Moved Temporarily"; /* The spec actually says "Found" */ + break; + case PROTOCOL_SEE_OTHER: // 303 + r = "See Other"; + break; + case PROTOCOL_NOT_MODIFIED: // 304 + r = "Use local copy"; /* The spec actually says "Not Modified" */ + break; + case PROTOCOL_USE_PROXY: // 305 + r = "Use Proxy"; + break; + case PROTOCOL_TEMPORARY_REDIRECT: // 307 + r = "Temporary Redirect"; + break; + case PROTOCOL_BAD_REQUEST: // 400 + r = "Bad request"; + break; + case PROTOCOL_UNAUTHORIZED: // 401 + r = "Unauthorized"; + break; + case PROTOCOL_PAYMENT_REQUIRED: // 402 + r = "Payment Required"; + break; + case PROTOCOL_FORBIDDEN: // 403 + r = "Forbidden"; + break; + case PROTOCOL_NOT_FOUND: // 404 + r = "Not found"; + break; + case PROTOCOL_METHOD_NOT_ALLOWED: // 405 /* HTTP/1.1 */ + r = "Method Not Allowed"; + break; + case PROTOCOL_NOT_ACCEPTABLE: // 406 /* HTTP/1.1 */ + r = "Not Acceptable"; + break; + case PROTOCOL_PROXY_UNAUTHORIZED: // 407 + r = "Proxy Authentication Required"; + break; + case PROTOCOL_REQUEST_TIMEOUT: // 408 /* HTTP/1.1 */ + r = "Request Timeout"; + break; + case PROTOCOL_CONFLICT: // 409 + r = "Conflict"; /* HTTP/1.1 */ + break; + case PROTOCOL_GONE: // 410 + r = "Gone"; /* HTTP/1.1 */ + break; + case PROTOCOL_LENGTH_REQUIRED: // 411 /* HTTP/1.1 */ + r = "Length Required"; + break; + case PROTOCOL_PRECONDITION_FAIL: // 412 /* HTTP/1.1 */ + r = "Precondition Failed"; + break; + case PROTOCOL_ENTITY_TOO_LARGE: // 413 /* HTTP/1.1 */ + r = "Request Entity Too Large"; + break; + case PROTOCOL_URI_TOO_LARGE: // 414 /* HTTP/1.1 */ + r = "Request-URI Too Large"; + break; + case PROTOCOL_UNSUPPORTED_MEDIA_TYPE: // 415 + r = "Unsupported Media Type"; + break; + case PROTOCOL_REQUESTED_RANGE_NOT_SATISFIABLE: // 416 + r = "Requested range not satisfiable"; + break; + case PROTOCOL_EXPECTATION_FAILED: // 417 + r = "Expectation Failed"; + break; + case PROTOCOL_LOCKED: // 423 + r = "Locked"; + break; + case PROTOCOL_FAILED_DEPENDENCY: // 424 + r = "Failed Dependency"; + break; + case PROTOCOL_SERVER_ERROR: // 500 + r = "Server Error"; /* The spec actually says "Internal Server Error" */ + break; + case PROTOCOL_NOT_IMPLEMENTED: // 501 + r = "Not Implemented"; + break; + case PROTOCOL_BAD_GATEWAY: // 502 + r = "Bad Gateway"; + break; + case PROTOCOL_SERVICE_UNAVAILABLE: // 503 + r = "Service Unavailable"; + break; + case PROTOCOL_GATEWAY_TIMEOUT: // 504 /* HTTP/1.1 */ + r = "Gateway Timeout"; + break; + case PROTOCOL_VERSION_NOT_SUPPORTED: // 505 /* HTTP/1.1 */ + r = "HTTP Version Not Supported"; + break; + case PROTOCOL_INSUFFICIENT_STORAGE: // 507 + r = "Insufficient Storage"; + break; + default: + switch (code / 100) + { + case 1: + r = "Information"; + break; + case 2: + r = "Success"; + break; + case 3: + r = "Redirect"; + break; + case 4: + r = "Client error"; + break; + case 5: + r = "Server error"; + break; + default: + r = "Unknown reason"; + break; + } + break; + } + + return r; +} + + +void add_http_status_line(iovec_buf_t *out, Request *rq) { + iovec_buf_write(out, "HTTP/1.1 ", 9); + + char *status_code_str = pool_malloc(out->pool, 8); + int sc_len = snprintf(status_code_str, 8, "%d ", rq->status_num); + iovec_buf_write(out, status_code_str, sc_len); + + char *scmsg = pblock_findkeyval(pb_key_status, rq->srvhdrs); + iovec_buf_write(out, scmsg, strlen(scmsg)); + + iovec_buf_write(out, "\r\n", 2); +} + +int http_start_response(Session *sn, Request *rq) { + int fd = ((SystemIOStream*)sn->csd)->fd; + + /* set socket blocking */ + int flags; + flags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, flags ^ O_NONBLOCK); + + /* iovec output buffer */ + iovec_buf_t *out = iovec_buf_create(sn->pool); + + /* add the http status line to the output buffer */ + add_http_status_line(out, rq); + + /* add server header */ + iovec_buf_write(out, "Server: WS uap-dev\r\n", 20); + + // TODO: add header from rq->srvhdrs + iovec_buf_write(out, "\r\n", 2); + + /* flush buffer to the socket */ + iovec_buf_flush(out, fd); + + rq->senthdrs = 1; +} + + diff -r 137197831306 -r 998844b5ed25 src/server/protocol.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/protocol.h Sun Nov 13 13:43:01 2011 +0100 @@ -0,0 +1,50 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HTTP_H +#define HTTP_H + +#include "nsapi.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void protocol_status(Session *sn, Request *rq, int n, const char *m); +const char* protocol_status_message(int code); + +int http_start_response(Session *sn, Request *rq); + +#ifdef __cplusplus +} +#endif + +#endif /* HTTP_H */ + diff -r 137197831306 -r 998844b5ed25 src/server/service.c --- a/src/server/service.c Sun Oct 30 16:26:57 2011 +0100 +++ b/src/server/service.c Sun Nov 13 13:43:01 2011 +0100 @@ -31,6 +31,7 @@ #include "service.h" #include "io.h" #include "pblock.h" +#include "protocol.h" int test_service(pblock *pb, Session *sn, Request *rq) { printf("test_service\n"); @@ -41,11 +42,17 @@ FILE *in = fopen(ppath, "r"); printf("open path: %s\n", ppath); + protocol_status(sn, rq, 200, NULL); + + http_start_response(sn, rq); + + /* fprintf(out, "HTTP/1.1 200 OK\n"); fprintf(out, "Server: Webserver Pre-Alpha\n"); fprintf(out, "Concent-Length: 27\n"); fprintf(out, "Connection: close\n\n"); fflush(out); + */ char buffer[128]; int r;