Line data Source code
1 : /* 2 : * Copyright (C) 2004-2026 Savoir-faire Linux Inc. 3 : * 4 : * This program is free software: you can redistribute it and/or modify 5 : * it under the terms of the GNU General Public License as published by 6 : * the Free Software Foundation, either version 3 of the License, or 7 : * (at your option) any later version. 8 : * 9 : * This program is distributed in the hope that it will be useful, 10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 : * GNU General Public License for more details. 13 : * 14 : * You should have received a copy of the GNU General Public License 15 : * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 : */ 17 : 18 : #pragma once 19 : 20 : #include <opendht/dhtrunner.h> 21 : #include <opendht/infohash.h> 22 : 23 : #include <map> 24 : #include <set> 25 : #include <mutex> 26 : #include <string> 27 : #include <functional> 28 : #include <vector> 29 : #include <future> 30 : #include <atomic> 31 : 32 : namespace jami { 33 : 34 : class PresenceManager 35 : { 36 : public: 37 : using PresenceCallback = std::function<void(const std::string& uri, bool online)>; 38 : using DevicePresenceCallback = std::function<void(const std::string& uri, const dht::PkId& deviceId, bool online)>; 39 : 40 : PresenceManager(const std::shared_ptr<dht::DhtRunner>& dht); 41 : ~PresenceManager(); 42 : 43 : /** 44 : * Start tracking a buddy. 45 : * Increments the reference count for the given URI. 46 : * If the buddy was not tracked, it starts listening on the DHT. 47 : */ 48 : void trackBuddy(const std::string& uri); 49 : 50 : /** 51 : * Stop tracking a buddy. 52 : * Decrements the reference count. 53 : * If the count reaches zero, stops listening on the DHT. 54 : */ 55 : void untrackBuddy(const std::string& uri); 56 : 57 : /** 58 : * Check if a buddy is currently online. 59 : */ 60 : bool isOnline(const std::string& uri) const; 61 : 62 : /** 63 : * Get the presence status of all tracked buddies. 64 : */ 65 : std::map<std::string, bool> getTrackedBuddyPresence() const; 66 : 67 : /** 68 : * Get the list of devices for a tracked buddy. 69 : */ 70 : std::vector<dht::PkId> getDevices(const std::string& uri) const; 71 : 72 : /** 73 : * Add a listener for presence changes. 74 : * The callback will be called whenever a tracked buddy goes online or offline. 75 : * @return A token that can be used to remove the listener. 76 : */ 77 : uint64_t addListener(PresenceCallback cb); 78 : 79 : /** 80 : * Remove a listener using the token returned by addListener. 81 : */ 82 : 83 : void removeListener(uint64_t token); 84 : 85 : /** 86 : * Add a listener for device presence changes. 87 : * The callback will be called whenever a device of a tracked buddy goes online or offline. 88 : * @return A token that can be used to remove the listener. 89 : */ 90 : uint64_t addDeviceListener(DevicePresenceCallback cb); 91 : 92 : /** 93 : * Remove a listener using the token returned by addDeviceListener. 94 : */ 95 : void removeDeviceListener(uint64_t token); 96 : 97 : /** 98 : * Refresh all tracked buddies. 99 : * This should be called when the DHT is restarted. 100 : */ 101 : void refresh(); 102 : 103 : private: 104 : struct TrackedBuddy 105 : { 106 : dht::InfoHash id; 107 : std::set<dht::PkId> devices; 108 : std::future<size_t> listenToken; 109 : int refCount {0}; 110 : 111 799 : TrackedBuddy(dht::InfoHash h) 112 799 : : id(h) 113 799 : {} 114 : }; 115 : 116 : void trackPresence(const dht::InfoHash& h, TrackedBuddy& buddy); 117 : void notifyListeners(const std::string& uri, bool online); 118 : void notifyDeviceListeners(const std::string& uri, const dht::PkId& deviceId, bool online); 119 : 120 : std::shared_ptr<dht::DhtRunner> dht_; 121 : 122 : mutable std::mutex mutex_; 123 : std::map<dht::InfoHash, TrackedBuddy> trackedBuddies_; 124 : 125 : std::mutex listenersMutex_; 126 : std::map<uint64_t, PresenceCallback> listeners_; 127 : std::map<uint64_t, DevicePresenceCallback> deviceListeners_; 128 : std::atomic_uint64_t nextListenerId_ {1}; 129 : }; 130 : 131 : } // namespace jami