src/server/service.c

changeset 6
ce8fecc9847d
parent 4
998844b5ed25
child 8
f4d56bf9de40
--- a/src/server/service.c	Mon Dec 26 15:48:32 2011 +0100
+++ b/src/server/service.c	Tue Dec 27 20:12:21 2011 +0100
@@ -27,41 +27,95 @@
  */
 
 #include <stdio.h>
+#include <errno.h>
 
 #include "service.h"
 #include "io.h"
 #include "pblock.h"
 #include "protocol.h"
 
+#include <sys/sendfile.h>
+
+// TODO: system sendfile Abstraktionen in neue Datei auslagern
+/*
+ssize_t sys_sendfile(int out_fd, int in_fd, off_t *off, size_t len) {
+    
+}
+*/
+#define sys_sendfile sendfile
+
+
+/*
+ * prepares for servicing a file
+ *
+ * adds content-length header and starts the response
+ *
+ * return the file descriptor or an error code
+ */
+int prepare_service_file(Session *sn, Request *rq) {
+    char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars);
+
+    /* open the file */
+    int fd = open(ppath, O_RDONLY);
+    if(fd < 0) {
+        perror("prepare_service_file: open");
+
+        int status = 500;
+        switch(errno) {
+            case EACCES: {
+                status = 403;
+                break;
+            }
+            case ENOENT: {
+                status = 404;
+                break;
+            }
+        }
+        protocol_status(sn, rq, status, NULL);
+        return -1;
+    }
+
+    /* get stat */
+    struct stat stat;
+    if (fstat(fd, &stat) != 0) {
+        perror("prepare_service_file: stat");
+
+        protocol_status(sn, rq, 500, NULL);
+        return -1;
+    }
+
+    /* add content-length header*/
+    char contentLength[32];
+    int len = snprintf(contentLength, 32, "%d", stat.st_size);
+
+    pblock_kvinsert(pb_key_content_length, contentLength, len, rq->srvhdrs);
+
+    /* start response */
+    protocol_status(sn, rq, 200, NULL);
+    http_start_response(sn, rq);
+
+    return fd;
+}
+
 int test_service(pblock *pb, Session *sn, Request *rq) {
     printf("test_service\n");
 
-    SystemIOStream *io = (SystemIOStream*) sn->csd;
-    char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars);
-    FILE *out = fdopen(io->fd, "w");
-    FILE *in = fopen(ppath, "r");
-    printf("open path: %s\n", ppath);
-
-    protocol_status(sn, rq, 200, NULL);
-
-    http_start_response(sn, rq);
+    int fd = prepare_service_file(sn, rq);
+    if(fd < 0) {
+        /* TODO: service error */
+        http_start_response(sn, rq);
+        return REQ_PROCEED;
+    }
 
-    /*
-    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);
-    */
+    /* send file*/
+    SystemIOStream *io = (SystemIOStream*) sn->csd;
 
-    char buffer[128];
-    int r;
-    while((r = fread(buffer, 1, 64, in)) > 0) {
-        fwrite(buffer, 1, r, out);
-    }
-    fflush(out);
-    fclose(in);
-    fclose(out);
+    off_t fileoffset = 0;
+    int len = atoi(pblock_findkeyval(pb_key_content_length, rq->srvhdrs));
+    printf("content-length: %d\n", len);
+    sendfile(io->fd, fd, &fileoffset, len);
+
+    close(fd);
 
     return REQ_PROCEED;
 }

mercurial