Exemple #1
0
static void
chanSwitchListen(TChanSwitch * const chanSwitchP,
                 uint32_t      const backlog,
                 const char ** const errorP) {

    struct socketWin * const socketWinP = chanSwitchP->implP;

    int32_t const minus1 = -1;

    int rc;

    /* Disable the Nagle algorithm to make persistant connections faster */

    setsockopt(socketWinP->winsock, IPPROTO_TCP, TCP_NODELAY,
               (const char *)&minus1, sizeof(minus1));

    rc = listen(socketWinP->winsock, backlog);

    if (rc != 0) {
        int const lastError = WSAGetLastError();
        xmlrpc_asprintf(errorP, "setsockopt() failed with WSAERROR %d (%s)",
                        lastError, getWSAError(lastError));
    } else
        *errorP = NULL;
}
Exemple #2
0
void
bindSocketToPort(SOCKET           const winsock,
                 struct in_addr * const addrP,
                 uint16_t         const portNumber,
                 const char **    const errorP) {
    
    struct sockaddr_in name;
    int rc;
	int one = 1;

    ZeroMemory(&name, sizeof(name));
    name.sin_family = AF_INET;
    name.sin_port   = htons(portNumber);
    if (addrP)
        name.sin_addr = *addrP;

	setsockopt(winsock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(int));
    rc = bind(winsock, (struct sockaddr *)&name, sizeof(name));

    if (rc != 0) {
        int const lastError = WSAGetLastError();
        xmlrpc_asprintf(errorP, "Unable to bind socket to port number %u.  "
                        "bind() failed with WSAERROR %i (%s)",
                        portNumber, lastError, getWSAError(lastError));
    } else
        *errorP = NULL;
}
Exemple #3
0
static void
channelRead(TChannel *   const channelP, 
            unsigned char * const buffer, 
            uint32_t     const bufferSize,
            uint32_t *   const bytesReceivedP,
            bool * const failedP) {

    struct socketWin * const socketWinP = channelP->implP;
    int retries = 300; 
	
	for (*failedP = TRUE; *failedP && retries; retries--) {
		int rc = recv(socketWinP->winsock, buffer, bufferSize, 0);
		int lastError = WSAGetLastError();

		if (rc < 0) {
			if (lastError == WSAEWOULDBLOCK || lastError == ERROR_IO_PENDING) {
				fprintf(stderr, "Abyss: recv() failed with errno %d (%s) cnt %d, will retry\n", lastError, getWSAError(lastError), retries);
				SleepEx(30, TRUE);  /* give socket another chance after xx millisec)*/
				*failedP = FALSE;
			} else {
				fprintf(stderr, "Abyss: recv() failed with errno %d (%s)\n", lastError, getWSAError(lastError));
				break;
			}
		} else {
			*failedP = FALSE;
			*bytesReceivedP = rc;

			if (ChannelTraceIsActive)
				fprintf(stderr, "Abyss channel: read %u bytes: '%.*s'\n", bytesReceivedP, (int)(*bytesReceivedP), buffer);
		}
	}
}
Exemple #4
0
static void
chanSwitchAccept(TChanSwitch * const chanSwitchP,
                 TChannel **   const channelPP,
                 void **       const channelInfoPP,
                 const char ** const errorP) {
/*----------------------------------------------------------------------------
   Accept a connection via the channel switch *chanSwitchP.  Return as
   *channelPP the channel for the accepted connection.

   If no connection is waiting at *chanSwitchP, wait until one is.

   If we receive a signal while waiting, return immediately with
   *channelPP == NULL.
-----------------------------------------------------------------------------*/
    struct socketWin * const listenSocketP = chanSwitchP->implP;

    bool interrupted;
    TChannel * channelP;

    interrupted = FALSE; /* Haven't been interrupted yet */
    channelP    = NULL;  /* No connection yet */
    *errorP     = NULL;  /* No error yet */

    while (!channelP && !*errorP && !interrupted) {
        struct sockaddr peerAddr;
        socklen_t size = sizeof(peerAddr);
        int rc;

        rc = accept(listenSocketP->winsock, &peerAddr, &size);

        if (rc >= 0) {
            int const acceptedWinsock = rc;

            createChannelForAccept(acceptedWinsock, peerAddr,
                                   &channelP, channelInfoPP, errorP);

            if (*errorP)
                closesocket(acceptedWinsock);
        } else {
            int const lastError = WSAGetLastError();

            if (lastError == WSAEINTR)
                interrupted = TRUE;
            else
                xmlrpc_asprintf(errorP,
                                "accept() failed, WSA error = %d (%s)",
                                lastError, getWSAError(lastError));
        }
    }
    *channelPP = channelP;
}
Exemple #5
0
void
ChannelWinCreateWinsock(SOCKET                       const fd,
                        TChannel **                  const channelPP,
                        struct abyss_win_chaninfo ** const channelInfoPP,
                        const char **                const errorP) {

    struct sockaddr peerAddr;
    socklen_t peerAddrLen;
    int rc;

    peerAddrLen = sizeof(peerAddr);

    rc = getpeername(fd, &peerAddr, &peerAddrLen);

    if (rc != 0) {
        int const lastError = WSAGetLastError();
        if (lastError == WSAENOTCONN) {
            /* NOTE: This specific string 'not in connected' is
               required by one of the rpctest suite items, in abyss.c
               (line 186), hence the separation of the error messages
               in this case ...
            */
            xmlrpc_asprintf(errorP, "Socket on file descriptor %d "
                            "is not in connected state. WSAERROR = %d (%s)",
                            fd, lastError, getWSAError(lastError));
        } else
            xmlrpc_asprintf(errorP, "getpeername() failed. WSAERROR = %d (%s)",
                        lastError, getWSAError(lastError));
    } else {
        makeChannelInfo(channelInfoPP, peerAddr, peerAddrLen, errorP);
        if (!*errorP) {
            makeChannelFromWinsock(fd, channelPP, errorP);

            if (*errorP)
                free(*channelInfoPP);
        }
    }
}
Exemple #6
0
void
ChanSwitchWinCreate(uint16_t       const portNumber,
                    TChanSwitch ** const chanSwitchPP,
                    const char **  const errorP) {
/*----------------------------------------------------------------------------
   Create a Winsock-based channel switch.

   Set the socket's local address so that a subsequent "listen" will listen
   on all IP addresses, port number 'portNumber'.
-----------------------------------------------------------------------------*/
    struct socketWin * socketWinP;

    MALLOCVAR(socketWinP);

    if (!socketWinP)
        xmlrpc_asprintf(errorP, "Unable to allocate memory for Windows socket "
                        "descriptor structure.");
    else {
        SOCKET winsock;

        winsock = socket(AF_INET, SOCK_STREAM, 0);

        if (winsock == 0 || winsock == INVALID_SOCKET) {
            int const lastError = WSAGetLastError();
            xmlrpc_asprintf(errorP, "socket() failed with WSAERROR %d (%s)",
                            lastError, getWSAError(lastError));
        } else {
            socketWinP->winsock = winsock;
            socketWinP->userSuppliedWinsock = FALSE;
            socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
            
            setSocketOptions(socketWinP->winsock, errorP);
            if (!*errorP) {
                bindSocketToPort(socketWinP->winsock, NULL, portNumber,
                                 errorP);
                if (!*errorP)
                    ChanSwitchCreate(&chanSwitchVtbl, socketWinP,
                                     chanSwitchPP);
            }

            if (*errorP) {
                CloseHandle(socketWinP->interruptEvent);
                closesocket(winsock);
            }
        }
        if (*errorP)
            free(socketWinP);
    }
}
void
ChanSwitchWinCreate2(int                     const protocolFamily,
                     const struct sockaddr * const sockAddrP,
                     socklen_t               const sockAddrLen,
                     TChanSwitch **          const chanSwitchPP,
                     const char **           const errorP) {

    struct socketWin * socketWinP;

    MALLOCVAR(socketWinP);

    if (!socketWinP)
        xmlrpc_asprintf(errorP, "Unable to allocate memory for Windows socket "
                        "descriptor structure.");
    else {
        SOCKET winsock;

        winsock = socket(protocolFamily, SOCK_STREAM, 0);

        if (winsock == 0 || winsock == INVALID_SOCKET) {
            int const lastError = WSAGetLastError();
            xmlrpc_asprintf(errorP, "socket() failed with WSAERROR %d (%s)",
                            lastError, getWSAError(lastError));
        } else {
            socketWinP->winsock = winsock;
            socketWinP->userSuppliedWinsock = FALSE;
            socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
            
            setSocketOptions(socketWinP->winsock, errorP);
            if (!*errorP) {
                bindSocketToAddr(socketWinP->winsock, sockAddrP, sockAddrLen,
                                 errorP);
                if (!*errorP)
                    ChanSwitchCreate(&chanSwitchVtbl, socketWinP,
                                     chanSwitchPP);
            }

            if (*errorP) {
                CloseHandle(socketWinP->interruptEvent);
                closesocket(winsock);
            }
        }
        if (*errorP)
            free(socketWinP);
    }
}
Exemple #8
0
static void
setSocketOptions(SOCKET        const fd,
                 const char ** const errorP) {

    int32_t const n = 1;

    int rc;

    rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof(n));

    if (rc != 0) {
        int const lastError = WSAGetLastError();
        xmlrpc_asprintf(errorP, "Failed to set socket options.  "
                        "setsockopt() failed with WSAERROR %d (%s)",
                        lastError, getWSAError(lastError));
    } else
        *errorP = NULL;
}
Exemple #9
0
void
SocketWinInit(const char ** const errorP) {

    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
 
    wVersionRequested = MAKEWORD(1, 0);
 
    err = WSAStartup(wVersionRequested, &wsaData);

    if (err != 0) {
        int const lastError = WSAGetLastError();
        xmlrpc_asprintf(errorP, "WSAStartup() faild with error %d (%s)",
                        lastError, getWSAError(lastError));
    } else
        *errorP = NULL;
}
static void
bindSocketToAddr(SOCKET                     const winsock,
                 const struct sockaddr *    const addrP,
                 socklen_t                  const sockAddrLen,
                 const char **              const errorP) {
    
    int rc;

    rc = bind(winsock, (struct sockaddr *)addrP, sockAddrLen);

    if (rc != 0) {
        int const lastError = WSAGetLastError();
        xmlrpc_asprintf(errorP, "Unable to bind socket to the socket address.  "
                        "bind() failed with WSAERROR %i (%s)",
                        lastError, getWSAError(lastError));
    } else
        *errorP = NULL;
}
Exemple #11
0
static void
channelFormatPeerInfo(TChannel *    const channelP,
                      const char ** const peerStringP) {

    struct socketWin * const socketWinP = channelP->implP;

    struct sockaddr sockaddr;
    socklen_t sockaddrLen;
    int rc;

    sockaddrLen = sizeof(sockaddr);
    
    rc = getpeername(socketWinP->winsock, &sockaddr, &sockaddrLen);
    
    if (rc != 0) {
        int const lastError = WSAGetLastError();
        xmlrpc_asprintf(peerStringP, "?? getpeername() failed.  "
                        "WSAERROR %d (%s)",
                        lastError, getWSAError(lastError));
    } else {
        switch (sockaddr.sa_family) {
        case AF_INET: {
            struct sockaddr_in * const sockaddrInP =
                (struct sockaddr_in *) &sockaddr;
            if (sockaddrLen < sizeof(*sockaddrInP))
                xmlrpc_asprintf(peerStringP, "??? getpeername() returned "
                                "the wrong size");
            else {
                unsigned char * const ipaddr = (unsigned char *)
                    &sockaddrInP->sin_addr.s_addr;
                xmlrpc_asprintf(peerStringP, "%u.%u.%u.%u:%hu",
                                ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3],
                                sockaddrInP->sin_port);
            }
        } break;
        default:
            xmlrpc_asprintf(peerStringP, "??? AF=%u", sockaddr.sa_family);
        }
    }
}
Exemple #12
0
void
ChannelWinGetPeerName(TChannel *           const channelP,
                      struct sockaddr_in * const inAddrP,
                      const char **        const errorP) {

    struct socketWin * const socketWinP = channelP->implP;

    socklen_t addrlen;
    int rc;
    struct sockaddr sockAddr;

    addrlen = sizeof(sockAddr);
    
    rc = getpeername(socketWinP->winsock, &sockAddr, &addrlen);

    if (rc != 0) {
        int const lastError = WSAGetLastError();
        xmlrpc_asprintf(errorP, "getpeername() failed.  WSA error = %d (%s)",
                        lastError, getWSAError(lastError));
    } else {
        if (addrlen != sizeof(sockAddr))
            xmlrpc_asprintf(errorP, "getpeername() returned a socket address "
                            "of the wrong size: %u.  Expected %u",
                            addrlen, sizeof(sockAddr));
        else {
            if (sockAddr.sa_family != AF_INET)
                xmlrpc_asprintf(errorP,
                                "Socket does not use the Inet (IP) address "
                                "family.  Instead it uses family %d",
                                sockAddr.sa_family);
            else {
                *inAddrP = *(struct sockaddr_in *)&sockAddr;

                *errorP = NULL;
            }
        }
    }
}
Exemple #13
0
static void
chanSwitchAccept(TChanSwitch * const chanSwitchP,
                 TChannel **   const channelPP,
                 void **       const channelInfoPP,
                 const char ** const errorP) {
/*----------------------------------------------------------------------------
   Accept a connection via the channel switch *chanSwitchP.  Return as
   *channelPP the channel for the accepted connection.

   If no connection is waiting at *chanSwitchP, wait until one is.

   If we receive a signal while waiting, return immediately with
   *channelPP == NULL.
-----------------------------------------------------------------------------*/
    struct socketWin * const listenSocketP = chanSwitchP->implP;
    HANDLE acceptEvent = WSACreateEvent();
    bool interrupted;
    TChannel * channelP;

    interrupted = FALSE; /* Haven't been interrupted yet */
    channelP    = NULL;  /* No connection yet */
    *errorP     = NULL;  /* No error yet */

    WSAEventSelect(listenSocketP->winsock, acceptEvent,
                   FD_ACCEPT | FD_CLOSE | FD_READ);

    while (!channelP && !*errorP && !interrupted) {
        HANDLE interrupts[2] = {acceptEvent, listenSocketP->interruptEvent};
        int rc;
        struct sockaddr peerAddr;
        socklen_t size = sizeof(peerAddr);

        rc = WaitForMultipleObjects(2, interrupts, FALSE, INFINITE);
        if (WAIT_OBJECT_0 + 1 == rc) {
            interrupted = TRUE;
            continue;
        };

        rc = accept(listenSocketP->winsock, &peerAddr, &size);

        if (rc >= 0) {
            int const acceptedWinsock = rc;

            createChannelForAccept(acceptedWinsock, peerAddr,
                                   &channelP, channelInfoPP, errorP);

            if (*errorP)
                closesocket(acceptedWinsock);
        } else {
            int const lastError = WSAGetLastError();

            if (lastError == WSAEINTR)
                interrupted = TRUE;
            else
                xmlrpc_asprintf(errorP,
                                "accept() failed, WSA error = %d (%s)",
                                lastError, getWSAError(lastError));
        }
    }
    *channelPP = channelP;
    CloseHandle(acceptEvent);
}
Exemple #14
0
static void
channelWrite(TChannel *            const channelP,
             const unsigned char * const buffer,
             uint32_t              const len,
             bool *                const failedP) {

    struct socketWin * const socketWinP = channelP->implP;

    size_t bytesLeft;
    bool error;
	int to_count = 0;
	int lastError = 0;

	for (bytesLeft = len, error = FALSE; bytesLeft > 0 && !error;) {
        size_t const maxSend = 	4096 * 2; /* with respect to resource allocation this might be a better value than 2^31 */ 

        int rc = send(socketWinP->winsock, buffer + len - bytesLeft, MIN(maxSend, bytesLeft), 0);
		if (rc > 0) {          /* 0 means connection closed; < 0 means severe error */
			to_count = 0;
		    bytesLeft -= rc;
		} 
		else if (!rc) {
			error = TRUE;
			fprintf(stderr, "Abyss: send() failed: connection closed");
		}
		else {
			error = TRUE;
			lastError = WSAGetLastError();
            if (lastError == WSAEWOULDBLOCK || lastError == ERROR_IO_PENDING) {
				SleepEx(20, TRUE);  /* give socket another chance after xx millisec) */
				if (++to_count < 300) {
					error = FALSE;
				}
			    //  fprintf(stderr, "Abyss: send() failed with errno %d (%s) cnt %d, will retry\n", lastError, getWSAError(lastError), to_count);
			}
			if (error) fprintf(stderr, "Abyss: send() failed with errno %d (%s)\n", lastError, getWSAError(lastError));
		}
    }

	*failedP = error;
}