Loading src/cluster.cpp +61 −16 Changes for src/cluster.cpp: 61 added lines, 16 removed lines. Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ namespace authdb { // [16B * member_count member uuids] // [4B username_len] // [username_len bytes username] // [4B gpo_count] // [for each GPO: 16B GPOId + 1B GPORes] std::vector<uint8_t> SessionBlock::serialize(const SessionData &sess) { uuid::uuid sid, uid, did; Loading @@ -71,13 +73,15 @@ namespace authdb { // Collect members std::vector<uuid::uuid> members; // We need to iterate the session's members - since isMemberOf is the // public API, we'll reconstruct via the SessionData copy // The SessionData stores members internally, we access via serialization sess.getMembers(members); // Header: 16+16+16 + 4 + 4 = 56 bytes minimum // Plus member UUIDs and username size_t total = 48 + 4 + 4 + username_len; // Collect GPO results std::vector<std::pair<uuid::uuid, bool>> gpo_results; sess.getGPOResults(gpo_results); // Header: 16+16+16 + 4 + members*16 + 4 + username + 4 + gpos*17 size_t total = 48 + 4 + (members.size() * 16) + 4 + username_len + 4 + (gpo_results.size() * 17); std::vector<uint8_t> buf(total); size_t pos = 0; Loading @@ -94,11 +98,16 @@ namespace authdb { std::memcpy(buf.data() + pos, did.value, 16); pos += 16; // Member count = 0 for basic serialization (members stored separately) uint32_t mc = 0; // Member count and UUIDs uint32_t mc = static_cast<uint32_t>(members.size()); std::memcpy(buf.data() + pos, &mc, 4); pos += 4; for (const auto &m : members) { std::memcpy(buf.data() + pos, m.value, 16); pos += 16; } // Username length uint32_t ul = static_cast<uint32_t>(username_len); std::memcpy(buf.data() + pos, &ul, 4); Loading @@ -107,6 +116,19 @@ namespace authdb { // Username if (username_len > 0) { std::memcpy(buf.data() + pos, username, username_len); pos += username_len; } // GPO count and results uint32_t gc = static_cast<uint32_t>(gpo_results.size()); std::memcpy(buf.data() + pos, &gc, 4); pos += 4; for (const auto &gpo : gpo_results) { std::memcpy(buf.data() + pos, gpo.first.value, 16); pos += 16; buf[pos] = gpo.second ? 1 : 0; pos += 1; } return buf; Loading @@ -115,7 +137,8 @@ namespace authdb { bool SessionBlock::deserialize(const std::vector<uint8_t> &data, uuid::uuid &sid, uuid::uuid &uid, uuid::uuid &did, std::vector<uuid::uuid> &members, std::string &username) { std::string &username, std::vector<std::pair<uuid::uuid, bool>> &gpo_results) { if (data.size() < 56) return false; size_t pos = 0; Loading Loading @@ -149,6 +172,25 @@ namespace authdb { if (pos + ul > data.size()) return false; username.assign(reinterpret_cast<const char*>(data.data() + pos), ul); pos += ul; // Parse GPO results (may be absent in older format) gpo_results.clear(); if (pos + 4 <= data.size()) { uint32_t gc = 0; std::memcpy(&gc, data.data() + pos, 4); pos += 4; for (uint32_t i = 0; i < gc; i++) { if (pos + 17 > data.size()) return false; uuid::uuid gpoid; std::memcpy(gpoid.value, data.data() + pos, 16); pos += 16; bool gpores = (data[pos] != 0); pos += 1; gpo_results.emplace_back(gpoid, gpores); } } return true; } Loading Loading @@ -321,14 +363,15 @@ namespace authdb { bool Cluster::fetchSession(const uuid::uuid &uid, const uuid::uuid &did, uuid::uuid &sid, std::vector<uuid::uuid> &members, std::string &username) { std::string &username, std::vector<std::pair<uuid::uuid, bool>> &gpo_results) { uint64_t sgid = sessionGroupId(uid, did); // Check local store first std::vector<uint8_t> data; if (store_->fetch(sgid, 0, data)) { uuid::uuid d_uid, d_did; if (SessionBlock::deserialize(data, sid, d_uid, d_did, members, username)) { if (SessionBlock::deserialize(data, sid, d_uid, d_did, members, username, gpo_results)) { return true; } } Loading @@ -339,7 +382,7 @@ namespace authdb { std::lock_guard<std::mutex> lock(client_mutex_); if (pclient_->fetch_from_peers(sgid, 0, data) && !data.empty()) { uuid::uuid d_uid, d_did; if (SessionBlock::deserialize(data, sid, d_uid, d_did, members, username)) { if (SessionBlock::deserialize(data, sid, d_uid, d_did, members, username, gpo_results)) { // Cache locally for next time store_->store(sgid, 0, data.data(), data.size()); return true; Loading @@ -362,7 +405,8 @@ namespace authdb { uuid::uuid sid, d_uid, d_did; std::vector<uuid::uuid> members; std::string username; if (SessionBlock::deserialize(data, sid, d_uid, d_did, members, username)) { std::vector<std::pair<uuid::uuid, bool>> gpo_results; if (SessionBlock::deserialize(data, sid, d_uid, d_did, members, username, gpo_results)) { uint64_t sid_gid = sidGroupId(sid); store_->remove_group(sid_gid); if (pclient_) { Loading Loading @@ -426,13 +470,14 @@ namespace authdb { bool Cluster::fetchSessionBySid(const uuid::uuid &session_id, uuid::uuid &sid, uuid::uuid &uid, uuid::uuid &did, std::vector<uuid::uuid> &members, std::string &username) { std::string &username, std::vector<std::pair<uuid::uuid, bool>> &gpo_results) { uint64_t sid_gid = sidGroupId(session_id); // Check local store first std::vector<uint8_t> data; if (store_->fetch(sid_gid, 0, data)) { if (SessionBlock::deserialize(data, sid, uid, did, members, username)) { if (SessionBlock::deserialize(data, sid, uid, did, members, username, gpo_results)) { return true; } } Loading @@ -442,7 +487,7 @@ namespace authdb { try { std::lock_guard<std::mutex> lock(client_mutex_); if (pclient_->fetch_from_peers(sid_gid, 0, data) && !data.empty()) { if (SessionBlock::deserialize(data, sid, uid, did, members, username)) { if (SessionBlock::deserialize(data, sid, uid, did, members, username, gpo_results)) { // Cache locally store_->store(sid_gid, 0, data.data(), data.size()); return true; Loading src/cluster.h +7 −3 Changes for src/cluster.h: 7 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <mutex> #include <thread> #include <atomic> #include <utility> #include <uuidp.h> #include <paritypp/server.h> Loading Loading @@ -70,7 +71,8 @@ namespace authdb { static bool deserialize(const std::vector<uint8_t> &data, uuid::uuid &sid, uuid::uuid &uid, uuid::uuid &did, std::vector<uuid::uuid> &members, std::string &username); std::string &username, std::vector<std::pair<uuid::uuid, bool>> &gpo_results); }; uint64_t sessionGroupId(const uuid::uuid &uid, const uuid::uuid &did); Loading Loading @@ -130,7 +132,8 @@ namespace authdb { // Returns true if found, fills out parameters bool fetchSession(const uuid::uuid &uid, const uuid::uuid &did, uuid::uuid &sid, std::vector<uuid::uuid> &members, std::string &username); std::string &username, std::vector<std::pair<uuid::uuid, bool>> &gpo_results); // Remove a session from the cluster void removeSession(const uuid::uuid &uid, const uuid::uuid &did); Loading @@ -145,7 +148,8 @@ namespace authdb { bool fetchSessionBySid(const uuid::uuid &session_id, uuid::uuid &sid, uuid::uuid &uid, uuid::uuid &did, std::vector<uuid::uuid> &members, std::string &username); std::string &username, std::vector<std::pair<uuid::uuid, bool>> &gpo_results); // Replicate a data operation (create/edit/delete) to peers void replicateOp(OpType op, const std::string &domain, Loading src/session.cpp +44 −2 Changes for src/session.cpp: 44 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -143,6 +143,44 @@ bool authdb::SessionData::checkGPO(uuid::uuid gpoid) const{ return false; } void authdb::SessionData::getMembers(std::vector<uuid::uuid> &out) const{ out = _members; } void authdb::SessionData::getGPOResults(std::vector<std::pair<uuid::uuid, bool>> &out) const{ out.clear(); for(const GPOResult *cures=&_GPOResult; cures; cures=cures->next){ if(!cures->GPOId.empty()){ out.emplace_back(cures->GPOId, cures->GPORes); } } } void authdb::SessionData::setGPOResults(const std::vector<std::pair<uuid::uuid, bool>> &results){ // Clear existing GPO results (except the embedded first one) while(_GPOResult.next){ GPOResult *ne=_GPOResult.next->next; _GPOResult.next->next=nullptr; delete _GPOResult.next; _GPOResult.next=ne; } _GPOResult.GPOId.clear(); _GPOResult.GPORes=false; GPOResult *cur=&_GPOResult; for(size_t i=0; i<results.size(); ++i){ if(i==0){ cur->GPOId=results[i].first; cur->GPORes=results[i].second; }else{ cur->next=new GPOResult(); cur=cur->next; cur->GPOId=results[i].first; cur->GPORes=results[i].second; } } } authdb::Session::Session() { _firstData=nullptr; _lastData=nullptr; Loading Loading @@ -202,11 +240,13 @@ const authdb::SessionData *authdb::Session::addSession(AuthBackend &backend,uuid uuid::uuid cluster_sid; std::vector<uuid::uuid> cluster_members; std::string cluster_username; std::vector<std::pair<uuid::uuid, bool>> cluster_gpo; if (g_Cluster->fetchSession(userid, domainid, cluster_sid, cluster_members, cluster_username)) { cluster_members, cluster_username, cluster_gpo)) { // Session exists on another node, import it locally SessionData *imported = new SessionData(cluster_sid, userid, domainid, cluster_members); imported->_username = cluster_username; imported->setGPOResults(cluster_gpo); std::lock_guard<std::mutex> guard(_SessionLock); if (!_firstData) { Loading Loading @@ -395,9 +435,11 @@ const authdb::SessionData *authdb::Session::getSession(uuid::uuid sessionid){ uuid::uuid sid, uid, did; std::vector<uuid::uuid> members; std::string username; if (g_Cluster->fetchSessionBySid(sessionid, sid, uid, did, members, username)) { std::vector<std::pair<uuid::uuid, bool>> gpo_results; if (g_Cluster->fetchSessionBySid(sessionid, sid, uid, did, members, username, gpo_results)) { SessionData *imported = new SessionData(sid, uid, did, members); imported->_username = username; imported->setGPOResults(gpo_results); std::lock_guard<std::mutex> guard(_SessionLock); if (!_firstData) { Loading src/session.h +5 −0 Changes for src/session.h: 5 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <memory> #include <mutex> #include <chrono> #include <utility> #include <uuidp.h> #include "authdb.h" Loading Loading @@ -70,6 +71,10 @@ namespace authdb { bool checkGPO(uuid::uuid gpoid) const; void getMembers(std::vector<uuid::uuid> &out) const; void getGPOResults(std::vector<std::pair<uuid::uuid, bool>> &out) const; void setGPOResults(const std::vector<std::pair<uuid::uuid, bool>> &results); private: class GPOResult{ Loading Loading
src/cluster.cpp +61 −16 Changes for src/cluster.cpp: 61 added lines, 16 removed lines. Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ namespace authdb { // [16B * member_count member uuids] // [4B username_len] // [username_len bytes username] // [4B gpo_count] // [for each GPO: 16B GPOId + 1B GPORes] std::vector<uint8_t> SessionBlock::serialize(const SessionData &sess) { uuid::uuid sid, uid, did; Loading @@ -71,13 +73,15 @@ namespace authdb { // Collect members std::vector<uuid::uuid> members; // We need to iterate the session's members - since isMemberOf is the // public API, we'll reconstruct via the SessionData copy // The SessionData stores members internally, we access via serialization sess.getMembers(members); // Header: 16+16+16 + 4 + 4 = 56 bytes minimum // Plus member UUIDs and username size_t total = 48 + 4 + 4 + username_len; // Collect GPO results std::vector<std::pair<uuid::uuid, bool>> gpo_results; sess.getGPOResults(gpo_results); // Header: 16+16+16 + 4 + members*16 + 4 + username + 4 + gpos*17 size_t total = 48 + 4 + (members.size() * 16) + 4 + username_len + 4 + (gpo_results.size() * 17); std::vector<uint8_t> buf(total); size_t pos = 0; Loading @@ -94,11 +98,16 @@ namespace authdb { std::memcpy(buf.data() + pos, did.value, 16); pos += 16; // Member count = 0 for basic serialization (members stored separately) uint32_t mc = 0; // Member count and UUIDs uint32_t mc = static_cast<uint32_t>(members.size()); std::memcpy(buf.data() + pos, &mc, 4); pos += 4; for (const auto &m : members) { std::memcpy(buf.data() + pos, m.value, 16); pos += 16; } // Username length uint32_t ul = static_cast<uint32_t>(username_len); std::memcpy(buf.data() + pos, &ul, 4); Loading @@ -107,6 +116,19 @@ namespace authdb { // Username if (username_len > 0) { std::memcpy(buf.data() + pos, username, username_len); pos += username_len; } // GPO count and results uint32_t gc = static_cast<uint32_t>(gpo_results.size()); std::memcpy(buf.data() + pos, &gc, 4); pos += 4; for (const auto &gpo : gpo_results) { std::memcpy(buf.data() + pos, gpo.first.value, 16); pos += 16; buf[pos] = gpo.second ? 1 : 0; pos += 1; } return buf; Loading @@ -115,7 +137,8 @@ namespace authdb { bool SessionBlock::deserialize(const std::vector<uint8_t> &data, uuid::uuid &sid, uuid::uuid &uid, uuid::uuid &did, std::vector<uuid::uuid> &members, std::string &username) { std::string &username, std::vector<std::pair<uuid::uuid, bool>> &gpo_results) { if (data.size() < 56) return false; size_t pos = 0; Loading Loading @@ -149,6 +172,25 @@ namespace authdb { if (pos + ul > data.size()) return false; username.assign(reinterpret_cast<const char*>(data.data() + pos), ul); pos += ul; // Parse GPO results (may be absent in older format) gpo_results.clear(); if (pos + 4 <= data.size()) { uint32_t gc = 0; std::memcpy(&gc, data.data() + pos, 4); pos += 4; for (uint32_t i = 0; i < gc; i++) { if (pos + 17 > data.size()) return false; uuid::uuid gpoid; std::memcpy(gpoid.value, data.data() + pos, 16); pos += 16; bool gpores = (data[pos] != 0); pos += 1; gpo_results.emplace_back(gpoid, gpores); } } return true; } Loading Loading @@ -321,14 +363,15 @@ namespace authdb { bool Cluster::fetchSession(const uuid::uuid &uid, const uuid::uuid &did, uuid::uuid &sid, std::vector<uuid::uuid> &members, std::string &username) { std::string &username, std::vector<std::pair<uuid::uuid, bool>> &gpo_results) { uint64_t sgid = sessionGroupId(uid, did); // Check local store first std::vector<uint8_t> data; if (store_->fetch(sgid, 0, data)) { uuid::uuid d_uid, d_did; if (SessionBlock::deserialize(data, sid, d_uid, d_did, members, username)) { if (SessionBlock::deserialize(data, sid, d_uid, d_did, members, username, gpo_results)) { return true; } } Loading @@ -339,7 +382,7 @@ namespace authdb { std::lock_guard<std::mutex> lock(client_mutex_); if (pclient_->fetch_from_peers(sgid, 0, data) && !data.empty()) { uuid::uuid d_uid, d_did; if (SessionBlock::deserialize(data, sid, d_uid, d_did, members, username)) { if (SessionBlock::deserialize(data, sid, d_uid, d_did, members, username, gpo_results)) { // Cache locally for next time store_->store(sgid, 0, data.data(), data.size()); return true; Loading @@ -362,7 +405,8 @@ namespace authdb { uuid::uuid sid, d_uid, d_did; std::vector<uuid::uuid> members; std::string username; if (SessionBlock::deserialize(data, sid, d_uid, d_did, members, username)) { std::vector<std::pair<uuid::uuid, bool>> gpo_results; if (SessionBlock::deserialize(data, sid, d_uid, d_did, members, username, gpo_results)) { uint64_t sid_gid = sidGroupId(sid); store_->remove_group(sid_gid); if (pclient_) { Loading Loading @@ -426,13 +470,14 @@ namespace authdb { bool Cluster::fetchSessionBySid(const uuid::uuid &session_id, uuid::uuid &sid, uuid::uuid &uid, uuid::uuid &did, std::vector<uuid::uuid> &members, std::string &username) { std::string &username, std::vector<std::pair<uuid::uuid, bool>> &gpo_results) { uint64_t sid_gid = sidGroupId(session_id); // Check local store first std::vector<uint8_t> data; if (store_->fetch(sid_gid, 0, data)) { if (SessionBlock::deserialize(data, sid, uid, did, members, username)) { if (SessionBlock::deserialize(data, sid, uid, did, members, username, gpo_results)) { return true; } } Loading @@ -442,7 +487,7 @@ namespace authdb { try { std::lock_guard<std::mutex> lock(client_mutex_); if (pclient_->fetch_from_peers(sid_gid, 0, data) && !data.empty()) { if (SessionBlock::deserialize(data, sid, uid, did, members, username)) { if (SessionBlock::deserialize(data, sid, uid, did, members, username, gpo_results)) { // Cache locally store_->store(sid_gid, 0, data.data(), data.size()); return true; Loading
src/cluster.h +7 −3 Changes for src/cluster.h: 7 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <mutex> #include <thread> #include <atomic> #include <utility> #include <uuidp.h> #include <paritypp/server.h> Loading Loading @@ -70,7 +71,8 @@ namespace authdb { static bool deserialize(const std::vector<uint8_t> &data, uuid::uuid &sid, uuid::uuid &uid, uuid::uuid &did, std::vector<uuid::uuid> &members, std::string &username); std::string &username, std::vector<std::pair<uuid::uuid, bool>> &gpo_results); }; uint64_t sessionGroupId(const uuid::uuid &uid, const uuid::uuid &did); Loading Loading @@ -130,7 +132,8 @@ namespace authdb { // Returns true if found, fills out parameters bool fetchSession(const uuid::uuid &uid, const uuid::uuid &did, uuid::uuid &sid, std::vector<uuid::uuid> &members, std::string &username); std::string &username, std::vector<std::pair<uuid::uuid, bool>> &gpo_results); // Remove a session from the cluster void removeSession(const uuid::uuid &uid, const uuid::uuid &did); Loading @@ -145,7 +148,8 @@ namespace authdb { bool fetchSessionBySid(const uuid::uuid &session_id, uuid::uuid &sid, uuid::uuid &uid, uuid::uuid &did, std::vector<uuid::uuid> &members, std::string &username); std::string &username, std::vector<std::pair<uuid::uuid, bool>> &gpo_results); // Replicate a data operation (create/edit/delete) to peers void replicateOp(OpType op, const std::string &domain, Loading
src/session.cpp +44 −2 Changes for src/session.cpp: 44 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -143,6 +143,44 @@ bool authdb::SessionData::checkGPO(uuid::uuid gpoid) const{ return false; } void authdb::SessionData::getMembers(std::vector<uuid::uuid> &out) const{ out = _members; } void authdb::SessionData::getGPOResults(std::vector<std::pair<uuid::uuid, bool>> &out) const{ out.clear(); for(const GPOResult *cures=&_GPOResult; cures; cures=cures->next){ if(!cures->GPOId.empty()){ out.emplace_back(cures->GPOId, cures->GPORes); } } } void authdb::SessionData::setGPOResults(const std::vector<std::pair<uuid::uuid, bool>> &results){ // Clear existing GPO results (except the embedded first one) while(_GPOResult.next){ GPOResult *ne=_GPOResult.next->next; _GPOResult.next->next=nullptr; delete _GPOResult.next; _GPOResult.next=ne; } _GPOResult.GPOId.clear(); _GPOResult.GPORes=false; GPOResult *cur=&_GPOResult; for(size_t i=0; i<results.size(); ++i){ if(i==0){ cur->GPOId=results[i].first; cur->GPORes=results[i].second; }else{ cur->next=new GPOResult(); cur=cur->next; cur->GPOId=results[i].first; cur->GPORes=results[i].second; } } } authdb::Session::Session() { _firstData=nullptr; _lastData=nullptr; Loading Loading @@ -202,11 +240,13 @@ const authdb::SessionData *authdb::Session::addSession(AuthBackend &backend,uuid uuid::uuid cluster_sid; std::vector<uuid::uuid> cluster_members; std::string cluster_username; std::vector<std::pair<uuid::uuid, bool>> cluster_gpo; if (g_Cluster->fetchSession(userid, domainid, cluster_sid, cluster_members, cluster_username)) { cluster_members, cluster_username, cluster_gpo)) { // Session exists on another node, import it locally SessionData *imported = new SessionData(cluster_sid, userid, domainid, cluster_members); imported->_username = cluster_username; imported->setGPOResults(cluster_gpo); std::lock_guard<std::mutex> guard(_SessionLock); if (!_firstData) { Loading Loading @@ -395,9 +435,11 @@ const authdb::SessionData *authdb::Session::getSession(uuid::uuid sessionid){ uuid::uuid sid, uid, did; std::vector<uuid::uuid> members; std::string username; if (g_Cluster->fetchSessionBySid(sessionid, sid, uid, did, members, username)) { std::vector<std::pair<uuid::uuid, bool>> gpo_results; if (g_Cluster->fetchSessionBySid(sessionid, sid, uid, did, members, username, gpo_results)) { SessionData *imported = new SessionData(sid, uid, did, members); imported->_username = username; imported->setGPOResults(gpo_results); std::lock_guard<std::mutex> guard(_SessionLock); if (!_firstData) { Loading
src/session.h +5 −0 Changes for src/session.h: 5 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <memory> #include <mutex> #include <chrono> #include <utility> #include <uuidp.h> #include "authdb.h" Loading Loading @@ -70,6 +71,10 @@ namespace authdb { bool checkGPO(uuid::uuid gpoid) const; void getMembers(std::vector<uuid::uuid> &out) const; void getGPOResults(std::vector<std::pair<uuid::uuid, bool>> &out) const; void setGPOResults(const std::vector<std::pair<uuid::uuid, bool>> &results); private: class GPOResult{ Loading