Edit

kc3-lang/libevent/evutil.c

Branch :

  • Show log

    Commit

  • Author : Nick Mathewson
    Date : 2007-10-12 17:55:37
    Hash : e1f09dfe
    Message : Fix evutil code to use correct EVUTIL_SET_SOCKET_ERROR macro. svn:r460

  • evutil.c
  • /*
     * 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 <winsock2.h>
    #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 <errno.h>
    
    #include "evutil.h"
    #include "log.h"
    
    int
    evutil_socketpair(int family, int type, int protocol, int fd[2])
    {
    #ifndef WIN32
    	return socketpair(family, type, protocol, fd);
    #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
    		) {
    		EVUTIL_SET_SOCKET_ERROR(WSAEAFNOSUPPORT);
    		return -1;
    	}
    	if (!fd) {
    		EVUTIL_SET_SOCKET_ERROR(WSAEINVAL);
    		return -1;
    	}
    
    	listener = socket(AF_INET, type, 0);
    	if (listener < 0)
    		return -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 = 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 = WSAGetLastError();
    	if (listener != -1)
    		EVUTIL_CLOSESOCKET(listener);
    	if (connector != -1)
    		EVUTIL_CLOSESOCKET(connector);
    	if (acceptor != -1)
    		EVUTIL_CLOSESOCKET(acceptor);
    
    	EVUTIL_SET_SOCKET_ERROR(saved_errno);
    	return -1;
    #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;
    }