diff options
author | Martin Willi <martin@revosec.ch> | 2012-10-02 15:37:36 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2012-10-02 15:37:36 +0200 |
commit | 565bfc08c6d8779673f6435dacb701961ddacd1d (patch) | |
tree | 2e5afcfbe83e085ff94b57f2f3566f2ea8c13cec | |
parent | 9564f9eb6e5567d39aa1ed9f4de89144f82f69f1 (diff) | |
download | strongswan-565bfc08c6d8779673f6435dacb701961ddacd1d.tar.bz2 strongswan-565bfc08c6d8779673f6435dacb701961ddacd1d.tar.xz |
Add a libfast sendfile() method to send files from disk5.0.1
-rw-r--r-- | src/libfast/request.c | 60 | ||||
-rw-r--r-- | src/libfast/request.h | 9 |
2 files changed, 69 insertions, 0 deletions
diff --git a/src/libfast/request.c b/src/libfast/request.c index 3acd831b2..6ca474037 100644 --- a/src/libfast/request.c +++ b/src/libfast/request.c @@ -22,6 +22,11 @@ #include <stdlib.h> #include <pthread.h> #include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <fcntl.h> + #include <ClearSilver/ClearSilver.h> #include <threading/thread.h> @@ -275,6 +280,60 @@ METHOD(request_t, serve, void, FCGX_PutStr(chunk.ptr, chunk.len, this->req.out); } +METHOD(request_t, sendfile, bool, + private_request_t *this, char *path, char *mime) +{ + struct stat sb; + chunk_t data; + void *addr; + int fd, written; + char buf[24]; + + fd = open(path, O_RDONLY); + if (fd == -1) + { + return FALSE; + } + if (fstat(fd, &sb) == -1) + { + close(fd); + return FALSE; + } + addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (addr == MAP_FAILED) + { + close(fd); + return FALSE; + } + + /* FCGX does not like large integers, print to a buffer using libc */ + snprintf(buf, sizeof(buf), "%lld", (int64_t)sb.st_size); + FCGX_FPrintF(this->req.out, "Content-Length: %s\n", buf); + if (mime) + { + FCGX_FPrintF(this->req.out, "Content-Type: %s\n", mime); + } + FCGX_FPrintF(this->req.out, "\n"); + + data = chunk_create(addr, sb.st_size); + + while (data.len) + { + written = FCGX_PutStr(data.ptr, data.len, this->req.out); + if (written == -1) + { + munmap(addr, sb.st_size); + close(fd); + return FALSE; + } + data = chunk_skip(data, written); + } + + munmap(addr, sb.st_size); + close(fd); + return TRUE; +} + METHOD(request_t, render, void, private_request_t *this, char *template) { @@ -380,6 +439,7 @@ request_t *request_create(int fd, bool debug) .render = _render, .streamf = _streamf, .serve = _serve, + .sendfile = _sendfile, .set = _set, .setf = _setf, .get_ref = _get_ref, diff --git a/src/libfast/request.h b/src/libfast/request.h index c9c1f13e2..63a465bb8 100644 --- a/src/libfast/request.h +++ b/src/libfast/request.h @@ -185,6 +185,15 @@ struct request_t { void (*serve)(request_t *this, char *headers, chunk_t chunk); /** + * Send a file from the file system. + * + * @param path path to file to serve + * @param mime mime type of file to send, or NULL + * @return TRUE if file served successfully + */ + bool (*sendfile)(request_t *this, char *path, char *mime); + + /** * Increase the reference count to the stream. * * @return this with increased refcount |