From 376bbea249f17eda9c682ff7153f102990548888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Wed, 6 Jan 2016 23:37:30 +0100 Subject: Factor out socket_io_try_{read,write}() To be reused in Lua connection API. --- common.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'common.c') diff --git a/common.c b/common.c index 8974f57..a92bae4 100644 --- a/common.c +++ b/common.c @@ -95,6 +95,74 @@ xwrite (int fd, const char *data, size_t len, struct error **e) return true; } +// --- Simple network I/O ------------------------------------------------------ + +// TODO: move to liberty and remove from dwmstatus.c as well + +#define SOCKET_IO_OVERFLOW (8 << 20) ///< How large a read buffer can be + +enum socket_io_result +{ + SOCKET_IO_OK, ///< Completed successfully + SOCKET_IO_EOF, ///< Connection shut down by peer + SOCKET_IO_ERROR ///< Connection error +}; + +static enum socket_io_result +socket_io_try_read (int socket_fd, struct str *rb, struct error **e) +{ + // We allow buffering of a fair amount of data, however within reason, + // so that it's not so easy to flood us and cause an allocation failure + ssize_t n_read; + while (rb->len < SOCKET_IO_OVERFLOW) + { + str_ensure_space (rb, 4096); + n_read = recv (socket_fd, rb->str + rb->len, + rb->alloc - rb->len - 1 /* null byte */, 0); + + if (n_read > 0) + { + rb->str[rb->len += n_read] = '\0'; + continue; + } + if (n_read == 0) + return SOCKET_IO_EOF; + + if (errno == EAGAIN) + return SOCKET_IO_OK; + if (errno == EINTR) + continue; + + error_set (e, "%s", strerror (errno)); + return SOCKET_IO_ERROR; + } + return SOCKET_IO_OK; +} + +static enum socket_io_result +socket_io_try_write (int socket_fd, struct str *wb, struct error **e) +{ + ssize_t n_written; + while (wb->len) + { + n_written = send (socket_fd, wb->str, wb->len, 0); + if (n_written >= 0) + { + str_remove_slice (wb, 0, n_written); + continue; + } + + if (errno == EAGAIN) + return SOCKET_IO_OK; + if (errno == EINTR) + continue; + + error_set (e, "%s", strerror (errno)); + return SOCKET_IO_ERROR; + } + return SOCKET_IO_OK; +} + // --- Logging ----------------------------------------------------------------- static void -- cgit v1.2.3