Sio code is dirty and full of unused functions. Lets
clean it a bit: move comments to declarations, add
explicit 'struct' to struct types, remove unused code,
put function return values onto separate lines, remove
unused headers, reduce indentation level.
This is a preparation patch to make sio C.
---
src/evio.cc | 9 +-
src/sio.cc | 335 +++++++++++-----------------------------------------
src/sio.h | 142 +++++++++++++---------
3 files changed, 155 insertions(+), 331 deletions(-)
diff --git a/src/evio.cc b/src/evio.cc
index a6ac65daf..a8475e0d1 100644
--- a/src/evio.cc
+++ b/src/evio.cc
@@ -111,7 +111,7 @@ evio_setsockopt_client(int fd, int family, int type)
{
int on = 1;
/* In case this throws, the socket is not leaked. */
- if (sio_setfl(fd, O_NONBLOCK, on))
+ if (sio_setfl(fd, O_NONBLOCK) != 0)
diag_raise();
if (type == SOCK_STREAM && family != AF_UNIX) {
/*
@@ -136,7 +136,7 @@ evio_setsockopt_server(int fd, int family, int type)
{
int on = 1;
/* In case this throws, the socket is not leaked. */
- if (sio_setfl(fd, O_NONBLOCK, on))
+ if (sio_setfl(fd, O_NONBLOCK) != 0)
diag_raise();
/* Allow reuse local adresses. */
if (sio_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
@@ -294,10 +294,7 @@ evio_service_listen(struct evio_service *service)
sio_strfaddr(&service->addr, service->addr_len));
int fd = service->ev.fd;
- if (sio_listen(fd)) {
- /* raise for addr in use to */
- tnt_raise(SocketError, sio_socketname(fd), "listen");
- }
+ sio_listen(fd);
ev_io_start(service->loop, &service->ev);
}
diff --git a/src/sio.cc b/src/sio.cc
index 0475b9e83..b2f05e5c8 100644
--- a/src/sio.cc
+++ b/src/sio.cc
@@ -33,23 +33,13 @@
#include <sys/un.h>
#include <sys/uio.h>
#include <errno.h>
-#include <stdio.h>
#include <limits.h>
#include <netinet/in.h> /* TCP_NODELAY */
#include <netinet/tcp.h> /* TCP_NODELAY */
-#include <arpa/inet.h> /* inet_ntoa */
-#include <poll.h>
-#include <unistd.h> /* lseek for sending file */
-#include <sys/stat.h> /* fstat for sending file */
-#ifdef TARGET_OS_LINUX
-#include <sys/sendfile.h> /* sendfile system call */
-#endif /* #ifdef TARGET_OS_LINUX */
-
#include "say.h"
#include "trivia/util.h"
#include "exception.h"
-/** Pretty print socket name and peer (for exceptions) */
const char *
sio_socketname(int fd)
{
@@ -62,10 +52,9 @@ sio_socketname(int fd)
socklen_t addrlen = sizeof(addr);
int rc = getsockname(fd, (struct sockaddr *) &addr, &addrlen);
if (rc == 0) {
- n += snprintf(name + n,
- sizeof(name) - n, ", aka %s",
- sio_strfaddr((struct sockaddr *)&addr,
- addrlen));
+ n += snprintf(name + n, sizeof(name) - n, ", aka %s",
+ sio_strfaddr((struct sockaddr *)&addr,
+ addrlen));
}
addrlen = sizeof(addr);
rc = getpeername(fd, (struct sockaddr *) &addr, &addrlen);
@@ -73,7 +62,7 @@ sio_socketname(int fd)
n += snprintf(name + n, sizeof(name) - n,
", peer of %s",
sio_strfaddr((struct sockaddr *)&addr,
- addrlen));
+ addrlen));
}
}
/*
@@ -84,7 +73,8 @@ sio_socketname(int fd)
return name;
}
-/** Get a string representation of a socket option name,
+/**
+ * Get a string representation of a socket option name,
* for logging.
*/
static const char *
@@ -107,27 +97,18 @@ sio_option_name(int option)
#undef CASE_OPTION
}
-/** shut down part of a full-duplex connection */
-int
-sio_shutdown(int fd, int how)
-{
- int rc = shutdown(fd, how);
- if (rc < 0)
- diag_set(SocketError, sio_socketname(fd), "shutdown");
- return rc;
-}
-
-/** Try to automatically configure a listen backlog.
+/**
+ * Try to automatically configure a listen backlog.
* On Linux, use the system setting, which defaults
* to 128. This way a system administrator can tune
* the backlog as needed. On other systems, use SOMAXCONN.
*/
-int
+static int
sio_listen_backlog()
{
#ifdef TARGET_OS_LINUX
FILE *proc = fopen("/proc/sys/net/core/somaxconn", "r");
- if (proc) {
+ if (proc != NULL) {
int backlog;
int rc = fscanf(proc, "%d", &backlog);
fclose(proc);
@@ -138,11 +119,10 @@ sio_listen_backlog()
return SOMAXCONN;
}
-/** Create a TCP socket. */
int
sio_socket(int domain, int type, int protocol)
{
- /* AF_UNIX can't use tcp protocol */
+ /* AF_UNIX can't use a protocol. */
if (domain == AF_UNIX)
protocol = 0;
int fd = socket(domain, type, protocol);
@@ -151,60 +131,55 @@ sio_socket(int domain, int type, int protocol)
return fd;
}
-/** Get socket flags, raise an exception if error. */
int
sio_getfl(int fd)
{
int flags = fcntl(fd, F_GETFL, 0);
- if (flags < 0)
+ if (flags < 0) {
diag_set(SocketError, sio_socketname(fd),
"fcntl(..., F_GETFL, ...)");
+ }
return flags;
}
-/** Set socket flags, raise an exception if error. */
int
-sio_setfl(int fd, int flag, int on)
+sio_setfl(int fd, int flag)
{
int flags = sio_getfl(fd);
if (flags < 0)
return flags;
- flags = fcntl(fd, F_SETFL, on ? flags | flag : flags & ~flag);
- if (flags < 0)
+ flags = fcntl(fd, F_SETFL, flags | flag);
+ if (flags < 0) {
diag_set(SocketError, sio_socketname(fd),
"fcntl(..., F_SETFL, ...)");
+ }
return flags;
}
-/** Set an option on a socket.
- * @retval -1 on error
- * */
int
sio_setsockopt(int fd, int level, int optname,
const void *optval, socklen_t optlen)
{
int rc = setsockopt(fd, level, optname, optval, optlen);
- if (rc) {
+ if (rc != 0) {
diag_set(SocketError, sio_socketname(fd),
"setsockopt(%s)", sio_option_name(optname));
}
return rc;
}
-/** Get a socket option value. */
int
sio_getsockopt(int fd, int level, int optname,
void *optval, socklen_t *optlen)
{
int rc = getsockopt(fd, level, optname, optval, optlen);
- if (rc) {
+ if (rc != 0) {
diag_set(SocketError, sio_socketname(fd), "getsockopt(%s)",
sio_option_name(optname));
}
return rc;
}
-/** Connect a client socket to a server. */
int
sio_connect(int fd, struct sockaddr *addr, socklen_t addrlen)
{
@@ -217,7 +192,6 @@ sio_connect(int fd, struct sockaddr *addr, socklen_t
addrlen)
return rc;
}
-/** Bind a socket to the given address. */
int
sio_bind(int fd, struct sockaddr *addr, socklen_t addrlen)
{
@@ -227,71 +201,62 @@ sio_bind(int fd, struct sockaddr *addr, socklen_t addrlen)
return rc;
}
-/** Mark a socket as accepting connections. */
int
sio_listen(int fd)
{
int rc = listen(fd, sio_listen_backlog());
- if (rc < 0 && errno != EADDRINUSE)
+ if (rc < 0)
tnt_raise(SocketError, sio_socketname(fd), "listen");
return rc;
}
-/** Accept a client connection on a server socket. */
int
sio_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
{
/* Accept a connection. */
int newfd = accept(fd, addr, addrlen);
- if (newfd < 0 &&
- (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR))
+ if (newfd < 0 && errno != EAGAIN && errno != EWOULDBLOCK &&
+ errno != EINTR)
tnt_raise(SocketError, sio_socketname(fd), "accept");
return newfd;
}
-/** Read up to 'count' bytes from a socket. */
ssize_t
sio_read(int fd, void *buf, size_t count)
{
ssize_t n = read(fd, buf, count);
- if (n < 0) {
- if (errno == EWOULDBLOCK)
- errno = EINTR;
- switch (errno) {
- case EAGAIN:
- case EINTR:
- break;
- /*
- * Happens typically when the client closes
- * socket on timeout without reading the previous
- * query's response completely. Treat the same as
- * EOF.
- */
- case ECONNRESET:
- errno = 0;
- n = 0;
- break;
- default:
- tnt_raise(SocketError, sio_socketname(fd),
- "read(%zd)", count);
- }
+ if (n >= 0)
+ return n;
+ if (errno == EWOULDBLOCK)
+ errno = EINTR;
+ switch (errno) {
+ case EAGAIN:
+ case EINTR:
+ break;
+ /*
+ * Happens typically when the client closes socket on
+ * timeout without reading the previous query's response
+ * completely. Treat the same as EOF.
+ */
+ case ECONNRESET:
+ errno = 0;
+ n = 0;
+ break;
+ default:
+ tnt_raise(SocketError, sio_socketname(fd), "read(%zd)", count);
}
return n;
}
-/** Write up to 'count' bytes to a socket. */
ssize_t
sio_write(int fd, const void *buf, size_t count)
{
ssize_t n = write(fd, buf, count);
- if (n < 0 && errno != EAGAIN &&
- errno != EWOULDBLOCK && errno != EINTR)
- tnt_raise(SocketError, sio_socketname(fd),
- "write(%zd)", count);
+ if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
+ tnt_raise(SocketError, sio_socketname(fd), "write(%zd)", count);
return n;
}
-/** Write to a socket with iovec. */
ssize_t
sio_writev(int fd, const struct iovec *iov, int iovcnt)
{
@@ -305,225 +270,59 @@ sio_writev(int fd, const struct iovec *iov, int iovcnt)
return n;
}
-/** Blocking I/O writev */
-ssize_t
-sio_writev_all(int fd, struct iovec *iov, int iovcnt)
-{
- ssize_t bytes_total = 0;
- struct iovec *iovend = iov + iovcnt;
- while (1) {
- int cnt = iovend - iov;
- if (cnt > IOV_MAX)
- cnt = IOV_MAX;
- ssize_t write_res = writev(fd, iov, cnt);
- if (write_res < 0) {
- if (errno == EINTR)
- continue;
- tnt_raise(SocketError, sio_socketname(fd),
- "writev(%d)", cnt);
- }
- size_t bytes_written = (size_t)write_res;
- bytes_total += bytes_written;
- /*
- * Check for iov < iovend, since otherwise
- * if iovend->iov_len is 0, iov may go beyond
- * iovend
- */
- while (bytes_written >= iov->iov_len) {
- bytes_written -= (iov++)->iov_len;
- if (iov == iovend)
- break;
- }
- if (iov == iovend)
- break;
- iov->iov_base = (char *) iov->iov_base + bytes_written;
- iov->iov_len -= bytes_written;
- }
- return bytes_total;
-}
-
-ssize_t
-sio_readn_ahead(int fd, void *buf, size_t count, size_t buf_size)
-{
- size_t read_count = 0;
- while (read_count < count) {
- ssize_t read_res = read(fd, (char *) buf + read_count,
- buf_size - read_count);
- if (read_res < 0 && (errno == EWOULDBLOCK ||
- errno == EINTR || errno == EAGAIN))
- continue;
-
- if (read_res <= 0)
- tnt_raise(SocketError, sio_socketname(fd),
- "read (%zd)", count);
-
- read_count += read_res;
- }
- return read_count;
-}
-
-ssize_t
-sio_writen(int fd, const void *buf, size_t count)
-{
- size_t write_count = 0;
- while (write_count < count) {
- ssize_t write_res = write(fd, (char *) buf + write_count,
- count - write_count);
- if (write_res < 0 && (errno == EWOULDBLOCK ||
- errno == EINTR || errno == EAGAIN))
- continue;
-
- if (write_res <= 0)
- tnt_raise(SocketError, sio_socketname(fd),
- "write (%zd)", count);
-
- write_count += write_res;
- }
- return write_count;
-}
-
-static inline off_t
-sio_lseek(int fd, off_t offset, int whence)
-{
- off_t res = lseek(fd, offset, whence);
- if (res == -1)
- tnt_raise(SocketError, sio_socketname(fd),
- "lseek");
- return res;
-}
-
-#if defined(HAVE_SENDFILE_LINUX)
-ssize_t
-sio_sendfile(int sock_fd, int file_fd, off_t *offset, size_t size)
-{
- ssize_t send_res = sendfile(sock_fd, file_fd, offset, size);
- if (send_res < 0 || (size_t)send_res < size)
- tnt_raise(SocketError, sio_socketname(sock_fd),
- "sendfile");
- return send_res;
-}
-#else
-ssize_t
-sio_sendfile(int sock_fd, int file_fd, off_t *offset, size_t size)
-{
- if (offset)
- sio_lseek(file_fd, *offset, SEEK_SET);
-
- const size_t buffer_size = 8192;
- char buffer[buffer_size];
- size_t bytes_sent = 0;
- while (bytes_sent < size) {
- size_t to_send_now = MIN(size - bytes_sent, buffer_size);
- ssize_t n = sio_read(file_fd, buffer, to_send_now);
- sio_writen(sock_fd, buffer, n);
- bytes_sent += n;
- }
-
- if (offset)
- lseek(file_fd, *offset, SEEK_SET);
-
- return bytes_sent;
-}
-#endif
-
-ssize_t
-sio_recvfile(int sock_fd, int file_fd, off_t *offset, size_t size)
-{
- if (offset)
- sio_lseek(file_fd, *offset, SEEK_SET);
-
- const size_t buffer_size = 8192;
- char buffer[buffer_size];
- size_t bytes_read = 0;
- while (bytes_read < size) {
- size_t to_read_now = MIN(size - bytes_read, buffer_size);
- ssize_t n = sio_read(sock_fd, buffer, to_read_now);
- if (n < 0)
- return -1;
- sio_writen(file_fd, buffer, n);
- bytes_read += n;
- }
-
- if (offset)
- sio_lseek(file_fd, *offset, SEEK_SET);
-
- return bytes_read;
-}
-
-/** Send a message on a socket. */
ssize_t
sio_sendto(int fd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen)
{
ssize_t n = sendto(fd, buf, len, flags, (struct sockaddr*)dest_addr,
addrlen);
- if (n < 0 && errno != EAGAIN &&
- errno != EWOULDBLOCK && errno != EINTR)
- tnt_raise(SocketError, sio_socketname(fd),
- "sendto(%zd)", len);
+ if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
+ tnt_raise(SocketError, sio_socketname(fd), "sendto(%zd)", len);
return n;
}
-/** Receive a message on a socket. */
ssize_t
sio_recvfrom(int fd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
{
ssize_t n = recvfrom(fd, buf, len, flags, (struct sockaddr*)src_addr,
addrlen);
- if (n < 0 && errno != EAGAIN &&
- errno != EWOULDBLOCK && errno != EINTR)
- tnt_raise(SocketError, sio_socketname(fd),
- "recvfrom(%zd)", len);
+ if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
{
+ tnt_raise(SocketError, sio_socketname(fd), "recvfrom(%zd)",
+ len);
+ }
return n;
}
-/** Get socket peer name. */
int
sio_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen)
{
- if (getpeername(fd, addr, addrlen) < 0) {
+ int rc = getpeername(fd, addr, addrlen);
+ if (rc < 0)
say_syserror("getpeername");
- return -1;
- }
- /* XXX: I've no idea where this is copy-pasted from. */
- /*
- if (addr->sin_addr.s_addr == 0) {
- say_syserror("getpeername: empty peer");
- return -1;
- }
- */
- return 0;
+ return rc;
}
-/** Pretty print a peer address. */
const char *
sio_strfaddr(struct sockaddr *addr, socklen_t addrlen)
{
static __thread char name[NI_MAXHOST + _POSIX_PATH_MAX + 2];
- switch(addr->sa_family) {
- case AF_UNIX:
- if (addrlen >= sizeof(sockaddr_un)) {
- snprintf(name, sizeof(name), "unix/:%s",
- ((struct sockaddr_un *)addr)->sun_path);
- } else {
- snprintf(name, sizeof(name),
- "unix/:(socket)");
- }
- break;
- default: {
- char host[NI_MAXHOST], serv[NI_MAXSERV];
- if (getnameinfo(addr, addrlen, host, sizeof(host),
- serv, sizeof(serv),
- NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
- snprintf(name, sizeof(name),
- addr->sa_family == AF_INET
- ? "%s:%s" : "[%s]:%s", host, serv);
- } else {
- snprintf(name, sizeof(name), "(host):(port)");
- }
- break;
+ if (addr->sa_family == AF_UNIX) {
+ if (addrlen >= sizeof(struct sockaddr_un)) {
+ snprintf(name, sizeof(name), "unix/:%s",
+ ((struct sockaddr_un *)addr)->sun_path);
+ } else {
+ snprintf(name, sizeof(name), "unix/:(socket)");
}
+ return name;
+ }
+ char host[NI_MAXHOST], serv[NI_MAXSERV];
+ if (getnameinfo(addr, addrlen, host, sizeof(host), serv, sizeof(serv),
+ NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
+ snprintf(name, sizeof(name), addr->sa_family == AF_INET ?
+ "%s:%s" : "[%s]:%s", host, serv);
+ } else {
+ snprintf(name, sizeof(name), "(host):(port)");
}
return name;
}
diff --git a/src/sio.h b/src/sio.h
index f728af547..d937cfd3d 100644
--- a/src/sio.h
+++ b/src/sio.h
@@ -48,22 +48,23 @@ extern "C" {
enum { SERVICE_NAME_MAXLEN = 32 };
+/** Pretty print a peer address. */
const char *
sio_strfaddr(struct sockaddr *addr, socklen_t addrlen);
+/** Get socket peer name. */
int
sio_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen);
/**
- * Advance write position in the iovec array
- * based on its current value and the number of
- * bytes written.
+ * Advance write position in the iovec array based on its current
+ * value and the number of bytes written.
*
- * @param[in] iov the vector being written with writev().
- * @param[in] nwr number of bytes written, @pre >= 0
- * @param[in,out] iov_len offset in iov[0];
+ * @param iov The vector written with writev().
+ * @param nwr Number of bytes written.
+ * @param[in, out] iov_len Offset in iov[0];
*
- * @return offset of iov[0] for the next write
+ * @retval Offset of iov[0] for the next write
*/
static inline int
sio_move_iov(struct iovec *iov, size_t nwr, size_t *iov_len)
@@ -92,88 +93,115 @@ sio_add_to_iov(struct iovec *iov, size_t size)
#if defined(__cplusplus)
} /* extern "C" */
-const char *sio_socketname(int fd);
-int sio_socket(int domain, int type, int protocol);
+/** Pretty format socket name and peer. */
+const char *
+sio_socketname(int fd);
+
+/**
+ * Create a socket. A wrapper for socket() function, but sets
+ * diagnostics on error.
+ */
+int
+sio_socket(int domain, int type, int protocol);
-int sio_shutdown(int fd, int how);
+/**
+ * Get file descriptor flags. A wrapper for fcntl(F_GETFL), but
+ * sets diagnostics on error.
+ */
+int
+sio_getfl(int fd);
-int sio_getfl(int fd);
-int sio_setfl(int fd, int flag, int on);
+/**
+ * Set a file descriptor flag. A wrapper for
+ * fcntl(F_SETFL, flag | fcntl(F_GETFL)), but sets diagnostics on
+ * error.
+ */
+int
+sio_setfl(int fd, int flag);
+/**
+ * Set an option on a socket. A wrapper for setsockopt(), but sets
+ * diagnostics on error.
+ */
int
sio_setsockopt(int fd, int level, int optname,
const void *optval, socklen_t optlen);
+
+/**
+ * Get a socket option value. A wrapper for setsockopt(), but sets
+ * diagnostics on error.
+ */
int
sio_getsockopt(int fd, int level, int optname,
void *optval, socklen_t *optlen);
-int sio_connect(int fd, struct sockaddr *addr, socklen_t addrlen);
-int sio_bind(int fd, struct sockaddr *addr, socklen_t addrlen);
-int sio_listen(int fd);
-int sio_listen_backlog();
-int sio_accept(int fd, struct sockaddr *addr, socklen_t *addrlen);
-
-ssize_t sio_read(int fd, void *buf, size_t count);
-
-ssize_t sio_write(int fd, const void *buf, size_t count);
-ssize_t sio_writev(int fd, const struct iovec *iov, int iovcnt);
+/**
+ * Connect a client socket to a server. A wrapper for connect(),
+ * but sets diagnostics on error except EINPROGRESS.
+ */
+int
+sio_connect(int fd, struct sockaddr *addr, socklen_t addrlen);
-ssize_t sio_write_total(int fd, const void *buf, size_t count, size_t total);
+/**
+ * Bind a socket to the given address. A wrapper for bind(), but
+ * sets diagnostics on error except EADDRINUSE.
+ */
+int
+sio_bind(int fd, struct sockaddr *addr, socklen_t addrlen);
/**
- * Read at least count and up to buf_size bytes from fd.
- * Throw exception on error or disconnect.
- *
- * @return the number of of bytes actually read.
+ * Mark a socket as accepting connections. A wrapper for listen(),
+ * but throws exception on error.
*/
-ssize_t
-sio_readn_ahead(int fd, void *buf, size_t count, size_t buf_size);
+int
+sio_listen(int fd);
/**
- * Read count bytes from fd.
- * Throw an exception on error or disconnect.
- *
- * @return count of bytes actually read.
+ * Accept a client connection on a server socket. A wrapper for
+ * accept(), but throws exception on error except EAGAIN, EINTR,
+ * EWOULDBLOCK.
*/
-static inline ssize_t
-sio_readn(int fd, void *buf, size_t count)
-{
- return sio_readn_ahead(fd, buf, count, count);
-}
+int
+sio_accept(int fd, struct sockaddr *addr, socklen_t *addrlen);
/**
- * Write count bytes to fd.
- * Throw an exception on error or disconnect.
- *
- * @return count of bytes actually written.
+ * Read up to @a count bytes from a socket. A wrapper for read(),
+ * but throws exception on error except EWOULDBLOCK, EINTR,
+ * EAGAIN, ECONNRESET.
*/
ssize_t
-sio_writen(int fd, const void *buf, size_t count);
+sio_read(int fd, void *buf, size_t count);
-/* Only for blocked I/O */
+/**
+ * Write up to @a count bytes to a socket. A wrapper for write(),
+ * but throws exception on error except EAGAIN, EINTR,
+ * EWOULDBLOCK.
+ */
ssize_t
-sio_writev_all(int fd, struct iovec *iov, int iovcnt);
+sio_write(int fd, const void *buf, size_t count);
/**
- * A wrapper over sendfile.
- * Throw if send file failed.
+ * Write @a iov vector to a socket. A wrapper for writev(), but
+ * throws exception on error except EAGAIN, EINTR, EWOULDBLOCK.
*/
ssize_t
-sio_sendfile(int sock_fd, int file_fd, off_t *offset, size_t size);
+sio_writev(int fd, const struct iovec *iov, int iovcnt);
/**
- * Receive a file sent by sendfile
- * Throw if receiving failed
+ * Send a message on a socket. A wrapper for sendto(), but throws
+ * exception on error except EAGAIN, EINTR, EWOULDBLOCK.
*/
ssize_t
-sio_recvfile(int sock_fd, int file_fd, off_t *offset, size_t size);
-
+sio_sendto(int fd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen);
-ssize_t sio_sendto(int fd, const void *buf, size_t len, int flags,
- const struct sockaddr *dest_addr, socklen_t addrlen);
-
-ssize_t sio_recvfrom(int fd, void *buf, size_t len, int flags,
- struct sockaddr *src_addr, socklen_t *addrlen);
+/**
+ * Receive a message on a socket. A wrapper for recvfrom(), but
+ * throws exception on error except EAGAIN, EINTR, EWOULDBLOCK.
+ */
+ssize_t
+sio_recvfrom(int fd, void *buf, size_t len, int flags,
+ struct sockaddr *src_addr, socklen_t *addrlen);
#endif /* defined(__cplusplus) */
--
2.17.2 (Apple Git-113)