Ring Daemon
Loading...
Searching...
No Matches
contact_list.h
Go to the documentation of this file.
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#pragma once
18
19#include "jami_contact.h"
20
21#include <dhtnet/certstore.h>
22#include <opendht/infohash.h>
23#include <opendht/crypto.h>
24
25#include <map>
26#include <mutex>
27#include <chrono>
28
29namespace jami {
30
32{
33public:
34 using clock = std::chrono::system_clock;
35 using time_point = clock::time_point;
36 using VerifyResult = dht::crypto::TrustList::VerifyResult;
37
38 using OnContactAdded = std::function<void(const std::string&, bool)>;
39 using OnContactRemoved = std::function<void(const std::string&, bool)>;
41 = std::function<void(const std::string&, const std::string&, const std::vector<uint8_t>&, time_t)>;
42 using OnAcceptConversation = std::function<void(const std::string&, const std::string&)>;
43 using OnConfirmation = std::function<void(const std::string&, const std::string&)>;
44 using OnDevicesChanged = std::function<void(const std::map<dht::PkId, KnownDevice>&)>;
45
55
56 ContactList(const std::string& accountId,
57 const std::shared_ptr<crypto::Certificate>& cert,
58 const std::filesystem::path& path,
61
62 const std::string& accountId() const { return accountId_; }
63
64 void load();
65 void save();
66
67 /* Contacts */
68 std::map<std::string, std::string> getContactDetails(const dht::InfoHash&) const;
69 std::optional<Contact> getContactInfo(const dht::InfoHash&) const;
70
71 bool removeContact(const dht::InfoHash&, bool ban);
72 bool removeContactConversation(const dht::InfoHash&);
73 bool addContact(const dht::InfoHash&, bool confirmed = false, const std::string& conversationId = "");
74 bool updateConversation(const dht::InfoHash& h, const std::string& conversationId, bool added = false);
75
76 bool setCertificateStatus(const std::string& cert_id, const dhtnet::tls::TrustStore::PermissionStatus status);
77
78 bool setCertificateStatus(const std::shared_ptr<crypto::Certificate>& cert,
79 dhtnet::tls::TrustStore::PermissionStatus status,
80 bool local = true);
81
82 dhtnet::tls::TrustStore::PermissionStatus getCertificateStatus(const std::string& cert_id) const
83 {
84 return trust_->getCertificateStatus(cert_id);
85 }
86
87 std::vector<std::string> getCertificatesByStatus(dhtnet::tls::TrustStore::PermissionStatus status) const
88 {
89 return trust_->getCertificatesByStatus(status);
90 }
91
92 bool isAllowed(const crypto::Certificate& crt, bool allowPublic) { return trust_->isAllowed(crt, allowPublic); }
93
94 VerifyResult isValidAccountDevice(const crypto::Certificate& crt) const { return accountTrust_.verify(crt); }
95
96 const std::map<dht::InfoHash, Contact>& getContacts() const;
97 void setContacts(const std::map<dht::InfoHash, Contact>&);
98 void updateContact(const dht::InfoHash&, const Contact&, bool emit = true);
99
101 void saveContacts() const;
102
103 const std::filesystem::path& path() const { return path_; }
104
105 /* Contact requests */
106
109 bool onTrustRequest(const dht::InfoHash& peer_account,
110 const std::shared_ptr<dht::crypto::PublicKey>& peer_device,
111 time_t received,
112 bool confirm,
113 const std::string& conversationId,
114 std::vector<uint8_t>&& payload);
115 std::vector<std::map<std::string, std::string>> getTrustRequests() const;
116 std::map<std::string, std::string> getTrustRequest(const dht::InfoHash& from) const;
117 void acceptConversation(const std::string& convId,
118 const std::string& deviceId = ""); // ToDO this is a bit dirty imho
119 bool acceptTrustRequest(const dht::InfoHash& from);
120 bool discardTrustRequest(const dht::InfoHash& from);
121
122 /* Devices */
123 const std::map<dht::PkId, KnownDevice>& getKnownDevices() const { return knownDevices_; }
124 void foundAccountDevice(const dht::PkId& device,
125 const std::string& name = {},
126 const time_point& last_sync = time_point::min());
127 bool foundAccountDevice(const std::shared_ptr<dht::crypto::Certificate>& crt,
128 const std::string& name = {},
129 const time_point& last_sync = time_point::min(),
130 bool notify = true);
131 bool removeAccountDevice(const dht::PkId& device);
132 void setAccountDeviceName(const dht::PkId& device, const std::string& name);
133 std::string getAccountDeviceName(const dht::PkId& device) const;
134
135 DeviceSync getSyncData() const;
136 bool syncDevice(const dht::PkId& device, const time_point& syncDate);
137
138private:
139 const std::string accountId_;
140 const std::filesystem::path path_;
141 mutable std::mutex mutex_;
142 std::map<dht::InfoHash, Contact> contacts_;
143 std::map<dht::InfoHash, TrustRequest> trustRequests_;
144 std::map<dht::InfoHash, KnownDevice> knownDevicesLegacy_;
145
146 std::map<dht::PkId, KnownDevice> knownDevices_;
147
148 // Trust store with account main certificate as the only CA
149 dht::crypto::TrustList accountTrust_;
150 // Trust store for to match peer certificates
151 std::unique_ptr<dhtnet::tls::TrustStore> trust_;
152 std::string accountUri_;
153
154 OnChangeCallback callbacks_;
155
156 void loadContacts();
157 void loadTrustRequests();
158
159 void loadKnownDevices();
160 void saveKnownDevices() const;
161
163 void saveTrustRequests() const;
164};
165
166} // namespace jami
const std::string & accountId() const
std::function< void(const std::string &, bool)> OnContactRemoved
bool removeAccountDevice(const dht::PkId &device)
std::vector< std::map< std::string, std::string > > getTrustRequests() const
void foundAccountDevice(const dht::PkId &device, const std::string &name={}, const time_point &last_sync=time_point::min())
bool removeContactConversation(const dht::InfoHash &)
bool addContact(const dht::InfoHash &, bool confirmed=false, const std::string &conversationId="")
std::function< void(const std::string &, bool)> OnContactAdded
std::function< void(const std::string &, const std::string &, const std::vector< uint8_t > &, time_t)> OnIncomingTrustRequest
clock::time_point time_point
void setContacts(const std::map< dht::InfoHash, Contact > &)
const std::filesystem::path & path() const
void saveContacts() const
Should be called only after updateContact.
bool onTrustRequest(const dht::InfoHash &peer_account, const std::shared_ptr< dht::crypto::PublicKey > &peer_device, time_t received, bool confirm, const std::string &conversationId, std::vector< uint8_t > &&payload)
Inform of a new contact request.
std::string getAccountDeviceName(const dht::PkId &device) const
VerifyResult isValidAccountDevice(const crypto::Certificate &crt) const
std::chrono::system_clock clock
DeviceSync getSyncData() const
void setAccountDeviceName(const dht::PkId &device, const std::string &name)
bool acceptTrustRequest(const dht::InfoHash &from)
bool discardTrustRequest(const dht::InfoHash &from)
std::map< std::string, std::string > getContactDetails(const dht::InfoHash &) const
void updateContact(const dht::InfoHash &, const Contact &, bool emit=true)
bool setCertificateStatus(const std::string &cert_id, const dhtnet::tls::TrustStore::PermissionStatus status)
dhtnet::tls::TrustStore::PermissionStatus getCertificateStatus(const std::string &cert_id) const
std::function< void(const std::map< dht::PkId, KnownDevice > &)> OnDevicesChanged
bool syncDevice(const dht::PkId &device, const time_point &syncDate)
const std::map< dht::PkId, KnownDevice > & getKnownDevices() const
std::optional< Contact > getContactInfo(const dht::InfoHash &) const
const std::map< dht::InfoHash, Contact > & getContacts() const
std::function< void(const std::string &, const std::string &)> OnAcceptConversation
void acceptConversation(const std::string &convId, const std::string &deviceId="")
std::map< std::string, std::string > getTrustRequest(const dht::InfoHash &from) const
dht::crypto::TrustList::VerifyResult VerifyResult
std::function< void(const std::string &, const std::string &)> OnConfirmation
std::vector< std::string > getCertificatesByStatus(dhtnet::tls::TrustStore::PermissionStatus status) const
bool isAllowed(const crypto::Certificate &crt, bool allowPublic)
bool updateConversation(const dht::InfoHash &h, const std::string &conversationId, bool added=false)
bool removeContact(const dht::InfoHash &, bool ban)
void emitSignal(Args... args)
Definition jami_signal.h:64
OnIncomingTrustRequest trustRequest
OnAcceptConversation acceptConversation