root/opal/win32/opal_socket.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. create_socketpair

   1 /*
   2  * Copyright (c) 2010      High Performance Computing Center Stuttgart,
   3  *                         University of Stuttgart.  All rights reserved.
   4  * $COPYRIGHT$
   5  *
   6  * Additional copyrights may follow
   7  *
   8  * $HEADER$
   9  */
  10 
  11 #include "opal_config.h"
  12 
  13 #include "opal/win32/opal_socket.h"
  14 #include "opal/util/output.h"
  15 
  16 int
  17 create_socketpair(int family, int type, int protocol, int fd[2])
  18 {
  19     /* This code is originally from Tor.  Used with permission. */
  20 
  21     /* This socketpair does not work when localhost is down. So
  22      * it's really not the same thing at all. But it's close enough
  23      * for now, and really, when localhost is down sometimes, we
  24      * have other problems too.
  25      */
  26 #ifdef WIN32
  27 #define ERR(e) WSA##e
  28 #else
  29 #define ERR(e) e
  30 #endif
  31     int listener = -1;
  32     int connector = -1;
  33     int acceptor = -1;
  34     struct sockaddr_in listen_addr;
  35     struct sockaddr_in connect_addr;
  36     int size;
  37     int saved_errno = -1;
  38 
  39     if (protocol
  40         || (family != AF_INET
  41 #ifdef AF_UNIX
  42             && family != AF_UNIX
  43 #endif
  44         )) {
  45         opal_output(0, "Protocol not support: %d", (ERR(EAFNOSUPPORT)));
  46         return -1;
  47     }
  48     if (!fd) {
  49         opal_output(0, "Invalid socked: %d", (ERR(EINVAL)));
  50         return -1;
  51     }
  52 
  53     listener = socket(AF_INET, type, 0);
  54     if (listener < 0)
  55         return -1;
  56     memset(&listen_addr, 0, sizeof(listen_addr));
  57     listen_addr.sin_family = AF_INET;
  58     listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  59     listen_addr.sin_port = 0;    /* kernel chooses port.     */
  60     if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
  61         == -1)
  62         goto tidy_up_and_fail;
  63     if (listen(listener, 1) == -1)
  64         goto tidy_up_and_fail;
  65 
  66     connector = socket(AF_INET, type, 0);
  67     if (connector < 0)
  68         goto tidy_up_and_fail;
  69     /* We want to find out the port number to connect to.  */
  70     size = sizeof(connect_addr);
  71     if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
  72         goto tidy_up_and_fail;
  73     if (size != sizeof (connect_addr))
  74         goto abort_tidy_up_and_fail;
  75     if (connect(connector, (struct sockaddr *) &connect_addr,
  76                 sizeof(connect_addr)) == -1)
  77         goto tidy_up_and_fail;
  78 
  79     size = sizeof(listen_addr);
  80     acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
  81     if (acceptor < 0)
  82         goto tidy_up_and_fail;
  83     if (size != sizeof(listen_addr))
  84         goto abort_tidy_up_and_fail;
  85     closesocket(listener);
  86     /* Now check we are talking to ourself by matching port and host on the
  87        two sockets.     */
  88     if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
  89         goto tidy_up_and_fail;
  90     if (size != sizeof (connect_addr)
  91         || listen_addr.sin_family != connect_addr.sin_family
  92         || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
  93         || listen_addr.sin_port != connect_addr.sin_port)
  94         goto abort_tidy_up_and_fail;
  95     fd[0] = connector;
  96     fd[1] = acceptor;
  97 
  98     return 0;
  99 
 100  abort_tidy_up_and_fail:
 101     saved_errno = ERR(ECONNABORTED);
 102  tidy_up_and_fail:
 103     if (saved_errno < 0)
 104         saved_errno = WSAGetLastError();
 105     if (listener != -1)
 106         closesocket(listener);
 107     if (connector != -1)
 108         closesocket(connector);
 109     if (acceptor != -1)
 110         closesocket(acceptor);
 111 
 112     WSASetLastError(saved_errno);
 113     return -1;
 114 #undef ERR
 115 }

/* [<][>][^][v][top][bottom][index][help] */