"Fossies" - the Fresh Open Source Software Archive

Member "nanomsg-1.1.5/src/utils/efd_win.inc" (15 Oct 2018, 5796 Bytes) of package /linux/misc/nanomsg-1.1.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) fasm source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "efd_win.inc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.1.4_vs_1.1.5.

    1 /*
    2     Copyright (c) 2012-2013 Martin Sustrik  All rights reserved.
    3     Copyright 2017 Garrett D'Amore <garrett@damore.org>
    4     Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
    5     Copyright 2018 Capitar IT Group BV <info@capitar.com>
    6 
    7 
    8     Permission is hereby granted, free of charge, to any person obtaining a copy
    9     of this software and associated documentation files (the "Software"),
   10     to deal in the Software without restriction, including without limitation
   11     the rights to use, copy, modify, merge, publish, distribute, sublicense,
   12     and/or sell copies of the Software, and to permit persons to whom
   13     the Software is furnished to do so, subject to the following conditions:
   14 
   15     The above copyright notice and this permission notice shall be included
   16     in all copies or substantial portions of the Software.
   17 
   18     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   19     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   20     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   21     THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   22     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   23     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   24     IN THE SOFTWARE.
   25 */
   26 
   27 #include "err.h"
   28 #include "fast.h"
   29 
   30 #include <string.h>
   31 #include <stdint.h>
   32 
   33 int nn_efd_init (struct nn_efd *self)
   34 {
   35     SOCKET listener;
   36     int rc;
   37     struct sockaddr_in addr;
   38     socklen_t addrlen;
   39     int one;
   40     BOOL nodelay;
   41     u_long nonblock;
   42 
   43     /*  Unfortunately, on Windows the only way to send signal to a file
   44         descriptor (SOCKET) is to create a full-blown TCP connecting on top of
   45         the loopback interface. */
   46     self->w = INVALID_SOCKET;
   47     self->r = INVALID_SOCKET;
   48 
   49     /*  Create listening socket. */
   50     listener = socket (AF_INET, SOCK_STREAM, 0);
   51     if (listener == SOCKET_ERROR)
   52         goto wsafail;
   53 
   54     one = 1;
   55     rc = setsockopt (listener, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 
   56         (char*) &one, sizeof (one));
   57     if (rc == SOCKET_ERROR)
   58         goto wsafail;
   59 
   60     /*  Bind the listening socket to the local port. */
   61     memset (&addr, 0, sizeof (addr));
   62     addr.sin_family = AF_INET;
   63     addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
   64     addr.sin_port = 0;
   65 
   66     rc = bind (listener, (const struct sockaddr*) &addr, sizeof (addr));
   67     if (rc == SOCKET_ERROR)
   68         goto wsafail;
   69 
   70     /*  Get the port we bound to (will be ephemeral.) */
   71     addrlen = sizeof (addr);
   72     rc = getsockname (listener, (struct sockaddr *) &addr, &addrlen);
   73     if (rc == SOCKET_ERROR)
   74         goto wsafail;
   75 
   76     /*  Start listening for the incomming connections. In normal case we are
   77         going to accept just a single connection, so backlog buffer of size
   78         1 is sufficient. */
   79     rc = listen (listener, 1);
   80     if (rc == SOCKET_ERROR)
   81         goto wsafail;
   82 
   83     /*  The following code is in the loop, because windows sometimes delays
   84         WSAEADDRINUSE error to the `connect` call. But retrying the connection
   85         works like a charm. Still we want to limit number of retries  */
   86 
   87     /*  Create the writer socket. */
   88     self->w = socket (AF_INET, SOCK_STREAM, 0);
   89     if (listener == SOCKET_ERROR)
   90         goto wsafail;
   91 
   92     /*  Set TCP_NODELAY on the writer socket to make efd as fast as possible.
   93         There's only one byte going to be written, so batching would not make
   94         sense anyway. */
   95         nodelay = 1;
   96     rc = setsockopt (self->w, IPPROTO_TCP, TCP_NODELAY, (char*) &nodelay,
   97         sizeof (nodelay));
   98     if (nn_slow (rc == SOCKET_ERROR))
   99         goto wsafail;
  100 
  101     /*  Connect the writer socket to the listener socket. */
  102     rc = connect (self->w, (struct sockaddr*) &addr, sizeof (addr));
  103     if (rc == SOCKET_ERROR)
  104         goto wsafail;
  105 
  106     /*  Accept new incoming connection. */
  107     addrlen = sizeof (addr);
  108     self->r = accept (listener, (struct sockaddr*) &addr, &addrlen);
  109     if (self->r == INVALID_SOCKET)
  110         goto wsafail;
  111 
  112     /*  Close the listener, we don't need it anymore. */
  113     (void) closesocket (listener);
  114 
  115     /*  Make the receiving socket non-blocking. */
  116     nonblock = 1;
  117     rc = ioctlsocket (self->r, FIONBIO, &nonblock);
  118     wsa_assert (rc != SOCKET_ERROR);
  119 
  120     return 0;
  121 
  122 wsafail:
  123     rc = nn_err_wsa_to_posix (WSAGetLastError ());
  124     return -rc;
  125 }
  126 
  127 void nn_efd_stop (struct nn_efd *self)
  128 {
  129     int rc;
  130     SOCKET s = self->w;
  131     self->w = INVALID_SOCKET;
  132 
  133     if (s != INVALID_SOCKET) {
  134         rc = closesocket (s);
  135         wsa_assert (rc != INVALID_SOCKET);
  136     }
  137 }
  138 
  139 void nn_efd_term (struct nn_efd *self)
  140 {
  141     int rc;
  142     SOCKET s;
  143 
  144     s = self->r;
  145     self->r = INVALID_SOCKET;
  146     if (s != INVALID_SOCKET) {
  147         rc = closesocket (s);
  148         wsa_assert (rc != INVALID_SOCKET);
  149     }
  150     s = self->w;
  151     self->w = INVALID_SOCKET;
  152     if (s != INVALID_SOCKET) {
  153        rc = closesocket (s);
  154        wsa_assert (rc != INVALID_SOCKET);
  155     }
  156 }
  157 
  158 nn_fd nn_efd_getfd (struct nn_efd *self)
  159 {
  160     return self->r;
  161 }
  162 
  163 void nn_efd_signal (struct nn_efd *self)
  164 {
  165     int rc;
  166     unsigned char c = 0xec;
  167     SOCKET s = self->w;
  168 
  169     if (nn_fast (s != INVALID_SOCKET)) {
  170         rc = send (s, (char*) &c, 1, 0);
  171         wsa_assert (rc != SOCKET_ERROR);
  172         nn_assert (rc == 1);
  173     }
  174 }
  175 
  176 void nn_efd_unsignal (struct nn_efd *self)
  177 {
  178     int rc;
  179     uint8_t buf [16];
  180 
  181     while (1) {
  182         SOCKET s = self->r;
  183         if (nn_slow (s == INVALID_SOCKET))
  184             break;
  185         rc = recv (s, (char*) buf, sizeof (buf), 0);
  186         if (rc == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK)
  187             rc = 0;
  188         wsa_assert (rc != SOCKET_ERROR);
  189         if ((rc == SOCKET_ERROR) || (rc < sizeof (buf)))
  190             break;
  191     }
  192 }
  193