- numerous bugfixes mostly centered around network lag, but also added more logging and protective code (like buffer overflow checks)

*NOTE: This version is NOT backwards compatible with other builds
This commit is contained in:
Mark Vejvoda
2010-08-07 03:26:38 +00:00
parent 270fa8fef0
commit fe8d3b3130
14 changed files with 373 additions and 128 deletions

View File

@@ -48,6 +48,7 @@ ClientInterface::ClientInterface(){
gotIntro = false; gotIntro = false;
lastNetworkCommandListSendTime = 0; lastNetworkCommandListSendTime = 0;
currentFrameCount = 0; currentFrameCount = 0;
clientSimulationLagStartTime = 0;
networkGameDataSynchCheckOkMap = false; networkGameDataSynchCheckOkMap = false;
networkGameDataSynchCheckOkTile = false; networkGameDataSynchCheckOkTile = false;
@@ -508,6 +509,17 @@ void ClientInterface::updateKeyframe(int frameCount)
//wait for the next message //wait for the next message
waitForMessage(); waitForMessage();
// START: Test simulating lag for the client
if(Config::getInstance().getInt("SimulateClientLag","0") > 0) {
if(clientSimulationLagStartTime == 0) {
clientSimulationLagStartTime = time(NULL);
}
if(difftime(time(NULL),clientSimulationLagStartTime) <= Config::getInstance().getInt("SimulateClientLagDurationSeconds","0")) {
sleep(Config::getInstance().getInt("SimulateClientLag","0"));
}
}
// END: Test simulating lag for the client
//check we have an expected message //check we have an expected message
NetworkMessageType networkMessageType= getNextMessageType(true); NetworkMessageType networkMessageType= getNextMessageType(true);
@@ -533,7 +545,10 @@ void ClientInterface::updateKeyframe(int frameCount)
chrono.start(); chrono.start();
//check that we are in the right frame //check that we are in the right frame
if(networkMessageCommandList.getFrameCount() != frameCount) { if(networkMessageCommandList.getFrameCount() != frameCount) {
string sErr = "Network synchronization error, frame counts do not match, server frameCount = " + intToStr(networkMessageCommandList.getFrameCount()) + ", local frameCount = " + intToStr(frameCount); string sErr = "Player: " + Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()) +
" got a Network synchronization error, frame counts do not match, server frameCount = " +
intToStr(networkMessageCommandList.getFrameCount()) + ", local frameCount = " +
intToStr(frameCount);
//throw runtime_error("Network synchronization error, frame counts do not match"); //throw runtime_error("Network synchronization error, frame counts do not match");
sendTextMessage(sErr,-1, true); sendTextMessage(sErr,-1, true);
DisplayErrorMessage(sErr); DisplayErrorMessage(sErr);

View File

@@ -52,6 +52,7 @@ private:
int currentFrameCount; int currentFrameCount;
time_t lastNetworkCommandListSendTime; time_t lastNetworkCommandListSendTime;
time_t clientSimulationLagStartTime;
string versionString; string versionString;
public: public:

View File

@@ -249,11 +249,15 @@ void ConnectionSlot::update(bool checkForNewClients) {
if(socket->isConnected()) { if(socket->isConnected()) {
this->clearChatInfo(); this->clearChatInfo();
if(socket->hasDataToRead() == true) { bool gotTextMsg = true;
NetworkMessageType networkMessageType= getNextMessageType(); for(;socket->hasDataToRead() == true && gotTextMsg == true;) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] polling for networkMessageType...\n",__FILE__,__FUNCTION__,__LINE__);
NetworkMessageType networkMessageType= getNextMessageType(true);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] networkMessageType = %d\n",__FILE__,__FUNCTION__,__LINE__,networkMessageType); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] networkMessageType = %d\n",__FILE__,__FUNCTION__,__LINE__,networkMessageType);
gotTextMsg = false;
//process incoming commands //process incoming commands
switch(networkMessageType) { switch(networkMessageType) {
@@ -281,6 +285,7 @@ void ConnectionSlot::update(bool checkForNewClients) {
if(receiveMessage(&networkMessageText)) { if(receiveMessage(&networkMessageText)) {
ChatMsgInfo msg(networkMessageText.getText().c_str(),networkMessageText.getSender().c_str(),networkMessageText.getTeamIndex()); ChatMsgInfo msg(networkMessageText.getText().c_str(),networkMessageText.getSender().c_str(),networkMessageText.getTeamIndex());
this->addChatInfo(msg); this->addChatInfo(msg);
gotTextMsg = true;
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] chatText [%s] chatSender [%s] chatTeamIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,chatText.c_str(),chatSender.c_str(),chatTeamIndex); //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] chatText [%s] chatSender [%s] chatTeamIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,chatText.c_str(),chatSender.c_str(),chatTeamIndex);
} }

View File

@@ -97,8 +97,9 @@ bool NetworkMessage::receive(Socket* socket, void* data, int dataSize)
return false; return false;
} }
void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const {
{ SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] socket = %p, data = %p, dataSize = %d\n",__FILE__,__FUNCTION__,__LINE__,socket,data,dataSize);
if(socket != NULL) { if(socket != NULL) {
int sendResult = socket->send(data, dataSize); int sendResult = socket->send(data, dataSize);
if(sendResult != dataSize) { if(sendResult != dataSize) {
@@ -137,6 +138,7 @@ bool NetworkMessageIntro::receive(Socket* socket){
} }
void NetworkMessageIntro::send(Socket* socket) const{ void NetworkMessageIntro::send(Socket* socket) const{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] nmtIntro\n",__FILE__,__FUNCTION__,__LINE__);
assert(data.messageType==nmtIntro); assert(data.messageType==nmtIntro);
NetworkMessage::send(socket, &data, sizeof(data)); NetworkMessage::send(socket, &data, sizeof(data));
} }
@@ -163,6 +165,7 @@ bool NetworkMessagePing::receive(Socket* socket){
} }
void NetworkMessagePing::send(Socket* socket) const{ void NetworkMessagePing::send(Socket* socket) const{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] nmtPing\n",__FILE__,__FUNCTION__,__LINE__);
assert(data.messageType==nmtPing); assert(data.messageType==nmtPing);
NetworkMessage::send(socket, &data, sizeof(data)); NetworkMessage::send(socket, &data, sizeof(data));
} }
@@ -185,6 +188,7 @@ bool NetworkMessageReady::receive(Socket* socket){
} }
void NetworkMessageReady::send(Socket* socket) const{ void NetworkMessageReady::send(Socket* socket) const{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] nmtReady\n",__FILE__,__FUNCTION__,__LINE__);
assert(data.messageType==nmtReady); assert(data.messageType==nmtReady);
NetworkMessage::send(socket, &data, sizeof(data)); NetworkMessage::send(socket, &data, sizeof(data));
} }
@@ -258,6 +262,7 @@ bool NetworkMessageLaunch::receive(Socket* socket){
} }
void NetworkMessageLaunch::send(Socket* socket) const{ void NetworkMessageLaunch::send(Socket* socket) const{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] nmtLaunch\n",__FILE__,__FUNCTION__,__LINE__);
NetworkMessage::send(socket, &data, sizeof(data)); NetworkMessage::send(socket, &data, sizeof(data));
} }
@@ -335,6 +340,8 @@ bool NetworkMessageCommandList::receive(Socket* socket) {
} }
void NetworkMessageCommandList::send(Socket* socket) const{ void NetworkMessageCommandList::send(Socket* socket) const{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] nmtCommandList, frameCount = %d\n",__FILE__,__FUNCTION__,__LINE__,data.header.frameCount);
assert(data.header.messageType==nmtCommandList); assert(data.header.messageType==nmtCommandList);
int totalMsgSize = commandListHeaderSize + (sizeof(NetworkCommand) * data.header.commandCount); int totalMsgSize = commandListHeaderSize + (sizeof(NetworkCommand) * data.header.commandCount);
NetworkMessage::send(socket, &data, totalMsgSize); NetworkMessage::send(socket, &data, totalMsgSize);
@@ -359,6 +366,16 @@ void NetworkMessageCommandList::send(Socket* socket) const{
// ===================================================== // =====================================================
NetworkMessageText::NetworkMessageText(const string &text, const string &sender, int teamIndex){ NetworkMessageText::NetworkMessageText(const string &text, const string &sender, int teamIndex){
if(text.length() >= maxTextStringSize) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING / ERROR - text [%s] length = %d, max = %d\n",__FILE__,__FUNCTION__,__LINE__,text.c_str(),text.length(),maxTextStringSize);
//throw runtime_error("NetworkMessageText - text.length() >= maxStringSize");
}
if(sender.length() >= maxSenderStringSize) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING / ERROR - sender [%s] length = %d, max = %d\n",__FILE__,__FUNCTION__,__LINE__,sender.c_str(),sender.length(),maxSenderStringSize);
//throw runtime_error("NetworkMessageText - sender.length() >= maxSenderStringSize");
}
data.messageType= nmtText; data.messageType= nmtText;
data.text= text; data.text= text;
data.sender= sender; data.sender= sender;
@@ -370,6 +387,8 @@ bool NetworkMessageText::receive(Socket* socket){
} }
void NetworkMessageText::send(Socket* socket) const{ void NetworkMessageText::send(Socket* socket) const{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] nmtText\n",__FILE__,__FUNCTION__,__LINE__);
assert(data.messageType==nmtText); assert(data.messageType==nmtText);
NetworkMessage::send(socket, &data, sizeof(data)); NetworkMessage::send(socket, &data, sizeof(data));
} }
@@ -387,6 +406,8 @@ bool NetworkMessageQuit::receive(Socket* socket){
} }
void NetworkMessageQuit::send(Socket* socket) const{ void NetworkMessageQuit::send(Socket* socket) const{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] nmtQuit\n",__FILE__,__FUNCTION__,__LINE__);
assert(data.messageType==nmtQuit); assert(data.messageType==nmtQuit);
NetworkMessage::send(socket, &data, sizeof(data)); NetworkMessage::send(socket, &data, sizeof(data));
} }
@@ -442,8 +463,9 @@ bool NetworkMessageSynchNetworkGameData::receive(Socket* socket)
return NetworkMessage::receive(socket, &data, sizeof(data)); return NetworkMessage::receive(socket, &data, sizeof(data));
} }
void NetworkMessageSynchNetworkGameData::send(Socket* socket) const void NetworkMessageSynchNetworkGameData::send(Socket* socket) const {
{ SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] nmtSynchNetworkGameData\n",__FILE__,__FUNCTION__,__LINE__);
assert(data.messageType==nmtSynchNetworkGameData); assert(data.messageType==nmtSynchNetworkGameData);
NetworkMessage::send(socket, &data, sizeof(data)); NetworkMessage::send(socket, &data, sizeof(data));
} }
@@ -467,8 +489,9 @@ bool NetworkMessageSynchNetworkGameDataStatus::receive(Socket* socket)
return NetworkMessage::receive(socket, &data, sizeof(data)); return NetworkMessage::receive(socket, &data, sizeof(data));
} }
void NetworkMessageSynchNetworkGameDataStatus::send(Socket* socket) const void NetworkMessageSynchNetworkGameDataStatus::send(Socket* socket) const {
{ SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] nmtSynchNetworkGameDataStatus\n",__FILE__,__FUNCTION__,__LINE__);
assert(data.messageType==nmtSynchNetworkGameDataStatus); assert(data.messageType==nmtSynchNetworkGameDataStatus);
NetworkMessage::send(socket, &data, sizeof(data)); NetworkMessage::send(socket, &data, sizeof(data));
} }
@@ -492,8 +515,9 @@ bool NetworkMessageSynchNetworkGameDataFileCRCCheck::receive(Socket* socket)
return NetworkMessage::receive(socket, &data, sizeof(data)); return NetworkMessage::receive(socket, &data, sizeof(data));
} }
void NetworkMessageSynchNetworkGameDataFileCRCCheck::send(Socket* socket) const void NetworkMessageSynchNetworkGameDataFileCRCCheck::send(Socket* socket) const {
{ SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] nmtSynchNetworkGameDataFileCRCCheck\n",__FILE__,__FUNCTION__,__LINE__);
assert(data.messageType==nmtSynchNetworkGameDataFileCRCCheck); assert(data.messageType==nmtSynchNetworkGameDataFileCRCCheck);
NetworkMessage::send(socket, &data, sizeof(data)); NetworkMessage::send(socket, &data, sizeof(data));
} }
@@ -514,8 +538,9 @@ bool NetworkMessageSynchNetworkGameDataFileGet::receive(Socket* socket)
return NetworkMessage::receive(socket, &data, sizeof(data)); return NetworkMessage::receive(socket, &data, sizeof(data));
} }
void NetworkMessageSynchNetworkGameDataFileGet::send(Socket* socket) const void NetworkMessageSynchNetworkGameDataFileGet::send(Socket* socket) const {
{ SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] nmtSynchNetworkGameDataFileGet\n",__FILE__,__FUNCTION__,__LINE__);
assert(data.messageType==nmtSynchNetworkGameDataFileGet); assert(data.messageType==nmtSynchNetworkGameDataFileGet);
NetworkMessage::send(socket, &data, sizeof(data)); NetworkMessage::send(socket, &data, sizeof(data));
} }

View File

@@ -270,13 +270,14 @@ public:
class NetworkMessageText: public NetworkMessage{ class NetworkMessageText: public NetworkMessage{
private: private:
static const int maxStringSize= 256; static const int maxTextStringSize= 340;
static const int maxSenderStringSize= 60;
private: private:
struct Data{ struct Data{
int8 messageType; int8 messageType;
NetworkString<maxStringSize> text; NetworkString<maxTextStringSize> text;
NetworkString<maxStringSize> sender; NetworkString<maxSenderStringSize> sender;
int8 teamIndex; int8 teamIndex;
}; };

View File

@@ -40,7 +40,11 @@ private:
public: public:
NetworkString() {memset(buffer, 0, S);} NetworkString() {memset(buffer, 0, S);}
void operator=(const string& str) {strncpy(buffer, str.c_str(), S-1);} void operator=(const string& str) {
// ensure we don't have a buffer overflow
int maxBufferSize = sizeof(buffer) / sizeof(buffer[0]);
strncpy(buffer, str.c_str(), std::min(S-1,maxBufferSize));
}
string getString() const {return buffer;} string getString() const {return buffer;}
}; };

View File

@@ -51,6 +51,10 @@ double warnFrameCountLagPercent = 0.65;
// Seconds grace period before we start checking LAG // Seconds grace period before we start checking LAG
double LAG_CHECK_GRACE_PERIOD = 15; double LAG_CHECK_GRACE_PERIOD = 15;
// The max amount of time to 'freeze' gameplay per packet when a client is lagging
// badly and we want to give time for them to catch up
double MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE = 2;
ServerInterface::ServerInterface(){ ServerInterface::ServerInterface(){
gameHasBeenInitiated = false; gameHasBeenInitiated = false;
gameSettingsUpdateCount = 0; gameSettingsUpdateCount = 0;
@@ -264,7 +268,7 @@ void ServerInterface::updateSlot(ConnectionSlotEvent *event) {
} }
// Only call when client has just sent us data // Only call when client has just sent us data
std::pair<bool,bool> ServerInterface::clientLagCheck(ConnectionSlot* connectionSlot) { std::pair<bool,bool> ServerInterface::clientLagCheck(ConnectionSlot* connectionSlot, bool skipNetworkBroadCast) {
std::pair<bool,bool> clientLagExceededOrWarned = std::make_pair(false,false); std::pair<bool,bool> clientLagExceededOrWarned = std::make_pair(false,false);
static bool alreadyInLagCheck = false; static bool alreadyInLagCheck = false;
@@ -320,8 +324,10 @@ std::pair<bool,bool> ServerInterface::clientLagCheck(ConnectionSlot* connectionS
#endif #endif
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf);
if(skipNetworkBroadCast == false) {
string sMsg = szBuf; string sMsg = szBuf;
sendTextMessage(sMsg,-1, true); sendTextMessage(sMsg,-1, true);
}
if(gameSettings.getNetworkPauseGameForLaggedClients() == false) { if(gameSettings.getNetworkPauseGameForLaggedClients() == false) {
connectionSlot->close(); connectionSlot->close();
@@ -347,10 +353,12 @@ std::pair<bool,bool> ServerInterface::clientLagCheck(ConnectionSlot* connectionS
#endif #endif
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf);
if(skipNetworkBroadCast == false) {
string sMsg = szBuf; string sMsg = szBuf;
sendTextMessage(sMsg,-1, true); sendTextMessage(sMsg,-1, true);
} }
} }
}
else if(connectionSlot->getLagCountWarning() == true) { else if(connectionSlot->getLagCountWarning() == true) {
connectionSlot->setLagCountWarning(false); connectionSlot->setLagCountWarning(false);
} }
@@ -437,11 +445,58 @@ void ServerInterface::update() {
mapSlotSignalledList[i] = signalClientReceiveCommands(connectionSlot,i,socketTriggered,event); mapSlotSignalledList[i] = signalClientReceiveCommands(connectionSlot,i,socketTriggered,event);
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #2\n",__FILE__,__FUNCTION__,__LINE__);
// Step #2 check all connection slot worker threads for completed status // Step #2 check all connection slot worker threads for completed status
std::map<int,bool> slotsCompleted; std::map<int,bool> slotsCompleted;
std::map<int,bool> slotsWarnedAndRetried; for(bool threadsDone = false; threadsDone == false;) {
threadsDone = true;
// Examine all threads for completion of delegation
for(int i= 0; i< GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot = slots[i];
if(connectionSlot != NULL && mapSlotSignalledList[i] == true &&
slotsCompleted.find(i) == slotsCompleted.end()) {
try {
std::vector<std::string> errorList = connectionSlot->getThreadErrorList();
// Collect any collected errors from threads
if(errorList.size() > 0) {
for(int iErrIdx = 0; iErrIdx < errorList.size(); ++iErrIdx) {
string &sErr = errorList[iErrIdx];
if(sErr != "") {
errorMsgList.push_back(sErr);
}
}
connectionSlot->clearThreadErrorList();
}
connectionSlot = slots[i];
// Not done waiting for data yet
bool updateFinished = (connectionSlot != NULL ? connectionSlot->updateCompleted() : true);
if(updateFinished == false) {
threadsDone = false;
sleep(0);
break;
}
else {
slotsCompleted[i] = true;
}
}
catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error detected [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
errorMsgList.push_back(ex.what());
}
}
}
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #3\n",__FILE__,__FUNCTION__,__LINE__);
// Step #3 check clients for any lagging scenarios and try to deal with them
time_t waitForClientsElapsed = time(NULL);
slotsCompleted.clear();
//std::map<int,bool> slotsWarnedAndRetried;
std::map<int,bool> slotsWarnedList;
for(bool threadsDone = false; threadsDone == false;) { for(bool threadsDone = false; threadsDone == false;) {
threadsDone = true; threadsDone = true;
// Examine all threads for completion of delegation // Examine all threads for completion of delegation
@@ -456,7 +511,6 @@ void ServerInterface::update() {
for(int iErrIdx = 0; iErrIdx < errorList.size(); ++iErrIdx) { for(int iErrIdx = 0; iErrIdx < errorList.size(); ++iErrIdx) {
string &sErr = errorList[iErrIdx]; string &sErr = errorList[iErrIdx];
if(sErr != "") { if(sErr != "") {
//DisplayErrorMessage(sErr);
errorMsgList.push_back(sErr); errorMsgList.push_back(sErr);
} }
} }
@@ -479,20 +533,38 @@ void ServerInterface::update() {
std::pair<bool,bool> clientLagExceededOrWarned = std::make_pair(false,false); std::pair<bool,bool> clientLagExceededOrWarned = std::make_pair(false,false);
if( gameHasBeenInitiated == true && connectionSlot != NULL && if( gameHasBeenInitiated == true && connectionSlot != NULL &&
connectionSlot->isConnected() == true) { connectionSlot->isConnected() == true) {
clientLagExceededOrWarned = clientLagCheck(connectionSlot); clientLagExceededOrWarned = clientLagCheck(connectionSlot,slotsWarnedList[i]);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d, gameSettings.getNetworkPauseGameForLaggedClients() = %d\n",__FILE__,__FUNCTION__,__LINE__,clientLagExceededOrWarned.first,clientLagExceededOrWarned.second,gameSettings.getNetworkPauseGameForLaggedClients());
if(clientLagExceededOrWarned.first == true) {
slotsWarnedList[i] = true;
}
} }
// If the client has exceeded lag and the server wants // If the client has exceeded lag and the server wants
// to pause while they catch up, re-trigger the // to pause while they catch up, re-trigger the
// client reader thread // client reader thread
if((clientLagExceededOrWarned.first == true && gameSettings.getNetworkPauseGameForLaggedClients() == true) || if((clientLagExceededOrWarned.first == true && gameSettings.getNetworkPauseGameForLaggedClients() == true)) { // ||
(clientLagExceededOrWarned.second == true && slotsWarnedAndRetried[i] == false)) { //(clientLagExceededOrWarned.second == true && slotsWarnedAndRetried[i] == false)) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d, clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d, difftime(time(NULL),waitForClientsElapsed) = %.2f, MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE = %.2f\n",__FILE__,__FUNCTION__,__LINE__,clientLagExceededOrWarned.first,clientLagExceededOrWarned.second,difftime(time(NULL),waitForClientsElapsed),MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE);
if(difftime(time(NULL),waitForClientsElapsed) < MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE) {
connectionSlot = slots[i];
if(connectionSlot != NULL) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d, clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d\n",__FILE__,__FUNCTION__,__LINE__,clientLagExceededOrWarned.first,clientLagExceededOrWarned.second);
bool socketTriggered = (connectionSlot != NULL && connectionSlot->getSocket() != NULL ? socketTriggeredList[connectionSlot->getSocket()->getSocketId()] : false); bool socketTriggered = (connectionSlot != NULL && connectionSlot->getSocket() != NULL ? socketTriggeredList[connectionSlot->getSocket()->getSocketId()] : false);
ConnectionSlotEvent &event = eventList[i]; ConnectionSlotEvent &event = eventList[i];
signalClientReceiveCommands(connectionSlot,i,socketTriggered,event); mapSlotSignalledList[i] = signalClientReceiveCommands(connectionSlot,i,socketTriggered,event);
sleep(0); sleep(0);
threadsDone = false;
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d, clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d\n",__FILE__,__FUNCTION__,__LINE__,clientLagExceededOrWarned.first,clientLagExceededOrWarned.second);
if(gameSettings.getNetworkPauseGameForLaggedClients() == false) { //if(gameSettings.getNetworkPauseGameForLaggedClients() == false) {
slotsWarnedAndRetried[i] = true; // slotsWarnedAndRetried[i] = true;
//}
} }
} }
else { else {
@@ -508,20 +580,20 @@ void ServerInterface::update() {
} }
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #4\n",__FILE__,__FUNCTION__,__LINE__);
// Step #3 dispatch network commands to the pending list so that they are done in proper order // Step #4 dispatch network commands to the pending list so that they are done in proper order
if(gameHasBeenInitiated == true) { if(gameHasBeenInitiated == true) {
for(int i= 0; i< GameConstants::maxPlayers; ++i) { for(int i= 0; i< GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected() == true) { if(connectionSlot != NULL && connectionSlot->isConnected() == true) {
if(connectionSlot->getPendingNetworkCommandList().size() > 0) { if(connectionSlot->getPendingNetworkCommandList().size() > 0) {
// New lag check // New lag check
std::pair<bool,bool> clientLagExceededOrWarned = clientLagCheck(connectionSlot); //std::pair<bool,bool> clientLagExceededOrWarned = clientLagCheck(connectionSlot);
if(clientLagExceededOrWarned.first == true) { //if(clientLagExceededOrWarned.first == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d, clientLagExceeded = %d, warned = %d\n",__FILE__,__FUNCTION__,__LINE__,i,clientLagExceededOrWarned.first,clientLagExceededOrWarned.second); // SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d, clientLagExceeded = %d, warned = %d\n",__FILE__,__FUNCTION__,__LINE__,i,clientLagExceededOrWarned.first,clientLagExceededOrWarned.second);
} //}
else { //else {
vector<NetworkCommand> vctPendingNetworkCommandList = connectionSlot->getPendingNetworkCommandList(); vector<NetworkCommand> vctPendingNetworkCommandList = connectionSlot->getPendingNetworkCommandList();
for(int idx = 0; idx < vctPendingNetworkCommandList.size(); ++idx) { for(int idx = 0; idx < vctPendingNetworkCommandList.size(); ++idx) {
@@ -529,20 +601,22 @@ void ServerInterface::update() {
this->requestCommand(&cmd); this->requestCommand(&cmd);
} }
connectionSlot->clearPendingNetworkCommandList(); connectionSlot->clearPendingNetworkCommandList();
//}
} }
} }
} }
} }
} SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #5\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
// Step #4 dispatch pending chat messages // Step #5 dispatch pending chat messages
for(int i= 0; i< GameConstants::maxPlayers; ++i) { for(int i= 0; i< GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot != NULL && if(connectionSlot != NULL &&
connectionSlot->getChatTextList().empty() == false) { connectionSlot->getChatTextList().empty() == false) {
try { try {
for(int chatIdx = 0; chatIdx < connectionSlot->getChatTextList().size(); chatIdx++) { for(int chatIdx = 0; slots[i] != NULL && chatIdx < connectionSlot->getChatTextList().size(); chatIdx++) {
connectionSlot= slots[i];
if(connectionSlot != NULL) {
ChatMsgInfo msg(connectionSlot->getChatTextList()[chatIdx]); ChatMsgInfo msg(connectionSlot->getChatTextList()[chatIdx]);
this->addChatInfo(msg); this->addChatInfo(msg);
@@ -557,6 +631,7 @@ void ServerInterface::update() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] after broadcast nmtText chatText [%s] chatSender [%s] chatTeamIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,newChatText.c_str(),newChatSender.c_str(),newChatTeamIndex); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] after broadcast nmtText chatText [%s] chatSender [%s] chatTeamIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,newChatText.c_str(),newChatSender.c_str(),newChatTeamIndex);
} }
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] i = %d\n",__FILE__,__FUNCTION__,__LINE__,i); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] i = %d\n",__FILE__,__FUNCTION__,__LINE__,i);
// Its possible that the slot is disconnected here // Its possible that the slot is disconnected here
@@ -573,50 +648,6 @@ void ServerInterface::update() {
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
//process text messages
/*
if(this->getChatTextList().empty() == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
for(int i= 0; i< GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot!= NULL &&
(gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true))) {
if( connectionSlot->isConnected() &&
socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true) {
if(connectionSlot->getSocket() != NULL) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] calling connectionSlot->getNextMessageType() for slots[i]->getSocket()->getSocketId() = %d\n",__FILE__,__FUNCTION__,connectionSlot->getSocket()->getSocketId());
try {
if(connectionSlot->getNextMessageType() == nmtText) {
NetworkMessageText networkMessageText;
if(connectionSlot->receiveMessage(&networkMessageText)) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 about to broadcast nmtText msg for SlotIndex# %d\n",__FILE__,__FUNCTION__,i);
broadcastMessage(&networkMessageText, i);
//chatText= networkMessageText.getText();
//chatSender= networkMessageText.getSender();
//chatTeamIndex= networkMessageText.getTeamIndex();
//break;
ChatMsgInfo msg(networkMessageText.getText().c_str(),networkMessageText.getSender().c_str(),networkMessageText.getTeamIndex());
this->addChatInfo(msg);
}
}
}
catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error detected [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
errorMsgList.push_back(ex.what());
}
}
}
}
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
*/
} }
} }
} }
@@ -990,12 +1021,12 @@ void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int
ConnectionSlot* connectionSlot = slots[i]; ConnectionSlot* connectionSlot = slots[i];
// New lag check // New lag check
std::pair<bool,bool> clientLagExceededOrWarned = std::make_pair(false,false); //std::pair<bool,bool> clientLagExceededOrWarned = std::make_pair(false,false);
if( gameHasBeenInitiated == true && connectionSlot != NULL && //if( gameHasBeenInitiated == true && connectionSlot != NULL &&
connectionSlot->isConnected() == true) { // connectionSlot->isConnected() == true) {
clientLagExceededOrWarned = clientLagCheck(connectionSlot); // clientLagExceededOrWarned = clientLagCheck(connectionSlot);
} //}
if(clientLagExceededOrWarned.first == false) { //if(clientLagExceededOrWarned.first == false) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] networkMessage = %p\n",__FILE__,__FUNCTION__,__LINE__,networkMessage); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] networkMessage = %p\n",__FILE__,__FUNCTION__,__LINE__,networkMessage);
ConnectionSlotEvent &event = eventList[i]; ConnectionSlotEvent &event = eventList[i];
@@ -1024,7 +1055,7 @@ void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
removeSlot(i); removeSlot(i);
} }
} //}
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
@@ -1064,12 +1095,12 @@ void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int
if(i != excludeSlot && connectionSlot != NULL) { if(i != excludeSlot && connectionSlot != NULL) {
// New lag check // New lag check
std::pair<bool,bool> clientLagExceededOrWarned = std::make_pair(false,false); //std::pair<bool,bool> clientLagExceededOrWarned = std::make_pair(false,false);
if( gameHasBeenInitiated == true && connectionSlot != NULL && //if( gameHasBeenInitiated == true && connectionSlot != NULL &&
connectionSlot->isConnected() == true) { // connectionSlot->isConnected() == true) {
clientLagExceededOrWarned = clientLagCheck(connectionSlot); // clientLagExceededOrWarned = clientLagCheck(connectionSlot);
} //}
if(clientLagExceededOrWarned.first == false) { //if(clientLagExceededOrWarned.first == false) {
if(connectionSlot->isConnected()) { if(connectionSlot->isConnected()) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] before sendMessage\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] before sendMessage\n",__FILE__,__FUNCTION__,__LINE__);
connectionSlot->sendMessage(networkMessage); connectionSlot->sendMessage(networkMessage);
@@ -1079,7 +1110,7 @@ void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,__LINE__,i); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,__LINE__,i);
removeSlot(i); removeSlot(i);
} }
} //}
} }
else if(i == excludeSlot && gameHasBeenInitiated == true && else if(i == excludeSlot && gameHasBeenInitiated == true &&
connectionSlot != NULL && connectionSlot->isConnected() == false) { connectionSlot != NULL && connectionSlot->isConnected() == false) {

View File

@@ -80,7 +80,7 @@ public:
virtual void slotUpdateTask(ConnectionSlotEvent *event); virtual void slotUpdateTask(ConnectionSlotEvent *event);
bool hasClientConnection(); bool hasClientConnection();
int getCurrentFrameCount() const { return currentFrameCount; } int getCurrentFrameCount() const { return currentFrameCount; }
std::pair<bool,bool> clientLagCheck(ConnectionSlot* connectionSlot); std::pair<bool,bool> clientLagCheck(ConnectionSlot* connectionSlot,bool skipNetworkBroadCast=false);
bool signalClientReceiveCommands(ConnectionSlot* connectionSlot, bool signalClientReceiveCommands(ConnectionSlot* connectionSlot,
int slotIndex, int slotIndex,

View File

@@ -91,7 +91,8 @@ std::string Command::toString() const {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__, __LINE__); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__, __LINE__);
if(unitType != NULL) { if(unitType != NULL) {
result += ", unitTypeId = " + intToStr(unitType->getId()) + ", unitTypeDesc = " + unitType->getReqDesc(); result += ", unitTypeId = " + intToStr(unitType->getId());
result += ", unitTypeDesc = " + unitType->getReqDesc();
} }
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__, __LINE__); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__, __LINE__);

View File

@@ -0,0 +1,117 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martio Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "element_type.h"
#include <cassert>
#include "resource_type.h"
#include "upgrade_type.h"
#include "unit_type.h"
#include "resource.h"
#include "tech_tree.h"
#include "logger.h"
#include "lang.h"
#include "renderer.h"
#include "leak_dumper.h"
using namespace Shared::Util;
namespace Glest{ namespace Game{
// =====================================================
// class DisplayableType
// =====================================================
DisplayableType::DisplayableType(){
image= NULL;
}
// =====================================================
// class RequirableType
// =====================================================
string RequirableType::getReqDesc() const{
bool anyReqs= false;
string reqString="";
for(int i=0; i<getUnitReqCount(); ++i){
if(getUnitReq(i) == NULL) {
throw runtime_error("getUnitReq(i) == NULL");
}
reqString+= getUnitReq(i)->getName();
reqString+= "\n";
anyReqs= true;
}
for(int i=0; i<getUpgradeReqCount(); ++i){
if(getUpgradeReq(i) == NULL) {
throw runtime_error("getUpgradeReq(i) == NULL");
}
reqString+= getUpgradeReq(i)->getName();
reqString+= "\n";
anyReqs= true;
}
string str= getName();
if(anyReqs){
return str + " " + Lang::getInstance().get("Reqs") + ":\n" + reqString;
}
else{
return str;
}
}
// =====================================================
// class ProducibleType
// =====================================================
ProducibleType::ProducibleType(){
cancelImage= NULL;
}
ProducibleType::~ProducibleType(){
}
const Resource *ProducibleType::getCost(const ResourceType *rt) const{
for(int i=0; i<costs.size(); ++i){
if(costs[i].getType()==rt){
return &costs[i];
}
}
return NULL;
}
string ProducibleType::getReqDesc() const{
string str= getName()+" "+Lang::getInstance().get("Reqs")+":\n";
for(int i=0; i<getCostCount(); ++i){
if(getCost(i)->getAmount()!=0){
str+= getCost(i)->getType()->getName();
str+= ": "+ intToStr(getCost(i)->getAmount());
str+= "\n";
}
}
for(int i=0; i<getUnitReqCount(); ++i){
str+= getUnitReq(i)->getName();
str+= "\n";
}
for(int i=0; i<getUpgradeReqCount(); ++i){
str+= getUpgradeReq(i)->getName();
str+= "\n";
}
return str;
}
}}//end namespace

View File

@@ -156,8 +156,10 @@ void World::init(Game *game, bool createUnits){
initSplattedTextures(); initSplattedTextures();
// must be done after initMap() // must be done after initMap()
if(gs->getPathFinderType() != pfBasic) {
routePlanner = new RoutePlanner(this); routePlanner = new RoutePlanner(this);
cartographer = new Cartographer(this); cartographer = new Cartographer(this);
}
unitUpdater.init(game); unitUpdater.init(game);
@@ -338,8 +340,10 @@ void World::tick(){
} }
} }
} }
if(cartographer != NULL) {
cartographer->tick(); cartographer->tick();
} }
}
Unit* World::findUnitById(int id){ Unit* World::findUnitById(int id){
for(int i= 0; i<getFactionCount(); ++i){ for(int i= 0; i<getFactionCount(); ++i){
@@ -785,8 +789,10 @@ void World::initUnits(){
} }
if (unit->getType()->hasSkillClass(scBeBuilt)) { if (unit->getType()->hasSkillClass(scBeBuilt)) {
map.flatternTerrain(unit); map.flatternTerrain(unit);
if(cartographer != NULL) {
cartographer->updateMapMetrics(unit->getPos(), unit->getType()->getSize()); cartographer->updateMapMetrics(unit->getPos(), unit->getType()->getSize());
} }
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unit created for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,unit->toString().c_str()); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unit created for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,unit->toString().c_str());
} }
} }

View File

@@ -98,6 +98,8 @@ protected:
time_t lastThreadedPing; time_t lastThreadedPing;
Mutex pingThreadAccessor; Mutex pingThreadAccessor;
Mutex dataSynchAccessor;
public: public:
Socket(PLATFORM_SOCKET sock); Socket(PLATFORM_SOCKET sock);
Socket(); Socket();

View File

@@ -788,8 +788,14 @@ void showCursor(bool b) {
if(b) { if(b) {
//SDL_GetMouseState( &x, &y ); //SDL_GetMouseState( &x, &y );
} }
int state = SDL_ShowCursor(SDL_QUERY);
if( (state == SDL_DISABLE && b == false) ||
(state == SDL_ENABLE && b == true)) {
return;
}
SDL_ShowCursor(b ? SDL_ENABLE : SDL_DISABLE); SDL_ShowCursor(b ? SDL_ENABLE : SDL_DISABLE);
SDL_WM_GrabInput(SDL_GRAB_OFF); //SDL_WM_GrabInput(SDL_GRAB_OFF);
if(b) { if(b) {
//SDL_WM_GrabInput(SDL_GRAB_OFF); //SDL_WM_GrabInput(SDL_GRAB_OFF);
//SDL_WarpMouse(x,y); //SDL_WarpMouse(x,y);

View File

@@ -827,7 +827,12 @@ bool Socket::hasDataToRead(std::map<PLATFORM_SOCKET,bool> &socketTriggeredList)
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
int retval = select(imaxsocket + 1, &rfds, NULL, NULL, &tv);
int retval = 0;
{
//MutexSafeWrapper safeMutex(&dataSynchAccessor);
retval = select(imaxsocket + 1, &rfds, NULL, NULL, &tv);
}
if(retval < 0) if(retval < 0)
{ {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] ERROR SELECTING SOCKET DATA retval = %d error = %s\n",__FILE__,__FUNCTION__,retval,getLastSocketErrorFormattedText().c_str()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] ERROR SELECTING SOCKET DATA retval = %d error = %s\n",__FILE__,__FUNCTION__,retval,getLastSocketErrorFormattedText().c_str());
@@ -884,7 +889,11 @@ bool Socket::hasDataToRead(PLATFORM_SOCKET socket)
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
int retval = select(socket + 1, &rfds, NULL, NULL, &tv); int retval = 0;
{
//MutexSafeWrapper safeMutex(&dataSynchAccessor);
retval = select(socket + 1, &rfds, NULL, NULL, &tv);
}
if(retval) if(retval)
{ {
if (FD_ISSET(socket, &rfds)) if (FD_ISSET(socket, &rfds))
@@ -933,6 +942,10 @@ int Socket::getDataToRead(bool wantImmediateReply) {
} }
else if(err == 0) else if(err == 0)
{ {
if(isConnected() == false) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] ERROR PEEKING SOCKET DATA, err = %d %s\n",__FILE__,__FUNCTION__,err,getLastSocketErrorFormattedText().c_str());
break;
}
//if(Socket::enableNetworkDebugInfo) printf("In [%s] ioctl returned = %d, size = %ld\n",__FUNCTION__,err,size); //if(Socket::enableNetworkDebugInfo) printf("In [%s] ioctl returned = %d, size = %ld\n",__FUNCTION__,err,size);
} }
@@ -962,6 +975,8 @@ int Socket::send(const void *data, int dataSize) {
ssize_t bytesSent= 0; ssize_t bytesSent= 0;
if(isSocketValid() == true) { if(isSocketValid() == true) {
errno = 0; errno = 0;
MutexSafeWrapper safeMutex(&dataSynchAccessor);
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0); bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
} }
@@ -985,6 +1000,7 @@ int Socket::send(const void *data, int dataSize) {
if(Socket::isWritable(true) == true) { if(Socket::isWritable(true) == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] attemptCount = %d, sock = %d, dataSize = %d, data = %p\n",__FILE__,__FUNCTION__,__LINE__,attemptCount,sock,dataSize,data); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] attemptCount = %d, sock = %d, dataSize = %d, data = %p\n",__FILE__,__FUNCTION__,__LINE__,attemptCount,sock,dataSize,data);
MutexSafeWrapper safeMutex(&dataSynchAccessor);
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0); bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 EAGAIN during send, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesSent); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 EAGAIN during send, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesSent);
@@ -1012,6 +1028,7 @@ int Socket::receive(void *data, int dataSize)
ssize_t bytesReceived = 0; ssize_t bytesReceived = 0;
if(isSocketValid() == true) { if(isSocketValid() == true) {
MutexSafeWrapper safeMutex(&dataSynchAccessor);
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0); bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
} }
if(bytesReceived < 0 && getLastSocketError() != PLATFORM_SOCKET_TRY_AGAIN) { if(bytesReceived < 0 && getLastSocketError() != PLATFORM_SOCKET_TRY_AGAIN) {
@@ -1024,6 +1041,7 @@ int Socket::receive(void *data, int dataSize)
time_t tStartTimer = time(NULL); time_t tStartTimer = time(NULL);
while((bytesReceived < 0 && getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) && (difftime(time(NULL),tStartTimer) <= 5)) { while((bytesReceived < 0 && getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) && (difftime(time(NULL),tStartTimer) <= 5)) {
if(Socket::isReadable() == true) { if(Socket::isReadable() == true) {
MutexSafeWrapper safeMutex(&dataSynchAccessor);
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0); bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 EAGAIN during receive, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesReceived); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 EAGAIN during receive, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesReceived);
@@ -1044,6 +1062,7 @@ int Socket::receive(void *data, int dataSize)
int Socket::peek(void *data, int dataSize){ int Socket::peek(void *data, int dataSize){
ssize_t err = 0; ssize_t err = 0;
if(isSocketValid() == true) { if(isSocketValid() == true) {
MutexSafeWrapper safeMutex(&dataSynchAccessor);
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK); err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
} }
if(err < 0 && getLastSocketError() != PLATFORM_SOCKET_TRY_AGAIN) { if(err < 0 && getLastSocketError() != PLATFORM_SOCKET_TRY_AGAIN) {
@@ -1058,6 +1077,7 @@ int Socket::peek(void *data, int dataSize){
time_t tStartTimer = time(NULL); time_t tStartTimer = time(NULL);
while((err < 0 && getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) && (difftime(time(NULL),tStartTimer) <= 5)) { while((err < 0 && getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) && (difftime(time(NULL),tStartTimer) <= 5)) {
if(Socket::isReadable() == true) { if(Socket::isReadable() == true) {
MutexSafeWrapper safeMutex(&dataSynchAccessor);
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK); err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 EAGAIN during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,err); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 EAGAIN during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,err);
@@ -1106,7 +1126,11 @@ bool Socket::isReadable() {
FD_ZERO(&set); FD_ZERO(&set);
FD_SET(sock, &set); FD_SET(sock, &set);
int i= select(sock+1, &set, NULL, NULL, &tv); int i = 0;
{
MutexSafeWrapper safeMutex(&dataSynchAccessor);
i= select(sock+1, &set, NULL, NULL, &tv);
}
if(i < 0) { if(i < 0) {
if(difftime(time(NULL),lastDebugEvent) >= 1) { if(difftime(time(NULL),lastDebugEvent) >= 1) {
lastDebugEvent = time(NULL); lastDebugEvent = time(NULL);
@@ -1137,7 +1161,11 @@ bool Socket::isWritable(bool waitOnDelayedResponse) {
bool result = false; bool result = false;
do do
{ {
int i = select(sock+1, NULL, &set, NULL, &tv); int i = 0;
{
MutexSafeWrapper safeMutex(&dataSynchAccessor);
i = select(sock+1, NULL, &set, NULL, &tv);
}
if(i < 0 ) { if(i < 0 ) {
if(difftime(time(NULL),lastDebugEvent) >= 1) { if(difftime(time(NULL),lastDebugEvent) >= 1) {
lastDebugEvent = time(NULL); lastDebugEvent = time(NULL);
@@ -1302,7 +1330,10 @@ void ClientSocket::connect(const Ip &ip, int port)
FD_ZERO(&myset); FD_ZERO(&myset);
FD_SET(sock, &myset); FD_SET(sock, &myset);
{
MutexSafeWrapper safeMutex(&dataSynchAccessor);
err = select(sock+1, NULL, &myset, NULL, &tv); err = select(sock+1, NULL, &myset, NULL, &tv);
}
if (err < 0 && getLastSocketError() != PLATFORM_SOCKET_INTERRUPTED) if (err < 0 && getLastSocketError() != PLATFORM_SOCKET_INTERRUPTED)
{ {