/*------------------------------------------------------------------------------------------------------------------------------------- FUNCTION: ServerRoutine INTERFACE: void CALLBACK ServerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD InFlags) RETURNS: void NOTES: Gets called when there is an I/O request on the socket. Checks for control information and EOF on the socket, and normal packet data. Once data is received, it is written to a file for analysis --------------------------------------------------------------------------------------------------------------------------------------*/ void CALLBACK ServerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD InFlags) { DWORD RecvBytes = 0, Index; DWORD Flags = 0; WSAEVENT EventArray[1] = { 0 }; WSAEVENT acceptEvent; // Reference the WSAOVERLAPPED structure as a SOCKET_INFORMATION structure LPSOCKET_INFORMATION SI = (LPSOCKET_INFORMATION)Overlapped; initSockInfo(SI, SI->Buffer, DATA_BUFSIZE); if (Error != 0) { int i = WSAGetLastError(); formatMessage("I/O operation failed"); } if (checkControlFormat(SI)) { formatMessage("Initial Packet Received"); sscanf(SI->DataBuf.buf, "%*s %d %d", &fileInfo->sizeOfPackets, &fileInfo->numberOfPackets); QueryPerformanceFrequency(&fileInfo->frequency); QueryPerformanceCounter(&fileInfo->startTimeStamp); } if (checkEOFFormat(SI)) { formatMessage("Final Packet Received"); exitThread = true; QueryPerformanceCounter(&fileInfo->endTimeStamp); fileInfo->protocol = protocol; return; } initSockInfo(SI, SI->Buffer, fileInfo->sizeOfPackets); //UDP if (protocol == UDP) { if ((acceptEvent = WSACreateEvent()) == WSA_INVALID_EVENT) { formatMessage("WSACreateEvent() failed"); ExitThread(1); } Index = WSAWaitForMultipleEvents(1, EventArray, FALSE, 2000, TRUE); if (Index == WSA_WAIT_TIMEOUT) { formatMessage("Timeout in UDP Server"); exitThread = true; return; } receiveUDP(SI, serverUDP, BytesTransferred, Flags); } if (protocol == TCP) receiveTCP(SI, RecvBytes, Flags); //Gather data logCommStats(SI, fileInfo, BytesTransferred); fwrite(SI->DataBuf.buf, sizeof(char), SI->DataBuf.len, serverFP); }
/** * dealClientThread - 处理一个客户端 * * 处理流程:向DST进行连接-> 利用select对DST与CLI之间的数据进行转发 * @lpParameter: 线程参数 * * * return * ==0: 成功 * !=0: 出错 */ unsigned int WINAPI dealClientThread(LPVOID lpParameter) { assert(lpParameter != NULL); THREAD_PARAM *param = (THREAD_PARAM*)lpParameter; SOCKET srvSock, cliSock = param->cliSock; SOCK_INFO cliSockInfo, srvSockInfo; int ret; if((ret = connDst(param->DstIP, param->DstPort, srvSock)) != 0) { printf("connect[%s:%d] failed with errCode[%d]\n", param->DstIP, param->DstPort, ret); return 1; } printf("Begin transdata between cliSock[%d] and srvSock[%d]\n", cliSock, srvSock); initSockInfo(cliSockInfo, cliSock, srvSockInfo, srvSock); ret = select2sock(cliSockInfo, srvSockInfo); if(NEED_FAST_CLOSE(ret)){ close2socket(cliSock, srvSock, true);/** fast close*/ ret = 0; } else close2socket(cliSock, srvSock, false);/** normal close*/ printf("End select2sock return sysError[%d] userError[%d]\n", GET_SYS_ERR(ret), GET_USER_ERR(ret)); return ret; }
/*------------------------------------------------------------------------------------------------------------------------------------- FUNCTION: UDPWorkerThread INTERFACE: DWORD WINAPI UDPWorkerThread(LPVOID lpParameter) RETURNS: DWORD NOTES: Waits on the socket until there is data receieved. Once data is deteceted on the socket, the completion routine is called to handle the I/O on the socket. --------------------------------------------------------------------------------------------------------------------------------------*/ DWORD WINAPI UDPWorkerThread(LPVOID lpParameter) { DWORD Flags = 0; LPSOCKET_INFORMATION SocketInfo; WSAEVENT EventArray[1]; DWORD Index; DWORD RecvBytes = 0; WSAEVENT UDPEvent; // Create a socket information structure to associate with the accepted socket. if ((SocketInfo = (LPSOCKET_INFORMATION)GlobalAlloc(GPTR, sizeof(SOCKET_INFORMATION))) == NULL) { formatMessage("GlobalAlloc() failed"); return FALSE; } if ((UDPEvent = WSACreateEvent()) == WSA_INVALID_EVENT) { formatMessage("WSACreateEvent() failed"); ExitThread(1); } // Save the accept event in the event array. EventArray[0] = UDPEvent; // Fill in the details of our accepted socket. SocketInfo->Socket = sd; initSockInfo(SocketInfo, SocketInfo->Buffer, DATA_BUFSIZE); receiveUDP(SocketInfo, serverUDP, RecvBytes, Flags); while (TRUE) { Index = WSAWaitForMultipleEvents(1, EventArray, FALSE, WSA_INFINITE, TRUE); if (Index == WSA_WAIT_FAILED) { formatMessage("WSAWaitForMultipleEvents failed"); return FALSE; } if (Index != WAIT_IO_COMPLETION) { // An accept() call event is ready - break the wait loop //break; } if (Index == WAIT_IO_COMPLETION && exitThread == true) { formatMessage("Server Terminating"); exitThread = false; closesocket(SocketInfo->Socket); logDataFile(fileInfo); free(fileInfo); fclose(serverFP); WSACleanup(); return TRUE; } } }
/*------------------------------------------------------------------------------------------------------------------------------------- FUNCTION: sendControlUDP INTERFACE: void sendControlUDP(LPSOCKET_INFORMATION SI, struct sockaddr_in server, char* message, int sizeOfPackets) RETURNS: void NOTES: Sends the control information to a UDP socket --------------------------------------------------------------------------------------------------------------------------------------*/ void sendControlUDP(LPSOCKET_INFORMATION SI, struct sockaddr_in server, char* message, int sizeOfPackets) { initSockInfo(SI, message, strlen(message)); //Send control data if (WSASendTo(SI->Socket, &(SI->DataBuf), 1, &SI->BytesSEND, 0, (struct sockaddr *)&server, sizeof(server), &(SI->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { formatMessage("Sending control information failed"); ExitThread(1); } } formatMessage("Sending Control Data to Server"); }
/*------------------------------------------------------------------------------------------------------------------------------------- FUNCTION: sendfileDataUDP INTERFACE: bool sendfileDataUDP(LPSOCKET_INFORMATION SI, sockaddr_in server, int packetSize) RETURNS: bool NOTES: Sends the file information to the UDP socket --------------------------------------------------------------------------------------------------------------------------------------*/ bool sendfileDataUDP(LPSOCKET_INFORMATION SI, sockaddr_in server, int packetSize) { size_t read = 0; char* fbuf = (char*)malloc(packetSize); initSockInfo(SI, "", packetSize); while ((read = fread(fbuf, sizeof(char), packetSize, clientFP)) > 0) { sendControlUDP(SI, server, fbuf, read); memset(fbuf, 0, packetSize); if (feof(clientFP)) break; } free(fbuf); return 0; }
/*------------------------------------------------------------------------------------------------------------------------------------- FUNCTION: sendDataTCP INTERFACE: void sendDataTCP(LPSOCKET_INFORMATION SI, char* message, int sizeOfPackets, int numberOfPackets) RETURNS: void NOTES: Sends the data information to a TCP socket --------------------------------------------------------------------------------------------------------------------------------------*/ void sendDataTCP(LPSOCKET_INFORMATION SI, char* message, int sizeOfPackets, int numberOfPackets) { initSockInfo(SI, message, sizeOfPackets); for (int i = 0; i < numberOfPackets; i++) { if (WSASend(SI->Socket, &(SI->DataBuf), 1, &SI->BytesSEND, 0, &(SI->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { formatMessage("Sending TCP data information failed"); ExitThread(1); } } formatMessage("Sending Data to Server"); } }
/** * dealClientThread - 处理一个客户端 * * 处理流程:向DST进行连接-> 利用select对DST与CLI之间的数据进行转发 * @lpParameter: 线程参数 * * * return * ==0: 成功 * !=0: 出错 */ int dealClient(SOCKET cliSock, SOCKET srvSock) { SOCK_INFO cliSockInfo, srvSockInfo; int ret; initSockInfo(cliSockInfo, cliSock, srvSockInfo, srvSock); ret = select2sock(cliSockInfo, srvSockInfo); if(NEED_FAST_CLOSE(ret)){ close2socket(cliSock, srvSock, true);/** fast close*/ ret = 0; } else close2socket(cliSock, srvSock, false);/** normal close*/ printf("End select2sock return sysError[%d] userError[%d]\n", GET_SYS_ERR(ret), GET_USER_ERR(ret)); return ret; }
/*------------------------------------------------------------------------------------------------------------------ -- FUNCTION: ServerRoutine -- DATE: 14/04/16 -- REVISIONS: (V1.0) -- DESIGNER: Martin Minkov -- PROGRAMMER: Martin Minkov -- INTERFACE: void CALLBACK ServerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD InFlags) -- -- -- RETURNS: VOID -- NOTES: The completion routine used for UDP receiving. Constantly pushes valid data received into the circ buff so it can be used to play audio later. ----------------------------------------------------------------------------------------------------------------------*/ void CALLBACK ServerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD InFlags) { DWORD RecvBytes = 0, Index; DWORD Flags = 0; WSAEVENT EventArray[1] = { 0 }; WSAEVENT acceptEvent; // Reference the WSAOVERLAPPED structure as a SOCKET_INFORMATION structure LPSOCKET_INFORMATION SOCKINFO = (LPSOCKET_INFORMATION)Overlapped; initSockInfo(SOCKINFO, SOCKINFO->Buffer, SOCKINFO->server); if (Error != 0) { qDebug() << "I/O operation failed with value" + Error; printf("%d", Error); fflush(stdout); GlobalFree(SOCKINFO); SetEvent(streamStop); return; } if ((acceptEvent = WSACreateEvent()) == WSA_INVALID_EVENT) { qDebug() <<"WSACreateEvent() failed"; GlobalFree(SOCKINFO); return; } Index = WSAWaitForMultipleEvents(1, EventArray, FALSE, 10000000, TRUE); if (Index == WSA_WAIT_TIMEOUT) { qDebug() <<"Timeout in UDP Server"; GlobalFree(SOCKINFO); return; } receiveUDP(SOCKINFO, streamServer, BytesTransferred, Flags); cData.push(SOCKINFO->Buffer, 60000); }