int __cdecl main(int argc, char **argv) { char *interface = NULL; char *Buffer = NULL; char *port = DEFAULT_PORT; char host[NI_MAXHOST]; char serv[NI_MAXSERV]; int hostlen = NI_MAXHOST; int servlen = NI_MAXSERV; int ai_family = AF_UNSPEC; int i = 0; int nStartup = 0; struct addrinfo hints = {0}; struct addrinfo *local = NULL; WSADATA wsaData; SOCKET listen_socket = INVALID_SOCKET; SOCKET accept_socket = INVALID_SOCKET; WSAOVERLAPPED *Overlap = NULL; DWORD bytes = 0; DWORD bytes_read = 0; DWORD lasterror = 0; // // Handles is the array that stores the Event Handles // WSAEVENT Handles[MAX_IO_PEND] ; // // socklist is a parallel array that keeps state information for // each Handle. // Socklist socklist[MAX_IO_PEND]; // // Pointers to Microsoft specific extensions // LPFN_ACCEPTEX pfnAcceptEx; GUID acceptex_guid = WSAID_ACCEPTEX; __try { if (NULL == (Buffer = (char*)XMALLOC(((2*sizeof(SOCKADDR_STORAGE))+32)*sizeof(char)))) { ERR("HeapAlloc()"); __leave; } // // Parse arguments // if ( argc > 1 ) { for ( i = 1;i < argc; i++ ) { if ( (argv[i][0] == '-') || (argv[i][0] == '/') ) { switch ( tolower(argv[i][1]) ) { case 'i': if ( i+1 < argc ) interface = argv[++i]; break; case 'e': if ( i+1 < argc ) port = argv[++i]; break; default: { Usage(argv[0]); __leave; } break; } } else { Usage(argv[0]); __leave; } } } // // Since port 0 would be any available port. // Resetting port back to DEFAULT_PORT to avoid confusion. // if ( 0 == strncmp(port, "0", 1) ) { port = DEFAULT_PORT; } if ( 0 != (nStartup = WSAStartup(WS_VER, &wsaData)) ) { WSASetLastError(nStartup); //WSAStartup does not set last error on failure ERR("WSAStartup()"); __leave; } else nStartup++; // // Resolve the interface // SecureZeroMemory(&hints,sizeof(hints)); hints.ai_flags = ((interface) ? 0 : AI_PASSIVE); hints.ai_family = ai_family; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if ( 0 != getaddrinfo(interface, port, &hints, &local)) { ERR("getaddrinfo()"); __leave; } ai_family = local->ai_family; if (NULL == local) { fprintf(stderr, "getaddrinfo() failed to resolve/convert the interface\n"); __leave; } if (INVALID_SOCKET == (listen_socket = WSASocket(local->ai_family, local->ai_socktype, local->ai_protocol, NULL, 0, WSA_FLAG_OVERLAPPED ))) { ERR("WSASocket()"); __leave; } if ( SOCKET_ERROR == bind(listen_socket, local->ai_addr, (int)local->ai_addrlen )) { ERR("bind()"); __leave; } if ( SOCKET_ERROR == listen(listen_socket, DEFAULT_BACKLOG)) { ERR("listen()"); __leave; } // // Resolve numeric host name // if ( 0 != getnameinfo(local->ai_addr, (int)local->ai_addrlen, host, hostlen, serv, servlen, NI_NUMERICHOST | NI_NUMERICSERV )) { ERR("getnameinfo()"); __leave; } // Don't need the local interface anymore if (NULL != local) freeaddrinfo(local); printf("Listening on %s:%s\n", host, serv); // // Add the listening socket to our state information for the handle. // socklist[0].sock = listen_socket; curr_size =1; for ( i = 0;i < MAX_IO_PEND;i++ ) Handles[i] = WSA_INVALID_EVENT; // // Load the extension functions // if ( SOCKET_ERROR == WSAIoctl(listen_socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &acceptex_guid, sizeof(acceptex_guid), &pfnAcceptEx, sizeof(pfnAcceptEx), &bytes, NULL, NULL )) { fprintf(stderr,"Failed to obtain AcceptEx() pointer: "); ERR("WSAIoctl()"); __leave; } // // The structure of the following loop is very similar to a situation // where select() might be used. // We use WSAGetOverlappedResult() to multiplex between incoming/outgoing // data on existing connections. // // We don't queue an AcceptEx() until someone actually connects to // the previous socket. This is to keep the code simple, not a limitation // of the API itself. // for ( ;; ) { // create a socket for AcceptEx() if (INVALID_SOCKET == (accept_socket = WSASocket(ai_family, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED ))) { ERR("WSASocket()"); __leave; } // // Allocate an overlapped structure. // We use the Offset field to keep track of the socket handle // we have accepted a connection on, since there is no other // way to pass information to GetOverlappedResult() // Overlap = (WSAOVERLAPPED*)XMALLOC(sizeof(WSAOVERLAPPED)); // // Did the HeapAllocation FAIL?? // if ( Overlap == NULL ) { ERR("HeapAlloc()"); __leave; } SecureZeroMemory(Overlap, sizeof(WSAOVERLAPPED)); if ( WSA_INVALID_EVENT == (Overlap->hEvent = WSACreateEvent() )) { ERR("WSACreateEvent()"); __leave; } // // Set the appropriate array members // Handles[0] = Overlap->hEvent; socklist[0].overlap = Overlap; socklist[0].SockAccepted = accept_socket; // // AcceptEx() // if ( !pfnAcceptEx(listen_socket, accept_socket, Buffer, 0, // read nothing from the socket sizeof(SOCKADDR_STORAGE)+16, sizeof(SOCKADDR_STORAGE)+16, &bytes_read, Overlap )) { lasterror = WSAGetLastError(); if ( WSA_IO_PENDING != lasterror) { ERR("AcceptEx()"); for ( i = 0; i < curr_size; i++ ) { shutdown(socklist[i].sock, SD_BOTH); CLOSESOCK(socklist[i].sock); XFREE(socklist[i].overlap); CLOSEEVENT(Handles[i]); } __leave; } } // // This loop simple checks the handles to see which one is // signalled. // If error, exit. // If there is a new incoming connection, we break to the outer loop // queue another AcceptEx() // for ( ;; ) { i = DoWait(Handles, socklist); if ( i < 0 ) break; HandleEvent(i, Handles, socklist); if ( i == 0 ) break; }; if ( i < 0 ) { for ( i = 0; i < curr_size; i++ ) { shutdown(socklist[i].sock, SD_BOTH); CLOSESOCK(socklist[i].sock); XFREE(socklist[i].overlap); CLOSEEVENT(Handles[i]); } __leave; } } } __finally { XFREE(Buffer); if (NULL != local) freeaddrinfo(local); CLOSESOCK(listen_socket); CLOSESOCK(accept_socket); CLOSEEVENT(Overlap->hEvent); XFREE(Overlap); } }
int net_recvSmtpResponse(int sock, int * smtpCode, int timeout) { WSAOVERLAPPED recvOverlapped; WSABUF dataBuf; DWORD recvBytes = 0; int index = 0; DWORD flags = 0; int rc = 0; int lastError = 0; int bytesLeft = SMTP_MAX_TEXT_LINE_LEN-1; int bufSize = SMTP_MAX_TEXT_LINE_LEN; char buf[SMTP_MAX_TEXT_LINE_LEN] = {0}; char * p = NULL; // Make sure the RecvOverlapped struct is zeroed out SecureZeroMemory((PVOID) &recvOverlapped, sizeof (WSAOVERLAPPED)); SecureZeroMemory((PVOID) &dataBuf, sizeof (WSABUF)); SecureZeroMemory((PVOID) &buf, sizeof (buf)); // Create an event handle and setup an overlapped structure. recvOverlapped.hEvent = WSACreateEvent(); if (recvOverlapped.hEvent == NULL) { debug_log(LOG_ERR, "net_recvSmtpResponse(): WSACreateEvent failed: %d", WSAGetLastError()); closesocket(sock); return SOCK_IO_ERROR; } while (index < bufSize) { recvBytes = 0; flags = 0; dataBuf.len = 1; dataBuf.buf = &buf[index]; wait_for_recv: // submit the request rc = WSARecv(sock, &dataBuf, 1, &recvBytes, &flags, &recvOverlapped, NULL); if (rc != 0) { if (rc == SOCKET_ERROR) { lastError = WSAGetLastError(); if (lastError == WSAEWOULDBLOCK) { if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) { closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_WDOG_SHUTDOWN; } SleepEx(SLEEP_EX_INTERVAL, TRUE); goto wait_for_recv; } else { if (lastError != WSA_IO_PENDING) { debug_log(LOG_ERR, "net_recvSmtpResponse(): WSARecv failed with error: %d", lastError); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } } } wait_for_io: // Wait for I/O completion rc = WSAWaitForMultipleEvents(1, &recvOverlapped.hEvent, TRUE, timeout, TRUE); if (rc == WSA_WAIT_TIMEOUT) { debug_log(LOG_ERR, "net_recvSmtpResponse(): overlapped I/O timeout: %d", timeout); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_TIMEOUT; } if (rc == WSA_WAIT_IO_COMPLETION) { if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) { closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_WDOG_SHUTDOWN; } SleepEx(SLEEP_EX_INTERVAL, TRUE); goto wait_for_io; } wait_for_ov: // Check the result of the I/O overlapped operation rc = WSAGetOverlappedResult(sock, &recvOverlapped, &recvBytes, FALSE, &flags); if (rc == FALSE) { lastError = WSAGetLastError(); if (lastError == WSA_IO_INCOMPLETE) { if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) { closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_WDOG_SHUTDOWN; } SleepEx(SLEEP_EX_INTERVAL, TRUE); goto wait_for_ov; } debug_log(LOG_ERR, "net_recvSmtpResponse(): overlapped I/O failed with error: %d", lastError); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } // ------------------------ // Reset the signaled event // ------------------------ rc = WSAResetEvent(recvOverlapped.hEvent); if (rc == FALSE) { debug_log(LOG_ERR, "net_recvSmtpResponse(): WSAResetEvent failed with error = %d", WSAGetLastError()); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } } // Check what we received... if (buf[index] == '\r') { index += recvBytes; recvBytes = 0; flags = 0; dataBuf.len = 1; dataBuf.buf = &buf[index]; // Receive another byte wait_for_recv2: rc = WSARecv(sock, &dataBuf, 1, &recvBytes, &flags, &recvOverlapped, NULL); if (rc != 0) { if (rc == SOCKET_ERROR) { lastError = WSAGetLastError(); if (lastError == WSAEWOULDBLOCK) { if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) { closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_WDOG_SHUTDOWN; } SleepEx(SLEEP_EX_INTERVAL, TRUE); goto wait_for_recv2; } else { if (lastError != WSA_IO_PENDING) { debug_log(LOG_ERR, "net_recvSmtpResponse(): WSARecv failed with error: %d", lastError); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } } } wait_for_io2: rc = WSAWaitForMultipleEvents(1, &recvOverlapped.hEvent, TRUE, timeout, TRUE); if (rc == WSA_WAIT_TIMEOUT) { debug_log(LOG_ERR, "net_recvSmtpResponse(): overlapped I/O timeout: %d", timeout); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_TIMEOUT; } if (rc == WSA_WAIT_IO_COMPLETION) { if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) { closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_WDOG_SHUTDOWN; } SleepEx(SLEEP_EX_INTERVAL, TRUE); goto wait_for_io2; } wait_for_ov2: rc = WSAGetOverlappedResult(sock, &recvOverlapped, &recvBytes, FALSE, &flags); if (rc == FALSE) { lastError = WSAGetLastError(); if (lastError == WSA_IO_INCOMPLETE) { if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) { closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_WDOG_SHUTDOWN; } SleepEx(SLEEP_EX_INTERVAL, TRUE); goto wait_for_ov2; } debug_log(LOG_ERR, "net_recvSmtpResponse(): overlapped I/O failed with error: %d", lastError); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } // ------------------------ // Reset the signaled event // ------------------------ rc = WSAResetEvent(recvOverlapped.hEvent); if (rc == FALSE) { debug_log(LOG_ERR, "net_recvSmtpResponse(): WSAResetEvent failed with error = %d", WSAGetLastError()); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } } if ( buf[index] == '\n') { // we got to the end of line (CRLF found) index += recvBytes; if (buf[3] == '-') { net_recvSmtpResponse(sock, smtpCode, timeout); // receive another line in multiline replies } // endif break; } } else { // Continue receiving the line until we get CRLF, we need to receive those bytes to cler the buffer. index += recvBytes; recvBytes = 0; flags = 0; dataBuf.len = 1; dataBuf.buf = &buf[index]; } } // while (index < bufSize) buf[3] = 0; // get frist three bytes *smtpCode = atoi(buf); WSACloseEvent(recvOverlapped.hEvent); return SOCK_NO_ERROR; } // end of "net_recvSmtpResponse()"
int net_recvHttpLine(int sock, char * line, int maxLineLen, int timeout) { WSAOVERLAPPED recvOverlapped; WSABUF dataBuf; DWORD recvBytes = 0; int index = 0; DWORD flags = 0; int rc = 0; int lastError = 0; time_t start = 0; time_t end = 0; char * p = line; time(&start); // Make sure the RecvOverlapped struct is zeroed out SecureZeroMemory((PVOID) &recvOverlapped, sizeof (WSAOVERLAPPED)); SecureZeroMemory((PVOID) &dataBuf, sizeof (WSABUF)); // Create an event handle and setup an overlapped structure. recvOverlapped.hEvent = WSACreateEvent(); if (recvOverlapped.hEvent == NULL) { debug_log(LOG_ERR, "net_recvHttpLine(): WSACreateEvent failed: %d", WSAGetLastError()); closesocket(sock); return SOCK_IO_ERROR; } while (index < maxLineLen) { recvBytes = 0; flags = 0; dataBuf.len = 1; dataBuf.buf = p; wait_for_recv: // submit the request rc = WSARecv(sock, &dataBuf, 1, &recvBytes, &flags, &recvOverlapped, NULL); if (rc != 0) { if (rc == SOCKET_ERROR) { lastError = WSAGetLastError(); if (lastError == WSAEWOULDBLOCK) { if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) { closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_WDOG_SHUTDOWN; } SleepEx(SLEEP_EX_INTERVAL, TRUE); goto wait_for_recv; } else { if (lastError != WSA_IO_PENDING) { debug_log(LOG_ERR, "net_recvHttpLine(): WSARecv failed with error: %d", lastError); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } } } wait_for_io: // Wait for I/O completion rc = WSAWaitForMultipleEvents(1, &recvOverlapped.hEvent, TRUE, timeout, TRUE); if (rc == WSA_WAIT_TIMEOUT) { debug_log(LOG_ERR, "net_recvHttpLine(): overlapped I/O timeout: %d", timeout); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_TIMEOUT; } if (rc == WSA_WAIT_IO_COMPLETION) { if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) { closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_WDOG_SHUTDOWN; } SleepEx(SLEEP_EX_INTERVAL, TRUE); goto wait_for_io; } wait_for_ov: // Check the result of the I/O overlapped operation rc = WSAGetOverlappedResult(sock, &recvOverlapped, &recvBytes, FALSE, &flags); if (rc == FALSE) { lastError = WSAGetLastError(); if (lastError == WSA_IO_INCOMPLETE) { if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) { closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_WDOG_SHUTDOWN; } SleepEx(SLEEP_EX_INTERVAL, TRUE); goto wait_for_ov; } debug_log(LOG_ERR, "net_recvHttpLine(): overlapped I/O failed with error: %d", lastError); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } // ------------------------ // Reset the signaled event // ------------------------ rc = WSAResetEvent(recvOverlapped.hEvent); if (rc == FALSE) { debug_log(LOG_ERR, "net_recvHttpLine(): WSAResetEvent failed with error = %d", WSAGetLastError()); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } } // Check what we received... if (*p == '\n') { p += recvBytes; index += recvBytes; break; } else { // Continue receiving the line until we get LF, we need to receive those bytes to cler the buffer. p += recvBytes; index += recvBytes; recvBytes = 0; flags = 0; dataBuf.len = 1; dataBuf.buf = p; } time(&end); if (end-start > timeout/1000) { debug_log(LOG_SVR, "net_recvHttpLine(): timeout waiting for LF character..."); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } } // while (index < maxLineLen) WSACloseEvent(recvOverlapped.hEvent); if (index < maxLineLen) return SOCK_NO_ERROR; return SOCK_PROTOCOL_ERROR; } // end of "net_recvHttpLine()"
static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_address, UINT16 port) { int ai_flags = 0; int status; int sockfd; char addr[64]; void* sin_addr; int option_value; struct addrinfo* ai; struct addrinfo* res; rdpListener* listener = (rdpListener*) instance->listener; #ifdef _WIN32 u_long arg; #endif if (!bind_address) ai_flags = AI_PASSIVE; res = freerdp_tcp_resolve_host(bind_address, port, ai_flags); if (!res) return FALSE; for (ai = res; ai && (listener->num_sockfds < 5); ai = ai->ai_next) { if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6)) continue; if (listener->num_sockfds == MAX_LISTENER_HANDLES) { WLog_ERR(TAG, "too many listening sockets"); continue; } sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfd == -1) { WLog_ERR(TAG, "socket"); continue; } if (ai->ai_family == AF_INET) sin_addr = &(((struct sockaddr_in*) ai->ai_addr)->sin_addr); else sin_addr = &(((struct sockaddr_in6*) ai->ai_addr)->sin6_addr); inet_ntop(ai->ai_family, sin_addr, addr, sizeof(addr)); option_value = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &option_value, sizeof(option_value)) == -1) WLog_ERR(TAG, "setsockopt"); #ifndef _WIN32 fcntl(sockfd, F_SETFL, O_NONBLOCK); #else arg = 1; ioctlsocket(sockfd, FIONBIO, &arg); #endif status = _bind((SOCKET) sockfd, ai->ai_addr, ai->ai_addrlen); if (status != 0) { closesocket((SOCKET) sockfd); continue; } status = _listen((SOCKET) sockfd, 10); if (status != 0) { WLog_ERR(TAG, "listen"); closesocket((SOCKET) sockfd); continue; } /* FIXME: these file descriptors do not work on Windows */ listener->sockfds[listener->num_sockfds] = sockfd; listener->events[listener->num_sockfds] = WSACreateEvent(); if (!listener->events[listener->num_sockfds]) { listener->num_sockfds = 0; break; } WSAEventSelect(sockfd, listener->events[listener->num_sockfds], FD_READ | FD_ACCEPT | FD_CLOSE); listener->num_sockfds++; WLog_INFO(TAG, "Listening on %s:%d", addr, port); } freeaddrinfo(res); return (listener->num_sockfds > 0 ? TRUE : FALSE); }
// Register the NetDescriptor with the NetManager. int NetManager_addDesc(NetDescriptor *nd) { long eventMask = 0; WSAEVENT event; if (numSockets >= WSA_MAXIMUM_WAIT_EVENTS) { errno = EMFILE; return -1; } if (nd->readCallback != NULL) eventMask |= FD_READ | FD_ACCEPT; if (nd->writeCallback != NULL) eventMask |= FD_WRITE /* | FD_CONNECT */; if (nd->exceptionCallback != NULL) eventMask |= FD_OOB; eventMask |= FD_CLOSE; event = WSACreateEvent(); if (event == WSA_INVALID_EVENT) { errno = getWinsockErrno(); return -1; } nd->smd = SocketManagementData_alloc(); if (eventMask != 0) { // XXX: This guard is now always true, because of FD_CLOSE. // This means that numActiveEvents will always be equal to // numEvents. // Once I'm convinced this is the right way to go, // I can remove some unnecessary code. if (WSAEventSelect(nd->socket->sock, event, eventMask) == SOCKET_ERROR) { int savedErrno = getWinsockErrno(); int closeStatus = closeWSAEvent(event); if (closeStatus == -1) { log_add(log_Fatal, "closeWSAEvent() failed: %s.\n", strerror(errno)); explode(); } SocketManagementData_free(nd->smd); errno = savedErrno; return -1; } // Move existing socket for which there exists no event, so // so that all sockets for which there exists an event are at // the front of the array of netdescriptors. if (numActiveEvents < numSockets) { netDescriptors[numSockets] = netDescriptors[numActiveEvents]; netDescriptors[numSockets]->smd->index = numSockets; } nd->smd->index = numActiveEvents; numActiveEvents++; } else { nd->smd->index = numSockets; } nd->smd->eventMask = eventMask; netDescriptors[nd->smd->index] = nd; events[nd->smd->index] = event; numSockets++; return 0; }
/* * Wait for activity on one or more sockets. * While waiting, allow signals to run * * NOTE! Currently does not implement exceptfds check, * since it is not used in postgresql! */ int pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval * timeout) { WSAEVENT events[FD_SETSIZE * 2]; /* worst case is readfds totally * different from writefds, so * 2*FD_SETSIZE sockets */ SOCKET sockets[FD_SETSIZE * 2]; int numevents = 0; int i; int r; DWORD timeoutval = WSA_INFINITE; FD_SET outreadfds; FD_SET outwritefds; int nummatches = 0; Assert(exceptfds == NULL); if (pgwin32_poll_signals()) return -1; FD_ZERO(&outreadfds); FD_ZERO(&outwritefds); /* * Write FDs are different in the way that it is only flagged by * WSASelectEvent() if we have tried to write to them first. So try an * empty write */ if (writefds) { for (i = 0; i < writefds->fd_count; i++) { char c; WSABUF buf; DWORD sent; buf.buf = &c; buf.len = 0; r = WSASend(writefds->fd_array[i], &buf, 1, &sent, 0, NULL, NULL); if (r == 0) /* Completed - means things are fine! */ FD_SET (writefds->fd_array[i], &outwritefds); else { /* Not completed */ if (WSAGetLastError() != WSAEWOULDBLOCK) /* * Not completed, and not just "would block", so an error * occured */ FD_SET (writefds->fd_array[i], &outwritefds); } } if (outwritefds.fd_count > 0) { memcpy(writefds, &outwritefds, sizeof(fd_set)); if (readfds) FD_ZERO(readfds); return outwritefds.fd_count; } } /* Now set up for an actual select */ if (timeout != NULL) { /* timeoutval is in milliseconds */ timeoutval = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; } if (readfds != NULL) { for (i = 0; i < readfds->fd_count; i++) { events[numevents] = WSACreateEvent(); sockets[numevents] = readfds->fd_array[i]; numevents++; } } if (writefds != NULL) { for (i = 0; i < writefds->fd_count; i++) { if (!readfds || !FD_ISSET(writefds->fd_array[i], readfds)) { /* If the socket is not in the read list */ events[numevents] = WSACreateEvent(); sockets[numevents] = writefds->fd_array[i]; numevents++; } } } for (i = 0; i < numevents; i++) { int flags = 0; if (readfds && FD_ISSET(sockets[i], readfds)) flags |= FD_READ | FD_ACCEPT | FD_CLOSE; if (writefds && FD_ISSET(sockets[i], writefds)) flags |= FD_WRITE | FD_CLOSE; if (WSAEventSelect(sockets[i], events[i], flags) == SOCKET_ERROR) { TranslateSocketError(); for (i = 0; i < numevents; i++) WSACloseEvent(events[i]); return -1; } } events[numevents] = pgwin32_signal_event; r = WaitForMultipleObjectsEx(numevents + 1, events, FALSE, timeoutval, TRUE); if (r != WAIT_TIMEOUT && r != WAIT_IO_COMPLETION && r != (WAIT_OBJECT_0 + numevents)) { /* * We scan all events, even those not signalled, in case more than one * event has been tagged but Wait.. can only return one. */ WSANETWORKEVENTS resEvents; for (i = 0; i < numevents; i++) { ZeroMemory(&resEvents, sizeof(resEvents)); if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) == SOCKET_ERROR) ereport(FATAL, (errmsg_internal("failed to enumerate network events: %i", (int) GetLastError()))); /* Read activity? */ if (readfds && FD_ISSET(sockets[i], readfds)) { if ((resEvents.lNetworkEvents & FD_READ) || (resEvents.lNetworkEvents & FD_ACCEPT) || (resEvents.lNetworkEvents & FD_CLOSE)) { FD_SET (sockets[i], &outreadfds); nummatches++; } } /* Write activity? */ if (writefds && FD_ISSET(sockets[i], writefds)) { if ((resEvents.lNetworkEvents & FD_WRITE) || (resEvents.lNetworkEvents & FD_CLOSE)) { FD_SET (sockets[i], &outwritefds); nummatches++; } } } } /* Clean up all handles */ for (i = 0; i < numevents; i++) { WSAEventSelect(sockets[i], events[i], 0); WSACloseEvent(events[i]); } if (r == WSA_WAIT_TIMEOUT) { if (readfds) FD_ZERO(readfds); if (writefds) FD_ZERO(writefds); return 0; } if (r == WAIT_OBJECT_0 + numevents) { pgwin32_dispatch_queued_signals(); errno = EINTR; if (readfds) FD_ZERO(readfds); if (writefds) FD_ZERO(writefds); return -1; } /* Overwrite socket sets with our resulting values */ if (readfds) memcpy(readfds, &outreadfds, sizeof(fd_set)); if (writefds) memcpy(writefds, &outwritefds, sizeof(fd_set)); return nummatches; }
inline int RecvIt( SOCKET sock, PCHAR buf, int size ) { int iErrcode; int len = size, iReceived; WSAOVERLAPPED overlapped; WSABUF buffer[1]; DWORD dwFlag; DWORD dwRecvDataLen; WSAEVENT hEvent; BOOL bResult; // Overlapped event // hEvent = WSACreateEvent(); // // Receive Reply Header. // memset(&overlapped, 0, sizeof(WSAOVERLAPPED)); overlapped.hEvent = hEvent; iReceived = 0; while(iReceived < size) { if(size - iReceived >= 1024) buffer[0].len = 1024; else buffer[0].len = size - iReceived; buffer[0].buf = buf + iReceived; // Flag dwFlag = 0; iErrcode = WSARecv( sock, buffer, 1, &dwRecvDataLen, &dwFlag, &overlapped, NULL ); if(iErrcode == SOCKET_ERROR) { DWORD dwError = WSAGetLastError(); if(dwError == WSA_IO_PENDING) { DWORD dwFlags; dwError = WSAWaitForMultipleEvents( 1, &hEvent, TRUE, TIME_OUT, TRUE ); if(dwError != WSA_WAIT_EVENT_0) { PrintErrorCode(TEXT("[LanScsiCli]RecvIt: "), dwError); dwRecvDataLen = -1; TRACE("[LanScsiCli]RecvIt: Request %d, Received %d\n", size, iReceived ); goto Out; } // Get Result... bResult = WSAGetOverlappedResult( sock, &overlapped, &dwRecvDataLen, TRUE, &dwFlags ); if(bResult == FALSE) { PrintErrorCode(TEXT("[LanScsiCli]RecvIt: GetOverlappedResult Failed "), GetLastError()); dwRecvDataLen = SOCKET_ERROR; goto Out; } } else { PrintErrorCode(TEXT("[LanScsiCli]RecvIt: WSARecv Failed "), dwError); dwRecvDataLen = -1; goto Out; } } iReceived += dwRecvDataLen; WSAResetEvent(hEvent); } Out: WSACloseEvent(hEvent); return dwRecvDataLen; }
/* * WinSock select() does not support standard file descriptors, * it can only check SOCKETs. The following function is an attempt * to re-create a select() function with support for other handle types. * * select() function with support for WINSOCK2 sockets and all * other handle types supported by WaitForMultipleObjectsEx(). * * TODO: Differentiate between read/write/except for non-SOCKET handles. * * http://msdn.microsoft.com/en-us/library/windows/desktop/ms687028.aspx * http://msdn.microsoft.com/en-us/library/windows/desktop/ms741572.aspx */ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { long networkevents; DWORD milliseconds, wait, idx, mode, avail, events, inputs; WSAEVENT wsaevent, *wsaevents; WSANETWORKEVENTS wsanetevents; INPUT_RECORD *inputrecords; HANDLE handle, *handles; curl_socket_t sock, *fdarr, *wsasocks; int error, fds; DWORD nfd = 0, wsa = 0; int ret = 0; /* check if the input value is valid */ if(nfds < 0) { errno = EINVAL; return -1; } /* check if we got descriptors, sleep in case we got none */ if(!nfds) { Sleep((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000)); return 0; } /* allocate internal array for the original input handles */ fdarr = malloc(nfds * sizeof(curl_socket_t)); if(fdarr == NULL) { errno = ENOMEM; return -1; } /* allocate internal array for the internal event handles */ handles = malloc(nfds * sizeof(HANDLE)); if(handles == NULL) { errno = ENOMEM; return -1; } /* allocate internal array for the internal socket handles */ wsasocks = malloc(nfds * sizeof(curl_socket_t)); if(wsasocks == NULL) { errno = ENOMEM; return -1; } /* allocate internal array for the internal WINSOCK2 events */ wsaevents = malloc(nfds * sizeof(WSAEVENT)); if(wsaevents == NULL) { errno = ENOMEM; return -1; } /* loop over the handles in the input descriptor sets */ for(fds = 0; fds < nfds; fds++) { networkevents = 0; handles[nfd] = 0; if(FD_ISSET(fds, readfds)) networkevents |= FD_READ|FD_ACCEPT|FD_CLOSE; if(FD_ISSET(fds, writefds)) networkevents |= FD_WRITE|FD_CONNECT; if(FD_ISSET(fds, exceptfds)) networkevents |= FD_OOB|FD_CLOSE; /* only wait for events for which we actually care */ if(networkevents) { fdarr[nfd] = curlx_sitosk(fds); if(fds == fileno(stdin)) { handles[nfd] = GetStdHandle(STD_INPUT_HANDLE); } else if(fds == fileno(stdout)) { handles[nfd] = GetStdHandle(STD_OUTPUT_HANDLE); } else if(fds == fileno(stderr)) { handles[nfd] = GetStdHandle(STD_ERROR_HANDLE); } else { wsaevent = WSACreateEvent(); if(wsaevent != WSA_INVALID_EVENT) { error = WSAEventSelect(fds, wsaevent, networkevents); if(error != SOCKET_ERROR) { handles[nfd] = wsaevent; wsasocks[wsa] = curlx_sitosk(fds); wsaevents[wsa] = wsaevent; wsa++; } else { handles[nfd] = (HANDLE) curlx_sitosk(fds); WSACloseEvent(wsaevent); } } } nfd++; } } /* convert struct timeval to milliseconds */ if(timeout) { milliseconds = ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000)); } else { milliseconds = INFINITE; } /* wait for one of the internal handles to trigger */ wait = WaitForMultipleObjectsEx(nfd, handles, FALSE, milliseconds, FALSE); /* loop over the internal handles returned in the descriptors */ for(idx = 0; idx < nfd; idx++) { handle = handles[idx]; sock = fdarr[idx]; fds = curlx_sktosi(sock); /* check if the current internal handle was triggered */ if(wait != WAIT_FAILED && (wait - WAIT_OBJECT_0) <= idx && WaitForSingleObjectEx(handle, 0, FALSE) == WAIT_OBJECT_0) { /* try to handle the event with STD* handle functions */ if(fds == fileno(stdin)) { /* check if there is no data in the input buffer */ if(!stdin->_cnt) { /* check if we are getting data from a PIPE */ if(!GetConsoleMode(handle, &mode)) { /* check if there is no data from PIPE input */ if(!PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL)) avail = 0; if(!avail) { FD_CLR(sock, readfds); /* reduce CPU load */ Sleep(10); } } /* check if there is no data from keyboard input */ else if (!_kbhit()) { /* check if there are INPUT_RECORDs in the input buffer */ if(GetNumberOfConsoleInputEvents(handle, &events)) { if(events > 0) { /* remove INPUT_RECORDs from the input buffer */ inputrecords = (INPUT_RECORD*)malloc(events * sizeof(INPUT_RECORD)); if(inputrecords) { if(!ReadConsoleInput(handle, inputrecords, events, &inputs)) inputs = 0; free(inputrecords); } /* check if we got all inputs, otherwise clear buffer */ if(events != inputs) FlushConsoleInputBuffer(handle); } } /* remove from descriptor set since there is no real data */ FD_CLR(sock, readfds); } } /* stdin is never ready for write or exceptional */ FD_CLR(sock, writefds); FD_CLR(sock, exceptfds); } else if(fds == fileno(stdout) || fds == fileno(stderr)) { /* stdout and stderr are never ready for read or exceptional */ FD_CLR(sock, readfds); FD_CLR(sock, exceptfds); } else { /* try to handle the event with the WINSOCK2 functions */ error = WSAEnumNetworkEvents(fds, handle, &wsanetevents); if(error != SOCKET_ERROR) { /* remove from descriptor set if not ready for read/accept/close */ if(!(wsanetevents.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))) FD_CLR(sock, readfds); /* remove from descriptor set if not ready for write/connect */ if(!(wsanetevents.lNetworkEvents & (FD_WRITE|FD_CONNECT))) FD_CLR(sock, writefds); /* HACK: * use exceptfds together with readfds to signal * that the connection was closed by the client. * * Reason: FD_CLOSE is only signaled once, sometimes * at the same time as FD_READ with data being available. * This means that recv/sread is not reliable to detect * that the connection is closed. */ /* remove from descriptor set if not exceptional */ if(!(wsanetevents.lNetworkEvents & (FD_OOB|FD_CLOSE))) FD_CLR(sock, exceptfds); } } /* check if the event has not been filtered using specific tests */ if(FD_ISSET(sock, readfds) || FD_ISSET(sock, writefds) || FD_ISSET(sock, exceptfds)) { ret++; } } else { /* remove from all descriptor sets since this handle did not trigger */ FD_CLR(sock, readfds); FD_CLR(sock, writefds); FD_CLR(sock, exceptfds); } } for(idx = 0; idx < wsa; idx++) { WSAEventSelect(wsasocks[idx], NULL, 0); WSACloseEvent(wsaevents[idx]); } free(wsaevents); free(wsasocks); free(handles); free(fdarr); return ret; }
/* Main 'loop' */ void axel_do(axel_t *axel) { #if WIN32 WSAEVENT hEventObject = WSACreateEvent(); DWORD byte; #else fd_set fds[1]; struct timeval timeval[1]; int hifd; #endif int i; long long int remaining, size; /* Create statefile if necessary */ if (axel->next_state < gettime()) { save_state(axel); axel->next_state = gettime() + axel->conf->save_state_interval; } /* Wait for data on (one of) the connections */ #if !WIN32 FD_ZERO(fds); hifd = 0; for (i = 0; i < axel->conf->num_connections; i++) { if (axel->conn[i].enabled) { FD_SET(axel->conn[i].fd, fds); } hifd = max(hifd, axel->conn[i].fd); } if (0 == hifd) { #ifdef DEBUG printf("DEBUG no connection yet. Wait...\n"); #endif /* No connections yet. Wait... */ usleep(100000); goto conn_check; } else { timeval->tv_sec = 0; timeval->tv_usec = 100000; /* A select() error probably means it was interrupted by a signal, or that something else's very wrong... */ if (-1 == select(hifd + 1, fds, NULL, NULL, timeval)) { axel->ready = -1; return; } } #endif /* Handle connections which need attention */ for (i = 0; i < axel->conf->num_connections; i++) { if (axel->conn[i].enabled) { #if WIN32 if (is_readable(axel, axel->conn[i].fd, hEventObject)) #else if (FD_ISSET(axel->conn[i].fd, fds)) #endif { axel->conn[i].last_transfer = gettime(); #if WIN32 memset(buffer, 0, max(MAX_STRING, axel->conf->buffer_size)); size = recv(axel->conn[i].fd, buffer, axel->conf->buffer_size, 0); #else size = read(axel->conn[i].fd, buffer, axel->conf->buffer_size); #endif #if WIN32 if (SOCKET_ERROR == size) #else if (-1 == size) #endif { #if !WIN32 if (axel->conf->verbose) { axel_message( axel, _("Error on connection %i! " "Connection closed"), i ); } #endif axel->conn[i].enabled = 0; conn_disconnect(&axel->conn[i]); continue; } else if (0 == size) { if (axel->conf->verbose) { /* Only abnormal behaviour if: */ if (axel->conn[i].currentbyte < axel->conn[i].lastbyte && axel->size != INT_MAX) { axel_message(axel, _("Connection %i unexpectedly closed"), i); } else { axel_message(axel, _("Connection %i finished"), i); } } if (!axel->conn[0].supported) { axel->ready = 1; } axel->conn[i].enabled = 0; conn_disconnect(&axel->conn[i]); continue; } /* remaining == Bytes to go */ remaining = axel->conn[i].lastbyte - axel->conn[i].currentbyte + 1; if (remaining < size) { if (axel->conf->verbose) { axel_message(axel, _("Connection %i finished"), i); } axel->conn[i].enabled = 0; conn_disconnect(&axel->conn[i]); size = remaining; /* Don't terminate, still stuff to write! */ } /* This should always succeed.. */ #if WIN32 SetFilePointer(axel->outfd, axel->conn[i].currentbyte, NULL, FILE_BEGIN); if (0 == WriteFile(axel->outfd, buffer, size, &byte, NULL)) #else lseek(axel->outfd, axel->conn[i].currentbyte, SEEK_SET); if (write(axel->outfd, buffer, size) != size) #endif { axel_message(axel, _("Write error!")); axel->ready = -1; return; } axel->conn[i].currentbyte += size; axel->bytes_done += size; } else { if (gettime() > axel->conn[i].last_transfer + axel->conf->connection_timeout) { if (axel->conf->verbose) { axel_message(axel, _("Connection %i timed out"), i); } conn_disconnect(&axel->conn[i]); axel->conn[i].enabled = 0; } } } } if (axel->ready) { return; } conn_check: /* Look for aborted connections and attempt to restart them. */ for (i = 0; i < axel->conf->num_connections; i++) { if (!axel->conn[i].enabled && axel->conn[i].currentbyte < axel->conn[i].lastbyte) { if (0 == axel->conn[i].state) { // Wait for termination of this thread #if WIN32 WaitForSingleObject(axel->conn[i].setup_thread, INFINITE); CloseHandle(axel->conn[i].setup_thread); #else pthread_join(*(axel->conn[i].setup_thread), NULL); #endif conn_set(&axel->conn[i], axel->url->text); axel->url = axel->url->next; if (axel->conf->verbose >= 2) { axel_message(axel, _("Connection %i downloading from %s:%i using interface %s"), i, axel->conn[i].host, axel->conn[i].port, axel->conn[i].local_if); } axel->conn[i].state = 1; #if WIN32 axel->conn[i].setup_thread = CreateThread(NULL, 0, setup_thread_cb, &axel->conn[i], 0, NULL); if (NULL != axel->conn[i].setup_thread) #else if (pthread_create(axel->conn[i].setup_thread, NULL, setup_thread_cb, &axel->conn[i]) == 0) #endif { axel->conn[i].last_transfer = gettime(); } else { axel_message(axel, _("thread error in axel_do!!!")); axel->ready = -1; } } else { if (gettime() > axel->conn[i].last_transfer + axel->conf->reconnect_delay) { #if WIN32 TerminateThread(axel->conn[i].setup_thread, 0); CloseHandle(axel->conn[i].setup_thread); #else pthread_cancel(*axel->conn[i].setup_thread); #endif axel->conn[i].state = 0; } } } } /* Calculate current average speed and finish_time */ axel->bytes_per_second = (int)((double)(axel->bytes_done - axel->start_byte) / (gettime() - axel->start_time)); axel->finish_time = (int)(axel->start_time + (double)(axel->size - axel->start_byte) / axel->bytes_per_second); /* Check speed. If too high, delay for some time to slow things down a bit. I think a 5% deviation should be acceptable. */ if (0 < axel->conf->max_speed) { if (1.05 < (float) axel->bytes_per_second / axel->conf->max_speed) { axel->delay_time += 10000; } else if (((float)axel->bytes_per_second / axel->conf->max_speed < 0.95) && 10000 <= (axel->delay_time)) { axel->delay_time -= 10000; } else if (((float)axel->bytes_per_second / axel->conf->max_speed < 0.95)) { axel->delay_time = 0; } usleep(axel->delay_time); } /* Ready? */ if (axel->bytes_done == axel->size) { axel->ready = 1; } }
void Event::Create(EventWaitType type_) { type = type_; wsaEvent = WSACreateEvent(); }
DWORD DarunGrim::IDACommandProcessor() { SOCKET SocketArray[WSA_MAXIMUM_WAIT_EVENTS]; WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS]; WSANETWORKEVENTS NetworkEvents; DWORD EventTotal = 0, index; SocketArray[0] = pSourceController->GetSocket(); SocketArray[1] = pTargetController->GetSocket(); for (int i = 0; i<2; i++) { WSAEVENT NewEvent = WSACreateEvent(); WSAEventSelect(SocketArray[i], NewEvent, FD_READ | FD_CLOSE); EventArray[EventTotal] = NewEvent; EventTotal++; } while (1) { index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE); if (index<0) break; index = index - WSA_WAIT_EVENT_0; //------------------------- // Iterate through all events and enumerate // if the wait does not fail. for (DWORD i = index; i<EventTotal; i++) { if (SocketArray[i] == WSA_INVALID_HANDLE) continue; index = WSAWaitForMultipleEvents(1, &EventArray[i], TRUE, 1000, FALSE); if ((index != WSA_WAIT_FAILED) && (index != WSA_WAIT_TIMEOUT)) { if (WSAEnumNetworkEvents(SocketArray[i], EventArray[i], &NetworkEvents) == 0) { Logger.Log(10, "Signal( %d - %d )\n", i, NetworkEvents.lNetworkEvents); if (NetworkEvents.lNetworkEvents == FD_READ) { char buffer[DATA_BUFSIZE] = { 0, }; WSABUF DataBuf; DataBuf.len = DATA_BUFSIZE; DataBuf.buf = buffer; /* DWORD RecvBytes; DWORD Flags=0; if ( WSARecv( SocketArray[i], &DataBuf, 1, &RecvBytes, &Flags, NULL, NULL )==SOCKET_ERROR ) { Logger.Log( 10, "Error occurred at WSARecv()\n" ); }else { Logger.Log( 10, "Read %d bytes\n", RecvBytes ); }*/ char type; DWORD length; PBYTE data = RecvTLVData(SocketArray[i], &type, &length); if (data) { Logger.Log(10, "%s: Type: %d Length: %d data:%x\n", __FUNCTION__, type, length, data); if (type == SHOW_MATCH_ADDR && length >= 4) { DWORD address = *(DWORD *)data; Logger.Log(10, "%s: Showing address=%x\n", __FUNCTION__, address); //Get Matching Address DWORD MatchingAddress = 0; if (pDiffMachine) { MatchingAddress = pDiffMachine->GetMatchAddr(i, address); } if (MatchingAddress != 0) { //Show using JUMP_TO_ADDR if (i == 0) { pTargetController->ShowAddress(MatchingAddress); } else { pSourceController->ShowAddress(MatchingAddress); } } } } } else if (NetworkEvents.lNetworkEvents == FD_CLOSE) { closesocket(SocketArray[i]); WSACloseEvent(EventArray[i]); memcpy(SocketArray + i, SocketArray + i + 1, EventTotal - i + 1); memcpy(EventArray + i, EventArray + i + 1, EventTotal - i + 1); EventTotal--; break; } } } } } return 1; }
int main(int argc, char* argv[]) { //---------------------- // Initialize Winsock. WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != NO_ERROR) { wprintf(L"WSAStartup failed with error: %ld\n", iResult); return 1; } //---------------------- // Create a SOCKET for listening for // incoming connection requests. SOCKET ListenSocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ListenSocket == INVALID_SOCKET) { wprintf(L"socket failed with error: %ld\n", WSAGetLastError()); WSACleanup(); return 1; } //---------------------- // The sockaddr_in structure specifies the address family, // IP address, and port for the socket that is being bound. sockaddr_in addrServer; addrServer.sin_family = AF_INET; addrServer.sin_addr.s_addr = htonl(INADDR_ANY); //实际上是0 addrServer.sin_port = htons(20131); //绑定套接字到一个IP地址和一个端口上 if (bind(ListenSocket,(SOCKADDR *) & addrServer, sizeof (addrServer)) == SOCKET_ERROR) { wprintf(L"bind failed with error: %ld\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } //将套接字设置为监听模式等待连接请求 //---------------------- // Listen for incoming connection requests. // on the created socket if (listen(ListenSocket, 5) == SOCKET_ERROR) { wprintf(L"listen failed with error: %ld\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } DWORD dwThread; HANDLE hThread = CreateThread(NULL,0,ThreadProc,NULL,0,&dwThread); if(hThread==NULL) { wprintf(L"Thread Creat Failed!\n"); closesocket(ListenSocket); WSACleanup(); return 1; } CloseHandle(hThread); SOCKADDR_IN addrClient; int len=sizeof(SOCKADDR); //以一个无限循环的方式,不停地接收客户端socket连接 while(1) { //请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字 SOCKET AcceptSocket=accept(ListenSocket,(SOCKADDR*)&addrClient,&len); if(AcceptSocket == INVALID_SOCKET)break; //出错 g_CliSocketArr[g_iTotalConn] = AcceptSocket; g_CliEventArr[g_iTotalConn] = WSACreateEvent(); // Launch an asynchronous operation WSAEventSelect(g_CliSocketArr[g_iTotalConn], g_CliEventArr[g_iTotalConn], FD_READ | FD_CLOSE); g_iTotalConn++; } closesocket(ListenSocket); WSACleanup(); return 0; }
DWORD WINAPI PnpModuleThreadProc( LPVOID lpParameter // thread data ) { int iResult; CPnpModule *pRC; WSAOVERLAPPED overlapped; WSABUF buffer[1]; DWORD dwFlag; DWORD dwRecvDataLen; SOCKADDR_LPX PeerAddr; INT iFromLen; BOOL bFinish; HANDLE hEvents[2]; PNP_MESSAGE message; DebugPrint(2, (TEXT("[NetdiskTest]PnpModuleThread: PnpModule Thread Started.\n"))); pRC = (CPnpModule *) lpParameter; // Server Stop Event. hEvents[0] = hServerStopEvent; // Overlapped event // hEvents[1] = WSACreateEvent(); memset(&overlapped, 0, sizeof(WSAOVERLAPPED)); overlapped.hEvent = hEvents[1]; buffer[0].len = sizeof(message); buffer[0].buf = (PCHAR)&message; bFinish = FALSE; do { DWORD dwResult; // Flag dwFlag = 0; WSAResetEvent(hEvents[1]); iFromLen = sizeof(PeerAddr); iResult = WSARecvFrom( pRC->ListenSocket, buffer, 1, &dwRecvDataLen, &dwFlag, (struct sockaddr *)&PeerAddr, &iFromLen, &overlapped, NULL ); if(iResult != SOCKET_ERROR) { DebugPrint(4, ("[NetDiskTest]PnpModuleThreadProc: no Error when Recv.\n")); continue; } if((iResult = WSAGetLastError()) != WSA_IO_PENDING) { DebugPrint(1, ("[NetDiskTest]PnpModuleThreadProc: Error when Recv. %d\n", iResult)); bFinish = TRUE; continue; } // Wait dwResult = WaitForMultipleObjects( 2, hEvents, FALSE, 3000 //INFINITE ); switch(dwResult) { case WAIT_TIMEOUT: TRACE("\nWAIT_TIMEOUT\n"); SetEvent(hUpdateEvent); break; case WAIT_OBJECT_0: { TRACE("\nWAIT_OBJECT_0\n"); bFinish = TRUE; DebugPrint(1, ("[NetDiskTest]PnpModuleThreadProc: Recv Stop Event.\n")); } break; case WAIT_OBJECT_0 + 1: { TRACE("\nWAIT_OBJECT_0+1\n"); BOOL bResult; bResult = WSAGetOverlappedResult( pRC->ListenSocket, &overlapped, &dwRecvDataLen, TRUE, &dwFlag ); // Check Size. if(dwRecvDataLen != sizeof(message)) { DebugPrint(1, ("[NetDiskTest]PnpModuleThreadProc: Recv Packet size = %d. Ignore...\n", dwRecvDataLen)); break; } // Is Valid? if (message.ucType != 0 || ( message.ucVersion != 0 && message.ucVersion != 1 && message.ucVersion != 2 ) ) { DebugPrint(1, ("[NetDiskTest]PnpModuleThreadProc: Bad Packet 0x%x. 0x%x. Ignore...\n", message.ucType, message.ucVersion)); break; } } // DebugPrint(4, ("[NetDiskTest]PnpModuleThreadProc: %.2X%.2X%.2X\n", // PeerAddr.LpxAddress.Node[0], PeerAddr.LpxAddress.Node[1], PeerAddr.LpxAddress.Node[2])); memcpy((void *) ucCurrentNetdisk, (void *) PeerAddr.LpxAddress.Node, 6); ucVersion = message.ucVersion; bNewNetdiskArrived = TRUE; SetEvent(hUpdateEvent); break; default: break; } } while(bFinish != TRUE); CloseHandle(hEvents[1]); ExitThread(0); return 0; }
bool CIOCPServer::Initialize(NOTIFYPROC pNotifyProc, CMainFrame* pFrame, int nMaxConnections, int nPort) { m_pNotifyProc = pNotifyProc; m_pFrame = pFrame; m_nMaxConnections = nMaxConnections; m_socketListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); if (INVALID_SOCKET == m_socketListen) { TRACE(_T("Could not create listen socket %ld\n"),WSAGetLastError()); return false; } // Event for handling Network IO m_hEvent = WSACreateEvent(); if (WSA_INVALID_EVENT == m_hEvent) { TRACE(_T("WSACreateEvent() error %ld\n"),WSAGetLastError()); closesocket(m_socketListen); return false; } // The listener is ONLY interested in FD_ACCEPT // That is when a client connects to or IP/Port // Request async notification int nRet = WSAEventSelect(m_socketListen, m_hEvent, FD_ACCEPT); if (SOCKET_ERROR == nRet) { TRACE(_T("WSAAsyncSelect() error %ld\n"),WSAGetLastError()); closesocket(m_socketListen); return false; } SOCKADDR_IN saServer; // Listen on our designated Port# saServer.sin_port = htons(nPort); // Fill in the rest of the address structure saServer.sin_family = AF_INET; saServer.sin_addr.s_addr = INADDR_ANY; // bind our name to the socket nRet = bind(m_socketListen, (LPSOCKADDR)&saServer, sizeof(struct sockaddr)); if (SOCKET_ERROR == nRet) { TRACE(_T("bind() error %ld\n"),WSAGetLastError()); closesocket(m_socketListen); return false; } // Set the socket to listen nRet = listen(m_socketListen, SOMAXCONN); if (nRet == SOCKET_ERROR) { TRACE(_T("listen() error %ld\n"),WSAGetLastError()); closesocket(m_socketListen); return false; } UINT dwThreadId = 0; m_hThread = (HANDLE)_beginthreadex(NULL, // Security 0, // Stack size - use default ListenThreadProc, // Thread fn entry point (void*) this, 0, // Init flag &dwThreadId); // Thread address if (m_hThread != INVALID_HANDLE_VALUE) { InitializeIOCP(); m_bInit = true; return true; } return false; }
/* * This function uses to WaitForMultipleObjects to wait for both * stdin and socket reading or writing. * Stdin is treated special in WIN32. Waiting for stdin is done * via a bounce_full event which is set in the stdin thread. * Execute command file reading is done via handle. * WaitForMultipleObjects will only respond with one object, * so an additonal select is also done to determine * which individual events are active. */ static int w32_select(int nfds, fd_set *rdfd, fd_set *wrfd, fd_set *errfd, struct timeval *time) { HANDLE handles[3]; SOCKET sock; int inp, sockfd, result, s_result, num_handles; struct timeval tv_time = {0, 0}; fd_set rdsock, wrsock; switch (rdfd->fd_count) { case 1: inp = -1; sockfd = rdfd->fd_array[0]; break; case 2: inp = rdfd->fd_array[0]; sockfd = rdfd->fd_array[1]; break; default: assert(0); } sock = w32_fd2socket(sockfd); assert(wrfd->fd_count == 0 || (wrfd->fd_count == 1 && wrfd->fd_array[0] == (SOCKET)sockfd)); assert(inp < 0 || inp == input_fd); num_handles = 0; handles[num_handles++] = ctrl_c_event; if (inp >= 0) handles[num_handles++] = inp ? (HANDLE)_get_osfhandle(inp) : bounce_full; /* always wait on the socket */ handles[num_handles++] = WSACreateEvent(); if (wrfd->fd_count > 0) WSAEventSelect(sock, handles[num_handles - 1], FD_READ | FD_WRITE | FD_CLOSE); else WSAEventSelect(sock, handles[num_handles - 1], FD_READ | FD_CLOSE); result = WaitForMultipleObjects(num_handles, handles, 0, INFINITE); if (result < 0) { errno = GetLastError(); WSACloseEvent(handles[num_handles - 1]); return -1; } WSACloseEvent(handles[num_handles - 1]); if (result == WAIT_OBJECT_0) { errno = EINTR; return -1; } FD_ZERO(&rdsock); FD_ZERO(&wrsock); FD_SET(sock, &rdsock); if (wrfd->fd_count) FD_SET(sock, &wrsock); s_result = select(sock + 1, &rdsock, &wrsock, NULL, &tv_time); if (s_result < 0) { w32_set_winsock_errno(); return s_result; } if (!FD_ISSET(sock, &rdsock)) FD_CLR((SOCKET)sockfd, rdfd); if (!FD_ISSET(sock, &wrsock)) FD_CLR((SOCKET)sockfd, wrfd); if (inp >= 0 && result == WAIT_OBJECT_0 + 1) s_result++; else FD_CLR((SOCKET)inp, rdfd); return s_result; }
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); }
WEventSocket::WEventSocket() { m_hEvent=WSACreateEvent(); }
DWORD Q3_ConnectToMasterServer(GAME_INFO *pGI, int iMasterIdx) { size_t packetlen=0; char sendbuf[80]; ZeroMemory(sendbuf,sizeof(sendbuf)); SOCKET ConnectSocket; // UINT_PTR timerProgressWait = SetTimer(g_hWnd,IDT_TIMER_1SECOND,100,NULL); int i = 0; unsigned char *packet[MAX_PACKETS]; size_t packet_len[MAX_PACKETS]; for(i=0; i<MAX_PACKETS;i++) packet[i] = NULL; i = 0; char szIP[260]; strcpy(szIP,pGI->szMasterServerIP[iMasterIdx]); SplitIPandPORT(szIP,pGI->dwMasterServerPORT); int len = 0;//(int)strlen(sendbuf); string query; query = pGI->szMasterQueryString; ReplaceStrInStr(query,"%PROTOCOL%",pGI->szGameProtocol[iMasterIdx]); len = UTILZ_ConvertEscapeCodes((TCHAR*)query.c_str(),sendbuf,sizeof(sendbuf)); ConnectSocket = getsockudp(szIP,(unsigned short)pGI->dwMasterServerPORT); // etmaster.idsoftware.com"27950 master server if(INVALID_SOCKET==ConnectSocket) { KillTimer(g_hWnd,IDT_1SECOND); g_log.AddLogInfo(GS_LOG_ERROR,"Error connecting to server %s:%d!",szIP,pGI->dwMasterServerPORT); return 1; } WSAEVENT hEvent; hEvent = WSACreateEvent(); if (hEvent == WSA_INVALID_EVENT) { KillTimer(g_hWnd,IDT_1SECOND); g_log.AddLogInfo(GS_LOG_ERROR,"WSACreateEvent() = WSA_INVALID_EVENT"); closesocket(ConnectSocket); return 1; } // // Make the socket non-blocking and // associate it with network events // int nRet; nRet = WSAEventSelect(ConnectSocket, hEvent,FD_READ|FD_CONNECT|FD_CLOSE); if (nRet == SOCKET_ERROR) { KillTimer(g_hWnd,IDT_1SECOND); g_log.AddLogInfo(GS_LOG_ERROR,"EventSelect() = SOCKET_ERROR"); closesocket(ConnectSocket); WSACloseEvent(hEvent); return 5; } // // Handle async network events // WSANETWORKEVENTS events; while(1) { // // Wait for something to happen // //dbg_print("\nWaitForMultipleEvents()"); DWORD dwRet; dwRet = WSAWaitForMultipleEvents(1, &hEvent, FALSE,4000,FALSE); if (dwRet == WSA_WAIT_TIMEOUT) { g_log.AddLogInfo(GS_LOG_ERROR,"WSAWaitForMultipleEvents = WSA_WAIT_TIMEOUT"); break; } // // Figure out what happened // //g_log.AddLogInfo(0,"\nWSAEnumNetworkEvents()"); nRet = WSAEnumNetworkEvents(ConnectSocket, hEvent, &events); if (nRet == SOCKET_ERROR) { g_log.AddLogInfo(GS_LOG_ERROR,"WSAEnumNetworkEvents() = SOCKET_ERROR"); break; } // // // Handle events // // // // Connect event? if (events.lNetworkEvents & FD_CONNECT) { //g_log.AddLogInfo(0,"\nFD_CONNECT: %d", events.iErrorCode[FD_CONNECT_BIT]); g_log.AddLogInfo(0,"Master server %s",pGI->szMasterServerIP[0]); g_log.AddLogInfo(0,"Sending packet string: [%s] Length: %d",sendbuf,len); g_log.AddLogInfo(0,"xml config: %s ",pGI->szMasterQueryString); if(send(ConnectSocket, sendbuf, len , 0)==SOCKET_ERROR) { KillTimer(g_hWnd,IDT_1SECOND); WSACloseEvent(hEvent); closesocket(ConnectSocket); g_log.AddLogInfo(GS_LOG_ERROR,"Error sending master query packet!"); return 2; } } // Read event? if (events.lNetworkEvents & FD_READ) { //g_log.AddLogInfo(0,"\nFD_READ: %d, %d",events.iErrorCode[FD_READ_BIT],i); // Read the data and write it to stdout packet[i]=(unsigned char*)ReadPacket(ConnectSocket, &packetlen); packet_len[i] = packetlen; i++; if(i>=MAX_PACKETS) break; } // Close event? if (events.lNetworkEvents & FD_CLOSE) { g_log.AddLogInfo(0,"\nFD_CLOSE: %d",events.iErrorCode[FD_CLOSE_BIT]); break; } /* // Write event? if (events.lNetworkEvents & FD_WRITE) { g_log.AddLogInfo(0,"\nFD_WRITE: %d",events.iErrorCode[FD_WRITE_BIT]); } */ } closesocket(ConnectSocket); WSACloseEvent(hEvent); DWORD Q3_dwNewTotalServers=0; for(i=0; i<MAX_PACKETS;i++) { if(packet[i] != NULL) { Q3_dwNewTotalServers += Q3_ParseServers((char*)packet[i],packet_len[i],pGI); free(packet[i]); packet[i]=NULL; SetStatusText(pGI->iIconIndex,g_lang.GetString("StatusReceivingMaster"),Q3_dwNewTotalServers,pGI->szGAME_NAME); if(g_bCancel) { //ensure to clean up for(i=0; i<MAX_PACKETS;i++) { if(packet[i] != NULL) { free(packet[i]); packet[i]=NULL; } } break; } Sleep(50); //give cpu sometime to breath } } // KillTimer(g_hWnd,IDT_TIMER_1SECOND); pGI->dwTotalServers += Q3_dwNewTotalServers; return 0; }
int main ( int argc, char* argv[] ) { pgm_error_t* pgm_err = NULL; setlocale (LC_ALL, ""); #ifndef _WIN32 puts ("いちごのショートケーキ"); #else puts ("ichigo no shōtokēki"); #endif if (!pgm_init (&pgm_err)) { fprintf (stderr, "Unable to start PGM engine: %s\n", pgm_err->message); pgm_error_free (pgm_err); return EXIT_FAILURE; } /* parse program arguments */ #ifdef _WIN32 const char* binary_name = strrchr (argv[0], '\\'); #else const char* binary_name = strrchr (argv[0], '/'); #endif if (NULL == binary_name) binary_name = argv[0]; else binary_name++; int c; while ((c = getopt (argc, argv, "s:n:p:f:K:N:lih")) != -1) { switch (c) { case 'n': network = optarg; break; case 's': port = atoi (optarg); break; case 'p': udp_encap_port = atoi (optarg); break; case 'f': use_fec = TRUE; break; case 'K': rs_k = atoi (optarg); break; case 'N': rs_n = atoi (optarg); break; case 'l': use_multicast_loop = TRUE; break; case 'i': pgm_if_print_all(); return EXIT_SUCCESS; case 'h': case '?': usage (binary_name); } } if (use_fec && ( !rs_n || !rs_k )) { fprintf (stderr, "Invalid Reed-Solomon parameters RS(%d,%d).\n", rs_n, rs_k); usage (binary_name); } /* setup signal handlers */ #ifdef SIGHUP signal (SIGHUP, SIG_IGN); #endif #ifndef _WIN32 int e = pipe (terminate_pipe); assert (0 == e); signal (SIGINT, on_signal); signal (SIGTERM, on_signal); #else terminateEvent = WSACreateEvent (); SetConsoleCtrlHandler ((PHANDLER_ROUTINE)on_console_ctrl, TRUE); setvbuf (stdout, (char *) NULL, _IONBF, 0); #endif /* !_WIN32 */ if (!on_startup()) { fprintf (stderr, "Startup failed\n"); return EXIT_FAILURE; } /* dispatch loop */ #ifndef _WIN32 int fds, read_fd = async_get_socket (async); fd_set readfds; #else DWORD cEvents = 2; WSAEVENT waitEvents[ 2 ]; DWORD dwEvents; waitEvents[0] = terminateEvent; waitEvents[1] = async_get_event (async); #endif /* !_WIN32 */ puts ("Entering PGM message loop ... "); do { char buffer[4096]; struct pgm_sockaddr_t from; socklen_t fromlen = sizeof (from); const ssize_t len = async_recvfrom (async, buffer, sizeof(buffer), &from, &fromlen); if (len >= 0) { on_data (buffer, len, &from); } else { #ifndef _WIN32 fds = MAX(terminate_pipe[0], read_fd) + 1; FD_ZERO(&readfds); FD_SET(terminate_pipe[0], &readfds); FD_SET(read_fd, &readfds); fds = select (fds, &readfds, NULL, NULL, NULL); #else dwEvents = WSAWaitForMultipleEvents (cEvents, waitEvents, FALSE, WSA_INFINITE, FALSE); switch (dwEvents) { case WSA_WAIT_EVENT_0+1: WSAResetEvent (waitEvents[1]); break; default: break; } #endif /* _WIN32 */ } } while (!is_terminated); puts ("Message loop terminated, cleaning up."); /* cleanup */ #ifndef _WIN32 close (terminate_pipe[0]); close (terminate_pipe[1]); #else WSACloseEvent (terminateEvent); #endif /* !_WIN32 */ if (async) { puts ("Destroying asynchronous queue."); async_destroy (async); async = NULL; } if (sock) { puts ("Closing PGM socket."); pgm_close (sock, TRUE); sock = NULL; } puts ("PGM engine shutdown."); pgm_shutdown (); puts ("finished."); return EXIT_SUCCESS; }
string GetGamerData::GetHTML(const string& strServerName, const string& strFileName) { string strGET = ""; string strHTML = ""; // ホストの検索 LPHOSTENT lpHostEntry; lpHostEntry = gethostbyname(this->GamerCardServer.c_str()); if (lpHostEntry == NULL) { //PRINTERROR("gethostbyname()"); return strHTML; } // サーバーアドレス構造体を埋める SOCKADDR_IN sa; sa.sin_family = AF_INET; sa.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list); sa.sin_port = htons(80); //HTTPポート // TCP/IPストリームソケットを作成する SOCKET Socket; Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (Socket == INVALID_SOCKET) { //PRINTERROR("socket()"); return strHTML; } // このソケットで使用するイベントオブジェクトを作成する WSAEVENT hEvent; hEvent = WSACreateEvent(); if (hEvent == WSA_INVALID_EVENT) { //PRINTERROR("WSACreateEvent()"); closesocket(Socket); return strHTML; } // ソケットを非ブロッキングにし、ネットワークイベントを関連付ける int nRet; nRet = WSAEventSelect(Socket,hEvent,FD_READ|FD_CONNECT|FD_CLOSE); if (nRet == SOCKET_ERROR) { //PRINTERROR("EventSelect()"); closesocket(Socket); WSACloseEvent(hEvent); return strHTML; } // 接続を要求する nRet = connect(Socket,(LPSOCKADDR)&sa,sizeof(SOCKADDR_IN)); if (nRet == SOCKET_ERROR) { nRet = WSAGetLastError(); if (nRet == WSAEWOULDBLOCK) { //fprintf(stderr,"\nConnect would block"); } else { //PRINTERROR("connect()"); closesocket(Socket); WSACloseEvent(hEvent); return strHTML; } } // 非同期ネットワークイベントを処理する char szBuffer[4096]; char szBufferZ[8192]; WSANETWORKEVENTS events; while(1) { // 何か発生するのを待機する DWORD dwRet; dwRet = WSAWaitForMultipleEvents(1, &hEvent, FALSE,10000,FALSE); if (dwRet == WSA_WAIT_TIMEOUT) { break; } // どのイベントが発生したかを判別する nRet = WSAEnumNetworkEvents(Socket, hEvent, &events); if (nRet == SOCKET_ERROR) { //PRINTERROR("WSAEnumNetworkEvents()"); break; } // イベントを処理する // 接続イベントかどうか? if (events.lNetworkEvents & FD_CONNECT) { // http要求を送信する strGET = ""; strGET += "GET "; strGET += strFileName; strGET += " HTTP/1.1\r\nHost: "; strGET += strServerName; strGET += "\r\nKeep-Alive: timeout=5, max=20\r\nConnection: close\r\n\r\n"; nRet = send(Socket, strGET.c_str(), strGET.size(), 0); if (nRet == SOCKET_ERROR) { //PRINTERROR("send()"); break; } } // 読み取りイベントかどうか? if (events.lNetworkEvents & FD_READ) { // データを読み取り、stdoutに書き込む nRet = recv(Socket, szBuffer, sizeof(szBuffer), 0); if (nRet == SOCKET_ERROR) { //PRINTERROR("recv()"); break; } ZeroMemory(szBufferZ,sizeof(szBufferZ)); memcpy(szBufferZ,szBuffer,nRet); strHTML.append(szBufferZ); } // 終了イベントかどうか? if (events.lNetworkEvents & FD_CLOSE) { break; } // 書き込みイベントかどうか? if (events.lNetworkEvents & FD_WRITE) { } } closesocket(Socket); WSACloseEvent(hEvent); return strHTML; }
int WaitLatchOrSocket(volatile Latch *latch, SOCKET sock, long timeout) { DWORD rc; HANDLE events[3]; HANDLE latchevent; HANDLE sockevent; int numevents; int result = 0; latchevent = latch->event; events[0] = latchevent; events[1] = pgwin32_signal_event; numevents = 2; if (sock != PGINVALID_SOCKET) { sockevent = WSACreateEvent(); WSAEventSelect(sock, sockevent, FD_READ); events[numevents++] = sockevent; } for (;;) { /* * Reset the event, and check if the latch is set already. If someone * sets the latch between this and the WaitForMultipleObjects() call * below, the setter will set the event and WaitForMultipleObjects() * will return immediately. */ if (!ResetEvent(latchevent)) elog(ERROR, "ResetEvent failed: error code %d", (int) GetLastError()); if (latch->is_set) { result = 1; break; } rc = WaitForMultipleObjects(numevents, events, FALSE, (timeout >= 0) ? (timeout / 1000) : INFINITE); if (rc == WAIT_FAILED) elog(ERROR, "WaitForMultipleObjects() failed: error code %d", (int) GetLastError()); else if (rc == WAIT_TIMEOUT) { result = 0; break; } else if (rc == WAIT_OBJECT_0 + 1) pgwin32_dispatch_queued_signals(); else if (rc == WAIT_OBJECT_0 + 2) { Assert(sock != PGINVALID_SOCKET); result = 2; break; } else if (rc != WAIT_OBJECT_0) elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %d", rc); } /* Clean up the handle we created for the socket */ if (sock != PGINVALID_SOCKET) { WSAEventSelect(sock, sockevent, 0); WSACloseEvent(sockevent); } return result; }
void main() { WSADATA wsa; // 버전정보 if( WSAStartup( MAKEWORD(2,2), &wsa) != 0) //DLL 로딩 { puts("WSAStartup Error !! "); return ; } //1) 핸드폰 단말기 구입 --> SOCKET : 통신을 하기위한 매개체 !! SOCKET ServerSocket; //2) 소켓 생성 !! // TCP/UDP TCP ServerSocket = socket( AF_INET , SOCK_STREAM, 0); if( ServerSocket == INVALID_SOCKET) { puts("socket() error!!"); return ; } //3) Usim SOCKADDR_IN ServerAddr; ServerAddr.sin_family = AF_INET; // TCP/UDP ServerAddr.sin_port = htons(20000); // 포트번호 ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 4) socket + sockaddr == 핸드폰 + Usim int ret = bind( ServerSocket, // 소켓 (SOCKADDR*)&ServerAddr, //주소 구조체 sizeof(ServerAddr)); // 주소의 크기 if( ret == SOCKET_ERROR) { puts("bind() error !! "); return ; } // 4) 통화 대기 !! ret = listen( ServerSocket, // 기다릴 소켓 SOMAXCONN); // 가능한 최대값 if( ret == SOCKET_ERROR ) { puts("listen() error !!"); return ; } // 1) 소켓과 이벤트를 연결하고 배열에 저장 HANDLE hEvent = WSACreateEvent(); //이벤트 객체 생성 ! // 2) 연결 !! WSAEventSelect( ServerSocket, // 이벤트를 처리할 소켓 hEvent, // 신호를 보내줄 이벤트 FD_ACCEPT|FD_CLOSE); SockList[SockCnt] = ServerSocket; EventList[SockCnt] = hEvent; SockCnt++; int index = 0; WSANETWORKEVENTS ne; while(1) { // 소켓에서 네트워크 이벤트 발생하면 Event객체가 시그날 되기를 기다린다!! index = WSAWaitForMultipleEvents( SockCnt, // 시그날을 기다리는 이벤트 수 EventList, // 이벤트 배열 FALSE, // 1개만 시그날이 돼도 리턴 !! WSA_INFINITE, FALSE); index -= WSA_WAIT_EVENT_0; // 1) networkevent 구조체에 이벤트 내용을 가져온다 !! // 2) EventList[index] 이벤트를 넌시그날로 변경 WSAEnumNetworkEvents( SockList[index], // 이벤트가 발생한 소켓 EventList[index], // 시그널 된 이벤트 &ne); // out put if( ne.lNetworkEvents & FD_ACCEPT) { if(ne.iErrorCode[FD_ACCEPT_BIT] != 0) { puts("accept error"); return; } SOCKADDR_IN ClientAddr; int len = sizeof(ClientAddr); SOCKET ClientSocket; ClientSocket = accept( SockList[index] , // 대기하는 소켓 (SOCKADDR*)&ClientAddr, // 클라이언트의 주소를 가져올 구조체 &len); if ( ClientSocket == INVALID_SOCKET) { puts("accept error "); return ; } printf("[ %s ] : %d 님 접속\n" , inet_ntoa( ClientAddr.sin_addr), ntohs( ClientAddr.sin_port ) ); // 접속자 소켓과 연결될 이벤트 생성 !! WSAEVENT hClientEvent = WSACreateEvent(); // socket + event WSAEventSelect( ClientSocket, hClientEvent, FD_READ|FD_WRITE|FD_CLOSE); SockList[SockCnt] = ClientSocket; EventList[SockCnt] = hClientEvent; SockCnt++; } if( ne.lNetworkEvents & FD_READ || ne.lNetworkEvents & FD_WRITE) { if( ne.lNetworkEvents & FD_READ && ne.iErrorCode[FD_READ_BIT] != 0 ) { puts("FD_READ_BIT"); return; } if( ne.lNetworkEvents & FD_WRITE && ne.iErrorCode[FD_WRITE_BIT] != 0) { puts("FD_WRITE_BIT"); return; } char buf[BUF_SIZE] = {0}; recv( SockList[index], buf , BUF_SIZE, 0); SOCKADDR_IN SenderAddr; int len = sizeof(SenderAddr); getpeername( SockList[index], (SOCKADDR*)&SenderAddr, &len); printf("[ %s ] %s\n", inet_ntoa( SenderAddr.sin_addr) ,buf ); for( int i = 1; i< SockCnt; i++) { if( i != index) send( SockList[i], buf, BUF_SIZE, 0); } } if( ne.lNetworkEvents & FD_CLOSE) { if(ne.iErrorCode[FD_CLOSE_BIT] != 0) { puts("FD_CLOSE_BIT"); return; } RemoveSocket( index ); } } /* // 화면에 접속한 클라이언트의 IP를 출력 !! */ WSACleanup(); // DLL 정리 }
/* Relay data between a socket and a process until the process dies or stops sending or receiving data. The socket descriptor and process pipe handles are in the data argument, which must be a pointer to struct subprocess_info. This function is a workaround for the fact that we can't just run a process after redirecting its input handles to a socket. If the process, for example, redirects its own stdin, it somehow confuses the socket and stdout stops working. This is exactly what ncat does (as part of the Windows stdin workaround), so it can't be ignored. This function can be invoked through CreateThread to simulate fork+exec, or called directly to simulate exec. It frees the subprocess_info struct and closes the socket and pipe handles before returning. Returns the exit code of the subprocess. */ static DWORD WINAPI subprocess_thread_func(void *data) { struct subprocess_info *info; char pipe_buffer[BUFSIZ]; OVERLAPPED overlap = { 0 }; HANDLE events[3]; DWORD ret, rc; int crlf_state = 0; info = (struct subprocess_info *) data; /* Three events we watch for: socket read, pipe read, and process end. */ events[0] = (HANDLE) WSACreateEvent(); WSAEventSelect(info->fdn.fd, events[0], FD_READ | FD_CLOSE); events[1] = info->child_out_r; events[2] = info->proc; /* To avoid blocking or polling, we use asynchronous I/O, or what Microsoft calls "overlapped" I/O, on the process pipe. WaitForMultipleObjects reports when the read operation is complete. */ ReadFile(info->child_out_r, pipe_buffer, sizeof(pipe_buffer), NULL, &overlap); /* Loop until EOF or error. */ for (;;) { DWORD n_r, n_w; int i, n; i = WaitForMultipleObjects(3, events, FALSE, INFINITE); if (i == WAIT_OBJECT_0) { /* Read from socket, write to process. */ char buffer[BUFSIZ]; int pending; ResetEvent(events[0]); do { n = ncat_recv(&info->fdn, buffer, sizeof(buffer), &pending); if (n <= 0) goto loop_end; n_r = n; if (WriteFile(info->child_in_w, buffer, n_r, &n_w, NULL) == 0) break; if (n_w != n) goto loop_end; } while (pending); } else if (i == WAIT_OBJECT_0 + 1) { char *crlf = NULL, *wbuf; /* Read from process, write to socket. */ if (GetOverlappedResult(info->child_out_r, &overlap, &n_r, FALSE)) { wbuf = pipe_buffer; if (o.crlf) { n = n_r; if (fix_line_endings((char *) pipe_buffer, &n, &crlf, &crlf_state)) wbuf = crlf; n_r = n; } /* The above call to WSAEventSelect puts the socket in non-blocking mode, but we want this send to block, not potentially return WSAEWOULDBLOCK. We call block_socket, but first we must clear out the select event. */ WSAEventSelect(info->fdn.fd, events[0], 0); block_socket(info->fdn.fd); n = ncat_send(&info->fdn, wbuf, n_r); if (crlf != NULL) free(crlf); if (n != n_r) break; /* Restore the select event (and non-block the socket again.) */ WSAEventSelect(info->fdn.fd, events[0], FD_READ | FD_CLOSE); /* Queue another asychronous read. */ ReadFile(info->child_out_r, pipe_buffer, sizeof(pipe_buffer), NULL, &overlap); } else { if (GetLastError() != ERROR_IO_PENDING) /* Error or end of file. */ break; } } else if (i == WAIT_OBJECT_0 + 2) { /* The child died. There are no more writes left in the pipe because WaitForMultipleObjects guarantees events with lower indexes are handled first. */ break; } else { break; } } loop_end: WSACloseEvent(events[0]); rc = unregister_subprocess(info->proc); ncat_assert(rc != -1); GetExitCodeProcess(info->proc, &ret); if (ret == STILL_ACTIVE) { if (o.debug > 1) logdebug("Subprocess still running, terminating it.\n"); rc = TerminateProcess(info->proc, 0); if (rc == 0) { if (o.debug > 1) logdebug("TerminateProcess failed with code %d.\n", rc); } } GetExitCodeProcess(info->proc, &ret); if (o.debug > 1) logdebug("Subprocess ended with exit code %d.\n", ret); shutdown(info->fdn.fd, 2); subprocess_info_close(info); free(info); rc = WaitForSingleObject(pseudo_sigchld_mutex, INFINITE); ncat_assert(rc == WAIT_OBJECT_0); if (pseudo_sigchld_handler != NULL) pseudo_sigchld_handler(); rc = ReleaseMutex(pseudo_sigchld_mutex); ncat_assert(rc != 0); return ret; }
static int select_ws(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { DWORD milliseconds, wait, idx; WSANETWORKEVENTS wsanetevents; struct select_ws_data *data; HANDLE handle, *handles; curl_socket_t sock; long networkevents; WSAEVENT wsaevent; int error, fds; HANDLE waitevent = NULL; DWORD nfd = 0, thd = 0, wsa = 0; int ret = 0; /* check if the input value is valid */ if(nfds < 0) { errno = EINVAL; return -1; } /* check if we got descriptors, sleep in case we got none */ if(!nfds) { Sleep((timeout->tv_sec*1000)+(DWORD)(((double)timeout->tv_usec)/1000.0)); return 0; } /* create internal event to signal waiting threads */ waitevent = CreateEvent(NULL, TRUE, FALSE, NULL); if(!waitevent) { errno = ENOMEM; return -1; } /* allocate internal array for the internal data */ data = malloc(nfds * sizeof(struct select_ws_data)); if(data == NULL) { errno = ENOMEM; return -1; } /* allocate internal array for the internal event handles */ handles = malloc(nfds * sizeof(HANDLE)); if(handles == NULL) { free(data); errno = ENOMEM; return -1; } /* clear internal arrays */ memset(data, 0, nfds * sizeof(struct select_ws_data)); memset(handles, 0, nfds * sizeof(HANDLE)); /* loop over the handles in the input descriptor sets */ for(fds = 0; fds < nfds; fds++) { networkevents = 0; handles[nfd] = 0; if(FD_ISSET(fds, readfds)) networkevents |= FD_READ|FD_ACCEPT|FD_CLOSE; if(FD_ISSET(fds, writefds)) networkevents |= FD_WRITE|FD_CONNECT; if(FD_ISSET(fds, exceptfds)) networkevents |= FD_OOB|FD_CLOSE; /* only wait for events for which we actually care */ if(networkevents) { data[nfd].fd = curlx_sitosk(fds); if(fds == fileno(stdin)) { handle = GetStdHandle(STD_INPUT_HANDLE); handle = select_ws_wait(handle, waitevent); handles[nfd] = handle; data[thd].thread = handle; thd++; } else if(fds == fileno(stdout)) { handles[nfd] = GetStdHandle(STD_OUTPUT_HANDLE); } else if(fds == fileno(stderr)) { handles[nfd] = GetStdHandle(STD_ERROR_HANDLE); } else { wsaevent = WSACreateEvent(); if(wsaevent != WSA_INVALID_EVENT) { error = WSAEventSelect(fds, wsaevent, networkevents); if(error != SOCKET_ERROR) { handle = (HANDLE) wsaevent; handles[nfd] = handle; data[wsa].wsasock = curlx_sitosk(fds); data[wsa].wsaevent = wsaevent; wsa++; } else { WSACloseEvent(wsaevent); handle = (HANDLE) curlx_sitosk(fds); handle = select_ws_wait(handle, waitevent); handles[nfd] = handle; data[thd].thread = handle; thd++; } } } nfd++; } } /* convert struct timeval to milliseconds */ if(timeout) { milliseconds = ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000)); } else { milliseconds = INFINITE; } /* wait for one of the internal handles to trigger */ wait = WaitForMultipleObjectsEx(nfd, handles, FALSE, milliseconds, FALSE); /* signal the event handle for the waiting threads */ SetEvent(waitevent); /* loop over the internal handles returned in the descriptors */ for(idx = 0; idx < nfd; idx++) { handle = handles[idx]; sock = data[idx].fd; fds = curlx_sktosi(sock); /* check if the current internal handle was triggered */ if(wait != WAIT_FAILED && (wait - WAIT_OBJECT_0) <= idx && WaitForSingleObjectEx(handle, 0, FALSE) == WAIT_OBJECT_0) { /* first handle stdin, stdout and stderr */ if(fds == fileno(stdin)) { /* stdin is never ready for write or exceptional */ FD_CLR(sock, writefds); FD_CLR(sock, exceptfds); } else if(fds == fileno(stdout) || fds == fileno(stderr)) { /* stdout and stderr are never ready for read or exceptional */ FD_CLR(sock, readfds); FD_CLR(sock, exceptfds); } else { /* try to handle the event with the WINSOCK2 functions */ wsanetevents.lNetworkEvents = 0; error = WSAEnumNetworkEvents(fds, handle, &wsanetevents); if(error != SOCKET_ERROR) { /* remove from descriptor set if not ready for read/accept/close */ if(!(wsanetevents.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))) FD_CLR(sock, readfds); /* remove from descriptor set if not ready for write/connect */ if(!(wsanetevents.lNetworkEvents & (FD_WRITE|FD_CONNECT))) FD_CLR(sock, writefds); /* HACK: * use exceptfds together with readfds to signal * that the connection was closed by the client. * * Reason: FD_CLOSE is only signaled once, sometimes * at the same time as FD_READ with data being available. * This means that recv/sread is not reliable to detect * that the connection is closed. */ /* remove from descriptor set if not exceptional */ if(!(wsanetevents.lNetworkEvents & (FD_OOB|FD_CLOSE))) FD_CLR(sock, exceptfds); } } /* check if the event has not been filtered using specific tests */ if(FD_ISSET(sock, readfds) || FD_ISSET(sock, writefds) || FD_ISSET(sock, exceptfds)) { ret++; } } else { /* remove from all descriptor sets since this handle did not trigger */ FD_CLR(sock, readfds); FD_CLR(sock, writefds); FD_CLR(sock, exceptfds); } } for(fds = 0; fds < nfds; fds++) { if(FD_ISSET(fds, readfds)) logmsg("select_ws: %d is readable", fds); if(FD_ISSET(fds, writefds)) logmsg("select_ws: %d is writable", fds); if(FD_ISSET(fds, exceptfds)) logmsg("select_ws: %d is excepted", fds); } for(idx = 0; idx < wsa; idx++) { WSAEventSelect(data[idx].wsasock, NULL, 0); WSACloseEvent(data[idx].wsaevent); } for(idx = 0; idx < thd; idx++) { WaitForSingleObject(data[idx].thread, INFINITE); CloseHandle(data[idx].thread); } CloseHandle(waitevent); free(handles); free(data); return ret; }
explicit IOController(std::unique_ptr<NUClear::Environment> environment) : Reactor(std::move(environment)) { // Startup WSA for IO WORD version = MAKEWORD(2, 2); WSADATA wsa_data; WSAStartup(version, &wsa_data); // Reserve 1024 event slots // Hopefully we won't have more events than that // Even if we do it should be fine (after a glitch) fds.reserve(1024); // Create an event to use for the notifier notifier = WSACreateEvent(); // We always have the notifier in the event list fds.push_back(notifier); on<Trigger<dsl::word::IOConfiguration>>().then( "Configure IO Reaction", [this](const dsl::word::IOConfiguration& config) { // Lock our mutex std::lock_guard<std::mutex> lock(reaction_mutex); // Make an event for this SOCKET auto event = WSACreateEvent(); // Link our event to the socket WSAEventSelect(config.fd, event, config.events); // Add all the information to the list reactions.insert(std::make_pair(event, Event{config.fd, config.reaction, config.events})); // Also add it to the end of our watching list fds.push_back(event); // Enable our notification event WSASetEvent(notifier); }); on<Trigger<dsl::operation::Unbind<IO>>>().then("Unbind IO Reaction", [this](const dsl::operation::Unbind<IO>& unbind) { // Lock our mutex // Find this reaction in our list of reactions // Remove it // WSACloseEvent // Flag that our list is dirty // Enable our notification event }); on<Shutdown>().then("Shutdown IO Controller", [this] { // Set shutdown to true shutdown = true; // Enable our notification event WSASetEvent(notifier); }); on<Always>().then("IO Controller", [this] { if (!shutdown) { // Wait for events auto event = WSAWaitForMultipleEvents(fds.size(), fds.data(), false, WSA_INFINITE, false); // Check if the return value is an event in our list if (event >= WSA_WAIT_EVENT_0 && event < WSA_WAIT_EVENT_0 + fds.size()) { // Check for notification event if (event == WSA_WAIT_EVENT_0) { WSAResetEvent(notifier); } else { // Get our event auto& e = fds[event - WSA_WAIT_EVENT_0]; // Get our associated Event object (if it exists) auto r = reactions.find(e); if (r != reactions.end()) { // Enum the events to work out which ones fired WSANETWORKEVENTS wsae; WSAEnumNetworkEvents(r->second.fd, e, &wsae); // Make our event to pass through IO::Event e; e.fd = r->second.fd; // Our events are what we got from the enum events call e.events = wsae.lNetworkEvents; // Store the event in our thread local cache IO::ThreadEventStore::value = &e; // Submit the task (which should run the get) try { auto task = r->second.reaction->get_task(); if (task) { powerplant.submit(std::move(task)); } } catch (...) { } // Reset our value IO::ThreadEventStore::value = nullptr; } } } } // If not shudown // If dirty then update our list // If // WSAWaitForMultipleEvents( // countOfEvents // arrayofWSAEVENT // waituntilall?orany // FALSE // timeout // WSA_INFINITE // alertable? // FALSE // ) // Get the item that is associated with this event // Call the reaction with the information }); }
int WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock, long timeout) { DWORD rc; instr_time start_time, cur_time; long cur_timeout; HANDLE events[4]; HANDLE latchevent; HANDLE sockevent = WSA_INVALID_EVENT; int numevents; int result = 0; int pmdeath_eventno = 0; /* Ignore WL_SOCKET_* events if no valid socket is given */ if (sock == PGINVALID_SOCKET) wakeEvents &= ~(WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE); Assert(wakeEvents != 0); /* must have at least one wake event */ /* Cannot specify WL_SOCKET_WRITEABLE without WL_SOCKET_READABLE */ Assert((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) != WL_SOCKET_WRITEABLE); if ((wakeEvents & WL_LATCH_SET) && latch->owner_pid != MyProcPid) elog(ERROR, "cannot wait on a latch owned by another process"); /* * Initialize timeout if requested. We must record the current time so * that we can determine the remaining timeout if WaitForMultipleObjects * is interrupted. */ if (wakeEvents & WL_TIMEOUT) { INSTR_TIME_SET_CURRENT(start_time); Assert(timeout >= 0); cur_timeout = timeout; } else cur_timeout = INFINITE; /* * Construct an array of event handles for WaitforMultipleObjects(). * * Note: pgwin32_signal_event should be first to ensure that it will be * reported when multiple events are set. We want to guarantee that * pending signals are serviced. */ latchevent = latch->event; events[0] = pgwin32_signal_event; events[1] = latchevent; numevents = 2; if (wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) { /* Need an event object to represent events on the socket */ int flags = 0; if (wakeEvents & WL_SOCKET_READABLE) flags |= (FD_READ | FD_CLOSE); if (wakeEvents & WL_SOCKET_WRITEABLE) flags |= FD_WRITE; sockevent = WSACreateEvent(); if (sockevent == WSA_INVALID_EVENT) elog(ERROR, "failed to create event for socket: error code %u", WSAGetLastError()); if (WSAEventSelect(sock, sockevent, flags) != 0) elog(ERROR, "failed to set up event for socket: error code %u", WSAGetLastError()); events[numevents++] = sockevent; } if (wakeEvents & WL_POSTMASTER_DEATH) { pmdeath_eventno = numevents; events[numevents++] = PostmasterHandle; } /* Ensure that signals are serviced even if latch is already set */ pgwin32_dispatch_queued_signals(); do { /* * Reset the event, and check if the latch is set already. If someone * sets the latch between this and the WaitForMultipleObjects() call * below, the setter will set the event and WaitForMultipleObjects() * will return immediately. */ if (!ResetEvent(latchevent)) elog(ERROR, "ResetEvent failed: error code %lu", GetLastError()); if ((wakeEvents & WL_LATCH_SET) && latch->is_set) { result |= WL_LATCH_SET; /* * Leave loop immediately, avoid blocking again. We don't attempt * to report any other events that might also be satisfied. */ break; } rc = WaitForMultipleObjects(numevents, events, FALSE, cur_timeout); if (rc == WAIT_FAILED) elog(ERROR, "WaitForMultipleObjects() failed: error code %lu", GetLastError()); else if (rc == WAIT_TIMEOUT) { result |= WL_TIMEOUT; } else if (rc == WAIT_OBJECT_0) { /* Service newly-arrived signals */ pgwin32_dispatch_queued_signals(); } else if (rc == WAIT_OBJECT_0 + 1) { /* * Latch is set. We'll handle that on next iteration of loop, but * let's not waste the cycles to update cur_timeout below. */ continue; } else if ((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) && rc == WAIT_OBJECT_0 + 2) /* socket is at event slot 2 */ { WSANETWORKEVENTS resEvents; ZeroMemory(&resEvents, sizeof(resEvents)); if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) != 0) elog(ERROR, "failed to enumerate network events: error code %u", WSAGetLastError()); if ((wakeEvents & WL_SOCKET_READABLE) && (resEvents.lNetworkEvents & (FD_READ | FD_CLOSE))) { result |= WL_SOCKET_READABLE; } if ((wakeEvents & WL_SOCKET_WRITEABLE) && (resEvents.lNetworkEvents & FD_WRITE)) { result |= WL_SOCKET_WRITEABLE; } } else if ((wakeEvents & WL_POSTMASTER_DEATH) && rc == WAIT_OBJECT_0 + pmdeath_eventno) { /* * Postmaster apparently died. Since the consequences of falsely * returning WL_POSTMASTER_DEATH could be pretty unpleasant, we * take the trouble to positively verify this with * PostmasterIsAlive(), even though there is no known reason to * think that the event could be falsely set on Windows. */ if (!PostmasterIsAlive()) result |= WL_POSTMASTER_DEATH; } else elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %lu", rc); /* If we're not done, update cur_timeout for next iteration */ if (result == 0 && cur_timeout != INFINITE) { INSTR_TIME_SET_CURRENT(cur_time); INSTR_TIME_SUBTRACT(cur_time, start_time); cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time); if (cur_timeout < 0) cur_timeout = 0; } } while (result == 0); /* Clean up the event object we created for the socket */ if (sockevent != WSA_INVALID_EVENT) { WSAEventSelect(sock, NULL, 0); WSACloseEvent(sockevent); } return result; }
int net_recvBytes(int sock, char *buf, int bufSize, int * outLen, int timeout) { WSAOVERLAPPED recvOverlapped; WSABUF dataBuf; DWORD recvBytes = 0; int index = 0; DWORD flags = 0; int rc = 0; int lastError = 0; // Make sure the RecvOverlapped struct is zeroed out SecureZeroMemory((PVOID) & recvOverlapped, sizeof (WSAOVERLAPPED)); SecureZeroMemory((PVOID) & dataBuf, sizeof (WSABUF)); // Create an event handle and setup an overlapped structure. recvOverlapped.hEvent = WSACreateEvent(); if (recvOverlapped.hEvent == NULL) { debug_log(LOG_ERR, "net_recvBytes(): WSACreateEvent failed: %d", WSAGetLastError()); return SOCK_IO_ERROR; } dataBuf.len = bufSize-1; // one for ending null dataBuf.buf = buf; *buf = '\0'; while (index < bufSize) { recvBytes = 0; flags = 0; wait_for_recv: rc = WSARecv(sock, &dataBuf, 1, &recvBytes, &flags, &recvOverlapped, NULL); if (rc != 0) { if (rc == SOCKET_ERROR) { lastError = WSAGetLastError(); if (lastError == WSAEWOULDBLOCK) { if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) { closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_WDOG_SHUTDOWN; } SleepEx(SLEEP_EX_INTERVAL, TRUE); goto wait_for_recv; } else { if (lastError != WSA_IO_PENDING) { debug_log(LOG_ERR, "net_recvBytes(): WSARecv failed with error: %d", lastError); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } } } wait_for_io: rc = WSAWaitForMultipleEvents(1, &recvOverlapped.hEvent, TRUE, timeout, TRUE); if (rc == WSA_WAIT_TIMEOUT) { debug_log(LOG_ERR, "net_recvBytes(): overlapped I/O timeout: %d", timeout); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_TIMEOUT; } if (rc == WSA_WAIT_IO_COMPLETION) { if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) { closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_WDOG_SHUTDOWN; } SleepEx(SLEEP_EX_INTERVAL, TRUE); goto wait_for_io; } wait_for_ov: rc = WSAGetOverlappedResult(sock, &recvOverlapped, &recvBytes, FALSE, &flags); if (rc == FALSE) { lastError = WSAGetLastError(); if (lastError == WSA_IO_INCOMPLETE) { if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) { closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_WDOG_SHUTDOWN; } SleepEx(SLEEP_EX_INTERVAL, TRUE); goto wait_for_ov; } debug_log(LOG_ERR, "net_recvBytes(): overlapped I/O failed with error: %d", lastError); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } // ------------------------ // Reset the signaled event // ------------------------ rc = WSAResetEvent(recvOverlapped.hEvent); if (rc == FALSE) { debug_log(LOG_ERR, "net_recvBytes(): WSAResetEvent failed with error = %d", WSAGetLastError()); closesocket(sock); WSACloseEvent(recvOverlapped.hEvent); return SOCK_IO_ERROR; } } if (recvBytes == 0) break; if ((index + (int) recvBytes) > bufSize) break; index += recvBytes; buf[index] = '\0'; if ((bufSize-index) <= 0) break; dataBuf.len = bufSize-index; dataBuf.buf = buf+index; } // while (index < bufSize) WSACloseEvent(recvOverlapped.hEvent); *outLen = index; return SOCK_NO_ERROR; } // end of net_recvBytes()
void TCPServer::WaitForClientThread() { csIsWaiting.Enter(); bIsWaiting = true; csIsWaiting.Leave(); SOCKET UDPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (UDPSocket == INVALID_SOCKET) { ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("UDPSocket create fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } sockaddr_in udp_addr = {0}; udp_addr.sin_family = AF_INET; udp_addr.sin_port = htons(PORT); udp_addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(UDPSocket, (sockaddr*)&udp_addr, sizeof(sockaddr_in)) == SOCKET_ERROR) { ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("UDPSocket bind fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } WSAEVENT hEvent = WSACreateEvent(); if (hEvent == WSA_INVALID_EVENT) { ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("WSACreateEvent fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } if (WSAEventSelect(UDPSocket, hEvent, FD_READ) == SOCKET_ERROR) { ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("WSAEventSelect fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } csStopWait.Enter(); bStopWait = false; csStopWait.Leave(); while (true) { DWORD result = WSAWaitForMultipleEvents(1, &hEvent, FALSE, 500, FALSE); if (result == WSA_WAIT_FAILED) { ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("WSAWaitForMultipleEvents fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } csStopWait.Enter(); if (bStopWait) { csStopWait.Leave(); closesocket(UDPSocket); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } csStopWait.Leave(); if (result == WSA_WAIT_TIMEOUT) { continue; } WSANETWORKEVENTS netEvents = {0}; if (WSAEnumNetworkEvents(UDPSocket, hEvent, &netEvents) == SOCKET_ERROR) { ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("WSAWaitForMultipleEvents fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } if (netEvents.iErrorCode[FD_READ]) { ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("iErrorCode FD_READ fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } sockaddr_in client_addr = {0}; int client_addr_size = sizeof(sockaddr_in); UDPPacket packet = {0}; if (recvfrom(UDPSocket, (char*)&packet, sizeof(UDPPacket), 0, (sockaddr*)&client_addr, &client_addr_size) == SOCKET_ERROR) { ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("UDPSocket recvfrom fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } if (packet.message == LOCATE_SERVER) { UDPPacket answer = {0}; answer.message = CONFIRM_SERVER; csTCP.Enter(); _tcscpy_s(answer.nick, STR_SIZE, Nick); _tcscpy_s(answer.pcname, STR_SIZE, PCName); csTCP.Leave(); if (sendto(UDPSocket, (char*)&answer, sizeof(UDPPacket), 0, (sockaddr*)&client_addr, client_addr_size) == SOCKET_ERROR) { ErrorHandler(UDPSocket, WSAGetLastError(), TEXT("UDPSocket sendto fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } continue; } if (packet.message == CONNECT_TO_SERVER) { csTCP.Enter(); _tcscpy_s(oppNick, STR_SIZE, packet.nick); _tcscpy_s(oppPCName, STR_SIZE, packet.pcname); csTCP.Leave(); closesocket(UDPSocket); break; } } SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listenSocket == INVALID_SOCKET) { ErrorHandler(listenSocket, WSAGetLastError(), TEXT("listenSocket create fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } sockaddr_in listen_addr = {0}; listen_addr.sin_family = AF_INET; listen_addr.sin_port = htons(PORT); listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(listenSocket, (sockaddr*)&listen_addr, sizeof(sockaddr_in)) == SOCKET_ERROR) { ErrorHandler(listenSocket, WSAGetLastError(), TEXT("listenSocket bind fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } if (listen(listenSocket, 1) == SOCKET_ERROR) { ErrorHandler(listenSocket, WSAGetLastError(), TEXT("listenSocket listen fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } int connect_addr_size = sizeof(sockaddr_in); TCPSocket = accept(listenSocket, (sockaddr*)&connect_addr, &connect_addr_size); closesocket(listenSocket); if (TCPSocket == INVALID_SOCKET) { ErrorHandler(TCPSocket, WSAGetLastError(), TEXT("listenSocket accept fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } if (!KeepAlive()) { csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } if (!ReceiveData()) { ErrorHandler(TCPSocket, ERROR_CREATE_THREAD_FAIL, TEXT("ReceiveDataThread start fail!")); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; } csTCP.Enter(); bIsConnected = true; csTCP.Leave(); PostMessage(hSendWnd, SUCCESS_CONNECTED, NULL, NULL); csIsWaiting.Enter(); bIsWaiting = false; csIsWaiting.Leave(); return; };
int main ( int argc, char* argv[] ) { pgm_error_t* pgm_err = NULL; setlocale (LC_ALL, ""); #ifndef _WIN32 puts ("プリン プリン"); #else _putws (L"プリン プリン"); #endif if (!pgm_init (&pgm_err)) { fprintf (stderr, "Unable to start PGM engine: %s\n", pgm_err->message); pgm_error_free (pgm_err); return EXIT_FAILURE; } /* parse program arguments */ const char* binary_name = strrchr (argv[0], '/'); int c; while ((c = getopt (argc, argv, "s:n:p:f:K:N:lih")) != -1) { switch (c) { case 'n': network = optarg; break; case 's': port = atoi (optarg); break; case 'p': udp_encap_port = atoi (optarg); break; case 'f': use_fec = TRUE; break; case 'K': rs_k = atoi (optarg); break; case 'N': rs_n = atoi (optarg); break; case 'l': use_multicast_loop = TRUE; break; case 'i': pgm_if_print_all(); return EXIT_SUCCESS; case 'h': case '?': usage (binary_name); } } if (use_fec && ( !rs_n || !rs_k )) { fprintf (stderr, "Invalid Reed-Solomon parameters RS(%d,%d).\n", rs_n, rs_k); usage (binary_name); } /* setup signal handlers */ #ifdef SIGHUP signal (SIGHUP, SIG_IGN); #endif #ifndef _WIN32 int e = pipe (terminate_pipe); assert (0 == e); signal (SIGINT, on_signal); signal (SIGTERM, on_signal); #else terminate_event = CreateEvent (NULL, TRUE, FALSE, TEXT("TerminateEvent")); SetConsoleCtrlHandler ((PHANDLER_ROUTINE)on_console_ctrl, TRUE); #endif /* !_WIN32 */ if (!on_startup()) { fprintf (stderr, "Startup failed\n"); return EXIT_FAILURE; } /* dispatch loop */ #ifndef _WIN32 int fds; fd_set readfds; #else int n_handles = 3, recv_sock, pending_sock; HANDLE waitHandles[ 3 ]; DWORD dwTimeout, dwEvents; WSAEVENT recvEvent, pendingEvent; recvEvent = WSACreateEvent (); pgm_getsockopt (sock, PGM_RECV_SOCK, &recv_sock, sizeof(recv_sock)); WSAEventSelect (recv_sock, recvEvent, FD_READ); pendingEvent = WSACreateEvent (); pgm_getsockopt (sock, PGM_PENDING_SOCK, &pending_sock, sizeof(pending_sock)); WSAEventSelect (pending_sock, pendingEvent, FD_READ); waitHandles[0] = terminate_event; waitHandles[1] = recvEvent; waitHandles[2] = pendingEvent; #endif /* !_WIN32 */ puts ("Entering PGM message loop ... "); do { struct timeval tv; char buffer[4096]; size_t len; pgm_tsi_t from; const int status = pgm_recvfrom (sock, buffer, sizeof(buffer), 0, &len, &from, &pgm_err); switch (status) { case PGM_IO_STATUS_NORMAL: on_data (buffer, len, &from); break; case PGM_IO_STATUS_TIMER_PENDING: pgm_getsockopt (sock, PGM_TIME_REMAIN, &tv, sizeof(tv)); goto block; case PGM_IO_STATUS_RATE_LIMITED: pgm_getsockopt (sock, PGM_RATE_REMAIN, &tv, sizeof(tv)); case PGM_IO_STATUS_WOULD_BLOCK: /* select for next event */ block: #ifndef _WIN32 fds = terminate_pipe[0] + 1; FD_ZERO(&readfds); FD_SET(terminate_pipe[0], &readfds); pgm_select_info (sock, &readfds, NULL, &fds); fds = select (fds, &readfds, NULL, NULL, PGM_IO_STATUS_WOULD_BLOCK == status ? NULL : &tv); #else dwTimeout = PGM_IO_STATUS_WOULD_BLOCK == status ? INFINITE : (DWORD)((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); dwEvents = WaitForMultipleObjects (n_handles, waitHandles, FALSE, dwTimeout); switch (dwEvents) { case WAIT_OBJECT_0+1: WSAResetEvent (recvEvent); break; case WAIT_OBJECT_0+2: WSAResetEvent (pendingEvent); break; default: break; } #endif /* !_WIN32 */ break; default: if (pgm_err) { fprintf (stderr, "%s\n", pgm_err->message); pgm_error_free (pgm_err); pgm_err = NULL; } if (PGM_IO_STATUS_ERROR == status) break; } } while (!is_terminated); puts ("Message loop terminated, cleaning up."); /* cleanup */ #ifndef _WIN32 close (terminate_pipe[0]); close (terminate_pipe[1]); #else WSACloseEvent (recvEvent); WSACloseEvent (pendingEvent); CloseHandle (terminate_event); #endif /* !_WIN32 */ if (sock) { puts ("Destroying PGM socket."); pgm_close (sock, TRUE); sock = NULL; } puts ("PGM engine shutdown."); pgm_shutdown (); puts ("finished."); return EXIT_SUCCESS; }
static ErlDrvSSizeT call(ErlDrvData edd, unsigned int cmd, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, unsigned int *flags) { dnssd_drv_t* dd = (dnssd_drv_t*) edd; int version, out_len, index, rindex, local_only; DNSServiceErrorType err; char* out_atom_text; ei_term arg, name, type, domain, txt, host, hostport; char *name_tmp, *type_tmp, *domain_tmp, *txt_tmp, *host_tmp; /* don't allow reuse */ if (dd->sd_ref) return -1; index = 0; dd->sd_ref = NULL; ei_decode_version(buf, &index, &version); ei_decode_ei_term(buf, &index, &arg); if (cmd == DNSSD_CMD_ENUM) { if (arg.ei_type == ERL_ATOM_EXT) { if (strncmp(arg.value.atom_name, "browse", 6) == 0) { // init for enum browse err = DNSServiceEnumerateDomains(&dd->sd_ref, kDNSServiceFlagsBrowseDomains, kDNSServiceInterfaceIndexAny, (DNSServiceDomainEnumReply) EnumReply, dd); } else if (strncmp(arg.value.atom_name,"reg", 3) == 0) { // init for enum reg err = DNSServiceEnumerateDomains(&dd->sd_ref, kDNSServiceFlagsRegistrationDomains, kDNSServiceInterfaceIndexAny, (DNSServiceDomainEnumReply) EnumReply, dd); } else { goto badarg; } } else { goto badarg; } } else if (cmd == DNSSD_CMD_BROWSE) { if (!arg.ei_type == ERL_TUPLE || arg.arity != 2) goto badarg; /* decode type */ ei_decode_ei_term(buf, &index, &type); if (type.ei_type != ERL_BINARY_EXT) goto badarg; index += 5; // skip tag + 4 byte size type_tmp = (char*)driver_alloc(type.size + 1); memset(type_tmp, 0, type.size + 1); memcpy(type_tmp, buf + index, type.size); index += type.size; /* decode domain */ ei_decode_ei_term(buf, &index, &domain); if (domain.ei_type != ERL_BINARY_EXT) { driver_free(type_tmp); goto badarg; } index += 5; // skip tag + 4 byte size domain_tmp = (char *) driver_alloc(domain.size + 1); memset(domain_tmp, 0, domain.size + 1); memcpy(domain_tmp, buf + index, domain.size); err = DNSServiceBrowse(&dd->sd_ref, 0, // Flags kDNSServiceInterfaceIndexAny, type_tmp, domain_tmp, (DNSServiceBrowseReply) BrowseReply, dd); driver_free(type_tmp); driver_free(domain_tmp); } else if (cmd == DNSSD_CMD_RESOLVE) { if (!arg.ei_type == ERL_TUPLE || arg.arity != 3) goto badarg; /* decode name */ ei_decode_ei_term(buf, &index, &name); if (name.ei_type != ERL_BINARY_EXT) goto badarg; index += 5; // skip tag + 4 byte size name_tmp = (char *) driver_alloc(name.size + 1); memset(name_tmp, 0, name.size + 1); memcpy(name_tmp, buf + index, name.size); index += name.size; /* decode type */ ei_decode_ei_term(buf, &index, &type); if (type.ei_type != ERL_BINARY_EXT) { driver_free(name_tmp); goto badarg; } index += 5; // skip tag + 4 byte size type_tmp = (char *) driver_alloc(type.size + 1); memset(type_tmp, 0, type.size + 1); memcpy(type_tmp, buf + index, type.size); index += type.size; /* decode domain */ ei_decode_ei_term(buf, &index, &domain); if (domain.ei_type != ERL_BINARY_EXT) { driver_free(name_tmp); driver_free(type_tmp); goto badarg; } index += 5; // skip tag + 4 byte size domain_tmp = (char *) driver_alloc(domain.size + 1); memset(domain_tmp, 0, domain.size + 1); memcpy(domain_tmp, buf + index, domain.size); /* start op */ err = DNSServiceResolve(&dd->sd_ref, 0, // Flags kDNSServiceInterfaceIndexAny, name_tmp, type_tmp, domain_tmp, (DNSServiceResolveReply) ResolveReply, dd); driver_free(name_tmp); driver_free(type_tmp); driver_free(domain_tmp); } else if (cmd == DNSSD_CMD_REGISTER) { if (!arg.ei_type == ERL_TUPLE || arg.arity != 6) goto badarg; /* decode name */ ei_decode_ei_term(buf, &index, &name); if (name.ei_type != ERL_BINARY_EXT) goto badarg; index += 5; // skip tag + 4 byte size name_tmp = (char *) driver_alloc(name.size + 1); memset(name_tmp, 0, name.size + 1); memcpy(name_tmp, buf + index, name.size); index += name.size; /* decode type */ ei_decode_ei_term(buf, &index, &type); if (type.ei_type != ERL_BINARY_EXT) { driver_free(name_tmp); goto badarg; } index += 5; // skip tag + 4 byte size type_tmp = (char *) driver_alloc(type.size + 1); memset(type_tmp, 0, type.size + 1); memcpy(type_tmp, buf + index, type.size); index += type.size; /* decode domain */ ei_decode_ei_term(buf, &index, &domain); if (domain.ei_type != ERL_BINARY_EXT) { driver_free(name_tmp); driver_free(type_tmp); goto badarg; } index += 5; // skip tag + 4 byte size domain_tmp = (char *) driver_alloc(domain.size + 1); memset(domain_tmp, 0, domain.size + 1); memcpy(domain_tmp, buf + index, domain.size); index += domain.size; /* decode host */ ei_decode_ei_term(buf, &index, &host); if (host.ei_type != ERL_BINARY_EXT) { driver_free(name_tmp); driver_free(type_tmp); driver_free(domain_tmp); goto badarg; } index += 5; // skip tag + 4 byte size host_tmp = (char *) driver_alloc(host.size + 1); memset(host_tmp, 0, host.size + 1); memcpy(host_tmp, buf + index, host.size); index += host.size; /* decode port */ ei_decode_ei_term(buf, &index, &hostport); if (hostport.ei_type != ERL_INTEGER_EXT && hostport.ei_type != ERL_SMALL_INTEGER_EXT) { driver_free(name_tmp); driver_free(type_tmp); driver_free(domain_tmp); driver_free(host_tmp); goto badarg; } /* decode txt */ ei_decode_ei_term(buf, &index, &txt); if (txt.ei_type != ERL_BINARY_EXT) { driver_free(name_tmp); driver_free(type_tmp); driver_free(domain_tmp); driver_free(host_tmp); goto badarg; } index += 5; // skip tag + 4 byte size txt_tmp = (char *) driver_alloc(txt.size + 1); memset(txt_tmp, 0, txt.size + 1); memcpy(txt_tmp, buf + index, txt.size); local_only = (0 == strcmp("localhost", host_tmp)); err = DNSServiceRegister(&dd->sd_ref, 0, // Flags local_only ? -1 : 0, // Interface: local / any name_tmp, type_tmp, local_only ? "local" : domain_tmp, host_tmp, htons(hostport.value.i_val), txt.size, txt_tmp, (DNSServiceRegisterReply) RegisterReply, dd); driver_free(name_tmp); driver_free(type_tmp); driver_free(domain_tmp); driver_free(host_tmp); driver_free(txt_tmp); } else { goto badarg; } rindex = 0; out_len = 0; ei_encode_version(NULL, &out_len); if (err == kDNSServiceErr_NoError) { #ifdef __WIN32__ dd->event = WSACreateEvent(); WSAEventSelect(DNSServiceRefSockFD(dd->sd_ref), dd->event, FD_READ); driver_select(dd->erl_port, dd->event, ERL_DRV_READ, 1); #else driver_select(dd->erl_port, (ErlDrvEvent)(size_t) DNSServiceRefSockFD(dd->sd_ref), ERL_DRV_READ, 1); #endif out_atom_text = "ok"; ei_encode_atom(NULL, &out_len, out_atom_text); if(rlen < out_len) { *rbuf = driver_alloc(out_len); rlen = out_len; } ei_encode_version(*rbuf, &rindex); ei_encode_atom(*rbuf, &rindex, out_atom_text); return out_len; } else { out_atom_text = "error"; ei_encode_tuple_header(NULL, &out_len, 2); ei_encode_atom(NULL, &out_len, out_atom_text); ei_encode_long(NULL, &out_len, 1337); if(rlen < out_len) { *rbuf = driver_alloc(out_len); rlen = out_len; } ei_encode_version(*rbuf, &rindex); ei_encode_tuple_header(*rbuf, &rindex, 2); ei_encode_atom(*rbuf, &rindex, out_atom_text); ei_encode_long(*rbuf, &rindex, (long) err); return out_len; } badarg: return -1; }