aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2012-10-02 15:37:36 +0200
committerMartin Willi <martin@revosec.ch>2012-10-02 15:37:36 +0200
commit565bfc08c6d8779673f6435dacb701961ddacd1d (patch)
tree2e5afcfbe83e085ff94b57f2f3566f2ea8c13cec
parent9564f9eb6e5567d39aa1ed9f4de89144f82f69f1 (diff)
downloadstrongswan-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.c60
-rw-r--r--src/libfast/request.h9
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