Introduction
Introduction Statistics Contact Development Disclaimer Help
optimize binary file transfers: use sendfile(2) syscall if supported - geomyida…
git clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfri…
Log
Files
Refs
Tags
README
LICENSE
---
commit d8b18c7bfa0d75f38bbceefde217c83813473e5f
parent 1c6dfdef1faabdb80161e5490526491e2a02c28c
Author: Hiltjo Posthuma <[email protected]>
Date: Sat, 23 Sep 2017 16:08:28 +0200
optimize binary file transfers: use sendfile(2) syscall if supported
The OS supporting sendfile(2) are (for now): Linux, FreeBSD, DragonFlyBSD.
When the file is empty or has no filesize information (such as block,
character devices etc) fallback to the normal read/write loop in userland.
A platform with no sendfile(2) support always uses this loop.
Optimize the buffer size in the normal read/write loop by using the block size
information, fallback to BUFSIZ.
Set socket options TCP_CORK (Linux), TCP_NOPUSH (BSDs) and TCP_NODELAY to
optimize packet transfers for large file transfers.
Tested on Linux (glibc and musl), FreeBSD, DragonFlyBSD and OpenBSD.
Signed-off-by: Christoph Lohmann <[email protected]>
Diffstat:
M handlr.c | 14 +++-----------
M ind.c | 68 +++++++++++++++++++++++++++++…
M ind.h | 1 +
3 files changed, 72 insertions(+), 11 deletions(-)
---
diff --git a/handlr.c b/handlr.c
@@ -104,8 +104,7 @@ void
handlebin(int sock, char *file, char *port, char *base, char *args,
char *sear, char *ohost)
{
- char sendb[1024];
- int len, fd, sent;
+ int fd;
USED(port);
USED(base);
@@ -115,15 +114,8 @@ handlebin(int sock, char *file, char *port, char *base, ch…
fd = open(file, O_RDONLY);
if(fd >= 0) {
- while((len = read(fd, sendb, sizeof(sendb))) > 0) {
- while(len > 0) {
- if ((sent = send(sock, sendb, len, 0)) < 0) {
- close(fd);
- return;
- }
- len -= sent;
- }
- }
+ if(xsendfile(fd, sock) < 0)
+ perror("sendfile");
close(fd);
}
}
diff --git a/ind.c b/ind.c
@@ -12,9 +12,19 @@
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <arpa/inet.h>
+/* for sendfile(2) */
+#ifdef __linux__
+#include <sys/sendfile.h>
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
+#include <sys/types.h>
+#include <sys/uio.h>
+#endif
+
#include "ind.h"
#include "handlr.h"
@@ -42,6 +52,64 @@ filetype type[] = {
{nil, nil, nil},
};
+int
+xsendfile(int fd, int sock)
+{
+ struct stat st;
+ char *sendb;
+ size_t bufsiz = BUFSIZ, count = 0;
+ int len, sent, optval;
+
+#ifdef TCP_CORK
+ optval = 1;
+ setsockopt(sock, IPPROTO_TCP, TCP_CORK, &optval, sizeof(int));
+#endif
+
+#ifdef TCP_NOPUSH
+ optval = 1;
+ setsockopt(sock, IPPROTO_TCP, TCP_NOPUSH, &optval, sizeof(int));
+#endif
+
+#ifdef TCP_NODELAY
+ optval = 0;
+ setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int));
+#endif
+
+ if(fstat(fd, &st) >= 0) {
+ if((bufsiz = st.st_blksize) < BUFSIZ)
+ bufsiz = BUFSIZ;
+ count = st.st_size;
+ }
+
+#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__DragonFly__)
+ count = 0;
+#endif
+
+ if (count == 0) {
+ sendb = xmalloc(bufsiz);
+ while((len = read(fd, sendb, bufsiz)) > 0) {
+ while(len > 0) {
+ if ((sent = send(sock, sendb, len, 0)) < 0) {
+ close(fd);
+ free(sendb);
+ return -1;
+ }
+ len -= sent;
+ }
+ }
+ free(sendb);
+ return 0;
+ }
+
+#ifdef __linux__
+ return sendfile(sock, fd, NULL, count);
+#endif
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+ return sendfile(fd, sock, 0, count, NULL, NULL, 0);
+#endif
+ return -1;
+}
+
void *
xcalloc(size_t nmemb, size_t size)
{
diff --git a/ind.h b/ind.h
@@ -35,6 +35,7 @@ void *xcalloc(size_t, size_t);
void *xmalloc(size_t);
void *xrealloc(void *, size_t);
char *xstrdup(const char *str);
+int xsendfile(int, int);
Indexs *scanfile(char *fname);
Elems *getadv(char *str);
int printelem(int fd, Elems *el, char *addr, char *port);
You are viewing proxied material from bitreich.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.