ioptimize binary file transfers: use sendfile(2) syscall if supported - geomyidae - A small C-based gopherd. Err bitreich.org 70 hgit clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/ URL:git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/ bitreich.org 70 1Log /scm/geomyidae/log.gph bitreich.org 70 1Files /scm/geomyidae/files.gph bitreich.org 70 1Refs /scm/geomyidae/refs.gph bitreich.org 70 1Tags /scm/geomyidae/tag bitreich.org 70 1README /scm/geomyidae/file/README.gph bitreich.org 70 1LICENSE /scm/geomyidae/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 1commit d8b18c7bfa0d75f38bbceefde217c83813473e5f /scm/geomyidae/commit/d8b18c7bfa0d75f38bbceefde217c83813473e5f.gph bitreich.org 70 1parent 1c6dfdef1faabdb80161e5490526491e2a02c28c /scm/geomyidae/commit/1c6dfdef1faabdb80161e5490526491e2a02c28c.gph bitreich.org 70 hAuthor: Hiltjo Posthuma URL:mailto:hiltjo@codemadness.org bitreich.org 70 iDate: Sat, 23 Sep 2017 16:08:28 +0200 Err bitreich.org 70 i Err bitreich.org 70 ioptimize binary file transfers: use sendfile(2) syscall if supported Err bitreich.org 70 i Err bitreich.org 70 iThe OS supporting sendfile(2) are (for now): Linux, FreeBSD, DragonFlyBSD. Err bitreich.org 70 i Err bitreich.org 70 iWhen the file is empty or has no filesize information (such as block, Err bitreich.org 70 icharacter devices etc) fallback to the normal read/write loop in userland. Err bitreich.org 70 iA platform with no sendfile(2) support always uses this loop. Err bitreich.org 70 i Err bitreich.org 70 iOptimize the buffer size in the normal read/write loop by using the block size Err bitreich.org 70 iinformation, fallback to BUFSIZ. Err bitreich.org 70 i Err bitreich.org 70 iSet socket options TCP_CORK (Linux), TCP_NOPUSH (BSDs) and TCP_NODELAY to Err bitreich.org 70 ioptimize packet transfers for large file transfers. Err bitreich.org 70 i Err bitreich.org 70 iTested on Linux (glibc and musl), FreeBSD, DragonFlyBSD and OpenBSD. Err bitreich.org 70 i Err bitreich.org 70 iSigned-off-by: Christoph Lohmann <20h@r-36.net> Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M handlr.c | 14 +++----------- Err bitreich.org 70 i M ind.c | 68 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i M ind.h | 1 + Err bitreich.org 70 i Err bitreich.org 70 i3 files changed, 72 insertions(+), 11 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/handlr.c b/handlr.c /scm/geomyidae/file/handlr.c.gph bitreich.org 70 i@@ -104,8 +104,7 @@ void Err bitreich.org 70 i handlebin(int sock, char *file, char *port, char *base, char *args, Err bitreich.org 70 i char *sear, char *ohost) Err bitreich.org 70 i { Err bitreich.org 70 i- char sendb[1024]; Err bitreich.org 70 i- int len, fd, sent; Err bitreich.org 70 i+ int fd; Err bitreich.org 70 i Err bitreich.org 70 i USED(port); Err bitreich.org 70 i USED(base); Err bitreich.org 70 i@@ -115,15 +114,8 @@ handlebin(int sock, char *file, char *port, char *base, char *args, Err bitreich.org 70 i Err bitreich.org 70 i fd = open(file, O_RDONLY); Err bitreich.org 70 i if(fd >= 0) { Err bitreich.org 70 i- while((len = read(fd, sendb, sizeof(sendb))) > 0) { Err bitreich.org 70 i- while(len > 0) { Err bitreich.org 70 i- if ((sent = send(sock, sendb, len, 0)) < 0) { Err bitreich.org 70 i- close(fd); Err bitreich.org 70 i- return; Err bitreich.org 70 i- } Err bitreich.org 70 i- len -= sent; Err bitreich.org 70 i- } Err bitreich.org 70 i- } Err bitreich.org 70 i+ if(xsendfile(fd, sock) < 0) Err bitreich.org 70 i+ perror("sendfile"); Err bitreich.org 70 i close(fd); Err bitreich.org 70 i } Err bitreich.org 70 i } Err bitreich.org 70 1diff --git a/ind.c b/ind.c /scm/geomyidae/file/ind.c.gph bitreich.org 70 i@@ -12,9 +12,19 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i+#include Err bitreich.org 70 i #include Err bitreich.org 70 i+#include Err bitreich.org 70 i #include Err bitreich.org 70 i Err bitreich.org 70 i+/* for sendfile(2) */ Err bitreich.org 70 i+#ifdef __linux__ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#elif defined(__FreeBSD__) || defined(__DragonFly__) Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#endif Err bitreich.org 70 i+ Err bitreich.org 70 i #include "ind.h" Err bitreich.org 70 i #include "handlr.h" Err bitreich.org 70 i Err bitreich.org 70 i@@ -42,6 +52,64 @@ filetype type[] = { Err bitreich.org 70 i {nil, nil, nil}, Err bitreich.org 70 i }; Err bitreich.org 70 i Err bitreich.org 70 i+int Err bitreich.org 70 i+xsendfile(int fd, int sock) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct stat st; Err bitreich.org 70 i+ char *sendb; Err bitreich.org 70 i+ size_t bufsiz = BUFSIZ, count = 0; Err bitreich.org 70 i+ int len, sent, optval; Err bitreich.org 70 i+ Err bitreich.org 70 i+#ifdef TCP_CORK Err bitreich.org 70 i+ optval = 1; Err bitreich.org 70 i+ setsockopt(sock, IPPROTO_TCP, TCP_CORK, &optval, sizeof(int)); Err bitreich.org 70 i+#endif Err bitreich.org 70 i+ Err bitreich.org 70 i+#ifdef TCP_NOPUSH Err bitreich.org 70 i+ optval = 1; Err bitreich.org 70 i+ setsockopt(sock, IPPROTO_TCP, TCP_NOPUSH, &optval, sizeof(int)); Err bitreich.org 70 i+#endif Err bitreich.org 70 i+ Err bitreich.org 70 i+#ifdef TCP_NODELAY Err bitreich.org 70 i+ optval = 0; Err bitreich.org 70 i+ setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)); Err bitreich.org 70 i+#endif Err bitreich.org 70 i+ Err bitreich.org 70 i+ if(fstat(fd, &st) >= 0) { Err bitreich.org 70 i+ if((bufsiz = st.st_blksize) < BUFSIZ) Err bitreich.org 70 i+ bufsiz = BUFSIZ; Err bitreich.org 70 i+ count = st.st_size; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__DragonFly__) Err bitreich.org 70 i+ count = 0; Err bitreich.org 70 i+#endif Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (count == 0) { Err bitreich.org 70 i+ sendb = xmalloc(bufsiz); Err bitreich.org 70 i+ while((len = read(fd, sendb, bufsiz)) > 0) { Err bitreich.org 70 i+ while(len > 0) { Err bitreich.org 70 i+ if ((sent = send(sock, sendb, len, 0)) < 0) { Err bitreich.org 70 i+ close(fd); Err bitreich.org 70 i+ free(sendb); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ len -= sent; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ free(sendb); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+#ifdef __linux__ Err bitreich.org 70 i+ return sendfile(sock, fd, NULL, count); Err bitreich.org 70 i+#endif Err bitreich.org 70 i+#if defined(__FreeBSD__) || defined(__DragonFly__) Err bitreich.org 70 i+ return sendfile(fd, sock, 0, count, NULL, NULL, 0); Err bitreich.org 70 i+#endif Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i void * Err bitreich.org 70 i xcalloc(size_t nmemb, size_t size) Err bitreich.org 70 i { Err bitreich.org 70 1diff --git a/ind.h b/ind.h /scm/geomyidae/file/ind.h.gph bitreich.org 70 i@@ -35,6 +35,7 @@ void *xcalloc(size_t, size_t); Err bitreich.org 70 i void *xmalloc(size_t); Err bitreich.org 70 i void *xrealloc(void *, size_t); Err bitreich.org 70 i char *xstrdup(const char *str); Err bitreich.org 70 i+int xsendfile(int, int); Err bitreich.org 70 i Indexs *scanfile(char *fname); Err bitreich.org 70 i Elems *getadv(char *str); Err bitreich.org 70 i int printelem(int fd, Elems *el, char *addr, char *port); Err bitreich.org 70 .