manage-contacts.md (7067B)
1 # Managing Contacts 2 3 This section will present how to find and add a contact from the DHT to the client. The usage of a name server will not be explained here. If you want details about that, please read: https://git.ring.cx/savoirfairelinux/ring-project/wikis/technical/Name-Server-Protocol 4 5 ## Presence on the network 6 7 ### Announce the presence on the DHT 8 9 The presence is pretty simple to announce on the DHT. In fact, it's 10 just a value containing the device hash (see [previous 11 section](https://git.ring.cx/savoirfairelinux/ring-project/wikis/technical/2.1.-Manage-Accounts)) 12 on the hash corresponding to the Ring ID. So, if we have the account 13 `bf5f1e21d3eb2c1246946aa49d5dcf3e5b9cb1b9` with the device 14 `62fbdff0ce86f368c7d3c2682539e5ba9e06404f`, the following defined 15 value will be sent over the DHT: 16 17 ```cpp 18 /** 19 * Device announcement stored on DHT. 20 */ 21 struct RingAccount::DeviceAnnouncement : public dht::SignedValue<DeviceAnnouncement> 22 { 23 private: 24 using BaseClass = dht::SignedValue<DeviceAnnouncement>; 25 public: 26 static const constexpr dht::ValueType& TYPE = dht::ValueType::USER_DATA; 27 dht::InfoHash dev; 28 MSGPACK_DEFINE_MAP(dev); 29 }; 30 ``` 31 32 (This value can be put with `dht_.put(h, VALUE, dht::DoneCallback{}, {}, true);`, as a permanent put). If the device is announced, the device is present. For now, there is no way to delete or edit a value on the DHT (this will come when OpenDHT will supports ECC). So, the presence always have a delay for now (mean delay: expire-time/2, so 2min30 for now). 33 34 ### Get if a contact is present 35 36 Now our presence on the network, it's time to get if somebody is present on the DHT. With the previous section, it's easy to do the reverse process. To know if somebody is present on the DHT (ex: `bf5f1e21d3eb2c1246946aa49d5dcf3e5b9cb1b9`), we have to get value at `bf5f1e21d3eb2c1246946aa49d5dcf3e5b9cb1b9` and retrieve the `DeviceAnnouncement` on this hash. The related code in the ring daemon is in `ringaccount.cpp`: 37 38 ```cpp 39 auto shared = std::static_pointer_cast<RingAccount>(shared_from_this()); 40 auto treatedDevices = std::make_shared<std::set<dht::InfoHash>>(); 41 dht_.get<dht::crypto::RevocationList>(to, [to](dht::crypto::RevocationList&& crl){ 42 tls::CertificateStore::instance().pinRevocationList(to.toString(), std::move(crl)); 43 return true; 44 }); 45 dht_.get<DeviceAnnouncement>(to, [shared,to,treatedDevices,op](DeviceAnnouncement&& dev) { 46 if (dev.from != to) 47 return true; 48 if (treatedDevices->emplace(dev.dev).second) 49 op(shared, dev.dev); 50 return true; 51 }, [=](bool /*ok*/){ 52 { 53 std::lock_guard<std::recursive_mutex> lock(shared->buddyInfoMtx); 54 auto buddy_info_it = shared->trackedBuddies_.find(to); 55 if (buddy_info_it != shared->trackedBuddies_.end()) { 56 if (not treatedDevices->empty()) { 57 for (auto& device_id : *treatedDevices) 58 shared->onTrackedBuddyOnline(buddy_info_it, device_id); 59 } else 60 shared->onTrackedBuddyOffline(buddy_info_it); 61 } 62 } 63 RING_DBG("[Account %s] found %lu devices for %s", 64 getAccountID().c_str(), treatedDevices->size(), to.to_c_str()); 65 if (end) end(shared, not treatedDevices->empty()); 66 }); 67 ``` 68 69 And that's all. 70 71 ### Pending request 72 73 ### Send a request 74 75 **TODO craft request** 76 77 Finally, once the trust request is crafted, we can push the request to the following hash: `InfoHash("inbox:" + deviceId)` 78 79 The following code is used in the daemon: 80 ```cpp 81 dht_.putEncrypted(dht::InfoHash::get("inbox:"+dev.toString()), dev, dht::TrustRequest(DHT_TYPE_NS, payload)); 82 ``` 83 84 ### Receiving a request 85 86 **TODO** 87 88 (Accept/Block/Discard) 89 90 ### Daemon API 91 92 All methods to follow the presence of a buddy is located in the `PresenceManager` such as: 93 94 ```xml 95 <signal name="newBuddyNotification" tp:name-for-bindings="newBuddyNotification"> 96 <tp:added version="1.3.0"/> 97 <tp:docstring> 98 Notify when a registered presence uri presence informations changes 99 </tp:docstring> 100 <arg type="s" name="accountID"> 101 <tp:docstring> 102 The associated account 103 </tp:docstring> 104 </arg> 105 <arg type="s" name="buddyUri"> 106 <tp:docstring> 107 The registered URI 108 </tp:docstring> 109 </arg> 110 <arg type="b" name="status"> 111 <tp:docstring> 112 Is the URI present or not 113 </tp:docstring> 114 </arg> 115 <arg type="s" name="lineStatus"> 116 <tp:docstring> 117 A string containing informations from the user (human readable) 118 </tp:docstring> 119 </arg> 120 </signal> 121 ``` 122 123 All methods and signals used to manage trust requests and contacts are in the `ConfigurationManager` such as: 124 125 ```xml 126 <method name="getTrustRequests" tp:name-for-bindings="getTrustRequests"> 127 <tp:added version="2.2.0"/> 128 <arg type="s" name="accountID" direction="in"> 129 </arg> 130 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/> 131 <arg type="aa{ss}" name="requests" direction="out" > 132 <tp:docstring> 133 A list of contact request details. Details: 134 - from: account ID of sender 135 - received: UNIX timestamp of reception date 136 - payload: attached payload 137 </tp:docstring> 138 </arg> 139 </method> 140 141 <method name="acceptTrustRequest" tp:name-for-bindings="acceptTrustRequest"> 142 <tp:added version="2.2.0"/> 143 <arg type="s" name="accountID" direction="in"> 144 </arg> 145 <arg type="s" name="from" direction="in"> 146 </arg> 147 <arg type="b" name="success" direction="out" tp:type="Boolean"> 148 <tp:docstring> 149 True if the operation succeeded. 150 </tp:docstring> 151 </arg> 152 </method> 153 154 <method name="discardTrustRequest" tp:name-for-bindings="discardTrustRequest"> 155 <tp:added version="2.2.0"/> 156 <arg type="s" name="accountID" direction="in"> 157 </arg> 158 <arg type="s" name="from" direction="in"> 159 </arg> 160 <arg type="b" name="success" direction="out" tp:type="Boolean"> 161 <tp:docstring> 162 True if the operation succeeded. 163 </tp:docstring> 164 </arg> 165 </method> 166 167 <signal name="incomingTrustRequest" tp:name-for-bindings="incomingTrustRequest"> 168 <tp:added version="2.2.0"/> 169 <tp:docstring> 170 Notify clients that a new contact request has been received. 171 </tp:docstring> 172 <arg type="s" name="accountID"> 173 </arg> 174 <arg type="s" name="from"> 175 </arg> 176 <arg type="ay" name="payload"> 177 </arg> 178 <arg type="t" name="receiveTime"> 179 </arg> 180 </signal> 181 182 <method name="sendTrustRequest" tp:name-for-bindings="sendTrustRequest"> 183 <tp:added version="2.2.0"/> 184 <arg type="s" name="accountID" direction="in"> 185 </arg> 186 <arg type="s" name="to" direction="in"> 187 </arg> 188 <arg type="ay" name="payload" direction="in"> 189 </arg> 190 </method> 191 192 <method name="addContact" tp:name-for-bindings="addContact"> 193 <tp:added version="3.0.0"/> 194 <arg type="s" name="accountID" direction="in"> 195 </arg> 196 <arg type="s" name="uri" direction="in"> 197 </arg> 198 </method> 199 200 <method name="removeContact" tp:name-for-bindings="removeContact"> 201 <tp:added version="3.0.0"/> 202 <arg type="s" name="accountID" direction="in"> 203 </arg> 204 <arg type="s" name="uri" direction="in"> 205 </arg> 206 <arg type="b" name="ban" direction="in" tp:type="Boolean"> 207 <tp:docstring> 208 True if the the contact should be banned. 209 If false, the contact is removed from the contact list (banned or not). 210 </tp:docstring> 211 </arg> 212 </method> 213 ``` 214 215 If you want some examples, these methods are used into `contactmodel.cpp` in LRC.