#include "orkestra_kule.hpp" #include #include #include #include "fiko/cekirdek/gecici.hpp" #include "fiko/cekirdek/olay.hpp" #include "fiko/cekirdek/surum.hpp" #include "surec_kopru.hpp" namespace fiko { // App-global kule (bkz. orkestra_kule.hpp extern) — belge penceresi drain'i besler, // panel node şeridi okur. OrkestraKule g_orkestraKule; void OrkestraKule::tik(SurecKopru& kopru, OlayGunlugu& olaylar, uint32_t aktifGorev, bool aktif, uint64_t simdiMs) { if (!aktif) return; if (sonTikMs_ && simdiMs - sonTikMs_ < orkestraTazelemeMs()) return; sonTikMs_ = simdiMs; if (!kuruldu_) { kuruldu_ = true; char ad[MAX_COMPUTERNAME_LENGTH + 1] = {}; DWORD n = (DWORD)sizeof(ad); makineAd_ = GetComputerNameA(ad, &n) ? std::string(ad, n) : std::string("yerel"); yerelNodeId_ = orkestraNodeId(makineAd_); // Defter diff'leri → merkezi olay akışı (makro/plugin/lisans aynı nehirden görür). OlayGunlugu* g = &olaylar; defter_.katildi = [g](const orkestra::NodeBilgi& nb) { g->yayinla(NodeKatildi{nb.nodeId}, nb.ad.c_str()); }; defter_.ayrildi = [g](const orkestra::NodeBilgi& nb) { g->yayinla(NodeAyrildi{nb.nodeId}, nb.ad.c_str()); }; defter_.durumDegisti = [g](const orkestra::NodeBilgi& nb, orkestra::NodeDurum eski) { g->yayinla(NodeDurumDegisti{nb.nodeId, (u32)nb.durum, (u32)eski}, orkestra::nodeDurumAdi(nb.durum)); }; } defter_.esikAyarla(orkestraYanitsizEsikMs(), orkestraOfflineEsikMs()); const orkestra::NodeBilgi yerelIlan = yerelIlanKur( yerelNodeId_, makineAd_, SURUM_METIN, (uint32_t)kopru.surecler().size(), aktifGorev); defter_.ilanIsle(yerelIlan, simdiMs); defter_.aktifTaskAyarla(yerelNodeId_, aktifGorev); // Eşleştirme: bekleyen istekleri süz + eşli node'ları doğrulanmış işaretle. orkestra::EslesmeYonetici& esl = eslesmeKur(); if (sonEslesmeTemizMs_ == 0 || simdiMs - sonEslesmeTemizMs_ >= 1000) { sonEslesmeTemizMs_ = simdiMs; esl.temizle(simdiMs, orkestraEslesmeTtlSn() * 1000); } for (const auto& n : defter_.liste()) if (n.nodeId != yerelNodeId_) defter_.dogrulanmisAyarla(n.nodeId, esl.esliMi(n.nodeId)); if (sonMetrikMs_ == 0 || simdiMs - sonMetrikMs_ >= orkestraMetrikAralikMs()) { sonMetrikMs_ = simdiMs; orkestra::NodeMetrikOzet m; if (metrik_.topla(m)) { defter_.metrikIsle(yerelNodeId_, m, simdiMs); sonMetrikDeger_ = m; // LAN yayını beacon throttle'ında bunu kullanır metrikHazir_ = true; } } lanTik(yerelIlan, simdiMs); tcpTik(simdiMs); defter_.tazele(simdiMs); } void OrkestraKule::tcpTik(uint64_t simdiMs) { if (!orkestraLanKesif()) { // ağ ana bayrağı — kapalıyken TCP de tamamen kapalı if (tcpDinleyici_.acikMi() || !kanallar_.empty()) { kanallar_.clear(); tcpDinleyici_.kapat(); } return; } // Dinleyici yaşam döngüsü (makinede İLK açan dinler; meşgulse 5 sn'de bir dene). if (tcpDinleyici_.acikMi() && tcpDinleyici_.port() != orkestraTcpPort()) tcpDinleyici_.kapat(); if (!tcpDinleyici_.acikMi()) { if (sonTcpDenemeMs_ && simdiMs - sonTcpDenemeMs_ < 5000) return; sonTcpDenemeMs_ = simdiMs; if (!tcpDinleyici_.ac(orkestraTcpPort())) return; } // Yeni bağlantılar (tavanlı — kaynak tüketimi sınırlı). while (kanallar_.size() < orkestraTcpMaksBaglanti()) { const uintptr_t s = tcpDinleyici_.kabulEt(); if (!s) break; kanallar_.push_back( std::make_unique(s, (size_t)orkestraTcpMaksGovdeMB() << 20)); } // Kanal okuma: çerçeveler ŞİMDİLİK yalnız sayılır (işleme eşleştirme+rol sonrası). for (size_t i = 0; i < kanallar_.size();) { TcpKanal& k = *kanallar_[i]; std::string veri; bool dusur = false; for (int tur = 0; tur < 8; ++tur) { // kanal başına okuma bütçesi (kare bloklanmaz) const int n = k.baglanti.al(veri); if (n < 0) { dusur = true; break; } if (n == 0) break; std::vector cerceveler; if (!k.cozucu.besle(veri.data(), veri.size(), cerceveler)) { dusur = true; // bozuk akış (yanlış sihir/tavan) → bağlantı kes (güvenlik) break; } tcpAlinanCerceve_ += cerceveler.size(); // Yalnız EŞLEŞTİRME çerçeveleri işlenir; komut/görev tipleri eşleşme+rol // kapısı gelmeden YOK SAYILIR (güvenlik sırası — tasarım §8). for (const SurecCerceve& c : cerceveler) eslesmeCerceveIsle(k, c, simdiMs); } if (dusur) kanallar_.erase(kanallar_.begin() + (long)i); else ++i; } } void OrkestraKule::eslesmeCerceveIsle(TcpKanal& k, const SurecCerceve& c, uint64_t simdiMs) { orkestra::EslesmeYonetici& esl = eslesmeKur(); if (c.tip == SurecMesajTip::EslesmeIste) { uint64_t id = 0; std::string ad, kod; if (esl.istekAl(c.govde, yerelNodeId_, simdiMs, id, ad, kod)) k.nodeId = id; // kanal bu node'a ait — onay bu kanaldan yazılacak (panel onaylayınca) } else if (c.tip == SurecMesajTip::EslesmeOnay) { uint64_t id = 0; std::string kod; if (esl.onayAl(c.govde, yerelNodeId_, id, kod)) k.nodeId = id; // giden akış tamam } else if (c.tip == SurecMesajTip::Komut || c.tip == SurecMesajTip::Parametre) { // KOMUT KANALI: yalnız EŞLİ + Operatör/Yönetici rollü node komut çalıştırabilir. // (Yürütme = komutCalistir lisans kapısı, belge_penceresi drain'inde — sonraki dalga.) if (k.nodeId == 0 || esl.rol(k.nodeId) < orkestra::Rol::Operator) { ++redUzakKomut_; // eşsiz/İzleyici → reddet (güvenlik zinciri: eşleşme→rol→lisans) return; } UzakKomut uk; uk.nodeId = k.nodeId; uk.tip = c.tip; if (c.tip == SurecMesajTip::Parametre) surecproto::paramCoz(c.govde, uk.ad, uk.parametreler); else uk.ad = c.govde; onayliUzakKomut_.push_back(std::move(uk)); } else if (c.tip == SurecMesajTip::TaskAta) { // İş atama da KOMUT yetkisi ister (Operatör+). Kabul → yerel kuyruğa (id korunur). if (k.nodeId == 0 || esl.rol(k.nodeId) < orkestra::Rol::Operator) { ++redUzakKomut_; return; } orkestra::Task t; if (orkestra::taskproto::ataCoz(c.govde, t)) { t.atananNode = yerelNodeId_; tasklar_.kabulEt(t); // GorevSistemi köprüsü (gerçek yürütme) sonraki dalga } } else if (c.tip == SurecMesajTip::TaskDurumu) { // Node→kule ilerleme geri bildirimi (yalnız eşli node — teşhis, yetki gerektirmez). if (k.nodeId == 0 || !esl.esliMi(k.nodeId)) return; uint64_t id = 0; orkestra::TaskDurum d = orkestra::TaskDurum::Kuyrukta; uint8_t il = 0; if (orkestra::taskproto::durumCoz(c.govde, id, d, il)) { tasklar_.durumGecir(id, d); // geçersiz geçiş sessiz yok sayılır (kural denetimli) tasklar_.ilerlemeAyarla(id, il); } } else if (c.tip == SurecMesajTip::DosyaParca) { // Dosya ALMA da yetki ister (Operatör+). Birleştir; tamamlanınca aktarim'a yaz. if (k.nodeId == 0 || esl.rol(k.nodeId) < orkestra::Rol::Operator) { ++redUzakKomut_; return; } orkestra::DosyaParcaGovde p; if (!orkestra::dosyaproto::parcaCoz(c.govde, p)) return; orkestra::ParcaBirlestirici& b = aktarimlar_[p.transferId]; const auto s = b.ekle(p); if (s == orkestra::ParcaBirlestirici::Sonuc::Tamam) { char ad[64]; std::snprintf(ad, sizeof(ad), "%llu_%llu.bin", (unsigned long long)k.nodeId, (unsigned long long)p.transferId); const std::filesystem::path yol = fiko::gecici::altDizin("orkestra/aktarim") / ad; std::ofstream out(yol, std::ios::binary); if (out) out.write(b.icerik().data(), (std::streamsize)b.icerik().size()); ++tamamlananTransfer_; aktarimlar_.erase(p.transferId); } else if (s == orkestra::ParcaBirlestirici::Sonuc::HashHatasi) { aktarimlar_.erase(p.transferId); // bozuk transfer düşer (yeniden gönderim gerekir) } } // Diğer tipler: sessiz yok say. } bool OrkestraKule::rolAyarla(uint64_t nodeId, orkestra::Rol rol) { return eslesmeKur().rolAyarla(nodeId, rol); } std::vector OrkestraKule::beklemedekiUzakKomutlar() { return std::exchange(onayliUzakKomut_, {}); } std::vector OrkestraKule::beklemedekiAtanmisTasklar() { std::vector cikti; for (uint64_t id : tasklar_.atanmisBaslat(yerelNodeId_)) { const orkestra::Task* t = tasklar_.bul(id); if (!t) continue; cikti.push_back({id, t->tur, t->param}); taskDurumGeriGonder(*t); // Calisiyor bildirimi kaynağa } return cikti; } void OrkestraKule::taskTamamla(uint64_t taskId, bool basarili) { tasklar_.durumGecir(taskId, basarili ? orkestra::TaskDurum::Bitti : orkestra::TaskDurum::Hata); if (const orkestra::Task* t = tasklar_.bul(taskId)) taskDurumGeriGonder(*t); } void OrkestraKule::taskDurumGeriGonder(const orkestra::Task& t) { if (t.kaynakNode == 0 || t.kaynakNode == yerelNodeId_) return; // yerel iş → ağ yok SurecCerceve c; c.tip = SurecMesajTip::TaskDurumu; c.govde = orkestra::taskproto::durumSerialize(t.taskId, t.durum, t.ilerleme); const std::string wire = surecproto::cerceveSerialize(c); for (auto& k : kanallar_) if (k->nodeId == t.kaynakNode) { k->baglanti.gonder(wire); break; } } bool OrkestraKule::eslesmeOnayla(uint64_t nodeId) { orkestra::EslesmeYonetici& esl = eslesmeKur(); std::string onayGovde; if (!esl.onayla(yerelNodeId_, nodeId, onayGovde)) return false; SurecCerceve c; c.tip = SurecMesajTip::EslesmeOnay; c.kaynakPid = 0; c.govde = onayGovde; const std::string wire = surecproto::cerceveSerialize(c); for (auto& k : kanallar_) if (k->nodeId == nodeId) return k->baglanti.gonder(wire); return false; // kanal kapanmış (karşı taraf gitti) — kayıt yine de kuruldu (yerelde eşli) } void OrkestraKule::eslesmeReddet(uint64_t nodeId) { if (eslesme_) eslesme_->reddet(nodeId); } uint64_t OrkestraKule::taskOlusturVeGonder( const std::string& tur, const std::vector>& param, const orkestra::TaskHedef& hedef) { const uint64_t simdiMs = GetTickCount64(); const uint64_t taskId = tasklar_.olustur(tur, param, hedef, yerelNodeId_, simdiMs); // Hedef node seçimi. uint64_t hedefNode = 0; if (hedef.tip == orkestra::HedefTipi::BelirliNode) hedefNode = hedef.nodeId; else { hedefNode = tasklar_.otomatikHedefSec(*tasklar_.bul(taskId), defter_, orkestraYerlestirmeAgirlik()); } if (hedefNode == 0) return taskId; // uygun node yok → Kuyrukta bekler tasklar_.ata(taskId, hedefNode); // Atanan node'un kanalına TaskAta yaz (yalnız eşli+kanal varsa; yoksa atanmış kalır). SurecCerceve c; c.tip = SurecMesajTip::TaskAta; c.govde = orkestra::taskproto::ataSerialize(*tasklar_.bul(taskId)); const std::string wire = surecproto::cerceveSerialize(c); for (auto& k : kanallar_) if (k->nodeId == hedefNode) { k->baglanti.gonder(wire); break; } return taskId; } bool OrkestraKule::dosyaGonder(uint64_t nodeId, const std::string& yol) { std::ifstream f(yol, std::ios::binary); if (!f) return false; std::string icerik((std::istreambuf_iterator(f)), std::istreambuf_iterator()); TcpKanal* kanal = nullptr; for (auto& k : kanallar_) if (k->nodeId == nodeId) { kanal = k.get(); break; } if (!kanal) return false; // eşli+kanal yok const uint64_t tid = ++sonTransferId_; const size_t parcaBoy = (size_t)orkestraTransferParcaKB() * 1024; for (const auto& p : orkestra::dosyayiParcala(tid, icerik, parcaBoy)) { SurecCerceve c; c.tip = SurecMesajTip::DosyaParca; c.govde = orkestra::dosyaproto::parcaSerialize(p); if (!kanal->baglanti.gonder(surecproto::cerceveSerialize(c))) return false; } return true; } bool OrkestraKule::eslesmeBaslat(uint64_t nodeId) { const orkestra::NodeBilgi* n = defter_.bul(nodeId); if (!n || n->ip.empty()) return false; // IP henüz keşfedilmedi (beacon bekle) auto kanal = std::make_unique(0, (size_t)orkestraTcpMaksGovdeMB() << 20); if (!kanal->baglanti.baglan(n->ip.c_str(), orkestraTcpPort())) return false; kanal->nodeId = nodeId; const uint64_t simdiMs = GetTickCount64(); const std::string istek = eslesmeKur().istekOlustur(yerelNodeId_, makineAd_, nodeId, simdiMs); SurecCerceve c; c.tip = SurecMesajTip::EslesmeIste; c.govde = istek; if (!kanal->baglanti.gonder(surecproto::cerceveSerialize(c))) return false; kanallar_.push_back(std::move(kanal)); // onay bu kanaldan okunacak (tcpTik dispatch) return true; } orkestra::EslesmeYonetici& OrkestraKule::eslesmeKur() { if (!eslesme_) { eslesme_ = std::make_unique( [](uint8_t* p, size_t n) { orkestraRastgeleDoldur(p, n); }); if (!bekleyenDepo_.empty()) { // startup'ta yüklenen depo şimdi uygulanır eslesme_->yukle(orkestraHexCoz(bekleyenDepo_)); bekleyenDepo_.clear(); } } return *eslesme_; } orkestra::EslesmeYonetici& OrkestraKule::eslesme() { return eslesmeKur(); } std::string OrkestraKule::eslesmeKaydet() const { return eslesme_ ? orkestraHexKodla(eslesme_->serialize()) : bekleyenDepo_; } void OrkestraKule::eslesmeYukle(const std::string& hex) { if (eslesme_) eslesme_->yukle(orkestraHexCoz(hex)); else bekleyenDepo_ = hex; // kule daha kurulmadı — ilk tik'te uygula } void OrkestraKule::lanTik(const orkestra::NodeBilgi& yerelIlan, uint64_t simdiMs) { if (!orkestraLanKesif()) { if (lan_) { // bayrak kapatıldı → keşfi ve soketi bırak (uzak kayıtlar bayatlayıp lan_.reset(); // Offline'a düşer — silinmez, tasarım §3) lanSoket_.kapat(); } return; } // Port değişimi → soketi yeniden aç (aynı LanKesif sayaçları korunur). if (lanSoket_.acikMi() && lanSoket_.port() != orkestraLanPort()) lanSoket_.kapat(); if (!lanSoket_.acikMi()) { if (sonSoketDenemeMs_ && simdiMs - sonSoketDenemeMs_ < 5000) return; sonSoketDenemeMs_ = simdiMs; if (!lanSoket_.ac(orkestraLanPort())) return; // port meşgul/güvenlik → sessiz, 5 sn sonra } if (!lan_) lan_ = std::make_unique(lanSoket_); lan_->beaconAralikAyarla(orkestraBeaconSn() * 1000); lan_->ilanAyarla(yerelIlan); if (metrikHazir_) lan_->metrikAyarla(sonMetrikDeger_); lan_->tik(defter_, simdiMs); } } // namespace fiko