* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
- * $Id: commio.c 25358 2008-05-13 14:48:46Z androsyn $
+ * $Id: commio.c 26254 2008-12-10 04:04:38Z androsyn $
*/
#include <libratbox_config.h>
#include <ratbox_lib.h>
/* Highest FD and number of open FDs .. */
static int number_fd = 0;
-static int rb_maxconnections = 0;
+int rb_maxconnections = 0;
static PF rb_connect_timeout;
static PF rb_connect_tryconnect;
#ifndef HAVE_SOCKETPAIR
static int rb_inet_socketpair(int d, int type, int protocol, int sv[2]);
+static int rb_inet_socketpair_udp(rb_fde_t **newF1, rb_fde_t **newF2);
#endif
static inline rb_fde_t *
add_fd(int fd)
{
rb_fde_t *F = rb_find_fd(fd);
- rb_dlink_list *list;
/* look up to see if we have it already */
if(F != NULL)
- return F;
-
+ return F;
+
F = rb_bh_alloc(fd_heap);
F->fd = fd;
- list = &rb_fd_table[rb_hash_fd(fd)];
- rb_dlinkAdd(F, &F->node, list);
- return(F);
+ rb_dlinkAdd(F, &F->node, &rb_fd_table[rb_hash_fd(fd)]);
+ return (F);
}
static inline void
remove_fd(rb_fde_t *F)
{
- rb_dlink_list *list;
-
if(F == NULL || !IsFDOpen(F))
return;
-
- list = &rb_fd_table[rb_hash_fd(F->fd)];
- rb_dlinkMoveNode(&F->node, list, &closed_list);
+
+ rb_dlinkMoveNode(&F->node, &rb_fd_table[rb_hash_fd(F->fd)], &closed_list);
}
-static void
+static void
free_fds(void)
{
rb_fde_t *F;
static void
rb_close_all(void)
{
+#ifndef _WIN32
int i;
-#ifndef NDEBUG
- int fd;
-#endif
/* XXX someone tell me why we care about 4 fd's ? */
/* XXX btw, fd 3 is used for profiler ! */
- for (i = 4; i < rb_maxconnections; ++i)
+ for(i = 3; i < rb_maxconnections; ++i)
{
close(i);
}
-
- /* XXX should his hack be done in all cases? */
-#ifndef NDEBUG
- /* fugly hack to reserve fd == 2 */
- (void) close(2);
- fd = open("stderr.log", O_WRONLY | O_CREAT | O_APPEND, 0644);
- if(fd >= 0)
- {
- dup2(fd, 2);
- close(fd);
- }
#endif
}
errtmp = errno;
#ifdef SO_ERROR
- if(F != NULL && !getsockopt(rb_get_fd(F), SOL_SOCKET, SO_ERROR, (char *) &err, (rb_socklen_t *) & len))
+ if(F != NULL
+ && !getsockopt(rb_get_fd(F), SOL_SOCKET, SO_ERROR, (char *)&err, (rb_socklen_t *) & len))
{
if(err)
errtmp = err;
int
rb_getmaxconnect(void)
{
- return(rb_maxconnections);
+ return (rb_maxconnections);
}
/*
if(F == NULL)
return 0;
if(setsockopt
- (F->fd, SOL_SOCKET, SO_RCVBUF, (char *) &size, sizeof(size))
- || setsockopt(F->fd, SOL_SOCKET, SO_SNDBUF, (char *) &size, sizeof(size)))
+ (F->fd, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size))
+ || setsockopt(F->fd, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(size)))
return 0;
return 1;
}
if(F == NULL)
return 0;
fd = F->fd;
-
+
if((res = rb_setup_fd(F)))
return res;
#ifdef O_NONBLOCK
lrb_assert(IsFDOpen(F));
td = F->timeout;
- if(callback == NULL) /* user wants to remove */
+ if(callback == NULL) /* user wants to remove */
{
if(td == NULL)
return;
rb_dlinkDelete(&td->node, &timeout_list);
rb_free(td);
F->timeout = NULL;
- if(rb_dlink_list_length(&timeout_list) == 0)
+ if(rb_dlink_list_length(&timeout_list) == 0)
{
rb_event_delete(rb_timeout_ev);
rb_timeout_ev = NULL;
}
if(F->timeout == NULL)
- td = F->timeout = rb_malloc(sizeof(struct timeout_data));
-
+ td = F->timeout = rb_malloc(sizeof(struct timeout_data));
+
td->F = F;
td->timeout = rb_current_time() + timeout;
td->timeout_handler = callback;
rb_dlinkAdd(td, &td->node, &timeout_list);
if(rb_timeout_ev == NULL)
{
- rb_timeout_ev = rb_event_add("rb_checktimeouts", rb_checktimeouts, NULL, 5);
+ rb_timeout_ev = rb_event_add("rb_checktimeouts", rb_checktimeouts, NULL, 5);
}
}
F->timeout = NULL;
rb_free(td);
hdl(F, data);
- }
+ }
}
}
new_F = rb_open(new_fd, RB_FD_SOCKET, "Incoming Connection");
- if(unlikely(!rb_set_nb(new_F)))
+ if(new_F == NULL)
+ {
+ rb_lib_log
+ ("rb_accept: new_F == NULL on incoming connection. Closing new_fd == %d\n",
+ new_fd);
+ close(new_fd);
+ continue;
+ }
+
+ if(rb_unlikely(!rb_set_nb(new_F)))
{
rb_get_errno();
rb_lib_log("rb_accept: Couldn't set FD %d non blocking!", new_F->fd);
#ifdef RB_IPV6
mangle_mapped_sockaddr((struct sockaddr *)&st);
#endif
-
+
if(F->accept->precb != NULL)
{
- if(!F->accept->precb(new_F, (struct sockaddr *)&st, addrlen, F->accept->data)) /* pre-callback decided to drop it */
+ if(!F->accept->precb(new_F, (struct sockaddr *)&st, addrlen, F->accept->data)) /* pre-callback decided to drop it */
continue;
}
#ifdef HAVE_SSL
if(F->type & RB_FD_SSL)
{
- rb_ssl_accept_setup(F, new_fd, (struct sockaddr *)&st, addrlen);
- }
+ rb_ssl_accept_setup(F, new_F, (struct sockaddr *)&st, addrlen);
+ }
else
-#endif /* HAVE_SSL */
+#endif /* HAVE_SSL */
{
- F->accept->callback(new_F, RB_OK, (struct sockaddr *)&st, addrlen, F->accept->data);
+ F->accept->callback(new_F, RB_OK, (struct sockaddr *)&st, addrlen,
+ F->accept->data);
}
}
/* try to accept a TCP connection */
void
-rb_accept_tcp(rb_fde_t *F, ACPRE *precb, ACCB *callback, void *data)
+rb_accept_tcp(rb_fde_t *F, ACPRE * precb, ACCB * callback, void *data)
{
if(F == NULL)
return;
*/
void
rb_connect_tcp(rb_fde_t *F, struct sockaddr *dest,
- struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int timeout)
+ struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int timeout)
{
if(F == NULL)
return;
-
+
lrb_assert(callback);
F->connect = rb_malloc(sizeof(struct conndata));
F->connect->callback = callback;
{
CNCB *hdl;
void *data;
- int errtmp = errno; /* save errno as rb_settimeout clobbers it sometimes */
+ int errtmp = errno; /* save errno as rb_settimeout clobbers it sometimes */
/* This check is gross..but probably necessary */
if(F == NULL || F->connect == NULL || F->connect->callback == NULL)
/* Clear the timeout handler */
rb_settimeout(F, 0, NULL, NULL);
- errno = errtmp;
+ errno = errtmp;
/* Call the handler */
hdl(F, status, data);
}
return;
/* Try the connect() */
retval = connect(F->fd,
- (struct sockaddr *) &F->connect->hostaddr, GET_SS_LEN(&F->connect->hostaddr));
+ (struct sockaddr *)&F->connect->hostaddr,
+ GET_SS_LEN(&F->connect->hostaddr));
/* Error? */
if(retval < 0)
{
rb_connect_callback(F, RB_OK);
else if(rb_ignore_errno(errno))
/* Ignore error? Reschedule */
- rb_setselect(F, RB_SELECT_CONNECT,
- rb_connect_tryconnect, NULL);
+ rb_setselect(F, RB_SELECT_CONNECT, rb_connect_tryconnect, NULL);
else
/* Error? Fail with RB_ERR_CONNECT */
rb_connect_callback(F, RB_ERR_CONNECT);
return -1;
}
-#ifndef WIN32
+#ifdef HAVE_SOCKETPAIR
if(socketpair(family, sock_type, proto, nfd))
#else
- if(rb_inet_socketpair(AF_INET, SOCK_STREAM, proto, nfd))
+ if(sock_type == SOCK_DGRAM)
+ {
+ return rb_inet_socketpair_udp(F1, F2);
+ }
+
+ if(rb_inet_socketpair(AF_INET, sock_type, proto, nfd))
#endif
return -1;
}
/* Set the socket non-blocking, and other wonderful bits */
- if(unlikely(!rb_set_nb(*F1)))
+ if(rb_unlikely(!rb_set_nb(*F1)))
{
rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd[0], strerror(errno));
rb_close(*F1);
return -1;
}
- if(unlikely(!rb_set_nb(*F2)))
+ if(rb_unlikely(!rb_set_nb(*F2)))
{
rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd[1], strerror(errno));
rb_close(*F1);
int
rb_pipe(rb_fde_t **F1, rb_fde_t **F2, const char *desc)
{
-#ifndef WIN32
+#ifndef _WIN32
int fd[2];
if(number_fd >= rb_maxconnections)
{
*F1 = rb_open(fd[0], RB_FD_PIPE, desc);
*F2 = rb_open(fd[1], RB_FD_PIPE, desc);
- if(unlikely(!rb_set_nb(*F1)))
+ if(rb_unlikely(!rb_set_nb(*F1)))
{
rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd[0], strerror(errno));
rb_close(*F1);
return -1;
}
- if(unlikely(!rb_set_nb(*F2)))
+ if(rb_unlikely(!rb_set_nb(*F2)))
{
rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd[1], strerror(errno));
rb_close(*F1);
/* Its not a pipe..but its selectable. I'll take dirty hacks
* for $500 Alex.
*/
- return rb_socketpair(AF_INET, SOCK_STREAM, 0, F1, F2, desc);
+ return rb_socketpair(AF_INET, SOCK_STREAM, 0, F1, F2, desc);
#endif
}
rb_fde_t *F;
int fd;
/* First, make sure we aren't going to run out of file descriptors */
- if(unlikely(number_fd >= rb_maxconnections))
+ if(rb_unlikely(number_fd >= rb_maxconnections))
{
errno = ENFILE;
return NULL;
*/
fd = socket(family, sock_type, proto);
rb_fd_hack(&fd);
- if(unlikely(fd < 0))
+ if(rb_unlikely(fd < 0))
return NULL; /* errno will be passed through, yay.. */
#if defined(RB_IPV6) && defined(IPV6_V6ONLY)
if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)) == -1)
{
rb_lib_log("rb_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s",
- fd, strerror(errno));
+ fd, strerror(errno));
close(fd);
return NULL;
}
F = rb_open(fd, RB_FD_SOCKET, note);
if(F == NULL)
+ {
+ rb_lib_log("rb_socket: rb_open returns NULL on FD %d: %s, closing fd", fd,
+ strerror(errno));
+ close(fd);
return NULL;
-
+ }
/* Set the socket non-blocking, and other wonderful bits */
- if(unlikely(!rb_set_nb(F)))
+ if(rb_unlikely(!rb_set_nb(F)))
{
rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd, strerror(errno));
rb_close(F);
static void
mangle_mapped_sockaddr(struct sockaddr *in)
{
- struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) in;
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)in;
if(in->sa_family == AF_INET)
return;
memset(&in4, 0, sizeof(struct sockaddr_in));
in4.sin_family = AF_INET;
in4.sin_port = in6->sin6_port;
- in4.sin_addr.s_addr = ((rb_uint32_t *) & in6->sin6_addr)[3];
+ in4.sin_addr.s_addr = ((uint32_t *)&in6->sin6_addr)[3];
memcpy(in, &in4, sizeof(struct sockaddr_in));
}
return;
int
rb_listen(rb_fde_t *F, int backlog)
{
- F->type = RB_FD_SOCKET|RB_FD_LISTEN;
+ F->type = RB_FD_SOCKET | RB_FD_LISTEN;
/* Currently just a simple wrapper for the sake of being complete */
return listen(F->fd, backlog);
}
rb_fdlist_init(int closeall, int maxfds, size_t heapsize)
{
static int initialized = 0;
-#ifdef WIN32
+#ifdef _WIN32
WSADATA wsaData;
int err;
int vers = MAKEWORD(2, 0);
-
+
err = WSAStartup(vers, &wsaData);
if(err != 0)
{
/* Called to open a given filedescriptor */
rb_fde_t *
-rb_open(int fd, rb_uint8_t type, const char *desc)
+rb_open(int fd, uint8_t type, const char *desc)
{
- rb_fde_t *F = add_fd(fd);
+ rb_fde_t *F;
lrb_assert(fd >= 0);
- if(unlikely(IsFDOpen(F)))
+ F = add_fd(fd);
+
+ lrb_assert(!IsFDOpen(F));
+ if(rb_unlikely(IsFDOpen(F)))
{
+ const char *fdesc;
+ if(F != NULL && F->desc != NULL)
+ fdesc = F->desc;
+ else
+ fdesc = "NULL";
+ rb_lib_log("Trying to rb_open an already open FD: %d desc: %s", fd, fdesc);
return NULL;
}
- lrb_assert(!IsFDOpen(F));
F->fd = fd;
F->type = type;
SetFDOpen(F);
rb_close(rb_fde_t *F)
{
int type, fd;
-
+
if(F == NULL)
return;
fd = F->fd;
- type = F->type;
+ type = F->type;
lrb_assert(IsFDOpen(F));
lrb_assert(!(type & RB_FD_FILE));
- if(unlikely(type & RB_FD_FILE))
+ if(rb_unlikely(type & RB_FD_FILE))
{
lrb_assert(F->read_handler == NULL);
lrb_assert(F->write_handler == NULL);
number_fd--;
-#ifdef WIN32
- if(type & (RB_FD_SOCKET|RB_FD_PIPE))
+#ifdef _WIN32
+ if(type & (RB_FD_SOCKET | RB_FD_PIPE))
{
closesocket(fd);
return;
- } else
+ }
+ else
#endif
- close(fd);
+ close(fd);
}
}
void
-rb_set_type(rb_fde_t *F, rb_uint8_t type)
+rb_set_type(rb_fde_t *F, uint8_t type)
{
/* if the caller is calling this, lets assume they have a clue */
F->type = type;
return;
}
-rb_uint8_t
+uint8_t
rb_get_type(rb_fde_t *F)
{
return F->type;
}
-int
+int
rb_fd_ssl(rb_fde_t *F)
{
if(F == NULL)
return 0;
}
-int
+int
rb_get_fd(rb_fde_t *F)
{
if(F == NULL)
return -1;
- return(F->fd);
+ return (F->fd);
}
rb_fde_t *
ssize_t ret;
if(F == NULL)
return 0;
-
+
/* This needs to be *before* RB_FD_SOCKET otherwise you'll process
* an SSL socket as a regular socket
*/
if(F->type & RB_FD_SSL)
{
return rb_ssl_read(F, buf, count);
- }
+ }
#endif
if(F->type & RB_FD_SOCKET)
{
if(F->type & RB_FD_SSL)
{
return rb_ssl_write(F, buf, count);
- }
+ }
#endif
if(F->type & RB_FD_SOCKET)
{
ret = send(F->fd, buf, count, MSG_NOSIGNAL);
- if(ret < 0) {
+ if(ret < 0)
+ {
rb_get_errno();
}
return ret;
{
ssize_t count = 0;
- while (vpcount-- > 0)
+ while(vpcount-- > 0)
{
ssize_t written = rb_write(F, vp->iov_base, vp->iov_len);
- if (written <= 0)
+ if(written <= 0)
{
if(count > 0)
return count;
#if defined(WIN32) || !defined(HAVE_WRITEV)
ssize_t
-rb_writev(rb_fde_t *F, struct rb_iovec *vecount, int count)
+rb_writev(rb_fde_t *F, struct rb_iovec * vecount, int count)
{
return rb_fake_writev(F, vecount, count);
}
#else
ssize_t
-rb_writev(rb_fde_t *F, struct rb_iovec *vector, int count)
+rb_writev(rb_fde_t *F, struct rb_iovec * vector, int count)
{
- if(F == NULL) {
+ if(F == NULL)
+ {
errno = EBADF;
return -1;
}
#ifdef HAVE_SSL
if(F->type & RB_FD_SSL)
{
- return rb_fake_writev(F, vector, count);
+ return rb_fake_writev(F, vector, count);
}
#endif /* HAVE_SSL */
#ifdef HAVE_SENDMSG
msg.msg_iov = (struct iovec *)vector;
msg.msg_iovlen = count;
return sendmsg(F->fd, &msg, MSG_NOSIGNAL);
- }
+ }
#endif /* HAVE_SENDMSG */
return writev(F->fd, (struct iovec *)vector, count);
}
-#endif
+#endif
/*
{
static char buf[16];
char *bufptr = buf;
- const unsigned char *a = (const unsigned char *) in;
+ const unsigned char *a = (const unsigned char *)in;
const char *n;
n = IpQuadTab[*a++];
- while (*n)
+ while(*n)
*bufptr++ = *n++;
*bufptr++ = '.';
n = IpQuadTab[*a++];
- while (*n)
+ while(*n)
*bufptr++ = *n++;
*bufptr++ = '.';
n = IpQuadTab[*a++];
- while (*n)
+ while(*n)
*bufptr++ = *n++;
*bufptr++ = '.';
n = IpQuadTab[*a];
- while (*n)
+ while(*n)
*bufptr++ = *n++;
*bufptr = '\0';
return buf;
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
-static const char *inet_ntop4(const unsigned char * src, char *dst, unsigned int size);
+static const char *inet_ntop4(const unsigned char *src, char *dst, unsigned int size);
#ifdef RB_IPV6
-static const char *inet_ntop6(const unsigned char * src, char *dst, unsigned int size);
+static const char *inet_ntop6(const unsigned char *src, char *dst, unsigned int size);
#endif
/* const char *
{
if(size < 16)
return NULL;
- return strcpy(dst, inetntoa((const char *) src));
+ return strcpy(dst, inetntoa((const char *)src));
}
/* const char *
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
memset(words, '\0', sizeof words);
- for (i = 0; i < IN6ADDRSZ; i += 2)
+ for(i = 0; i < IN6ADDRSZ; i += 2)
words[i / 2] = (src[i] << 8) | src[i + 1];
best.base = -1;
best.len = 0;
cur.base = -1;
cur.len = 0;
- for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
+ for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
{
if(words[i] == 0)
{
* Format the result.
*/
tp = tmp;
- for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
+ for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
{
/* Are we inside the best run of 0x00's? */
if(best.base != -1 && i >= best.base && i < (best.base + best.len))
* Check for overflow, copy, and we're done.
*/
- if((unsigned int) (tp - tmp) > size)
+ if((unsigned int)(tp - tmp) > size)
{
return (NULL);
}
int
rb_inet_pton_sock(const char *src, struct sockaddr *dst)
{
- if(rb_inet_pton(AF_INET, src, &((struct sockaddr_in *) dst)->sin_addr))
+ if(rb_inet_pton(AF_INET, src, &((struct sockaddr_in *)dst)->sin_addr))
{
- ((struct sockaddr_in *) dst)->sin_port = 0;
- ((struct sockaddr_in *) dst)->sin_family = AF_INET;
+ ((struct sockaddr_in *)dst)->sin_port = 0;
+ ((struct sockaddr_in *)dst)->sin_family = AF_INET;
SET_SS_LEN(dst, sizeof(struct sockaddr_in));
return 1;
}
#ifdef RB_IPV6
- else if(rb_inet_pton(AF_INET6, src, &((struct sockaddr_in6 *) dst)->sin6_addr))
+ else if(rb_inet_pton(AF_INET6, src, &((struct sockaddr_in6 *)dst)->sin6_addr))
{
- ((struct sockaddr_in6 *) dst)->sin6_port = 0;
- ((struct sockaddr_in6 *) dst)->sin6_family = AF_INET6;
+ ((struct sockaddr_in6 *)dst)->sin6_port = 0;
+ ((struct sockaddr_in6 *)dst)->sin6_family = AF_INET6;
SET_SS_LEN(dst, sizeof(struct sockaddr_in6));
return 1;
}
switch (src->sa_family)
{
case AF_INET:
- return (rb_inet_ntop(AF_INET, &((struct sockaddr_in *) src)->sin_addr, dst, size));
+ return (rb_inet_ntop(AF_INET, &((struct sockaddr_in *)src)->sin_addr, dst, size));
break;
#ifdef RB_IPV6
case AF_INET6:
- return (rb_inet_ntop(AF_INET6, &((struct sockaddr_in6 *) src)->sin6_addr, dst, size));
+ return (rb_inet_ntop
+ (AF_INET6, &((struct sockaddr_in6 *)src)->sin6_addr, dst, size));
break;
#endif
default:
return (inet_ntop4(src, dst, size));
#ifdef RB_IPV6
case AF_INET6:
- if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr *) src) ||
- IN6_IS_ADDR_V4COMPAT((const struct in6_addr *) src))
+ if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src) ||
+ IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src))
return (inet_ntop4
- ((const unsigned char *)
- &((const struct in6_addr *) src)->s6_addr[12], dst, size));
+ ((const unsigned char *)&((const struct in6_addr *)src)->
+ s6_addr[12], dst, size));
else
return (inet_ntop6(src, dst, size));
saw_digit = 0;
octets = 0;
*(tp = tmp) = 0;
- while ((ch = *src++) != '\0')
+ while((ch = *src++) != '\0')
{
if(ch >= '0' && ch <= '9')
curtok = src;
saw_xdigit = 0;
val = 0;
- while ((ch = tolower(*src++)) != '\0')
+ while((ch = tolower(*src++)) != '\0')
{
const char *pch;
}
if(tp + INT16SZ > endp)
return (0);
- *tp++ = (unsigned char) (val >> 8) & 0xff;
- *tp++ = (unsigned char) val & 0xff;
+ *tp++ = (unsigned char)(val >> 8) & 0xff;
+ *tp++ = (unsigned char)val & 0xff;
saw_xdigit = 0;
val = 0;
continue;
{
if(tp + INT16SZ > endp)
return (0);
- *tp++ = (unsigned char) (val >> 8) & 0xff;
- *tp++ = (unsigned char) val & 0xff;
+ *tp++ = (unsigned char)(val >> 8) & 0xff;
+ *tp++ = (unsigned char)val & 0xff;
}
if(colonp != NULL)
{
if(tp == endp)
return (0);
- for (i = 1; i <= n; i++)
+ for(i = 1; i <= n; i++)
{
endp[-i] = colonp[n - i];
colonp[n - i] = 0;
#ifndef HAVE_SOCKETPAIR
+
+/* mostly based on perl's emulation of socketpair udp */
+static int
+rb_inet_socketpair_udp(rb_fde_t **newF1, rb_fde_t **newF2)
+{
+ struct sockaddr_in addr[2];
+ rb_socklen_t size = sizeof(struct sockaddr_in);
+ rb_fde_t *F[2];
+ unsigned int fd[2];
+ int i, got;
+ unsigned short port;
+ struct timeval wait = { 0, 100000 };
+ int max;
+ fd_set rset;
+ struct sockaddr_in readfrom;
+ unsigned short buf[2];
+ int o_errno;
+
+ memset(&addr, 0, sizeof(addr));
+
+ for(i = 0; i < 2; i++)
+ {
+ F[i] = rb_socket(AF_INET, SOCK_DGRAM, 0, "udp socketpair");
+ if(F[i] == NULL)
+ goto failed;
+ addr[i].sin_family = AF_INET;
+ addr[i].sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr[i].sin_port = 0;
+ if(bind(rb_get_fd(F[i]), (struct sockaddr *)&addr[i], sizeof(struct sockaddr_in)))
+ goto failed;
+ fd[i] = rb_get_fd(F[i]);
+ }
+
+ for(i = 0; i < 2; i++)
+ {
+ if(getsockname(fd[i], (struct sockaddr *)&addr[i], &size))
+ goto failed;
+ if(size != sizeof(struct sockaddr_in))
+ goto failed;
+ if(connect(fd[!i], (struct sockaddr *)&addr[i], sizeof(struct sockaddr_in)) == -1)
+ goto failed;
+ }
+
+ for(i = 0; i < 2; i++)
+ {
+ port = addr[i].sin_port;
+ got = rb_write(F[i], &port, sizeof(port));
+ if(got != sizeof(port))
+ {
+ if(got == -1)
+ goto failed;
+ goto abort_failed;
+ }
+ }
+
+ max = fd[1] > fd[0] ? fd[1] : fd[0];
+ FD_ZERO(&rset);
+ FD_SET(fd[0], &rset);
+ FD_SET(fd[1], &rset);
+ got = select(max + 1, &rset, NULL, NULL, &wait);
+ if(got != 2 || !FD_ISSET(fd[0], &rset) || !FD_ISSET(fd[1], &rset))
+ {
+ if(got == -1)
+ goto failed;
+ goto abort_failed;
+ }
+
+ for(i = 0; i < 2; i++)
+ {
+#ifdef MSG_DONTWAIT
+ int flag = MSG_DONTWAIT
+#else
+ int flag = 0;
+#endif
+ got = recvfrom(rb_get_fd(F[i]), (char *)&buf, sizeof(buf), flag,
+ (struct sockaddr *)&readfrom, &size);
+ if(got == -1)
+ goto failed;
+ if(got != sizeof(port)
+ || size != sizeof(struct sockaddr_in)
+ || buf[0] != (unsigned short)addr[!i].sin_port
+ || readfrom.sin_family != addr[!i].sin_family
+ || readfrom.sin_addr.s_addr != addr[!i].sin_addr.s_addr
+ || readfrom.sin_port != addr[!i].sin_port)
+ goto abort_failed;
+ }
+
+ *newF1 = F[0];
+ *newF2 = F[1];
+ return 0;
+
+#ifdef _WIN32
+#define ECONNABORTED WSAECONNABORTED
+#endif
+
+ abort_failed:
+ rb_get_errno();
+ errno = ECONNABORTED;
+ failed:
+ if(errno != ECONNABORTED)
+ rb_get_errno();
+ o_errno = errno;
+ if(F[0] != NULL)
+ rb_close(F[0]);
+ if(F[1] != NULL)
+ rb_close(F[1]);
+ errno = o_errno;
+ return -1;
+}
+
+
int
rb_inet_socketpair(int family, int type, int protocol, int fd[2])
{
int acceptor = -1;
struct sockaddr_in listen_addr;
struct sockaddr_in connect_addr;
- size_t size;
+ rb_socklen_t size;
if(protocol || family != AF_INET)
{
listen_addr.sin_family = AF_INET;
listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
listen_addr.sin_port = 0; /* kernel choses port. */
- if(bind(listener, (struct sockaddr *) &listen_addr, sizeof(listen_addr)) == -1)
+ if(bind(listener, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) == -1)
goto tidy_up_and_fail;
if(listen(listener, 1) == -1)
goto tidy_up_and_fail;
goto tidy_up_and_fail;
/* We want to find out the port number to connect to. */
size = sizeof(connect_addr);
- if(getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
+ if(getsockname(listener, (struct sockaddr *)&connect_addr, &size) == -1)
goto tidy_up_and_fail;
if(size != sizeof(connect_addr))
goto abort_tidy_up_and_fail;
- if(connect(connector, (struct sockaddr *) &connect_addr, sizeof(connect_addr)) == -1)
+ if(connect(connector, (struct sockaddr *)&connect_addr, sizeof(connect_addr)) == -1)
goto tidy_up_and_fail;
size = sizeof(listen_addr);
- acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
+ acceptor = accept(listener, (struct sockaddr *)&listen_addr, &size);
if(acceptor == -1)
goto tidy_up_and_fail;
if(size != sizeof(listen_addr))
close(listener);
/* Now check we are talking to ourself by matching port and host on the
two sockets. */
- if(getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
+ if(getsockname(connector, (struct sockaddr *)&connect_addr, &size) == -1)
goto tidy_up_and_fail;
if(size != sizeof(connect_addr)
|| listen_addr.sin_family != connect_addr.sin_family
rb_strlcpy(iotype, "kqueue", sizeof(iotype));
return 0;
}
- return -1;
+ return -1;
}
static int
{
setselect_handler = rb_setselect_ports;
select_handler = rb_select_ports;
- setup_fd_handler = rb_setup_fd_ports;
- io_sched_event = NULL;
- io_unsched_event = NULL;
- io_init_event = NULL;
- io_supports_event = rb_unsupported_event;
+ setup_fd_handler = rb_setup_fd_ports;
+ io_sched_event = rb_ports_sched_event;
+ io_unsched_event = rb_ports_unsched_event;
+ io_init_event = rb_ports_init_event;
+ io_supports_event = rb_ports_supports_event;
rb_strlcpy(iotype, "ports", sizeof(iotype));
return 0;
}
{
setselect_handler = rb_setselect_devpoll;
select_handler = rb_select_devpoll;
- setup_fd_handler = rb_setup_fd_devpoll;
+ setup_fd_handler = rb_setup_fd_devpoll;
io_sched_event = NULL;
io_unsched_event = NULL;
io_init_event = NULL;
{
setselect_handler = rb_setselect_sigio;
select_handler = rb_select_sigio;
- setup_fd_handler = rb_setup_fd_sigio;
+ setup_fd_handler = rb_setup_fd_sigio;
io_sched_event = rb_sigio_sched_event;
- io_unsched_event = rb_sigio_unsched_event;
- io_supports_event = rb_sigio_supports_event;
- io_init_event = rb_sigio_init_event;
-
+ io_unsched_event = rb_sigio_unsched_event;
+ io_supports_event = rb_sigio_supports_event;
+ io_init_event = rb_sigio_init_event;
+
rb_strlcpy(iotype, "sigio", sizeof(iotype));
return 0;
}
return -1;
}
-static int
+static int
try_poll(void)
{
if(!rb_init_netio_poll())
{
setselect_handler = rb_setselect_poll;
select_handler = rb_select_poll;
- setup_fd_handler = rb_setup_fd_poll;
+ setup_fd_handler = rb_setup_fd_poll;
io_sched_event = NULL;
io_unsched_event = NULL;
io_init_event = NULL;
{
setselect_handler = rb_setselect_win32;
select_handler = rb_select_win32;
- setup_fd_handler = rb_setup_fd_win32;
+ setup_fd_handler = rb_setup_fd_win32;
io_sched_event = NULL;
io_unsched_event = NULL;
io_init_event = NULL;
static int
try_select(void)
-{
+{
if(!rb_init_netio_select())
{
setselect_handler = rb_setselect_select;
select_handler = rb_select_select;
- setup_fd_handler = rb_setup_fd_select;
+ setup_fd_handler = rb_setup_fd_select;
io_sched_event = NULL;
io_unsched_event = NULL;
io_init_event = NULL;
int
rb_io_sched_event(struct ev_entry *ev, int when)
{
- if(ev == NULL || io_supports_event == NULL || io_sched_event == NULL || !io_supports_event())
+ if(ev == NULL || io_supports_event == NULL || io_sched_event == NULL
+ || !io_supports_event())
return 0;
return io_sched_event(ev, when);
}
void
rb_io_unsched_event(struct ev_entry *ev)
{
- if(ev == NULL || io_supports_event == NULL || io_unsched_event == NULL || !io_supports_event())
+ if(ev == NULL || io_supports_event == NULL || io_unsched_event == NULL
+ || !io_supports_event())
return;
- io_unsched_event(ev);
+ io_unsched_event(ev);
}
+
int
rb_io_supports_event(void)
{
char *ioenv = getenv("LIBRB_USE_IOTYPE");
rb_fd_table = rb_malloc(RB_FD_HASH_SIZE * sizeof(rb_dlink_list));
rb_init_ssl();
-
+
if(ioenv != NULL)
{
if(!strcmp("epoll", ioenv))
{
if(!try_epoll())
return;
- } else
- if(!strcmp("kqueue", ioenv))
+ }
+ else if(!strcmp("kqueue", ioenv))
{
if(!try_kqueue())
return;
- } else
- if(!strcmp("ports", ioenv))
+ }
+ else if(!strcmp("ports", ioenv))
{
if(!try_ports())
return;
- } else
- if(!strcmp("poll", ioenv))
+ }
+ else if(!strcmp("poll", ioenv))
{
if(!try_poll())
return;
- } else
- if(!strcmp("devpoll", ioenv))
+ }
+ else if(!strcmp("devpoll", ioenv))
{
if(!try_devpoll())
return;
- } else
- if(!strcmp("sigio", ioenv))
+ }
+ else if(!strcmp("sigio", ioenv))
{
if(!try_sigio())
return;
- } else
- if(!strcmp("win32", ioenv))
+ }
+ else if(!strcmp("select", ioenv))
{
- if(!try_win32())
+ if(!try_select())
return;
}
- if(!strcmp("select", ioenv))
+ if(!strcmp("win32", ioenv))
{
- if(!try_select())
+ if(!try_win32())
return;
}
-
+
}
if(!try_kqueue())
abort();
}
-void
+void
rb_setselect(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
{
setselect_handler(F, type, handler, client_data);
}
-int
+int
rb_select(unsigned long timeout)
{
int ret = select_handler(timeout);
return ret;
}
-int
+int
rb_setup_fd(rb_fde_t *F)
{
return setup_fd_handler(F);
int
rb_ignore_errno(int error)
{
- switch(error)
+ switch (error)
{
#ifdef EINPROGRESS
- case EINPROGRESS:
+ case EINPROGRESS:
#endif
#if defined EWOULDBLOCK
- case EWOULDBLOCK:
+ case EWOULDBLOCK:
#endif
#if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN)
- case EAGAIN:
+ case EAGAIN:
#endif
#ifdef EINTR
- case EINTR:
+ case EINTR:
#endif
#ifdef ERESTART
- case ERESTART:
+ case ERESTART:
#endif
#ifdef ENOBUFS
- case ENOBUFS:
-#endif
- return 1;
- default:
- break;
- }
+ case ENOBUFS:
+#endif
+ return 1;
+ default:
+ break;
+ }
return 0;
}
+#if defined(HAVE_SENDMSG) && !defined(WIN32)
int
rb_recv_fd_buf(rb_fde_t *F, void *data, size_t datasize, rb_fde_t **xF, int nfds)
{
struct cmsghdr *cmsg;
struct iovec iov[1];
struct stat st;
- rb_uint8_t stype = RB_FD_UNKNOWN;
+ uint8_t stype = RB_FD_UNKNOWN;
const char *desc;
int fd, len, x, rfds;
iov[0].iov_base = data;
iov[0].iov_len = datasize;
-
+
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
if((len = recvmsg(rb_get_fd(F), &msg, 0)) <= 0)
return len;
- if(msg.msg_controllen > 0 && msg.msg_control != NULL && (cmsg = CMSG_FIRSTHDR(&msg)) != NULL)
+ if(msg.msg_controllen > 0 && msg.msg_control != NULL
+ && (cmsg = CMSG_FIRSTHDR(&msg)) != NULL)
{
- rfds = (msg.msg_controllen - sizeof(struct cmsghdr)) / sizeof(int);
+ rfds = ((unsigned char *)cmsg + cmsg->cmsg_len - CMSG_DATA(cmsg)) / sizeof(int);
for(x = 0; x < nfds && x < rfds; x++)
{
}
xF[x] = rb_open(fd, stype, desc);
}
- } else
+ }
+ else
*xF = NULL;
- return len;
+ return len;
}
int
-rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasize)
+rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasize, pid_t pid)
{
int n;
struct msghdr msg;
if(datasize == 0)
{
iov[0].iov_base = ∅
- iov[0].iov_len = 1;
- } else {
+ iov[0].iov_len = 1;
+ }
+ else
+ {
iov[0].iov_base = data;
iov[0].iov_len = datasize;
}
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * count);
for(i = 0; i < count; i++)
- {
- ((int *)CMSG_DATA(cmsg))[i] = rb_get_fd(F[i]);
+ {
+ ((int *)CMSG_DATA(cmsg))[i] = rb_get_fd(F[i]);
}
msg.msg_controllen = cmsg->cmsg_len;
}
n = sendmsg(rb_get_fd(xF), &msg, MSG_NOSIGNAL);
return n;
}
+#else
+#ifndef _WIN32
+int
+rb_recv_fd_buf(rb_fde_t *F, void *data, size_t datasize, rb_fde_t **xF, int nfds)
+{
+ errno = ENOSYS;
+ return -1;
+}
+int
+rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasize, pid_t pid)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+#endif