#include "session_registry.h" #ifdef VOICECAT_HAS_NET #include #include #include "conn_session.h" namespace voicecat::server { void SessionRegistry::init_default_channels() { std::unique_lock lk(mu_); ChannelEntry lobby; lobby.proto.set_id(1); lobby.proto.set_name("Lobby"); lobby.proto.set_type(voicecat::v1::CHANNEL_PERMANENT); lobby.proto.set_order(0); channels_[1] = std::move(lobby); } uint64_t SessionRegistry::register_session(std::weak_ptr session) { std::unique_lock lk(mu_); uint64_t id = next_session_id_++; sessions_[id] = std::move(session); return id; } void SessionRegistry::unregister_session(uint64_t session_id) { std::unique_lock lk(mu_); sessions_.erase(session_id); } uint32_t SessionRegistry::add_user(uint64_t session_id, const voicecat::v1::User& user) { std::unique_lock lk(mu_); uint32_t uid = next_user_id_++; UserEntry entry; entry.proto = user; entry.proto.set_id(uid); entry.proto.set_channel_id(1); // start in Lobby entry.session_id = session_id; users_[uid] = std::move(entry); return uid; } void SessionRegistry::remove_user(uint32_t user_id) { std::unique_lock lk(mu_); users_.erase(user_id); } bool SessionRegistry::set_user_channel(uint32_t user_id, uint32_t channel_id) { std::unique_lock lk(mu_); auto ch_it = channels_.find(channel_id); if (ch_it == channels_.end()) return false; auto user_it = users_.find(user_id); if (user_it == users_.end()) return false; user_it->second.proto.set_channel_id(channel_id); return true; } std::vector SessionRegistry::channel_snapshot() const { std::shared_lock lk(mu_); std::vector result; result.reserve(channels_.size()); for (auto& [id, entry] : channels_) result.push_back(entry.proto); return result; } std::vector SessionRegistry::user_snapshot() const { std::shared_lock lk(mu_); std::vector result; result.reserve(users_.size()); for (auto& [id, entry] : users_) result.push_back(entry.proto); return result; } std::vector> SessionRegistry::resolve_text_targets( uint64_t sender_session_id, voicecat::v1::TextScope scope, uint32_t target_id) const { std::shared_lock lk(mu_); std::vector> targets; if (scope == voicecat::v1::TEXT_CHANNEL) { // Find channel_id of the target, then all users in that channel for (auto& [uid, entry] : users_) { if (entry.proto.channel_id() != target_id) continue; if (entry.session_id == sender_session_id) continue; auto sit = sessions_.find(entry.session_id); if (sit == sessions_.end()) continue; if (auto sess = sit->second.lock()) targets.push_back(sess); } } else if (scope == voicecat::v1::TEXT_PRIVATE) { // target_id is user_id auto user_it = users_.find(target_id); if (user_it != users_.end()) { auto sit = sessions_.find(user_it->second.session_id); if (sit != sessions_.end()) { if (auto sess = sit->second.lock()) targets.push_back(sess); } } } return targets; } void SessionRegistry::broadcast(const voicecat::v1::Envelope& env, uint64_t exclude_session_id) const { std::shared_lock lk(mu_); for (auto& [sid, weak] : sessions_) { if (sid == exclude_session_id) continue; if (auto sess = weak.lock()) sess->send_envelope(env); } } } // namespace voicecat::server #endif // VOICECAT_HAS_NET