void threadIdaServer::OnExit(void) { // Called when the thread exits by termination or with Delete() // but not Kill()ed wxMutexGuiEnter(); wxLogDebug(wxT("Exiting")); wxMutexGuiLeave(); closesocket(ListenSocket); for(i = 0 ; i < TotalSockets ; i++) FreeSocketInformation(i); this->sendDoneEvent(wxT("Done"), THREAD_IDA_FINISHED_NOERROR); }
int HandleNetConn() { int iResult; DWORD i; DWORD Total; ULONG NonBlock; DWORD Flags, SendBytes, RecvBytes; iResult=init_socket(); if (!iResult) { // Prepare a socket to listen for connections if (bind(ListenSocket, (PSOCKADDR) &ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR) { printf("error in binding the port"); closesocket(ListenSocket); WSACleanup(); return ERR_SERVER_BIND_FAILED; } printf("Bind succeeded"); if (listen(ListenSocket, MAX)) { printf("error in Listening"); closesocket(ListenSocket); WSACleanup(); return ERR_SERVER_LISTEN_FAILED; } printf("\n\nServer Listening\n"); // Change the socket mode on the listening socket from blocking to // non-block so the application will not block waiting for requests NonBlock = 1; if (ioctlsocket(ListenSocket, FIONBIO, &NonBlock) == SOCKET_ERROR) { printf("ioctlsocket() failed with error\n"); return ERR_IOCTLSOCKET_FAILED; } while(TRUE) { // Prepare the Read and Write socket sets for network I/O notification FD_ZERO(&ReadSet); FD_ZERO(&WriteSet); // Always look for connection attempts FD_SET(ListenSocket, &ReadSet); // Set Read and Write notification for each socket based on the // current state the buffer. If there is data remaining in the // buffer then set the Write set otherwise the Read set for (i = 0; i < TotalSockets; i++) { FD_SET(SocketArray[i]->Socket, &ReadSet); } if ((Total = select(0, &ReadSet, &WriteSet, NULL, NULL)) == SOCKET_ERROR) { printf("select() returned with error\n"); return 1; } else printf("select() is OK!\n"); // Check for arriving connections on the listening socket. if (FD_ISSET(ListenSocket, &ReadSet)) { Total--; if ((AcceptSocket = accept(ListenSocket, NULL, NULL)) != INVALID_SOCKET) { // Set the accepted socket to non-blocking mode so the server will // not get caught in a blocked condition on WSASends NonBlock = 1; if (ioctlsocket(AcceptSocket, FIONBIO, &NonBlock) == SOCKET_ERROR) { printf("ioctlsocket(FIONBIO) failed with error\n"); return 1; } else printf("ioctlsocket(FIONBIO) is OK!\n"); if (CreateSocketInformation(AcceptSocket) == FALSE) { printf("CreateSocketInformation(AcceptSocket) failed!\n"); return 1; } else printf("CreateSocketInformation() is OK!\n"); } else { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("accept() failed with error\n"); return 1; } else printf("accept() is fine!\n"); } } // Check each socket for Read notification until the number // of sockets in Total is satisfied for (i = 0; Total > 0 && i < TotalSockets; i++) { LPSOCKET_INFORMATION SocketInfo = SocketArray[i]; // If the ReadSet is marked for this socket then this means data // is available to be read on the socket if (FD_ISSET(SocketInfo->Socket, &ReadSet)) { Total--; SocketInfo->DataBuf.buf = SocketInfo->Buffer; SocketInfo->DataBuf.len = DATA_BUFSIZE; Flags = 0; if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes, &Flags, NULL, NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("WSARecv() failed with error\n"); FreeSocketInformation(i); } else printf("WSARecv() is OK!\n"); continue; } else { SocketInfo->BytesRECV = RecvBytes; // If zero bytes are received, this indicates the peer closed the connection. if (RecvBytes == 0) { FreeSocketInformation(i); continue; } } } } } } return ERR_SUCCESS; }
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { SOCKET Accept; LPSOCKET_INFORMATION SocketInfo; DWORD RecvBytes, SendBytes; DWORD Flags; if (uMsg == WM_SOCKET) { if (WSAGETSELECTERROR(lParam)) { printf("Socket failed with error %d\n", WSAGETSELECTERROR(lParam)); FreeSocketInformation(wParam); } else { switch(WSAGETSELECTEVENT(lParam)) { case FD_ACCEPT: if ((Accept = accept(wParam, NULL, NULL)) == INVALID_SOCKET) { printf("accept() failed with error %d\n", WSAGetLastError()); break; } // Create a socket information structure to associate with the // socket for processing I/O. CreateSocketInformation(Accept); printf("Socket number %d connected\n", Accept); WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE); break; case FD_READ: SocketInfo = GetSocketInformation(wParam); // Read data only if the receive buffer is empty. if (SocketInfo->BytesRECV != 0) { SocketInfo->RecvPosted = TRUE; return 0; } else { SocketInfo->DataBuf.buf = SocketInfo->Buffer; SocketInfo->DataBuf.len = DATA_BUFSIZE; Flags = 0; if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes, &Flags, NULL, NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); FreeSocketInformation(wParam); return 0; } } else // No error so update the byte count { SocketInfo->BytesRECV = RecvBytes; } } // DO NOT BREAK HERE SINCE WE GOT A SUCCESSFUL RECV. Go ahead // and begin writing data to the client. case FD_WRITE: SocketInfo = GetSocketInformation(wParam); if (SocketInfo->BytesRECV > SocketInfo->BytesSEND) { SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND; SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND; if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0, NULL, NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("WSASend() failed with error %d\n", WSAGetLastError()); FreeSocketInformation(wParam); return 0; } } else // No error so update the byte count { SocketInfo->BytesSEND += SendBytes; } } if (SocketInfo->BytesSEND == SocketInfo->BytesRECV) { SocketInfo->BytesSEND = 0; SocketInfo->BytesRECV = 0; // If a RECV occurred during our SENDs then we need to post an FD_READ // notification on the socket. if (SocketInfo->RecvPosted == TRUE) { SocketInfo->RecvPosted = FALSE; PostMessage(hwnd, WM_SOCKET, wParam, FD_READ); } } break; case FD_CLOSE: printf("Closing socket %d\n", wParam); FreeSocketInformation(wParam); break; } } return 0; } return DefWindowProc(hwnd, uMsg, wParam, lParam); }
void *threadIdaServer::Entry() { #ifdef _WIN32 if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { wxString retString = wxString::Format(wxT("Error creating socket: %d"), WSAGetLastError()); this->sendDoneEvent(retString, THREAD_IDA_FINISHED_ERROR); return NULL; } #endif InternetAddr.sin_family = AF_INET; InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY); InternetAddr.sin_port = htons(port); if(bind(ListenSocket, (sockaddr *) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR) { wxMutexGuiEnter(); wxLogDebug(wxT("bind error: %d"), WSAGetLastError()); wxMutexGuiLeave(); return NULL; } if(listen(ListenSocket, MAX_IDA_BACKLOG)) { wxMutexGuiEnter(); wxLogDebug(wxT("listen error: %d"), WSAGetLastError()); wxMutexGuiLeave(); return NULL; } NonBlock = 1; if (ioctlsocket(ListenSocket, FIONBIO, &NonBlock) == SOCKET_ERROR) { wxMutexGuiEnter(); wxLogDebug(wxT("Could not set non-blocking mode: %d"), WSAGetLastError()); wxMutexGuiLeave(); return NULL; } // Set the timeout value tv.tv_sec = 1; tv.tv_usec = 0; wxLogDebug(wxT("IDA Server started")); while(1) { if (this->TestDestroy() == true) return NULL; FD_ZERO(&ReadSet); FD_ZERO(&WriteSet); FD_SET(ListenSocket, &ReadSet); // Get the items from the list m_mutex.Lock(); DWORD numItems = commandList.size(); vector<wxString *> commandsToSend; for (i = 0 ; i < numItems ; i++) { commandsToSend.push_back(commandList.back()); commandList.pop_back(); } m_mutex.Unlock(); for(i = 0 ; i < TotalSockets ; i++) { // If we have items to transmit, send them, otherwise check for data to read if (commandsToSend.size() > 0) FD_SET(SocketArray[i]->Socket, &WriteSet); else FD_SET(SocketArray[i]->Socket, &ReadSet); } if ((Total = select(0, &ReadSet, &WriteSet, NULL, &tv)) == SOCKET_ERROR) { wxMutexGuiEnter(); wxLogDebug(wxT("Select error: %d"), WSAGetLastError()); wxMutexGuiLeave(); return NULL; } if(FD_ISSET(ListenSocket, &ReadSet)) { Total--; if((AcceptSocket = accept(ListenSocket, NULL, NULL)) != INVALID_SOCKET) { wxMutexGuiEnter(); wxLogDebug(wxT("Accepted a connection")); wxMutexGuiLeave(); NonBlock = 1; if(ioctlsocket(AcceptSocket, FIONBIO, &NonBlock) == SOCKET_ERROR) { wxMutexGuiEnter(); wxLogDebug(wxT("Error setting socket to non-blocked: %d"), WSAGetLastError()); wxMutexGuiLeave(); return NULL; } if(CreateSocketInformation(AcceptSocket) == FALSE) { wxMutexGuiEnter(); wxLogDebug(wxT("CreateSocketInformation error: %d"), WSAGetLastError()); wxMutexGuiLeave(); } // All is ok if we get here. } else { if (WSAGetLastError() != WSAEWOULDBLOCK) { wxMutexGuiEnter(); wxLogDebug(wxT("Error with accept: %d"), WSAGetLastError()); wxMutexGuiLeave(); } } } // Check the sockets for information for (i = 0; Total > 0 && i < TotalSockets;i++) { LPSOCKET_INFORMATION SocketInfo = SocketArray[i]; if(FD_ISSET(SocketInfo->Socket, &ReadSet)) { Total--; SocketInfo->DataBuf.buf = SocketInfo->Buffer; SocketInfo->DataBuf.len = MAX_IDA_SERVER_MSG_SIZE; Flags = 0; // The SocketInfo->DataBuf WSABUF structure should limit the size of received data here // according to MSDN http://msdn.microsoft.com/en-us/library/ms741688%28VS.85%29.aspx #ifdef _WIN32 if(WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes, &Flags, NULL, NULL) == SOCKET_ERROR) { if(WSAGetLastError() != WSAEWOULDBLOCK) { wxMutexGuiEnter(); wxLogDebug(wxT("Error with recv: %d"), WSAGetLastError()); wxMutexGuiLeave(); FreeSocketInformation(i); continue; } } #else defined _GNUC if (false) { // This is a stub for compilation } #endif else { SocketInfo->BytesRECV = RecvBytes; // If zero bytes are received this indicates the peer closed the connection. if (RecvBytes == 0) { wxMutexGuiEnter(); wxLogDebug(wxT("Socket disconnect")); wxMutexGuiLeave(); FreeSocketInformation(i); continue; } size_t len = strlen(SocketInfo->Buffer); // Trim off the carriage return if (len < MAX_IDA_SERVER_MSG_SIZE && len > 0 && SocketInfo->Buffer[len-1] == '\n') SocketInfo->Buffer[len-1] = 0; // Process the buffer here this->sendRecvEvent(new wxString(SocketInfo->Buffer, RecvBytes)); // Clear the buffer as we're done with it memset(SocketInfo->Buffer, 0, sizeof(SocketInfo->Buffer)); } } // End read check // If the write set is marked then buffers are ready for more data if(FD_ISSET(SocketInfo->Socket, &WriteSet)) { Total--; if (commandsToSend.size() > 0) { wxString *cmd = commandsToSend.back(); commandsToSend.pop_back(); // Convert to a C string char *cmd_c = (char *) cmd->mb_str(wxConvUTF8); size_t len = strlen(cmd_c); // Make sure we only send the proper buffer size len = (MAX_IDA_SERVER_MSG_SIZE < len) ? MAX_IDA_SERVER_MSG_SIZE : len; memcpy(SocketInfo->Buffer, cmd_c, len); // We're done with the cmd string now, so free it delete cmd; cmd = NULL; SocketInfo->DataBuf.buf = SocketInfo->Buffer; SocketInfo->DataBuf.len = len; } else { wxMutexGuiEnter(); wxLogDebug(wxT("Send set with no data available! ERROR")); wxMutexGuiLeave(); } if(WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0, NULL, NULL) == SOCKET_ERROR) { if(WSAGetLastError() != WSAEWOULDBLOCK) { wxMutexGuiEnter(); wxLogDebug(wxT("WSA Send error")); wxMutexGuiLeave(); FreeSocketInformation(i); } else { wxMutexGuiEnter(); wxLogDebug(wxT("WSASend() ok")); wxMutexGuiLeave(); } continue; } else { SocketInfo->BytesSEND += SendBytes; if(SocketInfo->BytesSEND == SocketInfo->BytesRECV) { SocketInfo->BytesSEND = 0; SocketInfo->BytesRECV = 0; } } // End Send } // End Write check } // End socket for loop } // End while loop return NULL; }
void main(void) { SOCKET Listen; SOCKET Accept; SOCKADDR_IN InternetAddr; DWORD Event; WSANETWORKEVENTS NetworkEvents; WSADATA wsaData; DWORD Ret; DWORD Flags; DWORD RecvBytes; DWORD SendBytes; if ((Ret = WSAStartup(0x0202, &wsaData)) != 0) { printf("WSAStartup() failed with error %d\n", Ret); return; } if ((Listen = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { printf("socket() failed with error %d\n", WSAGetLastError()); return; } CreateSocketInformation(Listen); if (WSAEventSelect(Listen, EventArray[EventTotal - 1], FD_ACCEPT | FD_CLOSE) == SOCKET_ERROR) { printf("WSAEventSelect() failed with error %d\n", WSAGetLastError()); return; } InternetAddr.sin_family = AF_INET; InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY); InternetAddr.sin_port = htons(PORT); if (bind(Listen, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR) { printf("bind() failed with error %d\n", WSAGetLastError()); return; } if (listen(Listen, 5)) { printf("listen() failed with error %d\n", WSAGetLastError()); return; } while (TRUE) { // Wait for one of the sockets to receive I/O notification and if ((Event = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED) { printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError()); return; } if (WSAEnumNetworkEvents(SocketArray[Event - WSA_WAIT_EVENT_0]->Socket, EventArray[Event - WSA_WAIT_EVENT_0], &NetworkEvents) == SOCKET_ERROR) { printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError()); return; } if (NetworkEvents.lNetworkEvents & FD_ACCEPT) { if (NetworkEvents.iErrorCode[FD_ACCEPT_BIT] != 0) { printf("FD_ACCEPT failed with error %d\n", NetworkEvents.iErrorCode[FD_ACCEPT_BIT]); break; } if ((Accept = accept(SocketArray[Event - WSA_WAIT_EVENT_0]->Socket, NULL, NULL)) == INVALID_SOCKET) { printf("accept() failed with error %d\n", WSAGetLastError()); break; } if (EventTotal > WSA_MAXIMUM_WAIT_EVENTS) { printf("Too many connections - closing socket.\n"); closesocket(Accept); break; } CreateSocketInformation(Accept); if (WSAEventSelect(Accept, EventArray[EventTotal - 1], FD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR) { printf("WSAEventSelect() failed with error %d\n", WSAGetLastError()); return; } printf("Socket %d connected\n", Accept); } // Try to read and write data to and from the data buffer if read and write events occur. if (NetworkEvents.lNetworkEvents & FD_READ || NetworkEvents.lNetworkEvents & FD_WRITE) { if (NetworkEvents.lNetworkEvents & FD_READ && NetworkEvents.iErrorCode[FD_READ_BIT] != 0) { printf("FD_READ failed with error %d\n", NetworkEvents.iErrorCode[FD_READ_BIT]); break; } if (NetworkEvents.lNetworkEvents & FD_WRITE && NetworkEvents.iErrorCode[FD_WRITE_BIT] != 0) { printf("FD_WRITE failed with error %d\n", NetworkEvents.iErrorCode[FD_WRITE_BIT]); break; } LPSOCKET_INFORMATION SocketInfo = SocketArray[Event - WSA_WAIT_EVENT_0]; // Read data only if the receive buffer is empty. if (SocketInfo->BytesRECV == 0) { SocketInfo->DataBuf.buf = SocketInfo->Buffer; SocketInfo->DataBuf.len = DATA_BUFSIZE; Flags = 0; if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes, &Flags, NULL, NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); FreeSocketInformation(Event - WSA_WAIT_EVENT_0); return; } } else { SocketInfo->BytesRECV = RecvBytes; } } // Write buffer data if it is available. if (SocketInfo->BytesRECV > SocketInfo->BytesSEND) { SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND; SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND; if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0, NULL, NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("WSASend() failed with error %d\n", WSAGetLastError()); FreeSocketInformation(Event - WSA_WAIT_EVENT_0); return; } // A WSAEWOULDBLOCK error has occured. An FD_WRITE event will be posted // when more buffer space becomes available } else { SocketInfo->BytesSEND += SendBytes; if (SocketInfo->BytesSEND == SocketInfo->BytesRECV) { SocketInfo->BytesSEND = 0; SocketInfo->BytesRECV = 0; } } } } if (NetworkEvents.lNetworkEvents & FD_CLOSE) { if (NetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0) { printf("FD_CLOSE failed with error %d\n", NetworkEvents.iErrorCode[FD_CLOSE_BIT]); break; } printf("Closing socket information %d\n", SocketArray[Event - WSA_WAIT_EVENT_0]->Socket); FreeSocketInformation(Event - WSA_WAIT_EVENT_0); } } return; }
void main(void) { SOCKET ListenSocket; SOCKET AcceptSocket; SOCKADDR_IN InternetAddr; WSADATA wsaData; INT Ret; FD_SET WriteSet; FD_SET ReadSet; DWORD i; DWORD Total; ULONG NonBlock; DWORD Flags; DWORD SendBytes; DWORD RecvBytes; if ((Ret = WSAStartup(0x0202,&wsaData)) != 0) { printf("WSAStartup() failed with error %d\n", Ret); WSACleanup(); return; } // Prepare a socket to listen for connections. if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("WSASocket() failed with error %d\n", WSAGetLastError()); return; } InternetAddr.sin_family = AF_INET; InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY); InternetAddr.sin_port = htons(PORT); if (bind(ListenSocket, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR) { printf("bind() failed with error %d\n", WSAGetLastError()); return; } if (listen(ListenSocket, 5)) { printf("listen() failed with error %d\n", WSAGetLastError()); return; } // Change the socket mode on the listening socket from blocking to // non-block so the application will not block waiting for requests. NonBlock = 1; if (ioctlsocket(ListenSocket, FIONBIO, &NonBlock) == SOCKET_ERROR) { printf("ioctlsocket() failed with error %d\n", WSAGetLastError()); return; } while(TRUE) { // Prepare the Read and Write socket sets for network I/O notification. FD_ZERO(&ReadSet); FD_ZERO(&WriteSet); // Always look for connection attempts. FD_SET(ListenSocket, &ReadSet); // Set Read and Write notification for each socket based on the // current state the buffer. If there is data remaining in the // buffer then set the Write set otherwise the Read set. for (i = 0; i < TotalSockets; i++) if (SocketArray[i]->BytesRECV > SocketArray[i]->BytesSEND) FD_SET(SocketArray[i]->Socket, &WriteSet); else FD_SET(SocketArray[i]->Socket, &ReadSet); if ((Total = select(0, &ReadSet, &WriteSet, NULL, NULL)) == SOCKET_ERROR) { printf("select() returned with error %d\n", WSAGetLastError()); return; } // Check for arriving connections on the listening socket. if (FD_ISSET(ListenSocket, &ReadSet)) { Total--; if ((AcceptSocket = accept(ListenSocket, NULL, NULL)) != INVALID_SOCKET) { // Set the accepted socket to non-blocking mode so the server will // not get caught in a blocked condition on WSASends NonBlock = 1; if (ioctlsocket(AcceptSocket, FIONBIO, &NonBlock) == SOCKET_ERROR) { printf("ioctlsocket() failed with error %d\n", WSAGetLastError()); return; } if (CreateSocketInformation(AcceptSocket) == FALSE) return; } else { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("accept() failed with error %d\n", WSAGetLastError()); return; } } } // Check each socket for Read and Write notification until the number // of sockets in Total is satisfied. for (i = 0; Total > 0 && i < TotalSockets; i++) { LPSOCKET_INFORMATION SocketInfo = SocketArray[i]; // If the ReadSet is marked for this socket then this means data // is available to be read on the socket. if (FD_ISSET(SocketInfo->Socket, &ReadSet)) { Total--; SocketInfo->DataBuf.buf = SocketInfo->Buffer; SocketInfo->DataBuf.len = DATA_BUFSIZE; Flags = 0; if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes, &Flags, NULL, NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); FreeSocketInformation(i); } continue; } else { SocketInfo->BytesRECV = RecvBytes; // If zero bytes are received, this indicates the peer closed the // connection. if (RecvBytes == 0) { FreeSocketInformation(i); continue; } } } // If the WriteSet is marked on this socket then this means the internal // data buffers are available for more data. if (FD_ISSET(SocketInfo->Socket, &WriteSet)) { Total--; SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND; SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND; if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0, NULL, NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("WSASend() failed with error %d\n", WSAGetLastError()); FreeSocketInformation(i); } continue; } else { SocketInfo->BytesSEND += SendBytes; if (SocketInfo->BytesSEND == SocketInfo->BytesRECV) { SocketInfo->BytesSEND = 0; SocketInfo->BytesRECV = 0; } } } } } }
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { SOCKET sd; LPSOCKET_INFORMATION SocketInfo; DWORD RecvBytes, SendBytes; DWORD Flags; switch (Message) { case WM_CREATE: createElements(hwnd); break; case WM_SOCKET: if (WSAGETSELECTERROR(lParam)) { printf("Socket failed with error %d\n", WSAGETSELECTERROR(lParam)); FreeSocketInformation(wParam); } else { switch (WSAGETSELECTEVENT(lParam)) { case FD_CONNECT: break; case FD_ACCEPT: if ((sd = accept(wParam, NULL, NULL)) == INVALID_SOCKET) { break; } CreateSocketInformation(sd); WSAAsyncSelect(sd, hwnd, WM_SOCKET, FD_READ | FD_CLOSE); break; case FD_READ: SocketInfo = GetSocketInformation(wParam); // Read data only if the receive buffer is empty. if (SocketInfo->BytesRECV != 0) { SocketInfo->RecvPosted = TRUE; return 0; } else { SocketInfo->DataBuf.buf = SocketInfo->Buffer; SocketInfo->DataBuf.len = DATA_BUFSIZE; Flags = 0; if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes, &Flags, NULL, NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); FreeSocketInformation(wParam); return 0; } } else { // No error so update the byte count SocketInfo->BytesRECV = RecvBytes; } break; } break; case FD_WRITE: SocketInfo = GetSocketInformation(wParam); if (SocketInfo->BytesRECV > SocketInfo->BytesSEND) { SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND; SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND; if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0, NULL, NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("WSASend() failed with error %d\n", WSAGetLastError()); FreeSocketInformation(wParam); return 0; } } else { // No error so update the byte count SocketInfo->BytesSEND += SendBytes; } } if (SocketInfo->BytesSEND == SocketInfo->BytesRECV) { SocketInfo->BytesSEND = 0; SocketInfo->BytesRECV = 0; // If a RECV occurred during our SENDs then we need to post an FD_READ // notification on the socket. if (SocketInfo->RecvPosted == TRUE) { SocketInfo->RecvPosted = FALSE; PostMessage(hwnd, WM_SOCKET, wParam, FD_READ); } } break; case FD_CLOSE: printf("Closing socket %d\n", wParam); FreeSocketInformation(wParam); break; } } break; case WM_DESTROY: // Terminate program PostQuitMessage(0); break; default: return DefWindowProc(hwnd, Message, wParam, lParam); } return 0; }