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 : #include <asio.hpp>
18 : #include <string>
19 : #include <cstdlib>
20 :
21 : #ifdef HAVE_CONFIG_H
22 : #include "config.h"
23 : #endif
24 :
25 : #include "jami.h"
26 : #include "manager.h"
27 : #include "logger.h"
28 : #include "client/jami_signal.h"
29 :
30 : namespace libjami {
31 :
32 : static InitFlag initFlags = {};
33 :
34 : bool
35 307 : init(enum InitFlag flags) noexcept
36 : {
37 307 : initFlags = flags;
38 307 : jami::Logger::setDebugMode(LIBJAMI_FLAG_DEBUG == (flags & LIBJAMI_FLAG_DEBUG));
39 307 : jami::Logger::setSysLog(LIBJAMI_FLAG_SYSLOG == (flags & LIBJAMI_FLAG_SYSLOG));
40 307 : jami::Logger::setConsoleLog(LIBJAMI_FLAG_CONSOLE_LOG == (flags & LIBJAMI_FLAG_CONSOLE_LOG));
41 :
42 307 : const char* log_file = getenv("JAMI_LOG_FILE");
43 :
44 307 : if (log_file) {
45 0 : jami::Logger::setFileLog(log_file);
46 : }
47 :
48 : // Following function create a local static variable inside
49 : // This var must have the same live as Manager.
50 : // So we call it now to create this var.
51 307 : jami::getSignalHandlers();
52 :
53 : try {
54 : // current implementation use static variable
55 307 : auto& manager = jami::Manager::instance();
56 307 : manager.setAutoAnswer(flags & LIBJAMI_FLAG_AUTOANSWER);
57 :
58 : #if TARGET_OS_IOS
59 : if (flags & LIBJAMI_FLAG_IOS_EXTENSION)
60 : manager.isIOSExtension = true;
61 : #endif
62 307 : if (flags & LIBJAMI_FLAG_NO_AUTOSYNC)
63 0 : manager.syncOnRegister = false;
64 0 : } catch (...) {
65 0 : return false;
66 0 : }
67 :
68 : #ifdef __linux__
69 : // HACK: ignore system-wide GnuTLS configuration
70 : //
71 : // Since version 3.6.9, GnuTLS makes it possible to selectively disable algorithms
72 : // and protocols via a global configuration file. In particular, RSA PKCS1 v1.5
73 : // encryption can be disabled by setting the "allow-rsa-pkcs1-encrypt" option to
74 : // false. Doing this makes OpenDHT's putEncrypted function fail systematically and
75 : // therefore breaks several major features in Jami (e.g. sending contact requests).
76 : // As of December 2025, this is an issue on AlmaLinux 10 (there are other distributions
77 : // supported by Jami, including Ubuntu and Fedora, that include a system-wide
78 : // configuration file for GnuTLS, but for now they don't disable RSA PKCS1 v1.5).
79 : //
80 : // Some of the options in the configuration file can be bypassed by calling the right
81 : // function, but GnuTLS currently does not allow this in the case of RSA PKCS1 v1.5.
82 : // As a workaround, we take advantage of the fact that the location of the configuration
83 : // file can be changed at runtime via the GNUTLS_SYSTEM_PRIORITY_FILE environment
84 : // variable.
85 : static bool gnutlsInitialized = false;
86 307 : if (!gnutlsInitialized) {
87 38 : setenv("GNUTLS_SYSTEM_PRIORITY_FILE", "/dev/null", 1);
88 : // GnuTLS has already been initialized (in a library constructor) by the time we set
89 : // GNUTLS_SYSTEM_PRIORITY_FILE, so we need to reinitialize it in order for the new
90 : // value to be taken into account.
91 38 : gnutls_global_deinit();
92 38 : if (gnutls_global_init() < 0) {
93 0 : JAMI_ERROR("Failed to intialize gnutls");
94 0 : return false;
95 : }
96 38 : gnutlsInitialized = true;
97 : }
98 : #endif
99 :
100 307 : return true;
101 : }
102 :
103 : bool
104 32 : start(const std::filesystem::path& config_file) noexcept
105 : {
106 : try {
107 32 : jami::Manager::instance().init(config_file, initFlags);
108 0 : } catch (const std::exception& e) {
109 0 : JAMI_ERROR("Failed to start jami: {}", e.what());
110 0 : return false;
111 0 : }
112 32 : return true;
113 : }
114 :
115 : bool
116 0 : initialized() noexcept
117 : {
118 0 : return jami::Manager::initialized;
119 : }
120 :
121 : void
122 307 : fini() noexcept
123 : {
124 307 : jami::Manager::instance().finish();
125 307 : jami::Logger::fini();
126 307 : }
127 :
128 : void
129 0 : logging(const std::string& whom, const std::string& action) noexcept
130 : {
131 0 : if ("syslog" == whom) {
132 0 : jami::Logger::setSysLog(not action.empty());
133 0 : } else if ("console" == whom) {
134 0 : jami::Logger::setConsoleLog(not action.empty());
135 0 : } else if ("monitor" == whom) {
136 0 : jami::Logger::setMonitorLog(not action.empty());
137 0 : } else if ("file" == whom) {
138 0 : jami::Logger::setFileLog(action);
139 : } else {
140 0 : JAMI_ERROR("Bad log handler {}", whom);
141 : }
142 0 : }
143 :
144 : void
145 0 : CallbackWrapperBase::post(std::function<void()> cb)
146 : {
147 0 : if (auto io = jami::Manager::instance().ioContext())
148 0 : asio::post(*io, std::move(cb));
149 0 : }
150 :
151 : } // namespace libjami
|