Thủy

A swarm (group chat) is a set of participants capable of resilient, decentralized communication. For example, if two participants lose connectivity with the rest of the group (e.g., during an Internet outage) but can still reach each other over a LAN or subnetwork, they can exchange messages locally and then synchronize with the rest of the group once connectivity is restored.

A swarm is defined by the following properties:

  1. Ability to split and merge based on network connectivity.

  2. History synchronization. Every participant must be able to send a message to the entire group.

  3. Không có cơ quan trung ương, không thể tin vào bất kỳ máy chủ nào.

  4. Non-repudiation. Devices must be able to verify past messages' validity and to replay the entire history.

  5. Perfect Forward Secrecy (PFS) is provided on the transport channels. Storage is handled by each device.

Ý tưởng chính là có được một cây Merkle đồng bộ với các thành viên.

We identified four modes for swarms that we want to implement:

  • ONE_TO_ONE: A private conversation between two endpoints—either between two users or with yourself.

  • ADMIN_INVITES_ONLY: A swarm in which only the administrator can invite members (for example, a teacher-managed classroom).

  • INVITES_ONLY: A closed swarm that admits members strictly by invitation; no one may join without explicit approval.

  • PUBLIC: A public swarm that anyone can join without prior invitation (For example a forum).

Các kịch bản

Tạo một nhóm

Bob muốn tạo ra một đám đông mới

  1. Bob creates a local Git repository.

  2. Sau đó, ông ta tạo ra một cam kết ban đầu được ký kết với những điều sau:

    • Chìa khóa công khai của anh ấy trong /admins

    • Giấy chứng nhận thiết bị của anh ta trong ̀ / thiết bị `

    • CRL của anh ta trong ̀ /crls`

  3. Hash của commit đầu tiên trở thành ID của cuộc trò chuyện

  4. Bob announces to his other devices that he created a new conversation. This is done via an invite to join the group sent through the DHT to other devices linked to that account.

Thêm ai đó

Bob adds Alice

  1. Bob adds Alice to the repo:

    • Thêm URI được mời vào /invited

    • Thêm CRL vào /crls

  2. Bob sends a request on the DHT.

Nhận lời mời

Alice gets the invite to join the previously created swarm

  1. Alice accepts the invite (if she declines, nothing happens; she will remain in the "invited" list, and will never receive any messages)

  2. A peer-to-peer connection is established between Alice and Bob.

  3. Alice pulls the Git repository from Bob. WARNING this means that messages require a connection, not from the DHT as it is today.

  4. Alice validates the commits from Bob.

  5. To validate that Alice is a member, she removes the invite from /invited directory, then adds her certificate to the /members directory

  6. Once all commits are validated and syncronized to her device, Alice discovers other members of the group. with these peers, she will then construct the DRT with Bob as a bootstrap.

Gửi tin nhắn

Alice sends a message to Bob

  1. Alice creates a commit message. She constructs a JSON payload containing the MIME type and message body. For example:

{
    "type": "text/plain",
    "body": "hello"
}
  1. Alice ensure her device credentials are present. If Alice’s device certificate or its associated CRL isn’t already stored in the repository, she adds them so that other participants can verify the commit.

  2. Alice commits to the repository (Because Jami relies primarily on commit-message metadata rather than file contents, merge conflicts are rare; the only potential conflicts would involve CRLs or certificates, which are versioned in a dedicated location).

  3. Alice announces the commit via the DRT with a service message and pings the DHT for mobile devices (they must receive a push notification).

Ghi chú

To notify other devices, the sender transmits a SIP message with type: application/im-gitmessage-id. The JSON payload includes the deviceId (the sender’s), the conversationId and the reference (hash) of the new commit.

Nhận tin nhắn

Bob receives a message from Alice

  1. Bob performs a Git pull on Alice's repository.

  2. All incoming commits MUST be verified by a hook.

  3. If all commits are valid, commits are stored and displayed.Bob then announces the message via the DRT for other devices.

  4. If any commit is invalid, pull is aborted. Alice must restore her repository to a correct state before retrying.

Đăng bằng một cam kết

Để tránh người dùng đẩy một số cam kết không mong muốn (với xung đột, tin nhắn sai, vv), đây là cách mỗi cam kết (từ cũ nhất đến mới nhất) MUST được xác nhận trước khi sáp nhập một chi nhánh từ xa:

Ghi chú

  1. If the validation fails, the fetch is ignored and we do not merge the branch (and remove the data), and the user should be notified.

  2. If a fetch is too big, it's not merged.

  • For each incoming commit, ensure that the sending device is currently authorized and that the issuer’s certificate exists under /members or /admins, and the device’s certificate under /devices.

  • Then handle one of three cases, based on the commit’s parent count:

    • Merge Commit (2 parents). No further validation is required, merges are always accepted.

    • Initial Commit (0 parents). Validate that this is the very first repository snapshot:

      • Admin certificate is added.

      • Device certificate is added.

      • CRLs (Certificate Revocation Lists) are added.

      • No other files are present.

    • Ordinary Commit (1 parent). The commit message must be JSON with a top‑level type field. Handle each type as follows:

      • If text (or any non–file‑modifying MIME type)

        • Signature is valid against the author’s certificate in the repo.

        • No unexpected files are added or removed.

      • If vote

        • voteType is one of the supported values (e.g. "ban", "unban").

        • The vote matches the signing user.

        • The signer is an admin, their device is present, and not themselves banned.

        • No unexpected files are added or removed.

      • If member

        • If adds

          • Properly signed by the inviter.

          • New member’s URI appears under /invited.

          • No unexpected files are added or removed.

          • If ONE_TO_ONE, ensure exactly one admin and one member.

          • If ADMIN_INVITES_ONLY, the inviter must be an admin.

        • If joins

          • Properly signed by the joining device.

          • Device certificate added under /devices.

          • Corresponding invite removed from /invited and certificate added to /members.

          • No unexpected files are added or removed.

        • If banned

          • Vote is valid per the vote rules above.

          • Ban is issued by an admin.

          • Target’s certificate moved to /banned.

          • Only files related to the ban vote are removed.

          • No unexpected files are added or removed.

      • Fallback. If the commit’s type or structure is unrecognized, reject it and notify the peer (or user) that they may be running an outdated version or attempting unauthorized changes.

Thiết bị cấm

Quan trọng

Jami source code tends to use the terms (un)ban, while the user interface uses the terms (un)block.

Alice, Bob, Carla, Denys are in a swarm. Alice issues a ban against Denys.

In a fully peer‑to‑peer system with no central authority, this simple action exposes three core challenges:

  1. Untrusted Timestamps: Commit timestamps cannot be relied upon for ordering ban events, as any device can forge or replay commits with arbitrary dates.

  2. Conflicting bans: In cases where multiple admin devices exist, network partitions can result in conflicting ban decisions. For instance, if Alice can communicate with Bob but not with Denys and Carla, while Carla can communicate with Denys, conflicting bans may occur. If Denys bans Alice while Alice bans Denys, the group’s state becomes unclear when all members eventually reconnect and merge their conversation histories.

  3. Compromised or expired devices: Devices can be compromised, stolen, or have their certificates expire. The system must allow banning such devices and ensure they cannot manipulate their certificate or commit timestamps to send unauthorized messages or falsify their expiration status.

Các hệ thống tương tự (với hệ thống nhóm phân tán) không nhiều, nhưng đây là một số ví dụ:

  • [mpOTR không định nghĩa cách cấm một người nào đó]

  • Cấu hiệu, không có bất kỳ máy chủ trung tâm nào cho trò chuyện nhóm (EDIT: họ gần đây thay đổi điểm đó), không cung cấp khả năng cấm ai đó từ một nhóm.

This voting system needs a human action to ban someone or must be based on the CRLs info from the repository (because we can not trust external CRLs).

Tắt một thiết bị từ cuộc trò chuyện

Đây là phần duy nhất mà CHÀO phải có sự đồng thuận để tránh chia rẽ cuộc trò chuyện, như nếu hai thành viên đá nhau khỏi cuộc trò chuyện, cái gì sẽ thấy thứ ba?

Điều này là cần thiết để phát hiện các thiết bị bị bị hủy bỏ, hoặc đơn giản là tránh có những người không mong muốn ở trong một phòng công cộng.

Alice removes Bob

Quan trọng

Alice MUST be an admin to vote.

  • Trước tiên, cô bỏ phiếu cấm Bob. Để làm điều đó, cô tạo ra tệp trong /votes/ban/members/uri_bob/uri_alice (những thành viên có thể được thay thế bằng các thiết bị cho một thiết bị, hoặc được mời mời để mời hoặc quản trị viên cho quản trị viên) và cam kết

  • Sau đó cô ấy kiểm tra xem phiếu bầu đã được giải quyết hay không. Điều này có nghĩa là > 50% người quản trị đồng ý cấm Bob (nếu cô ấy là một mình, chắc chắn đó là hơn 50%).

  • Nếu bỏ phiếu được giải quyết, các tập tin vào /votes/ban có thể được xóa, tất cả các tập tin cho Bob trong /members, /admins, /invited, /CRLs, /devices có thể được xóa (hoặc chỉ trong /devices nếu đó là một thiết bị bị cấm) và chứng chỉ của Bob có thể được đặt vào /banned/members/bob_uri.crt (hoặc /banned/devices/uri.crt nếu một thiết bị bị bị cấm) và được cam kết với repo

  • Sau đó, Alice thông báo cho người dùng khác (ngoài Bob)

Alice (admin) re-adds Bob (banned member)

  • If she votes for unbanning Bob. To do that, she creates the file in /votes/unban/members/uri_bob/uri_alice (members can be replaced by devices for a device, or invited for invites or admins for admins) and commits

  • Sau đó cô ấy kiểm tra xem phiếu bầu đã được giải quyết hay không. Điều này có nghĩa là > 50% người quản trị đồng ý cấm Bob (nếu cô ấy là một mình, chắc chắn đó là hơn 50%).

  • Nếu bỏ phiếu được giải quyết, các tập tin vào /votes/unban có thể được xóa, tất cả các tập tin cho Bob trong /members, /admins, /invited, /CRLs, có thể được thêm lại (hoặc chỉ trong /devices nếu đó là một thiết bị không bị cấm) và cam kết cho repo

Tháo cuộc trò chuyện

  1. Cung cấp trong convInfos removed=time::now() (như removeContact save in contacts) rằng cuộc trò chuyện được xóa và đồng bộ hóa với các thiết bị của người dùng khác

  2. Nếu nhận được một lời mời mới cho cuộc trò chuyện này thì nó sẽ bị bỏ qua.

  3. Bây giờ, nếu Jami khởi động và repo vẫn hiện diện, cuộc trò chuyện không được công bố cho khách hàng

  4. Two cases: a. If no other member in the conversation we can immediately remove the repository b. If still other members, commit that we leave the conversation, and now wait that at least another device sync this message. This avoids the fact that other members will still detect the user as a valid member and still sends new message notifications.

  5. Khi chúng ta chắc chắn rằng ai đó đã đồng bộ hóa, xóa xóa=time::now() và đồng bộ hóa với các thiết bị của người dùng khác

  6. Tất cả các thiết bị thuộc sở hữu của người dùng bây giờ có thể xóa kho và các tập tin liên quan

Làm thế nào để xác định chế độ

Các chế độ không thể thay đổi theo thời gian. hoặc đó là một cuộc trò chuyện khác. Vì vậy, dữ liệu này được lưu trữ trong thông điệp commit ban đầu. thông điệp commit sẽ như sau:

{
    "type": "initial",
    "mode": 0,
}

Hiện tại, "mode" chấp nhận các giá trị 0 (ONE_TO_ONE), 1 (ADMIN_INVITES_ONLY), 2 (INVITES_ONLY), 3 (PUBLIC)

Processes for 1:1 chats

The goal here is to keep the old API (addContact/removeContact, sendTrustRequest/acceptTrustRequest/discardTrustRequest) to create a chat with a peer and its contact. This still implies some changes that we cannot ignore:

Quá trình vẫn giống nhau, một tài khoản có thể thêm một liên hệ thông qua addContact, sau đó gửi TrustRequest thông qua DHT.

  1. TrustRequest nhúng một "conversationId" để thông báo cho người đồng nghiệp cuộc trò chuyện nào để sao chép khi chấp nhận yêu cầu

  2. TrustRequest được thử lại khi liên lạc trở lại trực tuyến. Không phải là trường hợp ngày nay (chẳng muốn tạo TrustRequest mới nếu người đồng nghiệp loại bỏ thứ nhất). Vì vậy, nếu một tài khoản nhận được yêu cầu tin tưởng, nó sẽ được tự động bỏ qua nếu yêu cầu với một cuộc trò chuyện liên quan bị từ chối (vì convRequests được đồng bộ hóa)

Sau đó, khi một liên lạc chấp nhận yêu cầu, một thời gian đồng bộ là cần thiết, bởi vì liên lạc bây giờ cần phải nhân bản cuộc trò chuyện.

removeContact() sẽ xóa liên lạc và các cuộc trò chuyện 1: 1 liên quan (với cùng một quy trình như "Remove a conversation").

Các kịch bản khó khăn

Có một số trường hợp có thể tạo ra hai cuộc trò chuyện.

  1. Alice adds Bob.

  2. Bob accepts.

  3. Alice removes Bob.

  4. Alice adds Bob.

hoặc

  1. Alice adds Bob and Bob adds Alice at the same time, but both are not connected together.

In this case, two conversations are generated. We don't want to remove messages from users or choose one conversation here. So, sometimes two conversations between the same members will be shown. It will generate some bugs during the transition time (as we don't want to break API, the inferred conversation will be one of the two shown conversations, but for now it's "ok-ish", will be fixed when clients will fully handle conversationId for all APIs (calls, file transfer, etc)).

Quan trọng

After accepting a conversation's request, there is a time the daemon needs to retrieve the distant repository. During this time, clients MUST show a syncing view to give informations to the user. While syncing:

  • ConfigurationManager::getConversations() will return the conversation's id even while syncing.

  • ConfigurationManager::conversationInfos() sẽ trả lại {{"syncing": "true"}} nếu đồng bộ hóa.

  • ConfigurationManager::getConversationMembers() will return a map of two URIs (the current account and the peer who sent the request).

Các cuộc trò chuyện yêu cầu thông số kỹ thuật

Các yêu cầu trò chuyện được đại diện bởi một Map<String, String> với các phím sau:

  • id: the conversation ID

  • from: URI of the sender

  • nhận: dấu thời gian

  • Tiêu đề: (bắt buộc) tên cho cuộc trò chuyện

  • mô tả: (không chọn lựa)

  • avatar: (optional) the profile picture

Đồng bộ hóa hồ sơ của cuộc trò chuyện

Để được xác định, một cuộc trò chuyện thường cần một số siêu dữ liệu, chẳng hạn như tiêu đề (ví dụ: Jami), mô tả (ví dụ: một số liên kết, dự án là gì, v.v.), và một hình ảnh (chữ liệu biểu tượng của dự án).

Tạp lưu trữ trong kho

Profile của cuộc trò chuyện được lưu trữ trong tệp vCard cổ điển ở gốc (/profile.vcf) như:

BEGIN:VCARD
VERSION:2.1
FN:TITLE
DESCRIPTION:DESC
END:VCARD

Đồng bộ hóa

To update the vCard, a user with enough permissions (by default: =ADMIN) needs to edit /profile.vcf and will commit the file with the mimetype application/update-profile. The new message is sent via the same mechanism and all peers will receive the MessageReceived signal from the daemon. The branch is dropped if the commit contains other files or too big or if done by a non-authorized member (by default: <ADMIN).

Tiếp theo được hiển thị

Trong dữ liệu đồng bộ, mỗi thiết bị gửi đến các thiết bị khác trạng thái của các cuộc trò chuyện. Trong trạng thái này, cuối cùng được hiển thị được gửi. Tuy nhiên, vì mỗi thiết bị có thể có trạng thái riêng cho mỗi cuộc trò chuyện, và có lẽ không có cùng một cam kết cuối cùng tại một thời điểm nào đó, có một số kịch bản cần tính:

5 kịch bản được hỗ trợ:

  • nếu màn hình cuối cùng được gửi bởi các thiết bị khác giống như màn hình hiện tại, không có gì để làm.

  • Nếu không có hiển thị cuối cùng cho thiết bị hiện tại, thông điệp hiển thị từ xa được sử dụng.

  • nếu từ xa lần cuối được hiển thị không có mặt trong repo, nó có nghĩa là commit sẽ được lấy sau đó, do đó cache kết quả

  • nếu điều khiển từ xa đã được lấy, chúng tôi kiểm tra rằng địa phương cuối cùng hiển thị là trước trong lịch sử để thay thế nó

  • Cuối cùng, nếu một thông điệp được công bố từ cùng một tác giả, nó có nghĩa là chúng ta cần phải cập nhật thông điệp cuối cùng được hiển thị.

Tự ưu tiên

Mỗi cuộc trò chuyện đều có tùy chọn được đặt bởi người dùng. Những tùy chọn đó được đồng bộ hóa trên các thiết bị của người dùng. Đây có thể là màu của cuộc trò chuyện, nếu người dùng muốn bỏ qua thông báo, giới hạn kích thước chuyển tập tin, vv. Cho đến nay, các khóa được công nhận là:

  • "color" - the color of the conversation (#RRGGBB format)

  • "ignoreNotifications" - để bỏ qua các thông báo cho các tin nhắn mới trong cuộc trò chuyện này

  • "symbol" - để xác định emoji mặc định.

Những sở thích đó được lưu trữ trong một gói MapStringString, được lưu trữ trong accountDir/conversation_data/conversationId/preferences và chỉ được gửi qua các thiết bị của cùng một người dùng thông qua SyncMsg.

API để tương tác với các sở thích là:

// Update preferences
void setConversationPreferences(const std::string& accountId,
                                const std::string& conversationId,
                                const std::map<std::string, std::string>& prefs);
// Retrieve preferences
std::map<std::string, std::string> getConversationPreferences(const std::string& accountId,
                                                              const std::string& conversationId);
// Emitted when preferences are updated (via setConversationPreferences or by syncing with other devices)
struct ConversationPreferencesUpdated
{
    constexpr static const char* name = "ConversationPreferencesUpdated";
    using cb_type = void(const std::string& /*accountId*/,
                            const std::string& /*conversationId*/,
                            std::map<std::string, std::string> /*preferences*/);
};

Quản lý xung đột sáp nhập

Bởi vì hai người quản trị có thể thay đổi mô tả cùng một lúc, một xung đột sáp nhập có thể xảy ra trên profile.vcf. Trong trường hợp này, commit với hash cao hơn (ví dụ ffffff > 000000) sẽ được chọn.

API

Người dùng có 2 phương pháp để lấy và đặt metadata của cuộc trò chuyện:

       <method name="updateConversationInfos" tp:name-for-bindings="updateConversationInfos">
           <tp:added version="10.0.0"/>
           <tp:docstring>
               Update conversation's infos (supported keys: title, description, avatar)
           </tp:docstring>
           <arg type="s" name="accountId" direction="in"/>
           <arg type="s" name="conversationId" direction="in"/>
           <annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="VectorMapStringString"/>
           <arg type="a{ss}" name="infos" direction="in"/>
       </method>

       <method name="conversationInfos" tp:name-for-bindings="conversationInfos">
           <tp:added version="10.0.0"/>
           <tp:docstring>
               Get conversation's infos (mode, title, description, avatar)
           </tp:docstring>
           <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/>
           <arg type="a{ss}" name="infos" direction="out"/>
           <arg type="s" name="accountId" direction="in"/>
           <arg type="s" name="conversationId" direction="in"/>
       </method>

nơi infos là một map<str, str> với các phím sau:

  • chế độ: Đọc chỉ

  • tiêu đề

  • mô tả

  • avatar: the profile picture

Các giao thức được sử dụng

Git

Tại sao lựa chọn này

Each conversation will be a Git repository. This choice is motivated by:

  1. Chúng ta cần đồng bộ hóa và sắp xếp các tin nhắn. Cây Merkle là cấu trúc hoàn hảo để làm điều đó và có thể được tuyến tính bằng cách sáp nhập các nhánh. Hơn nữa, vì nó được sử dụng rộng rãi bởi Git, nó dễ dàng đồng bộ hóa giữa các thiết bị.

  2. Được phân phối bởi tự nhiên, được sử dụng rộng rãi, nhiều backend và có thể bật.

  3. Có thể xác minh các cam kết thông qua các cái móng và tiền điện tử được sử dụng rộng rãi

  4. Có thể được lưu trữ trong cơ sở dữ liệu nếu cần thiết

  5. Các xung đột được tránh bằng cách sử dụng tin nhắn commit, không phải các tệp.

Những gì chúng ta phải xác nhận

  • Hiệu suất? git.lock có thể thấp

  • Cây đập trong libgit2

  • Nhiều lần kéo cùng một lúc?

Các giới hạn

Lịch sử không thể xóa. Để xóa một cuộc trò chuyện, thiết bị phải rời khỏi cuộc trò chuyện và tạo một cuộc trò chuyện khác.

Tuy nhiên, các thông điệp không thường xuyên (như thông điệp chỉ được đọc trong vài phút) có thể được gửi qua một thông điệp đặc biệt thông qua DRT (như thông báo nhập hoặc đọc).

Cấu trúc

/
 - invited
 - admins (public keys)
 - members (public keys)
 - devices (certificates of authors to verify commits)
 - banned
   - devices
   - invited
   - admins
   - members
 - votes
    - ban
        - members
            - uri
                - uriAdmin
        - devices
            - uri
                - uriAdmin
    - unban
        - members
            - uri
                - uriAdmin
 - CRLs

Chuyển tập tin

This new system overhauls file sharing: the entire history is now kept in sync, so any device in the conversation can instantly access past files. Rather than forcing the sender to push files directly—an approach that was fragile in the face of connection drops and often required manual retries—devices simply download files when they need them. Moreover, once one device has downloaded a file, it can act as a host for others, ensuring files remain available even if the original sender goes offline.

Phương pháp

Người gửi thêm một commit mới trong cuộc trò chuyện với định dạng sau:

value["tid"] = "RANDOMID";
value["displayName"] = "DISPLAYNAME";
value["totalSize"] = "SIZE OF THE FILE";
value["sha3sum"] = "SHA3SUM OF THE FILE";
value["type"] = "application/data-transfer+json";

và tạo ra một liên kết trong ${data_path}/conversation_data/${conversation_id}/${file_id} nơi file_id=${commitid}_${value["tide"]}.${extension}

Sau đó, người nhận có thể tải xuống các tệp bằng cách liên hệ với các thiết bị lưu trữ tệp bằng cách mở kênh với name="data-transfer://" + conversationId + "/" + currentDeviceId() + "/" + fileId và lưu trữ thông tin rằng tệp đang chờ đợi trong ${data_path}/conversation_data/${conversation_id}/waiting

Thiết bị nhận kết nối sẽ chấp nhận kênh bằng cách xác minh liệu tệp có thể được gửi (nếu sha3sum là đúng và tệp có). Người nhận sẽ giữ kênh mở đầu tiên, đóng các kênh khác và ghi vào tệp (với cùng con đường như người gửi: ${data_path}/conversation_data/${conversation_id}/${file_id}) tất cả dữ liệu nhập.

Khi chuyển giao hoàn thành hoặc kênh đóng, số lượng sha3 được xác minh để xác minh rằng tệp là đúng (hoặc nó đã bị xóa). Nếu hợp lệ, tệp sẽ được xóa khỏi chờ.

Trong trường hợp thất bại, khi thiết bị của cuộc trò chuyện sẽ trở lại trực tuyến, chúng tôi sẽ yêu cầu tất cả các tệp chờ theo cùng một cách.

Call in Swarm

Ý tưởng

A swarm conversation can have multiple rendez-vous. A rendez-vous is defined by the following URI:

"accountUri/deviceId/conversationId/confId" nơi accountUri/deviceId mô tả máy chủ.

Người chủ có thể được xác định bằng hai cách:

  • In the swarm metadatas. Where it's stored like the title/desc/avatar (profile picture) of the room

  • Hoặc là người gọi đầu tiên.

When starting a call, the host will add a new commit to the repository, with the URI to join (accountUri/deviceId/conversationId/confId). This will be valid till the end of the call (announced by a commit with the duration to show)

Vì vậy, mỗi phần sẽ nhận được thông tin rằng một cuộc gọi đã bắt đầu và sẽ có thể tham gia nó bằng cách gọi nó.

Chuyện tấn công?

  • Avoid Git bombs

Các ghi chú

Bức timestamp của một commit có thể được tin cậy bởi vì nó có thể chỉnh sửa. Chỉ có timestamp của người dùng có thể được tin cậy.

TLS

Các hoạt động Git, tin nhắn kiểm soát, tệp, và những thứ khác sẽ sử dụng một liên kết TLS v1.3 p2p chỉ có mã hóa đảm bảo PFS. Vì vậy mỗi khóa được đàm phán lại cho mỗi kết nối mới.

DHT (UDP)

Được sử dụng để gửi tin nhắn cho điện thoại di động (để kích hoạt thông báo đẩy) và để khởi động kết nối TCP.

Hoạt động mạng

Quá trình mời ai đó

Alice muốn mời Bob:

  1. Alice thêm Bob vào cuộc trò chuyện

  2. Alice generates an invite: { "application/invite+json" : { "conversationId": "$id", "members": [{...}] }}

  3. Hai khả năng để gửi thông điệp a. Nếu không kết nối, qua DHT b. Nếu không, Alice gửi trên kênh SIP

  4. Bob nhận được lời mời, một tín hiệu được phát ra cho khách hàng b. Không kết nối, vì vậy sẽ không bao giờ nhận được yêu cầu vì Alice không thể biết nếu Bob đã bỏ qua hoặc chặn Alice. Cách duy nhất là tái tạo lời mời mới thông qua một tin nhắn mới (xem kịch bản tiếp theo)

Quá trình để gửi tin nhắn cho ai đó

Alice muốn gửi tin nhắn cho Bob:

  1. Alice thêm một tin nhắn vào repo, cho một ID

  2. Alice nhận được một tin nhắn (từ chính mình) nếu thành công

  3. Hai khả năng, alice và bob có kết nối, hoặc không. Trong cả hai trường hợp một thông điệp được tạo ra: { "application/im-gitmessage-id" : "{"id":"\(convId", "commit":"\)commitId", "deviceId": "$alice_device_hash"}"}.

  4. Bốn khả năng cho Bob: a. Bob không kết nối với Alice, vì vậy nếu ông tin tưởng Alice, hãy yêu cầu kết nối mới và đi đến b. b. Nếu kết nối, hãy lấy từ Alice và thông báo tin mới c. Bob không biết cuộc trò chuyện đó. Hãy yêu cầu thông qua DHT để nhận được một lời mời trước tiên để có thể chấp nhận cuộc trò chuyện đó ({" ứng dụng/ mời", cuộc trò chuyệnId}) d. Bob bị ngắt kết nối (không có mạng, hoặc chỉ đóng).

Thực hiện

! [Chương trình: lớp học trò chuyện đám đông](hình ảnh/chương trình trò chuyện đám đông lớp học.jpg)

Supported messages

Initial message

{
    "type": "initial",
    "mode": 0,
    "invited": "URI"
}

Represents the first commit of a repository and contains the mode:

enum class ConversationMode : int { ONE_TO_ONE = 0, ADMIN_INVITES_ONLY, INVITES_ONLY, PUBLIC }

and invited if mode = 0.

Text message

{
    "type": "text/plain",
    "body": "content",
    "react-to": "id (optional)"
}

Or for an edition:

{
    "type": "application/edited-message",
    "body": "content",
    "edit": "id of the edited commit"
}

Calls

Show the end of a call (duration in milliseconds):

{
    "type": "application/call-history+json",
    "to": "URI",
    "duration": "3000"
}

Or for hosting a call in a group (when it starts)

{
    "type": "application/call-history+json",
    "uri": "host URI",
    "device": "device of the host",
    "confId": "hosted confId"
}

A second commit with the same JSON + duration is added at the end of the call when hosted.

Add a file

{
    "type": "application/data-transfer+json",
    "tid": "unique identifier of the file",
    "displayName": "File name",
    "totalSize": "3000",
    "sha3sum": "a sha3 sum"
}

totalSize is in bits,

Updating profile

{
    "type": "application/update-profile",
}

Member event

{
    "type": "member",
    "uri": "member URI",
    "action": "add/join/remove/ban"
}

When a member is invited, join or leave or is kicked from a conversation

Vote event

Generated by administrators to add a vote for kicking or un-kicking someone.

{
    "type": "vote",
    "uri": "member URI",
    "action": "ban/unban"
}

!! DRAFT LÀN!!

Ghi chú

Following notes are not organized yet. Just some line of thoughts.

Những cải tiến về tiền điện tử.

Đối với một tính năng trò chuyện nhóm nghiêm túc, chúng ta cũng cần mã hóa nghiêm túc. Với thiết kế hiện tại, nếu một chứng chỉ bị đánh cắp như các giá trị DHT trước của một cuộc trò chuyện, cuộc trò chuyện có thể được giải mã. Có lẽ chúng ta cần phải đi đến một cái gì đó như ** Double ratchet**.

Ghi chú

A lib might exist to implement group conversations.

Cần hỗ trợ ECC trong OpenDHT

Sử dụng

Thêm vai trò?

Có hai trường hợp sử dụng chính cho trò chuyện nhóm:

  1. Một cái gì đó như một Mattermost trong một công ty, với các kênh riêng, và một số vai trò (admin/spectator/bot/etc) hoặc cho giáo dục (nơi chỉ có một vài người hoạt động).

  2. Những cuộc trò chuyện ngang ngang như một cuộc trò chuyện giữa bạn bè.

Jami will be for which one?

Ý tưởng thực hiện

Một chứng chỉ cho một nhóm ký tên người dùng với cờ cho một vai trò.

Tham gia cuộc trò chuyện

  • Chỉ qua lời mời trực tiếp

  • Thông qua một liên kết/QR Code/ bất cứ điều gì

  • Thông qua tên phòng?

Những gì chúng ta cần

  • Bảo mật: các thành viên bên ngoài trò chuyện nhóm không nên có thể đọc tin nhắn trong nhóm

  • Sự bí mật tiếp theo: nếu bất kỳ khóa nào từ nhóm bị xâm nhập, tin nhắn trước đó nên được giữ bí mật (tối đa khả năng)

  • Định hướng thông điệp: Có nhu cầu có thông điệp theo thứ tự đúng

  • Đồng bộ hóa: Ngoài ra còn cần phải đảm bảo có tất cả các tin nhắn càng sớm càng tốt.

  • Sự kiên trì: Thực tế, một tin nhắn trên DHT chỉ tồn tại 10 phút. Bởi vì đó là thời gian tốt nhất được tính toán cho loại DHT này. Để duy trì dữ liệu, nút phải đặt lại giá trị trên DHT mỗi 10 phút. Một cách khác để làm khi nút offline là để các nút đặt lại dữ liệu. Nhưng, nếu sau 10 phút, 8 nút vẫn ở đây, họ sẽ thực hiện 64 yêu cầu (và nó là tăng trưởng). Cách hiện tại để tránh spam cho điều đó là truy vấn. Điều này vẫn sẽ thực hiện 64 yêu cầu nhưng giới hạn sự dư thừa tối đa đến 8 nút.

Các phương thức phân phối khác

  • IPFS: cần một số điều tra

  • Bắt đầu điều tra

  • Tôi cần điều tra.

Dựa trên công việc hiện tại chúng ta có

Các trò chuyện nhóm có thể dựa trên cùng một công việc mà chúng ta đã có cho nhiều thiết bị (nhưng ở đây, với một chứng chỉ nhóm).

  1. Điều này cần phải di chuyển cơ sở dữ liệu từ khách hàng sang con quỷ.

  2. Nếu không ai kết nối, đồng bộ hóa không thể được thực hiện, và người đó sẽ không bao giờ thấy cuộc trò chuyện

Một DHT chuyên dụng khác

Giống như một DHT với một người dùng siêu.

What's next for file transfers

Currently, the file transfer algorithm is based on a TURN connection (See Chuyển tập tin). In the case of a big group, this will be bad. We first need a P2P connection for the file transfer. Implement the RFC for P2P transfer.

Other problem: currently there is no implementation for TCP support for ICE in PJSIP. This is mandatory for this point (in PJSIP or homemade)

Tài nguyên