src/server/util/io.c

changeset 66
74babc0082b7
parent 65
14722c5f8856
child 69
4a10bc0ee80d
--- a/src/server/util/io.c	Wed May 22 15:05:06 2013 +0200
+++ b/src/server/util/io.c	Sun May 26 12:12:07 2013 +0200
@@ -80,14 +80,14 @@
     st->st = net_io_funcs;
     st->fd = fd;
     st->max_read = 0;
-    st->rd = 0;
-    st->chunkedenc = 0;
+    st->read = 0;
+    st->chunked_enc = 0;
     st->buffered = 0;
     return (IOStream*)st;
 }
 
 ssize_t net_stream_write(NetIOStream *st, void *buf, size_t nbytes) {
-    if(st->chunkedenc) {
+    if(st->chunked_enc) {
         // TODO: on some plattforms iov_len is smaller than size_t
         struct iovec io[2];
         char chunk_len[16];
@@ -103,7 +103,7 @@
 }
 
 ssize_t net_stream_writev(NetIOStream *st, struct iovec *iovec, int iovcnt) {
-    if(st->chunkedenc) {
+    if(st->chunked_enc) {
         struct iovec *io = calloc(iovcnt + 1, sizeof(struct iovec));
         char chunk_len[16];
         io[0].iov_base = chunk_len;
@@ -121,11 +121,11 @@
 }
 
 ssize_t net_stream_read(NetIOStream *st, void *buf, size_t nbytes) {
-    if(st->max_read != 0 && st->rd >= st->max_read) {
+    if(st->max_read != 0 && st->read >= st->max_read) {
         return 0;
     }
     ssize_t r = read(st->fd, buf, nbytes);
-    st->rd += r;
+    st->read += r;
     return r;
 }
 
@@ -179,14 +179,75 @@
 }
 
 ssize_t net_sendfile(SYS_NETFD fd, sendfiledata *sfd) {
-    IOStream *out = fd;
-    if(out->sendfile) {
+    NetIOStream *out = fd;
+    if(out->st.sendfile && sfd->fd && sfd->fd->fd != -1) {
         ssize_t r = ((IOStream*)fd)->sendfile(fd, sfd);
         if(r < 0) {
             return IO_ERROR;
         }
     } else {
-        fprintf(stderr, "stream does not support sendfile\n");
+        // stream/file does not support sendfile
+        // do regular copy
+        char *buf = malloc(4096);
+        if(!buf) {
+            // TODO: out of memory error
+            return IO_ERROR;
+        }
+        char *header = (char*)sfd->header;
+        int hlen = sfd->hlen;
+        char *trailer = (char*)sfd->trailer;
+        int tlen = sfd->tlen;
+        if(header == NULL) {
+            hlen = 0;
+        }
+        if(trailer == NULL) {
+            tlen = 0;
+        }
+        
+        ssize_t r;
+        while(hlen > 0) {
+            r = out->st.write(fd, header, hlen);
+            header += r;
+            hlen -= r;
+            if(r <= 0) {
+                free(buf);
+                return IO_ERROR;
+            }
+        }
+        
+        if(system_lseek(sfd->fd, sfd->offset, SEEK_SET) == -1) {
+            free(buf);
+            return IO_ERROR;
+        }
+        
+        size_t length = sfd->len;
+        while(length > 0) {
+            if((r = system_fread(sfd->fd, buf, 4096)) <= 0) {
+                break;
+            }
+            char *write_buf = buf;
+            while(r > 0) {
+                ssize_t w = out->st.write(fd, write_buf, r);
+                r -= w;
+                length -= w;
+                write_buf += w;
+            }
+        }
+        free(buf);
+        if(length > 0) {
+            return IO_ERROR;
+        }
+        
+        while(tlen > 0) {
+            r = out->st.write(fd, trailer, tlen);
+            trailer += r;
+            tlen -= r;
+            if(r <= 0) {
+                return IO_ERROR;
+            }
+        }
+        
+        return sfd->hlen + sfd->len + sfd->tlen;
     }
     return IO_ERROR;
 }

mercurial