Beispiel #1
0
void printError(const wchar_t *msg)
{
    wprintf(L"%s error:%ld\n", msg,  WSAGetLastError());
}
Beispiel #2
0
static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
  uv_read_t* req;
  uv_buf_t buf;
  int result;
  DWORD bytes, flags;

  assert(handle->flags & UV_HANDLE_READING);
  assert(!(handle->flags & UV_HANDLE_READ_PENDING));

  req = &handle->read_req;
  memset(&req->overlapped, 0, sizeof(req->overlapped));

  /*
   * Preallocate a read buffer if the number of active streams is below
   * the threshold.
  */
  if (loop->active_tcp_streams < uv_active_tcp_streams_threshold) {
    handle->flags &= ~UV_HANDLE_ZERO_READ;
    handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->read_buffer);
    if (handle->read_buffer.len == 0) {
      handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &handle->read_buffer);
      return;
    }
    assert(handle->read_buffer.base != NULL);
    buf = handle->read_buffer;
  } else {
    handle->flags |= UV_HANDLE_ZERO_READ;
    buf.base = (char*) &uv_zero_;
    buf.len = 0;
  }

  /* Prepare the overlapped structure. */
  memset(&(req->overlapped), 0, sizeof(req->overlapped));
  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
    assert(req->event_handle);
    req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
  }

  flags = 0;
  result = WSARecv(handle->socket,
                   (WSABUF*)&buf,
                   1,
                   &bytes,
                   &flags,
                   &req->overlapped,
                   NULL);

  if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
    /* Process the req without IOCP. */
    handle->flags |= UV_HANDLE_READ_PENDING;
    req->overlapped.InternalHigh = bytes;
    handle->reqs_pending++;
    uv_insert_pending_req(loop, (uv_req_t*)req);
  } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
    /* The req will be processed with IOCP. */
    handle->flags |= UV_HANDLE_READ_PENDING;
    handle->reqs_pending++;
    if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
        req->wait_handle == INVALID_HANDLE_VALUE &&
        !RegisterWaitForSingleObject(&req->wait_handle,
          req->event_handle, post_completion, (void*) req,
          INFINITE, WT_EXECUTEINWAITTHREAD)) {
      SET_REQ_ERROR(req, GetLastError());
      uv_insert_pending_req(loop, (uv_req_t*)req);
    }
  } else {
    /* Make this req pending reporting an error. */
    SET_REQ_ERROR(req, WSAGetLastError());
    uv_insert_pending_req(loop, (uv_req_t*)req);
    handle->reqs_pending++;
  }
}
Beispiel #3
0
static int uv_tcp_try_connect(uv_connect_t* req,
                              uv_tcp_t* handle,
                              const struct sockaddr* addr,
                              unsigned int addrlen,
                              uv_connect_cb cb) {
  uv_loop_t* loop = handle->loop;
  const struct sockaddr* bind_addr;
  BOOL success;
  DWORD bytes;
  int err;

  if (handle->flags & UV_HANDLE_BIND_ERROR) {
    return handle->bind_error;
  }

  if (!(handle->flags & UV_HANDLE_BOUND)) {
    if (addrlen == sizeof(uv_addr_ip4_any_)) {
      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
    } else if (addrlen == sizeof(uv_addr_ip6_any_)) {
      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
    } else {
      abort();
    }
    err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0);
    if (err)
      return err;
  }

  if (!handle->func_connectex) {
    if (!uv_get_connectex_function(handle->socket, &handle->func_connectex)) {
      return WSAEAFNOSUPPORT;
    }
  }

  uv_req_init(loop, (uv_req_t*) req);
  req->type = UV_CONNECT;
  req->handle = (uv_stream_t*) handle;
  req->cb = cb;
  memset(&req->overlapped, 0, sizeof(req->overlapped));

  success = handle->func_connectex(handle->socket,
                                   addr,
                                   addrlen,
                                   NULL,
                                   0,
                                   &bytes,
                                   &req->overlapped);

  if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
    /* Process the req without IOCP. */
    handle->reqs_pending++;
    REGISTER_HANDLE_REQ(loop, handle, req);
    uv_insert_pending_req(loop, (uv_req_t*)req);
  } else if (UV_SUCCEEDED_WITH_IOCP(success)) {
    /* The req will be processed with IOCP. */
    handle->reqs_pending++;
    REGISTER_HANDLE_REQ(loop, handle, req);
  } else {
    return WSAGetLastError();
  }

  return 0;
}
Beispiel #4
0
int _getdns_event_add(struct _getdns_event *ev, struct timeval *tv)
{
	printf( "event_add %p added=%d fd=%d tv=" ARG_LL "d %s%s%s", 
		ev, ev->added, ev->ev_fd, 
		(tv?(long long)tv->tv_sec*1000+(long long)tv->tv_usec/1000:-1),
		(ev->ev_events&EV_READ)?" EV_READ":"",
		(ev->ev_events&EV_WRITE)?" EV_WRITE":"",
		(ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":"");
		
   if(ev->added)
       event_del(ev);
 /* gowri no works
 if (ev->ev_fd == -1 || find_fd(ev->ev_base, ev->ev_fd) == -1) {
	   printf("event_add failed, bad fd\n");
	   return 0;
   }
   */

	ev->is_tcp = 0;
	ev->is_signal = 0;
	ev->just_checked = 0;

	if ((ev->ev_events&(EV_READ | EV_WRITE)) && ev->ev_fd != -1) {
		BOOL b = 0;
		int t, l;
		long events = 0;
		//gprintf("\getdns_event_add %d %d\n", ev->ev_fd, events);

		if (ev->ev_base->max == ev->ev_base->cap)
			return -1;
		ev->idx = ev->ev_base->max++;
		ev->ev_base->items[ev->idx] = ev;

		if ((ev->ev_events&EV_READ))
			events |= FD_READ;
		if ((ev->ev_events&EV_WRITE))
		{
			events |= FD_CONNECT;
		    events |= FD_WRITE;
	    }

		//printf("\getdns_event_add %d read = %d write = %d %d\n", ev->ev_fd, ev->ev_events&EV_READ, ev->ev_events&EV_WRITE, events);

		l = sizeof(t);
		if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_TYPE,
			(void*)&t, &l) != 0)
			log_err("getdns: getsockopt(SO_TYPE) failed: %s",
				wsa_strerror(WSAGetLastError()));
		if(t == SOCK_STREAM) {
			/* TCP socket */
			ev->is_tcp = 1;
			events |= FD_CLOSE;
			if( (ev->ev_events&EV_WRITE) )
				events |= FD_CONNECT;
			l = sizeof(b);
			if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_ACCEPTCONN,
				(void*)&b, &l) != 0)
				log_err("getdns: getsockopt(SO_ACCEPTCONN) failed: %s",
					wsa_strerror(WSAGetLastError()));
			if(b) /* TCP accept socket */
				events |= FD_ACCEPT;
		}
		ev->hEvent = WSACreateEvent();
		if(ev->hEvent == WSA_INVALID_EVENT)
			log_err("getdns: WSACreateEvent failed: %s",
				wsa_strerror(WSAGetLastError()));
		/* automatically sets fd to nonblocking mode.
		 * nonblocking cannot be disabled, until wsaES(fd, NULL, 0) */
		//g printf("\nWSAEventSelect %d events %d hEvent %d\n", ev->ev_fd, events, ev->hEvent); 
		//gg if (WSAEventSelect(ev->ev_fd, ev->hEvent, FD_ACCEPT | FD_CONNECT | FD_READ | FD_CLOSE | FD_WRITE) != 0) {
		//if (WSAEventSelect(ev->ev_fd, ev->hEvent,FD_READ | FD_WRITE) != 0) {
		if (WSAEventSelect(ev->ev_fd, ev->hEvent, events) != 0) {
			log_err("getdns: WSAEventSelect in getdns failed: %s",
				wsa_strerror(WSAGetLastError()));
		}
		if(ev->is_tcp && ev->stick_events && 
			(ev->ev_events & ev->old_events)) {
			/* go to processing the sticky event right away */
			ev->ev_base->tcp_reinvigorated = 1;
		}
	}

	if(tv && (ev->ev_events&EV_TIMEOUT)) {
#ifndef S_SPLINT_S
                struct timeval *now = ev->ev_base->time_tv;
                ev->ev_timeout.tv_sec = tv->tv_sec + now->tv_sec;
                ev->ev_timeout.tv_usec = tv->tv_usec + now->tv_usec;
                while(ev->ev_timeout.tv_usec > 1000000) {
                        ev->ev_timeout.tv_usec -= 1000000;
                        ev->ev_timeout.tv_sec++;
                }
#endif
                (void)_getdns_rbtree_insert(ev->ev_base->times, &ev->node);
        }
        ev->added = 1;
	return 0;
}
Beispiel #5
0
static int uv_tcp_try_bind(uv_tcp_t* handle,
                           const struct sockaddr* addr,
                           unsigned int addrlen,
                           unsigned int flags) {
  DWORD err;
  int r;

  if (handle->socket == INVALID_SOCKET) {
    SOCKET sock;

    /* Cannot set IPv6-only mode on non-IPv6 socket. */
    if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)
      return ERROR_INVALID_PARAMETER;

    sock = socket(addr->sa_family, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET) {
      return WSAGetLastError();
    }

    /* Make the socket non-inheritable */
    if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) {
      err = GetLastError();
      closesocket(sock);
      return err;
    }

    err = uv_tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0);
    if (err) {
      closesocket(sock);
      return err;
    }
  }

#ifdef IPV6_V6ONLY
  if (addr->sa_family == AF_INET6) {
    int on;

    on = (flags & UV_TCP_IPV6ONLY) != 0;

    /* TODO: how to handle errors? This may fail if there is no ipv4 stack */
    /* available, or when run on XP/2003 which have no support for dualstack */
    /* sockets. For now we're silently ignoring the error. */
    setsockopt(handle->socket,
               IPPROTO_IPV6,
               IPV6_V6ONLY,
               (const char*)&on,
               sizeof on);
  }
#endif

  r = bind(handle->socket, addr, addrlen);

  if (r == SOCKET_ERROR) {
    err = WSAGetLastError();
    if (err == WSAEADDRINUSE) {
      /* Some errors are not to be reported until connect() or listen() */
      handle->bind_error = err;
      handle->flags |= UV_HANDLE_BIND_ERROR;
    } else {
      return err;
    }
  }

  handle->flags |= UV_HANDLE_BOUND;

  return 0;
}
Beispiel #6
0
bool CSocket::Recv( char* pszData, long nLen, bool bEmptyError /*= true*/ )
{
	bool bResult = false;
	static uint anTimeOuts[ DEFAULT_CHECK_ATTEMPTS ] = { 500, 2000, 5000 };

	do
	{
		bool bLoopError = false;
		long nExpectedLen = 0, nRecvLen = 0, nRes = 0, nNetLen = 0;

		m_nBytesRead = 0;

		if( !nLen ) LOG_ERROR_BREAK( "Receiving buffer size is 0" );
		if( !pszData ) LOG_ERROR_BREAK( "pszData is NULL" );

		size_t nAttempts = 0;
		do
		{
			m_tvTimeOut.tv_sec  = (long)anTimeOuts[nAttempts] / 1000;
			m_tvTimeOut.tv_usec = ( anTimeOuts[nAttempts] % 1000 ) * 1000;

			FD_ZERO(&m_fdReadSockets);
			FD_SET(m_sockMain, &m_fdReadSockets);
			if( SOCKET_ERROR == (nRes = select(int(m_sockMain)+1, &m_fdReadSockets, 0, 0, &m_tvTimeOut)) ) {
				LOG_ERROR3_BREAK( szErrorFailedWithCodeFmt, "select", WSAGetLastError() );
			}
		}
		while( !nRes && m_nCheckAttempts > nAttempts++ );
		if( !nRes ) break; // LOG_ERROR_BREAK( szSocketNotReady );

		if( !FD_ISSET(m_sockMain, &m_fdReadSockets) ) LOG_ERROR_BREAK( "Timeout elapsed" );

		nExpectedLen = nLen;
		if( m_bUseHeaderLength )
		{
			nRecvLen = recv( m_sockMain, (char*)&nNetLen, sizeof(nNetLen), 0 );
			if( SOCKET_ERROR == nRecvLen || !nRecvLen ) {
				LOG_ERROR3_BREAK( szErrorFailedWithCodeFmt, "recv", WSAGetLastError() );
			}

			nExpectedLen = ntohl( nNetLen );
			if( nExpectedLen > nLen ) {
				LOG_ERROR( "Too small receiving buffer" );
				nExpectedLen = nLen;
			}

			//cout << nExpectedLen << " (" << nNetLen << " : " << nRecvLen << ")";
		}

		while( nExpectedLen > 0 )
		{
			nRecvLen = recv( m_sockMain, pszData, nExpectedLen, 0 );
			if( !nRecvLen  ) 
			{
				if( !m_nBytesRead ) {
					// when it is not first read attempt we shouldn't show this error
					if( bEmptyError ) {
						LOG_ERROR( "Received 0 bytes" );
						bLoopError = true;
					}
				}
				break;
			}

			if( SOCKET_ERROR == nRecvLen || nRecvLen < 0 ) {
				bLoopError = true;
				LOG_ERROR3_BREAK( szErrorFailedWithCodeFmt, "recv", WSAGetLastError() );
			}

			nExpectedLen -= nRecvLen;
			pszData += nRecvLen;
			m_nBytesRead += nRecvLen;

			if (!nExpectedLen)
			{
				break;
			}
			
			sizeint siNextTimeout = m_bUseHeaderLength ? 5000 : m_nWaitNextTimeOut;
			if (!CanRead(siNextTimeout))
			{
				if (m_bUseHeaderLength)
				{
					LOG_ERROR2("Wait times out %u", siNextTimeout);
					bLoopError = true;
				}

				break;
			}
		}

		bResult = !bLoopError;
	}
	while( false );

	return bResult;
}
Beispiel #7
0
/** call select and callbacks for that */
int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait)
{
	fd_set r, w;
	int ret, i, timeout = 0, numwait = 0;
	struct _getdns_event* eventlist[WSK_MAX_ITEMS];

#ifndef S_SPLINT_S
	if (wait->tv_sec == (time_t)-1)
		wait = NULL;
#endif
	memmove(&r, &base->reads, sizeof(fd_set));
	memmove(&w, &base->writes, sizeof(fd_set));
	memmove(&base->ready, &base->content, sizeof(fd_set));
	/*
	if ((ret = select(base->max + 1, &r, &w, NULL, wait)) == -1) {
		ret = errno;
		if (settime(base) < 0)
			return -1;
		errno = ret;
		if (ret == EAGAIN || ret == EINTR)
			return 0;
		return -1;
	}
	*/

	/* prepare event array */
	for (i = 0; i<base->max; i++) {
		if (base->items[i]->ev_fd == -1 && !base->items[i]->is_signal)
			continue; /* skip timer only events */
		eventlist[numwait] = base->items[i];
		base->waitfor[numwait++] = base->items[i]->hEvent;
		if (numwait == WSK_MAX_ITEMS)
			break; /* sanity check */
	}

	ret = WSAWaitForMultipleEvents(base->max, base->waitfor,
		0 /* do not wait for all, just one will do */,
		wait ? timeout : WSA_INFINITE,
		0); /* we are not alertable (IO completion events) */
	if (ret == WSA_WAIT_IO_COMPLETION) {
		log_err("getdns: WSAWaitForMultipleEvents failed: WSA_WAIT_IO_COMPLETION");
		return -1;
	}
	else if (ret == WSA_WAIT_FAILED) {
		log_err("getdns: WSAWaitForMultipleEvents failed: %s",
			wsa_strerror(WSAGetLastError()));
		return -1;
	}
	else if (ret == WSA_WAIT_TIMEOUT) {
		was_timeout = 1;
	}
	else
		startidx = ret - WSA_WAIT_EVENT_0;


	if (settime(base) < 0)
		return -1;

	for (i = 0; i<base->max + 1; i++) {
		short bits = 0;
		if (!base->items[i] || !(FD_ISSET(i, &base->ready))) {
			continue;
		}
		if (FD_ISSET(i, &r)) {
			bits |= EV_READ;
			ret--;
		}
		if (FD_ISSET(i, &w)) {
			bits |= EV_WRITE;
			ret--;
		}
		bits &= base->items[i]->ev_events;
		if (bits) {
			fptr_ok(fptr_whitelist_event(
				base->items[i]->ev_callback));
			(*base->items[i]->ev_callback)(base->items[i]->ev_fd,
				bits, base->items[i]->ev_arg);
			if (ret == 0)
				break;
		}
	}
	return 0;
}
Beispiel #8
0
    void Listener::initAndListen() {
        checkTicketNumbers();
        vector<SOCKET> socks;
        
        {
            vector<SockAddr> mine = ipToAddrs(_ip.c_str(), _port, false);
            if ( ! _setupSockets( mine , socks ) )
                return;
        }

#ifdef MONGO_SSL
        _logListen(_port, _ssl);
#else
        _logListen(_port, false);
#endif
                
        OwnedPointerVector<EventHolder> eventHolders;
        boost::scoped_array<WSAEVENT> events(new WSAEVENT[socks.size()]);
        
        
        // Populate events array with an event for each socket we are watching
        for (size_t count = 0; count < socks.size(); ++count) {
            EventHolder* ev(new EventHolder);
            eventHolders.mutableVector().push_back(ev);
            events[count] = ev->get();            
        }
            
        while ( ! inShutdown() ) {
            // Turn on listening for accept-ready sockets
            for (size_t count = 0; count < socks.size(); ++count) {
                int status = WSAEventSelect(socks[count], events[count], FD_ACCEPT | FD_CLOSE);
                if (status == SOCKET_ERROR) {
                    const int mongo_errno = WSAGetLastError();
                    error() << "Windows WSAEventSelect returned " 
                        << errnoWithDescription(mongo_errno) << endl;
                    fassertFailed(16727);
                }
            }
        
            // Wait till one of them goes active, or we time out
            DWORD result = WSAWaitForMultipleEvents(socks.size(), 
                                                    events.get(), 
                                                    FALSE, // don't wait for all the events
                                                    10, // timeout, in ms 
                                                    FALSE); // do not allow I/O interruptions
            if (result == WSA_WAIT_FAILED) {
                const int mongo_errno = WSAGetLastError();
                error() << "Windows WSAWaitForMultipleEvents returned " 
                    << errnoWithDescription(mongo_errno) << endl;
                fassertFailed(16723);
            }
        
            if (result == WSA_WAIT_TIMEOUT) {
                _elapsedTime += 10;
                continue;
            }
            _elapsedTime += 1; // assume 1ms to grab connection. very rough
            
            // Determine which socket is ready
            DWORD eventIndex = result - WSA_WAIT_EVENT_0;
            WSANETWORKEVENTS networkEvents;            
            // Extract event details, and clear event for next pass
            int status = WSAEnumNetworkEvents(socks[eventIndex], 
                                              events[eventIndex], 
                                              &networkEvents);
            if (status == SOCKET_ERROR) {
                const int mongo_errno = WSAGetLastError();
                error() << "Windows WSAEnumNetworkEvents returned " 
                    << errnoWithDescription(mongo_errno) << endl;
                continue;
            }
            
            if (networkEvents.lNetworkEvents & FD_CLOSE) {              
                log() << "listen socket closed" << endl;
                break;
            }
            
            if (!(networkEvents.lNetworkEvents & FD_ACCEPT)) {
                error() << "Unexpected network event: " << networkEvents.lNetworkEvents << endl;
                continue;
            }
            
            int iec = networkEvents.iErrorCode[FD_ACCEPT_BIT];
            if (iec != 0) {                 
                error() << "Windows socket accept did not work:" << errnoWithDescription(iec) 
                        << endl;
                continue;
            }
            
            status = WSAEventSelect(socks[eventIndex], NULL, 0);                
            if (status == SOCKET_ERROR) {
                const int mongo_errno = WSAGetLastError();
                error() << "Windows WSAEventSelect returned " 
                    << errnoWithDescription(mongo_errno) << endl;
                continue;
            }
            
            disableNonblockingMode(socks[eventIndex]);
            
            SockAddr from;
            int s = accept(socks[eventIndex], from.raw(), &from.addressSize);
            if ( s < 0 ) {
                int x = errno; // so no global issues
                if ( x == ECONNABORTED || x == EBADF ) {
                    log() << "Listener on port " << _port << " aborted" << endl;
                    return;
                }
                if ( x == 0 && inShutdown() ) {
                    return;   // socket closed
                }
                if( !inShutdown() ) {
                    log() << "Listener: accept() returns " << s << " " 
                        << errnoWithDescription(x) << endl;
                    if (x == EMFILE || x == ENFILE) {
                        // Connection still in listen queue but we can't accept it yet
                        error() << "Out of file descriptors. Waiting one second before"
                            " trying to accept more connections." << warnings;
                        sleepsecs(1);
                    }
                }
                continue;
            }
            if (from.getType() != AF_UNIX)
                disableNagle(s);

            long long myConnectionNumber = globalConnectionNumber.addAndFetch(1);

            if ( _logConnect && ! cmdLine.quiet ){
                int conns = globalTicketHolder.used()+1;
                const char* word = (conns == 1 ? " connection" : " connections");
                log() << "connection accepted from " << from.toString() << " #" << myConnectionNumber << " (" << conns << word << " now open)" << endl;
            }
            
            boost::shared_ptr<Socket> pnewSock( new Socket(s, from) );
#ifdef MONGO_SSL
            if (_ssl) {
                pnewSock->secureAccepted(_ssl);
            }
#endif
            accepted( pnewSock , myConnectionNumber );
        }
    }
Beispiel #9
0
int
libnet_write_raw_ipv4(libnet_t *l, const uint8_t *packet, uint32_t size)
{
    int c;
    struct sockaddr_in sin;
    struct libnet_ipv4_hdr *ip_hdr;

    if (l == NULL)
    { 
        return (-1);
    } 

    ip_hdr = (struct libnet_ipv4_hdr *)packet;

#if (LIBNET_BSD_BYTE_SWAP)
    /*
     *  For link access, we don't need to worry about the inconsistencies of
     *  certain BSD kernels.  However, raw socket nuances abound.  Certain
     *  BSD implmentations require the ip_len and ip_off fields to be in host
     *  byte order.
     */
    ip_hdr->ip_len = FIX(ip_hdr->ip_len);
    ip_hdr->ip_off = FIX(ip_hdr->ip_off);
#endif /* LIBNET_BSD_BYTE_SWAP */

    memset(&sin, 0, sizeof(sin));
    sin.sin_family  = AF_INET;
    sin.sin_addr.s_addr = ip_hdr->ip_dst.s_addr;
#if (__WIN32__)
    /* set port for TCP */
    /*
     *  XXX - should first check to see if there's a pblock for a TCP
     *  header, if not we can use a dummy value for the port.
     */
    if (ip_hdr->ip_p == 6)
    {
        struct libnet_tcp_hdr *tcph_p =
                (struct libnet_tcp_hdr *)(packet + (ip_hdr->ip_hl << 2));
        sin.sin_port = tcph_p->th_dport;
    }
    /* set port for UDP */
    /*
     *  XXX - should first check to see if there's a pblock for a UDP
     *  header, if not we can use a dummy value for the port.
     */
    else if (ip_hdr->ip_p == 17)
    {
        struct libnet_udp_hdr *udph_p =
                (struct libnet_udp_hdr *)(packet + (ip_hdr->ip_hl << 2));
       sin.sin_port = udph_p->uh_dport;
    }
#endif /* __WIN32__ */

    c = sendto(l->fd, packet, size, 0, (struct sockaddr *)&sin,
            sizeof(sin));

#if (LIBNET_BSD_BYTE_SWAP)
    ip_hdr->ip_len = UNFIX(ip_hdr->ip_len);
    ip_hdr->ip_off = UNFIX(ip_hdr->ip_off);
#endif /* LIBNET_BSD_BYTE_SWAP */

    if (c != size)
    {
#if !(__WIN32__)
        snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
                "%s(): %d bytes written (%s)", __func__, c,
                strerror(errno));
#else /* __WIN32__ */
        snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
                "%s(): %d bytes written (%d)", __func__, c,
                WSAGetLastError());
#endif /* !__WIN32__ */
    }
    return (c);
}
Beispiel #10
0
/*@
   beasy_send - send

   Parameters:
+  int bfd - bsocket
.  char *buffer - buffer
-  int length - length

   Notes:
@*/
int beasy_send(int bfd, char *buffer, int length)
{
#ifdef HAVE_WINSOCK2_H
    int error;
    int num_sent;

    while ((num_sent = write(bfd, buffer, length)) == SOCKET_ERROR)
    {
	error = WSAGetLastError();
	if (error == WSAEWOULDBLOCK)
	{
            //Sleep(0);
	    continue;
	}
	if (error == WSAENOBUFS)
	{
	    // If there is no buffer space available then split the buffer in half and send each piece separately.
	    if (beasy_send(bfd, buffer, length/2) == SOCKET_ERROR)
		return SOCKET_ERROR;
	    if (beasy_send(bfd, buffer+(length/2), length - (length/2)) == SOCKET_ERROR)
		return SOCKET_ERROR;
	    return length;
	}
	WSASetLastError(error);
	return SOCKET_ERROR;
    }
    
    return length;
#else
    int ret_val;
    int num_written;
    bfd_set writefds;
    int total = length;
    
    num_written = write(bfd, buffer, length);
    if (num_written == SOCKET_ERROR)
    {
	if ((errno != EINTR) || (errno != EAGAIN))
	    return SOCKET_ERROR;
    }
    else
    {
	length -= num_written;
	buffer += num_written;
    }
    
    while (length)
    {
	BFD_ZERO(&writefds); 
	BFD_SET(bfd, &writefds);
	
	ret_val = bselect(1, NULL, &writefds, NULL, NULL);
	if (ret_val == 1)
	{
	    num_written = write(((BFD_Buffer*)bfd)->real_fd, buffer, length);
	    if (num_written == SOCKET_ERROR)
	    {
		if ((errno != EINTR) || (errno != EAGAIN))
		    return SOCKET_ERROR;
	    }
	    else
	    {
		if (num_written == 0)
		{
		    //printf("beasy_send: socket closed\n");
		    return total - length;
		}
		length -= num_written;
		buffer += num_written;
	    }
	}
	else
	{
	    if (ret_val == SOCKET_ERROR)
	    {
		if ((errno != EINTR) || (errno != EAGAIN))
		    return SOCKET_ERROR;
	    }
	}
    }
    return total;
#endif
}
Beispiel #11
0
/*@
   beasy_connect - connect

   Parameters:
+  int bfd - bsocket
.  char *host - hostname
.  int port - port
-  int seconds - timeout value in seconds

   Notes:
@*/
int beasy_connect_timeout(int bfd, char *host, int port, int seconds)
{
#ifdef HAVE_WINSOCK2_H
    BOOL b;
#endif
    clock_t start, current;
    int error;
    int reps = 0;
    struct hostent *lphost;
    struct sockaddr_in sockAddr;
#ifdef USE_LINGER_SOCKOPT
    struct linger linger;
#endif
#ifdef HAVE_WINSOCK2_H
    /* use this array to make sure the warning only gets logged once */
    BOOL bWarningLogged[4] = { FALSE, FALSE, FALSE, FALSE };
#endif

    start = clock();

    memset(&sockAddr,0,sizeof(sockAddr));
    
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_addr.s_addr = inet_addr(host);
    
    if (sockAddr.sin_addr.s_addr == INADDR_NONE || sockAddr.sin_addr.s_addr == 0)
    {
	lphost = gethostbyname(host);
	if (lphost != NULL)
	    sockAddr.sin_addr.s_addr = ((struct in_addr *)lphost->h_addr)->s_addr;
	else
	    return SOCKET_ERROR;
    }
    
    sockAddr.sin_port = htons((u_short)port);
    
    while (bconnect(bfd, (SOCKADDR*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR)
    {
	current = clock();
	if (((current - start) / CLOCKS_PER_SEC) > seconds)
	{
#ifdef HAVE_WINSOCK2_H
	    WSASetLastError(WSAETIMEDOUT);
#endif
	    return SOCKET_ERROR;
	}
#ifdef HAVE_WINSOCK2_H
	error = WSAGetLastError();
	srand(clock());
	if( (error == WSAECONNREFUSED || error == WSAETIMEDOUT || error == WSAENETUNREACH || error == WSAEADDRINUSE)
	    && (reps < g_beasy_connection_attempts) )
	{
	    double d = (double)rand() / (double)RAND_MAX;
	    Sleep(200 + (int)(d*200));
	    reps++;
	    switch (error)
	    {
	    case WSAECONNREFUSED:
		if (!bWarningLogged[0])
		{
		    /*log_warning("WSAECONNREFUSED error, re-attempting bconnect(%s)", host);*/
		    bWarningLogged[0] = TRUE;
		}
		break;
	    case WSAETIMEDOUT:
		if (!bWarningLogged[1])
		{
		    log_warning("WSAETIMEDOUT error, re-attempting bconnect(%s)", host);
		    bWarningLogged[1] = TRUE;
		}
		break;
	    case WSAENETUNREACH:
		if (!bWarningLogged[2])
		{
		    log_warning("WSAENETUNREACH error, re-attempting bconnect(%s)", host);
		    bWarningLogged[2] = TRUE;
		}
		break;
	    case WSAEADDRINUSE:
		if (!bWarningLogged[3])
		{
		    log_warning("WSAEADDRINUSE error, re-attempting bconnect(%s)", host);
		    bWarningLogged[3] = TRUE;
		}
		break;
	    default:
		log_warning("%d error, re-attempting bconnect");
		break;
	    }
	}
	else
	{
	    return SOCKET_ERROR;
	}
#else
	if( (errno == ECONNREFUSED || errno == ETIMEDOUT || errno == ENETUNREACH)
	    && (reps < g_beasy_connection_attempts) )
	{
#ifdef HAVE_USLEEP
	    usleep(200);
#else
	    sleep(0);
#endif
	    reps++;
	}
	else
	{
	    return SOCKET_ERROR;
	}
#endif
    }

#ifdef USE_LINGER_SOCKOPT
    /* Set the linger on close option */
    linger.l_onoff = 1 ;
    linger.l_linger = 60;
    bsetsockopt(bfd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger));
#endif

#ifdef HAVE_WINSOCK2_H
    b = TRUE;
    bsetsockopt(bfd, IPPROTO_TCP, TCP_NODELAY, (char*)&b, sizeof(BOOL));
#endif
    return 0;
}
Beispiel #12
0
int main(int argc, char *argv[])
{
	WSADATA wsa_data;
	SOCKET echo_soc = 0;
	SOCKET accept_soc = 0;
	struct sockaddr_in serv_addr, client_addr;
	unsigned short port = ECHO_DEF_PORT;
	int result = 0;
	int addr_len = sizeof(struct sockaddr_in);
	char recv_buf[ECHO_BUF_SIZE];

	if (argc == 2)
	{
		port = atoi(argv[1]);
	}

	WSAStartup(MAKEWORD(2,0), &wsa_data);
	echo_soc = socket(AF_INET, SOCK_STREAM, 0);

	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port   = htons(port);
	serv_addr.sin_addr.s_addr = INADDR_ANY;

	result = bind(echo_soc, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
	if (result == SOCKET_ERROR)
	{
		printf("[EchoServer] bind error: %d\n", WSAGetLastError());
		closesocket(echo_soc);
		WSACleanup();
		return -1;
	}

	listen(echo_soc, SOMAXCONN);

	printf("[EchoServer] running on port %d ...\n", port);
	while (1)
	{
		accept_soc = accept(echo_soc, (struct sockaddr *)&client_addr, &addr_len);
		if (accept_soc == INVALID_SOCKET)
		{
			printf("[EchoServer] accept error: %d\n", WSAGetLastError());
			break;
		}

		result = recv(accept_soc, recv_buf, ECHO_BUF_SIZE, 0);
		if (result > 0)
		{
			recv_buf[result] = 0;
			printf("[EchoServer] recv: \"%s\", from %s\n", recv_buf,
				inet_ntoa(client_addr.sin_addr));

			result = send(accept_soc, recv_buf, result, 0);
		}

		closesocket(accept_soc);
	}

	closesocket(echo_soc);
	WSACleanup();

	return 0;
}
Beispiel #13
0
int zmq::make_fdpair (fd_t *r_, fd_t *w_)
{
#if defined ZMQ_HAVE_EVENTFD
    int flags = 0;
#if defined ZMQ_HAVE_EVENTFD_CLOEXEC
    //  Setting this option result in sane behaviour when exec() functions
    //  are used. Old sockets are closed and don't block TCP ports, avoid
    //  leaks, etc.
    flags |= EFD_CLOEXEC;
#endif
    fd_t fd = eventfd (0, flags);
    if (fd == -1) {
        errno_assert (errno == ENFILE || errno == EMFILE);
        *w_ = *r_ = -1;
        return -1;
    } else {
        *w_ = *r_ = fd;
        return 0;
    }

#elif defined ZMQ_HAVE_WINDOWS
#if !defined _WIN32_WCE && !defined ZMQ_HAVE_WINDOWS_UWP
    //  Windows CE does not manage security attributes
    SECURITY_DESCRIPTOR sd;
    SECURITY_ATTRIBUTES sa;
    memset (&sd, 0, sizeof sd);
    memset (&sa, 0, sizeof sa);

    InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl (&sd, TRUE, 0, FALSE);

    sa.nLength = sizeof (SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = &sd;
#endif

    //  This function has to be in a system-wide critical section so that
    //  two instances of the library don't accidentally create signaler
    //  crossing the process boundary.
    //  We'll use named event object to implement the critical section.
    //  Note that if the event object already exists, the CreateEvent requests
    //  EVENT_ALL_ACCESS access right. If this fails, we try to open
    //  the event object asking for SYNCHRONIZE access only.
    HANDLE sync = NULL;

    //  Create critical section only if using fixed signaler port
    //  Use problematic Event implementation for compatibility if using old port 5905.
    //  Otherwise use Mutex implementation.
    int event_signaler_port = 5905;

    if (signaler_port == event_signaler_port) {
#if !defined _WIN32_WCE && !defined ZMQ_HAVE_WINDOWS_UWP
        sync =
          CreateEventW (&sa, FALSE, TRUE, L"Global\\zmq-signaler-port-sync");
#else
        sync =
          CreateEventW (NULL, FALSE, TRUE, L"Global\\zmq-signaler-port-sync");
#endif
        if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED)
            sync = OpenEventW (SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE,
                               L"Global\\zmq-signaler-port-sync");

        win_assert (sync != NULL);
    } else if (signaler_port != 0) {
        wchar_t mutex_name[MAX_PATH];
#ifdef __MINGW32__
        _snwprintf (mutex_name, MAX_PATH, L"Global\\zmq-signaler-port-%d",
                    signaler_port);
#else
        swprintf (mutex_name, MAX_PATH, L"Global\\zmq-signaler-port-%d",
                  signaler_port);
#endif

#if !defined _WIN32_WCE && !defined ZMQ_HAVE_WINDOWS_UWP
        sync = CreateMutexW (&sa, FALSE, mutex_name);
#else
        sync = CreateMutexW (NULL, FALSE, mutex_name);
#endif
        if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED)
            sync = OpenMutexW (SYNCHRONIZE, FALSE, mutex_name);

        win_assert (sync != NULL);
    }

    //  Windows has no 'socketpair' function. CreatePipe is no good as pipe
    //  handles cannot be polled on. Here we create the socketpair by hand.
    *w_ = INVALID_SOCKET;
    *r_ = INVALID_SOCKET;

    //  Create listening socket.
    SOCKET listener;
    listener = open_socket (AF_INET, SOCK_STREAM, 0);
    wsa_assert (listener != INVALID_SOCKET);

    //  Set SO_REUSEADDR and TCP_NODELAY on listening socket.
    BOOL so_reuseaddr = 1;
    int rc = setsockopt (listener, SOL_SOCKET, SO_REUSEADDR,
                         reinterpret_cast<char *> (&so_reuseaddr),
                         sizeof so_reuseaddr);
    wsa_assert (rc != SOCKET_ERROR);

    tune_socket (listener);

    //  Init sockaddr to signaler port.
    struct sockaddr_in addr;
    memset (&addr, 0, sizeof addr);
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
    addr.sin_port = htons (signaler_port);

    //  Create the writer socket.
    *w_ = open_socket (AF_INET, SOCK_STREAM, 0);
    wsa_assert (*w_ != INVALID_SOCKET);

    //  Set TCP_NODELAY on writer socket.
    tune_socket (*w_);

    if (sync != NULL) {
        //  Enter the critical section.
        DWORD dwrc = WaitForSingleObject (sync, INFINITE);
        zmq_assert (dwrc == WAIT_OBJECT_0 || dwrc == WAIT_ABANDONED);
    }

    //  Bind listening socket to signaler port.
    rc = bind (listener, reinterpret_cast<const struct sockaddr *> (&addr),
               sizeof addr);

    if (rc != SOCKET_ERROR && signaler_port == 0) {
        //  Retrieve ephemeral port number
        int addrlen = sizeof addr;
        rc = getsockname (listener, reinterpret_cast<struct sockaddr *> (&addr),
                          &addrlen);
    }

    //  Listen for incoming connections.
    if (rc != SOCKET_ERROR)
        rc = listen (listener, 1);

    //  Connect writer to the listener.
    if (rc != SOCKET_ERROR)
        rc = connect (*w_, reinterpret_cast<struct sockaddr *> (&addr),
                      sizeof addr);

    //  Accept connection from writer.
    if (rc != SOCKET_ERROR)
        *r_ = accept (listener, NULL, NULL);

    //  Send/receive large chunk to work around TCP slow start
    //  This code is a workaround for #1608
    if (*r_ != INVALID_SOCKET) {
        size_t dummy_size =
          1024 * 1024; //  1M to overload default receive buffer
        unsigned char *dummy =
          static_cast<unsigned char *> (malloc (dummy_size));
        wsa_assert (dummy);

        int still_to_send = static_cast<int> (dummy_size);
        int still_to_recv = static_cast<int> (dummy_size);
        while (still_to_send || still_to_recv) {
            int nbytes;
            if (still_to_send > 0) {
                nbytes = ::send (
                  *w_,
                  reinterpret_cast<char *> (dummy + dummy_size - still_to_send),
                  still_to_send, 0);
                wsa_assert (nbytes != SOCKET_ERROR);
                still_to_send -= nbytes;
            }
            nbytes = ::recv (
              *r_,
              reinterpret_cast<char *> (dummy + dummy_size - still_to_recv),
              still_to_recv, 0);
            wsa_assert (nbytes != SOCKET_ERROR);
            still_to_recv -= nbytes;
        }
        free (dummy);
    }

    //  Save errno if error occurred in bind/listen/connect/accept.
    int saved_errno = 0;
    if (*r_ == INVALID_SOCKET)
        saved_errno = WSAGetLastError ();

    //  We don't need the listening socket anymore. Close it.
    rc = closesocket (listener);
    wsa_assert (rc != SOCKET_ERROR);

    if (sync != NULL) {
        //  Exit the critical section.
        BOOL brc;
        if (signaler_port == event_signaler_port)
            brc = SetEvent (sync);
        else
            brc = ReleaseMutex (sync);
        win_assert (brc != 0);

        //  Release the kernel object
        brc = CloseHandle (sync);
        win_assert (brc != 0);
    }

    if (*r_ != INVALID_SOCKET) {
        make_socket_noninheritable (*r_);
        return 0;
    }
    //  Cleanup writer if connection failed
    if (*w_ != INVALID_SOCKET) {
        rc = closesocket (*w_);
        wsa_assert (rc != SOCKET_ERROR);
        *w_ = INVALID_SOCKET;
    }
    //  Set errno from saved value
    errno = wsa_error_to_errno (saved_errno);
    return -1;


#elif defined ZMQ_HAVE_OPENVMS

    //  Whilst OpenVMS supports socketpair - it maps to AF_INET only.  Further,
    //  it does not set the socket options TCP_NODELAY and TCP_NODELACK which
    //  can lead to performance problems.
    //
    //  The bug will be fixed in V5.6 ECO4 and beyond.  In the meantime, we'll
    //  create the socket pair manually.
    struct sockaddr_in lcladdr;
    memset (&lcladdr, 0, sizeof lcladdr);
    lcladdr.sin_family = AF_INET;
    lcladdr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
    lcladdr.sin_port = 0;

    int listener = open_socket (AF_INET, SOCK_STREAM, 0);
    errno_assert (listener != -1);

    int on = 1;
    int rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELAY, &on, sizeof on);
    errno_assert (rc != -1);

    rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELACK, &on, sizeof on);
    errno_assert (rc != -1);

    rc = bind (listener, (struct sockaddr *) &lcladdr, sizeof lcladdr);
    errno_assert (rc != -1);

    socklen_t lcladdr_len = sizeof lcladdr;

    rc = getsockname (listener, (struct sockaddr *) &lcladdr, &lcladdr_len);
    errno_assert (rc != -1);

    rc = listen (listener, 1);
    errno_assert (rc != -1);

    *w_ = open_socket (AF_INET, SOCK_STREAM, 0);
    errno_assert (*w_ != -1);

    rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY, &on, sizeof on);
    errno_assert (rc != -1);

    rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELACK, &on, sizeof on);
    errno_assert (rc != -1);

    rc = connect (*w_, (struct sockaddr *) &lcladdr, sizeof lcladdr);
    errno_assert (rc != -1);

    *r_ = accept (listener, NULL, NULL);
    errno_assert (*r_ != -1);

    close (listener);

    return 0;
#elif defined ZMQ_HAVE_VXWORKS
    struct sockaddr_in lcladdr;
    memset (&lcladdr, 0, sizeof lcladdr);
    lcladdr.sin_family = AF_INET;
    lcladdr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
    lcladdr.sin_port = 0;

    int listener = open_socket (AF_INET, SOCK_STREAM, 0);
    errno_assert (listener != -1);

    int on = 1;
    int rc =
      setsockopt (listener, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof on);
    errno_assert (rc != -1);

    rc = bind (listener, (struct sockaddr *) &lcladdr, sizeof lcladdr);
    errno_assert (rc != -1);

    socklen_t lcladdr_len = sizeof lcladdr;

    rc = getsockname (listener, (struct sockaddr *) &lcladdr,
                      (int *) &lcladdr_len);
    errno_assert (rc != -1);

    rc = listen (listener, 1);
    errno_assert (rc != -1);

    *w_ = open_socket (AF_INET, SOCK_STREAM, 0);
    errno_assert (*w_ != -1);

    rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof on);
    errno_assert (rc != -1);

    rc = connect (*w_, (struct sockaddr *) &lcladdr, sizeof lcladdr);
    errno_assert (rc != -1);

    *r_ = accept (listener, NULL, NULL);
    errno_assert (*r_ != -1);

    close (listener);

    return 0;
#else
    // All other implementations support socketpair()
    int sv[2];
    int type = SOCK_STREAM;
    //  Setting this option result in sane behaviour when exec() functions
    //  are used. Old sockets are closed and don't block TCP ports, avoid
    //  leaks, etc.
#if defined ZMQ_HAVE_SOCK_CLOEXEC
    type |= SOCK_CLOEXEC;
#endif
    int rc = socketpair (AF_UNIX, type, 0, sv);
    if (rc == -1) {
        errno_assert (errno == ENFILE || errno == EMFILE);
        *w_ = *r_ = -1;
        return -1;
    } else {
        make_socket_noninheritable (sv[0]);
        make_socket_noninheritable (sv[1]);

        *w_ = sv[0];
        *r_ = sv[1];
        return 0;
    }
#endif
}
Beispiel #14
0
static int socket_error(void)
{
    switch (WSAGetLastError()) {
    case 0:
        return 0;
    case WSAEINTR:
        return EINTR;
    case WSAEINVAL:
        return EINVAL;
    case WSA_INVALID_HANDLE:
        return EBADF;
    case WSA_NOT_ENOUGH_MEMORY:
        return ENOMEM;
    case WSA_INVALID_PARAMETER:
        return EINVAL;
    case WSAENAMETOOLONG:
        return ENAMETOOLONG;
    case WSAENOTEMPTY:
        return ENOTEMPTY;
    case WSAEWOULDBLOCK:
         /* not using EWOULDBLOCK as we don't want code to have
          * to check both EWOULDBLOCK and EAGAIN */
        return EAGAIN;
    case WSAEINPROGRESS:
        return EINPROGRESS;
    case WSAEALREADY:
        return EALREADY;
    case WSAENOTSOCK:
        return ENOTSOCK;
    case WSAEDESTADDRREQ:
        return EDESTADDRREQ;
    case WSAEMSGSIZE:
        return EMSGSIZE;
    case WSAEPROTOTYPE:
        return EPROTOTYPE;
    case WSAENOPROTOOPT:
        return ENOPROTOOPT;
    case WSAEPROTONOSUPPORT:
        return EPROTONOSUPPORT;
    case WSAEOPNOTSUPP:
        return EOPNOTSUPP;
    case WSAEAFNOSUPPORT:
        return EAFNOSUPPORT;
    case WSAEADDRINUSE:
        return EADDRINUSE;
    case WSAEADDRNOTAVAIL:
        return EADDRNOTAVAIL;
    case WSAENETDOWN:
        return ENETDOWN;
    case WSAENETUNREACH:
        return ENETUNREACH;
    case WSAENETRESET:
        return ENETRESET;
    case WSAECONNABORTED:
        return ECONNABORTED;
    case WSAECONNRESET:
        return ECONNRESET;
    case WSAENOBUFS:
        return ENOBUFS;
    case WSAEISCONN:
        return EISCONN;
    case WSAENOTCONN:
        return ENOTCONN;
    case WSAETIMEDOUT:
        return ETIMEDOUT;
    case WSAECONNREFUSED:
        return ECONNREFUSED;
    case WSAELOOP:
        return ELOOP;
    case WSAEHOSTUNREACH:
        return EHOSTUNREACH;
    default:
        return EIO;
    }
}
/* Connect to SERVER at PORT and return a file descriptor or -1 on
   error. */
static int
connect_server (const char *server, unsigned short port)
{
  int sock = -1;

#ifdef _WIN32
  struct hostent *hp;
  struct sockaddr_in addr;
  unsigned long l;

  init_sockets ();

  memset (&addr, 0, sizeof addr);
  addr.sin_family = AF_INET;
  addr.sin_port = htons (port);

  /* Win32 gethostbyname doesn't handle IP addresses internally, so we
     try inet_addr first on that platform only. */
  if ((l = inet_addr (server)) != INADDR_NONE) 
    memcpy (&addr.sin_addr, &l, sizeof l);
  else if ((hp = gethostbyname (server))) 
    {
      if (hp->h_addrtype != AF_INET)
        {
          fprintf (console, "gpgkeys: unknown address family for `%s'\n",
                   server);
          return -1;
        }
      if (hp->h_length != 4)
        {
          fprintf (console, "gpgkeys: illegal address length for `%s'\n",
                   server);
          return -1;
        }
      memcpy (&addr.sin_addr, hp->h_addr, hp->h_length);
    }
  else
    {
      fprintf (console, "gpgkeys: host `%s' not found: ec=%d\n",
               server, (int)WSAGetLastError ());
      return -1;
    }

  sock = socket (AF_INET, SOCK_STREAM, 0);
  if (sock == INVALID_SOCKET)
    {
      fprintf (console, "gpgkeys: error creating socket: ec=%d\n", 
               (int)WSAGetLastError ());
      return -1;
    }

  if (connect (sock, (struct sockaddr *)&addr, sizeof addr))
    {
      fprintf (console, "gpgkeys: error connecting `%s': ec=%d\n", 
               server, (int)WSAGetLastError ());
      sock_close (sock);
      return -1;
    }

#else

  struct sockaddr_in addr;
  struct hostent *host;

  addr.sin_family = AF_INET;
  addr.sin_port = htons (port);
  host = gethostbyname ((char*)server);
  if (!host)
    {
      fprintf (console, "gpgkeys: host `%s' not found: %s\n",
               server, strerror (errno));
      return -1;
    }
  
  addr.sin_addr = *(struct in_addr*)host->h_addr;

  sock = socket (AF_INET, SOCK_STREAM, 0);
  if (sock == -1)
    {
      fprintf (console, "gpgkeys: error creating socket: %s\n", 
               strerror (errno));
      return -1;
    }
  
  if (connect (sock, (struct sockaddr *)&addr, sizeof addr) == -1)
    {
      fprintf (console, "gpgkeys: error connecting `%s': %s\n", 
               server, strerror (errno));
      close (sock);
      return -1;
    }
#endif
    
  return sock;
}
Beispiel #16
0
Pinger::Pinger() {
    // udp start
    sockaddr_in sa;     // for UDP and raw sockets

    // ICMP must accept all responses
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = INADDR_ANY;	
    sa.sin_port = 0;

    udpStarted = false;
    // attempt to initialize raw ICMP socket
    is = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    if (is != INVALID_SOCKET) {
        int nRet = bind(is, (sockaddr *)&sa, sizeof(sa));
        if (nRet==SOCKET_ERROR) { 
            nRet = WSAGetLastError();
            closesocket(is);        // ignore return value - error close anyway
        } else {
            // attempt to initialize ordinal UDP socket - why should this fail???
            // NB! no need to bind this at a moment - will be bound later, implicitly at sendto
            us = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
            if (us == INVALID_SOCKET) {
                closesocket(is);            // ignore return value - we need to close it anyway!
            } else {
                udpStarted = true;
            }
        }
    }
    // udp end
 
    // Open ICMP.DLL
    hICMP_DLL = LoadLibrary(_T("ICMP.DLL"));
    if (hICMP_DLL == 0) {
        theApp.QueueDebugLogLine(false,_T("Pinger: LoadLibrary() failed: Unable to locate ICMP.DLL!"));
        return;
    }

    // Get pointers to ICMP.DLL functions
    lpfnIcmpCreateFile  = (IcmpCreateFile*)GetProcAddress(hICMP_DLL,"IcmpCreateFile");
    lpfnIcmpCloseHandle = (IcmpCloseHandle*)GetProcAddress(hICMP_DLL,"IcmpCloseHandle");
    lpfnIcmpSendEcho    = (IcmpSendEcho*)GetProcAddress(hICMP_DLL,"IcmpSendEcho");
    if ((!lpfnIcmpCreateFile) || 
        (!lpfnIcmpCloseHandle) || 
        (!lpfnIcmpSendEcho)) {

        theApp.QueueDebugLogLine(false,_T("Pinger: GetProcAddr() failed for at least one function."));
        return;
    }

    // Open the ping service
    hICMP = (HANDLE) lpfnIcmpCreateFile();
    if (hICMP == INVALID_HANDLE_VALUE) {
        int nErr = GetLastError();
        theApp.QueueDebugLogLine(false, _T("Pinger: IcmpCreateFile() failed, err: %u"), nErr);
        PIcmpErr(nErr);
        return;
    }

    // Init IPInfo structure
    stIPInfo.Tos      = 0;
    stIPInfo.Flags    = 0;
    stIPInfo.OptionsSize = 0;
    stIPInfo.OptionsData = NULL;
}
Beispiel #17
0
INT	SOCKET_SOCKET_CLASS::readBinary(BYTE *buffer_ptr, UINT length)

//  DESCRIPTION     : Read data from socket to given buffer.
//  PRECONDITIONS   :
//  POSTCONDITIONS  :
//  EXCEPTIONS      : 
//  NOTES           : Blocks until all of the requested data is read or a timeout occurs.
//<<===========================================================================
{
	struct fd_set fds;
	struct timeval tv = {socketTimeoutM, 0};
	UINT read_bytes = 0; // number of bytes read from the socket

	if (loggerM_ptr) 
	{
		loggerM_ptr->text(LOG_DEBUG, 1, "TCP/IP - socket::read(%d)", length);
	}

	if (!connectedM) 
	{
		if (loggerM_ptr) 
		{
			loggerM_ptr->text(LOG_ERROR, 1, "TCP/IP - Not connected to peer - can't read data");
		}

		return -1;
	}

	FD_ZERO(&fds);
	FD_SET(socketFdM, &fds);

	while (read_bytes < length)
	{
		int sel;

		// wait for something to read
		sel = select(socketFdM + 1, &fds, NULL, NULL, &tv);
		if (sel == 1)
		{
			INT rv = recv(socketFdM, (char *)(buffer_ptr + read_bytes), (length - read_bytes), 0);
			if (rv > 0)
			{
				// read some data
				read_bytes += rv;
			}
			else if (rv == 0)
			{
				// socket closed
				if (loggerM_ptr)
				{
					loggerM_ptr->text(LOG_ERROR, 1, "TCP/IP - Socket closed during socket read");
				}
				return -1;
			}
			else if (rv == SOCKET_ERROR)
			{
				// read error
				if (loggerM_ptr)
				{
					loggerM_ptr->text(LOG_ERROR, 1, "TCP/IP - Socket read error (error code %d)", WSAGetLastError());
				}
				return -1;
			}
			else
			{
				// unknown read error
				if (loggerM_ptr)
				{
					loggerM_ptr->text(LOG_ERROR, 1, "TCP/IP - Unkown socket read error (read returned %d)", rv);
				}
				return -1;
			}
		}
		else if (sel == 0)
		{
			// no data at the end of the timeout
			if (loggerM_ptr)
			{
				loggerM_ptr->text(LOG_ERROR, 2, "TCP/IP - Connection timed-out while waiting to receive data");
				return -1;
			}
		}
		else if (sel == SOCKET_ERROR)
		{
			// socket error
			if (loggerM_ptr)
			{
				loggerM_ptr->text(LOG_ERROR, 2, "TCP/IP - Error waiting to receive data (error code %d)", WSAGetLastError());
				return -1;
			}
		}
		else
		{
			// unknown error
			if (loggerM_ptr)
			{
				loggerM_ptr->text(LOG_ERROR, 2, "TCP/IP - Unkown error while waiting to receive data (select returned %d)", sel);
				return -1;
			}
		}
	}

	return read_bytes;
}
Beispiel #18
0
PingStatus Pinger::PingUDP(uint32 lAddr, uint32 ttl, bool doLog) {
	// UDPing reworked ping sequence -->
	int nTTL = ttl;
	int nRet;
	sockaddr_in sa;
	int nAddrLen = sizeof(struct sockaddr_in); 
	char bufICMP[1500];             // allow full MTU

	// clear ICMP socket before sending UDP - not best solution, but may be needed to exclude late responses etc
	u_long bytes2read = 0;
	do {
		nRet = ioctlsocket(is, FIONREAD, &bytes2read);
		if (bytes2read > 0) {       // ignore errors here
			sa.sin_family = AF_INET;
			sa.sin_addr.s_addr = INADDR_ANY;	
			sa.sin_port = 0;

			nRet = recvfrom (is,    /* socket */ 
				(LPSTR)bufICMP,     /* buffer */ 
				1500,               /* length */ 
				0,                  /* flags  */ 
				(sockaddr*)&sa,     /* source */ 
				&nAddrLen);         /* addrlen*/

			//if (lastTimeOut) lastTimeOut--;
			//if (!lastTimeOut && toNowTimeOut) {
			//		toNowTimeOut--;
			//		if (toNowTimeOut) lastTimeOut = 3;
			//}
		}
	} while (bytes2read > 0);

	// set TTL value for UDP packet - should success with winsock 2
	// NB! take care about IP_TTL value - it's redefined in Ws2tcpip.h!
	// TODO: solve next problem correctly:
	// eMule is linking sockets functions using wsock32.lib (IP_TTL=7)
	// to use IP_TTL define, we must enforce linker to bind this function 
	// to ws2_32.lib (IP_TTL=4) (linker options: ignore wsock32.lib)
	nRet = setsockopt(us, IPPROTO_IP, IP_TTL, (char*)&nTTL, sizeof(int));
	if (nRet==SOCKET_ERROR) { 
		DWORD lastError = WSAGetLastError();
        PingStatus returnValue;
		returnValue.success = false;
		returnValue.delay = TIMEOUT;
		returnValue.error = lastError;
		//if (toNowTimeOut < 3) toNowTimeOut++;
		//	lastTimeOut = 3;
		return returnValue;
	} 

	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = lAddr;	
	sa.sin_port = htons(UDP_PORT);

	// send lonely UDP packet with almost minimal content (0 bytes is allowed too, but no data will be sent then)
	nRet = sendto(us, (LPSTR)&nTTL, 4, 0, (sockaddr*)&sa, sizeof(sa));  // send four bytes - TTL :)
    CTimeTick m_time;
    m_time.Tick();
	if (nRet==SOCKET_ERROR) { 
		DWORD lastError = WSAGetLastError();
        PingStatus returnValue;
		returnValue.success = false;
		returnValue.error = lastError;
		//if (toNowTimeOut < 3) toNowTimeOut++;
		//	lastTimeOut = 3;
		return returnValue;
	} 

	IPHeader* reply = (IPHeader*)bufICMP;

	bytes2read = 0;
	int timeoutOpt = TIMEOUT;
	bool noRcvTimeOut = false;
	nRet = setsockopt(is, SOL_SOCKET, SO_RCVTIMEO, (const char*) &timeoutOpt, sizeof(timeoutOpt));
	if (nRet==SOCKET_ERROR)
		noRcvTimeOut = true;

    float usResTime = 0.0f;
	while((usResTime += m_time.Tick()) < TIMEOUT){
		if (noRcvTimeOut){
			nRet = ioctlsocket(is, FIONREAD, &bytes2read);
			if (nRet != 0) {
				DWORD lastError = WSAGetLastError();
                PingStatus returnValue;
				returnValue.success = false;
				returnValue.delay = TIMEOUT;
				returnValue.error = lastError;
				//if (toNowTimeOut < 3) toNowTimeOut++;
				//	lastTimeOut = 3;
				return returnValue;
			}
			if (bytes2read > 0) {       // read and filter incoming ICMP

			} else {
				Sleep(1);         // share time with other threads
				continue;
			}
		}
		sa.sin_family = AF_INET;
		sa.sin_addr.s_addr = INADDR_ANY;	
		sa.sin_port = 0;
		nRet = recvfrom (is,    /* socket */ 
			(LPSTR)bufICMP,     /* buffer */ 
			1500,               /* length */ 
			0,                  /* flags  */ 
			(sockaddr*)&sa,     /* source */ 
			&nAddrLen);         /* addrlen*/ 

		usResTime += m_time.Tick();
		if (nRet==SOCKET_ERROR) { 
			DWORD lastError = WSAGetLastError();
            PingStatus returnValue;
			returnValue.success = false;
			returnValue.delay = TIMEOUT;
			returnValue.error = lastError;
			//if (toNowTimeOut < 3) toNowTimeOut++;
			//	lastTimeOut = 3;
			return returnValue;
		} 

		unsigned short header_len = reply->h_len * 4;
		ICMPHeader* icmphdr = (ICMPHeader*)(bufICMP + header_len);
		IN_ADDR stDestAddr;

		stDestAddr.s_addr = reply->source_ip;

		if (((icmphdr->type == ICMP_TTL_EXPIRE) || (icmphdr->type == ICMP_DEST_UNREACH)) &&
			(icmphdr->UDP.dest_port == htons(UDP_PORT)) && (icmphdr->hdrsent.dest_ip == lAddr)) {

            PingStatus returnValue;

            if(icmphdr->type == ICMP_TTL_EXPIRE) {
                returnValue.success = true;
			    returnValue.status = IP_TTL_EXPIRED_TRANSIT;
			    returnValue.delay = usResTime;
			    returnValue.destinationAddress = stDestAddr.s_addr;
			    returnValue.ttl = ttl;
            } else {
                returnValue.success = true;
                returnValue.status = IP_DEST_HOST_UNREACHABLE;
			    returnValue.delay = usResTime;
			    returnValue.destinationAddress = stDestAddr.s_addr;
			    returnValue.ttl = 64 - (reply->ttl & 63);
            }

			if(doLog) {
				theApp.QueueDebugLogLine(false,_T("Reply (UDP-pinger) from %s: bytes=%d time=%3.2fms TTL=%i"),
					ipstr(stDestAddr),
					nRet,
					usResTime,
					returnValue.ttl);
			}
			return returnValue;
		} else {              // verbose log filtered packets info (not seen yet...)
			//if (lastTimeOut) lastTimeOut--;
			//if (!lastTimeOut && toNowTimeOut) {
			//		toNowTimeOut--;
			//		if (toNowTimeOut) lastTimeOut = 3;
			//}
			if(doLog) {
				theApp.QueueDebugLogLine(false,_T("Filtered reply (UDP-pinger) from %s: bytes=%d time=%3.2fms TTL=%i type=%i"),
					ipstr(stDestAddr),
					nRet,
					usResTime,
					64 - (reply->ttl & 63),
					icmphdr->type);
			}
		}
	}
	//if (usResTime >= TIMEOUT) {
	//	if (toNowTimeOut < 3) toNowTimeOut++;
	//	lastTimeOut = 3;
	//}
	// UDPing reworked ping sequence end <--

    PingStatus returnValue;
	returnValue.success = false;
	returnValue.delay = TIMEOUT;
	returnValue.error = IP_REQ_TIMED_OUT;

    return returnValue;
}
Beispiel #19
0
/****** C_Communication::DoComm() const ****************************************
*  NAME
*     C_Communication::DoComm() const -- does the communication
*
*  SYNOPSIS
*     int C_Communication::DoComm() const
*
*  FUNCTION
*     Does the communication with sge_shepherd. I.e. whenever a sge_shepherd
*     connects to the server, it receives the request, does what is requested
*     and then shuts down the connection.
*
*  RESULT
*     int - 0 if command was successfully received and processed, 1 else
*
*  NOTES
*******************************************************************************/
int C_Communication::DoComm() const
{
   int                ret = 1;
   int                idx = 0;
   SOCKET             comm_sock;
   int                remote_saddr_len;
   struct sockaddr_in remote_saddr;
   char               szMessage[1024];
   char               command[COMMAND_SIZE];
   const int          commandsize = sizeof(command);
   C_Job              Job;
   C_Job              *pJob = NULL;
   en_request_type    request_type;

   remote_saddr_len = sizeof(remote_saddr);
   comm_sock = accept(m_ListenSocket, 
                     (struct sockaddr*)&remote_saddr, &remote_saddr_len);
   if(comm_sock == INVALID_SOCKET) {
      return WSAGetLastError();
   }

   ZeroMemory(command, COMMAND_SIZE);
   while((ret=recv(comm_sock, command+idx, commandsize-idx, 0))>0) {
      idx += ret;
      if(command[idx-1] == EOF) {
         break;
      }
   }
   if(ret == -1) {
      ret = WSAGetLastError();
      ShutdownSocket(&comm_sock);
      return ret;
   }
   ret = 0;

   WriteToLogFile("Received new request, will parse it now.");
   request_type = Job.ParseCommand(command);
   WriteToLogFile("Finished parsing the new request.");

   switch(request_type) {
      case req_job_start:
         {
            BOOL   bAlreadyInList = TRUE;
            HANDLE hThread;

            WriteToLogFile("Got a job start request.");

            if(g_bAcceptJobs) {
               Job.m_comm_sock = comm_sock;

               sprintf(szMessage, "Starting job %lu.%lu %s", 
                  Job.m_job_id, Job.m_ja_task_id,
                  Job.m_pe_task_id ? Job.m_pe_task_id : "<null>");
               WriteToLogFile(szMessage);

               // try to put job in job list
               pJob = new C_Job(Job);
               bAlreadyInList = g_JobList.AddJobToList(pJob);
            }

            if (bAlreadyInList == FALSE) {
               WriteToLogFile("New job, starting thread");
               // job is not already in job list, send ACK and start worker thread
               hThread = CreateThread(NULL, 0, JobStarterThread, 0, 0, 0);
               CloseHandle(hThread);
            } else {
               WriteToLogFile("Existing job, send NACK and delete job object");
               // job is already in job list, send NACK and delete job object
               strcpy(szMessage, "NAK");
               szMessage[strlen(szMessage)+1] = (char)EOF;
               send(comm_sock, szMessage, (int)strlen(szMessage)+2, 0);
               ShutdownSocket(&comm_sock);
               delete pJob;
               pJob = NULL;
            }
         }
         break;

      case req_send_job_usage:
         WriteToLogFile("Got a send usage request.");
         pJob = g_JobList.RemoveJobFromList(Job);
         if(pJob) {
            pJob->m_comm_sock = comm_sock;
            SendJobUsage(*pJob);
            delete pJob;
            pJob = NULL;
            sprintf(szMessage, "Sending usage of job %lu.%lu %s",
                        Job.m_job_id, Job.m_ja_task_id,
                        Job.m_pe_task_id ? Job.m_pe_task_id : "<null>");
         } else {
            sprintf(szMessage, "Warning: Job %lu.%lu %s not found!",
                        Job.m_job_id, Job.m_ja_task_id,
                        Job.m_pe_task_id ? Job.m_pe_task_id : "<null>");
         }
         WriteToLogFile(szMessage);
         ShutdownSocket(&comm_sock);
         break;

      case req_forward_signal:
         WriteToLogFile("Got a forward signal request.");
         // lock access to job list
         WaitForSingleObject(g_JobList.m_hJobListMutex, INFINITE);
         pJob = g_JobList.FindJobInList(Job);
         if(pJob
            && pJob->m_JobStatus != js_Finished
            && pJob->m_JobStatus != js_Failed
            && pJob->m_JobStatus != js_Deleted) {
            BOOL bRet = FALSE;
            char szAnswer[100];
            int  sent;

            if(pJob->m_hProcess != INVALID_HANDLE_VALUE
               && pJob->m_hJobObject != INVALID_HANDLE_VALUE) {
               bRet = TerminateJobObject(pJob->m_hJobObject, 0);
               if(bRet) {
                  pJob->m_JobStatus = js_Deleted;
               }
            }
            ReleaseMutex(g_JobList.m_hJobListMutex);

            sprintf(szAnswer, "%s", bRet ? "ACK" : "NAK");
            szAnswer[strlen(szAnswer)+1] = (char)EOF;
            sent = send(comm_sock, szAnswer, (int)strlen(szAnswer)+2, 0);
            if(sent >= 0) {
               ret = 0;
            }
         } else {
	         ReleaseMutex(g_JobList.m_hJobListMutex);
         }
         ShutdownSocket(&comm_sock);
         break;
   }
   return ret;
}
Beispiel #20
0
// Initialize the listener, set up the socket to listen on, or return an error
CListener::ErrorType CListener::Initialize(int TCPSocket)
{
	TCHAR MsgText[100];
	CString TCPSocketText;
	TCPSocketText.Format(_T("%i"),TCPSocket);

	WSADATA wsadata;
	if (WSAStartup(MAKEWORD(2,0), &wsadata))
		return UnknownError;

	// Get list of addresses to listen on
	ADDRINFOT Hints, *AddrInfo, *AI;
	memset(&Hints, 0, sizeof (Hints));
	Hints.ai_family = PF_UNSPEC;
	Hints.ai_socktype = SOCK_STREAM;
	Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
	if (GetAddrInfo(NULL, TCPSocketText, &Hints, &AddrInfo) != 0)
	{
		StringCchPrintf(MsgText, _countof(MsgText), _T("getaddressinfo error: %i"), GetLastError());
		LogWarning(MsgText);
		return UnknownError;
	}

	// Create one or more passive sockets to listen on
	int i;
	for (i = 0, AI = AddrInfo; AI != NULL; AI = AI->ai_next)
	{
		// Did we receive more addresses than we can handle?  Highly unlikely, but check anyway.
		if (i == FD_SETSIZE) break;

		// Only support PF_INET and PF_INET6.  If something else, skip to next address.
		if ((AI->ai_family != AF_INET) && (AI->ai_family != AF_INET6)) continue;

		// StringCchPrintf(MsgText, _countof(MsgText), _T("::OnInit i = %d, ai_family = %d"), i, AI->ai_family);
		// LogWarning(MsgText);

		m_hSocketEvents[i] = CreateEvent(
			NULL,		// no security attributes
			true,		// manual reset event
			false,		// not signaled
			NULL);		// no name

		if (!(m_hSocketEvents[i]))
			return UnknownError;

		// StringCchPrintf(MsgText, _countof(MsgText), _T("::OnInit Created m_hSocketEvents[%d], handle=%d"), i, m_hSocketEvents[i]);
		// LogWarning(MsgText);

		m_iListenSockets[i] = WSASocket(AI->ai_family, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
		if (m_iListenSockets[i] == INVALID_SOCKET)
			return SocketUnusable;

		// StringCchPrintf(MsgText, _countof(MsgText), _T("::OnInit binding m_iListenSockets[%d] to sa_family=%u sa_data=%s len=%d"), i, AI->ai_addr->sa_family, AI->ai_addr->sa_data, AI->ai_addrlen);
		// LogWarning(MsgText);

		int rc = bind(m_iListenSockets[i], AI->ai_addr, (int)AI->ai_addrlen);
		if (rc)
		{
			if (WSAGetLastError()==WSAEADDRINUSE)
				return SocketInuse;
			else
				return SocketUnusable;
		}

		if (listen(m_iListenSockets[i], 10))
			return SocketUnusable;
		if (WSAEventSelect(m_iListenSockets[i], m_hSocketEvents[i], FD_ACCEPT))
			return SocketUnusable;
		i++;
	}

	m_iNumListenSockets = i;

	// StringCchPrintf(MsgText, _countof(MsgText), _T("::OnInit no errors, m_iNumListenSockets = %d"), m_iNumListenSockets);
	// LogWarning(MsgText);

	return NoError;
}
Beispiel #21
0
int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait)
{
	DWORD timeout = 0; /* in milliseconds */	
	DWORD ret;
	WSANETWORKEVENTS netev;
	struct _getdns_event* eventlist[WSK_MAX_ITEMS];
	int i, numwait = 0, startidx = 0, was_timeout = 0;
	int newstickies = 0;
	struct timeval nultm;

	printf("in handle select\n");

#ifndef S_SPLINT_S
        if(wait->tv_sec==(time_t)-1)
                wait = NULL;
		if (wait)
		//	timeout = 10 + wait->tv_usec / 1000;
		 timeout = wait->tv_sec * 1000 + wait->tv_usec / 1000;
 	if(base->tcp_stickies) {
		wait = &nultm;
		nultm.tv_sec = 0;
		nultm.tv_usec = 0;
		timeout = 0; /* no waiting, we have sticky events */
	}
#endif

	/* prepare event array */
	for(i=0; i<base->max; i++) {
		if(base->items[i]->ev_fd == -1 && !base->items[i]->is_signal)
			continue; /* skip timer only events */
		eventlist[numwait] = base->items[i];
		base->waitfor[numwait++] = base->items[i]->hEvent;
		printf("winsock_event bmax=%d numwait=%d wait=%x "
			"timeout=%d hEvent %d\n", base->max, numwait, (int)wait, (int)timeout, base->items[i]->hEvent);
		if (numwait == WSK_MAX_ITEMS)
			break; /* sanity check */
	}
	//log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS);

	/* do the wait */
	if(numwait == 0) {
		/* WSAWaitFor.. doesn't like 0 event objects */
		if(wait) {
			Sleep(timeout);
		}
		was_timeout = 1;
	}
	else {
		//g do not sched udp write
		for (i = 0; i<base->max; i++) {
			if (!base->items[i]->is_tcp && base->items[i]->ev_events&EV_WRITE) {
				//gprintf("skip UDP sched\n");
				(*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
					EV_WRITE & eventlist[i]->ev_events,
					eventlist[i]->ev_arg);
				return 0;
			}
	    } 
		//gprintf("before wait %d\n", base->items[0]->ev_events);
		ret = WSAWaitForMultipleEvents(numwait, base->waitfor,
			0 /* do not wait for all, just one will do */,
			wait?timeout:WSA_INFINITE,
			0); /* we are not alertable (IO completion events) */
		//gprintf("after wait %d %d\n", ret, numwait);
		if(ret == WSA_WAIT_IO_COMPLETION) {
			//printf("getdns: WSAWaitForMultipleEvents failed: WSA_WAIT_IO_COMPLETION");
			return -1;
		} else if(ret == WSA_WAIT_FAILED) {
			//printf("getdns: WSAWaitForMultipleEvents failed: %s", 
			//	wsa_strerror(WSAGetLastError()));
			return -1;
		} else if(ret == WSA_WAIT_TIMEOUT) {
			//printf("timeout\n");
			was_timeout = 1;
		} else
			startidx = ret - WSA_WAIT_EVENT_0;
	}
	////verbose(VERB_CLIENT, "winsock_event wake was_timeout=%d startidx=%d", 
	//	was_timeout, startidx);

	/* get new time after wait */
        if(settime(base) < 0)
               return -1;

	/* callbacks */
	if(base->tcp_stickies)
		startidx = 0; /* process all events, some are sticky */
	for(i=startidx; i<numwait; i++)
		eventlist[i]->just_checked = 1;

	//verbose(VERB_CLIENT, "winsock_event signals");
	for(i=startidx; i<numwait; i++) {
		if(!base->waitfor[i])
			continue; /* was deleted */
		if(eventlist[i]->is_signal) {
			eventlist[i]->just_checked = 0;
			_getdns_handle_signal(eventlist[i]);
		}
	}
	/* early exit - do not process network, exit quickly */
	if(base->need_to_exit)
		return 0;

	//verbose(VERB_CLIENT, "winsock_event net");
	for(i=startidx; i<numwait; i++) {
		short bits = 0;
		/* eventlist[i] fired */
		/* see if eventlist[i] is still valid and just checked from
		 * WSAWaitForEvents */
		if(!base->waitfor[i])
			continue; /* was deleted */
		if(!eventlist[i]->just_checked)
			continue; /* added by other callback */
		if(eventlist[i]->is_signal)
			continue; /* not a network event at all */
		eventlist[i]->just_checked = 0;

		if(WSAEnumNetworkEvents(eventlist[i]->ev_fd, 
			base->waitfor[i], /* reset the event handle */
			/*NULL,*/ /* do not reset the event handle */
			&netev) != 0) {
			log_err("getdns: WSAEnumNetworkEvents failed: %s", 
				wsa_strerror(WSAGetLastError()));
			return -1;
		}
		if((netev.lNetworkEvents & FD_READ)) {
			if(netev.iErrorCode[FD_READ_BIT] != 0)
				printf("FD_READ_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_READ_BIT]));
			bits |= EV_READ;
			printf("FD_READ_BIT\n");
		}
		if((netev.lNetworkEvents & FD_WRITE)) {
			if(netev.iErrorCode[FD_WRITE_BIT] != 0)
				printf("FD_WRITE_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_WRITE_BIT]));
			bits |= EV_WRITE;
			printf("FD_WRITE_BIT\n");
		}
		if((netev.lNetworkEvents & FD_CONNECT)) {
			if(netev.iErrorCode[FD_CONNECT_BIT] != 0)
				printf("FD_CONNECT_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_CONNECT_BIT]));
			bits |= EV_READ;
			bits |= EV_WRITE;
			printf("FD_CONNECT_BIT\n");
		}
		if((netev.lNetworkEvents & FD_ACCEPT)) {
			if(netev.iErrorCode[FD_ACCEPT_BIT] != 0)
				printf("FD_ACCEPT_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_ACCEPT_BIT]));
			bits |= EV_READ;
			printf("FD_ACCEPT_BIT\n");
		}
		if((netev.lNetworkEvents & FD_CLOSE)) {
			if(netev.iErrorCode[FD_CLOSE_BIT] != 0)
				printf("FD_CLOSE_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_CLOSE_BIT]));
			bits |= EV_READ;
			bits |= EV_WRITE;
			printf("FD_CLOSE_BIT\n");
		}
		if(eventlist[i]->is_tcp && eventlist[i]->stick_events) {
			/*
			printf("winsock %d pass sticky %s%s\n",
				eventlist[i]->ev_fd,
   			    (eventlist[i]->old_events&EV_READ)?"EV_READ":"",
				(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
			*/
			bits |= eventlist[i]->old_events;
		}
		if(eventlist[i]->is_tcp && bits) {
			eventlist[i]->old_events = bits;
			eventlist[i]->stick_events = 1;
			if((eventlist[i]->ev_events & bits)) {
				newstickies = 1;
			}
			/*
		printf("winsock %d store sticky %s%s",
				eventlist[i]->ev_fd,
				(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
				(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
			*/	
		}
		if((bits & eventlist[i]->ev_events)) {
		/*     printf( "winsock event callback %p fd=%d "
			    "%s%s%s%s%s ; %s%s%s\n", 
				eventlist[i], eventlist[i]->ev_fd,
				(netev.lNetworkEvents&FD_READ)?" FD_READ":"",
				(netev.lNetworkEvents&FD_WRITE)?" FD_WRITE":"",
				(netev.lNetworkEvents&FD_CONNECT)?
					" FD_CONNECT":"",
			    (netev.lNetworkEvents&FD_ACCEPT)?
					" FD_ACCEPT":"",
				(netev.lNetworkEvents&FD_CLOSE)?" FD_CLOSE":"",
			    (bits&EV_READ)?" EV_READ":"",
			    (bits&EV_WRITE)?" EV_WRITE":"",
				(bits&EV_TIMEOUT)?" EV_TIMEOUT":"");
				*/
				fptr_ok(fptr_whitelist_event(
					eventlist[i]->ev_callback));
				(*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
					bits & eventlist[i]->ev_events,
					eventlist[i]->ev_arg);
		}
		/*
	   if(eventlist[i]->is_tcp && bits)
			printf( "winsock %d got sticky %s%s\n",
				eventlist[i]->ev_fd,
				(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
				(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
	   */
	}
	//verbose(VERB_CLIENT, "winsock_event net");
	if(base->tcp_reinvigorated) {
		printf("winsock_event reinvigorated\n");
		base->tcp_reinvigorated = 0;
		newstickies = 1;
	}
	base->tcp_stickies = newstickies;
	//gprintf("winsock_event handle_select end\n");
        return 0;
}
/*
 * Class:     java_net_DualStackPlainSocketImpl
 * Method:    listen0
 * Signature: (II)V
 */
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_listen0
  (JNIEnv *env, jclass clazz, jint fd, jint backlog) {
    if (listen(fd, backlog) == SOCKET_ERROR) {
        NET_ThrowNew(env, WSAGetLastError(), "listen failed");
    }
}
Beispiel #23
0
void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
  int err;
  unsigned int i;
  uv_tcp_accept_t* req;

  if (handle->flags & UV_HANDLE_CONNECTION &&
      handle->shutdown_req != NULL &&
      handle->write_reqs_pending == 0) {

    UNREGISTER_HANDLE_REQ(loop, handle, handle->shutdown_req);

    err = 0;
    if (handle->flags & UV__HANDLE_CLOSING) {
      err = ERROR_OPERATION_ABORTED;
    } else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) {
      err = WSAGetLastError();
    }

    if (handle->shutdown_req->cb) {
      handle->shutdown_req->cb(handle->shutdown_req,
                               uv_translate_sys_error(err));
    }

    handle->shutdown_req = NULL;
    DECREASE_PENDING_REQ_COUNT(handle);
    return;
  }

  if (handle->flags & UV__HANDLE_CLOSING &&
      handle->reqs_pending == 0) {
    assert(!(handle->flags & UV_HANDLE_CLOSED));

    if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) {
      closesocket(handle->socket);
      handle->flags |= UV_HANDLE_TCP_SOCKET_CLOSED;
    }

    if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->accept_reqs) {
      if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
        for (i = 0; i < uv_simultaneous_server_accepts; i++) {
          req = &handle->accept_reqs[i];
          if (req->wait_handle != INVALID_HANDLE_VALUE) {
            UnregisterWait(req->wait_handle);
            req->wait_handle = INVALID_HANDLE_VALUE;
          }
          if (req->event_handle) {
            CloseHandle(req->event_handle);
            req->event_handle = NULL;
          }
        }
      }

      free(handle->accept_reqs);
      handle->accept_reqs = NULL;
    }

    if (handle->flags & UV_HANDLE_CONNECTION &&
        handle->flags & UV_HANDLE_EMULATE_IOCP) {
      if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
        UnregisterWait(handle->read_req.wait_handle);
        handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
      }
      if (handle->read_req.event_handle) {
        CloseHandle(handle->read_req.event_handle);
        handle->read_req.event_handle = NULL;
      }
    }

    uv__handle_close(handle);
    loop->active_tcp_streams--;
  }
}
Beispiel #24
0
int main() {

	SOCKET wsocket;
	
	struct sockaddr_in server;
	struct sockaddr_in secondary_input;

	int slen;
	int recv_len;

	char _buffer[BUFLEN];
	WSADATA wsa;

	slen = sizeof(secondary_input);

	// initialize socket
	printf("%s\n", "Initializing dear system sequence...");

	if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
		printf("%s%s\n", "ERR", "winsock failure initializing. Rejecting telemetry.");
		return WSAGetLastError();
	}

	printf("%s", "Winsock initialized...\n");

	// create socket
	if(wsocket = socket(AF_INET, SOCK_DGRAM, 0) == INVALID_SOCKET) {
		printf("%s%s\n", "ERR", "winsock failure spawning. Rejecting telemetry.");
		return WSAGetLastError();
	}

	printf("%s", "Winsock spawned. Binding...");

	// set struct properties
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = htons(PORT);

	// bind socket
	if(bind(wsocket, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
		printf("%s%s\n", "ERR", "winsock failure binding. Rejecting telemetry.");
		return WSAGetLastError();
	}

	printf("%s", "winsock ready. Listening for telemetry...\n");

	while(1) {

		fflush(stdout);
		memset(_buffer, '\0', BUFLEN);

		// receive data
		if((recv_len = recvfrom(wsocket, _buffer, BUFLEN, 0, (struct sockaddr *)&secondary_input, &slen)) == SOCKET_ERROR) {
			printf("%s\n", "winsock failure receiving telemetry. Flushing...");
			return WSAGetLastError();
		}

		// print data
		printf("%s\n", _buffer);

	}

	closesocket(wsocket);
	WSACleanup();

	return 0;
}
Beispiel #25
0
static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
  uv_loop_t* loop = handle->loop;
  BOOL success;
  DWORD bytes;
  SOCKET accept_socket;
  short family;

  assert(handle->flags & UV_HANDLE_LISTENING);
  assert(req->accept_socket == INVALID_SOCKET);

  /* choose family and extension function */
  if (handle->flags & UV_HANDLE_IPV6) {
    family = AF_INET6;
  } else {
    family = AF_INET;
  }

  /* Open a socket for the accepted connection. */
  accept_socket = socket(family, SOCK_STREAM, 0);
  if (accept_socket == INVALID_SOCKET) {
    SET_REQ_ERROR(req, WSAGetLastError());
    uv_insert_pending_req(loop, (uv_req_t*)req);
    handle->reqs_pending++;
    return;
  }

  /* Make the socket non-inheritable */
  if (!SetHandleInformation((HANDLE) accept_socket, HANDLE_FLAG_INHERIT, 0)) {
    SET_REQ_ERROR(req, GetLastError());
    uv_insert_pending_req(loop, (uv_req_t*)req);
    handle->reqs_pending++;
    closesocket(accept_socket);
    return;
  }

  /* Prepare the overlapped structure. */
  memset(&(req->overlapped), 0, sizeof(req->overlapped));
  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
    req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
  }

  success = handle->func_acceptex(handle->socket,
                                  accept_socket,
                                  (void*)req->accept_buffer,
                                  0,
                                  sizeof(struct sockaddr_storage),
                                  sizeof(struct sockaddr_storage),
                                  &bytes,
                                  &req->overlapped);

  if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
    /* Process the req without IOCP. */
    req->accept_socket = accept_socket;
    handle->reqs_pending++;
    uv_insert_pending_req(loop, (uv_req_t*)req);
  } else if (UV_SUCCEEDED_WITH_IOCP(success)) {
    /* The req will be processed with IOCP. */
    req->accept_socket = accept_socket;
    handle->reqs_pending++;
    if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
        req->wait_handle == INVALID_HANDLE_VALUE &&
        !RegisterWaitForSingleObject(&req->wait_handle,
          req->event_handle, post_completion, (void*) req,
          INFINITE, WT_EXECUTEINWAITTHREAD)) {
      SET_REQ_ERROR(req, GetLastError());
      uv_insert_pending_req(loop, (uv_req_t*)req);
      handle->reqs_pending++;
      return;
    }
  } else {
    /* Make this req pending reporting an error. */
    SET_REQ_ERROR(req, WSAGetLastError());
    uv_insert_pending_req(loop, (uv_req_t*)req);
    handle->reqs_pending++;
    /* Destroy the preallocated client socket. */
    closesocket(accept_socket);
    /* Destroy the event handle */
    if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
      CloseHandle(req->overlapped.hEvent);
      req->event_handle = NULL;
    }
  }
}
Beispiel #26
0
int zmq::tcp_listener_t::set_address (const char *addr_)
{
    //  Convert the textual address into address structure.
    int rc = address.resolve (addr_, true, options.ipv4only ? true : false);
    if (rc != 0)
        return -1;

    //  Create a listening socket.
    s = open_socket (address.family (), SOCK_STREAM, IPPROTO_TCP);
#ifdef ZMQ_HAVE_WINDOWS
    if (s == INVALID_SOCKET)
        errno = wsa_error_to_errno (WSAGetLastError ());
#endif

    //  IPv6 address family not supported, try automatic downgrade to IPv4.
    if (address.family () == AF_INET6 && errno == EAFNOSUPPORT &&
          !options.ipv4only) {
        rc = address.resolve (addr_, true, true);
        if (rc != 0)
            return rc;
        s = ::socket (address.family (), SOCK_STREAM, IPPROTO_TCP);
    }

#ifdef ZMQ_HAVE_WINDOWS
    if (s == INVALID_SOCKET) {
        errno = wsa_error_to_errno (WSAGetLastError ());
        return -1;
    }
    //  On Windows, preventing sockets to be inherited by child processes.
    BOOL brc = SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
    win_assert (brc);
#else
    if (s == -1)
        return -1;
#endif

    //  On some systems, IPv4 mapping in IPv6 sockets is disabled by default.
    //  Switch it on in such cases.
    if (address.family () == AF_INET6)
        enable_ipv4_mapping (s);

    //  Allow reusing of the address.
    int flag = 1;
#ifdef ZMQ_HAVE_WINDOWS
    rc = setsockopt (s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
        (const char*) &flag, sizeof (int));
    wsa_assert (rc != SOCKET_ERROR);
#else
    rc = setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof (int));
    errno_assert (rc == 0);
#endif

    address.to_string (endpoint);

    //  Bind the socket to the network interface and port.
    rc = bind (s, address.addr (), address.addrlen ());
#ifdef ZMQ_HAVE_WINDOWS
    if (rc == SOCKET_ERROR) {
        errno = wsa_error_to_errno (WSAGetLastError ());
        goto error;
    }
#else
    if (rc != 0)
        goto error;
#endif

    //  Listen for incomming connections.
    rc = listen (s, options.backlog);
#ifdef ZMQ_HAVE_WINDOWS
    if (rc == SOCKET_ERROR) {
        errno = wsa_error_to_errno (WSAGetLastError ());
        goto error;
    }
#else
    if (rc != 0)
        goto error;
#endif

    socket->monitor_event (ZMQ_EVENT_LISTENING, addr_, s);
    return 0;

error:
    int err = errno;
    close ();
    errno = err;
    return -1;
}
Beispiel #27
0
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
  uv_loop_t* loop = handle->loop;
  unsigned int i, simultaneous_accepts;
  uv_tcp_accept_t* req;
  int err;

  assert(backlog > 0);

  if (handle->flags & UV_HANDLE_LISTENING) {
    handle->connection_cb = cb;
  }

  if (handle->flags & UV_HANDLE_READING) {
    return WSAEISCONN;
  }

  if (handle->flags & UV_HANDLE_BIND_ERROR) {
    return handle->bind_error;
  }

  if (!(handle->flags & UV_HANDLE_BOUND)) {
    err = uv_tcp_try_bind(handle,
                          (const struct sockaddr*) &uv_addr_ip4_any_,
                          sizeof(uv_addr_ip4_any_),
                          0);
    if (err)
      return err;
  }

  if (!handle->func_acceptex) {
    if (!uv_get_acceptex_function(handle->socket, &handle->func_acceptex)) {
      return WSAEAFNOSUPPORT;
    }
  }

  if (!(handle->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&
      listen(handle->socket, backlog) == SOCKET_ERROR) {
    return WSAGetLastError();
  }

  handle->flags |= UV_HANDLE_LISTENING;
  handle->connection_cb = cb;
  INCREASE_ACTIVE_COUNT(loop, handle);

  simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1
    : uv_simultaneous_server_accepts;

  if(!handle->accept_reqs) {
    handle->accept_reqs = (uv_tcp_accept_t*)
      malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t));
    if (!handle->accept_reqs) {
      uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
    }

    for (i = 0; i < simultaneous_accepts; i++) {
      req = &handle->accept_reqs[i];
      uv_req_init(loop, (uv_req_t*)req);
      req->type = UV_ACCEPT;
      req->accept_socket = INVALID_SOCKET;
      req->data = handle;

      req->wait_handle = INVALID_HANDLE_VALUE;
      if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
        req->event_handle = CreateEvent(NULL, 0, 0, NULL);
        if (!req->event_handle) {
          uv_fatal_error(GetLastError(), "CreateEvent");
        }
      } else {
        req->event_handle = NULL;
      }

      uv_tcp_queue_accept(handle, req);
    }

    /* Initialize other unused requests too, because uv_tcp_endgame */
    /* doesn't know how how many requests were intialized, so it will */
    /* try to clean up {uv_simultaneous_server_accepts} requests. */
    for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) {
      req = &handle->accept_reqs[i];
      uv_req_init(loop, (uv_req_t*) req);
      req->type = UV_ACCEPT;
      req->accept_socket = INVALID_SOCKET;
      req->data = handle;
      req->wait_handle = INVALID_HANDLE_VALUE;
      req->event_handle = NULL;
    }
  }

  return 0;
}
Beispiel #28
0
void zmq::udp_engine_t::in_event()
{
  struct sockaddr_in in_address;
  socklen_t in_addrlen = sizeof(sockaddr_in);
#ifdef ZMQ_HAVE_WINDOWS
    int nbytes = recvfrom(fd, (char*) in_buffer, MAX_UDP_MSG, 0, (sockaddr*) &in_address, &in_addrlen);
    const int last_error = WSAGetLastError();
    if (nbytes == SOCKET_ERROR) {
        wsa_assert(
            last_error == WSAENETDOWN ||
            last_error == WSAENETRESET ||
            last_error == WSAEWOULDBLOCK);
        return;
    }
#else
    int nbytes = recvfrom(fd, in_buffer, MAX_UDP_MSG, 0, (sockaddr*) &in_address, &in_addrlen);
    if (nbytes == -1) {
        errno_assert(errno != EBADF
            && errno != EFAULT
            && errno != ENOMEM
            && errno != ENOTSOCK);
        return;
    }
#endif
    int rc;
    int body_size;
    int body_offset;
    msg_t msg;

    if (options.raw_socket) {
        sockaddr_to_msg (&msg, &in_address);

        body_size = nbytes;
        body_offset = 0;
    }
    else {
        char* group_buffer = (char *)in_buffer + 1;
        int group_size = in_buffer[0];

        rc = msg.init_size (group_size);
        errno_assert (rc == 0);
        msg.set_flags (msg_t::more);
        memcpy (msg.data (), group_buffer, group_size);

        //  This doesn't fit, just ingore
        if (nbytes - 1 < group_size)
            return;

        body_size = nbytes - 1 - group_size;
        body_offset = 1 + group_size;
    }

    rc = session->push_msg (&msg);
    errno_assert (rc == 0 || (rc == -1 && errno == EAGAIN));

    //  Pipe is full
    if (rc != 0) {
        rc = msg.close ();
        errno_assert (rc == 0);

        reset_pollin (handle);
        return;
    }

    rc = msg.close ();
    errno_assert (rc == 0);
    rc = msg.init_size (body_size);
    errno_assert (rc == 0);
    memcpy (msg.data (), in_buffer + body_offset, body_size);
    rc = session->push_msg (&msg);
    errno_assert (rc == 0);
    rc = msg.close ();
    errno_assert (rc == 0);
    session->flush ();
}
Beispiel #29
0
int uv_tcp_write(uv_loop_t* loop,
                 uv_write_t* req,
                 uv_tcp_t* handle,
                 const uv_buf_t bufs[],
                 unsigned int nbufs,
                 uv_write_cb cb) {
  int result;
  DWORD bytes;

  uv_req_init(loop, (uv_req_t*) req);
  req->type = UV_WRITE;
  req->handle = (uv_stream_t*) handle;
  req->cb = cb;

  /* Prepare the overlapped structure. */
  memset(&(req->overlapped), 0, sizeof(req->overlapped));
  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
    req->event_handle = CreateEvent(NULL, 0, 0, NULL);
    if (!req->event_handle) {
      uv_fatal_error(GetLastError(), "CreateEvent");
    }
    req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
    req->wait_handle = INVALID_HANDLE_VALUE;
  }

  result = WSASend(handle->socket,
                   (WSABUF*) bufs,
                   nbufs,
                   &bytes,
                   0,
                   &req->overlapped,
                   NULL);

  if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
    /* Request completed immediately. */
    req->queued_bytes = 0;
    handle->reqs_pending++;
    handle->write_reqs_pending++;
    REGISTER_HANDLE_REQ(loop, handle, req);
    uv_insert_pending_req(loop, (uv_req_t*) req);
  } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
    /* Request queued by the kernel. */
    req->queued_bytes = uv_count_bufs(bufs, nbufs);
    handle->reqs_pending++;
    handle->write_reqs_pending++;
    REGISTER_HANDLE_REQ(loop, handle, req);
    handle->write_queue_size += req->queued_bytes;
    if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
        !RegisterWaitForSingleObject(&req->wait_handle,
          req->event_handle, post_write_completion, (void*) req,
          INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) {
      SET_REQ_ERROR(req, GetLastError());
      uv_insert_pending_req(loop, (uv_req_t*)req);
    }
  } else {
    /* Send failed due to an error. */
    return WSAGetLastError();
  }

  return 0;
}
CString CHttpReqSocket::GetHTTPContent(CString strHost, CString strRequest,
									   bool* pbCancelDownload, int& nError,
									   int nApproxContentLength,									   
									   CProgressCtrl *pProgress, CWnd* pStatus,
									   CString strFilename)
{
	// init sockets
	AfxSocketInit ();
	CHttpReqSocket socket;
	nError = 0;

	// try to create the socket
	if (!socket.Create ())
	{
		nError = WSAGetLastError ();
		return "";
	}

	// try to connect to server
	if (!socket.Connect (strHost, 80))
	{
		nError = socket.GetLastError ();
		socket.Close ();
		return "";
	}

	// wait for response
	socket.Send (strRequest, strRequest.GetLength ());

	CString strRecv;
	char szBuf[4096 + 1];
	int nPos, nContLen = -1;
	int nLen = 0;

	// create and open file, if stream is to be written to a file
	// (i.e. strFilename is not empty)
	CFile file;
	bool bUseFile = !strFilename.IsEmpty ();
	bool bHeaderRead = false;
	if (bUseFile)
		file.Open (strFilename, CFile::modeCreate | CFile::modeWrite);

	// init progress control
	if (pProgress != NULL)
		pProgress->SetRange32 (0, nApproxContentLength);

	MSG msg;

	CString strStatus;

	// read http stream
	for (int nRead = 1; nRead > 0; )
	{
		if (*pbCancelDownload)
			break;

		// read from the socket
		nRead = socket.Receive (szBuf, 4096);

		switch (nRead)
		{
		case 0:
			continue;
		case SOCKET_ERROR:
			nError = socket.GetLastError ();
			break;
		default:
			if (bUseFile)
			{
				// write stream to file
				if (!bHeaderRead)
				{
					// try to get the Content-Length header
					char* pBuf = strstr (szBuf, "Content-Length:");
					if (pBuf)
						nContLen = atoi (pBuf + 15);
					if (pProgress != NULL)
						pProgress->SetRange32 (0, nContLen);

					// cut off the header (should not be saved to the file)
					pBuf = strstr (szBuf, "\r\n\r\n");
					int nHeaderLen = (int) (pBuf - szBuf);
					file.Write (pBuf + 4, nRead - nHeaderLen - 4);
//					file.Write (szBuf, nRead);

					// return the header
					LPSTR pRecvBuf = strRecv.GetBuffer (nHeaderLen);
					strncpy (pRecvBuf, szBuf, nHeaderLen);
					pRecvBuf[nHeaderLen] = '\0';
					strRecv.ReleaseBuffer ();

					bHeaderRead = true;
				}
				else
					file.Write (szBuf, nRead);
			}
			else
			{
				// save stream as string to return
				szBuf[nRead] = '\0';
				strRecv += szBuf;

				// try to get the Content-Length header
				// and set the progress control's range appropriately
				if (!bHeaderRead)
				{
					if ((nPos = strRecv.Find ("Content-Length:")) >= 0)
					{
						nContLen = atoi (strRecv.Mid (nPos + 15));
						if (pProgress != NULL)
							pProgress->SetRange32 (0, nContLen);
					}
					bHeaderRead = true;
				}
			}
		}

		nLen += nRead;

		if (nContLen >= 0)
			if (nLen >= nContLen)
				nRead = 0;

		if (pProgress != NULL)
			pProgress->SetPos (nLen);
		if (pStatus != NULL)
		{
			strStatus.Format (IDS_DOWNLOADSTATUS, (double) nLen / 1024.0, (double) nContLen / 1024.0);
			pStatus->SetWindowText (strStatus);
		}

		while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
			DispatchMessage (&msg);
	}

	socket.Close ();

	if (bUseFile)
		file.Close ();

	return strRecv;
}