示例#1
0
void C4Playback::Strip() {
  // Strip what?
  const bool fStripPlayers = false;
  const bool fStripSyncChecks = false;
  const bool fStripDebugRec = true;
  const bool fCheckCheat = false;
  const bool fStripMessages = true;
  // const bool fCheckEMControl = true;
  const int32_t iEndFrame = -1;
  // Iterate over chunk list
  for (chunks_t::iterator i = chunks.begin(); i != chunks.end();) {
    // Strip rest of record?
    if (iEndFrame >= 0 && i->Frame > iEndFrame) {
      // Remove this and all remaining chunks
      while (i != chunks.end()) {
        i->Delete();
        i = chunks.erase(i);
      }
      // Push new End-Chunk
      C4RecordChunk EndChunk;
      EndChunk.Frame = iEndFrame;
      EndChunk.Type = RCT_End;
      chunks.push_back(EndChunk);
      // Done
      break;
    }
    switch (i->Type) {
      case RCT_Ctrl: {
        // Iterate over controls
        C4Control *pCtrl = i->pCtrl;
        for (C4IDPacket *pPkt = pCtrl->firstPkt(), *pNext; pPkt; pPkt = pNext) {
          pNext = pCtrl->nextPkt(pPkt);
          switch (pPkt->getPktType()) {
            // Player join: Strip player file (if possible)
            case CID_JoinPlr:
              if (fStripPlayers) {
                C4ControlJoinPlayer *pJoinPlr =
                    static_cast<C4ControlJoinPlayer *>(pPkt->getPkt());
                pJoinPlr->Strip();
              }
              break;
            // EM commands: May be cheats, so log them
            case CID_Script:
            case CID_EMMoveObj:
            case CID_EMDrawTool:
              if (fCheckCheat)
                Log(DecompileToBuf<StdCompilerINIWrite>(
                        mkNamingAdapt(*pPkt, FormatString("Frame %d", i->Frame)
                                                 .getData())).getData());
              break;
            // Strip sync check
            case CID_SyncCheck:
              if (fStripSyncChecks) {
                i->pCtrl->Remove(pPkt);
              }
              break;
          }
        }
        // Strip empty control lists (always)
        if (!pCtrl->firstPkt()) {
          i->Delete();
          i = chunks.erase(i);
        } else
          i++;
      } break;
      case RCT_CtrlPkt: {
        bool fStripThis = false;
        switch (i->pPkt->getPktType()) {
          // EM commands: May be cheats, so log them
          case CID_Script:
          case CID_EMMoveObj:
          case CID_EMDrawTool:
            if (fCheckCheat)
              Log(DecompileToBuf<StdCompilerINIWrite>(
                      mkNamingAdapt(*i->pPkt, FormatString("Frame %d", i->Frame)
                                                  .getData())).getData());
            break;
          // Strip some stuff
          case CID_SyncCheck:
            if (fStripSyncChecks) fStripThis = true;
            break;
          case CID_Message:
            if (fStripMessages) fStripThis = true;
            break;
        }
        if (fStripThis) {
          i->Delete();
          i = chunks.erase(i);
        } else
          i++;
      } break;
      case RCT_End:
        i++;
        break;
      default:
        // Strip debugrec
        if (fStripDebugRec) {
          i->Delete();
          i = chunks.erase(i);
        } else
          i++;
    }
  }
}
示例#2
0
bool C4Network2IO::HandlePacket(const C4NetIOPacket &rPacket, C4Network2IOConnection *pConn, bool fThread)
{
    // security: add connection reference
    if (!pConn) return false;
    pConn->AddRef();

    // accept only PID_Conn and PID_Ping on non-accepted connections
    if(!pConn->isHalfAccepted())
        if(rPacket.getStatus() != PID_Conn && rPacket.getStatus() != PID_Ping && rPacket.getStatus() != PID_ConnRe)
            return false;

    // unpack packet (yet another no-idea-why-it's-needed-cast)
    C4IDPacket Pkt;
    C4PacketBase &PktB = Pkt;
    try
    {
        PktB.unpack(rPacket);
    }
    catch (StdCompiler::Exception *pExc)
    {
        Application.InteractiveThread.ThreadLog("Network: error: Failed to unpack packet id %02x: %s", rPacket.getStatus(), pExc->Msg.getData());
        delete pExc;
#ifndef _DEBUG
        pConn->Close();
#endif
        return false;
    }

    // dump packet (network thread only)
#if(C4NET2IO_DUMP_LEVEL > 0)
    if (Config.Network.PacketLogging && fThread && Pkt.getPktType() != PID_Ping && Pkt.getPktType() != PID_Pong && Pkt.getPktType() != PID_NetResData)
    {
        // StdStrBuf PacketDump = DecompileToBuf<StdCompilerINIWrite>(mkNamingAdaptrPacket);
        StdStrBuf PacketHeader = FormatString("HandlePacket: %s by %s:%d (%lu bytes, counter %d)",
                                              C4TimeMilliseconds::Now().AsString().getData(),
                                              inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port),
                                              static_cast<unsigned long>(rPacket.getSize()), pConn->getInPacketCounter());
        StdStrBuf Dump = DecompileToBuf<StdCompilerINIWrite>(mkNamingAdapt(Pkt, PacketHeader.getData()));
        // Put it directly. The standard functions behind StdBuf.Format seem to choke when you pass them too much data.
        Application.InteractiveThread.PushEvent(Ev_LogSilent, Dump.GrabPointer());
    }
#endif

    // search packet handling data
    bool fSendToMainThread = false, fHandled = false;
    for (const C4PktHandlingData *pHData = PktHandlingData; pHData->ID != PID_None; pHData++)
        if (pHData->ID == rPacket.getStatus())
        {
            // correct thread?
            if (!pHData->ProcByThread == !fThread)
            {
                // connection accepted?
                if (pHData->AcceptedOnly || pConn->isAccepted() || pConn->isClosed())
                {
                    fHandled = true;
#if(C4NET2IO_DUMP_LEVEL > 2)
                    C4TimeMilliseconds tStart = C4TimeMilliseconds::Now();
#endif

                    // call handler(s)
                    CallHandlers(pHData->HandlerID, &Pkt, pConn, fThread);

#if(C4NET2IO_DUMP_LEVEL > 2)
                    uint32_t iBlockedTime = C4TimeMilliseconds::Now() - tStart;
                    if (fThread && iBlockedTime > 100)
                    {
                        Application.InteractiveThread.ThreadLogS("HandlePacket: ... blocked for %u ms!", iBlockedTime);
                    }
#endif

                }
            }
            // transfer to main thread?
            else if (!pHData->ProcByThread && fThread)
            {
                fHandled = true;
                fSendToMainThread = true;
            }
        }

    // send to main thread?
    if (fSendToMainThread)
    {
        // create data
        NetEvPacketData *pEvData = new NetEvPacketData;
        pEvData->Packet.Take(rPacket.Duplicate());
        pEvData->Conn = pConn;
        pConn->AddRef();
        // trigger event
        if (!Application.InteractiveThread.PushEvent(Ev_Net_Packet, pEvData))
            Application.InteractiveThread.ThreadLogS("...push event ");
    }

    // unhandled?
    if (!fHandled && !pConn->isClosed())
        Application.InteractiveThread.ThreadLog("Network: Unhandled packet (status %02x)", rPacket.getStatus());

    // remove connection reference
    pConn->DelRef();
    return fHandled;
}