Exemple #1
0
//
// 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;
}
Exemple #3
0
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;
}