Added some protocol functions

Sun, 13 Nov 2011 13:43:01 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 13 Nov 2011 13:43:01 +0100
changeset 4
998844b5ed25
parent 3
137197831306
child 5
dbc01588686e

Added some protocol functions

src/server/httplistener.c file | annotate | diff | comparison | revisions
src/server/io.c file | annotate | diff | comparison | revisions
src/server/io.h file | annotate | diff | comparison | revisions
src/server/main.c file | annotate | diff | comparison | revisions
src/server/objs.mk file | annotate | diff | comparison | revisions
src/server/protocol.c file | annotate | diff | comparison | revisions
src/server/protocol.h file | annotate | diff | comparison | revisions
src/server/service.c file | annotate | diff | comparison | revisions
--- 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 */
--- 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 <unistd.h>
 #include <stdlib.h>
+#include <sys/uio.h>
 
 #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);
+}
--- 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
--- 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) {
--- 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)%)
 
--- /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;
+}
+
+
--- /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 <sys/uio.h>
+
+#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 */
+
--- 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;

mercurial