]> code.citadel.org Git - citadel.git/commitdiff
* correctly handle tcp write, so that we work properly on openbsd. Thanks to Maide...
authorWilfried Göesgens <willi@citadel.org>
Tue, 22 Jan 2008 21:22:10 +0000 (21:22 +0000)
committerWilfried Göesgens <willi@citadel.org>
Tue, 22 Jan 2008 21:22:10 +0000 (21:22 +0000)
webcit/webcit.c
webcit/webserver.c

index 9b8d74a69f8a1bb26c27ae0f283d3f011cac127f..da8d021412c56b6d7b4eac0fc081da44af8225f0 100644 (file)
@@ -676,6 +676,8 @@ void output_static(char *what)
        FILE *fp;
        struct stat statbuf;
        off_t bytes;
+       off_t count = 0;
+       size_t res;
        char *bigbuffer;
        char content_type[128];
        int len;
@@ -683,10 +685,10 @@ void output_static(char *what)
        fp = fopen(what, "rb");
        if (fp == NULL) {
                lprintf(9, "output_static('%s')  -- NOT FOUND --\n", what);
-               wprintf("HTTP/1.1 404 %s\n", strerror(errno));
+               wprintf("HTTP/1.1 404 %s\r\n", strerror(errno));
                wprintf("Content-Type: text/plain\r\n");
                wprintf("\r\n");
-               wprintf("Cannot open %s: %s\n", what, strerror(errno));
+               wprintf("Cannot open %s: %s\r\n", what, strerror(errno));
        } else {
                len = strlen (what);
                if (!strncasecmp(&what[len - 4], ".gif", 4))
@@ -720,10 +722,35 @@ void output_static(char *what)
                else
                        safestrncpy(content_type, "application/octet-stream", sizeof content_type);
 
-               fstat(fileno(fp), &statbuf);
+               if (fstat(fileno(fp), &statbuf) == -1) {
+                       lprintf(9, "output_static('%s')  -- FSTAT FAILED --\n", what);
+                       wprintf("HTTP/1.1 404 %s\r\n", strerror(errno));
+                       wprintf("Content-Type: text/plain\r\n");
+                       wprintf("\r\n");
+                       wprintf("Cannot fstat %s: %s\n", what, strerror(errno));
+                       return;
+               }
+
+               count = 0;
                bytes = statbuf.st_size;
-               bigbuffer = malloc(bytes + 2);
-               fread(bigbuffer, bytes, 1, fp);
+               if ((bigbuffer = malloc(bytes + 2)) == NULL) {
+                       lprintf(9, "output_static('%s')  -- MALLOC FAILED (%s) --\n", what, strerror(errno));
+                       wprintf("HTTP/1.1 500 internal server error\r\n");
+                       wprintf("Content-Type: text/plain\r\n");
+                       wprintf("\r\n");
+                       return;
+               }
+               while (count < bytes) {
+                       if ((res = fread(bigbuffer + count, 1, bytes - count, fp)) == 0) {
+                               lprintf(9, "output_static('%s')  -- FREAD FAILED (%s) %zu bytes of %zu --\n", what, strerror(errno), bytes - count, bytes);
+                               wprintf("HTTP/1.1 500 internal server error \r\n");
+                               wprintf("Content-Type: text/plain\r\n");
+                               wprintf("\r\n");
+                               return;
+                       }
+                       count += res;
+               }
+
                fclose(fp);
 
                lprintf(9, "output_static('%s')  %s\n", what, content_type);
index 2bb9270301342da85503e90cfb927e040aa47c3b..9a409e3a5924a38806e6e6ddf971d9796e5525eb 100644 (file)
@@ -108,7 +108,10 @@ int ig_tcp_server(char *ip_addr, int port_number, int queue_len)
        i = 1;
        setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
 
-       fcntl(s, F_SETFL, O_NONBLOCK);/// TODO
+       fcntl(s, F_SETFL, O_NONBLOCK); /* maide: this statement is incorrect
+                                         there should be a preceding F_GETFL
+                                         and a bitwise OR with the previous
+                                         fd flags */
        
        if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
                lprintf(1, "Can't bind: %s\n", strerror(errno));
@@ -237,8 +240,12 @@ int client_read_to(int sock, char *buf, int bytes, int timeout)
  */
 ssize_t client_write(const void *buf, size_t count)
 {
-       char *newptr;
-       size_t newalloc;
+        char *newptr;
+        size_t newalloc;
+        size_t bytesWritten = 0;
+        ssize_t res;
+        fd_set wset;
+        int fdflags;
 
        if (WC->burst != NULL) {
                if ((WC->burst_len + count) >= WC->burst_alloc) {
@@ -272,7 +279,26 @@ ssize_t client_write(const void *buf, size_t count)
        write(2, buf, count);
        write(2, "\033[30m", 5);
 #endif
-       return (write(WC->http_sock, buf, count));
+
+        while (bytesWritten < count) {
+                if ((fdflags & O_NONBLOCK) == O_NONBLOCK) {
+                        FD_ZERO(&wset);
+                        FD_SET(WC->http_sock, &wset);
+                        if (select(1, NULL, &wset, NULL, NULL) == -1) {
+                                lprintf(2, "client_write: Socket select failed (%s)\n", strerror(errno));
+                                return -1;
+                        }
+                }
+
+                if ((res = write(WC->http_sock, (char*)buf + bytesWritten,
+                  count - bytesWritten)) == -1) {
+                        lprintf(2, "client_write: Socket write failed (%s)\n", strerror(errno));
+                        return res;
+                }
+                bytesWritten += res;
+        }
+
+       return bytesWritten;
 }
 
 /*