]> granicus.if.org Git - libevent/commitdiff
r15216@catbus: nickm | 2007-09-20 13:58:23 -0400
authorNick Mathewson <nickm@torproject.org>
Thu, 20 Sep 2007 18:26:40 +0000 (18:26 +0000)
committerNick Mathewson <nickm@torproject.org>
Thu, 20 Sep 2007 18:26:40 +0000 (18:26 +0000)
 Add a new evutil module to contain the usual cross-platform hacks: socketpair, closesocket, and make_socket_nonblocking()

svn:r441

ChangeLog
Makefile.am
WIN32-Code/misc.c
configure.in
evutil.c [new file with mode: 0644]
evutil.h [new file with mode: 0644]

index 9a18a37513d30cca4f1323216c14565b98f429de..e660b6621c1f8bd8f3307315577281677cd12785 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -17,3 +17,4 @@ Changes in current version:
  o Add Doxygen documentation to header files; from Mark Heily
  o Add a evdns_set_transaction_id_fn() function to override the default
    transaction ID generation code.
+ o Add an evutil module (with header evutil.h) to implement our standard cross-platform hacks, on the theory that somebody else would like to use them too.
index f89c0bc008b477b805af146eff98301fd251653e..ff806910231b06c21f19836a05b45740358efb5d 100644 (file)
@@ -40,13 +40,14 @@ SYS_INCLUDES =
 endif
 
 libevent_la_SOURCES = event.c buffer.c evbuffer.c log.c event_tagging.c \
-       http.c evhttp.h http-internal.h evdns.c evdns.h evrpc.c strlcpy.c \
+       http.c evhttp.h http-internal.h evdns.c evdns.h evrpc.c evutil.c \
+       strlcpy.c \
        strlcpy-internal.h evrpc.h evrpc-internal.h strlcpy-internal.h \
        $(SYS_SRC)
 libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
 libevent_la_LDFLAGS = -release @VERSION@ -version-info 1:3:0
 
-include_HEADERS = event.h evhttp.h evdns.h evrpc.h
+include_HEADERS = event.h evhttp.h evdns.h evrpc.h evutil.h
 
 INCLUDES = -I$(srcdir)/compat $(SYS_INCLUDES)
 
index bdebc3a4f4948cb4bcfd3ec179cf478ddbf0362f..4de0f4292ca9239bae044676348bc64bd68e89ee 100644 (file)
@@ -65,6 +65,7 @@ win_write(int fd, void *buf, unsigned int length)
                return (dwBytesWritten);
 }
 
+#if 0
 int
 socketpair(int d, int type, int protocol, int *sv)
 {
@@ -89,3 +90,4 @@ socketpair(int d, int type, int protocol, int *sv)
 
        return (0);
 }
+#endif
index 0e7585e818273955069983c890ad479930e0c944..99de01d789b3bb231761838f1c42ed260bf7fdc3 100644 (file)
@@ -42,7 +42,7 @@ AC_CHECK_LIB(nsl, inet_ntoa)
 
 dnl Checks for header files.
 AC_HEADER_STDC
-AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in6.h)
+AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in6.h sys/socket.h)
 if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
        AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
        AC_EGREP_CPP(yes,
diff --git a/evutil.c b/evutil.c
new file mode 100644 (file)
index 0000000..2af3115
--- /dev/null
+++ b/evutil.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2007 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include "misc.h"
+#endif
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include "evutil.h"
+#include "log.h"
+
+int
+evutil_socketpair(int d, int type, int protocol, int sv[2])
+{
+#ifndef WIN32
+       return socketpair(d, type, protocol, sv);
+#else
+       /* This code is originally from Tor.  Used with permission. */
+
+       /* This socketpair does not work when localhost is down. So
+        * it's really not the same thing at all. But it's close enough
+        * for now, and really, when localhost is down sometimes, we
+        * have other problems too.
+        */
+       int listener = -1;
+       int connector = -1;
+       int acceptor = -1;
+       struct sockaddr_in listen_addr;
+       struct sockaddr_in connect_addr;
+       int size;
+       int saved_errno = -1;
+
+       if (protocol
+#ifdef AF_UNIX
+               || family != AF_UNIX
+#endif
+               ) {
+               return -WSAEAFNOSUPPORT;
+       }
+       if (!fd) {
+               return -EINVAL;
+       }
+
+       listener = tor_open_socket(AF_INET, type, 0);
+       if (listener < 0)
+               return -tor_socket_errno(-1);
+       memset(&listen_addr, 0, sizeof(listen_addr));
+       listen_addr.sin_family = AF_INET;
+       listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       listen_addr.sin_port = 0;       /* kernel chooses port.  */
+       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;
+
+       connector = tor_open_socket(AF_INET, type, 0);
+       if (connector < 0)
+               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)
+               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)
+               goto tidy_up_and_fail;
+
+       size = sizeof(listen_addr);
+       acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
+       if (acceptor < 0)
+               goto tidy_up_and_fail;
+       if (size != sizeof(listen_addr))
+               goto abort_tidy_up_and_fail;
+       EVUTIL_CLOSESOCKET(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)
+               goto tidy_up_and_fail;
+       if (size != sizeof (connect_addr)
+               || listen_addr.sin_family != connect_addr.sin_family
+               || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
+               || listen_addr.sin_port != connect_addr.sin_port)
+               goto abort_tidy_up_and_fail;
+       fd[0] = connector;
+       fd[1] = acceptor;
+
+       return 0;
+
+ abort_tidy_up_and_fail:
+       saved_errno = WSAECONNABORTED;
+ tidy_up_and_fail:
+       if (saved_errno < 0)
+               saved_errno = errno;
+       if (listener != -1)
+               EVUTIL_CLOSESOCKET(listener);
+       if (connector != -1)
+               EVUTIL_CLOSESOCKET(connector);
+       if (acceptor != -1)
+               EVUTIL_CLOSESOCKET(acceptor);
+       return -saved_errno;
+#endif
+}
+
+int
+evutil_make_socket_nonblocking(int fd)
+{
+#ifdef WIN32
+       {
+               unsigned long nonblocking = 1;
+               ioctlsocket(fd, FIONBIO, (unsigned long*) &nonblocking);
+       }
+#else
+       if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
+               event_warn("fcntl(O_NONBLOCK)");
+               return -1;
+       }
+#endif
+       return 0;
+}
+
diff --git a/evutil.h b/evutil.h
new file mode 100644 (file)
index 0000000..10cb417
--- /dev/null
+++ b/evutil.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _EVUTIL_H_
+#define _EVUTIL_H_
+
+/** @file evutil.h
+
+  Common convenience functions for cross-platform portability and
+  related socket manipulations.
+
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int evutil_socketpair(int d, int type, int protocol, int sv[2]);
+int evutil_make_socket_nonblocking(int sock);
+#ifdef WIN32
+#define EVUTIL_CLOSESOCKET(s) closesocket(s)
+#else
+#define EVUTIL_CLOSESOCKET(s) close(s)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EVUTIL_H_ */