diff options
author | Přemysl Janouch <p.janouch@gmail.com> | 2016-10-01 04:32:54 +0200 |
---|---|---|
committer | Přemysl Janouch <p.janouch@gmail.com> | 2016-10-01 04:35:12 +0200 |
commit | 6234f686e011dfff6c585309de27204122cdbb8a (patch) | |
tree | d64669f648da906fb71b44fbd59729e6896c9fb3 | |
parent | b07d9df5fc905abebdbda833daf5dd6b8cf08688 (diff) | |
download | liberty-6234f686e011dfff6c585309de27204122cdbb8a.tar.gz liberty-6234f686e011dfff6c585309de27204122cdbb8a.tar.xz liberty-6234f686e011dfff6c585309de27204122cdbb8a.zip |
Add socket_io_*() functions
-rw-r--r-- | liberty.c | 71 |
1 files changed, 71 insertions, 0 deletions
@@ -4313,6 +4313,77 @@ connector_add_target (struct connector *self, #endif // defined LIBERTY_WANT_POLLER && defined LIBERTY_WANT_ASYNC +// --- Simple network I/O ------------------------------------------------------ + +enum socket_io_result +{ + SOCKET_IO_OK = 0, ///< 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) +{ + // Flood protection, cannot afford to read too much at once + size_t read_limit = rb->len + (1 << 20); + if (read_limit < rb->len) + read_limit = SIZE_MAX; + + ssize_t n_read; + while (rb->len < read_limit) + { + str_ensure_space (rb, 1024); + 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; + + int errno_save = errno; + LOG_LIBC_FAILURE ("recv"); + errno = errno_save; + return SOCKET_IO_ERROR; + } + return SOCKET_IO_OK; +} + +static enum socket_io_result +socket_io_try_write (int socket_fd, struct str *wb) +{ + 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; + + int errno_save = errno; + LOG_LIBC_FAILURE ("send"); + errno = errno_save; + return SOCKET_IO_ERROR; + } + return SOCKET_IO_OK; +} + // --- Advanced configuration -------------------------------------------------- // This is a more powerful configuration format, adding key-value maps and |