Example #1
0
static int wait_read(mailstream_low * s)
{
  fd_set fds_read;
  struct timeval timeout;
  int fd;
  struct mailstream_ssl_data * ssl_data;
  int max_fd;
  int r;
  int cancelled;
  int got_data;
#ifdef WIN32
  HANDLE event;
#endif
  
  ssl_data = (struct mailstream_ssl_data *) s->data;
  if (s->timeout == 0) {
    timeout = mailstream_network_delay;
  }
  else {
		timeout.tv_sec = s->timeout;
    timeout.tv_usec = 0;
  }
  
#ifdef USE_GNUTLS
  if (gnutls_record_check_pending(ssl_data->session) != 0)
    return 0;
#endif

  FD_ZERO(&fds_read);
  fd = mailstream_cancel_get_fd(ssl_data->cancel);
  FD_SET(fd, &fds_read);
#ifdef WIN32
  event = CreateEvent(NULL, TRUE, FALSE, NULL);
  WSAEventSelect(ssl_data->fd, event, FD_READ | FD_CLOSE);
  FD_SET(event, &fds_read);
  r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
  if (WAIT_TIMEOUT == r) {
		WSAEventSelect(ssl_data->fd, event, 0);
		CloseHandle(event);
    return -1;
	}
  
  cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == fd);
  got_data = (fds_read.fd_array[r - WAIT_OBJECT_0] == event);
	WSAEventSelect(ssl_data->fd, event, 0);
	CloseHandle(event);
#else
  FD_SET(ssl_data->fd, &fds_read);
  max_fd = ssl_data->fd;
  if (fd > max_fd)
    max_fd = fd;
  r = select(max_fd + 1, &fds_read, NULL, NULL, &timeout);
  if (r <= 0)
    return -1;
  
  cancelled = (FD_ISSET(fd, &fds_read));
  got_data = FD_ISSET(ssl_data->fd, &fds_read);
#endif
  if (cancelled) {
    /* cancelled */
    mailstream_cancel_ack(ssl_data->cancel);
    return -1;
  }
  
  return 0;
}
Example #2
0
static int wait_write(mailstream_low * s)
{
  fd_set fds_read;
  fd_set fds_write;
  struct timeval timeout;
  int r;
  int fd;
  struct mailstream_ssl_data * ssl_data;
  int max_fd;
  int cancelled;
  int write_enabled;
#ifdef WIN32
  HANDLE event;
#endif
  
  ssl_data = (struct mailstream_ssl_data *) s->data;
  if (mailstream_cancel_cancelled(ssl_data->cancel))
    return -1;
 
  if (s->timeout == 0) {
    timeout = mailstream_network_delay;
  }
  else {
		timeout.tv_sec = s->timeout;
    timeout.tv_usec = 0;
  }
  
  FD_ZERO(&fds_read);
  fd = mailstream_cancel_get_fd(ssl_data->cancel);
  FD_SET(fd, &fds_read);
  FD_ZERO(&fds_write);
#ifdef WIN32
  event = CreateEvent(NULL, TRUE, FALSE, NULL);
  WSAEventSelect(ssl_data->fd, event, FD_WRITE | FD_CLOSE);
  FD_SET(event, &fds_read);
  r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
  if (r < 0) {
		WSAEventSelect(ssl_data->fd, event, 0);
		CloseHandle(event);
    return -1;
	}
  
  cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == fd) /* SEB 20070709 */;
  write_enabled = (fds_read.fd_array[r - WAIT_OBJECT_0] == event);
	WSAEventSelect(ssl_data->fd, event, 0);
	CloseHandle(event);
#else
  FD_SET(ssl_data->fd, &fds_write);
  
  max_fd = ssl_data->fd;
  if (fd > max_fd)
    max_fd = fd;
  
  r = select(max_fd + 1, &fds_read, &fds_write, NULL, &timeout);
  if (r <= 0)
    return -1;
  
  cancelled = FD_ISSET(fd, &fds_read);
  write_enabled = FD_ISSET(ssl_data->fd, &fds_write);
#endif
  
  if (cancelled) {
    /* cancelled */
    mailstream_cancel_ack(ssl_data->cancel);
    return -1;
  }
  
  if (!write_enabled)
    return 0;
  
  return 1;
}
Example #3
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 ansychronous 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;
}
Example #4
0
int
poll (struct pollfd *pfd, nfds_t nfd, int timeout)
{
#ifndef WINDOWS_NATIVE
    fd_set rfds, wfds, efds;
    struct timeval tv;
    struct timeval *ptv;
    int maxfd, rc;
    nfds_t i;

    if (nfd < 0)
    {
        errno = EINVAL;
        return -1;
    }
    /* Don't check directly for NFD too large.  Any practical use of a
       too-large NFD is caught by one of the other checks below, and
       checking directly for getdtablesize is too much of a portability
       and/or performance and/or correctness hassle.  */

    /* EFAULT is not necessary to implement, but let's do it in the
       simplest case. */
    if (!pfd && nfd)
    {
        errno = EFAULT;
        return -1;
    }

    /* convert timeout number into a timeval structure */
    if (timeout == 0)
    {
        ptv = &tv;
        ptv->tv_sec = 0;
        ptv->tv_usec = 0;
    }
    else if (timeout > 0)
    {
        ptv = &tv;
        ptv->tv_sec = timeout / 1000;
        ptv->tv_usec = (timeout % 1000) * 1000;
    }
    else if (timeout == INFTIM)
        /* wait forever */
        ptv = NULL;
    else
    {
        errno = EINVAL;
        return -1;
    }

    /* create fd sets and determine max fd */
    maxfd = -1;
    FD_ZERO (&rfds);
    FD_ZERO (&wfds);
    FD_ZERO (&efds);
    for (i = 0; i < nfd; i++)
    {
        if (pfd[i].fd < 0)
            continue;
        if (maxfd < pfd[i].fd)
        {
            maxfd = pfd[i].fd;
            if (FD_SETSIZE <= maxfd)
            {
                errno = EINVAL;
                return -1;
            }
        }
        if (pfd[i].events & (POLLIN | POLLRDNORM))
            FD_SET (pfd[i].fd, &rfds);
        /* see select(2): "the only exceptional condition detectable
           is out-of-band data received on a socket", hence we push
           POLLWRBAND events onto wfds instead of efds. */
        if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
            FD_SET (pfd[i].fd, &wfds);
        if (pfd[i].events & (POLLPRI | POLLRDBAND))
            FD_SET (pfd[i].fd, &efds);
    }

    /* examine fd sets */
    rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
    if (rc < 0)
        return rc;

    /* establish results */
    rc = 0;
    for (i = 0; i < nfd; i++)
    {
        pfd[i].revents = (pfd[i].fd < 0
                          ? 0
                          : compute_revents (pfd[i].fd, pfd[i].events,
                                             &rfds, &wfds, &efds));
        rc += pfd[i].revents != 0;
    }

    return rc;
#else
    static struct timeval tv0;
    static HANDLE hEvent;
    WSANETWORKEVENTS ev;
    HANDLE h, handle_array[FD_SETSIZE + 2];
    DWORD ret, wait_timeout, nhandles;
    fd_set rfds, wfds, xfds;
    BOOL poll_again;
    MSG msg;
    int rc = 0;
    nfds_t i;

    if (nfd < 0 || timeout < -1)
    {
        errno = EINVAL;
        return -1;
    }

    if (!hEvent)
        hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);

restart:
    handle_array[0] = hEvent;
    nhandles = 1;
    FD_ZERO (&rfds);
    FD_ZERO (&wfds);
    FD_ZERO (&xfds);

    /* Classify socket handles and create fd sets. */
    for (i = 0; i < nfd; i++)
    {
        int sought = pfd[i].events;
        pfd[i].revents = 0;
        if (pfd[i].fd < 0)
            continue;
        if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
                        | POLLPRI | POLLRDBAND)))
            continue;

        h = (HANDLE) _get_osfhandle (pfd[i].fd);
        assure (h != NULL);
        if (IsSocketHandle (h))
        {
            int requested = FD_CLOSE;

            /* see above; socket handles are mapped onto select.  */
            if (sought & (POLLIN | POLLRDNORM))
            {
                requested |= FD_READ | FD_ACCEPT;
                FD_SET ((SOCKET) h, &rfds);
            }
            if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
            {
                requested |= FD_WRITE | FD_CONNECT;
                FD_SET ((SOCKET) h, &wfds);
            }
            if (sought & (POLLPRI | POLLRDBAND))
            {
                requested |= FD_OOB;
                FD_SET ((SOCKET) h, &xfds);
            }

            if (requested)
                WSAEventSelect ((SOCKET) h, hEvent, requested);
        }
        else
        {
            /* Poll now.  If we get an event, do not poll again.  Also,
               screen buffer handles are waitable, and they'll block until
               a character is available.  windows_compute_revents eliminates
               bits for the "wrong" direction. */
            pfd[i].revents = windows_compute_revents (h, &sought);
            if (sought)
                handle_array[nhandles++] = h;
            if (pfd[i].revents)
                timeout = 0;
        }
    }

    if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
    {
        /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
           no need to call select again.  */
        poll_again = FALSE;
        wait_timeout = 0;
    }
    else
    {
        poll_again = TRUE;
        if (timeout == INFTIM)
            wait_timeout = INFINITE;
        else
            wait_timeout = timeout;
    }

    for (;;)
    {
        ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
                                         wait_timeout, QS_ALLINPUT);

        if (ret == WAIT_OBJECT_0 + nhandles)
        {
            /* new input of some other kind */
            BOOL bRet;
            while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
            {
                TranslateMessage (&msg);
                DispatchMessage (&msg);
            }
        }
        else
            break;
    }

    if (poll_again)
        select (0, &rfds, &wfds, &xfds, &tv0);

    /* Place a sentinel at the end of the array.  */
    handle_array[nhandles] = NULL;
    nhandles = 1;
    for (i = 0; i < nfd; i++)
    {
        int happened;

        if (pfd[i].fd < 0)
            continue;
        if (!(pfd[i].events & (POLLIN | POLLRDNORM |
                               POLLOUT | POLLWRNORM | POLLWRBAND)))
            continue;

        h = (HANDLE) _get_osfhandle (pfd[i].fd);
        if (h != handle_array[nhandles])
        {
            /* It's a socket.  */
            WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
            WSAEventSelect ((SOCKET) h, 0, 0);

            /* If we're lucky, WSAEnumNetworkEvents already provided a way
               to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */
            if (FD_ISSET ((SOCKET) h, &rfds)
                    && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
                ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
            if (FD_ISSET ((SOCKET) h, &wfds))
                ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
            if (FD_ISSET ((SOCKET) h, &xfds))
                ev.lNetworkEvents |= FD_OOB;

            happened = windows_compute_revents_socket ((SOCKET) h, pfd[i].events,
                       ev.lNetworkEvents);
        }
        else
        {
            /* Not a socket.  */
            int sought = pfd[i].events;
            happened = windows_compute_revents (h, &sought);
            nhandles++;
        }

        if ((pfd[i].revents |= happened) != 0)
            rc++;
    }

    if (!rc && timeout == INFTIM)
    {
        SleepEx (1, TRUE);
        goto restart;
    }

    return rc;
#endif
}
Example #5
0
BOOL 
CUdpCommClient::Init()
{
	//
	if (FALSE == CThreadClient::Init())
	{
		return FALSE;
	}

	//
	if (FALSE == m_bSockLibFlag)
	{
		return FALSE;
	}

	//
	m_tTimeout = time(NULL);

	//
	if (NULL == m_hQuit)
	{
		m_nErrorCode = GetLastError();
		HandleError(OCFCLIENT_ERROR_WINSOCK, m_nErrorCode, 0xFF, 0, NULL);
		return FALSE;
	}

	//
	if (NULL == m_hWrEvent)
	{
		m_nErrorCode = GetLastError();
		HandleError(OCFCLIENT_ERROR_WINSOCK, m_nErrorCode, 0xFF, 0, NULL);
		return FALSE;
	}

	//
	// 일단 UDP로 
	//
	m_dSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (INVALID_SOCKET == m_dSock)
	{
		m_nErrorCode = WSAGetLastError();
		HandleError(OCFCLIENT_ERROR_WINSOCK, m_nErrorCode, 0xFF, 0, NULL);
		return FALSE;
	}

	//
	if (FALSE == UdpFixBind())
	{
		return FALSE;
	}


	//... SOO SOCKET BUFF SIZING : 
//  	m_ulRcvBuff = 1024 * 1024 * 1000;
//  	m_ulSndBuff = 1024 * 1024 * 1000;

	//
	if (SOCKET_ERROR == setsockopt(m_dSock, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char*>(&m_ulRcvBuff), sizeof(m_ulRcvBuff)))
	{
		m_nErrorCode = WSAGetLastError();
		HandleError(OCFCLIENT_ERROR_WINSOCK, m_nErrorCode, 0xFF, 0, NULL);
	}
	
	//
	if (SOCKET_ERROR == setsockopt(m_dSock, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char*>(&m_ulSndBuff), sizeof(m_ulSndBuff)))
	{
		m_nErrorCode = WSAGetLastError();
		HandleError(OCFCLIENT_ERROR_WINSOCK, m_nErrorCode, 0xFF, 0, NULL);
	}
	
	//
	int nLenVariable = sizeof(m_ulMaxSndPktLen);
	if (SOCKET_ERROR == getsockopt(m_dSock, SOL_SOCKET, SO_MAX_MSG_SIZE, reinterpret_cast<char*>(&m_ulMaxSndPktLen), &nLenVariable))
	{
		m_nErrorCode = WSAGetLastError();
		HandleError(OCFCLIENT_ERROR_WINSOCK, m_nErrorCode, 0xFF, 0, NULL);
		return FALSE;
	}

	//
	if (FALSE == m_cRecvChunk.Ext(m_ulMaxRcvPktLen + 1))
	{
		m_nErrorCode = WSAGetLastError();
		HandleError(OCFCLIENT_ERROR_USERDEF, OCFCLIENT_ERROR_USERDEF_CATEGORY_MEMORY, 0xFF, 0, NULL);
		return FALSE;
	}

	//
	m_hSockEvent = WSACreateEvent();
	if (WSA_INVALID_EVENT == m_hSockEvent)
	{
		m_nErrorCode = WSAGetLastError();
		HandleError(OCFCLIENT_ERROR_WINSOCK, m_nErrorCode, 0xFF, 0, NULL);
		return FALSE;
	}

	//
	// Only For UDP
	//
	if (WSAEventSelect(m_dSock, m_hSockEvent, FD_READ | FD_WRITE) == SOCKET_ERROR)
	{
		m_nErrorCode = WSAGetLastError();
		HandleError(OCFCLIENT_ERROR_WINSOCK, m_nErrorCode, 0xFF, 0, NULL);
		return FALSE;
	}

	//
	m_bConnectFlag = TRUE;
	m_bWouldBlock = FALSE;

	return TRUE;
}
Example #6
0
void Network::Begin (void) 
{
	// an alternative to select() is to use Windows events; first create a regular auto-reset event
	HANDLE eventSocketReady =  CreateEvent (NULL, false, false, NULL);
	// second, register sock_in with the event using FD_READ notifications only (i.e., available for READ)
	WSAEventSelect(sock_in, eventSocketReady, FD_READ);	// associate event with socket

	char buf [MAX_PKT_SIZE];
	DWORD timeout = INFINITE;  //infinite timeout

	while (true)
	{
		int ret;
		
		if (timeout != 0)
			ret = WaitForSingleObject (eventSocketReady, timeout);// either a timeout occurs or something is pending inside sock_in
		
		double cur_time = m->GetTime();
			
		// packets are ready to be extracted?
		if (timeout == 0 || ret == WAIT_TIMEOUT)
		{
			// examine the front packet
			Packet head = Q.front();

			// can be tranmitted right now?
			while (head.d <= cur_time)
			{
				// remove from the queue
				Q.pop_front();

				// generate random number to decide reordering
				double u = (double)rand()/RAND_MAX; 	// u in [0,1]

				// reorder with probability P_REORDER, but only if the queue is non-empty
				// note: this code can reorder the same packet multiple times, but each time by one position
				// to disable multiple reorderings of the same packet, uncomment the statement below
				if (u < p_reorder && Q.size() > 0)// && head.has_been_reordered == false)	
				{
					m->printf ("[%f] Network: reordered pkt of size %d, message %d\n", m->ElapsedTime(), head.pkt_size, *(int*)head.pkt_data);
					head.has_been_reordered = true;

					// swap this packet with the next one
					Packet tmp;
					// save the current packet
					memcpy (&tmp, &head, sizeof (Packet));
					// take the next one
					head = Q.front();
					Q.pop_front();
					// store the old one in its place
					Q.push_front (tmp);
				}

				// printf takes 1.9 ms to execute, this will normally delay transmission of packets that follow if the sending rate is high;
				// disable all printfs for high-speed transfers, or they will become the bottleneck
				m->printf ("[%f] Network: sent message %d, scheduled %f\n", m->ElapsedTime(), *(int*)head.pkt_data, m->RelativeTime(head.d));

				// send to destination
				sendto (sock_out, head.pkt_data, head.pkt_size, 0, 
					(struct sockaddr*) &destination, sizeof(struct sockaddr_in));

				delete head.pkt_data;
				
				// if there is still stuff in the queue, see if it needs to be transmitted
				if (Q.size() > 0)
					head = Q.front();		// peek at the next packet
				else
					break;
			}
		}
		else	// data in socket
		{
			int bytes = recv (sock_in, buf, MAX_PKT_SIZE, 0);

			if (bytes == SOCKET_ERROR)
			{
					m->printf ("[%f] Network: recvfrom error %d\n", m->ElapsedTime(), WSAGetLastError());
					exit (-1);
			}
			else
			{
				// lose this pkt with probability p_loss
				double u = (double)rand()/RAND_MAX; 	// u in [0,1]
				
				if (u >= p_loss)			
				{
					// keep the packet
					Packet new_pkt;

					// create a new pkt entry
					new_pkt.pkt_data = new char [bytes];
					memcpy (new_pkt.pkt_data, buf, bytes);
					new_pkt.pkt_size = bytes;
					new_pkt.has_been_reordered = false;

					// add it to the queue
					PushInNetworkQueue (new_pkt);
				}
				else
					m->printf ("[%f] Network: dropped pkt of size %d, message %d\n", m->ElapsedTime(), bytes, *(int*)buf);
			}
		}

		// recompute the sleep delay
		if (Q.size() > 0)	
		{
			// if the queue is not empty, figure out how much to sleep
			double cur_time = m->GetTime();
			if (Q.front().d > cur_time)
				timeout = (DWORD)floor( (Q.front().d - cur_time) * 1000.0 + 0.5);		// round to the nearest integer ms
			else		// do not sleep
				timeout = 0;
		}
		else			// queue is empty, sleep forever
			timeout = INFINITE;
	}
}
Example #7
0
unsigned __stdcall I4C3DAcceptedThreadProc(void* pParam)
{
    LoggingMessage(Log_Debug, _T(MESSAGE_DEBUG_PROCESSING), GetLastError(), g_FILE, __LINE__);

    I4C3DChildContext* pChildContext = (I4C3DChildContext*)pParam;

    I4C3DUDPPacket packet = {0};
    const SIZE_T packetBufferSize = sizeof(packet.szCommand);

    SIZE_T totalRecvBytes = 0;
    int nBytes = 0;
    BOOL bBreak = FALSE;

    DWORD dwResult = 0;
    WSAEVENT hEvent = NULL;
    WSAEVENT hEventArray[2] = {0};
    WSANETWORKEVENTS events = {0};

    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (hEvent == NULL) {
        LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);

        shutdown(pChildContext->clientSocket, SD_SEND);
        recv(pChildContext->clientSocket, packet.szCommand, packetBufferSize, 0);
        shutdown(pChildContext->clientSocket, SD_BOTH);
        closesocket(pChildContext->clientSocket);

        RemoveChildThread( pChildContext->hChildThread );
        free(pChildContext);
        return EXIT_FAILURE;
    }
    WSAEventSelect(pChildContext->clientSocket, hEvent, FD_READ | FD_CLOSE);

    hEventArray[0] = hEvent;
    hEventArray[1] = pChildContext->pContext->hStopEvent;

    FillMemory(packet.szCommand, packetBufferSize, 0xFF);
    while (!bBreak) {
        if (!CheckNetworkEventError(events)) {
            break;
        }

        dwResult = WSAWaitForMultipleEvents(2, hEventArray, FALSE, WSA_INFINITE, FALSE);

        DEBUG_PROFILE_MONITOR;

        if (dwResult == WSA_WAIT_FAILED) {
            LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);
            break;
        }

        if (dwResult - WSA_WAIT_EVENT_0 == 0) {
            if (WSAEnumNetworkEvents(pChildContext->clientSocket, hEvent, &events) != 0) {
                LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);
                break;
            }

            if (events.lNetworkEvents & FD_CLOSE) {
                break;

            } else if (events.lNetworkEvents & FD_READ) {
                nBytes = recv(pChildContext->clientSocket, packet.szCommand + totalRecvBytes, packetBufferSize - totalRecvBytes, 0);

                if (nBytes == SOCKET_ERROR) {
                    if (WSAGetLastError() == WSAEWOULDBLOCK) {
                        continue;
                    } else {
                        LoggingMessage(Log_Error, _T(MESSAGE_ERROR_SOCKET_RECV), WSAGetLastError(), g_FILE, __LINE__);
                    }
                    break;

                } else if (nBytes > 0) {

                    totalRecvBytes += nBytes;
                    PCSTR pTermination = (PCSTR)memchr(packet.szCommand, pChildContext->cTermination, totalRecvBytes);

                    // 終端文字が見つからない場合、バッファをクリア
                    if (pTermination == NULL) {
                        if (totalRecvBytes >= packetBufferSize) {
                            FillMemory(packet.szCommand, packetBufferSize, 0xFF);
                            totalRecvBytes = 0;
                        }
                        continue;
                    }

                    do {

                        DEBUG_PROFILE_MONITOR;

                        // プラグインへ電文転送
                        pChildContext->pContext->pController->Execute(&packet, pTermination-packet.szCommand+1);

                        volatile int i;
                        for (i = 0; i < g_sleepCount; ++i) {
                            Sleep(1);
                        }

                        //} else {
                        //	// Hotkey
                        //	MoveMemory(szCommand, recvBuffer, pTermination-recvBuffer);
                        //	szCommand[pTermination-recvBuffer] = '\0';
                        //	EnterCriticalSection(&g_Lock);
                        //	pChildContext->pContext->pController->Execute(pChildContext->pContext, &delta, szCommand);
                        //	LeaveCriticalSection(&g_Lock);
                        //}

                        if (pTermination == (packet.szCommand + totalRecvBytes - 1)) {
                            FillMemory(packet.szCommand, packetBufferSize, 0xFF);
                            totalRecvBytes = 0;

                        } else if (pTermination < (packet.szCommand + totalRecvBytes - 1)) {
                            int nCopySize = packetBufferSize - (pTermination - packet.szCommand + 1);

                            totalRecvBytes -= (pTermination - packet.szCommand + 1);
                            MoveMemory(packet.szCommand, pTermination+1, nCopySize);
                            FillMemory(packet.szCommand + nCopySize, packetBufferSize - nCopySize, 0xFF);

                        } else {
                            bBreak = TRUE;
                            LoggingMessage(Log_Error, _T(MESSAGE_ERROR_MESSAGE_INVALID), GetLastError(), g_FILE, __LINE__);
                            break;
                        }

                        DEBUG_PROFILE_MONITOR;

                    } while ((pTermination = (LPCSTR)memchr(packet.szCommand, pChildContext->cTermination, totalRecvBytes)) != NULL);

                    DEBUG_PROFILE_MONITOR;
                }

            }

        } else if (dwResult - WSA_WAIT_EVENT_0 == 1) {
            // pChildContext->pContext->hStopEvent に終了イベントがセットされた
            break;
        }

    }
    SafeCloseHandle(hEvent);

    // closesocket
    shutdown(pChildContext->clientSocket, SD_SEND);
    recv(pChildContext->clientSocket, packet.szCommand, packetBufferSize, 0);
    shutdown(pChildContext->clientSocket, SD_BOTH);
    closesocket(pChildContext->clientSocket);

    RemoveChildThread( pChildContext->hChildThread );
    free(pChildContext);

    LoggingMessage(Log_Debug, _T(MESSAGE_DEBUG_PROCESSING), GetLastError(), g_FILE, __LINE__);

    return EXIT_SUCCESS;
}
Example #8
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);
}
Example #9
0
/* callback from ares when socket operation is started */
static void uv_ares_sockstate_cb(void *data, ares_socket_t sock, int read,
    int write) {
  /* look to see if we have a handle for this socket in our list */
  uv_loop_t* loop = (uv_loop_t*) data;
  uv_ares_task_t* uv_handle_ares = uv_find_ares_handle(loop, sock);

  int timeoutms = 0;

  if (read == 0 && write == 0) {
    /* if read and write are 0, cleanup existing data */
    /* The code assumes that c-ares does a callback with read = 0 and */
    /* write = 0 when the socket is closed. After we recieve this we stop */
    /* monitoring the socket. */
    if (uv_handle_ares != NULL) {
      uv_req_t* uv_ares_req;

      uv_handle_ares->h_close_event = CreateEvent(NULL, FALSE, FALSE, NULL);
      /* remove Wait */
      if (uv_handle_ares->h_wait) {
        UnregisterWaitEx(uv_handle_ares->h_wait,
                         uv_handle_ares->h_close_event);
        uv_handle_ares->h_wait = NULL;
      }

      /* detach socket from the event */
      WSAEventSelect(sock, NULL, 0);
      if (uv_handle_ares->h_event != WSA_INVALID_EVENT) {
        WSACloseEvent(uv_handle_ares->h_event);
        uv_handle_ares->h_event = WSA_INVALID_EVENT;
      }
      /* remove handle from list */
      uv_remove_ares_handle(uv_handle_ares);

      /* Post request to cleanup the Task */
      uv_ares_req = &uv_handle_ares->ares_req;
      uv_req_init(loop, uv_ares_req);
      uv_ares_req->type = UV_ARES_CLEANUP_REQ;
      uv_ares_req->data = uv_handle_ares;

      /* post ares done with socket - finish cleanup when all threads done. */
      POST_COMPLETION_FOR_REQ(loop, uv_ares_req);
    } else {
      assert(0);
      uv_fatal_error(ERROR_INVALID_DATA, "ares_SockStateCB");
    }
  } else {
    if (uv_handle_ares == NULL) {
      /* setup new handle */
      /* The code assumes that c-ares will call us when it has an open socket.
        We need to call into c-ares when there is something to read,
        or when it becomes writable. */
      uv_handle_ares = (uv_ares_task_t*)malloc(sizeof(uv_ares_task_t));
      if (uv_handle_ares == NULL) {
        uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
      }
      uv_handle_ares->type = UV_ARES_TASK;
      uv_handle_ares->close_cb = NULL;
      uv_handle_ares->data = loop;
      uv_handle_ares->sock = sock;
      uv_handle_ares->h_wait = NULL;
      uv_handle_ares->flags = 0;

      /* create an event to wait on socket signal */
      uv_handle_ares->h_event = WSACreateEvent();
      if (uv_handle_ares->h_event == WSA_INVALID_EVENT) {
        uv_fatal_error(WSAGetLastError(), "WSACreateEvent");
      }

      /* tie event to socket */
      if (SOCKET_ERROR == WSAEventSelect(sock,
                                         uv_handle_ares->h_event,
                                         FD_READ | FD_WRITE | FD_CONNECT)) {
        uv_fatal_error(WSAGetLastError(), "WSAEventSelect");
      }

      /* add handle to list */
      uv_add_ares_handle(loop, uv_handle_ares);
      uv_ref(loop);

      /*
       * we have a single polling timer for all ares sockets.
       * This is preferred to using ares_timeout. See ares_timeout.c warning.
       * if timer is not running start it, and keep socket count
       */
      if (loop->ares_active_sockets == 0) {
        uv_timer_init(loop, &loop->ares_polling_timer);
        uv_timer_start(&loop->ares_polling_timer, uv_ares_poll, 1000L, 1000L);
      }
      loop->ares_active_sockets++;

      /* specify thread pool function to call when event is signaled */
      if (RegisterWaitForSingleObject(&uv_handle_ares->h_wait,
                                  uv_handle_ares->h_event,
                                  uv_ares_socksignal_tp,
                                  (void*)uv_handle_ares,
                                  INFINITE,
                                  WT_EXECUTEINWAITTHREAD) == 0) {
        uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject");
      }
    } else {
      /* found existing handle.  */
      assert(uv_handle_ares->type == UV_ARES_TASK);
      assert(uv_handle_ares->data != NULL);
      assert(uv_handle_ares->h_event != WSA_INVALID_EVENT);
    }
  }
}
Example #10
0
int WEventSocket::EventSelect(long events)
{
	return WSAEventSelect(m_hSocket,m_hEvent,events);
}
Example #11
0
static ssize_t mailstream_low_socket_read(mailstream_low * s,
					  void * buf, size_t count)
{
  struct mailstream_socket_data * socket_data;
  
  socket_data = (struct mailstream_socket_data *) s->data;

  if (mailstream_cancel_cancelled(socket_data->cancel))
    return -1;
  
  /* timeout */
  {
    fd_set fds_read;
    struct timeval timeout;
    int r;
    int fd;
    int cancelled;
    int got_data;
#ifdef WIN32
    HANDLE event;
#else
    int max_fd;
#endif
    
    if (s->timeout == 0) {
      timeout = mailstream_network_delay;
    }
    else {
			timeout.tv_sec = s->timeout;
      timeout.tv_usec = 0;
    }
    
    FD_ZERO(&fds_read);
    fd = mailstream_cancel_get_fd(socket_data->cancel);
    FD_SET(fd, &fds_read);
    
#ifdef WIN32
    event = CreateEvent(NULL, TRUE, FALSE, NULL);
    WSAEventSelect(socket_data->fd, event, FD_READ | FD_CLOSE);
    FD_SET(event, &fds_read);
    r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
    if (WAIT_TIMEOUT == r) {
			WSAEventSelect(socket_data->fd, event, 0);
			CloseHandle(event);
      return -1;
		}
    
    cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == fd);
    got_data = (fds_read.fd_array[r - WAIT_OBJECT_0] == event);
		WSAEventSelect(socket_data->fd, event, 0);
		CloseHandle(event);
#else
    FD_SET(socket_data->fd, &fds_read);
    max_fd = socket_data->fd;
    if (fd > max_fd)
      max_fd = fd;
    r = select(max_fd + 1, &fds_read, NULL,/* &fds_excp*/ NULL, &timeout);
    if (r <= 0)
      return -1;
    
    cancelled = FD_ISSET(fd, &fds_read);
    got_data = FD_ISSET(socket_data->fd, &fds_read);
#endif
    
    if (cancelled) {
      /* cancelled */
      mailstream_cancel_ack(socket_data->cancel);
      return -1;
    }
    
    if (!got_data)
      return 0;
  }
  
  if (socket_data->use_read) {
    return read(socket_data->fd, buf, count);
  }
  else {
    return recv(socket_data->fd, buf, count, 0);
  }
}
Example #12
0
// Use the socket in the CHandshakes object to listen for remote computers who want to connect to us
// Returns true if we're listening, false if it didn't work
BOOL CHandshakes::Listen()
{
	if ( IsValid() )
		return TRUE;

	// Make sure only one thread can execute the code of this method at a time
	CSingleLock pLock( &m_pSection, TRUE ); // When the method exits, local pLock will be destructed, and the lock released

	m_hSocket = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
	if ( ! IsValid() )	// Now, make sure it has been created
	{
		theApp.Message( MSG_ERROR, _T("Failed to create TCP socket. (1st Try)") );
		// Second attempt
		m_hSocket = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
		if ( ! IsValid() )
		{
			theApp.Message( MSG_ERROR, _T("Failed to create TCP socket. (2nd Try)") );
			return FALSE;
		}
	}

	// Disables the Nagle algorithm for send coalescing
	VERIFY( setsockopt( m_hSocket, IPPROTO_TCP, TCP_NODELAY, "\x01", 1) == 0 );

	// Get our computer's Internet IP address and port number from the network object
	SOCKADDR_IN saHost = Network.m_pHost; // This is the address of our computer as visible to remote computers on the Internet

	// If the program connection settings disallow binding, zero the 4 bytes of the IP address
	if ( ! Settings.Connection.InBind ) 
		saHost.sin_addr.s_addr = INADDR_ANY; // s_addr is the IP address formatted as a single u_long
	else
	{
		// Set the exclusive address option
		VERIFY( setsockopt( m_hSocket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, "\x01", 1 ) == 0 );
	}

	// First attempt to bind socket
	if ( bind( m_hSocket, (SOCKADDR*)&saHost, sizeof( saHost ) ) != 0 )
	{
		theApp.Message( MSG_ERROR, IDS_NETWORK_CANT_LISTEN, (LPCTSTR)CString( inet_ntoa( saHost.sin_addr ) ), htons( saHost.sin_port ) );

		if ( saHost.sin_addr.s_addr == INADDR_ANY )
			return FALSE;

		// Second attempt to bind socket
		saHost.sin_addr.s_addr = INADDR_ANY;
		if ( bind( m_hSocket, (SOCKADDR*)&saHost, sizeof( saHost ) ) != 0 )
		{
			theApp.Message( MSG_ERROR, IDS_NETWORK_CANT_LISTEN, (LPCTSTR)CString( inet_ntoa( saHost.sin_addr ) ), htons( saHost.sin_port ) );
			return FALSE;
		}
	}

	// Report that we are now listening on our IP address
	theApp.Message( MSG_INFO, IDS_NETWORK_LISTENING_TCP, (LPCTSTR)CString( inet_ntoa( saHost.sin_addr ) ), htons( saHost.sin_port ) );

	// Set it up so that when a remote computer connects to us, the m_pWakeup event is fired
	WSAEventSelect(		// Specify an event object to associate with the specified set of FD_XXX network events
		m_hSocket,		// Our listening socket
		GetWakeupEvent(),		// Our event, a CEvent object member variable
		FD_ACCEPT );	// The network event to trigger this is us accepting a remote computer's connection

	// Have the socket wait, listening for remote computer on the Internet to connect to it
	listen(			// Place a socket in a state in which it is listening for an incoming connection
		m_hSocket,	// Our socket
		256 );		// Maximum length of the queue of pending connections, let 256 computers try to call us at once (do)

	Network.AcquireLocalAddress( m_hSocket );

	// Create a new thread to run the ThreadStart method, passing it a pointer to this C
	return BeginThread( "Handshakes" );
}
Example #13
0
    void Run()
	{
		break_ = false;

		// prepare the window events which we use to wake up on incoming data
		// we use this instead of select() primarily to support the AsyncBreak()
		// mechanism.

		std::vector<HANDLE> events( socketListeners_.size() + 1, 0 );
		int j=0;
		for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
				i != socketListeners_.end(); ++i, ++j ){

			HANDLE event = CreateEvent( NULL, FALSE, FALSE, NULL );
			WSAEventSelect( i->second->impl_->Socket(), event, FD_READ ); // note that this makes the socket non-blocking which is why we can safely call RecieveFrom() on all sockets below
			events[j] = event;
		}


		events[ socketListeners_.size() ] = breakEvent_; // last event in the collection is the break event


		// configure the timer queue
		double currentTimeMs = GetCurrentTimeMs();

		// expiry time ms, listener
		std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
		for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
				i != timerListeners_.end(); ++i )
			timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
		std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );

		const int MAX_BUFFER_SIZE = 4098;
		char *data = new char[ MAX_BUFFER_SIZE ];
		IpEndpointName remoteEndpoint;

		while( !break_ ){

			currentTimeMs = GetCurrentTimeMs();

            DWORD waitTime = INFINITE;
            if( !timerQueue_.empty() ){

                waitTime = (DWORD)( timerQueue_.front().first >= currentTimeMs
                            ? timerQueue_.front().first - currentTimeMs
                            : 0 );
            }

			DWORD waitResult = WaitForMultipleObjects( (DWORD)socketListeners_.size() + 1, &events[0], FALSE, waitTime );
			if( break_ )
				break;

			if( waitResult != WAIT_TIMEOUT ){
				for( int i = waitResult - WAIT_OBJECT_0; i < (int)socketListeners_.size(); ++i ){
					int size = socketListeners_[i].second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
					if( size > 0 ){
						socketListeners_[i].first->ProcessPacket( data, size, remoteEndpoint );
						if( break_ )
							break;
					}
				}
			}

			// execute any expired timers
			currentTimeMs = GetCurrentTimeMs();
			bool resort = false;
			for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
					i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){

				i->second.listener->TimerExpired();
				if( break_ )
					break;

				i->first += i->second.periodMs;
				resort = true;
			}
			if( resort )
				std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
		}

		delete [] data;

		// free events
		j = 0;
		for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
				i != socketListeners_.end(); ++i, ++j ){

			WSAEventSelect( i->second->impl_->Socket(), events[j], 0 ); // remove association between socket and event
			CloseHandle( events[j] );
			unsigned long enableNonblocking = 0;
			ioctlsocket( i->second->impl_->Socket(), FIONBIO, &enableNonblocking );  // make the socket blocking again
		}
	}