Ejemplo n.º 1
0
int __cdecl main(int argc, char **argv)
{

    char *interface = NULL;
    char *Buffer = NULL;
    char *port = DEFAULT_PORT;
    char host[NI_MAXHOST];
    char serv[NI_MAXSERV];
    int hostlen = NI_MAXHOST;
    int servlen = NI_MAXSERV;
    int ai_family = AF_UNSPEC;
    int i = 0;
    int nStartup = 0;
    struct addrinfo hints = {0};
    struct addrinfo *local = NULL;
    WSADATA wsaData;
    SOCKET listen_socket = INVALID_SOCKET;
    SOCKET accept_socket = INVALID_SOCKET;
    WSAOVERLAPPED *Overlap = NULL;
    DWORD bytes = 0;
    DWORD bytes_read = 0;
    DWORD lasterror = 0;

    //
    // Handles is the array that stores the Event Handles
    //
    WSAEVENT Handles[MAX_IO_PEND] ;

    //
    // socklist is a parallel array that keeps state information for
    // each Handle.
    //
    Socklist socklist[MAX_IO_PEND];

    //
    // Pointers to Microsoft specific extensions
    //
    LPFN_ACCEPTEX pfnAcceptEx;
    GUID acceptex_guid = WSAID_ACCEPTEX;

    __try
    {


        if (NULL == (Buffer = (char*)XMALLOC(((2*sizeof(SOCKADDR_STORAGE))+32)*sizeof(char))))
        {
            ERR("HeapAlloc()");
            __leave;

        }

        //
        // Parse arguments
        //
        if ( argc > 1 )
        {
            for ( i = 1;i < argc; i++ )
            {
                if ( (argv[i][0] == '-') || (argv[i][0] == '/') )
                {
                    switch ( tolower(argv[i][1]) )
                    {
                    
                    case 'i':
                        if ( i+1 < argc )
                            interface = argv[++i];
                        break;
                    case 'e':
                        if ( i+1 < argc )
                            port = argv[++i];
                        break;
                    default:
                        {
                            Usage(argv[0]);
                            __leave;
                        }
                        break;
                    }
                }
                else
                {
                    Usage(argv[0]);
                    __leave;
                }
            }
        }

        //
        // Since port 0 would be any available port. 
        // Resetting port back to DEFAULT_PORT to avoid confusion.
        //
        if ( 0 == strncmp(port, "0", 1) )
        {
            port = DEFAULT_PORT;
        }

        if ( 0 != (nStartup = WSAStartup(WS_VER, &wsaData)) )
        {
            WSASetLastError(nStartup); //WSAStartup does not set last error on failure
            ERR("WSAStartup()");
            __leave;

        }
        else
            nStartup++;

        //
        // Resolve the interface
        //
        SecureZeroMemory(&hints,sizeof(hints));
        hints.ai_flags  = ((interface) ? 0 : AI_PASSIVE);
        hints.ai_family = ai_family;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;

        if ( 0 != getaddrinfo(interface, port, &hints, &local))
        {
            ERR("getaddrinfo()");
            __leave;
        }

        ai_family = local->ai_family;

        if (NULL == local)
        {
            fprintf(stderr, "getaddrinfo() failed to resolve/convert the interface\n");
            __leave;
        }

        if (INVALID_SOCKET == (listen_socket = WSASocket(local->ai_family, 
                                                         local->ai_socktype, 
                                                         local->ai_protocol, 
                                                         NULL, 
                                                         0,
                                                         WSA_FLAG_OVERLAPPED
                                                        )))
        {
            ERR("WSASocket()");
            __leave;
        }


        if ( SOCKET_ERROR == bind(listen_socket, 
                                  local->ai_addr, 
                                  (int)local->ai_addrlen
                                 ))
        {
            ERR("bind()");
            __leave;
        }


        if ( SOCKET_ERROR == listen(listen_socket, DEFAULT_BACKLOG))
        {
            ERR("listen()");
            __leave;
        }

        //
        // Resolve numeric host name
        //
        if ( 0 != getnameinfo(local->ai_addr, 
                              (int)local->ai_addrlen, 
                              host, 
                              hostlen, 
                              serv, 
                              servlen,
                              NI_NUMERICHOST | NI_NUMERICSERV
                             ))
        {
            ERR("getnameinfo()");
            __leave;
        }

        // Don't need the local interface anymore
        if (NULL != local)
            freeaddrinfo(local);

        printf("Listening on %s:%s\n", host, serv);

        //
        // Add the listening socket to our state information for the handle.
        //
        socklist[0].sock = listen_socket;

        curr_size =1;

        for ( i = 0;i < MAX_IO_PEND;i++ )
            Handles[i] = WSA_INVALID_EVENT;

        //
        // Load the extension functions
        //

        if ( SOCKET_ERROR == WSAIoctl(listen_socket, 
                                      SIO_GET_EXTENSION_FUNCTION_POINTER,
                                      &acceptex_guid,
                                      sizeof(acceptex_guid),
                                      &pfnAcceptEx,
                                      sizeof(pfnAcceptEx), 
                                      &bytes, 
                                      NULL, 
                                      NULL
                                     ))
        {
            fprintf(stderr,"Failed to obtain AcceptEx() pointer: ");
            ERR("WSAIoctl()");
            __leave;
        }

        //
        // The structure of the following loop is very similar to a situation
        // where select() might be used. 
        // We use WSAGetOverlappedResult() to multiplex between incoming/outgoing
        // data on existing connections.
        //
        // We don't queue an AcceptEx() until someone actually connects to 
        // the previous socket. This is to keep the code simple, not a limitation
        // of the API itself.
        //
        for ( ;; )
        {

            // create a socket for AcceptEx()

            if (INVALID_SOCKET == (accept_socket = WSASocket(ai_family, 
                                                             SOCK_STREAM, 
                                                             0, 
                                                             NULL, 
                                                             0,
                                                             WSA_FLAG_OVERLAPPED
                                                            )))
            {
                ERR("WSASocket()");
                __leave;
            }

            //
            // Allocate an overlapped structure.
            // We use the Offset field to keep track of the socket handle
            // we have accepted a connection on, since there is no other
            // way to pass information to GetOverlappedResult()
            //
            Overlap = (WSAOVERLAPPED*)XMALLOC(sizeof(WSAOVERLAPPED));

            //
            // Did the HeapAllocation FAIL??
            //
            if ( Overlap == NULL )
            {
                ERR("HeapAlloc()");
                __leave;
            }

            SecureZeroMemory(Overlap, sizeof(WSAOVERLAPPED));

            if ( WSA_INVALID_EVENT == (Overlap->hEvent = WSACreateEvent() ))
            {
                ERR("WSACreateEvent()");
                __leave;
            }

            //
            // Set the appropriate array members
            //
            Handles[0] = Overlap->hEvent;
            socklist[0].overlap = Overlap;
            socklist[0].SockAccepted = accept_socket;

            //
            // AcceptEx()
            //
            if ( !pfnAcceptEx(listen_socket, 
                              accept_socket, 
                              Buffer,
                              0, // read nothing from the socket
                              sizeof(SOCKADDR_STORAGE)+16, 
                              sizeof(SOCKADDR_STORAGE)+16,
                              &bytes_read, 
                              Overlap
                             ))
            {

                lasterror = WSAGetLastError();
                if ( WSA_IO_PENDING != lasterror)
                {
                    ERR("AcceptEx()");
                    for ( i = 0; i < curr_size; i++ )
                    {
                        shutdown(socklist[i].sock, SD_BOTH);
                        CLOSESOCK(socklist[i].sock);
                        XFREE(socklist[i].overlap);
                        CLOSEEVENT(Handles[i]);
                    }
                    __leave;
                }
            }

            //
            // This loop simple checks the handles to see which one is 
            // signalled. 
            // If error, exit. 
            // If there is a new incoming connection, we break to the outer loop
            // queue another AcceptEx()
            //
            for ( ;; )
            {
                i = DoWait(Handles, socklist);
                if ( i < 0 )
                    break;
                HandleEvent(i, Handles, socklist);
                if ( i == 0 )
                    break;
            };
            if ( i < 0 )
            {
                for ( i = 0; i < curr_size; i++ )
                {
                    shutdown(socklist[i].sock, SD_BOTH);
                    CLOSESOCK(socklist[i].sock);
                    XFREE(socklist[i].overlap);
                    CLOSEEVENT(Handles[i]);
                }
                __leave;
            }
        }
    }
    __finally
    {
        XFREE(Buffer);
        if (NULL != local) freeaddrinfo(local);
        CLOSESOCK(listen_socket); 
        CLOSESOCK(accept_socket);
        CLOSEEVENT(Overlap->hEvent);
        XFREE(Overlap);

    }
}
Ejemplo n.º 2
0
int net_recvSmtpResponse(int sock, int * smtpCode, int timeout)
{
	WSAOVERLAPPED recvOverlapped;
	WSABUF dataBuf;

	DWORD recvBytes = 0;
	int index       = 0;
	DWORD flags     = 0;
	int rc          = 0;
	int lastError   = 0;

	int bytesLeft = SMTP_MAX_TEXT_LINE_LEN-1;
	int bufSize = SMTP_MAX_TEXT_LINE_LEN;

	char buf[SMTP_MAX_TEXT_LINE_LEN] = {0};
	char * p = NULL;

	// Make sure the RecvOverlapped struct is zeroed out
	SecureZeroMemory((PVOID) &recvOverlapped, sizeof (WSAOVERLAPPED));
	SecureZeroMemory((PVOID) &dataBuf, sizeof (WSABUF));
	SecureZeroMemory((PVOID) &buf, sizeof (buf));

	// Create an event handle and setup an overlapped structure.
	recvOverlapped.hEvent = WSACreateEvent();
	if (recvOverlapped.hEvent == NULL) 
	{
		debug_log(LOG_ERR, "net_recvSmtpResponse(): WSACreateEvent failed: %d", WSAGetLastError());	
		closesocket(sock);
		return SOCK_IO_ERROR;
	}

	while (index < bufSize) 
	{		
		recvBytes = 0;
		flags = 0;

		dataBuf.len = 1; 
	    dataBuf.buf = &buf[index];

wait_for_recv:  // submit the request

		rc = WSARecv(sock, &dataBuf, 1, &recvBytes, &flags, &recvOverlapped, NULL);
		if (rc != 0)
		{
			if (rc == SOCKET_ERROR) 
			{
				lastError = WSAGetLastError();

				if (lastError == WSAEWOULDBLOCK)
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_recv;
				} else
				{
					if (lastError != WSA_IO_PENDING)
					{
						debug_log(LOG_ERR, "net_recvSmtpResponse(): WSARecv failed with error: %d", lastError);
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_IO_ERROR;					
					}
				}
			}

wait_for_io: // Wait for I/O completion

			rc = WSAWaitForMultipleEvents(1, &recvOverlapped.hEvent, TRUE, timeout, TRUE);
			if (rc == WSA_WAIT_TIMEOUT)
			{
				debug_log(LOG_ERR, "net_recvSmtpResponse(): overlapped I/O timeout: %d", timeout);
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_TIMEOUT;
			}
			if (rc == WSA_WAIT_IO_COMPLETION) 
			{
				if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
				{
					closesocket(sock);
					WSACloseEvent(recvOverlapped.hEvent);
					return SOCK_WDOG_SHUTDOWN;
				}

				SleepEx(SLEEP_EX_INTERVAL, TRUE);
				goto wait_for_io;
			}

wait_for_ov: // Check the result of the I/O overlapped operation

			rc = WSAGetOverlappedResult(sock, &recvOverlapped, &recvBytes, FALSE, &flags);
			if (rc == FALSE) 
			{
				lastError = WSAGetLastError();
				if (lastError == WSA_IO_INCOMPLETE)
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_ov;
				}

				debug_log(LOG_ERR, "net_recvSmtpResponse(): overlapped I/O failed with error: %d", lastError);
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_IO_ERROR;
			}

			// ------------------------
			// Reset the signaled event
			// ------------------------
			rc = WSAResetEvent(recvOverlapped.hEvent);
			if (rc == FALSE) 
			{
				debug_log(LOG_ERR, "net_recvSmtpResponse(): WSAResetEvent failed with error = %d", WSAGetLastError());
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_IO_ERROR;
			}
		}

		// Check what we received...

		if (buf[index] == '\r')
		{
			index += recvBytes;

			recvBytes = 0;
			flags = 0;

			dataBuf.len = 1; 
			dataBuf.buf = &buf[index];

			// Receive another byte
wait_for_recv2:
			rc = WSARecv(sock, &dataBuf, 1, &recvBytes, &flags, &recvOverlapped, NULL);
			if (rc != 0)
			{
				if (rc == SOCKET_ERROR) 
				{
					lastError = WSAGetLastError();

					if (lastError == WSAEWOULDBLOCK)
					{
						if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
						{
							closesocket(sock);
							WSACloseEvent(recvOverlapped.hEvent);
							return SOCK_WDOG_SHUTDOWN;
						}

						SleepEx(SLEEP_EX_INTERVAL, TRUE);
						goto wait_for_recv2;
					} else
					{
						if (lastError != WSA_IO_PENDING)
						{
							debug_log(LOG_ERR, "net_recvSmtpResponse(): WSARecv failed with error: %d", lastError);
							closesocket(sock);
							WSACloseEvent(recvOverlapped.hEvent);
							return SOCK_IO_ERROR;					
						}
					}
				}
wait_for_io2: 
				rc = WSAWaitForMultipleEvents(1, &recvOverlapped.hEvent, TRUE, timeout, TRUE);
				if (rc == WSA_WAIT_TIMEOUT)
				{
					debug_log(LOG_ERR, "net_recvSmtpResponse(): overlapped I/O timeout: %d", timeout);
					closesocket(sock);
					WSACloseEvent(recvOverlapped.hEvent);
					return SOCK_TIMEOUT;
				}
				if (rc == WSA_WAIT_IO_COMPLETION) 
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_io2;
				}

wait_for_ov2:
				rc = WSAGetOverlappedResult(sock, &recvOverlapped, &recvBytes, FALSE, &flags);
				if (rc == FALSE) 
				{
					lastError = WSAGetLastError();
					if (lastError == WSA_IO_INCOMPLETE)
					{
						if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
						{
							closesocket(sock);
							WSACloseEvent(recvOverlapped.hEvent);
							return SOCK_WDOG_SHUTDOWN;
						}

						SleepEx(SLEEP_EX_INTERVAL, TRUE);
						goto wait_for_ov2;
					}

					debug_log(LOG_ERR, "net_recvSmtpResponse(): overlapped I/O failed with error: %d", lastError);
					closesocket(sock);
					WSACloseEvent(recvOverlapped.hEvent);
					return SOCK_IO_ERROR;
				}

				// ------------------------
				// Reset the signaled event
				// ------------------------
				rc = WSAResetEvent(recvOverlapped.hEvent);
				if (rc == FALSE) 
				{
					debug_log(LOG_ERR, "net_recvSmtpResponse(): WSAResetEvent failed with error = %d", WSAGetLastError());
					closesocket(sock);
					WSACloseEvent(recvOverlapped.hEvent);
					return SOCK_IO_ERROR;
				}
			}


			if ( buf[index] == '\n')
			{
				// we got to the end of line (CRLF found)
				index += recvBytes;

				if (buf[3] == '-')
				{
					net_recvSmtpResponse(sock, smtpCode, timeout); // receive another line in multiline replies
				} // endif 

				break;
			}
		} else
		{
			// Continue receiving the line until we get CRLF, we need to receive those bytes to cler the buffer.
			index += recvBytes;

			recvBytes = 0;
			flags = 0;

			dataBuf.len = 1; 
			dataBuf.buf = &buf[index];
		}

	} // while (index < bufSize) 

    buf[3] = 0; // get frist three bytes
    *smtpCode = atoi(buf);

	WSACloseEvent(recvOverlapped.hEvent);

	return SOCK_NO_ERROR;
} // end of "net_recvSmtpResponse()" 
Ejemplo n.º 3
0
int net_recvHttpLine(int sock, char * line, int maxLineLen, int timeout)
{
	WSAOVERLAPPED recvOverlapped;
	WSABUF dataBuf;

	DWORD recvBytes = 0;
	int index       = 0;
	DWORD flags     = 0;
	int rc          = 0;
	int lastError   = 0;

	time_t start = 0;
	time_t end   = 0;

	char * p = line;

	time(&start);

	// Make sure the RecvOverlapped struct is zeroed out
	SecureZeroMemory((PVOID) &recvOverlapped, sizeof (WSAOVERLAPPED));
	SecureZeroMemory((PVOID) &dataBuf, sizeof (WSABUF));

	// Create an event handle and setup an overlapped structure.
	recvOverlapped.hEvent = WSACreateEvent();
	if (recvOverlapped.hEvent == NULL) 
	{
		debug_log(LOG_ERR, "net_recvHttpLine(): WSACreateEvent failed: %d", WSAGetLastError());			
		closesocket(sock);
		return SOCK_IO_ERROR;
	}

	while (index < maxLineLen) 
	{		
		recvBytes = 0;
		flags = 0;

		dataBuf.len = 1; 
	    dataBuf.buf = p;

wait_for_recv:  // submit the request

		rc = WSARecv(sock, &dataBuf, 1, &recvBytes, &flags, &recvOverlapped, NULL);
		if (rc != 0)
		{
			if (rc == SOCKET_ERROR) 
			{
				lastError = WSAGetLastError();

				if (lastError == WSAEWOULDBLOCK)
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_recv;
				} else
				{
					if (lastError != WSA_IO_PENDING)
					{
						debug_log(LOG_ERR, "net_recvHttpLine(): WSARecv failed with error: %d", lastError);
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_IO_ERROR;					
					}
				}
			}

wait_for_io: // Wait for I/O completion

			rc = WSAWaitForMultipleEvents(1, &recvOverlapped.hEvent, TRUE, timeout, TRUE);
			if (rc == WSA_WAIT_TIMEOUT)
			{
				debug_log(LOG_ERR, "net_recvHttpLine(): overlapped I/O timeout: %d", timeout);
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_TIMEOUT;
			}
			if (rc == WSA_WAIT_IO_COMPLETION) 
			{
				if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
				{
					closesocket(sock);
					WSACloseEvent(recvOverlapped.hEvent);
					return SOCK_WDOG_SHUTDOWN;
				}

				SleepEx(SLEEP_EX_INTERVAL, TRUE);
				goto wait_for_io;
			}

wait_for_ov: // Check the result of the I/O overlapped operation

			rc = WSAGetOverlappedResult(sock, &recvOverlapped, &recvBytes, FALSE, &flags);
			if (rc == FALSE) 
			{
				lastError = WSAGetLastError();
				if (lastError == WSA_IO_INCOMPLETE)
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_ov;
				}

				debug_log(LOG_ERR, "net_recvHttpLine(): overlapped I/O failed with error: %d", lastError);
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_IO_ERROR;
			}

			// ------------------------
			// Reset the signaled event
			// ------------------------
			rc = WSAResetEvent(recvOverlapped.hEvent);
			if (rc == FALSE) 
			{
				debug_log(LOG_ERR, "net_recvHttpLine(): WSAResetEvent failed with error = %d", WSAGetLastError());
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_IO_ERROR;
			}
		}

		// Check what we received...

		if (*p == '\n')
		{
			p += recvBytes;
			index += recvBytes;
			break;
		} else
		{
			// Continue receiving the line until we get LF, we need to receive those bytes to cler the buffer.
			p += recvBytes;
			index += recvBytes;

			recvBytes = 0;
			flags = 0;

			dataBuf.len = 1; 
			dataBuf.buf = p;
		}

		time(&end);
		if (end-start > timeout/1000)
		{
			debug_log(LOG_SVR, "net_recvHttpLine(): timeout waiting for LF character...");
			closesocket(sock);
			WSACloseEvent(recvOverlapped.hEvent);
			return SOCK_IO_ERROR;
		}

	} // while (index < maxLineLen) 

	WSACloseEvent(recvOverlapped.hEvent);

	if (index < maxLineLen)
		return SOCK_NO_ERROR;

	return SOCK_PROTOCOL_ERROR;
} // end of "net_recvHttpLine()" 
Ejemplo n.º 4
0
static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_address, UINT16 port)
{
	int ai_flags = 0;
	int status;
	int sockfd;
	char addr[64];
	void* sin_addr;
	int option_value;
	struct addrinfo* ai;
	struct addrinfo* res;
	rdpListener* listener = (rdpListener*) instance->listener;
#ifdef _WIN32
	u_long arg;
#endif

	if (!bind_address)
		ai_flags = AI_PASSIVE;

	res = freerdp_tcp_resolve_host(bind_address, port, ai_flags);

	if (!res)
		return FALSE;

	for (ai = res; ai && (listener->num_sockfds < 5); ai = ai->ai_next)
	{
		if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6))
			continue;

		if (listener->num_sockfds == MAX_LISTENER_HANDLES)
		{
			WLog_ERR(TAG, "too many listening sockets");
			continue;
		}

		sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);

		if (sockfd == -1)
		{
			WLog_ERR(TAG, "socket");
			continue;
		}

		if (ai->ai_family == AF_INET)
			sin_addr = &(((struct sockaddr_in*) ai->ai_addr)->sin_addr);
		else
			sin_addr = &(((struct sockaddr_in6*) ai->ai_addr)->sin6_addr);

		inet_ntop(ai->ai_family, sin_addr, addr, sizeof(addr));
		option_value = 1;

		if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &option_value, sizeof(option_value)) == -1)
			WLog_ERR(TAG, "setsockopt");

#ifndef _WIN32
		fcntl(sockfd, F_SETFL, O_NONBLOCK);
#else
		arg = 1;
		ioctlsocket(sockfd, FIONBIO, &arg);
#endif
		status = _bind((SOCKET) sockfd, ai->ai_addr, ai->ai_addrlen);

		if (status != 0)
		{
			closesocket((SOCKET) sockfd);
			continue;
		}

		status = _listen((SOCKET) sockfd, 10);

		if (status != 0)
		{
			WLog_ERR(TAG, "listen");
			closesocket((SOCKET) sockfd);
			continue;
		}

		/* FIXME: these file descriptors do not work on Windows */
		listener->sockfds[listener->num_sockfds] = sockfd;
		listener->events[listener->num_sockfds] = WSACreateEvent();

		if (!listener->events[listener->num_sockfds])
		{
			listener->num_sockfds = 0;
			break;
		}

		WSAEventSelect(sockfd, listener->events[listener->num_sockfds], FD_READ | FD_ACCEPT | FD_CLOSE);
		listener->num_sockfds++;
		WLog_INFO(TAG, "Listening on %s:%d", addr, port);
	}

	freeaddrinfo(res);
	return (listener->num_sockfds > 0 ? TRUE : FALSE);
}
Ejemplo n.º 5
0
// Register the NetDescriptor with the NetManager.
int
NetManager_addDesc(NetDescriptor *nd) {
	long eventMask = 0;
	WSAEVENT event;

	if (numSockets >= WSA_MAXIMUM_WAIT_EVENTS) {
		errno = EMFILE;
		return -1;
	}

	if (nd->readCallback != NULL)
		eventMask |= FD_READ | FD_ACCEPT;

	if (nd->writeCallback != NULL)
		eventMask |= FD_WRITE /* | FD_CONNECT */;

	if (nd->exceptionCallback != NULL)
		eventMask |= FD_OOB;

	eventMask |= FD_CLOSE;

	event = WSACreateEvent();
	if (event == WSA_INVALID_EVENT) {
		errno = getWinsockErrno();
		return -1;
	}

	nd->smd = SocketManagementData_alloc();
	if (eventMask != 0) {
			// XXX: This guard is now always true, because of FD_CLOSE.
			//      This means that numActiveEvents will always be equal to
			//      numEvents.
			//      Once I'm convinced this is the right way to go,
			//      I can remove some unnecessary code.
		if (WSAEventSelect(nd->socket->sock, event, eventMask) ==
				SOCKET_ERROR) {
			int savedErrno = getWinsockErrno();
			int closeStatus = closeWSAEvent(event);
			if (closeStatus == -1) {
				log_add(log_Fatal, "closeWSAEvent() failed: %s.\n",
						strerror(errno));
				explode();
			}
			SocketManagementData_free(nd->smd);
			errno = savedErrno;
			return -1;
		}

		// Move existing socket for which there exists no event, so
		// so that all sockets for which there exists an event are at
		// the front of the array of netdescriptors.
		if (numActiveEvents < numSockets) {
			netDescriptors[numSockets] = netDescriptors[numActiveEvents];
			netDescriptors[numSockets]->smd->index = numSockets;
		}

		nd->smd->index = numActiveEvents;
		numActiveEvents++;
	} else {
		nd->smd->index = numSockets;
	}
	nd->smd->eventMask = eventMask;

	netDescriptors[nd->smd->index] = nd;
	events[nd->smd->index] = event;
	numSockets++;

	return 0;
}
Ejemplo n.º 6
0
/*
 * Wait for activity on one or more sockets.
 * While waiting, allow signals to run
 *
 * NOTE! Currently does not implement exceptfds check,
 * since it is not used in postgresql!
 */
int
pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval * timeout)
{
	WSAEVENT	events[FD_SETSIZE * 2]; /* worst case is readfds totally
										 * different from writefds, so
										 * 2*FD_SETSIZE sockets */
	SOCKET		sockets[FD_SETSIZE * 2];
	int			numevents = 0;
	int			i;
	int			r;
	DWORD		timeoutval = WSA_INFINITE;
	FD_SET		outreadfds;
	FD_SET		outwritefds;
	int			nummatches = 0;

	Assert(exceptfds == NULL);

	if (pgwin32_poll_signals())
		return -1;

	FD_ZERO(&outreadfds);
	FD_ZERO(&outwritefds);

	/*
	 * Write FDs are different in the way that it is only flagged by
	 * WSASelectEvent() if we have tried to write to them first. So try an
	 * empty write
	 */
	if (writefds)
	{
		for (i = 0; i < writefds->fd_count; i++)
		{
			char		c;
			WSABUF		buf;
			DWORD		sent;

			buf.buf = &c;
			buf.len = 0;

			r = WSASend(writefds->fd_array[i], &buf, 1, &sent, 0, NULL, NULL);
			if (r == 0)			/* Completed - means things are fine! */
				FD_SET		(writefds->fd_array[i], &outwritefds);

			else
			{					/* Not completed */
				if (WSAGetLastError() != WSAEWOULDBLOCK)

					/*
					 * Not completed, and not just "would block", so an error
					 * occured
					 */
					FD_SET		(writefds->fd_array[i], &outwritefds);
			}
		}
		if (outwritefds.fd_count > 0)
		{
			memcpy(writefds, &outwritefds, sizeof(fd_set));
			if (readfds)
				FD_ZERO(readfds);
			return outwritefds.fd_count;
		}
	}


	/* Now set up for an actual select */

	if (timeout != NULL)
	{
		/* timeoutval is in milliseconds */
		timeoutval = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
	}

	if (readfds != NULL)
	{
		for (i = 0; i < readfds->fd_count; i++)
		{
			events[numevents] = WSACreateEvent();
			sockets[numevents] = readfds->fd_array[i];
			numevents++;
		}
	}
	if (writefds != NULL)
	{
		for (i = 0; i < writefds->fd_count; i++)
		{
			if (!readfds ||
				!FD_ISSET(writefds->fd_array[i], readfds))
			{
				/* If the socket is not in the read list */
				events[numevents] = WSACreateEvent();
				sockets[numevents] = writefds->fd_array[i];
				numevents++;
			}
		}
	}

	for (i = 0; i < numevents; i++)
	{
		int			flags = 0;

		if (readfds && FD_ISSET(sockets[i], readfds))
			flags |= FD_READ | FD_ACCEPT | FD_CLOSE;

		if (writefds && FD_ISSET(sockets[i], writefds))
			flags |= FD_WRITE | FD_CLOSE;

		if (WSAEventSelect(sockets[i], events[i], flags) == SOCKET_ERROR)
		{
			TranslateSocketError();
			for (i = 0; i < numevents; i++)
				WSACloseEvent(events[i]);
			return -1;
		}
	}

	events[numevents] = pgwin32_signal_event;
	r = WaitForMultipleObjectsEx(numevents + 1, events, FALSE, timeoutval, TRUE);
	if (r != WAIT_TIMEOUT && r != WAIT_IO_COMPLETION && r != (WAIT_OBJECT_0 + numevents))
	{
		/*
		 * We scan all events, even those not signalled, in case more than one
		 * event has been tagged but Wait.. can only return one.
		 */
		WSANETWORKEVENTS resEvents;

		for (i = 0; i < numevents; i++)
		{
			ZeroMemory(&resEvents, sizeof(resEvents));
			if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) == SOCKET_ERROR)
				ereport(FATAL,
						(errmsg_internal("failed to enumerate network events: %i", (int) GetLastError())));
			/* Read activity? */
			if (readfds && FD_ISSET(sockets[i], readfds))
			{
				if ((resEvents.lNetworkEvents & FD_READ) ||
					(resEvents.lNetworkEvents & FD_ACCEPT) ||
					(resEvents.lNetworkEvents & FD_CLOSE))
				{
					FD_SET		(sockets[i], &outreadfds);

					nummatches++;
				}
			}
			/* Write activity? */
			if (writefds && FD_ISSET(sockets[i], writefds))
			{
				if ((resEvents.lNetworkEvents & FD_WRITE) ||
					(resEvents.lNetworkEvents & FD_CLOSE))
				{
					FD_SET		(sockets[i], &outwritefds);

					nummatches++;
				}
			}
		}
	}

	/* Clean up all handles */
	for (i = 0; i < numevents; i++)
	{
		WSAEventSelect(sockets[i], events[i], 0);
		WSACloseEvent(events[i]);
	}

	if (r == WSA_WAIT_TIMEOUT)
	{
		if (readfds)
			FD_ZERO(readfds);
		if (writefds)
			FD_ZERO(writefds);
		return 0;
	}

	if (r == WAIT_OBJECT_0 + numevents)
	{
		pgwin32_dispatch_queued_signals();
		errno = EINTR;
		if (readfds)
			FD_ZERO(readfds);
		if (writefds)
			FD_ZERO(writefds);
		return -1;
	}

	/* Overwrite socket sets with our resulting values */
	if (readfds)
		memcpy(readfds, &outreadfds, sizeof(fd_set));
	if (writefds)
		memcpy(writefds, &outwritefds, sizeof(fd_set));
	return nummatches;
}
Ejemplo n.º 7
0
inline int 
RecvIt(
	   SOCKET	sock,
	   PCHAR	buf, 
	   int		size
	   )
{
	int				iErrcode;
	int				len = size, iReceived;
	WSAOVERLAPPED	overlapped;
	WSABUF			buffer[1];
	DWORD			dwFlag;
	DWORD			dwRecvDataLen;
	WSAEVENT		hEvent;
	BOOL			bResult;

	// Overlapped event
	//
	hEvent = WSACreateEvent();
	
	//
	// Receive Reply Header.
	//
	memset(&overlapped, 0, sizeof(WSAOVERLAPPED));
	overlapped.hEvent = hEvent;
	
	iReceived = 0;

	while(iReceived < size) {
		if(size - iReceived >= 1024)
			buffer[0].len = 1024;
		else
			buffer[0].len = size - iReceived;

		buffer[0].buf = buf + iReceived;
		
		// Flag
		dwFlag = 0;
		
		iErrcode = WSARecv(
			sock,
			buffer,
			1, 
			&dwRecvDataLen,
			&dwFlag,
			&overlapped,
			NULL
			);
		
		if(iErrcode == SOCKET_ERROR) {
			DWORD dwError = WSAGetLastError();
			
			if(dwError == WSA_IO_PENDING) {
				DWORD	dwFlags;

				
				dwError = WSAWaitForMultipleEvents(
					1,
					&hEvent,
					TRUE,
					TIME_OUT,
					TRUE
					);				
				if(dwError != WSA_WAIT_EVENT_0) {
					
					PrintErrorCode(TEXT("[LanScsiCli]RecvIt: "), dwError);
					dwRecvDataLen = -1;
					
					TRACE("[LanScsiCli]RecvIt: Request %d, Received %d\n",
						size,
						iReceived
						);
					goto Out;
				}
				
				// Get Result...
				bResult = WSAGetOverlappedResult(
					sock,
					&overlapped,
					&dwRecvDataLen,
					TRUE,
					&dwFlags
					);
				if(bResult == FALSE) {
					PrintErrorCode(TEXT("[LanScsiCli]RecvIt: GetOverlappedResult Failed "), GetLastError());
					dwRecvDataLen = SOCKET_ERROR;
					goto Out;
				}
				
			} else {
				PrintErrorCode(TEXT("[LanScsiCli]RecvIt: WSARecv Failed "), dwError);
				
				dwRecvDataLen = -1;
				goto Out;
			}
		}

		iReceived += dwRecvDataLen;
		
		WSAResetEvent(hEvent);
	}

Out:
	WSACloseEvent(hEvent);
  
	return dwRecvDataLen;
}
Ejemplo n.º 8
0
/*
 * WinSock select() does not support standard file descriptors,
 * it can only check SOCKETs. The following function is an attempt
 * to re-create a select() function with support for other handle types.
 *
 * select() function with support for WINSOCK2 sockets and all
 * other handle types supported by WaitForMultipleObjectsEx().
 *
 * TODO: Differentiate between read/write/except for non-SOCKET handles.
 *
 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms687028.aspx
 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms741572.aspx
 */
static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
                     fd_set *exceptfds, struct timeval *timeout)
{
  long networkevents;
  DWORD milliseconds, wait, idx, mode, avail, events, inputs;
  WSAEVENT wsaevent, *wsaevents;
  WSANETWORKEVENTS wsanetevents;
  INPUT_RECORD *inputrecords;
  HANDLE handle, *handles;
  curl_socket_t sock, *fdarr, *wsasocks;
  int error, fds;
  DWORD nfd = 0, wsa = 0;
  int ret = 0;

  /* check if the input value is valid */
  if(nfds < 0) {
    errno = EINVAL;
    return -1;
  }

  /* check if we got descriptors, sleep in case we got none */
  if(!nfds) {
    Sleep((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000));
    return 0;
  }

  /* allocate internal array for the original input handles */
  fdarr = malloc(nfds * sizeof(curl_socket_t));
  if(fdarr == NULL) {
    errno = ENOMEM;
    return -1;
  }

  /* allocate internal array for the internal event handles */
  handles = malloc(nfds * sizeof(HANDLE));
  if(handles == NULL) {
    errno = ENOMEM;
    return -1;
  }

  /* allocate internal array for the internal socket handles */
  wsasocks = malloc(nfds * sizeof(curl_socket_t));
  if(wsasocks == NULL) {
    errno = ENOMEM;
    return -1;
  }

  /* allocate internal array for the internal WINSOCK2 events */
  wsaevents = malloc(nfds * sizeof(WSAEVENT));
  if(wsaevents == NULL) {
    errno = ENOMEM;
    return -1;
  }

  /* loop over the handles in the input descriptor sets */
  for(fds = 0; fds < nfds; fds++) {
    networkevents = 0;
    handles[nfd] = 0;

    if(FD_ISSET(fds, readfds))
      networkevents |= FD_READ|FD_ACCEPT|FD_CLOSE;

    if(FD_ISSET(fds, writefds))
      networkevents |= FD_WRITE|FD_CONNECT;

    if(FD_ISSET(fds, exceptfds))
      networkevents |= FD_OOB|FD_CLOSE;

    /* only wait for events for which we actually care */
    if(networkevents) {
      fdarr[nfd] = curlx_sitosk(fds);
      if(fds == fileno(stdin)) {
        handles[nfd] = GetStdHandle(STD_INPUT_HANDLE);
      }
      else if(fds == fileno(stdout)) {
        handles[nfd] = GetStdHandle(STD_OUTPUT_HANDLE);
      }
      else if(fds == fileno(stderr)) {
        handles[nfd] = GetStdHandle(STD_ERROR_HANDLE);
      }
      else {
        wsaevent = WSACreateEvent();
        if(wsaevent != WSA_INVALID_EVENT) {
          error = WSAEventSelect(fds, wsaevent, networkevents);
          if(error != SOCKET_ERROR) {
            handles[nfd] = wsaevent;
            wsasocks[wsa] = curlx_sitosk(fds);
            wsaevents[wsa] = wsaevent;
            wsa++;
          }
          else {
            handles[nfd] = (HANDLE) curlx_sitosk(fds);
            WSACloseEvent(wsaevent);
          }
        }
      }
      nfd++;
    }
  }

  /* convert struct timeval to milliseconds */
  if(timeout) {
    milliseconds = ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000));
  }
  else {
    milliseconds = INFINITE;
  }

  /* wait for one of the internal handles to trigger */
  wait = WaitForMultipleObjectsEx(nfd, handles, FALSE, milliseconds, FALSE);

  /* loop over the internal handles returned in the descriptors */
  for(idx = 0; idx < nfd; idx++) {
    handle = handles[idx];
    sock = fdarr[idx];
    fds = curlx_sktosi(sock);

    /* check if the current internal handle was triggered */
    if(wait != WAIT_FAILED && (wait - WAIT_OBJECT_0) <= idx &&
       WaitForSingleObjectEx(handle, 0, FALSE) == WAIT_OBJECT_0) {
      /* try to handle the event with STD* handle functions */
      if(fds == fileno(stdin)) {
        /* check if there is no data in the input buffer */
        if(!stdin->_cnt) {
          /* check if we are getting data from a PIPE */
          if(!GetConsoleMode(handle, &mode)) {
            /* check if there is no data from PIPE input */
            if(!PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL))
              avail = 0;
            if(!avail) {
              FD_CLR(sock, readfds);
              /* reduce CPU load */
              Sleep(10);
            }
          } /* check if there is no data from keyboard input */
          else if (!_kbhit()) {
            /* check if there are INPUT_RECORDs in the input buffer */
            if(GetNumberOfConsoleInputEvents(handle, &events)) {
              if(events > 0) {
                /* remove INPUT_RECORDs from the input buffer */
                inputrecords = (INPUT_RECORD*)malloc(events *
                                                     sizeof(INPUT_RECORD));
                if(inputrecords) {
                  if(!ReadConsoleInput(handle, inputrecords,
                                       events, &inputs))
                    inputs = 0;
                  free(inputrecords);
                }

                /* check if we got all inputs, otherwise clear buffer */
                if(events != inputs)
                  FlushConsoleInputBuffer(handle);
              }
            }

            /* remove from descriptor set since there is no real data */
            FD_CLR(sock, readfds);
          }
        }

        /* stdin is never ready for write or exceptional */
        FD_CLR(sock, writefds);
        FD_CLR(sock, exceptfds);
      }
      else if(fds == fileno(stdout) || fds == fileno(stderr)) {
        /* stdout and stderr are never ready for read or exceptional */
        FD_CLR(sock, readfds);
        FD_CLR(sock, exceptfds);
      }
      else {
        /* try to handle the event with the WINSOCK2 functions */
        error = WSAEnumNetworkEvents(fds, handle, &wsanetevents);
        if(error != SOCKET_ERROR) {
          /* remove from descriptor set if not ready for read/accept/close */
          if(!(wsanetevents.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE)))
            FD_CLR(sock, readfds);

          /* remove from descriptor set if not ready for write/connect */
          if(!(wsanetevents.lNetworkEvents & (FD_WRITE|FD_CONNECT)))
            FD_CLR(sock, writefds);

          /* HACK:
           * use exceptfds together with readfds to signal
           * that the connection was closed by the client.
           *
           * Reason: FD_CLOSE is only signaled once, sometimes
           * at the same time as FD_READ with data being available.
           * This means that recv/sread is not reliable to detect
           * that the connection is closed.
           */
          /* remove from descriptor set if not exceptional */
          if(!(wsanetevents.lNetworkEvents & (FD_OOB|FD_CLOSE)))
            FD_CLR(sock, exceptfds);
        }
      }

      /* check if the event has not been filtered using specific tests */
      if(FD_ISSET(sock, readfds) || FD_ISSET(sock, writefds) ||
         FD_ISSET(sock, exceptfds)) {
        ret++;
      }
    }
    else {
      /* remove from all descriptor sets since this handle did not trigger */
      FD_CLR(sock, readfds);
      FD_CLR(sock, writefds);
      FD_CLR(sock, exceptfds);
    }
  }

  for(idx = 0; idx < wsa; idx++) {
    WSAEventSelect(wsasocks[idx], NULL, 0);
    WSACloseEvent(wsaevents[idx]);
  }

  free(wsaevents);
  free(wsasocks);
  free(handles);
  free(fdarr);

  return ret;
}
Ejemplo n.º 9
0
/* Main 'loop' */
void axel_do(axel_t *axel)
{
#if WIN32
	WSAEVENT hEventObject = WSACreateEvent();
	DWORD byte;
#else
	fd_set fds[1];
	struct timeval timeval[1];
	int hifd;
#endif
	int i;
	long long int remaining, size;

	/* Create statefile if necessary */
	if (axel->next_state < gettime())
	{
		save_state(axel);
		axel->next_state = gettime() + axel->conf->save_state_interval;
	}

	/* Wait for data on (one of) the connections */
#if !WIN32
	FD_ZERO(fds);
	hifd = 0;
	for (i = 0; i < axel->conf->num_connections; i++)
	{
		if (axel->conn[i].enabled) 
		{
			FD_SET(axel->conn[i].fd, fds);
		}
		hifd = max(hifd, axel->conn[i].fd);
	}

	if (0 == hifd)
	{
#ifdef DEBUG
		printf("DEBUG no connection yet. Wait...\n");
#endif
		/* No connections yet. Wait... */
		usleep(100000);
		goto conn_check;
	}
	else
	{
		timeval->tv_sec = 0;
		timeval->tv_usec = 100000;
		/* A select() error probably means it was interrupted
		   by a signal, or that something else's very wrong...	*/
		if (-1 == select(hifd + 1, fds, NULL, NULL, timeval))
		{
			axel->ready = -1;
			return;
		}
	}
#endif

	/* Handle connections which need attention */
	for (i = 0; i < axel->conf->num_connections; i++) 
	{
		if (axel->conn[i].enabled) 
		{
#if WIN32
			if (is_readable(axel, axel->conn[i].fd, hEventObject))
#else
			if (FD_ISSET(axel->conn[i].fd, fds))
#endif
			{
				axel->conn[i].last_transfer = gettime();
#if WIN32
				memset(buffer, 0, max(MAX_STRING, axel->conf->buffer_size));
				size = recv(axel->conn[i].fd, buffer, axel->conf->buffer_size, 0);
#else
				size = read(axel->conn[i].fd, buffer, axel->conf->buffer_size);
#endif
#if WIN32
				if (SOCKET_ERROR == size)
#else
				if (-1 == size)
#endif
				{
#if !WIN32
					if (axel->conf->verbose)
					{
						axel_message( axel, _("Error on connection %i! "
							"Connection closed"), i );
					}
#endif
					axel->conn[i].enabled = 0;
					conn_disconnect(&axel->conn[i]);
					continue;
				}
				else if (0 == size)
				{
					if (axel->conf->verbose)
					{
						/* Only abnormal behaviour if: */
						if (axel->conn[i].currentbyte < axel->conn[i].lastbyte && axel->size != INT_MAX)
						{
							axel_message(axel, _("Connection %i unexpectedly closed"), i);
						}
						else
						{
							axel_message(axel, _("Connection %i finished"), i);
						}
					}
					if (!axel->conn[0].supported)
					{
						axel->ready = 1;
					}
					axel->conn[i].enabled = 0;
					conn_disconnect(&axel->conn[i]);
					continue;
				}
				/* remaining == Bytes to go */
				remaining = axel->conn[i].lastbyte - axel->conn[i].currentbyte + 1;
				if (remaining < size)
				{
					if (axel->conf->verbose)
					{
						axel_message(axel, _("Connection %i finished"), i);
					}
					axel->conn[i].enabled = 0;
					conn_disconnect(&axel->conn[i]);
					size = remaining;
					/* Don't terminate, still stuff to write!	*/
				}
				/* This should always succeed..				*/
#if WIN32
				SetFilePointer(axel->outfd, axel->conn[i].currentbyte, NULL, FILE_BEGIN);
				if (0 == WriteFile(axel->outfd, buffer, size, &byte, NULL))
#else
				lseek(axel->outfd, axel->conn[i].currentbyte, SEEK_SET);
				if (write(axel->outfd, buffer, size) != size)
#endif
				{
					axel_message(axel, _("Write error!"));
					axel->ready = -1;
					return;
				}
				axel->conn[i].currentbyte += size;
				axel->bytes_done += size;
			}
			else
			{
				if (gettime() > axel->conn[i].last_transfer + axel->conf->connection_timeout)
				{
					if (axel->conf->verbose) 
					{
						axel_message(axel, _("Connection %i timed out"), i);
					}
					conn_disconnect(&axel->conn[i]);
					axel->conn[i].enabled = 0;
				}
			}
		}
	}
	if (axel->ready) 
	{
		return;
	}
	
conn_check:
	/* Look for aborted connections and attempt to restart them. */
	for (i = 0; i < axel->conf->num_connections; i++)
	{
		if (!axel->conn[i].enabled 
            && axel->conn[i].currentbyte < axel->conn[i].lastbyte)
		{
			if (0 == axel->conn[i].state)
			{	
				// Wait for termination of this thread
#if WIN32
				WaitForSingleObject(axel->conn[i].setup_thread, INFINITE);
				CloseHandle(axel->conn[i].setup_thread);
#else
				pthread_join(*(axel->conn[i].setup_thread), NULL);
#endif	
				conn_set(&axel->conn[i], axel->url->text);
				axel->url = axel->url->next;
				if (axel->conf->verbose >= 2) 
				{
					axel_message(axel, _("Connection %i downloading from %s:%i using interface %s"), 
						i, axel->conn[i].host, axel->conn[i].port, axel->conn[i].local_if);
				}
				
				axel->conn[i].state = 1;
#if WIN32
				axel->conn[i].setup_thread = CreateThread(NULL, 0, setup_thread_cb, &axel->conn[i], 0, NULL);
				if (NULL != axel->conn[i].setup_thread) 
#else
				if (pthread_create(axel->conn[i].setup_thread, NULL, setup_thread_cb, &axel->conn[i]) == 0)
#endif
				{
					axel->conn[i].last_transfer = gettime();
				}
				else
				{
					axel_message(axel, _("thread error in axel_do!!!"));
					axel->ready = -1;
				}
			}
			else
			{
				if (gettime() > axel->conn[i].last_transfer + axel->conf->reconnect_delay)
				{
#if WIN32
					TerminateThread(axel->conn[i].setup_thread, 0);
                    CloseHandle(axel->conn[i].setup_thread);
#else
					pthread_cancel(*axel->conn[i].setup_thread);
#endif
					axel->conn[i].state = 0;
				}
			}
		}
	}

	/* Calculate current average speed and finish_time		*/
	axel->bytes_per_second = (int)((double)(axel->bytes_done - axel->start_byte) / (gettime() - axel->start_time));
	axel->finish_time = (int)(axel->start_time + (double)(axel->size - axel->start_byte) / axel->bytes_per_second);

	/* Check speed. If too high, delay for some time to slow things
	   down a bit. I think a 5% deviation should be acceptable.	*/
	if (0 < axel->conf->max_speed)
	{
		if (1.05 < (float) axel->bytes_per_second / axel->conf->max_speed) 
		{
			axel->delay_time += 10000;
		}
		else if (((float)axel->bytes_per_second / axel->conf->max_speed < 0.95) 
            && 10000 <= (axel->delay_time)) 
		{
			axel->delay_time -= 10000;
		}
		else if (((float)axel->bytes_per_second / axel->conf->max_speed < 0.95)) 
		{
			axel->delay_time = 0;
		}
		usleep(axel->delay_time);
	}
	
	/* Ready? */
	if (axel->bytes_done == axel->size) 
	{
		axel->ready = 1;
	}
}
Ejemplo n.º 10
0
void Event::Create(EventWaitType type_)
{
	type = type_;
	wsaEvent = WSACreateEvent();
}
Ejemplo n.º 11
0
DWORD DarunGrim::IDACommandProcessor()
{
	SOCKET SocketArray[WSA_MAXIMUM_WAIT_EVENTS];
	WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
	WSANETWORKEVENTS NetworkEvents;
	DWORD EventTotal = 0, index;

	SocketArray[0] = pSourceController->GetSocket();
	SocketArray[1] = pTargetController->GetSocket();
	for (int i = 0; i<2; i++)
	{
		WSAEVENT NewEvent = WSACreateEvent();
		WSAEventSelect(SocketArray[i], NewEvent, FD_READ | FD_CLOSE);
		EventArray[EventTotal] = NewEvent;
		EventTotal++;
	}
	while (1)
	{
		index = WSAWaitForMultipleEvents(EventTotal,
			EventArray,
			FALSE,
			WSA_INFINITE,
			FALSE);

		if (index<0)
			break;

		index = index - WSA_WAIT_EVENT_0;
		//-------------------------
		// Iterate through all events and enumerate
		// if the wait does not fail.
		for (DWORD i = index; i<EventTotal; i++)
		{
			if (SocketArray[i] == WSA_INVALID_HANDLE)
				continue;

			index = WSAWaitForMultipleEvents(1,
				&EventArray[i],
				TRUE,
				1000,
				FALSE);
			if ((index != WSA_WAIT_FAILED) && (index != WSA_WAIT_TIMEOUT))
			{
				if (WSAEnumNetworkEvents(SocketArray[i], EventArray[i], &NetworkEvents) == 0)
				{
					Logger.Log(10, "Signal( %d - %d )\n", i, NetworkEvents.lNetworkEvents);
					if (NetworkEvents.lNetworkEvents == FD_READ)
					{
						char buffer[DATA_BUFSIZE] = { 0, };
						WSABUF DataBuf;
						DataBuf.len = DATA_BUFSIZE;
						DataBuf.buf = buffer;
						/*
						DWORD RecvBytes;
						DWORD Flags=0;
						if ( WSARecv( SocketArray[i], &DataBuf, 1, &RecvBytes, &Flags, NULL, NULL )==SOCKET_ERROR )
						{
						Logger.Log( 10, "Error occurred at WSARecv()\n" );
						}else
						{
						Logger.Log( 10, "Read %d bytes\n", RecvBytes );
						}*/
						char type;
						DWORD length;
						PBYTE data = RecvTLVData(SocketArray[i], &type, &length);
						if (data)
						{
							Logger.Log(10, "%s: Type: %d Length: %d data:%x\n", __FUNCTION__, type, length, data);
							if (type == SHOW_MATCH_ADDR && length >= 4)
							{
								DWORD address = *(DWORD *)data;
								Logger.Log(10, "%s: Showing address=%x\n", __FUNCTION__, address);
								//Get Matching Address

								DWORD MatchingAddress = 0;
								if (pDiffMachine)
								{
									MatchingAddress = pDiffMachine->GetMatchAddr(i, address);
								}
								if (MatchingAddress != 0)
								{
									//Show using JUMP_TO_ADDR
									if (i == 0)
									{
										pTargetController->ShowAddress(MatchingAddress);
									}
									else
									{
										pSourceController->ShowAddress(MatchingAddress);
									}
								}
							}
						}
					}
					else if (NetworkEvents.lNetworkEvents == FD_CLOSE)
					{
						closesocket(SocketArray[i]);
						WSACloseEvent(EventArray[i]);
						memcpy(SocketArray + i, SocketArray + i + 1, EventTotal - i + 1);
						memcpy(EventArray + i, EventArray + i + 1, EventTotal - i + 1);
						EventTotal--;
						break;
					}
				}
			}
		}
	}
	return 1;
}
int main(int argc, char* argv[])
{
	//----------------------
	// Initialize Winsock.
	WSADATA wsaData;
	int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != NO_ERROR) {
		wprintf(L"WSAStartup failed with error: %ld\n", iResult);
		return 1;
	}
	//----------------------
	// Create a SOCKET for listening for
	// incoming connection requests.
	SOCKET ListenSocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (ListenSocket == INVALID_SOCKET) {
		wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
		WSACleanup();
		return 1;
	}
	//----------------------
	// The sockaddr_in structure specifies the address family,
	// IP address, and port for the socket that is being bound.
	sockaddr_in addrServer;
	addrServer.sin_family = AF_INET;
	addrServer.sin_addr.s_addr = htonl(INADDR_ANY); //实际上是0
	addrServer.sin_port = htons(20131);


	//绑定套接字到一个IP地址和一个端口上
	if (bind(ListenSocket,(SOCKADDR *) & addrServer, sizeof (addrServer)) == SOCKET_ERROR) {
		wprintf(L"bind failed with error: %ld\n", WSAGetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}

	//将套接字设置为监听模式等待连接请求
	//----------------------
	// Listen for incoming connection requests.
	// on the created socket
	if (listen(ListenSocket, 5) == SOCKET_ERROR) {
		wprintf(L"listen failed with error: %ld\n", WSAGetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}


	DWORD dwThread;
	HANDLE hThread = CreateThread(NULL,0,ThreadProc,NULL,0,&dwThread);
	if(hThread==NULL)
	{
		wprintf(L"Thread Creat Failed!\n");
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}
	CloseHandle(hThread);


	SOCKADDR_IN addrClient;
	int len=sizeof(SOCKADDR);
	//以一个无限循环的方式,不停地接收客户端socket连接
	while(1)
	{
		//请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字
		SOCKET AcceptSocket=accept(ListenSocket,(SOCKADDR*)&addrClient,&len);
		if(AcceptSocket  == INVALID_SOCKET)break; //出错

		g_CliSocketArr[g_iTotalConn] = AcceptSocket;

		g_CliEventArr[g_iTotalConn] =  WSACreateEvent();

		// Launch an asynchronous operation
		WSAEventSelect(g_CliSocketArr[g_iTotalConn],
			g_CliEventArr[g_iTotalConn],
			FD_READ | FD_CLOSE);
		g_iTotalConn++;

	}

	closesocket(ListenSocket);
	WSACleanup();
	return 0;
}
Ejemplo n.º 13
0
DWORD WINAPI 
PnpModuleThreadProc(
					LPVOID lpParameter   // thread data
					)
{
	int						iResult;
	CPnpModule				*pRC;
	WSAOVERLAPPED			overlapped;
	WSABUF					buffer[1];
	DWORD					dwFlag;
	DWORD					dwRecvDataLen;
	SOCKADDR_LPX			PeerAddr;
	INT						iFromLen;
	BOOL					bFinish;
	HANDLE					hEvents[2];
	PNP_MESSAGE				message;

	DebugPrint(2, (TEXT("[NetdiskTest]PnpModuleThread: PnpModule Thread Started.\n")));

	pRC = (CPnpModule *) lpParameter;

	// Server Stop Event.
	hEvents[0] = hServerStopEvent;

	// Overlapped event
	//
	hEvents[1] = WSACreateEvent();
	memset(&overlapped, 0, sizeof(WSAOVERLAPPED));
	overlapped.hEvent = hEvents[1];

	buffer[0].len = sizeof(message);
	buffer[0].buf = (PCHAR)&message;
	 
	
	bFinish = FALSE;

	do {
		DWORD	dwResult;

		// Flag
		dwFlag = 0;
	
		WSAResetEvent(hEvents[1]);

		iFromLen = sizeof(PeerAddr);

		iResult = WSARecvFrom(
			pRC->ListenSocket,
			buffer,
			1,
			&dwRecvDataLen,
			&dwFlag,
			(struct sockaddr *)&PeerAddr,
			&iFromLen,
			&overlapped,
			NULL
			);
		if(iResult != SOCKET_ERROR) {
			DebugPrint(4, ("[NetDiskTest]PnpModuleThreadProc: no Error when Recv.\n"));
			continue;
		}

		if((iResult = WSAGetLastError()) != WSA_IO_PENDING) {
			DebugPrint(1, ("[NetDiskTest]PnpModuleThreadProc: Error when Recv. %d\n", iResult));

			bFinish = TRUE;

			continue;
		}

		// Wait
		dwResult = WaitForMultipleObjects(
			2,
			hEvents,
			FALSE,
			3000 //INFINITE
			);
		switch(dwResult) {
		case WAIT_TIMEOUT:
			TRACE("\nWAIT_TIMEOUT\n");
			SetEvent(hUpdateEvent);
			break;
		case WAIT_OBJECT_0:
			{
				TRACE("\nWAIT_OBJECT_0\n");
				bFinish = TRUE;
				DebugPrint(1, ("[NetDiskTest]PnpModuleThreadProc: Recv Stop Event.\n"));
			}
			break;
		case WAIT_OBJECT_0 + 1:
			{
				TRACE("\nWAIT_OBJECT_0+1\n");
				BOOL		bResult;

				bResult = WSAGetOverlappedResult(
					pRC->ListenSocket,
					&overlapped,
					&dwRecvDataLen,
					TRUE,
					&dwFlag
					);

				// Check Size.
				if(dwRecvDataLen != sizeof(message)) {
					DebugPrint(1, ("[NetDiskTest]PnpModuleThreadProc: Recv Packet size = %d. Ignore...\n", dwRecvDataLen));
					break;
				}

				// Is Valid?
				if (message.ucType != 0 || 
					(
						message.ucVersion != 0 &&
						message.ucVersion != 1 &&
						message.ucVersion != 2
					)
				)
				{
					DebugPrint(1, ("[NetDiskTest]PnpModuleThreadProc: Bad Packet 0x%x. 0x%x. Ignore...\n", message.ucType, message.ucVersion));
					break;
				}
				
			}
//			DebugPrint(4, ("[NetDiskTest]PnpModuleThreadProc: %.2X%.2X%.2X\n",
//				PeerAddr.LpxAddress.Node[0], PeerAddr.LpxAddress.Node[1], PeerAddr.LpxAddress.Node[2]));
			memcpy((void *) ucCurrentNetdisk, (void *) PeerAddr.LpxAddress.Node, 6);
			ucVersion = message.ucVersion;
			bNewNetdiskArrived = TRUE;
			SetEvent(hUpdateEvent);
			break;

		default:
			break;
		}

	} while(bFinish != TRUE);

	CloseHandle(hEvents[1]);

	ExitThread(0);

	return 0;
}
Ejemplo n.º 14
0
bool CIOCPServer::Initialize(NOTIFYPROC pNotifyProc, CMainFrame* pFrame, int nMaxConnections, int nPort)
{
	m_pNotifyProc     = pNotifyProc;
	m_pFrame		  =  pFrame;
	m_nMaxConnections = nMaxConnections;

	m_socketListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
	if (INVALID_SOCKET == m_socketListen)
	{
		TRACE(_T("Could not create listen socket %ld\n"),WSAGetLastError());
		return false;
	}

	// Event for handling Network IO
	m_hEvent = WSACreateEvent();

	if (WSA_INVALID_EVENT == m_hEvent)
	{
		TRACE(_T("WSACreateEvent() error %ld\n"),WSAGetLastError());
		closesocket(m_socketListen);
		return false;
	}

	// The listener is ONLY interested in FD_ACCEPT
	// That is when a client connects to or IP/Port
	// Request async notification
	int nRet = WSAEventSelect(m_socketListen,
						  m_hEvent,
						  FD_ACCEPT);

	if (SOCKET_ERROR == nRet)
	{
		TRACE(_T("WSAAsyncSelect() error %ld\n"),WSAGetLastError());
		closesocket(m_socketListen);
		return false;
	}

	SOCKADDR_IN	saServer;		
	// Listen on our designated Port#
	saServer.sin_port = htons(nPort);
	// Fill in the rest of the address structure
	saServer.sin_family = AF_INET;
	saServer.sin_addr.s_addr = INADDR_ANY;

	// bind our name to the socket
	nRet = bind(m_socketListen,
				(LPSOCKADDR)&saServer, 
				sizeof(struct sockaddr));
	if (SOCKET_ERROR == nRet)
	{
		TRACE(_T("bind() error %ld\n"),WSAGetLastError());
		closesocket(m_socketListen);
		return false;
	}

	// Set the socket to listen
	nRet = listen(m_socketListen, SOMAXCONN);
	if (nRet == SOCKET_ERROR)
	{
		TRACE(_T("listen() error %ld\n"),WSAGetLastError());
		closesocket(m_socketListen);
		return false;
	}

	UINT	dwThreadId = 0;
	m_hThread = (HANDLE)_beginthreadex(NULL,				// Security
									 0,					// Stack size - use default
									 ListenThreadProc,  // Thread fn entry point
									 (void*) this,	    
									 0,					// Init flag
									 &dwThreadId);	// Thread address

	if (m_hThread != INVALID_HANDLE_VALUE)
	{
		InitializeIOCP();
		m_bInit = true;
		return true;
	}

	return false;
}
Ejemplo n.º 15
0
/*
 * This function uses to WaitForMultipleObjects to wait for both
 * stdin and socket reading or writing.
 * Stdin is treated special in WIN32.  Waiting for stdin is done
 * via a bounce_full event which is set in the stdin thread.
 * Execute command file reading is done via handle.
 * WaitForMultipleObjects will only respond with one object,
 * so an additonal select is also done to determine
 * which individual events are active.
 */
static int
w32_select(int nfds, fd_set *rdfd, fd_set *wrfd, fd_set *errfd,
	   struct timeval *time)
{
    HANDLE handles[3];
    SOCKET sock;
    int inp, sockfd, result, s_result, num_handles;
    struct timeval tv_time = {0, 0};
    fd_set rdsock, wrsock;

    switch (rdfd->fd_count) {
    case 1:
	inp = -1;
	sockfd = rdfd->fd_array[0];
	break;
    case 2:
	inp = rdfd->fd_array[0];
	sockfd = rdfd->fd_array[1];
	break;
    default:
	assert(0);
    }
    sock = w32_fd2socket(sockfd);

    assert(wrfd->fd_count == 0
	   || (wrfd->fd_count == 1 && wrfd->fd_array[0] == (SOCKET)sockfd));
    assert(inp < 0 || inp == input_fd);

    num_handles = 0;
    handles[num_handles++] = ctrl_c_event;
    if (inp >= 0)
	handles[num_handles++]
	    = inp ? (HANDLE)_get_osfhandle(inp) : bounce_full;
    /* always wait on the socket */
    handles[num_handles++] = WSACreateEvent();

    if (wrfd->fd_count > 0)
	WSAEventSelect(sock, handles[num_handles - 1],
		       FD_READ | FD_WRITE | FD_CLOSE);
    else
	WSAEventSelect(sock, handles[num_handles - 1],
		       FD_READ | FD_CLOSE);

    result = WaitForMultipleObjects(num_handles, handles, 0, INFINITE);
    if (result < 0) {
	errno = GetLastError();
	WSACloseEvent(handles[num_handles - 1]);
	return -1;
    }
    WSACloseEvent(handles[num_handles - 1]);

    if (result == WAIT_OBJECT_0) {
	errno = EINTR;
	return -1;
    }

    FD_ZERO(&rdsock);
    FD_ZERO(&wrsock);
    FD_SET(sock, &rdsock);
    if (wrfd->fd_count)
	FD_SET(sock, &wrsock);
    s_result = select(sock + 1, &rdsock, &wrsock, NULL, &tv_time);

    if (s_result < 0) {
	w32_set_winsock_errno();
	return s_result;
    }

    if (!FD_ISSET(sock, &rdsock))
	FD_CLR((SOCKET)sockfd, rdfd);
    if (!FD_ISSET(sock, &wrsock))
	FD_CLR((SOCKET)sockfd, wrfd);
    if (inp >= 0 && result == WAIT_OBJECT_0 + 1)
	s_result++;
    else
	FD_CLR((SOCKET)inp, rdfd);

    return s_result;
}
Ejemplo n.º 16
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);
}
Ejemplo n.º 17
0
WEventSocket::WEventSocket()
{
	m_hEvent=WSACreateEvent();
}
Ejemplo n.º 18
0
DWORD Q3_ConnectToMasterServer(GAME_INFO *pGI, int iMasterIdx)
{
	size_t packetlen=0;
	char sendbuf[80];
	ZeroMemory(sendbuf,sizeof(sendbuf));
	SOCKET ConnectSocket;

//	UINT_PTR timerProgressWait = SetTimer(g_hWnd,IDT_TIMER_1SECOND,100,NULL);
	
	int i = 0;
	unsigned char *packet[MAX_PACKETS];
	size_t packet_len[MAX_PACKETS];

	for(i=0; i<MAX_PACKETS;i++)
		packet[i] = NULL;

	i = 0;

	char szIP[260];
	strcpy(szIP,pGI->szMasterServerIP[iMasterIdx]);
	
	SplitIPandPORT(szIP,pGI->dwMasterServerPORT);

	int len = 0;//(int)strlen(sendbuf);
	string query;
	query = pGI->szMasterQueryString;
	ReplaceStrInStr(query,"%PROTOCOL%",pGI->szGameProtocol[iMasterIdx]);
	len = UTILZ_ConvertEscapeCodes((TCHAR*)query.c_str(),sendbuf,sizeof(sendbuf));

	ConnectSocket = getsockudp(szIP,(unsigned short)pGI->dwMasterServerPORT); // etmaster.idsoftware.com"27950 master server
	if(INVALID_SOCKET==ConnectSocket)
	{

		KillTimer(g_hWnd,IDT_1SECOND);
		g_log.AddLogInfo(GS_LOG_ERROR,"Error connecting to server %s:%d!",szIP,pGI->dwMasterServerPORT);
		return 1;
	}

	WSAEVENT hEvent;
	hEvent = WSACreateEvent();
	if (hEvent == WSA_INVALID_EVENT)
	{
		KillTimer(g_hWnd,IDT_1SECOND);
		g_log.AddLogInfo(GS_LOG_ERROR,"WSACreateEvent() = WSA_INVALID_EVENT");
		closesocket(ConnectSocket);
		return 1;
	}

	//
	// Make the socket non-blocking and 
	// associate it with network events
	//
	int nRet;
	nRet = WSAEventSelect(ConnectSocket, hEvent,FD_READ|FD_CONNECT|FD_CLOSE);
	if (nRet == SOCKET_ERROR)
	{
		KillTimer(g_hWnd,IDT_1SECOND);
		g_log.AddLogInfo(GS_LOG_ERROR,"EventSelect() = SOCKET_ERROR");
		closesocket(ConnectSocket);
		WSACloseEvent(hEvent);
		return 5;
	}



	//
	// Handle async network events
	//

	WSANETWORKEVENTS events;
	while(1)
	{
		//
		// Wait for something to happen
		//
		//dbg_print("\nWaitForMultipleEvents()");
		DWORD dwRet;
		dwRet = WSAWaitForMultipleEvents(1, &hEvent, FALSE,4000,FALSE);
		if (dwRet == WSA_WAIT_TIMEOUT)
		{
			g_log.AddLogInfo(GS_LOG_ERROR,"WSAWaitForMultipleEvents = WSA_WAIT_TIMEOUT");
			break;
		}

		//
		// Figure out what happened
		//
		//g_log.AddLogInfo(0,"\nWSAEnumNetworkEvents()");
		nRet = WSAEnumNetworkEvents(ConnectSocket, hEvent, &events);
		if (nRet == SOCKET_ERROR)
		{
			g_log.AddLogInfo(GS_LOG_ERROR,"WSAEnumNetworkEvents() = SOCKET_ERROR");
			break;
		}

		//				 //
		// Handle events //
		//				 //

		// Connect event?
		if (events.lNetworkEvents & FD_CONNECT)
		{
			//g_log.AddLogInfo(0,"\nFD_CONNECT: %d", events.iErrorCode[FD_CONNECT_BIT]);
			g_log.AddLogInfo(0,"Master server %s",pGI->szMasterServerIP[0]);
			g_log.AddLogInfo(0,"Sending packet string: [%s]  Length: %d",sendbuf,len);
			g_log.AddLogInfo(0,"xml config: %s ",pGI->szMasterQueryString);

			if(send(ConnectSocket, sendbuf, len , 0)==SOCKET_ERROR) 
			{
				KillTimer(g_hWnd,IDT_1SECOND);
				WSACloseEvent(hEvent);
				closesocket(ConnectSocket);		
				g_log.AddLogInfo(GS_LOG_ERROR,"Error sending master query packet!");
				return 2;
			}
		}

		// Read event?
		if (events.lNetworkEvents & FD_READ)
		{
			//g_log.AddLogInfo(0,"\nFD_READ: %d, %d",events.iErrorCode[FD_READ_BIT],i);
			// Read the data and write it to stdout
			packet[i]=(unsigned char*)ReadPacket(ConnectSocket, &packetlen);
			packet_len[i] = packetlen;
			i++;

			if(i>=MAX_PACKETS)
				break;
	
		}

		// Close event?
		if (events.lNetworkEvents & FD_CLOSE)
		{
			g_log.AddLogInfo(0,"\nFD_CLOSE: %d",events.iErrorCode[FD_CLOSE_BIT]);
			break;
		}
/*
		// Write event?
		if (events.lNetworkEvents & FD_WRITE)
		{
			g_log.AddLogInfo(0,"\nFD_WRITE: %d",events.iErrorCode[FD_WRITE_BIT]);
		}
*/
	}
	
	closesocket(ConnectSocket);
	WSACloseEvent(hEvent);

	DWORD Q3_dwNewTotalServers=0;
	for(i=0; i<MAX_PACKETS;i++)
	{
		if(packet[i] != NULL)
		{
		    Q3_dwNewTotalServers += Q3_ParseServers((char*)packet[i],packet_len[i],pGI);
			free(packet[i]);			
			packet[i]=NULL;
			SetStatusText(pGI->iIconIndex,g_lang.GetString("StatusReceivingMaster"),Q3_dwNewTotalServers,pGI->szGAME_NAME);
			if(g_bCancel)
			{
				//ensure to clean up
				for(i=0; i<MAX_PACKETS;i++)
				{
					if(packet[i] != NULL)
					{
						free(packet[i]);			
						packet[i]=NULL;
					}
				}			
				break;
			}
			Sleep(50); //give cpu sometime to breath
		}
	}

//	KillTimer(g_hWnd,IDT_TIMER_1SECOND);
	pGI->dwTotalServers += Q3_dwNewTotalServers;


	return 0;
}
Ejemplo n.º 19
0
int
main (
	int		argc,
	char*		argv[]
	)
{
	pgm_error_t* pgm_err = NULL;

	setlocale (LC_ALL, "");

#ifndef _WIN32
	puts ("いちごのショートケーキ");
#else
	puts ("ichigo no shōtokēki");
#endif

	if (!pgm_init (&pgm_err)) {
		fprintf (stderr, "Unable to start PGM engine: %s\n", pgm_err->message);
		pgm_error_free (pgm_err);
		return EXIT_FAILURE;
	}

/* parse program arguments */
#ifdef _WIN32
	const char* binary_name = strrchr (argv[0], '\\');
#else
	const char* binary_name = strrchr (argv[0], '/');
#endif
	if (NULL == binary_name)	binary_name = argv[0];
	else				binary_name++;

	int c;
	while ((c = getopt (argc, argv, "s:n:p:f:K:N:lih")) != -1)
	{
		switch (c) {
		case 'n':	network = optarg; break;
		case 's':	port = atoi (optarg); break;
		case 'p':	udp_encap_port = atoi (optarg); break;
		case 'f':	use_fec = TRUE; break;
		case 'K':	rs_k = atoi (optarg); break;
		case 'N':	rs_n = atoi (optarg); break;
		case 'l':	use_multicast_loop = TRUE; break;

		case 'i':
			pgm_if_print_all();
			return EXIT_SUCCESS;

		case 'h':
		case '?': usage (binary_name);
		}
	}

	if (use_fec && ( !rs_n || !rs_k )) {
		fprintf (stderr, "Invalid Reed-Solomon parameters RS(%d,%d).\n", rs_n, rs_k);
		usage (binary_name);
	}

/* setup signal handlers */
#ifdef SIGHUP
	signal (SIGHUP,  SIG_IGN);
#endif
#ifndef _WIN32
	int e = pipe (terminate_pipe);
	assert (0 == e);
	signal (SIGINT,  on_signal);
	signal (SIGTERM, on_signal);
#else
	terminateEvent = WSACreateEvent ();
	SetConsoleCtrlHandler ((PHANDLER_ROUTINE)on_console_ctrl, TRUE);
	setvbuf (stdout, (char *) NULL, _IONBF, 0);
#endif /* !_WIN32 */

	if (!on_startup()) {
		fprintf (stderr, "Startup failed\n");
		return EXIT_FAILURE;
	}

/* dispatch loop */
#ifndef _WIN32
	int fds, read_fd = async_get_socket (async);
	fd_set readfds;
#else
	DWORD cEvents = 2;
	WSAEVENT waitEvents[ 2 ];
	DWORD dwEvents;

	waitEvents[0] = terminateEvent;
	waitEvents[1] = async_get_event (async);
#endif /* !_WIN32 */
	puts ("Entering PGM message loop ... ");
	do {
		char buffer[4096];
		struct pgm_sockaddr_t from;
		socklen_t fromlen = sizeof (from);
		const ssize_t len = async_recvfrom (async,
					            buffer,
					            sizeof(buffer),
					            &from,
						    &fromlen);
		if (len >= 0) {
			on_data (buffer, len, &from);
		} else {
#ifndef _WIN32
			fds = MAX(terminate_pipe[0], read_fd) + 1;
			FD_ZERO(&readfds);
			FD_SET(terminate_pipe[0], &readfds);
			FD_SET(read_fd, &readfds);
			fds = select (fds, &readfds, NULL, NULL, NULL);
#else
			dwEvents = WSAWaitForMultipleEvents (cEvents, waitEvents, FALSE, WSA_INFINITE, FALSE);
			switch (dwEvents) {
			case WSA_WAIT_EVENT_0+1: WSAResetEvent (waitEvents[1]); break;
			default: break;
			}
#endif /* _WIN32 */
		}
	} while (!is_terminated);

	puts ("Message loop terminated, cleaning up.");

/* cleanup */
#ifndef _WIN32
	close (terminate_pipe[0]);
	close (terminate_pipe[1]);
#else
	WSACloseEvent (terminateEvent);
#endif /* !_WIN32 */

	if (async) {
		puts ("Destroying asynchronous queue.");
		async_destroy (async);
		async = NULL;
	}

	if (sock) {
		puts ("Closing PGM socket.");
		pgm_close (sock, TRUE);
		sock = NULL;
	}

	puts ("PGM engine shutdown.");
	pgm_shutdown ();
	puts ("finished.");
	return EXIT_SUCCESS;
}
Ejemplo n.º 20
0
string GetGamerData::GetHTML(const string& strServerName, const string& strFileName)
{
	string strGET  = "";
	string strHTML = "";
	
	// ホストの検索
	LPHOSTENT lpHostEntry;
	lpHostEntry = gethostbyname(this->GamerCardServer.c_str());
	if (lpHostEntry == NULL)
	{
		//PRINTERROR("gethostbyname()");
		return strHTML;
	}

	// サーバーアドレス構造体を埋める
	SOCKADDR_IN sa;
	sa.sin_family = AF_INET;
	sa.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);
	sa.sin_port = htons(80);	//HTTPポート

	// TCP/IPストリームソケットを作成する
	SOCKET	Socket;
	Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (Socket == INVALID_SOCKET)
	{
		//PRINTERROR("socket()"); 
		return strHTML;
	}

	// このソケットで使用するイベントオブジェクトを作成する
	WSAEVENT hEvent;
	hEvent = WSACreateEvent();
	if (hEvent == WSA_INVALID_EVENT)
	{
		//PRINTERROR("WSACreateEvent()");
		closesocket(Socket);
		return strHTML;
	}

	// ソケットを非ブロッキングにし、ネットワークイベントを関連付ける
	int nRet;
	nRet = WSAEventSelect(Socket,hEvent,FD_READ|FD_CONNECT|FD_CLOSE);
	if (nRet == SOCKET_ERROR)
	{
		//PRINTERROR("EventSelect()");
		closesocket(Socket);
		WSACloseEvent(hEvent);
		return strHTML;
	}

	// 接続を要求する
	nRet = connect(Socket,(LPSOCKADDR)&sa,sizeof(SOCKADDR_IN));
	if (nRet == SOCKET_ERROR)
	{
		nRet = WSAGetLastError();
		if (nRet == WSAEWOULDBLOCK)
		{
			//fprintf(stderr,"\nConnect would block");
		}
		else
		{
			//PRINTERROR("connect()");
			closesocket(Socket);
			WSACloseEvent(hEvent);
			return strHTML;
		}
	}
	
	// 非同期ネットワークイベントを処理する
	char szBuffer[4096];
	char szBufferZ[8192];
	WSANETWORKEVENTS events;
	while(1)
	{
		// 何か発生するのを待機する
		DWORD dwRet;
		dwRet = WSAWaitForMultipleEvents(1, &hEvent, FALSE,10000,FALSE);
		if (dwRet == WSA_WAIT_TIMEOUT)
		{
			break;
		}

		// どのイベントが発生したかを判別する
		nRet = WSAEnumNetworkEvents(Socket, hEvent, &events);
		if (nRet == SOCKET_ERROR)
		{
			//PRINTERROR("WSAEnumNetworkEvents()");
			break;
		}

		// イベントを処理する

		// 接続イベントかどうか?
		if (events.lNetworkEvents & FD_CONNECT)
		{
			// http要求を送信する
			strGET = "";
			strGET += "GET ";
			strGET += strFileName;
			strGET += " HTTP/1.1\r\nHost: ";
			strGET += strServerName;
			strGET += "\r\nKeep-Alive: timeout=5, max=20\r\nConnection: close\r\n\r\n";
			nRet = send(Socket, strGET.c_str(), strGET.size(), 0);
			if (nRet == SOCKET_ERROR)
			{
				//PRINTERROR("send()");
				break;
			}
		}

		// 読み取りイベントかどうか?
		if (events.lNetworkEvents & FD_READ)
		{
			// データを読み取り、stdoutに書き込む
			nRet = recv(Socket, szBuffer, sizeof(szBuffer), 0);
			if (nRet == SOCKET_ERROR)
			{
				//PRINTERROR("recv()");
				break;
			}
			ZeroMemory(szBufferZ,sizeof(szBufferZ));
			memcpy(szBufferZ,szBuffer,nRet);
			strHTML.append(szBufferZ);
		}

		// 終了イベントかどうか?
		if (events.lNetworkEvents & FD_CLOSE)
		{
			break;
		}

		// 書き込みイベントかどうか?
		if (events.lNetworkEvents & FD_WRITE)
		{
		}

	}
	closesocket(Socket);	
	WSACloseEvent(hEvent);
	return strHTML;
}
Ejemplo n.º 21
0
int
WaitLatchOrSocket(volatile Latch *latch, SOCKET sock, long timeout)
{
	DWORD		rc;
	HANDLE		events[3];
	HANDLE		latchevent;
	HANDLE		sockevent;
	int			numevents;
	int			result = 0;

	latchevent = latch->event;

	events[0] = latchevent;
	events[1] = pgwin32_signal_event;
	numevents = 2;
	if (sock != PGINVALID_SOCKET)
	{
		sockevent = WSACreateEvent();
		WSAEventSelect(sock, sockevent, FD_READ);
		events[numevents++] = sockevent;
	}

	for (;;)
	{
		/*
		 * Reset the event, and check if the latch is set already. If someone
		 * sets the latch between this and the WaitForMultipleObjects() call
		 * below, the setter will set the event and WaitForMultipleObjects()
		 * will return immediately.
		 */
		if (!ResetEvent(latchevent))
			elog(ERROR, "ResetEvent failed: error code %d", (int) GetLastError());
		if (latch->is_set)
		{
			result = 1;
			break;
		}

		rc = WaitForMultipleObjects(numevents, events, FALSE,
								(timeout >= 0) ? (timeout / 1000) : INFINITE);
		if (rc == WAIT_FAILED)
			elog(ERROR, "WaitForMultipleObjects() failed: error code %d", (int) GetLastError());
		else if (rc == WAIT_TIMEOUT)
		{
			result = 0;
			break;
		}
		else if (rc == WAIT_OBJECT_0 + 1)
			pgwin32_dispatch_queued_signals();
		else if (rc == WAIT_OBJECT_0 + 2)
		{
			Assert(sock != PGINVALID_SOCKET);
			result = 2;
			break;
		}
		else if (rc != WAIT_OBJECT_0)
			elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %d", rc);
	}

	/* Clean up the handle we created for the socket */
		if (sock != PGINVALID_SOCKET)
	{
		WSAEventSelect(sock, sockevent, 0);
		WSACloseEvent(sockevent);
	}

	return result;
}
Ejemplo n.º 22
0
void main()
{
	WSADATA wsa; // 버전정보   

	if( WSAStartup( MAKEWORD(2,2), &wsa) != 0) //DLL 로딩 
	{
		puts("WSAStartup Error !! "); return ;
	}
	//1) 핸드폰 단말기 구입 -->  SOCKET : 통신을 하기위한 매개체 !! 
	SOCKET ServerSocket;  
	//2) 소켓 생성 !!		   // TCP/UDP   TCP   
	ServerSocket = socket( AF_INET  , SOCK_STREAM, 0);  

	if( ServerSocket == INVALID_SOCKET)
	{
		puts("socket() error!!");	return ; 
	}
	//3) Usim 
	SOCKADDR_IN ServerAddr; 
	ServerAddr.sin_family		  = AF_INET;		    // TCP/UDP 
	ServerAddr.sin_port		  = htons(20000);	// 포트번호 
	ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);  
	// 4) socket + sockaddr  ==   핸드폰 + Usim 	
	int ret =	bind( ServerSocket, // 소켓 
		(SOCKADDR*)&ServerAddr, //주소 구조체 
		sizeof(ServerAddr));		    // 주소의 크기 

	if( ret == SOCKET_ERROR) 
	{
		puts("bind() error !! "); return ; 
	}
	// 4) 통화 대기 !! 
	ret = 	  listen( ServerSocket,  // 기다릴 소켓 
		SOMAXCONN);	// 가능한 최대값 

	if( ret == SOCKET_ERROR ) 
	{
		puts("listen() error !!"); return ; 
	}
	// 1) 소켓과 이벤트를 연결하고 배열에 저장 
		
	HANDLE hEvent = WSACreateEvent(); //이벤트 객체 생성 !
	// 2) 연결 !! 
	WSAEventSelect( ServerSocket,  // 이벤트를 처리할 소켓 
						  hEvent,			 // 신호를 보내줄 이벤트 
						  FD_ACCEPT|FD_CLOSE); 

	SockList[SockCnt] = ServerSocket; 
	EventList[SockCnt] = hEvent;
	SockCnt++; 

	int index = 0; 
	WSANETWORKEVENTS ne;  
	while(1) 
	{	
		// 소켓에서 네트워크 이벤트 발생하면 Event객체가 시그날 되기를 기다린다!!
		index = WSAWaitForMultipleEvents( SockCnt,  // 시그날을 기다리는 이벤트 수 
										  EventList,  // 이벤트 배열 
										  FALSE, // 1개만 시그날이 돼도 리턴 !! 
										  WSA_INFINITE, 
										  FALSE); 
		index -= WSA_WAIT_EVENT_0; 
	
		// 1) networkevent 구조체에 이벤트 내용을 가져온다 !! 
		// 2) EventList[index] 이벤트를 넌시그날로 변경 
		WSAEnumNetworkEvents( SockList[index], // 이벤트가 발생한 소켓 
										EventList[index], // 시그널 된 이벤트 
										&ne); // out put 

		if( ne.lNetworkEvents & FD_ACCEPT) 
		{
			
			if(ne.iErrorCode[FD_ACCEPT_BIT] != 0) 
			{			
				puts("accept error"); 
				return;
			}
			SOCKADDR_IN ClientAddr; 
			int len = sizeof(ClientAddr); 
			SOCKET ClientSocket;

			ClientSocket = accept( SockList[index] , // 대기하는 소켓 
										 (SOCKADDR*)&ClientAddr, // 클라이언트의 주소를 가져올 구조체
										 &len); 

			if ( ClientSocket == INVALID_SOCKET) 
			{
				puts("accept error "); return ;
			}	
			printf("[ %s ] : %d 님 접속\n" ,   inet_ntoa( ClientAddr.sin_addr),
			ntohs( ClientAddr.sin_port )  ); 
			// 접속자 소켓과 연결될 이벤트 생성 !! 
			WSAEVENT hClientEvent = WSACreateEvent(); 
			// socket + event 
			WSAEventSelect( ClientSocket, hClientEvent, FD_READ|FD_WRITE|FD_CLOSE); 
				
			SockList[SockCnt] = ClientSocket; 
			EventList[SockCnt] = hClientEvent; 
			SockCnt++; 
		}
		
		if( ne.lNetworkEvents & FD_READ || ne.lNetworkEvents & FD_WRITE) 
		{
			if( ne.lNetworkEvents & FD_READ && 
								ne.iErrorCode[FD_READ_BIT] != 0 ) 
			{			
				puts("FD_READ_BIT"); 
				return;
			}
			if( ne.lNetworkEvents & FD_WRITE && ne.iErrorCode[FD_WRITE_BIT] != 0) 
			{			
				puts("FD_WRITE_BIT"); 
				return;
			}
			char buf[BUF_SIZE] = {0};	
			
			recv( SockList[index], buf , BUF_SIZE, 0); 
			SOCKADDR_IN SenderAddr; 
			int len = sizeof(SenderAddr);

			getpeername( SockList[index], (SOCKADDR*)&SenderAddr, &len); 

			printf("[ %s ] %s\n",  inet_ntoa( SenderAddr.sin_addr) ,buf );	
			
			for( int i = 1; i< SockCnt; i++) 
			{
				if( i != index) 
				send( SockList[i], buf, BUF_SIZE, 0);
			}
		}
		if( ne.lNetworkEvents & FD_CLOSE) 
		{
			if(ne.iErrorCode[FD_CLOSE_BIT] != 0) 
			{			
				puts("FD_CLOSE_BIT"); 
				return;
			}
			RemoveSocket( index );
		
		}

	}
	/*
	
	// 화면에 접속한 클라이언트의 IP를 출력 !! 


	*/
	WSACleanup(); // DLL 정리 

}
Ejemplo n.º 23
0
/* Relay data between a socket and a process until the process dies or stops
   sending or receiving data. The socket descriptor and process pipe handles
   are in the data argument, which must be a pointer to struct subprocess_info.

   This function is a workaround for the fact that we can't just run a process
   after redirecting its input handles to a socket. If the process, for
   example, redirects its own stdin, it somehow confuses the socket and stdout
   stops working. This is exactly what ncat does (as part of the Windows stdin
   workaround), so it can't be ignored.

   This function can be invoked through CreateThread to simulate fork+exec, or
   called directly to simulate exec. It frees the subprocess_info struct and
   closes the socket and pipe handles before returning. Returns the exit code
   of the subprocess. */
static DWORD WINAPI subprocess_thread_func(void *data)
{
    struct subprocess_info *info;
    char pipe_buffer[BUFSIZ];
    OVERLAPPED overlap = { 0 };
    HANDLE events[3];
    DWORD ret, rc;
    int crlf_state = 0;

    info = (struct subprocess_info *) data;

    /* Three events we watch for: socket read, pipe read, and process end. */
    events[0] = (HANDLE) WSACreateEvent();
    WSAEventSelect(info->fdn.fd, events[0], FD_READ | FD_CLOSE);
    events[1] = info->child_out_r;
    events[2] = info->proc;

    /* To avoid blocking or polling, we use asynchronous I/O, or what Microsoft
       calls "overlapped" I/O, on the process pipe. WaitForMultipleObjects
       reports when the read operation is complete. */
    ReadFile(info->child_out_r, pipe_buffer, sizeof(pipe_buffer), NULL, &overlap);

    /* Loop until EOF or error. */
    for (;;) {
        DWORD n_r, n_w;
        int i, n;

        i = WaitForMultipleObjects(3, events, FALSE, INFINITE);
        if (i == WAIT_OBJECT_0) {
            /* Read from socket, write to process. */
            char buffer[BUFSIZ];
            int pending;

            ResetEvent(events[0]);
            do {
                n = ncat_recv(&info->fdn, buffer, sizeof(buffer), &pending);
                if (n <= 0)
                    goto loop_end;
                n_r = n;
                if (WriteFile(info->child_in_w, buffer, n_r, &n_w, NULL) == 0)
                    break;
                if (n_w != n)
                    goto loop_end;
            } while (pending);
        } else if (i == WAIT_OBJECT_0 + 1) {
            char *crlf = NULL, *wbuf;
            /* Read from process, write to socket. */
            if (GetOverlappedResult(info->child_out_r, &overlap, &n_r, FALSE)) {
                wbuf = pipe_buffer;
                if (o.crlf) {
                    n = n_r;
                    if (fix_line_endings((char *) pipe_buffer, &n, &crlf, &crlf_state))
                        wbuf = crlf;
                    n_r = n;
                }
                /* The above call to WSAEventSelect puts the socket in
                   non-blocking mode, but we want this send to block, not
                   potentially return WSAEWOULDBLOCK. We call block_socket, but
                   first we must clear out the select event. */
                WSAEventSelect(info->fdn.fd, events[0], 0);
                block_socket(info->fdn.fd);
                n = ncat_send(&info->fdn, wbuf, n_r);
                if (crlf != NULL)
                    free(crlf);
                if (n != n_r)
                    break;
                /* Restore the select event (and non-block the socket again.) */
                WSAEventSelect(info->fdn.fd, events[0], FD_READ | FD_CLOSE);
                /* Queue another asychronous read. */
                ReadFile(info->child_out_r, pipe_buffer, sizeof(pipe_buffer), NULL, &overlap);
            } else {
                if (GetLastError() != ERROR_IO_PENDING)
                    /* Error or end of file. */
                    break;
            }
        } else if (i == WAIT_OBJECT_0 + 2) {
            /* The child died. There are no more writes left in the pipe
               because WaitForMultipleObjects guarantees events with lower
               indexes are handled first. */
            break;
        } else {
            break;
        }
    }

loop_end:

    WSACloseEvent(events[0]);

    rc = unregister_subprocess(info->proc);
    ncat_assert(rc != -1);

    GetExitCodeProcess(info->proc, &ret);
    if (ret == STILL_ACTIVE) {
        if (o.debug > 1)
            logdebug("Subprocess still running, terminating it.\n");
        rc = TerminateProcess(info->proc, 0);
        if (rc == 0) {
            if (o.debug > 1)
                logdebug("TerminateProcess failed with code %d.\n", rc);
        }
    }
    GetExitCodeProcess(info->proc, &ret);
    if (o.debug > 1)
        logdebug("Subprocess ended with exit code %d.\n", ret);

    shutdown(info->fdn.fd, 2);
    subprocess_info_close(info);
    free(info);

    rc = WaitForSingleObject(pseudo_sigchld_mutex, INFINITE);
    ncat_assert(rc == WAIT_OBJECT_0);
    if (pseudo_sigchld_handler != NULL)
        pseudo_sigchld_handler();
    rc = ReleaseMutex(pseudo_sigchld_mutex);
    ncat_assert(rc != 0);

    return ret;
}
Ejemplo n.º 24
0
static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
                     fd_set *exceptfds, struct timeval *timeout)
{
  DWORD milliseconds, wait, idx;
  WSANETWORKEVENTS wsanetevents;
  struct select_ws_data *data;
  HANDLE handle, *handles;
  curl_socket_t sock;
  long networkevents;
  WSAEVENT wsaevent;
  int error, fds;
  HANDLE waitevent = NULL;
  DWORD nfd = 0, thd = 0, wsa = 0;
  int ret = 0;

  /* check if the input value is valid */
  if(nfds < 0) {
    errno = EINVAL;
    return -1;
  }

  /* check if we got descriptors, sleep in case we got none */
  if(!nfds) {
    Sleep((timeout->tv_sec*1000)+(DWORD)(((double)timeout->tv_usec)/1000.0));
    return 0;
  }

  /* create internal event to signal waiting threads */
  waitevent = CreateEvent(NULL, TRUE, FALSE, NULL);
  if(!waitevent) {
    errno = ENOMEM;
    return -1;
  }

  /* allocate internal array for the internal data */
  data = malloc(nfds * sizeof(struct select_ws_data));
  if(data == NULL) {
    errno = ENOMEM;
    return -1;
  }

  /* allocate internal array for the internal event handles */
  handles = malloc(nfds * sizeof(HANDLE));
  if(handles == NULL) {
    free(data);
    errno = ENOMEM;
    return -1;
  }

  /* clear internal arrays */
  memset(data, 0, nfds * sizeof(struct select_ws_data));
  memset(handles, 0, nfds * sizeof(HANDLE));

  /* loop over the handles in the input descriptor sets */
  for(fds = 0; fds < nfds; fds++) {
    networkevents = 0;
    handles[nfd] = 0;

    if(FD_ISSET(fds, readfds))
      networkevents |= FD_READ|FD_ACCEPT|FD_CLOSE;

    if(FD_ISSET(fds, writefds))
      networkevents |= FD_WRITE|FD_CONNECT;

    if(FD_ISSET(fds, exceptfds))
      networkevents |= FD_OOB|FD_CLOSE;

    /* only wait for events for which we actually care */
    if(networkevents) {
      data[nfd].fd = curlx_sitosk(fds);
      if(fds == fileno(stdin)) {
        handle = GetStdHandle(STD_INPUT_HANDLE);
        handle = select_ws_wait(handle, waitevent);
        handles[nfd] = handle;
        data[thd].thread = handle;
        thd++;
      }
      else if(fds == fileno(stdout)) {
        handles[nfd] = GetStdHandle(STD_OUTPUT_HANDLE);
      }
      else if(fds == fileno(stderr)) {
        handles[nfd] = GetStdHandle(STD_ERROR_HANDLE);
      }
      else {
        wsaevent = WSACreateEvent();
        if(wsaevent != WSA_INVALID_EVENT) {
          error = WSAEventSelect(fds, wsaevent, networkevents);
          if(error != SOCKET_ERROR) {
            handle = (HANDLE) wsaevent;
            handles[nfd] = handle;
            data[wsa].wsasock = curlx_sitosk(fds);
            data[wsa].wsaevent = wsaevent;
            wsa++;
          }
          else {
            WSACloseEvent(wsaevent);
            handle = (HANDLE) curlx_sitosk(fds);
            handle = select_ws_wait(handle, waitevent);
            handles[nfd] = handle;
            data[thd].thread = handle;
            thd++;
          }
        }
      }
      nfd++;
    }
  }

  /* convert struct timeval to milliseconds */
  if(timeout) {
    milliseconds = ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000));
  }
  else {
    milliseconds = INFINITE;
  }

  /* wait for one of the internal handles to trigger */
  wait = WaitForMultipleObjectsEx(nfd, handles, FALSE, milliseconds, FALSE);

  /* signal the event handle for the waiting threads */
  SetEvent(waitevent);

  /* loop over the internal handles returned in the descriptors */
  for(idx = 0; idx < nfd; idx++) {
    handle = handles[idx];
    sock = data[idx].fd;
    fds = curlx_sktosi(sock);

    /* check if the current internal handle was triggered */
    if(wait != WAIT_FAILED && (wait - WAIT_OBJECT_0) <= idx &&
       WaitForSingleObjectEx(handle, 0, FALSE) == WAIT_OBJECT_0) {
      /* first handle stdin, stdout and stderr */
      if(fds == fileno(stdin)) {
        /* stdin is never ready for write or exceptional */
        FD_CLR(sock, writefds);
        FD_CLR(sock, exceptfds);
      }
      else if(fds == fileno(stdout) || fds == fileno(stderr)) {
        /* stdout and stderr are never ready for read or exceptional */
        FD_CLR(sock, readfds);
        FD_CLR(sock, exceptfds);
      }
      else {
        /* try to handle the event with the WINSOCK2 functions */
        wsanetevents.lNetworkEvents = 0;
        error = WSAEnumNetworkEvents(fds, handle, &wsanetevents);
        if(error != SOCKET_ERROR) {
          /* remove from descriptor set if not ready for read/accept/close */
          if(!(wsanetevents.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE)))
            FD_CLR(sock, readfds);

          /* remove from descriptor set if not ready for write/connect */
          if(!(wsanetevents.lNetworkEvents & (FD_WRITE|FD_CONNECT)))
            FD_CLR(sock, writefds);

          /* HACK:
           * use exceptfds together with readfds to signal
           * that the connection was closed by the client.
           *
           * Reason: FD_CLOSE is only signaled once, sometimes
           * at the same time as FD_READ with data being available.
           * This means that recv/sread is not reliable to detect
           * that the connection is closed.
           */
          /* remove from descriptor set if not exceptional */
          if(!(wsanetevents.lNetworkEvents & (FD_OOB|FD_CLOSE)))
            FD_CLR(sock, exceptfds);
        }
      }

      /* check if the event has not been filtered using specific tests */
      if(FD_ISSET(sock, readfds) || FD_ISSET(sock, writefds) ||
         FD_ISSET(sock, exceptfds)) {
        ret++;
      }
    }
    else {
      /* remove from all descriptor sets since this handle did not trigger */
      FD_CLR(sock, readfds);
      FD_CLR(sock, writefds);
      FD_CLR(sock, exceptfds);
    }
  }

  for(fds = 0; fds < nfds; fds++) {
    if(FD_ISSET(fds, readfds))
      logmsg("select_ws: %d is readable", fds);

    if(FD_ISSET(fds, writefds))
      logmsg("select_ws: %d is writable", fds);

    if(FD_ISSET(fds, exceptfds))
      logmsg("select_ws: %d is excepted", fds);
  }

  for(idx = 0; idx < wsa; idx++) {
    WSAEventSelect(data[idx].wsasock, NULL, 0);
    WSACloseEvent(data[idx].wsaevent);
  }

  for(idx = 0; idx < thd; idx++) {
    WaitForSingleObject(data[idx].thread, INFINITE);
    CloseHandle(data[idx].thread);
  }

  CloseHandle(waitevent);

  free(handles);
  free(data);

  return ret;
}
Ejemplo n.º 25
0
        explicit IOController(std::unique_ptr<NUClear::Environment> environment) : Reactor(std::move(environment)) {

            // Startup WSA for IO
            WORD version = MAKEWORD(2, 2);
            WSADATA wsa_data;
            WSAStartup(version, &wsa_data);

            // Reserve 1024 event slots
            // Hopefully we won't have more events than that
            // Even if we do it should be fine (after a glitch)
            fds.reserve(1024);

            // Create an event to use for the notifier
            notifier = WSACreateEvent();

            // We always have the notifier in the event list
            fds.push_back(notifier);

            on<Trigger<dsl::word::IOConfiguration>>().then(
                "Configure IO Reaction", [this](const dsl::word::IOConfiguration& config) {
                    // Lock our mutex
                    std::lock_guard<std::mutex> lock(reaction_mutex);

                    // Make an event for this SOCKET
                    auto event = WSACreateEvent();

                    // Link our event to the socket
                    WSAEventSelect(config.fd, event, config.events);

                    // Add all the information to the list
                    reactions.insert(std::make_pair(event, Event{config.fd, config.reaction, config.events}));

                    // Also add it to the end of our watching list
                    fds.push_back(event);

                    // Enable our notification event
                    WSASetEvent(notifier);
                });

            on<Trigger<dsl::operation::Unbind<IO>>>().then("Unbind IO Reaction",
                                                           [this](const dsl::operation::Unbind<IO>& unbind) {
                                                               // Lock our mutex

                                                               // Find this reaction in our list of reactions

                                                               // Remove it
                                                               // WSACloseEvent

                                                               // Flag that our list is dirty

                                                               // Enable our notification event
                                                           });

            on<Shutdown>().then("Shutdown IO Controller", [this] {
                // Set shutdown to true
                shutdown = true;

                // Enable our notification event
                WSASetEvent(notifier);
            });

            on<Always>().then("IO Controller", [this] {
                if (!shutdown) {

                    // Wait for events
                    auto event = WSAWaitForMultipleEvents(fds.size(), fds.data(), false, WSA_INFINITE, false);

                    // Check if the return value is an event in our list
                    if (event >= WSA_WAIT_EVENT_0 && event < WSA_WAIT_EVENT_0 + fds.size()) {

                        // Check for notification event
                        if (event == WSA_WAIT_EVENT_0) {
                            WSAResetEvent(notifier);
                        }
                        else {
                            // Get our event
                            auto& e = fds[event - WSA_WAIT_EVENT_0];

                            // Get our associated Event object (if it exists)
                            auto r = reactions.find(e);
                            if (r != reactions.end()) {

                                // Enum the events to work out which ones fired
                                WSANETWORKEVENTS wsae;
                                WSAEnumNetworkEvents(r->second.fd, e, &wsae);

                                // Make our event to pass through
                                IO::Event e;
                                e.fd = r->second.fd;

                                // Our events are what we got from the enum events call
                                e.events = wsae.lNetworkEvents;

                                // Store the event in our thread local cache
                                IO::ThreadEventStore::value = &e;

                                // Submit the task (which should run the get)
                                try {
                                    auto task = r->second.reaction->get_task();
                                    if (task) {
                                        powerplant.submit(std::move(task));
                                    }
                                }
                                catch (...) {
                                }

                                // Reset our value
                                IO::ThreadEventStore::value = nullptr;
                            }
                        }
                    }
                }

                // If not shudown

                // If dirty then update our list

                // If

                // WSAWaitForMultipleEvents(
                //     countOfEvents
                //     arrayofWSAEVENT
                //     waituntilall?orany // FALSE
                //     timeout // WSA_INFINITE
                //     alertable? // FALSE
                // )

                // Get the item that is associated with this event
                // Call the reaction with the information
            });
        }
Ejemplo n.º 26
0
int
WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
				  long timeout)
{
	DWORD		rc;
	instr_time	start_time,
				cur_time;
	long		cur_timeout;
	HANDLE		events[4];
	HANDLE		latchevent;
	HANDLE		sockevent = WSA_INVALID_EVENT;
	int			numevents;
	int			result = 0;
	int			pmdeath_eventno = 0;

	/* Ignore WL_SOCKET_* events if no valid socket is given */
	if (sock == PGINVALID_SOCKET)
		wakeEvents &= ~(WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE);

	Assert(wakeEvents != 0);	/* must have at least one wake event */
	/* Cannot specify WL_SOCKET_WRITEABLE without WL_SOCKET_READABLE */
	Assert((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) != WL_SOCKET_WRITEABLE);

	if ((wakeEvents & WL_LATCH_SET) && latch->owner_pid != MyProcPid)
		elog(ERROR, "cannot wait on a latch owned by another process");

	/*
	 * Initialize timeout if requested.  We must record the current time so
	 * that we can determine the remaining timeout if WaitForMultipleObjects
	 * is interrupted.
	 */
	if (wakeEvents & WL_TIMEOUT)
	{
		INSTR_TIME_SET_CURRENT(start_time);
		Assert(timeout >= 0);
		cur_timeout = timeout;
	}
	else
		cur_timeout = INFINITE;

	/*
	 * Construct an array of event handles for WaitforMultipleObjects().
	 *
	 * Note: pgwin32_signal_event should be first to ensure that it will be
	 * reported when multiple events are set.  We want to guarantee that
	 * pending signals are serviced.
	 */
	latchevent = latch->event;

	events[0] = pgwin32_signal_event;
	events[1] = latchevent;
	numevents = 2;
	if (wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE))
	{
		/* Need an event object to represent events on the socket */
		int			flags = 0;

		if (wakeEvents & WL_SOCKET_READABLE)
			flags |= (FD_READ | FD_CLOSE);
		if (wakeEvents & WL_SOCKET_WRITEABLE)
			flags |= FD_WRITE;

		sockevent = WSACreateEvent();
		if (sockevent == WSA_INVALID_EVENT)
			elog(ERROR, "failed to create event for socket: error code %u",
				 WSAGetLastError());
		if (WSAEventSelect(sock, sockevent, flags) != 0)
			elog(ERROR, "failed to set up event for socket: error code %u",
				 WSAGetLastError());

		events[numevents++] = sockevent;
	}
	if (wakeEvents & WL_POSTMASTER_DEATH)
	{
		pmdeath_eventno = numevents;
		events[numevents++] = PostmasterHandle;
	}

	/* Ensure that signals are serviced even if latch is already set */
	pgwin32_dispatch_queued_signals();

	do
	{
		/*
		 * Reset the event, and check if the latch is set already. If someone
		 * sets the latch between this and the WaitForMultipleObjects() call
		 * below, the setter will set the event and WaitForMultipleObjects()
		 * will return immediately.
		 */
		if (!ResetEvent(latchevent))
			elog(ERROR, "ResetEvent failed: error code %lu", GetLastError());

		if ((wakeEvents & WL_LATCH_SET) && latch->is_set)
		{
			result |= WL_LATCH_SET;

			/*
			 * Leave loop immediately, avoid blocking again. We don't attempt
			 * to report any other events that might also be satisfied.
			 */
			break;
		}

		rc = WaitForMultipleObjects(numevents, events, FALSE, cur_timeout);

		if (rc == WAIT_FAILED)
			elog(ERROR, "WaitForMultipleObjects() failed: error code %lu",
				 GetLastError());
		else if (rc == WAIT_TIMEOUT)
		{
			result |= WL_TIMEOUT;
		}
		else if (rc == WAIT_OBJECT_0)
		{
			/* Service newly-arrived signals */
			pgwin32_dispatch_queued_signals();
		}
		else if (rc == WAIT_OBJECT_0 + 1)
		{
			/*
			 * Latch is set.  We'll handle that on next iteration of loop, but
			 * let's not waste the cycles to update cur_timeout below.
			 */
			continue;
		}
		else if ((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) &&
				 rc == WAIT_OBJECT_0 + 2)		/* socket is at event slot 2 */
		{
			WSANETWORKEVENTS resEvents;

			ZeroMemory(&resEvents, sizeof(resEvents));
			if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) != 0)
				elog(ERROR, "failed to enumerate network events: error code %u",
					 WSAGetLastError());
			if ((wakeEvents & WL_SOCKET_READABLE) &&
				(resEvents.lNetworkEvents & (FD_READ | FD_CLOSE)))
			{
				result |= WL_SOCKET_READABLE;
			}
			if ((wakeEvents & WL_SOCKET_WRITEABLE) &&
				(resEvents.lNetworkEvents & FD_WRITE))
			{
				result |= WL_SOCKET_WRITEABLE;
			}
		}
		else if ((wakeEvents & WL_POSTMASTER_DEATH) &&
				 rc == WAIT_OBJECT_0 + pmdeath_eventno)
		{
			/*
			 * Postmaster apparently died.	Since the consequences of falsely
			 * returning WL_POSTMASTER_DEATH could be pretty unpleasant, we
			 * take the trouble to positively verify this with
			 * PostmasterIsAlive(), even though there is no known reason to
			 * think that the event could be falsely set on Windows.
			 */
			if (!PostmasterIsAlive())
				result |= WL_POSTMASTER_DEATH;
		}
		else
			elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %lu", rc);

		/* If we're not done, update cur_timeout for next iteration */
		if (result == 0 && cur_timeout != INFINITE)
		{
			INSTR_TIME_SET_CURRENT(cur_time);
			INSTR_TIME_SUBTRACT(cur_time, start_time);
			cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time);
			if (cur_timeout < 0)
				cur_timeout = 0;
		}
	} while (result == 0);

	/* Clean up the event object we created for the socket */
	if (sockevent != WSA_INVALID_EVENT)
	{
		WSAEventSelect(sock, NULL, 0);
		WSACloseEvent(sockevent);
	}

	return result;
}
Ejemplo n.º 27
0
int net_recvBytes(int sock, char *buf, int bufSize, int * outLen, int timeout)
{
	WSAOVERLAPPED recvOverlapped;
	WSABUF dataBuf;

	DWORD recvBytes = 0;
	int index       = 0;
	DWORD flags     = 0;
	int rc          = 0;
	int lastError   = 0;

	// Make sure the RecvOverlapped struct is zeroed out
	SecureZeroMemory((PVOID) & recvOverlapped, sizeof (WSAOVERLAPPED));
	SecureZeroMemory((PVOID) & dataBuf, sizeof (WSABUF));

	// Create an event handle and setup an overlapped structure.
	recvOverlapped.hEvent = WSACreateEvent();
	if (recvOverlapped.hEvent == NULL) 
	{
		debug_log(LOG_ERR, "net_recvBytes(): WSACreateEvent failed: %d", WSAGetLastError());			
		return SOCK_IO_ERROR;
	}

	dataBuf.len = bufSize-1; // one for ending null
	dataBuf.buf = buf;

	*buf = '\0';
	while (index < bufSize) 
	{		
		recvBytes = 0;
		flags = 0;

wait_for_recv:
		rc = WSARecv(sock, &dataBuf, 1, &recvBytes, &flags, &recvOverlapped, NULL);
		if (rc != 0)
		{
			if (rc == SOCKET_ERROR) 
			{
				lastError = WSAGetLastError();

				if (lastError == WSAEWOULDBLOCK)
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_recv;
				} else
				{
					if (lastError != WSA_IO_PENDING)
					{
						debug_log(LOG_ERR, "net_recvBytes(): WSARecv failed with error: %d", lastError);
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_IO_ERROR;					
					}
				}
			}

wait_for_io: 
			rc = WSAWaitForMultipleEvents(1, &recvOverlapped.hEvent, TRUE, timeout, TRUE);
			if (rc == WSA_WAIT_TIMEOUT)
			{
				debug_log(LOG_ERR, "net_recvBytes(): overlapped I/O timeout: %d", timeout);
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_TIMEOUT;
			}
			if (rc == WSA_WAIT_IO_COMPLETION) 
			{
				if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
				{
					closesocket(sock);
					WSACloseEvent(recvOverlapped.hEvent);
					return SOCK_WDOG_SHUTDOWN;
				}

				SleepEx(SLEEP_EX_INTERVAL, TRUE);
				goto wait_for_io;
			}

wait_for_ov:
			rc = WSAGetOverlappedResult(sock, &recvOverlapped, &recvBytes, FALSE, &flags);
			if (rc == FALSE) 
			{
				lastError = WSAGetLastError();
				if (lastError == WSA_IO_INCOMPLETE)
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_ov;
				}

				debug_log(LOG_ERR, "net_recvBytes(): overlapped I/O failed with error: %d", lastError);
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_IO_ERROR;
			}

			// ------------------------
			// Reset the signaled event
			// ------------------------
			rc = WSAResetEvent(recvOverlapped.hEvent);
			if (rc == FALSE) 
			{
				debug_log(LOG_ERR, "net_recvBytes(): WSAResetEvent failed with error = %d", WSAGetLastError());
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_IO_ERROR;
			}
		}

		if (recvBytes == 0)
			break;

		if ((index + (int) recvBytes) > bufSize)
			break;

		index += recvBytes;

		buf[index] = '\0';

		if ((bufSize-index) <= 0)
			break;

		dataBuf.len = bufSize-index;
		dataBuf.buf = buf+index;
	} // while (index < bufSize) 

	WSACloseEvent(recvOverlapped.hEvent);
	
	*outLen = index;

	return SOCK_NO_ERROR;
} // end of net_recvBytes()
Ejemplo n.º 28
0
void TCPServer::WaitForClientThread() {
	csIsWaiting.Enter();
	bIsWaiting = true;
	csIsWaiting.Leave();
	
	SOCKET UDPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (UDPSocket == INVALID_SOCKET) {
		ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("UDPSocket create fail!"));
		csIsWaiting.Enter();
		bIsWaiting = false;
		csIsWaiting.Leave();
		return;
	}
	
	sockaddr_in udp_addr = {0};
	udp_addr.sin_family = AF_INET;
	udp_addr.sin_port = htons(PORT);
	udp_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	
	if (bind(UDPSocket, (sockaddr*)&udp_addr, sizeof(sockaddr_in)) == SOCKET_ERROR) {
		ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("UDPSocket bind fail!"));
		csIsWaiting.Enter();
		bIsWaiting = false;
		csIsWaiting.Leave();
		return;
	}
	
	WSAEVENT hEvent = WSACreateEvent();
	if (hEvent == WSA_INVALID_EVENT) {
		ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("WSACreateEvent fail!"));
		csIsWaiting.Enter();
		bIsWaiting = false;
		csIsWaiting.Leave();
		return;
	}
	
	if (WSAEventSelect(UDPSocket, hEvent, FD_READ) == SOCKET_ERROR) {
		ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("WSAEventSelect fail!"));
		csIsWaiting.Enter();
		bIsWaiting = false;
		csIsWaiting.Leave();
		return;
	}
	
	csStopWait.Enter();
	bStopWait = false;
	csStopWait.Leave();
	
	while (true) {
		DWORD result = WSAWaitForMultipleEvents(1, &hEvent, FALSE, 500, FALSE);
		if (result == WSA_WAIT_FAILED) {
			ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("WSAWaitForMultipleEvents fail!"));
			csIsWaiting.Enter();
			bIsWaiting = false;
			csIsWaiting.Leave();
			return;
		}
		
		csStopWait.Enter();
		if (bStopWait) {
			csStopWait.Leave();
			closesocket(UDPSocket);
			csIsWaiting.Enter();
			bIsWaiting = false;
			csIsWaiting.Leave();
			return;
		}
		csStopWait.Leave();
		
		if (result == WSA_WAIT_TIMEOUT) {
			continue;
		}
		
		WSANETWORKEVENTS netEvents = {0};
		if (WSAEnumNetworkEvents(UDPSocket, hEvent, &netEvents) == SOCKET_ERROR) {
			ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("WSAWaitForMultipleEvents fail!"));
			csIsWaiting.Enter();
			bIsWaiting = false;
			csIsWaiting.Leave();
			return;
		}
		
		if (netEvents.iErrorCode[FD_READ]) {
			ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("iErrorCode FD_READ fail!"));
			csIsWaiting.Enter();
			bIsWaiting = false;
			csIsWaiting.Leave();
			return;
		}
		
		sockaddr_in client_addr = {0};
		int client_addr_size = sizeof(sockaddr_in);
		UDPPacket packet = {0};
		
		if (recvfrom(UDPSocket, (char*)&packet, sizeof(UDPPacket), 0, (sockaddr*)&client_addr, &client_addr_size) == SOCKET_ERROR) {
			ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("UDPSocket recvfrom fail!"));
			csIsWaiting.Enter();
			bIsWaiting = false;
			csIsWaiting.Leave();
			return;
		}
		
		if (packet.message == LOCATE_SERVER) {
			UDPPacket answer = {0};
			answer.message = CONFIRM_SERVER;
			
			csTCP.Enter();
			_tcscpy_s(answer.nick, STR_SIZE, Nick);
			_tcscpy_s(answer.pcname, STR_SIZE, PCName);
			csTCP.Leave();
			
			if (sendto(UDPSocket, (char*)&answer, sizeof(UDPPacket), 0, (sockaddr*)&client_addr, client_addr_size) == SOCKET_ERROR) {
				ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("UDPSocket sendto fail!"));
				csIsWaiting.Enter();
				bIsWaiting = false;
				csIsWaiting.Leave();
				return;
			}
			
			continue;
		}
		
		if (packet.message == CONNECT_TO_SERVER) {
			csTCP.Enter();
			_tcscpy_s(oppNick, STR_SIZE, packet.nick);
			_tcscpy_s(oppPCName, STR_SIZE, packet.pcname);
			csTCP.Leave();
			
			closesocket(UDPSocket);
			break;
		}
	}
	
	SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (listenSocket == INVALID_SOCKET) {
		ErrorHandler(listenSocket, WSAGetLastError(), TEXT("listenSocket create fail!"));
		csIsWaiting.Enter();
		bIsWaiting = false;
		csIsWaiting.Leave();
		return;
	}
	
	sockaddr_in listen_addr = {0};
	listen_addr.sin_family = AF_INET;
	listen_addr.sin_port = htons(PORT);
	listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	
	if (bind(listenSocket, (sockaddr*)&listen_addr, sizeof(sockaddr_in)) == SOCKET_ERROR) {
		ErrorHandler(listenSocket, WSAGetLastError(), TEXT("listenSocket bind fail!"));
		csIsWaiting.Enter();
		bIsWaiting = false;
		csIsWaiting.Leave();
		return;
	}
	
	if (listen(listenSocket, 1) == SOCKET_ERROR) {
		ErrorHandler(listenSocket, WSAGetLastError(), TEXT("listenSocket listen fail!"));
		csIsWaiting.Enter();
		bIsWaiting = false;
		csIsWaiting.Leave();
		return;
	}
	
	int connect_addr_size = sizeof(sockaddr_in);
	TCPSocket = accept(listenSocket, (sockaddr*)&connect_addr, &connect_addr_size);
	closesocket(listenSocket);
	if (TCPSocket == INVALID_SOCKET) {
		ErrorHandler(TCPSocket, WSAGetLastError(), TEXT("listenSocket accept fail!"));
		csIsWaiting.Enter();
		bIsWaiting = false;
		csIsWaiting.Leave();
		return;
	}
	
	if (!KeepAlive()) {
		csIsWaiting.Enter();
		bIsWaiting = false;
		csIsWaiting.Leave();
		return;
	}
	
	if (!ReceiveData()) {
		ErrorHandler(TCPSocket, ERROR_CREATE_THREAD_FAIL, TEXT("ReceiveDataThread start fail!"));
		csIsWaiting.Enter();
		bIsWaiting = false;
		csIsWaiting.Leave();
		return;
	}
	
	csTCP.Enter();
	bIsConnected = true;
	csTCP.Leave();
	PostMessage(hSendWnd, SUCCESS_CONNECTED, NULL, NULL);
	
	csIsWaiting.Enter();
	bIsWaiting = false;
	csIsWaiting.Leave();
	
	return;
};
Ejemplo n.º 29
0
int
main (
	int		argc,
	char*		argv[]
	)
{
	pgm_error_t* pgm_err = NULL;

	setlocale (LC_ALL, "");

#ifndef _WIN32
	puts ("プリン プリン");
#else
	_putws (L"プリン プリン");
#endif

	if (!pgm_init (&pgm_err)) {
		fprintf (stderr, "Unable to start PGM engine: %s\n", pgm_err->message);
		pgm_error_free (pgm_err);
		return EXIT_FAILURE;
	}

/* parse program arguments */
	const char* binary_name = strrchr (argv[0], '/');
	int c;
	while ((c = getopt (argc, argv, "s:n:p:f:K:N:lih")) != -1)
	{
		switch (c) {
		case 'n':	network = optarg; break;
		case 's':	port = atoi (optarg); break;
		case 'p':	udp_encap_port = atoi (optarg); break;
		case 'f':	use_fec = TRUE; break;
		case 'K':	rs_k = atoi (optarg); break;
		case 'N':	rs_n = atoi (optarg); break;
		case 'l':	use_multicast_loop = TRUE; break;

		case 'i':
			pgm_if_print_all();
			return EXIT_SUCCESS;

		case 'h':
		case '?': usage (binary_name);
		}
	}

	if (use_fec && ( !rs_n || !rs_k )) {
		fprintf (stderr, "Invalid Reed-Solomon parameters RS(%d,%d).\n", rs_n, rs_k);
		usage (binary_name);
	}

/* setup signal handlers */
#ifdef SIGHUP
	signal (SIGHUP,  SIG_IGN);
#endif
#ifndef _WIN32
	int e = pipe (terminate_pipe);
	assert (0 == e);
	signal (SIGINT,  on_signal);
	signal (SIGTERM, on_signal);
#else
	terminate_event = CreateEvent (NULL, TRUE, FALSE, TEXT("TerminateEvent"));
	SetConsoleCtrlHandler ((PHANDLER_ROUTINE)on_console_ctrl, TRUE);
#endif /* !_WIN32 */

	if (!on_startup()) {
		fprintf (stderr, "Startup failed\n");
		return EXIT_FAILURE;
	}

/* dispatch loop */
#ifndef _WIN32
	int fds;
	fd_set readfds;
#else
	int n_handles = 3, recv_sock, pending_sock;
	HANDLE waitHandles[ 3 ];
	DWORD dwTimeout, dwEvents;
	WSAEVENT recvEvent, pendingEvent;

	recvEvent = WSACreateEvent ();
	pgm_getsockopt (sock, PGM_RECV_SOCK, &recv_sock, sizeof(recv_sock));
	WSAEventSelect (recv_sock, recvEvent, FD_READ);
	pendingEvent = WSACreateEvent ();
	pgm_getsockopt (sock, PGM_PENDING_SOCK, &pending_sock, sizeof(pending_sock));
	WSAEventSelect (pending_sock, pendingEvent, FD_READ);

	waitHandles[0] = terminate_event;
	waitHandles[1] = recvEvent;
	waitHandles[2] = pendingEvent;
#endif /* !_WIN32 */
	puts ("Entering PGM message loop ... ");
	do {
		struct timeval tv;
		char buffer[4096];
		size_t len;
		pgm_tsi_t from;
		const int status = pgm_recvfrom (sock,
					         buffer,
					         sizeof(buffer),
					         0,
					         &len,
					         &from,
					         &pgm_err);
		switch (status) {
		case PGM_IO_STATUS_NORMAL:
			on_data (buffer, len, &from);
			break;
		case PGM_IO_STATUS_TIMER_PENDING:
			pgm_getsockopt (sock, PGM_TIME_REMAIN, &tv, sizeof(tv));
			goto block;
		case PGM_IO_STATUS_RATE_LIMITED:
			pgm_getsockopt (sock, PGM_RATE_REMAIN, &tv, sizeof(tv));
		case PGM_IO_STATUS_WOULD_BLOCK:
/* select for next event */
block:
#ifndef _WIN32
			fds = terminate_pipe[0] + 1;
			FD_ZERO(&readfds);
			FD_SET(terminate_pipe[0], &readfds);
			pgm_select_info (sock, &readfds, NULL, &fds);
			fds = select (fds, &readfds, NULL, NULL, PGM_IO_STATUS_WOULD_BLOCK == status ? NULL : &tv);
#else
			dwTimeout = PGM_IO_STATUS_WOULD_BLOCK == status ? INFINITE : (DWORD)((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
			dwEvents = WaitForMultipleObjects (n_handles, waitHandles, FALSE, dwTimeout);
			switch (dwEvents) {
			case WAIT_OBJECT_0+1: WSAResetEvent (recvEvent); break;
			case WAIT_OBJECT_0+2: WSAResetEvent (pendingEvent); break;
			default: break;
			}
#endif /* !_WIN32 */
			break;

		default:
			if (pgm_err) {
				fprintf (stderr, "%s\n", pgm_err->message);
				pgm_error_free (pgm_err);
				pgm_err = NULL;
			}
			if (PGM_IO_STATUS_ERROR == status)
				break;
		}
	} while (!is_terminated);

	puts ("Message loop terminated, cleaning up.");

/* cleanup */
#ifndef _WIN32
	close (terminate_pipe[0]);
	close (terminate_pipe[1]);
#else
	WSACloseEvent (recvEvent);
	WSACloseEvent (pendingEvent);
	CloseHandle (terminate_event);
#endif /* !_WIN32 */

	if (sock) {
		puts ("Destroying PGM socket.");
		pgm_close (sock, TRUE);
		sock = NULL;
	}

	puts ("PGM engine shutdown.");
	pgm_shutdown ();
	puts ("finished.");
	return EXIT_SUCCESS;
}
Ejemplo n.º 30
0
static ErlDrvSSizeT call(ErlDrvData edd, unsigned int cmd, char *buf,
			 ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen,
			 unsigned int *flags) {
  dnssd_drv_t* dd = (dnssd_drv_t*) edd;
  int version, out_len, index, rindex, local_only;
  DNSServiceErrorType err;
  char* out_atom_text;
  ei_term arg, name, type, domain, txt, host, hostport;
  char *name_tmp, *type_tmp, *domain_tmp, *txt_tmp, *host_tmp;

  /* don't allow reuse */
  if (dd->sd_ref) return -1;

  index = 0;
  dd->sd_ref = NULL;

  ei_decode_version(buf, &index, &version);
  ei_decode_ei_term(buf, &index, &arg);

  if (cmd == DNSSD_CMD_ENUM)  {
    if (arg.ei_type == ERL_ATOM_EXT) {
      if (strncmp(arg.value.atom_name, "browse", 6) == 0) {
	// init for enum browse
	err = DNSServiceEnumerateDomains(&dd->sd_ref,
					 kDNSServiceFlagsBrowseDomains,
					 kDNSServiceInterfaceIndexAny,
					 (DNSServiceDomainEnumReply) EnumReply,
					 dd);
      } else if (strncmp(arg.value.atom_name,"reg", 3) == 0) {
	// init for enum reg
	err = DNSServiceEnumerateDomains(&dd->sd_ref,
					 kDNSServiceFlagsRegistrationDomains,
					 kDNSServiceInterfaceIndexAny,
					 (DNSServiceDomainEnumReply) EnumReply,
					 dd);
      } else {
	goto badarg;
      }
    } else {
      goto badarg;
    }
  } else if (cmd == DNSSD_CMD_BROWSE) {
    if (!arg.ei_type == ERL_TUPLE || arg.arity != 2) goto badarg;
    /* decode type */
    ei_decode_ei_term(buf, &index, &type);
    if (type.ei_type != ERL_BINARY_EXT) goto badarg;
    index += 5; // skip tag + 4 byte size
    type_tmp = (char*)driver_alloc(type.size + 1);
    memset(type_tmp, 0, type.size + 1);
    memcpy(type_tmp, buf + index, type.size);
    index += type.size;
    /* decode domain */
    ei_decode_ei_term(buf, &index, &domain);
    if (domain.ei_type != ERL_BINARY_EXT) {
      driver_free(type_tmp);
      goto badarg;
    }
    index += 5; // skip tag + 4 byte size
    domain_tmp = (char *) driver_alloc(domain.size + 1);
    memset(domain_tmp, 0, domain.size + 1);
    memcpy(domain_tmp, buf + index, domain.size);
    err = DNSServiceBrowse(&dd->sd_ref,
			   0, // Flags
			   kDNSServiceInterfaceIndexAny,
			   type_tmp,
			   domain_tmp,
			   (DNSServiceBrowseReply) BrowseReply,
			   dd);
    driver_free(type_tmp);
    driver_free(domain_tmp);
  } else if (cmd == DNSSD_CMD_RESOLVE) {
    if (!arg.ei_type == ERL_TUPLE || arg.arity != 3) goto badarg;
    /* decode name */
    ei_decode_ei_term(buf, &index, &name);
    if (name.ei_type != ERL_BINARY_EXT) goto badarg;
    index += 5; // skip tag + 4 byte size
    name_tmp = (char *) driver_alloc(name.size + 1);
    memset(name_tmp, 0, name.size + 1);
    memcpy(name_tmp, buf + index, name.size);
    index += name.size;
    /* decode type */
    ei_decode_ei_term(buf, &index, &type);
    if (type.ei_type != ERL_BINARY_EXT) {
      driver_free(name_tmp);
      goto badarg;
    }
    index += 5; // skip tag + 4 byte size
    type_tmp = (char *) driver_alloc(type.size + 1);
    memset(type_tmp, 0, type.size + 1);
    memcpy(type_tmp, buf + index, type.size);
    index += type.size;
    /* decode domain */
    ei_decode_ei_term(buf, &index, &domain);
    if (domain.ei_type != ERL_BINARY_EXT) {
      driver_free(name_tmp);
      driver_free(type_tmp);
      goto badarg;
    }
    index += 5; // skip tag + 4 byte size
    domain_tmp = (char *) driver_alloc(domain.size + 1);
    memset(domain_tmp, 0, domain.size + 1);
    memcpy(domain_tmp, buf + index, domain.size);
    /* start op */
    err = DNSServiceResolve(&dd->sd_ref,
			    0, // Flags
			    kDNSServiceInterfaceIndexAny,
			    name_tmp,
			    type_tmp,
			    domain_tmp,
			    (DNSServiceResolveReply) ResolveReply,
			    dd);
    driver_free(name_tmp);
    driver_free(type_tmp);
    driver_free(domain_tmp);
  } else if (cmd == DNSSD_CMD_REGISTER) {
    if (!arg.ei_type == ERL_TUPLE || arg.arity != 6) goto badarg;
    /* decode name */
    ei_decode_ei_term(buf, &index, &name);
    if (name.ei_type != ERL_BINARY_EXT) goto badarg;
    index += 5; // skip tag + 4 byte size
    name_tmp = (char *) driver_alloc(name.size + 1);
    memset(name_tmp, 0, name.size + 1);
    memcpy(name_tmp, buf + index, name.size);
    index += name.size;
    /* decode type */
    ei_decode_ei_term(buf, &index, &type);
    if (type.ei_type != ERL_BINARY_EXT) {
      driver_free(name_tmp);
      goto badarg;
    }
    index += 5; // skip tag + 4 byte size
    type_tmp = (char *) driver_alloc(type.size + 1);
    memset(type_tmp, 0, type.size + 1);
    memcpy(type_tmp, buf + index, type.size);
    index += type.size;
    /* decode domain */
    ei_decode_ei_term(buf, &index, &domain);
    if (domain.ei_type != ERL_BINARY_EXT) {
      driver_free(name_tmp);
      driver_free(type_tmp);
      goto badarg;
    }
    index += 5; // skip tag + 4 byte size
    domain_tmp = (char *) driver_alloc(domain.size + 1);
    memset(domain_tmp, 0, domain.size + 1);
    memcpy(domain_tmp, buf + index, domain.size);
    index += domain.size;
    /* decode host */
    ei_decode_ei_term(buf, &index, &host);
    if (host.ei_type != ERL_BINARY_EXT) {
      driver_free(name_tmp);
      driver_free(type_tmp);
      driver_free(domain_tmp);
      goto badarg;
    }
    index += 5; // skip tag + 4 byte size
    host_tmp = (char *) driver_alloc(host.size + 1);
    memset(host_tmp, 0, host.size + 1);
    memcpy(host_tmp, buf + index, host.size);
    index += host.size;
    /* decode port */
    ei_decode_ei_term(buf, &index, &hostport);
    if (hostport.ei_type != ERL_INTEGER_EXT &&
	hostport.ei_type != ERL_SMALL_INTEGER_EXT) {
      driver_free(name_tmp);
      driver_free(type_tmp);
      driver_free(domain_tmp);
      driver_free(host_tmp);
      goto badarg;
    }
    /* decode txt */
    ei_decode_ei_term(buf, &index, &txt);
    if (txt.ei_type != ERL_BINARY_EXT) {
      driver_free(name_tmp);
      driver_free(type_tmp);
      driver_free(domain_tmp);
      driver_free(host_tmp);
      goto badarg;
    }
    index += 5; // skip tag + 4 byte size
    txt_tmp = (char *) driver_alloc(txt.size + 1);
    memset(txt_tmp, 0, txt.size + 1);
    memcpy(txt_tmp, buf + index, txt.size);
    local_only = (0 == strcmp("localhost", host_tmp));
    err = DNSServiceRegister(&dd->sd_ref,
			     0, // Flags
			     local_only ? -1 : 0, // Interface: local / any
			     name_tmp,
			     type_tmp,
			     local_only ? "local" : domain_tmp,
			     host_tmp,
			     htons(hostport.value.i_val),
			     txt.size,
			     txt_tmp,
			     (DNSServiceRegisterReply) RegisterReply,
			     dd);
    driver_free(name_tmp);
    driver_free(type_tmp);
    driver_free(domain_tmp);
    driver_free(host_tmp);
    driver_free(txt_tmp);
  } else {
    goto badarg;
  }
  rindex = 0;
  out_len = 0;
  ei_encode_version(NULL, &out_len);
  if (err == kDNSServiceErr_NoError) {
#ifdef __WIN32__
    dd->event = WSACreateEvent();
    WSAEventSelect(DNSServiceRefSockFD(dd->sd_ref), dd->event, FD_READ);
    driver_select(dd->erl_port, dd->event, ERL_DRV_READ, 1);
#else
    driver_select(dd->erl_port,
		  (ErlDrvEvent)(size_t) DNSServiceRefSockFD(dd->sd_ref),
		  ERL_DRV_READ,
		  1);
#endif
    out_atom_text = "ok";
    ei_encode_atom(NULL, &out_len, out_atom_text);
    if(rlen < out_len) {
      *rbuf = driver_alloc(out_len);
      rlen = out_len;
    }
    ei_encode_version(*rbuf, &rindex);
    ei_encode_atom(*rbuf, &rindex, out_atom_text);
    return out_len;
  } else {
    out_atom_text = "error";
    ei_encode_tuple_header(NULL, &out_len, 2);
    ei_encode_atom(NULL, &out_len, out_atom_text);
    ei_encode_long(NULL, &out_len, 1337);
    if(rlen < out_len) {
      *rbuf = driver_alloc(out_len);
      rlen = out_len;
    }
    ei_encode_version(*rbuf, &rindex);
    ei_encode_tuple_header(*rbuf, &rindex, 2);
    ei_encode_atom(*rbuf, &rindex, out_atom_text);
    ei_encode_long(*rbuf, &rindex, (long) err);
    return out_len;
  }
 badarg:
  return -1;
}