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 803 : TrackedBuddy(dht::InfoHash h)
112 803 : : id(h)
113 803 : {}
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
|