void C4Network2IRCClient::PackPacket(const C4NetIOPacket &rPacket, StdBuf &rOutBuf) { // Enlarge buffer int iSize = rPacket.getSize(), iPos = rOutBuf.getSize(); rOutBuf.Grow(iSize + 2); // Write packet rOutBuf.Write(rPacket, iPos); // Terminate uint8_t *pPos = getMBufPtr<uint8_t>(rOutBuf, iPos + iSize); *pPos = '\r'; *(pPos + 1) = '\n'; }
StdBuf C4Playback::ReWriteBinary() { const int OUTPUT_GROW = 16 * 1024; StdBuf Output; int iPos = 0; bool fFinished = false; uint32_t iFrame = 0; for (chunks_t::const_iterator i = chunks.begin(); !fFinished && i != chunks.end(); i++) { // Check frame difference if (i->Frame - iFrame < 0 || i->Frame - iFrame > 0xff) LogF( "ERROR: Invalid frame difference between chunks (0-255 allowed)! " "Data will be invalid!"); // Pack data StdBuf Chunk; try { switch (i->Type) { case RCT_Ctrl: Chunk = DecompileToBuf<StdCompilerBinWrite>(*i->pCtrl); break; case RCT_CtrlPkt: Chunk = DecompileToBuf<StdCompilerBinWrite>(*i->pPkt); break; case RCT_End: fFinished = true; break; default: // debugrec if (i->pDbg) Chunk = DecompileToBuf<StdCompilerBinWrite>(*i->pDbg); break; } } catch (StdCompiler::Exception *pEx) { LogF("Record: Binary unpack error: %s", pEx->Msg.getData()); delete pEx; return StdBuf(); } // Grow output while (Output.getSize() - iPos < sizeof(C4RecordChunkHead) + Chunk.getSize()) Output.Grow(OUTPUT_GROW); // Write header C4RecordChunkHead *pHead = getMBufPtr<C4RecordChunkHead>(Output, iPos); pHead->Type = i->Type; pHead->iFrm = i->Frame - iFrame; iPos += sizeof(C4RecordChunkHead); iFrame = i->Frame; // Write chunk Output.Write(Chunk, iPos); iPos += Chunk.getSize(); } Output.SetSize(iPos); return Output; }
bool C4Playback::StreamToRecord(const char *szStream, StdStrBuf *pRecordFile) { // Load data StdBuf CompressedData; Log("Reading stream..."); if (!CompressedData.LoadFromFile(szStream)) return false; // Decompress unsigned long iStreamSize = CompressedData.getSize() * 5; StdBuf StreamData; StreamData.New(iStreamSize); while (true) { // Initialize stream z_stream strm; ZeroMem(&strm, sizeof strm); strm.next_in = getMBufPtr<BYTE>(CompressedData); strm.avail_in = CompressedData.getSize(); strm.next_out = getMBufPtr<BYTE>(StreamData); strm.avail_out = StreamData.getSize(); // Decompress if (inflateInit(&strm) != Z_OK) return false; int ret = inflate(&strm, Z_FINISH); if (ret == Z_STREAM_END) { inflateEnd(&strm); break; } if (ret != Z_BUF_ERROR) return false; // All input consumed? iStreamSize = strm.total_out; if (strm.avail_in == 0) { Log("Stream data incomplete, using as much data as possible"); break; } // Larger buffer needed StreamData.Grow(CompressedData.getSize()); iStreamSize = StreamData.getSize(); } StreamData.SetSize(iStreamSize); // Parse C4Playback Playback; Playback.ReadBinary(StreamData); LogF("Got %d chunks from stream", Playback.chunks.size()); // Get first chunk, which must contain the initial chunks_t::iterator chunkIter = Playback.chunks.begin(); if (chunkIter == Playback.chunks.end() || chunkIter->Type != RCT_File) return false; // Get initial chunk, go over file name StdBuf InitialData = *chunkIter->pFileData; const char *szInitialFilename = chunkIter->Filename.getData(); // Put to temporary file and unpack char szInitial[_MAX_PATH + 1] = "~initial.tmp"; MakeTempFilename(szInitial); if (!InitialData.SaveToFile(szInitial) || !C4Group_UnpackDirectory(szInitial)) return false; // Load Scenario.txt from Initial C4Group Grp; C4Scenario Initial; if (!Grp.Open(szInitial) || !Initial.Load(Grp) || !Grp.Close()) return false; // Copy original scenario const char *szOrigin = Initial.Head.Origin.getData(); char szRecord[_MAX_PATH + 1]; SCopy(szStream, szRecord, _MAX_PATH); if (GetExtension(szRecord)) *(GetExtension(szRecord) - 1) = 0; SAppend(".c4s", szRecord, _MAX_PATH); LogF("Original scenario is %s, creating %s.", szOrigin, szRecord); if (!C4Group_CopyItem(szOrigin, szRecord, false, false)) return false; // Merge initial if (!Grp.Open(szRecord) || !Grp.Merge(szInitial)) return false; // Process other files in stream chunkIter->Delete(); chunkIter = Playback.chunks.erase(chunkIter); while (chunkIter != Playback.chunks.end()) if (chunkIter->Type == RCT_File) { LogF("Inserting %s...", chunkIter->Filename.getData()); StdStrBuf Temp; Temp.Copy(chunkIter->Filename); MakeTempFilename(&Temp); if (!chunkIter->pFileData->SaveToFile(Temp.getData())) return false; if (!Grp.Move(Temp.getData(), chunkIter->Filename.getData())) return false; chunkIter = Playback.chunks.erase(chunkIter); } else chunkIter++; // Write record data StdBuf RecordData = Playback.ReWriteBinary(); if (!Grp.Add(C4CFN_CtrlRec, RecordData, false, true)) return false; // Done Log("Writing record file..."); Grp.Close(); pRecordFile->Copy(szRecord); return true; }