//------------------------------------------------------------------------------------------------------------------------------------ bool __stdcall spiSend(DWORD addrCount, SOCKADDR * *addrList, char *buf, DWORD bufLen) { // DropMessage(0, "spiSend %d", GetCurrentThreadId()); if(!addrCount) return true; if(addrCount > 1) DropMessage(1, "spiSend, multicast not supported"); try { // support for 1 peer for now SOCKADDR him = *(addrList[0]); // send packet over the network module pluggedNetwork->sendAsyn(him, Util::MemoryFrame(buf, bufLen)); // debug // DropMessage(0, "Sent storm packet %d bytes", bufLen); // DropMessage(0, "S> %s", sprintfBytes(buf, bufLen)); } catch(GeneralException &e) { DropLastError("spiSend failed: %s", e.getMessage()); return false; } return true; }
//------------------------------------------------------------------------------------------------------------------------------------ void LocalPC::processIncomingPackets() { INTERLOCKED; try { // mark our slot shd->peer[self].lastOccupied = GetTickCount(); // pass all packets to storm int incomingCount = shd->peer[self].incomingCount; if(incomingCount > 16) incomingCount = 16; for(int i = 0; i < shd->peer[self].incomingCount; i++) { Packet &packet = shd->peer[self].incoming[i]; passPacket(packet.sender, Util::MemoryFrame(packet.data, packet.length)); } // clear incoming queue shd->peer[self].incomingCount = 0; } catch(GeneralException &e) { DropLastError("processIncomingPackets failed: %s", e.getMessage()); } }
//------------------------------------------------------------------------------------------------------------------------------------ bool __stdcall spiInitialize( client_info *gameClientInfo, user_info *userData, battle_info *bnCallbacks, module_info *moduleData, HANDLE hEvent) { // Called when the module is loaded // DropMessage(0, "spiInitialize"); fatalError = false; gameAppInfo = *gameClientInfo; receiveEvent = hEvent; critSec.init(); try { pluggedNetwork->initialize(); } catch(GeneralException &e) { fatalError = true; DropLastError(__FUNCTION__ " unhandled exception: %s", e.getMessage()); return false; } return true; }
//------------------------------------------------------------------------------------------------------------------------------------ bool __stdcall spiReceive(SOCKADDR **senderPeer, char **data, DWORD *databytes) { INTERLOCKED; // DropMessage(0, "spiReceive %d", GetCurrentThreadId()); // Passes pointers from queued receive data to storm *senderPeer = nullptr; *data = nullptr; *databytes = 0; try { pluggedNetwork->receive(); while(true) { // check if packets available if(incomingGamePackets.empty()) { SErrSetLastError(STORM_ERROR_NO_MESSAGES_WAITING); return false; } // save the packet before removing it from queue GamePacket *loan = new GamePacket(); *loan = incomingGamePackets.front(); incomingGamePackets.pop(); // paket outdated? if(GetTickCount() > loan->timeStamp + 10000) { DropMessage(1, "Dropped outdated packet (%dms delay)", GetTickCount() - loan->timeStamp); continue; } // give saved data to storm *senderPeer =&loan->sender; *data = loan->data; *databytes = loan->packetSize; // DropMessage(0, "R %s", sprintfBytes(*data, *databytes)); // DropMessage(0, "Received storm packet %d bytes", *databytes); break; } } catch(GeneralException &e) { DropLastError("spiLockGameList failed: %s", e.getMessage()); return false; } return true; }
//------------------------------------------------------------------------------------------------------------------------------------ bool __stdcall spiDestroy() { // called when you leave back to the network module selection menu // DropMessage(0, "spiDestroy"); try { pluggedNetwork->destroy(); } catch(GeneralException &e) { fatalError = true; DropLastError(__FUNCTION__ " unhandled exception: %s", e.getMessage()); return false; } return true; }
bool __stdcall spiUnlockGameList(game *pGameList, DWORD *a2) { // when storm is done reading from the gamelist // DropMessage(0, "spiUnlockGameList"); // release critical section delete critSecExLock; critSecExLock = NULL; try { pluggedNetwork->requestAds(); } catch(GeneralException &e) { fatalError = true; DropLastError(__FUNCTION__ " unhandled exception: %s", e.getMessage()); return false; } /* // Unlocks the game list and makes requests to update the list internally if ( pGameList != gpMGameList ) { SetLastError(ERROR_INVALID_PARAMETER); return false; } LeaveCriticalSection(&gCrit); if ( a2 ) *a2 = 300; DWORD dwThisTickCount = GetTickCount(); if ( dwThisTickCount - gdwLastTickCount > 200 ) { gdwLastTickCount = dwThisTickCount; BroadcastGameListRequest(); } */ return true; }
//------------------------------------------------------------------------------------------------------------------------------------ bool __stdcall spiLockGameList(int a1, int a2, game **ppGameList) { critSecExLock = new CriticalSection::Lock(critSec); // Strom locks the game list to access it // DropMessage(0, "spiLockGameList"); // interlink gamelist entries (for storm) AdFile *lastAd = nullptr; for ( auto &it : gameList) { it.gameInfo.pExtra = it.extraBytes; if ( lastAd ) lastAd->gameInfo.pNext = &it.gameInfo; lastAd = ⁢ } if(lastAd) lastAd->gameInfo.pNext = nullptr; // remove outdated entries //std::list<AdFile>::iterator nextAd = gameList.begin(); //std::list<AdFile>::iterator currAd; auto currAd = gameList.begin(); while ( currAd != gameList.end() ) { if(GetTickCount() > currAd->gameInfo.dwTimer + 2000) { // outdated, remove currAd = gameList.erase(currAd); } else // otherwise continue { ++currAd; } } try { // return game list *ppGameList = nullptr; if ( !gameList.empty() ) *ppGameList = &gameList.begin()->gameInfo; } catch(GeneralException &e) { fatalError = true; DropLastError(__FUNCTION__ " unhandled exception: %s", e.getMessage()); return false; } /* if ( !ppGameList ) { SetLastError(ERROR_INVALID_PARAMETER); return false; } // ClearGameList func embedded EnterCriticalSection(&gCrit); if ( gpMGameList ) { DWORD dwThisTickCount = GetTickCount(); volatile gameStruc **g = &gpMGameList; while ( *g ) { volatile gameStruc *t = *g; if ( dwThisTickCount - (*g)->dwTimer <= dwTimeout ) { g = (volatile gameStruc**)&t->pNext; } else { *g = t->pNext; if ( t->pExtra ) SMFree(t->pExtra); SMFree((void*)t); } } } LeaveCriticalSection(&gCrit); EnterCriticalSection(&gCrit); *ppGameList = (gameStruc*)gpMGameList; */ return true; }