--- 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; }