// // Process SDL msgs to send and recv state // bool plSDLModifier::MsgReceive(plMessage* msg) { plSDLModifierMsg* sdlMsg = plSDLModifierMsg::ConvertNoRef(msg); if (sdlMsg && !sdlMsg->GetSDLName().CompareI(GetSDLName())) { uint32_t sendFlags = IApplyModFlags(sdlMsg->GetFlags()); if (!fSentOrRecvdState) sendFlags |= plSynchedObject::kNewState; if (sdlMsg->GetAction()==plSDLModifierMsg::kSendToServer) { // local player is changing the state and sending it out plStateChangeNotifier::SetCurrentPlayerID(plNetClientApp::GetInstance()->GetPlayerID()); SendState(sendFlags); } else if (sdlMsg->GetAction()==plSDLModifierMsg::kSendToServerAndClients) { // local player is changing the state and sending it out plStateChangeNotifier::SetCurrentPlayerID(plNetClientApp::GetInstance()->GetPlayerID()); SendState(sendFlags | plSynchedObject::kBCastToClients); } else if (sdlMsg->GetAction()==plSDLModifierMsg::kRecv) { plStateDataRecord* sdRec=sdlMsg->GetState(); plStateChangeNotifier::SetCurrentPlayerID(sdlMsg->GetPlayerID()); // remote player changed the state ReceiveState(sdRec); } return true; // consumed } return plSingleModifier::MsgReceive(msg); }
int32 PacketTunnelIOGateway :: DoInputImplementation(AbstractGatewayMessageReceiver & receiver, uint32 maxBytes) { if (_inputPacketBuffer.SetNumBytes(_maxTransferUnit, false) != B_NO_ERROR) return -1; bool firstTime = true; uint32 totalBytesRead = 0; while((totalBytesRead < maxBytes)&&((firstTime)||(IsSuggestedTimeSliceExpired() == false))) { firstTime = false; int32 bytesRead = GetDataIO()()->Read(_inputPacketBuffer.GetBuffer(), _inputPacketBuffer.GetNumBytes()); //printf(" READ " INT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC " bytes\n", bytesRead, _inputPacketBuffer.GetNumBytes()); if (bytesRead > 0) { totalBytesRead += bytesRead; IPAddressAndPort fromIAP; const PacketDataIO * packetIO = dynamic_cast<PacketDataIO *>(GetDataIO()()); if (packetIO) fromIAP = packetIO->GetSourceOfLastReadPacket(); const uint8 * p = (const uint8 *) _inputPacketBuffer.GetBuffer(); if ((_allowMiscData)&&((bytesRead < (int32)FRAGMENT_HEADER_SIZE)||(((uint32)B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(p))) != _magic))) { // If we're allowed to handle miscellaneous data, we'll just pass it on through verbatim ByteBuffer temp; temp.AdoptBuffer(bytesRead, const_cast<uint8 *>(p)); HandleIncomingMessage(receiver, ByteBufferRef(&temp, false), fromIAP); (void) temp.ReleaseBuffer(); } else { const uint8 * invalidByte = p+bytesRead; while(invalidByte-p >= (int32)FRAGMENT_HEADER_SIZE) { const uint32 magic = B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(&p[0*sizeof(uint32)])); const uint32 sexID = B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(&p[1*sizeof(uint32)])); const uint32 messageID = B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(&p[2*sizeof(uint32)])); const uint32 offset = B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(&p[3*sizeof(uint32)])); const uint32 chunkSize = B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(&p[4*sizeof(uint32)])); const uint32 totalSize = B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(&p[5*sizeof(uint32)])); //printf(" PARSE magic=" UINT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC " sex=" UINT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC " messageID=" UINT32_FORMAT_SPEC " offset=" UINT32_FORMAT_SPEC " chunkSize=" UINT32_FORMAT_SPEC " totalSize=" UINT32_FORMAT_SPEC "\n", magic, _magic, sexID, _sexID, messageID, offset, chunkSize, totalSize); p += FRAGMENT_HEADER_SIZE; if ((magic == _magic)&&((_sexID == 0)||(_sexID != sexID))&&((invalidByte-p >= (int32)chunkSize)&&(totalSize <= _maxIncomingMessageSize))) { ReceiveState * rs = _receiveStates.Get(fromIAP); if (rs == NULL) { if (offset == 0) rs = _receiveStates.PutAndGet(fromIAP, ReceiveState(messageID)); if (rs) { rs->_buf = GetByteBufferFromPool(totalSize); if (rs->_buf() == NULL) { _receiveStates.Remove(fromIAP); rs = NULL; } } } if (rs) { if ((offset == 0)||(messageID != rs->_messageID)) { // A new message... start receiving it (but only if we are starting at the beginning) rs->_messageID = messageID; rs->_offset = 0; rs->_buf()->SetNumBytes(totalSize, false); } uint32 rsSize = rs->_buf()->GetNumBytes(); //printf(" CHECK: offset=" UINT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC " %s\n", offset, rs->_offset, (offset==rs->_offset)?"":"DISCONTINUITY!!!"); if ((messageID == rs->_messageID)&&(totalSize == rsSize)&&(offset == rs->_offset)&&(offset+chunkSize <= rsSize)) { memcpy(rs->_buf()->GetBuffer()+offset, p, chunkSize); rs->_offset += chunkSize; if (rs->_offset == rsSize) { HandleIncomingMessage(receiver, rs->_buf, fromIAP); rs->_offset = 0; rs->_buf()->Clear(rsSize > MAX_CACHE_SIZE); } } else { LogTime(MUSCLE_LOG_DEBUG, "Unknown fragment (" UINT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC ") received from %s, ignoring it.\n", messageID, offset, chunkSize, totalSize, fromIAP.ToString()()); rs->_offset = 0; rs->_buf()->Clear(rsSize > MAX_CACHE_SIZE); } } p += chunkSize; } else break; } } } else if (bytesRead < 0) return -1; else break; } return totalBytesRead; }
void MULTIPLAY::Update(double inc) { if (MP_DBGDEEP) cout << "multiplay update" << endl; //create packet arrays if necessary int i; for (i = 0; i < NumConnected() + 1; i++) { if (packetarrays[i] == NULL) { packetarrays[i] = new REPLAY_PACKET [PACKET_ARRAY_SIZE]; } } if (MP_DBGDEEP) cout << "packet mem allocated" << endl; bool oldc = Connected(); net.Update(); if (!oldc && Connected()) { //wasn't connected before, connected now. if (Server()) remote_players++; ExchangeWorldInfo(); int i; for (i = 0; i < MAX_PLAYERS; i++) { timeindex[i] = 0.0; loadstates[i].time = 0.0; loadstatenow[i] = false; numpackets[i] = 0; //packetarraytime[i] = 0.0; nooptime[i] = 0; noopvalid[i] = false; tickthisframe[i] = false; nooptick[i] = false; } dbgnumstates = 0; dbgnumpackets = 0; mq1.Clear(); mq1.AddMessage("A client successfully connected"); } if (MP_DBGDEEP) cout << "net updated" << endl; //read incoming data /*if (Connected() && net.NumBufferedPackets() > 0) { int i; for (i = 0; i < net.GetMaxBuffers(); i++) { if (net.GetBuffer(i)->Valid()) ProcessPacket(net.GetBuffer(i)); } }*/ if (Connected()) { if (!MP_DISABLEGET) { ReceiveState(); if (MP_DBGDEEP) cout << "state receive" << endl; ReceivePacketArray(); if (MP_DBGDEEP) cout << "packet array receive" << endl; } if (!MP_DISABLEFUNCUPDATE) { double tval = 0; string ticktype = "packet array"; nooptick[1] = false; if (PacketArrayValid(1)) tval = GetPacketArrayTime(1); if (noopvalid[1] && nooptime[1] > tval) { tval = nooptime[1]; ticktype = "noop"; nooptick[1] = true; } if ((noopvalid[1] || PacketArrayValid(1)) && timeindex[1] < tval + PACKET_ARRAY_FREQUENCY - FrameTime()/2.0) { tickthisframe[1] = true; /*int nextpacket = curpackets[1]; if (nextpacket >= numpackets[1]) nextpacket = numpackets[1] - 1; if (ticktype == "packet array") cout << "ticking " << ticktype << ": " << GetFuncMem(1)[GetPacketArray(1)[nextpacket].chardata[CHAR_FUNCNUM]].func_name << " " << curpackets[1] << "/" << numpackets[1] << " packets for " << tval << " at " << timeindex[1] << endl; else cout << "ticking " << ticktype << " for " << tval << " at " << timeindex[1] << endl;*/ timeindex[1] += inc; //process packet data into the function memory (which is then given to DoOp by vamosworld) //if (PacketArrayValid(1))// && !(ticktype == "noop")) int i; for (i = 0; i < fnums[1]; i++) { if (!GetFuncMem(1)[i].held && GetFuncMem(1)[i].active) GetFuncMem(1)[i].active = false; } UpdateFuncmem(1); } else { tickthisframe[1] = false; //cout << "not ticking at " << timeindex[1] << endl; } } if (MP_DBGDEEP) cout << "ticked" << endl; //check to see if we need to increment /*for (i = 0; i < NumConnected(); i++) { if (loadstatevalid[i+1] && timeindex[i+1] < loadstates[i+1].time + STATE_FREQUENCY + FrameTime()/2.0) { timeindex[i+1] += inc; } }*/ //if (packetarrayvalid[1] && timeindex[1] < loadstates[1].time + STATE_FREQUENCY - FrameTime()/2.0) } //cout << "Latency: " << GetLatency(1) << " (" << timeindex[0] << "-" << timeindex[1] << ")" << endl; //disconnect if the latency is super high if (GetLatency(1) > CLIENT_DISCONNECT_TIMEOUT) { Disconnect(); } //update statistics UpdateStats(); if (MP_DBGDEEP) cout << "multiplay update done" << endl; }