#include "fiko/orkestra/dosya_transfer.hpp" #include "fiko/orkestra/protokol.hpp" namespace fiko::orkestra { uint64_t dosyaHash(const std::string& veri) { uint64_t h = 1469598103934665603ull; // FNV-1a 64 for (unsigned char c : veri) { h ^= c; h *= 1099511628211ull; } return h; } namespace dosyaproto { constexpr uint16_t PARCA_SURUM = 1; std::string parcaSerialize(const DosyaParcaGovde& p) { std::string s; surecproto::yazU16(s, PARCA_SURUM); surecproto::yazU64(s, p.transferId); surecproto::yazU32(s, p.sira); surecproto::yazU32(s, p.toplamParca); surecproto::yazU64(s, p.hash); surecproto::yazU32(s, (uint32_t)p.veri.size()); s.append(p.veri); return s; } bool parcaCoz(const std::string& govde, DosyaParcaGovde& out) { const char* p = govde.data(); const char* son = p + govde.size(); if (son - p < 2 + 8 + 4 + 4 + 8 + 4) return false; p += 2; out.transferId = surecproto::okuU64(p); p += 8; out.sira = surecproto::okuU32(p); p += 4; out.toplamParca = surecproto::okuU32(p); p += 4; out.hash = surecproto::okuU64(p); p += 8; const uint32_t vl = surecproto::okuU32(p); p += 4; if ((size_t)(son - p) < vl) return false; // eksik veri → reddet out.veri.assign(p, vl); if (out.transferId == 0 || out.toplamParca == 0 || out.sira >= out.toplamParca) return false; // geçersiz meta return true; } } // namespace dosyaproto std::vector dosyayiParcala(uint64_t transferId, const std::string& icerik, size_t parcaBoy) { if (parcaBoy == 0 || parcaBoy > icerik.size()) parcaBoy = icerik.size() ? icerik.size() : 1; const uint64_t h = dosyaHash(icerik); const uint32_t toplam = (uint32_t)((icerik.size() + parcaBoy - 1) / parcaBoy); std::vector ps; ps.reserve(toplam ? toplam : 1); for (uint32_t i = 0; i < toplam; ++i) { DosyaParcaGovde p; p.transferId = transferId; p.sira = i; p.toplamParca = toplam; p.hash = h; p.veri = icerik.substr((size_t)i * parcaBoy, parcaBoy); ps.push_back(std::move(p)); } if (ps.empty()) { // boş dosya → tek boş parça (transfer yine tamamlanır) DosyaParcaGovde p; p.transferId = transferId; p.toplamParca = 1; p.hash = h; ps.push_back(std::move(p)); } return ps; } ParcaBirlestirici::Sonuc ParcaBirlestirici::ekle(const DosyaParcaGovde& p) { if (toplam_ == 0) { // ilk parça → transfer başlat transferId_ = p.transferId; toplam_ = p.toplamParca; beklenenHash_ = p.hash; geldi_.assign(toplam_, false); parcalar_.assign(toplam_, std::string{}); } // Tutarlılık: aynı transfer + toplam + aralık içinde. if (p.transferId != transferId_ || p.toplamParca != toplam_ || p.sira >= toplam_) return Sonuc::Bekliyor; if (geldi_[p.sira]) return Sonuc::Bekliyor; // mükerrer → yok say geldi_[p.sira] = true; parcalar_[p.sira] = p.veri; ++alinan_; if (p.hash) beklenenHash_ = p.hash; // hash son parçada gelir (ilk 0 olabilir) if (alinan_ < toplam_) return Sonuc::Bekliyor; // Tamamlandı → birleştir + doğrula. icerik_.clear(); for (auto& parca : parcalar_) icerik_ += parca; return dosyaHash(icerik_) == beklenenHash_ ? Sonuc::Tamam : Sonuc::HashHatasi; } } // namespace fiko::orkestra