From ac83b1a898bda74ed68147bb3f97792588de92ba Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Sun, 24 Apr 2011 04:22:19 +0000 Subject: [PATCH] - attempt to fix socket bug where we incorrectly polled for data using ioctl / ioctlsocket. While we stilkl do some peeks, the bulk of the socket work is now done properly by simply doing recv and thus should prove more stable and reliable as well as perform better. --- .../glest_game/network/client_interface.cpp | 1 + .../glest_game/network/network_interface.cpp | 16 +- source/glest_game/network/network_manager.cpp | 2 +- source/glest_game/network/network_message.cpp | 193 +++++++++++++++--- source/glest_game/network/network_message.h | 4 +- .../include/platform/posix/socket.h | 2 +- .../sources/platform/posix/socket.cpp | 61 +++--- 7 files changed, 218 insertions(+), 61 deletions(-) diff --git a/source/glest_game/network/client_interface.cpp b/source/glest_game/network/client_interface.cpp index 461343f4..e6e174dc 100755 --- a/source/glest_game/network/client_interface.cpp +++ b/source/glest_game/network/client_interface.cpp @@ -660,6 +660,7 @@ void ClientInterface::waitUntilReady(Checksum* checksum) { // FOR TESTING ONLY - delay to see the client count up while waiting //sleep(5000); + //clientSocket->setBlock(true); //send ready message NetworkMessageReady networkMessageReady; sendMessage(&networkMessageReady); diff --git a/source/glest_game/network/network_interface.cpp b/source/glest_game/network/network_interface.cpp index 37f95067..4ef5a048 100644 --- a/source/glest_game/network/network_interface.cpp +++ b/source/glest_game/network/network_interface.cpp @@ -184,7 +184,7 @@ void FileTransferSocketThread::execute() char data[513]=""; memset(data, 0, 256); - clientSocket->receive(data,256); + clientSocket->receive(data,256, true); if(*data == SEND_FILE) { FileInfo file; @@ -209,7 +209,7 @@ void FileTransferSocketThread::execute() memcpy(data+1,&file,sizeof(file)); clientSocket->send(data,256); - clientSocket->receive(data,256); + clientSocket->receive(data,256, true); if(*data != ACK) { //transfer error } @@ -225,7 +225,7 @@ void FileTransferSocketThread::execute() //if(written!=pack) // ; //read error clientSocket->send(data,512); - clientSocket->receive(data,256); + clientSocket->receive(data,256, true); if(*data!=ACK) { //transfer error } @@ -238,7 +238,7 @@ void FileTransferSocketThread::execute() // ; //read error clientSocket->send(data,remain); - clientSocket->receive(data,256); + clientSocket->receive(data,256, true); if(*data!=ACK) { //transfer error } @@ -274,12 +274,12 @@ void FileTransferSocketThread::execute() memcpy(data+1,&file,sizeof(file)); clientSocket.send(data,256); - clientSocket.receive(data,256); + clientSocket.receive(data,256, true); if(*data!=ACK) { //transfer error } - clientSocket.receive(data,256); + clientSocket.receive(data,256,true); if(*data == SEND_FILE) { memcpy(&file, data+1, sizeof(file)); @@ -291,7 +291,7 @@ void FileTransferSocketThread::execute() while(packs--) { - clientSocket.receive(data,512); + clientSocket.receive(data,512,true); outFile.write(data, 512); if(outFile.bad()) @@ -305,7 +305,7 @@ void FileTransferSocketThread::execute() *data=ACK; clientSocket.send(data,256); } - clientSocket.receive(data,remain); + clientSocket.receive(data,remain,true); outFile.write(data, remain); if(outFile.bad()) diff --git a/source/glest_game/network/network_manager.cpp b/source/glest_game/network/network_manager.cpp index f73f3156..13f18718 100644 --- a/source/glest_game/network/network_manager.cpp +++ b/source/glest_game/network/network_manager.cpp @@ -109,7 +109,7 @@ ServerInterface* NetworkManager::getServerInterface(bool throwErrorOnNull) { } ClientInterface* NetworkManager::getClientInterface(bool throwErrorOnNull) { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] this->networkRole = %d gameNetworkInterface [%p]\n",__FILE__,__FUNCTION__,__LINE__,this->networkRole,gameNetworkInterface); + //if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] this->networkRole = %d gameNetworkInterface [%p]\n",__FILE__,__FUNCTION__,__LINE__,this->networkRole,gameNetworkInterface); if(throwErrorOnNull) { assert(gameNetworkInterface!=NULL); diff --git a/source/glest_game/network/network_message.cpp b/source/glest_game/network/network_message.cpp index d24b7547..ebda5413 100644 --- a/source/glest_game/network/network_message.cpp +++ b/source/glest_game/network/network_message.cpp @@ -37,6 +37,7 @@ namespace Glest{ namespace Game{ // class NetworkMessage // ===================================================== +/* bool NetworkMessage::peek(Socket* socket, void* data, int dataSize) { if(socket != NULL) { int ipeekdatalen = socket->getDataToRead(); @@ -60,8 +61,10 @@ bool NetworkMessage::peek(Socket* socket, void* data, int dataSize) { } return false; } +*/ -bool NetworkMessage::receive(Socket* socket, void* data, int dataSize) { +bool NetworkMessage::receive(Socket* socket, void* data, int dataSize, bool tryReceiveUntilDataSizeMet) { +/* if(socket != NULL) { int ipeekdatalen = socket->getDataToRead(); if(ipeekdatalen >= dataSize) { @@ -83,6 +86,25 @@ bool NetworkMessage::receive(Socket* socket, void* data, int dataSize) { } } return false; +*/ + + if(socket != NULL) { + int dataReceived = socket->receive(data, dataSize, tryReceiveUntilDataSizeMet); + if(dataReceived != dataSize) { + if(socket != NULL && socket->getSocketId() > 0) { + throw runtime_error("Error receiving NetworkMessage, dataReceived = " + intToStr(dataReceived) + ", dataSize = " + intToStr(dataSize)); + } + else { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] socket has been disconnected\n",__FILE__,__FUNCTION__,__LINE__); + } + } + else { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] dataSize = %d, dataReceived = %d\n",__FILE__,__FUNCTION__,__LINE__,dataSize,dataReceived); + return true; + } + } + return false; + } void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const { @@ -133,7 +155,7 @@ NetworkMessageIntro::NetworkMessageIntro(int32 sessionId,const string &versionSt } bool NetworkMessageIntro::receive(Socket* socket) { - bool result = NetworkMessage::receive(socket, &data, sizeof(data)); + bool result = NetworkMessage::receive(socket, &data, sizeof(data), true); data.name.nullTerminate(); data.versionString.nullTerminate(); data.language.nullTerminate(); @@ -164,7 +186,7 @@ NetworkMessagePing::NetworkMessagePing(int32 pingFrequency, int64 pingTime){ } bool NetworkMessagePing::receive(Socket* socket){ - bool result = NetworkMessage::receive(socket, &data, sizeof(data)); + bool result = NetworkMessage::receive(socket, &data, sizeof(data), true); pingReceivedLocalTime = time(NULL); return result; } @@ -189,7 +211,7 @@ NetworkMessageReady::NetworkMessageReady(int32 checksum) { } bool NetworkMessageReady::receive(Socket* socket){ - return NetworkMessage::receive(socket, &data, sizeof(data)); + return NetworkMessage::receive(socket, &data, sizeof(data), true); } void NetworkMessageReady::send(Socket* socket) const { @@ -314,7 +336,7 @@ vector > NetworkMessageLaunch::getFactionCRCList() const { } bool NetworkMessageLaunch::receive(Socket* socket) { - bool result = NetworkMessage::receive(socket, &data, sizeof(data)); + bool result = NetworkMessage::receive(socket, &data, sizeof(data), true); data.description.nullTerminate(); data.map.nullTerminate(); data.tileset.nullTerminate(); @@ -367,8 +389,9 @@ bool NetworkMessageCommandList::addCommand(const NetworkCommand* networkCommand) bool NetworkMessageCommandList::receive(Socket* socket) { // _peek_ type, commandCount & frame num first. if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - const double MAX_MSG_WAIT_SECONDS = 3; +/* + const double MAX_MSG_WAIT_SECONDS = 3; // Wait a max of x seconds for this message for(time_t elapsedWait = time(NULL); difftime(time(NULL),elapsedWait) <= MAX_MSG_WAIT_SECONDS;) { if (NetworkMessage::peek(socket, &data, commandListHeaderSize) == true) { @@ -416,6 +439,38 @@ bool NetworkMessageCommandList::receive(Socket* socket) { } } return result; +*/ + + bool result = NetworkMessage::receive(socket, &data.header, commandListHeaderSize, true); + if(result == true) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got header, messageType = %d, commandCount = %u, frameCount = %d\n",__FILE__,__FUNCTION__,__LINE__,data.header.messageType,data.header.commandCount,data.header.frameCount); + // read header + data.commandCount commands. + //int totalMsgSize = commandListHeaderSize + (sizeof(NetworkCommand) * data.header.commandCount); + + if(data.header.commandCount > 0) { + int totalMsgSize = (sizeof(NetworkCommand) * data.header.commandCount); + result = NetworkMessage::receive(socket, &data.commands, totalMsgSize, true); + if(result == true) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled == true) { + for(int idx = 0 ; idx < data.header.commandCount; ++idx) { + const NetworkCommand &cmd = data.commands[idx]; + + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] index = %d, received networkCommand [%s]\n", + __FILE__,__FUNCTION__,__LINE__,idx, cmd.toString().c_str()); + } + } + } + else { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR Failed to get command data, totalMsgSize = %d.\n",__FILE__,__FUNCTION__,__LINE__,totalMsgSize); + } + } + } + else { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR header not received as expected\n",__FILE__,__FUNCTION__,__LINE__); + SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] ERROR header not received as expected\n",__FILE__,__FUNCTION__,__LINE__); + } + return result; + } void NetworkMessageCommandList::send(Socket* socket) const { @@ -466,7 +521,7 @@ NetworkMessageText * NetworkMessageText::getCopy() const { } bool NetworkMessageText::receive(Socket* socket){ - bool result = NetworkMessage::receive(socket, &data, sizeof(data)); + bool result = NetworkMessage::receive(socket, &data, sizeof(data), true); data.text.nullTerminate(); data.targetLanguage.nullTerminate(); @@ -490,7 +545,7 @@ NetworkMessageQuit::NetworkMessageQuit(){ } bool NetworkMessageQuit::receive(Socket* socket){ - return NetworkMessage::receive(socket, &data, sizeof(data)); + return NetworkMessage::receive(socket, &data, sizeof(data),true); } void NetworkMessageQuit::send(Socket* socket) const{ @@ -618,6 +673,7 @@ string NetworkMessageSynchNetworkGameData::getTechCRCFileMismatchReport(vector 0) { // Here we loop possibly multiple times @@ -671,7 +727,7 @@ bool NetworkMessageSynchNetworkGameData::receive(Socket* socket) { } } - result = NetworkMessage::receive(socket, &data.detail.techCRCFileList[packetIndex], packetDetail1DataSize); + result = NetworkMessage::receive(socket, &data.detail.techCRCFileList[packetIndex], packetDetail1DataSize, true); if(result == true) { for(int i = 0; i < data.header.techCRCFileCount; ++i) { data.detail.techCRCFileList[i].nullTerminate(); @@ -684,13 +740,61 @@ bool NetworkMessageSynchNetworkGameData::receive(Socket* socket) { } } - result = NetworkMessage::receive(socket, &data.detail.techCRCFileCRCList[packetIndex], packetDetail2DataSize); + result = NetworkMessage::receive(socket, &data.detail.techCRCFileCRCList[packetIndex], packetDetail2DataSize, true); } } } if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] result = %d\n",__FILE__,__FUNCTION__,__LINE__,result); return result; + +*/ + + data.header.techCRCFileCount = 0; + bool result = NetworkMessage::receive(socket, &data, HeaderSize, true); + if(result == true && data.header.techCRCFileCount > 0) { + data.header.map.nullTerminate(); + data.header.tileset.nullTerminate(); + data.header.tech.nullTerminate(); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] messageType = %d, data.techCRCFileCount = %d\n",__FILE__,__FUNCTION__,__LINE__,data.header.messageType,data.header.techCRCFileCount); + + + + // Here we loop possibly multiple times + int packetLoopCount = 1; + if(data.header.techCRCFileCount > NetworkMessageSynchNetworkGameData::maxFileCRCPacketCount) { + packetLoopCount = (data.header.techCRCFileCount / NetworkMessageSynchNetworkGameData::maxFileCRCPacketCount); + if(data.header.techCRCFileCount % NetworkMessageSynchNetworkGameData::maxFileCRCPacketCount > 0) { + packetLoopCount++; + } + } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] packetLoopCount = %d\n",__FILE__,__FUNCTION__,__LINE__,packetLoopCount); + + for(int iPacketLoop = 0; result == true && iPacketLoop < packetLoopCount; ++iPacketLoop) { + + int packetIndex = iPacketLoop * NetworkMessageSynchNetworkGameData::maxFileCRCPacketCount; + int maxFileCountPerPacket = maxFileCRCPacketCount; + int packetFileCount = min(maxFileCountPerPacket,data.header.techCRCFileCount - packetIndex); + int packetDetail1DataSize = (DetailSize1 * packetFileCount); + int packetDetail2DataSize = (DetailSize2 * packetFileCount); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] iPacketLoop = %d, packetIndex = %d, maxFileCountPerPacket = %d, packetFileCount = %d, packetDetail1DataSize = %d, packetDetail2DataSize = %d\n",__FILE__,__FUNCTION__,__LINE__,iPacketLoop,packetIndex,maxFileCountPerPacket,packetFileCount,packetDetail1DataSize,packetDetail2DataSize); + + // Wait a max of x seconds for this message + result = NetworkMessage::receive(socket, &data.detail.techCRCFileList[packetIndex], packetDetail1DataSize, true); + if(result == true) { + for(int i = 0; i < data.header.techCRCFileCount; ++i) { + data.detail.techCRCFileList[i].nullTerminate(); + } + + result = NetworkMessage::receive(socket, &data.detail.techCRCFileCRCList[packetIndex], packetDetail2DataSize, true); + } + } + } + + return result; } void NetworkMessageSynchNetworkGameData::send(Socket* socket) const { @@ -801,6 +905,8 @@ string NetworkMessageSynchNetworkGameDataStatus::getTechCRCFileMismatchReport(st bool NetworkMessageSynchNetworkGameDataStatus::receive(Socket* socket) { if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] about to get nmtSynchNetworkGameDataStatus\n",__FILE__,__FUNCTION__,__LINE__); + +/* data.header.techCRCFileCount = 0; const double MAX_MSG_WAIT_SECONDS = 3; @@ -819,7 +925,7 @@ bool NetworkMessageSynchNetworkGameDataStatus::receive(Socket* socket) { if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] messageType = %d, data.techCRCFileCount = %d\n",__FILE__,__FUNCTION__,__LINE__,data.header.messageType,data.header.techCRCFileCount); - bool result = NetworkMessage::receive(socket, &data, HeaderSize); + bool result = NetworkMessage::receive(socket, &data, HeaderSize, true); if(result == true && data.header.techCRCFileCount > 0) { // Here we loop possibly multiple times int packetLoopCount = 1; @@ -847,7 +953,7 @@ bool NetworkMessageSynchNetworkGameDataStatus::receive(Socket* socket) { } } - result = NetworkMessage::receive(socket, &data.detail.techCRCFileList[packetIndex], (DetailSize1 * packetFileCount)); + result = NetworkMessage::receive(socket, &data.detail.techCRCFileList[packetIndex], (DetailSize1 * packetFileCount),true); if(result == true) { for(int i = 0; i < data.header.techCRCFileCount; ++i) { data.detail.techCRCFileList[i].nullTerminate(); @@ -860,7 +966,47 @@ bool NetworkMessageSynchNetworkGameDataStatus::receive(Socket* socket) { } } - result = NetworkMessage::receive(socket, &data.detail.techCRCFileCRCList[packetIndex], (DetailSize2 * packetFileCount)); + result = NetworkMessage::receive(socket, &data.detail.techCRCFileCRCList[packetIndex], (DetailSize2 * packetFileCount),true); + } + } + } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] result = %d\n",__FILE__,__FUNCTION__,__LINE__,result); + + return result; +*/ + + data.header.techCRCFileCount = 0; + + bool result = NetworkMessage::receive(socket, &data, HeaderSize, true); + if(result == true && data.header.techCRCFileCount > 0) { + // Here we loop possibly multiple times + int packetLoopCount = 1; + if(data.header.techCRCFileCount > NetworkMessageSynchNetworkGameDataStatus::maxFileCRCPacketCount) { + packetLoopCount = (data.header.techCRCFileCount / NetworkMessageSynchNetworkGameDataStatus::maxFileCRCPacketCount); + if(data.header.techCRCFileCount % NetworkMessageSynchNetworkGameDataStatus::maxFileCRCPacketCount > 0) { + packetLoopCount++; + } + } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] packetLoopCount = %d\n",__FILE__,__FUNCTION__,__LINE__,packetLoopCount); + + for(int iPacketLoop = 0; iPacketLoop < packetLoopCount; ++iPacketLoop) { + + int packetIndex = iPacketLoop * NetworkMessageSynchNetworkGameDataStatus::maxFileCRCPacketCount; + int maxFileCountPerPacket = maxFileCRCPacketCount; + int packetFileCount = min(maxFileCountPerPacket,data.header.techCRCFileCount - packetIndex); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] iPacketLoop = %d, packetIndex = %d, packetFileCount = %d\n",__FILE__,__FUNCTION__,__LINE__,iPacketLoop,packetIndex,packetFileCount); + + result = NetworkMessage::receive(socket, &data.detail.techCRCFileList[packetIndex], (DetailSize1 * packetFileCount),true); + if(result == true) { + for(int i = 0; i < data.header.techCRCFileCount; ++i) { + data.detail.techCRCFileList[i].nullTerminate(); + } + + // Wait a max of x seconds for this message + result = NetworkMessage::receive(socket, &data.detail.techCRCFileCRCList[packetIndex], (DetailSize2 * packetFileCount),true); } } } @@ -916,7 +1062,7 @@ NetworkMessageSynchNetworkGameDataFileCRCCheck::NetworkMessageSynchNetworkGameDa } bool NetworkMessageSynchNetworkGameDataFileCRCCheck::receive(Socket* socket) { - bool result = NetworkMessage::receive(socket, &data, sizeof(data)); + bool result = NetworkMessage::receive(socket, &data, sizeof(data), true); data.fileName.nullTerminate(); @@ -942,7 +1088,7 @@ NetworkMessageSynchNetworkGameDataFileGet::NetworkMessageSynchNetworkGameDataFil } bool NetworkMessageSynchNetworkGameDataFileGet::receive(Socket* socket) { - bool result = NetworkMessage::receive(socket, &data, sizeof(data)); + bool result = NetworkMessage::receive(socket, &data, sizeof(data), true); data.fileName.nullTerminate(); @@ -990,7 +1136,7 @@ SwitchSetupRequest::SwitchSetupRequest(string selectedFactionName, int8 currentF } bool SwitchSetupRequest::receive(Socket* socket) { - bool result = NetworkMessage::receive(socket, &data, sizeof(data)); + bool result = NetworkMessage::receive(socket, &data, sizeof(data), true); data.selectedFactionName.nullTerminate(); data.networkPlayerName.nullTerminate(); @@ -1018,13 +1164,11 @@ PlayerIndexMessage::PlayerIndexMessage(int16 playerIndex) data.playerIndex=playerIndex; } -bool PlayerIndexMessage::receive(Socket* socket) -{ - return NetworkMessage::receive(socket, &data, sizeof(data)); +bool PlayerIndexMessage::receive(Socket* socket) { + return NetworkMessage::receive(socket, &data, sizeof(data), true); } -void PlayerIndexMessage::send(Socket* socket) const -{ +void PlayerIndexMessage::send(Socket* socket) const { assert(data.messageType==nmtPlayerIndexMessage); NetworkMessage::send(socket, &data, sizeof(data)); } @@ -1038,9 +1182,8 @@ NetworkMessageLoadingStatus::NetworkMessageLoadingStatus(uint32 status) data.status=status; } -bool NetworkMessageLoadingStatus::receive(Socket* socket) -{ - return NetworkMessage::receive(socket, &data, sizeof(data)); +bool NetworkMessageLoadingStatus::receive(Socket* socket) { + return NetworkMessage::receive(socket, &data, sizeof(data), true); } void NetworkMessageLoadingStatus::send(Socket* socket) const diff --git a/source/glest_game/network/network_message.h b/source/glest_game/network/network_message.h index 315372f0..54fdd558 100644 --- a/source/glest_game/network/network_message.h +++ b/source/glest_game/network/network_message.h @@ -68,8 +68,8 @@ public: virtual void send(Socket* socket) const = 0; protected: - bool peek(Socket* socket, void* data, int dataSize); - bool receive(Socket* socket, void* data, int dataSize); + //bool peek(Socket* socket, void* data, int dataSize); + bool receive(Socket* socket, void* data, int dataSize,bool tryReceiveUntilDataSizeMet); void send(Socket* socket, const void* data, int dataSize) const; }; diff --git a/source/shared_lib/include/platform/posix/socket.h b/source/shared_lib/include/platform/posix/socket.h index 70d25a9c..ab4c678f 100644 --- a/source/shared_lib/include/platform/posix/socket.h +++ b/source/shared_lib/include/platform/posix/socket.h @@ -145,7 +145,7 @@ public: int getDataToRead(bool wantImmediateReply=false); int send(const void *data, int dataSize); - int receive(void *data, int dataSize); + int receive(void *data, int dataSize, bool tryReceiveUntilDataSizeMet); int peek(void *data, int dataSize, bool mustGetData=true); void setBlock(bool block); diff --git a/source/shared_lib/sources/platform/posix/socket.cpp b/source/shared_lib/sources/platform/posix/socket.cpp index 42450610..54ac213e 100644 --- a/source/shared_lib/sources/platform/posix/socket.cpp +++ b/source/shared_lib/sources/platform/posix/socket.cpp @@ -1197,7 +1197,7 @@ int Socket::send(const void *data, int dataSize) { return static_cast(bytesSent); } -int Socket::receive(void *data, int dataSize) { +int Socket::receive(void *data, int dataSize, bool tryReceiveUntilDataSizeMet) { const int MAX_RECV_WAIT_SECONDS = 3; ssize_t bytesReceived = 0; @@ -1251,7 +1251,19 @@ int Socket::receive(void *data, int dataSize) { int iErr = getLastSocketError(); disconnectSocket(); - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,bytesReceived,getLastSocketErrorFormattedText(&iErr).c_str()); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, error = %s, dataSize = %d, tryReceiveUntilDataSizeMet = %d\n",__FILE__,__FUNCTION__,__LINE__,bytesReceived,getLastSocketErrorFormattedText(&iErr).c_str(),dataSize,tryReceiveUntilDataSizeMet); + } + else if(tryReceiveUntilDataSizeMet == true && bytesReceived < dataSize) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING, attempting to receive MORE data, bytesReceived = %d, dataSize = %d\n",__FILE__,__FUNCTION__,__LINE__,bytesReceived,dataSize); + + char *dataAsCharPointer = reinterpret_cast(data); + int additionalBytes = receive(&dataAsCharPointer[bytesReceived], dataSize, tryReceiveUntilDataSizeMet); + if(additionalBytes > 0) { + bytesReceived += additionalBytes; + } + else { + throw runtime_error("additionalBytes == " + intToStr(additionalBytes)); + } } return static_cast(bytesReceived); } @@ -1572,18 +1584,18 @@ void ClientSocket::connect(const Ip &ip, int port) connectedIpAddress = ""; int err= ::connect(sock, reinterpret_cast(&addr), sizeof(addr)); if(err < 0) { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 Error connecting socket for IP: %s for Port: %d err = %d error = %s\n",__FILE__,__FUNCTION__,ip.getString().c_str(),port,err,getLastSocketErrorFormattedText().c_str()); - if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s] #2 Error connecting socket for IP: %s for Port: %d err = %d error = %s\n",__FILE__,__FUNCTION__,ip.getString().c_str(),port,err,getLastSocketErrorFormattedText().c_str()); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #2 Error connecting socket for IP: %s for Port: %d err = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,ip.getString().c_str(),port,err,getLastSocketErrorFormattedText().c_str()); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] #2 Error connecting socket for IP: %s for Port: %d err = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,ip.getString().c_str(),port,err,getLastSocketErrorFormattedText().c_str()); if (getLastSocketError() == PLATFORM_SOCKET_INPROGRESS || getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) { fd_set myset; struct timeval tv; - int valopt; - socklen_t lon; + int valopt=0; + socklen_t lon=0; - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] PLATFORM_SOCKET_INPROGRESS in connect() - selecting\n",__FILE__,__FUNCTION__); - if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s] PLATFORM_SOCKET_INPROGRESS in connect() - selecting\n",__FILE__,__FUNCTION__); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] PLATFORM_SOCKET_INPROGRESS in connect() - selecting\n",__FILE__,__FUNCTION__,__LINE__); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] PLATFORM_SOCKET_INPROGRESS in connect() - selecting\n",__FILE__,__FUNCTION__,__LINE__); do { tv.tv_sec = 10; @@ -1599,40 +1611,41 @@ void ClientSocket::connect(const Ip &ip, int port) } if (err < 0 && getLastSocketError() != PLATFORM_SOCKET_INTERRUPTED) { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Error connecting %s\n",__FILE__,__FUNCTION__,getLastSocketErrorFormattedText().c_str()); - if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s] Error connecting %s\n",__FILE__,__FUNCTION__,getLastSocketErrorFormattedText().c_str()); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Error connecting %s\n",__FILE__,__FUNCTION__,__LINE__,getLastSocketErrorFormattedText().c_str()); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Error connecting %s\n",__FILE__,__FUNCTION__,__LINE__,getLastSocketErrorFormattedText().c_str()); break; } - else if (err > 0) { + else if(err > 0) { + //else if(FD_ISSET(sock, &myset)) { // Socket selected for write - lon = sizeof(int); + lon = sizeof(valopt); #ifndef WIN32 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) #else if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)(&valopt), &lon) < 0) #endif { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Error in getsockopt() %s\n",__FILE__,__FUNCTION__,getLastSocketErrorFormattedText().c_str()); - if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s] Error in getsockopt() %s\n",__FILE__,__FUNCTION__,getLastSocketErrorFormattedText().c_str()); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Error in getsockopt() %s\n",__FILE__,__FUNCTION__,__LINE__,getLastSocketErrorFormattedText().c_str()); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Error in getsockopt() %s\n",__FILE__,__FUNCTION__,__LINE__,getLastSocketErrorFormattedText().c_str()); break; } // Check the value returned... if(valopt) { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Error in delayed connection() %d - [%s]\n",__FILE__,__FUNCTION__,valopt, strerror(valopt)); - if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s] Error in delayed connection() %d - [%s]\n",__FILE__,__FUNCTION__,valopt, strerror(valopt)); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Error in delayed connection() %d - [%s]\n",__FILE__,__FUNCTION__,__LINE__,valopt, strerror(valopt)); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Error in delayed connection() %d - [%s]\n",__FILE__,__FUNCTION__,__LINE__,valopt, strerror(valopt)); break; } errno = 0; - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Apparent recovery for connection sock = %d, err = %d\n",__FILE__,__FUNCTION__,sock,err); - if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s] Apparent recovery for connection sock = %d, err = %d\n",__FILE__,__FUNCTION__,sock,err); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Apparent recovery for connection sock = %d, err = %d\n",__FILE__,__FUNCTION__,__LINE__,sock,err); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Apparent recovery for connection sock = %d, err = %d\n",__FILE__,__FUNCTION__,__LINE__,sock,err); break; } else { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Timeout in select() - Cancelling!\n",__FILE__,__FUNCTION__); - if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s] Timeout in select() - Cancelling!\n",__FILE__,__FUNCTION__); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Timeout in select() - Cancelling!\n",__FILE__,__FUNCTION__,__LINE__); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Timeout in select() - Cancelling!\n",__FILE__,__FUNCTION__,__LINE__); disconnectSocket(); break; @@ -1641,13 +1654,13 @@ void ClientSocket::connect(const Ip &ip, int port) } if(err < 0) { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Before END sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,sock,err,getLastSocketErrorFormattedText().c_str()); - if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s] Before END sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,sock,err,getLastSocketErrorFormattedText().c_str()); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Before END sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,sock,err,getLastSocketErrorFormattedText().c_str()); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Before END sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,sock,err,getLastSocketErrorFormattedText().c_str()); disconnectSocket(); } else { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Valid recovery for connection sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,sock,err,getLastSocketErrorFormattedText().c_str()); - if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s] Valid recovery for connection sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,sock,err,getLastSocketErrorFormattedText().c_str()); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Valid recovery for connection sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,sock,err,getLastSocketErrorFormattedText().c_str()); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Valid recovery for connection sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,sock,err,getLastSocketErrorFormattedText().c_str()); connectedIpAddress = ip.getString(); } }