Skip to content

Commit 47c5164

Browse files
committed
Added blinded contact records to Contacts and ConvoInfoVolatile
1 parent 77fb662 commit 47c5164

File tree

6 files changed

+1004
-74
lines changed

6 files changed

+1004
-74
lines changed

include/session/config/contacts.h

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,31 @@ typedef struct contacts_contact {
3636

3737
} contacts_contact;
3838

39+
typedef struct contacts_blinded_contact {
40+
char session_id[67]; // in hex; 66 hex chars + null terminator.
41+
char base_url[268]; // null-terminated (max length 267), normalized (i.e. always lower-case,
42+
// only has port if non-default, has trailing / removed)
43+
unsigned char pubkey[32]; // 32 bytes (not terminated, can contain nulls)
44+
45+
char name[101]; // This will be a 0-length strings when unset
46+
user_profile_pic profile_pic;
47+
48+
bool legacy_blinding;
49+
int64_t created; // unix timestamp (seconds)
50+
51+
} contacts_blinded_contact;
52+
53+
/// Struct containing a list of contacts_blinded_contact structs. Typically where this is returned
54+
/// by this API it must be freed (via `free()`) when done with it.
55+
///
56+
/// When returned as a pointer by a libsession-util function this is allocated in such a way that
57+
/// just the outer contacts_blinded_contact_list can be free()d to free both the list *and* the
58+
/// inner `value` and pointed-at values.
59+
typedef struct contacts_blinded_contact_list {
60+
contacts_blinded_contact** value; // array of blinded contacts
61+
size_t len; // length of `value`
62+
} contacts_blinded_contact_list;
63+
3964
/// API: contacts/contacts_init
4065
///
4166
/// Constructs a contacts config object and sets a pointer to it in `conf`.
@@ -208,6 +233,104 @@ LIBSESSION_EXPORT bool contacts_erase(config_object* conf, const char* session_i
208233
/// - `size_t` -- number of contacts
209234
LIBSESSION_EXPORT size_t contacts_size(const config_object* conf);
210235

236+
/// API: contacts/contacts_blinded_contacts
237+
///
238+
/// Retrieves a list of blinded contact records.
239+
///
240+
/// Declaration:
241+
/// ```cpp
242+
/// contacts_blinded_contact_list* contacts_blinded_contacts(
243+
/// [in] config_object* conf
244+
/// );
245+
/// ```
246+
///
247+
/// Inputs:
248+
/// - `conf` -- [in, out] Pointer to config_object object
249+
///
250+
/// Outputs:
251+
/// - `contacts_blinded_contact_list*` -- pointer to the list of blinded contact structs; the
252+
/// pointer belongs to the caller and must be freed when done with it.
253+
LIBSESSION_EXPORT contacts_blinded_contact_list* contacts_blinded_contacts(
254+
const config_object* conf);
255+
256+
/// API: contacts/contacts_get_blinded_contact
257+
///
258+
/// Fills `blinded_contact` with the blinded contact info given a blinded session ID (specified as a
259+
/// null-terminated hex string), if the blinded contact exists, and returns true. If the contact
260+
/// does not exist then `blinded_contact` is left unchanged and false is returned.
261+
///
262+
/// Declaration:
263+
/// ```cpp
264+
/// BOOL contacts_get_blinded_contact(
265+
/// [in] config_object* conf,
266+
/// [in] const char* blinded_session_id,
267+
/// [in] bool legacy_blinding,
268+
/// [out] contacts_blinded_contact* blinded_contact
269+
/// );
270+
/// ```
271+
///
272+
/// Inputs:
273+
/// - `conf` -- [in] Pointer to the config object
274+
/// - `blinded_session_id` -- [in] null terminated hex string
275+
/// - `legacy_blinding` -- [in] null terminated hex string
276+
/// - `blinded_contact` -- [out] the blinded contact info data
277+
///
278+
/// Output:
279+
/// - `bool` -- Returns true if blinded contact exists
280+
LIBSESSION_EXPORT bool contacts_get_blinded_contact(
281+
config_object* conf,
282+
const char* blinded_session_id,
283+
bool legacy_blinding,
284+
contacts_blinded_contact* blinded_contact) LIBSESSION_WARN_UNUSED;
285+
286+
/// API: contacts/contacts_set_blinded_contact
287+
///
288+
/// Adds or updates a blinded contact from the given contact info struct.
289+
///
290+
/// Declaration:
291+
/// ```cpp
292+
/// BOOL contacts_set_blinded_contact(
293+
/// [in] config_object* conf,
294+
/// [in] contacts_blinded_contact* bc
295+
/// );
296+
/// ```
297+
///
298+
/// Inputs:
299+
/// - `conf` -- [in] Pointer to the config object
300+
/// - `blinded_contact` -- [in] the blinded contact info data
301+
///
302+
/// Output:
303+
/// - `bool` -- Returns true if the call succeeds, false if an error occurs.
304+
LIBSESSION_EXPORT bool contacts_set_blinded_contact(
305+
config_object* conf, const contacts_blinded_contact* bc);
306+
307+
/// API: contacts/contacts_erase_blinded_contact
308+
///
309+
/// Erases a blinded contact from the blinded contact list. blinded_id is in hex. Returns true if
310+
/// the blinded contact was found and removed, false if the blinded contact was not present.
311+
///
312+
/// Declaration:
313+
/// ```cpp
314+
/// BOOL contacts_erase_blinded_contact(
315+
/// [in, out] config_object* conf,
316+
/// [in] const char* base_url,
317+
/// [in] const char* blinded_id,
318+
/// [in] bool legacy_blinding
319+
/// );
320+
/// ```
321+
///
322+
/// Inputs:
323+
/// - `conf` -- [in, out] Pointer to the config object
324+
/// - `base_url` -- [in] Text containing null terminated base url for the community this blinded
325+
/// contact originated from
326+
/// - `blinded_id` -- [in] Text containing null terminated hex string
327+
/// - `legacy_blinding` -- [in] Flag indicating whether this blinded contact used legacy blinding
328+
///
329+
/// Outputs:
330+
/// - `bool` -- True if erasing was successful
331+
LIBSESSION_EXPORT bool contacts_erase_blinded_contact(
332+
config_object* conf, const char* base_url, const char* blinded_id, bool legacy_blinding);
333+
211334
typedef struct contacts_iterator {
212335
void* _internals;
213336
} contacts_iterator;

include/session/config/contacts.hpp

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
#include <session/config.hpp>
88

99
#include "base.hpp"
10+
#include "community.hpp"
1011
#include "expiring.hpp"
1112
#include "namespaces.hpp"
1213
#include "notify.hpp"
1314
#include "profile_pic.hpp"
1415

1516
extern "C" struct contacts_contact;
17+
extern "C" struct contacts_blinded_contact;
1618

1719
using namespace std::literals;
1820

@@ -44,8 +46,24 @@ namespace session::config {
4446
/// E - Disappearing message timer, in seconds. Omitted when `e` is omitted.
4547
/// j - Unix timestamp (seconds) when the contact was created ("j" to match user_groups
4648
/// equivalent "j"oined field). Omitted if 0.
49+
///
50+
/// b - dict of blinded contacts. This is a nested dict where the outkey keys are the BASE_URL of
51+
/// the community the blinded contact originated from and the outer value is a dict containing:
52+
/// `#` - the 32-byte server pubkey
53+
/// `R` - dict of blinded contacts from the server; each key is the blinded session pubkey
54+
/// without the prefix ("R" to match user_groups equivalent "R"oom field, and to make use of
55+
/// existing community iterators, binary, 32 bytes), value is a dict containing keys:
56+
/// containing keys:
57+
///
58+
/// n - contact name (string). This is always serialized, even if empty (but empty indicates
59+
/// no name) so that we always have at least one key set (required to keep the dict value
60+
/// alive as empty dicts get pruned).
61+
/// p - profile url (string)
62+
/// q - profile decryption key (binary)
63+
/// j - Unix timestamp (seconds) when the contact was created ("j" to match user_groups
64+
/// equivalent "j"oined field). Omitted if 0.
65+
/// y - flag indicating whether the blinded message request is using legac"y" blinding.
4766

48-
/// Struct containing contact info.
4967
struct contact_info {
5068
static constexpr size_t MAX_NAME_LENGTH = 100;
5169

@@ -97,6 +115,47 @@ struct contact_info {
97115
void load(const dict& info_dict);
98116
};
99117

118+
struct blinded_contact_info : community {
119+
using community::community;
120+
121+
const std::string session_id() const; // in hex
122+
std::string name;
123+
profile_pic profile_picture;
124+
bool legacy_blinding;
125+
int64_t created = 0; // Unix timestamp (seconds) when this contact was added
126+
127+
explicit blinded_contact_info(
128+
std::string_view base_url,
129+
std::string_view blinded_id,
130+
std::span<const unsigned char> pubkey,
131+
bool legacy_blinding);
132+
133+
// Internal ctor/method for C API implementations:
134+
blinded_contact_info(const struct contacts_blinded_contact& c); // From c struct
135+
136+
/// API: contacts/blinded_contact_info::into
137+
///
138+
/// converts the contact info into a c struct
139+
///
140+
/// Inputs:
141+
/// - `c` -- Return Parameter that will be filled with data in blinded_contact_info
142+
void into(contacts_blinded_contact& c) const;
143+
144+
/// API: contacts/contact_info::set_name
145+
///
146+
/// Sets a name; this is exactly the same as assigning to .name directly,
147+
/// except that we throw an exception if the given name is longer than MAX_NAME_LENGTH.
148+
///
149+
/// Inputs:
150+
/// - `name` -- Name to assign to the contact
151+
void set_name(std::string name);
152+
153+
private:
154+
friend class Contacts;
155+
friend struct session::config::comm_iterator_helper;
156+
void load(const dict& info_dict);
157+
};
158+
100159
class Contacts : public ConfigBase {
101160

102161
public:
@@ -339,6 +398,70 @@ class Contacts : public ConfigBase {
339398

340399
bool accepts_protobuf() const override { return true; }
341400

401+
protected:
402+
// Drills into the nested dicts to access open group details
403+
DictFieldProxy blinded_contact_field(
404+
const blinded_contact_info& bc,
405+
std::span<const unsigned char>* get_pubkey = nullptr) const;
406+
407+
public:
408+
/// API: contacts/Contacts::blinded_contacts
409+
///
410+
/// Retrieves a list of all known blinded contacts.
411+
///
412+
/// Inputs: None
413+
///
414+
/// Outputs:
415+
/// - `std::vector<blinded_contact_info>` - Returns a list of blinded_contact_info
416+
std::vector<blinded_contact_info> blinded_contacts() const;
417+
418+
/// API: contacts/Contacts::get_blinded
419+
///
420+
/// Looks up and returns a blinded contact by blinded session ID (hex). Returns nullopt if the
421+
/// blinded session ID was not found, otherwise returns a filled out `blinded_contact_info`.
422+
///
423+
/// Inputs:
424+
/// - `pubkey_hex` -- hex string of the session id
425+
/// - `legacy_blinding` -- flag indicating whether the pubkey is using legacy blinding
426+
///
427+
/// Outputs:
428+
/// - `std::optional<blinded_contact_info>` - Returns nullopt if blinded session ID was not
429+
/// found, otherwise a filled out blinded_contact_info
430+
std::optional<blinded_contact_info> get_blinded(
431+
std::string_view pubkey_hex, bool legacy_blinding) const;
432+
433+
/// API: contacts/contacts::set_blinded_contact
434+
///
435+
/// Sets or updates multiple blinded contact info values at once with the given info. The usual
436+
/// use is to access the current info, change anything desired, then pass it back into
437+
/// set_blinded_contact, e.g.:
438+
///
439+
///```cpp
440+
/// auto c = contacts.get_blinded(pubkey, legacy_blinding);
441+
/// c.name = "Session User 42";
442+
/// contacts.set_blinded_contact(c);
443+
///```
444+
///
445+
/// Inputs:
446+
/// - `bc` -- set_blinded_contact value to set
447+
bool set_blinded_contact(const blinded_contact_info& bc);
448+
449+
/// API: contacts/contacts::erase_blinded_contact
450+
///
451+
/// Removes a blinded contact, if present. Returns true if it was found and removed, false
452+
/// otherwise. Note that this removes all fields related to a blinded contact, even fields we do
453+
/// not know about.
454+
///
455+
/// Inputs:
456+
/// - `base_url` -- the base url for the community this blinded contact originated from
457+
/// - `blinded_id` -- hex string of the blinded id
458+
/// - `legacy_blinding` -- flag indicating whether `blinded_id` is using legacy blinding
459+
///
460+
/// Outputs:
461+
/// - `bool` - Returns true if contact was found and removed, false otherwise
462+
bool erase_blinded_contact(
463+
std::string_view base_url, std::string_view blinded_id, bool legacy_blinding);
464+
342465
struct iterator;
343466
/// API: contacts/contacts::begin
344467
///

0 commit comments

Comments
 (0)