連絡管理

このセクションでは,DHTからクライアントに連絡先を検索し追加する方法を示します.名サーバの使用についてはここで説明されません.それについて詳細を知りたい場合は, 名前 サーバープロトコル を読みください.

ネットワークでの存在

DHTに存在を知らせる

存在はDHTで発表するのはかなり簡単です.実際には,デバイスハッシュを含む値です (前セクション, アカウント管理) キーの指紋に対応するハッシュです.

/**
 * Device announcement stored on DHT.
 */
struct DeviceAnnouncement : public dht::SignedValue<DeviceAnnouncement>
{
private:
    using BaseClass = dht::SignedValue<DeviceAnnouncement>;

public:
    static const constexpr dht::ValueType& TYPE = dht::ValueType::USER_DATA;
    dht::InfoHash dev;
    std::shared_ptr<dht::crypto::PublicKey> pk;
    MSGPACK_DEFINE_MAP(dev, pk)
};

(この値は,doneCallback{}, {}, true);`,永久的なセットとして設定できます).デバイスが発表された場合,デバイスは存在します.現在,DHTの値を削除または編集する方法はありません (OpenDHTがECCをサポートすると表示されます).

連絡先がある場合は連絡

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 daemon is in jamiaccount.cpp:

auto shared = std::static_pointer_cast<RingAccount>(shared_from_this());
auto treatedDevices = std::make_shared<std::set<dht::InfoHash>>();
dht_.get<dht::crypto::RevocationList>(to, [to](dht::crypto::RevocationList&& crl){
    tls::CertificateStore::instance().pinRevocationList(to.toString(), std::move(crl));
    return true;
});
dht_.get<DeviceAnnouncement>(to, [shared,to,treatedDevices,op](DeviceAnnouncement&& dev) {
    if (dev.from != to)
        return true;
    if (treatedDevices->emplace(dev.dev).second)
        op(shared, dev.dev);
    return true;
}, [=](bool /*ok*/){
    {
        std::lock_guard<std::recursive_mutex> lock(shared->buddyInfoMtx);
        auto buddy_info_it = shared->trackedBuddies_.find(to);
        if (buddy_info_it != shared->trackedBuddies_.end()) {
            if (not treatedDevices->empty()) {
                for (auto& device_id : *treatedDevices)
                    shared->onTrackedBuddyOnline(buddy_info_it, device_id);
            } else
                shared->onTrackedBuddyOffline(buddy_info_it);
        }
    }
    RING_DBG("[Account %s] found %lu devices for %s",
                getAccountID().c_str(), treatedDevices->size(), to.to_c_str());
    if (end) end(shared, not treatedDevices->empty());
});

ほら ほら

Client perspective

<method name="subscribeBuddy" tp:name-for-bindings="subscribeBuddy">
    <tp:docstring>
        Ask be be notified when 'uri' presence change
    </tp:docstring>
    <tp:added version="1.3.0"/>
    <arg type="s" name="accountID" direction="in">
        <tp:docstring>
            An account from which get request presence informations
        </tp:docstring>
    </arg>
    <arg type="s" name="uri" direction="in">
        <tp:docstring>
            A SIP uri to watch
        </tp:docstring>
    </arg>
    <arg type="b" name="flag" direction="in">
        <tp:docstring>
        </tp:docstring>
    </arg>
</method>

<signal name="newBuddyNotification" tp:name-for-bindings="newBuddyNotification">
    <tp:added version="1.3.0"/>
    <tp:docstring>
        Notify when a registered presence uri presence informations changes
    </tp:docstring>
    <arg type="s" name="accountID">
        <tp:docstring>
            The associated account
        </tp:docstring>
    </arg>
    <arg type="s" name="buddyUri">
        <tp:docstring>
            The registered URI
        </tp:docstring>
    </arg>
    <arg type="i" name="status">
        <tp:docstring>
            Is the URI present or not
        </tp:docstring>
    </arg>
    <arg type="s" name="lineStatus">
        <tp:docstring>
            A string containing informations from the user (human readable)
        </tp:docstring>
    </arg>
</signal>

<method name="publish" tp:name-for-bindings="publish">
    <tp:added version="1.3.0"/>
    <arg type="s" name="accountID" direction="in">
        <tp:docstring>
            The account from which the presence will be emitted
        </tp:docstring>
    </arg>
    <arg type="b" name="status" direction="in">
        <tp:docstring>
            Is this account present or not
        </tp:docstring>
    </arg>
    <arg type="s" name="note" direction="in">
        <tp:docstring>
            A message transmitted by the server to other users
        </tp:docstring>
    </arg>
</method>

Are the main APIs for clients. subscribeBuddy will listen on the DHT to detect presence changes and newBuddyNotification will be sent whenever a new status is detected:

  • The status sent to the client is now 0=offline (no device found on the DHT), 1=dht_presence (at least a device is found on the DHT), 2=connected (with a TCP + SIP channel, so ready to exchange data).

  • lineStatus will contain any custom status sent by the peer (e.g. Lunch Time!)

publish is used for publishing a custom note (status is ignored for Jami accounts, note will contain the custom status).

RFC3863 is used to send status over the SIP connection.

待機中の要請

要求を送信する

TODOの船要求

最後に,信頼要求が作成されたら,次のハッシュに要求を押し付けることができます: InfoHash("inbox:" + deviceId)

ダイモンには次のコードが使用されます.

dht_.putEncrypted(dht::InfoHash::get("inbox:"+dev.toString()), dev, dht::TrustRequest(DHT_TYPE_NS, payload));

申請を受信する

TODO

(受け入れ/ブロック/棄却)

デイモン API

PresenceManager の 友達の存在を追跡するすべての方法は,次のとおりです.

<signal name="newBuddyNotification" tp:name-for-bindings="newBuddyNotification">
    <tp:added version="1.3.0"/>
    <tp:docstring>
        Notify when a registered presence uri presence informations changes
    </tp:docstring>
    <arg type="s" name="accountID">
        <tp:docstring>
            The associated account
        </tp:docstring>
    </arg>
    <arg type="s" name="buddyUri">
        <tp:docstring>
            The registered URI
        </tp:docstring>
    </arg>
    <arg type="b" name="status">
        <tp:docstring>
            Is the URI present or not
        </tp:docstring>
    </arg>
    <arg type="s" name="lineStatus">
        <tp:docstring>
            A string containing informations from the user (human readable)
        </tp:docstring>
    </arg>
</signal>

信頼要求および連絡先を管理するために使用されるすべての方法と信号は, ConfigurationManager にあります:

<method name="getTrustRequests" tp:name-for-bindings="getTrustRequests">
    <tp:added version="2.2.0"/>
    <arg type="s" name="accountID" direction="in">
    </arg>
    <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/>
    <arg type="aa{ss}" name="requests" direction="out" >
        <tp:docstring>
            A list of contact request details. Details:
            - from: account ID of sender
            - received: UNIX timestamp of reception date
            - payload: attached payload
        </tp:docstring>
    </arg>
</method>

<method name="acceptTrustRequest" tp:name-for-bindings="acceptTrustRequest">
    <tp:added version="2.2.0"/>
    <arg type="s" name="accountID" direction="in">
    </arg>
    <arg type="s" name="from" direction="in">
    </arg>
    <arg type="b" name="success" direction="out" tp:type="Boolean">
        <tp:docstring>
            True if the operation succeeded.
        </tp:docstring>
    </arg>
</method>

<method name="discardTrustRequest" tp:name-for-bindings="discardTrustRequest">
    <tp:added version="2.2.0"/>
    <arg type="s" name="accountID" direction="in">
    </arg>
    <arg type="s" name="from" direction="in">
    </arg>
    <arg type="b" name="success" direction="out" tp:type="Boolean">
        <tp:docstring>
            True if the operation succeeded.
        </tp:docstring>
    </arg>
</method>

<signal name="incomingTrustRequest" tp:name-for-bindings="incomingTrustRequest">
    <tp:added version="2.2.0"/>
    <tp:docstring>
        Notify clients that a new contact request has been received.
    </tp:docstring>
    <arg type="s" name="accountID">
    </arg>
    <arg type="s" name="from">
    </arg>
    <arg type="ay" name="payload">
    </arg>
    <arg type="t" name="receiveTime">
    </arg>
</signal>

<method name="sendTrustRequest" tp:name-for-bindings="sendTrustRequest">
    <tp:added version="2.2.0"/>
    <arg type="s" name="accountID" direction="in">
    </arg>
    <arg type="s" name="to" direction="in">
    </arg>
    <arg type="ay" name="payload" direction="in">
    </arg>
</method>

<method name="addContact" tp:name-for-bindings="addContact">
    <tp:added version="3.0.0"/>
    <arg type="s" name="accountID" direction="in">
    </arg>
    <arg type="s" name="uri" direction="in">
    </arg>
</method>

<method name="removeContact" tp:name-for-bindings="removeContact">
    <tp:added version="3.0.0"/>
    <arg type="s" name="accountID" direction="in">
    </arg>
    <arg type="s" name="uri" direction="in">
    </arg>
    <arg type="b" name="ban" direction="in" tp:type="Boolean">
        <tp:docstring>
            True if the the contact should be banned.
            If false, the contact is removed from the contact list (banned or not).
        </tp:docstring>
    </arg>
</method>

図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書 図書