Swarm

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. Tidak ada otoritas pusat. Tidak bisa mengandalkan server.

  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.

Ide utama adalah mendapatkan pohon Merkle yang disinkronkan dengan para peserta.

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).

Skenario

Buatlah Swarm

Bob ingin membuat kelompok baru

  1. Bob creates a local Git repository.

  2. Kemudian, dia membuat komitmen awal yang ditandatangani dengan berikut:

    • Kunci publiknya di /admins

    • Sertifikat perangkatnya dalam ̀ / perangkat `

    • CRLnya di ̀ /crls`

  3. Hash dari komitmen pertama menjadi ** ID ** percakapan

  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.

Menambahkan seseorang

Bob adds Alice

  1. Bob adds Alice to the repo:

    • Tambahkan URI yang diundang dalam /invited

    • Tambahkan CRL ke /crls

  2. Bob sends a request on the DHT.

Menerima undangan

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.

Mengirim pesan

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).

Catatan

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.

Menerima pesan

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.

Validasi komitmen

Untuk menghindari pengguna mendorong beberapa komitmen yang tidak diinginkan (dengan konflik, pesan palsu, dll), inilah bagaimana setiap komitmen (dari yang tertua hingga yang terbaru) MUST divalidasi sebelum menggabungkan cabang jarak jauh:

Catatan

  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.

Larangan perangkat

Penting

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.

Sistem serupa (dengan sistem kelompok terdistribusi) tidak begitu banyak, tetapi ini adalah beberapa contoh:

  • [mpOTR tidak mendefinisikan bagaimana melarang seseorang]https://www.cypherpunks.ca/~iang/pubs/mpotr.pdf)

  • Signal, tanpa server pusat untuk obrolan kelompok (EDIT: mereka baru-baru ini mengubah titik itu), tidak memberikan kemampuan untuk melarang seseorang dari kelompok.

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).

Hapus perangkat dari percakapan

Ini satu-satunya bagian yang MUST memiliki konsensus untuk menghindari pemisahan percakapan, seperti jika dua anggota menendang satu sama lain dari percakapan, apa yang akan melihat yang ketiga?

Ini diperlukan untuk mendeteksi perangkat yang dicabut, atau hanya menghindari orang yang tidak diinginkan hadir di ruang publik. Prosesnya cukup mirip antara anggota dan perangkat:

Alice menghapus Bob

Penting

Alice MUST be an admin to vote.

  • Pertama, dia memilih untuk melarang Bob. Untuk melakukan itu, dia membuat file di /votes/ban/members/uri_bob/uri_alice (anggota dapat digantikan dengan perangkat untuk perangkat, atau diundang untuk undangan atau administrator untuk administrator) dan berkomitmen

  • Kemudian dia memeriksa apakah suara telah diselesaikan. Ini berarti bahwa > 50% dari administrator setuju untuk melarang Bob (jika dia sendirian, itu pasti lebih dari 50%).

  • Jika suara diselesaikan, file ke dalam /votes/ban dapat dihapus, semua file untuk Bob di /members, /admins, /invited, /CRLs, /devices dapat dihapus (atau hanya di /devices jika itu adalah perangkat yang dilarang) dan sertifikat Bob dapat ditempatkan di /banned/members/bob_uri.crt (atau /banned/devices/uri.crt jika perangkat dilarang) dan diarahkan ke repo

  • Kemudian, Alice menginformasikan pengguna lain (kecuali 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

  • Kemudian dia memeriksa apakah suara telah diselesaikan. Ini berarti bahwa > 50% dari administrator setuju untuk melarang Bob (jika dia sendirian, itu pasti lebih dari 50%).

  • Jika suara diselesaikan, file ke /votes/unban dapat dihapus, semua file untuk Bob di /members, /admins, /invited, /CRL, dapat ditambahkan kembali (atau hanya di /device jika itu adalah perangkat yang tidak dilarang) dan berkomitmen ke repo

Hapus percakapan

  1. Simpan di convInfos removed=time::now() (seperti removeContact save di kontak) bahwa percakapan dihapus dan disinkronkan dengan perangkat pengguna lain

  2. Sekarang, jika komitmen baru diterima untuk percakapan ini dia dia mengabaikan

  3. Sekarang, jika Jami startup dan repo masih hadir, percakapan tidak diumumkan kepada klien

  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. Ketika kita yakin bahwa seseorang disinkronkan, hapus dihapus=time::now() dan sinkronisasi dengan perangkat pengguna lain

  6. Semua perangkat milik pengguna sekarang dapat menghapus repositori dan file terkait

Cara menentukan mode

Modus tidak dapat diubah seiring waktu. atau itu adalah percakapan lain. jadi, data ini disimpan dalam pesan commit awal. pesan commit akan menjadi sebagai berikut:

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

Untuk saat ini, "mode" menerima nilai 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:

Prosesnya masih sama, akun dapat menambahkan kontak melalui addContact, kemudian mengirim TrustRequest melalui DHT. Tapi dua perubahan diperlukan:

  1. TrustRequest menyematkan "conversationId" untuk memberi tahu peer apa percakapan untuk diklon saat menerima permintaan

  2. TrustRequest di coba lagi ketika kontak kembali online. Ini tidak terjadi hari ini (karena kami tidak ingin menghasilkan TrustRequest baru jika rekan membuang yang pertama). Jadi, jika akun menerima permintaan kepercayaan, itu akan secara otomatis diabaikan jika permintaan dengan percakapan terkait ditolak (karena convRequests disinkronkan)

Kemudian, ketika kontak menerima permintaan, periode sinkronisasi diperlukan, karena kontak sekarang perlu mengkloning percakapan.

removeContact() akan menghapus kontak dan percakapan 1:1 terkait (dengan proses yang sama seperti "Untuk menghapus percakapan"). Satu-satunya catatan di sini adalah bahwa jika kita melarang kontak, kita tidak menunggu sinkronisasi, kita hanya menghapus semua file terkait.

Skenario yang sulit

Ada beberapa kasus di mana dua percakapan dapat dibuat.

  1. Alice adds Bob.

  2. Bob accepts.

  3. Alice removes Bob.

  4. Alice adds Bob.

atau

  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)).

Penting

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() akan mengembalikan {{"sinkronisasi": "benar"}} jika sinkronisasi.

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

Percakapan meminta spesifikasi

Permintaan percakapan diwakili oleh Map<String, String> dengan tombol berikut:

  • id: the conversation ID

  • from: URI of the sender

  • diterima: timestamp

  • judul: (opsional) nama untuk percakapan

  • deskripsi: (opsional)

  • avatar: (optional) the profile picture

Synchronization profil percakapan

Untuk dapat diidentifikasi, percakapan umumnya membutuhkan beberapa metadata, seperti judul (misalnya Jami), deskripsi (misalnya: beberapa tautan, apa itu proyek, dll), dan gambar (logo proyek). Metadata tersebut opsional tetapi dibagikan di semua anggota, jadi perlu disinkronkan dan dimasukkan ke dalam permintaan.

Penyimpanan di gudang

Profil percakapan disimpan dalam file vCard klasik di root (/profile.vcf) seperti:

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

Sinkronisasi

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).

Terakhir Ditampilkan

Dalam data sinkronisasi, setiap perangkat mengirim ke perangkat lain status percakapan. Dalam keadaan ini, yang terakhir ditampilkan dikirim. Namun, karena setiap perangkat dapat memiliki status sendiri untuk setiap percakapan, dan mungkin tanpa komitmen terakhir yang sama pada suatu titik, ada beberapa skenario yang harus diperhitungkan:

Ada 5 skenario yang didukung:

  • jika tampilan terakhir yang dikirim oleh perangkat lain sama dengan yang saat ini, tidak ada yang bisa dilakukan.

  • jika tidak ada tampilan terakhir untuk perangkat saat ini, pesan yang ditampilkan dari jarak jauh digunakan.

  • jika remote terakhir ditampilkan tidak hadir di repo, itu berarti bahwa commit akan dibawa kemudian, jadi cache hasil

  • jika remote sudah dibawa, kita memeriksa apakah lokal terakhir ditampilkan adalah sebelumnya dalam sejarah untuk menggantikannya

  • Akhirnya jika pesan yang diumumkan dari penulis yang sama, itu berarti kita perlu memperbarui yang terakhir ditampilkan.

Preferensi

Setiap percakapan memiliki preferensi yang disertakan oleh pengguna. Preferensi tersebut disinkronkan di seluruh perangkat pengguna. Ini bisa menjadi warna percakapan, jika pengguna ingin mengabaikan pemberitahuan, batas ukuran transfer file, dll. Untuk saat ini, kunci yang diakui adalah:

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

  • "ignoreNotifications" - untuk mengabaikan pemberitahuan untuk pesan baru dalam percakapan ini

  • "simbol" - untuk mendefinisikan emoji default.

Preferensi tersebut disimpan dalam paket MapStringString, disimpan di accountDir/conversation_data/conversationId/preferences dan hanya dikirim ke perangkat pengguna yang sama melalui SyncMsg.

API untuk berinteraksi dengan preferensi adalah:

// 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*/);
};

Pengelolaan konflik merger

Karena dua administrator dapat mengubah deskripsi pada saat yang sama, konflik merger dapat terjadi pada profile.vcf. Dalam hal ini, commit dengan hash yang lebih tinggi (misalnya ffffff > 000000) akan dipilih.

API

Pengguna memiliki 2 metode untuk mendapatkan dan mengatur metadata percakapan:

       <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>

di mana infos adalah map<str, str> dengan kunci berikut:

  • Mode: Membaca-Hanya

  • judul

  • deskripsi

  • avatar: the profile picture

Protokol yang digunakan

Git

Mengapa pilihan ini

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

  1. Merkle Tree adalah struktur yang sempurna untuk melakukan itu dan dapat linearisasi dengan menggabungkan cabang. Selain itu, karena banyak digunakan oleh Git, mudah untuk menyeinkronkan antara perangkat.

  2. Dibagikan oleh alam, banyak digunakan, banyak backend dan pluggable.

  3. Dapat memverifikasi komitmen melalui hooks dan crypto yang banyak digunakan

  4. Bisa disimpan di database jika diperlukan

  5. Konflik dihindari dengan menggunakan pesan commit, bukan file.

Apa yang harus kita validasi

  • Kinerja? git.lock bisa rendah

  • Hooks dalam libgit2

  • Berbagai tarik pada saat yang sama?

Batas

Untuk menghapus sebuah percakapan, perangkat harus meninggalkan percakapan dan membuat yang lain.

Namun, pesan non-permanen (seperti pesan yang hanya dapat dibaca selama beberapa menit) dapat dikirim melalui pesan khusus melalui DRT (seperti Notifikasi Ketik atau Baca).

Struktur

/
 - 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

Transfer file

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.

Protokol

Pengirim menambahkan komitmen baru dalam percakapan dengan format berikut:

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

dan membuat tautan di ${data_path}/conversation_data/${conversation_id}/${file_id} di mana file_id=${commitid}_${value["tid"]}.${extension}

Kemudian, penerima sekarang dapat mengunduh file dengan menghubungi perangkat yang meng-host file dengan membuka saluran dengan name="data-transfer://" + conversationId + "/" + currentDeviceId() + "/" + fileId dan menyimpan informasi bahwa file sedang menunggu di ${data_path}/conversation_data/${conversation_id}/waiting

Perangkat yang menerima koneksi akan menerima saluran dengan memverifikasi apakah file dapat dikirim (jika sha3sum benar dan jika file ada). Penerima akan menyimpan saluran yang pertama dibuka, menutup yang lain dan menulis ke dalam file (dengan jalur yang sama dengan pengirim: ${data_path}/conversation_data/${conversation_id}/${file_id}) semua data masuk.

Ketika transfer selesai atau saluran ditutup, sha3sum diverifikasi untuk memvalidasi bahwa file itu benar (jika tidak dihapus). Jika valid, file akan dihapus dari tunggu.

Jika gagal, ketika perangkat percakapan akan kembali online, kita akan meminta semua file menunggu dengan cara yang sama.

Call in Swarm

Ide

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

"accountUri/deviceId/conversationId/confId" di mana accountUri/deviceId menggambarkan host.

Tuan rumah dapat ditentukan melalui dua cara:

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

  • Atau pemanggil awal.

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)

Jadi setiap bagian akan menerima informasi bahwa panggilan telah dimulai dan akan dapat bergabung dengan itu dengan meneleponnya.

Serangan?

  • Avoid Git bombs

Catatan

Timestamp dari commit dapat dipercaya karena dapat diedit. Hanya timestamp pengguna yang dapat dipercaya.

TLS

Operasi Git, pesan kontrol, file, dan hal-hal lain akan menggunakan tautan P2p TLS v1.3 dengan hanya cipher yang menjamin PFS. Jadi setiap kunci dipernegotiasi ulang untuk setiap koneksi baru.

DHT (UDP)

Digunakan untuk mengirim pesan untuk ponsel (untuk memicu pemberitahuan push) dan untuk memulai koneksi TCP.

Aktivitas jaringan

Proses untuk mengundang seseorang

Alice ingin mengundang Bob:

  1. Alice menambahkan Bob untuk percakapan

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

  3. Dua kemungkinan untuk mengirim pesan a. Jika tidak terhubung, melalui DHT b. Jika tidak, Alice mengirim melalui saluran SIP

  4. Dua kemungkinan untuk Bob a. Menerima undangan, sinyal dikirimkan untuk klien b. Tidak terhubung, jadi tidak akan pernah menerima permintaan karena Alice tidak harus tahu apakah Bob hanya mengabaikan atau memblokir Alice. Satu-satunya cara adalah untuk memulihkan undangan baru melalui pesan baru (lihat skenario berikutnya)

Proses untuk mengirim pesan ke seseorang

Alice ingin mengirim pesan ke Bob:

  1. Alice menambahkan pesan di repo, memberikan ID

  2. Alice menerima pesan (dari dirinya sendiri) jika berhasil

  3. Dua kemungkinan, alice dan bob terhubung, atau tidak. Dalam kedua kasus ini pesan dibuat: { "aplikasi/im-gitmessage-id" : "{"id":"\(convId", "komit":"\)commitId", "deviceId": "$alice_device_hash"}"}. a. Jika tidak terhubung, melalui DHT b.

  4. Empat kemungkinan untuk Bob: a. Bob tidak terhubung ke Alice, jadi jika dia mempercayai Alice, minta koneksi baru dan pergi ke b. b. Jika terhubung, cari dari Alice dan mengumumkan pesan baru c. Bob tidak tahu percakapan itu. Minta melalui DHT untuk mendapatkan undangan terlebih dahulu untuk dapat menerima percakapan itu ({"aplikasi/undangan", percakapanId}) d. Bob terputus (tidak ada jaringan, atau hanya ditutup). Dia tidak akan menerima pesan baru tetapi akan mencoba untuk menyeinkronkan ketika koneksi berikutnya akan terjadi

Pelaksanaan

! Diagram: kelas chat swarm

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"
}

Panggilan

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"
}

!! Draf lama!!

Catatan

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

Perbaikan Crypto.

Untuk fitur chat kelompok yang serius, kita juga membutuhkan crypto yang serius. Dengan desain saat ini, jika sertifikat dicuri sebagai nilai DHT sebelumnya dari percakapan, percakapan dapat dienkripsi. Mungkin kita perlu pergi ke sesuatu seperti ** Double ratchet**.

Catatan

A lib might exist to implement group conversations.

Butuh dukungan ECC di OpenDHT

Penggunaan

Menambahkan Peran?

Ada dua kasus utama untuk chatting kelompok:

  1. Seperti Mattermost di sebuah perusahaan, dengan saluran pribadi, dan beberapa peran (admin/spectator/bot/dll) atau untuk pendidikan (di mana hanya beberapa yang aktif).

  2. Percakapan horizontal seperti percakapan antara teman.

Jami will be for which one?

Ide implementasi

Sertifikat untuk kelompok yang menandatangani pengguna dengan bendera untuk peran.

Bergabunglah dalam percakapan

  • Hanya melalui undangan langsung

  • Melalui tautan / QR Code / apa pun

  • Melalui nama kamar?

Apa yang kita butuhkan

  • Konfidensial: anggota di luar grup chat tidak boleh membaca pesan di grup

  • Rahasia ke depan: jika kunci dari kelompok terganggu, pesan sebelumnya harus tetap rahasia (sejauh mungkin)

  • Peresmian pesan: Perlu pesan dalam urutan yang tepat

  • Sinkronisasi: Ada juga kebutuhan untuk memastikan semua pesan memiliki secepat mungkin.

  • Persistensi: Sebenarnya, pesan di DHT hanya bertahan 10 menit. Karena itu adalah waktu terbaik yang dihitung untuk jenis DHT ini. Untuk mempertahankan data, node harus menempatkan kembali nilai pada DHT setiap 10 menit. Cara lain untuk melakukannya ketika node offline adalah membiarkan node memasukkan kembali data. Tapi, jika setelah 10 menit, 8 node masih di sini, mereka akan melakukan 64 permintaan (dan itu eksponensial). Cara saat ini untuk menghindari spam untuk itu ditanyakan. Ini masih akan melakukan 64 permintaan tetapi membatasi redundansi maksimum menjadi 8 node.

Cara terdistribusi lainnya

  • IPFS: Butuh beberapa penyelidikan

  • Butuh beberapa penyelidikan

  • Aku butuh beberapa penyelidikan.

Berdasarkan pekerjaan saat ini kita memiliki

Chat kelompok dapat didasarkan pada pekerjaan yang sama yang sudah kita miliki untuk perangkat multi (tapi di sini, dengan sertifikat kelompok).

  1. Ini perlu memindahkan database dari klien ke Daemon.

  2. Jika tidak ada yang terhubung, sinkronisasi tidak dapat dilakukan, dan orang tidak akan pernah melihat percakapan

DHT khusus lainnya

Seperti DHT dengan superuser.

Transfer file

Saat ini, algoritma transfer file didasarkan pada koneksi TURN (lihat Transfer file). Dalam kasus kelompok besar, ini akan buruk. Kita pertama-tama membutuhkan implement p2p untuk transfer file. Implementasi RFC untuk transfer p2p.

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

Sumber daya

  • https://eprint.iacr.org/2017/666.pdf

  • Sinkronisasi terdistribusi yang kuat dari sistem linier berjaringan dengan informasi yang berintermiten (Sean Phillips dan Ricardo G.Sanfelice)