Line data Source code
1 : /*
2 : * Copyright (C) 2004-2024 Savoir-faire Linux Inc.
3 : *
4 : * Author: Philippe Proulx <philippe.proulx@savoirfairelinux.com>
5 : * Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
6 : *
7 : * This program is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * This program is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, write to the Free Software
19 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 : */
21 : #ifndef LIBJAMI_H
22 : #define LIBJAMI_H
23 :
24 : #include "def.h"
25 :
26 : #include <vector>
27 : #include <functional>
28 : #include <string>
29 : #include <map>
30 : #include <memory>
31 : #include <type_traits>
32 : #include <filesystem>
33 :
34 : #include "trace-tools.h"
35 :
36 : namespace libjami {
37 :
38 : /* flags for initialization */
39 : enum InitFlag {
40 : LIBJAMI_FLAG_DEBUG = 1 << 0,
41 : LIBJAMI_FLAG_CONSOLE_LOG = 1 << 1,
42 : LIBJAMI_FLAG_AUTOANSWER = 1 << 2,
43 : LIBJAMI_FLAG_IOS_EXTENSION = 1 << 4,
44 : LIBJAMI_FLAG_NO_LOCAL_AUDIO = 1 << 6,
45 : LIBJAMI_FLAG_NO_LOCAL_VIDEO = 1 << 7,
46 : LIBJAMI_FLAG_NO_LOCAL_MEDIA = LIBJAMI_FLAG_NO_LOCAL_AUDIO | LIBJAMI_FLAG_NO_LOCAL_VIDEO,
47 : LIBJAMI_FLAG_NO_AUTOSYNC = 1 << 8,
48 : LIBJAMI_FLAG_NO_AUTOLOAD = 1 << 9 // disable auto loading of accounts and conversations
49 : };
50 :
51 : /**
52 : * Return the library version as string.
53 : */
54 : LIBJAMI_PUBLIC const char* version() noexcept;
55 :
56 : /**
57 : * Return the target platform (OS) as a string.
58 : */
59 : LIBJAMI_PUBLIC const char* platform() noexcept;
60 :
61 : /**
62 : * Initialize globals, create underlaying daemon.
63 : *
64 : * @param flags Flags to customize this initialization
65 : * @returns true if initialization succeed else false.
66 : */
67 : LIBJAMI_PUBLIC bool init(enum InitFlag flags) noexcept;
68 :
69 : /**
70 : * Start asynchronously daemon created by init().
71 : * @returns true if daemon started successfully
72 : */
73 :
74 : LIBJAMI_PUBLIC bool start(const std::filesystem::path& config_file = {}) noexcept;
75 :
76 : /**
77 : * Stop and freeing any resource allocated by daemon
78 : */
79 : LIBJAMI_PUBLIC void fini() noexcept;
80 :
81 : LIBJAMI_PUBLIC bool initialized() noexcept;
82 :
83 : /**
84 : * Control log handlers.
85 : *
86 : * @param whom Log handler to control
87 : */
88 : LIBJAMI_PUBLIC void logging(const std::string& whom, const std::string& action) noexcept;
89 :
90 : /* External Callback Dynamic Utilities
91 : *
92 : * The library provides to users a way to be acknowledged
93 : * when daemon's objects have a state change.
94 : * The user is aware of this changement when the deamon calls
95 : * a user-given callback.
96 : * Daemon handles many of these callbacks, one per event type.
97 : * The user registers his callbacks using registerXXXXHandlers() functions.
98 : * As each callback has its own function signature,
99 : * to keep compatibility over releases we don't let user directly provides
100 : * his callbacks as it or through a structure.
101 : * This way brings ABI violation if we need to change the order
102 : * and/or the existence of any callback type.
103 : * Thus the user have to pass them using following template classes
104 : * and functions, that wraps user-callback in a generic and ABI-compatible way.
105 : */
106 :
107 : /* Generic class to transit user callbacks to daemon library.
108 : * Used conjointly with std::shared_ptr to hide the concrete class.
109 : * See CallbackWrapper template for details.
110 : */
111 : class LIBJAMI_PUBLIC CallbackWrapperBase
112 : {
113 : protected:
114 : // Because post() needs Manager, it should be defined in a .cpp
115 : // so not in a templated class.
116 : // Also we do not want this method to be public in the API.
117 : void post(std::function<void()> cb);
118 : };
119 :
120 : /* Concrete class of CallbackWrapperBase.
121 : * This class wraps callbacks of a specific signature.
122 : * Also used to obtain the user callback from a CallbackWrapperBase shared ptr.
123 : *
124 : * This class is CopyConstructible, CopyAssignable, MoveConstructible
125 : * and MoveAssignable.
126 : */
127 : template<typename TProto>
128 : class CallbackWrapper : public CallbackWrapperBase
129 : {
130 : private:
131 : using TFunc = std::function<TProto>;
132 : TFunc cb_; // The user-callback
133 :
134 : public:
135 : const char* file_;
136 : uint32_t linum_;
137 :
138 : // Empty wrapper: no callback associated.
139 : // Used to initialize internal callback arrays.
140 3220 : CallbackWrapper() noexcept {}
141 :
142 : // Create and initialize a wrapper to given callback.
143 1207 : CallbackWrapper(TFunc&& func, const char* filename, uint32_t linum) noexcept
144 1207 : : cb_(std::forward<TFunc>(func))
145 1207 : , file_(filename)
146 1207 : , linum_(linum)
147 1207 : {}
148 :
149 : // Create and initialize a wrapper from a generic CallbackWrapperBase
150 : // shared pointer.
151 : // Note: the given callback is copied into internal storage.
152 18403 : CallbackWrapper(const std::shared_ptr<CallbackWrapperBase>& p) noexcept
153 18403 : {
154 18402 : if (p) {
155 5921 : auto other = (CallbackWrapper<TProto>*) p.get();
156 :
157 5921 : cb_ = other->cb_;
158 5920 : file_ = other->file_;
159 5920 : linum_ = other->linum_;
160 : }
161 18401 : }
162 :
163 : // Return user-callback reference.
164 : // The returned std::function can be null-initialized if no callback
165 : // has been set.
166 5290 : constexpr const TFunc& operator*() const noexcept { return cb_; }
167 :
168 : // Return boolean true value if a non-null callback has been set
169 18403 : constexpr explicit operator bool() const noexcept { return static_cast<bool>(cb_); }
170 : };
171 :
172 : /* Concrete class of CallbackWrapperBase.
173 : * This class wraps callbacks of a specific signature.
174 : * Used to retrigger callbacks on a io context to avoid lock if signals cannot
175 : * be emitted while a method is called.
176 : * Also used to obtain the user callback from a CallbackWrapperBase shared ptr.
177 : *
178 : * This class is CopyConstructible, CopyAssignable, MoveConstructible
179 : * and MoveAssignable.
180 : */
181 : template<typename TProto>
182 : class SerializedCallbackWrapper : public CallbackWrapperBase
183 : {
184 : private:
185 : using TFunc = std::function<TProto>;
186 : TFunc cb_; // The user-callback
187 :
188 : // This is quite a ugly method used to transmit templated TFunc with their arguments in the
189 : // ioContext of the manager to avoid locks for signals.
190 : template<typename TCallback>
191 : auto ioContextWrapper(TCallback&& fun)
192 : {
193 : return [this, fun {std::move(fun)}](
194 : auto&&... args) -> decltype(fun(std::forward<decltype(args)>(args)...)) {
195 : post([fun {std::move(fun)},
196 : forwardArgs = std::make_tuple(std::move(args)...)]() mutable {
197 : std::apply(std::move(fun), std::move(forwardArgs));
198 : });
199 : };
200 : }
201 :
202 : public:
203 : const char* file_;
204 : uint32_t linum_;
205 :
206 : // Empty wrapper: no callback associated.
207 : // Used to initialize internal callback arrays.
208 : SerializedCallbackWrapper() noexcept {}
209 :
210 : // Create and initialize a wrapper to given callback.
211 : SerializedCallbackWrapper(TFunc&& func, const char* filename, uint32_t linum) noexcept
212 : : file_(filename)
213 : , linum_(linum)
214 : {
215 : cb_ = ioContextWrapper(func);
216 : }
217 :
218 : // Create and initialize a wrapper from a generic CallbackWrapperBase
219 : // shared pointer.
220 : // Note: the given callback is copied into internal storage.
221 : SerializedCallbackWrapper(const std::shared_ptr<CallbackWrapperBase>& p) noexcept
222 : {
223 : if (p) {
224 : auto other = (CallbackWrapper<TProto>*) p.get();
225 :
226 : cb_ = ioContextWrapper(other.cb_);
227 : file_ = other->file_;
228 : linum_ = other->linum_;
229 : }
230 : }
231 :
232 : // Return user-callback reference.
233 : // The returned std::function can be null-initialized if no callback
234 : // has been set.
235 : constexpr const TFunc& operator*() const noexcept { return cb_; }
236 :
237 : // Return boolean true value if a non-null callback has been set
238 : constexpr explicit operator bool() const noexcept { return static_cast<bool>(cb_); }
239 : };
240 :
241 : /**
242 : * Return an exportable callback object.
243 : * This object is a std::pair of a string and a CallbackWrapperBase shared_ptr.
244 : * This last wraps given callback in a ABI-compatible way.
245 : * Note: this version accepts callbacks as rvalue only.
246 : */
247 : template<typename Ts>
248 : std::pair<std::string, std::shared_ptr<CallbackWrapperBase>>
249 1207 : exportable_callback(std::function<typename Ts::cb_type>&& func,
250 : const char* file = CURRENT_FILENAME(),
251 : uint32_t linum = CURRENT_LINE())
252 : {
253 : return std::make_pair((const std::string&) Ts::name,
254 : std::make_shared<CallbackWrapper<typename Ts::cb_type>>(
255 1207 : std::forward<std::function<typename Ts::cb_type>>(func), file, linum));
256 : }
257 :
258 : template<typename Ts>
259 : std::pair<std::string, std::shared_ptr<CallbackWrapperBase>>
260 : exportable_serialized_callback(std::function<typename Ts::cb_type>&& func,
261 : const char* file = CURRENT_FILENAME(),
262 : uint32_t linum = CURRENT_LINE())
263 : {
264 : return std::make_pair((const std::string&) Ts::name,
265 : std::make_shared<SerializedCallbackWrapper<typename Ts::cb_type>>(
266 : std::forward<std::function<typename Ts::cb_type>>(func), file, linum));
267 : }
268 :
269 : LIBJAMI_PUBLIC void registerSignalHandlers(
270 : const std::map<std::string, std::shared_ptr<CallbackWrapperBase>>&);
271 : LIBJAMI_PUBLIC void unregisterSignalHandlers();
272 :
273 : using MediaMap = std::map<std::string, std::string>;
274 :
275 : } // namespace libjami
276 :
277 : #endif /* LIBJAMI_H */
|