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. Merkez yetkisi yok, hiçbir sunucuya güvenemezsin.

  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.

Ana fikir, katılımcılarla senkronize bir Merkle ağacı elde etmek.

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

Scenariler

Bir swarm oluştur

Bob yeni bir swarm oluşturmak istiyor

  1. Bob creates a local Git repository.

  2. Sonra, aşağıdaki ile ilk imzalanan bir taahhüt oluşturur:

    • O’nun kamu anahtarı /admins

    • Cihaz sertifikası ̀ / cihazlarda `

    • CRL’si ̀ /crls`

  3. İlk commit’in hashı sohbetin ** ID ** olur.

  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.

Birini eklemek

Bob adds Alice

  1. Bob adds Alice to the repo:

    • /invited olarak davet edilen URI eklenir

    • CRL’yi /crls’ye ekler

  2. Bob sends a request on the DHT.

Bir daveti alıyorum

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.

Mesaj göndermek

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

Not

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.

Bir mesaj alıyorum

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.

Bağışlamanın doğrulanması

Kullanıcıların istenmeyen bazı commit’leri (koşullar, yanlış mesajlar vb.) zorlamasını önlemek için, her commit’in (en eskiden en yeniye kadar) uzak bir dalı birleştirmeden önce nasıl doğrulanması gerekir:

Not

  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.

Bir cihazı yasaklayın

Önemli

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.

Benzer sistemler ( dağılmış grup sistemleri ile) pek fazla değildir, ancak bunlar bazı örnekler:

  • [mpOTR birisini nasıl yasaklayacağınızı tanımlamıyor]

  • Grup sohbetleri için herhangi bir merkezi sunucu olmadan (EDIT: son zamanlarda bu noktayı değiştirdiler), bir gruba kimsenin katılmasını yasaklama yeteneği vermez.

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

Bir konuşmadan bir cihazı çıkar

Bu konuşmanın bölünmesini önlemek için bir fikir birliği olması gereken tek bölüm. İki üye konuşmadan birbirini tekmelediğinde üçüncü kişi ne olacak?

Bu, iptal edilen cihazları tespit etmek veya sadece istenmeyen insanları kamu odasına getirmekten kaçınmak için gereklidir.

Alice removes Bob

Önemli

Alice MUST be an admin to vote.

  • İlk olarak Bob’u yasaklamak için oy veriyor. Bunu yapmak için dosyayı /votes/ban/members/uri_bob/uri_alice olarak oluşturur (memberler bir cihaz için cihazlar ile değiştirilebilir veya davetler veya yöneticiler için yöneticiler için davet edilebilir) ve

  • Sonra oyunun çözülüp çözülmediğini kontrol eder. Bu, yöneticilerin %50’inin Bob’u yasaklamaya razı olduğu anlamına gelir (tek başına ise, bu %50’den fazla olduğundan emin).

  • Eğer oylama çözülürse, /votes/ban dosyaları kaldırılabilir, Bob için tüm dosyalar /members, /admins, /invited, /CRLs, /device’ler kaldırılabilir (veya sadece /device’ler yasaklanmış bir cihazsa) ve Bob’un sertifikası /banned/members/bob_uri.crt’e yerleştirilir (veya /banned/devices/uri.crt bir cihaz yasaklanmışsa) ve repo’ya ödeneklenebilir

  • Sonra Alice diğer kullanıcıları (Bob dışında) bilgilendiriyor

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

  • Sonra oyunun çözülüp çözülmediğini kontrol eder. Bu, yöneticilerin %50’inin Bob’u yasaklamaya razı olduğu anlamına gelir (tek başına ise, bu %50’den fazla olduğundan emin).

  • Eğer oylama çözülürse, dosyalar /votes/unban kaldırılabilir, Bob için tüm dosyalar / üyeleri, /admins, /invited, /CRLs, yeniden eklenebilir (veya sadece / cihazlar eğer yasaklanmamış bir cihazsa) ve repo’ya bağlı olabilir

Bir konuşmayı kaldır

  1. Konuşmanın silinmesini ve diğer kullanıcıların cihazlarıyla senkronize edilmesini convInfos remove=time::now() (Contact silinmesi gibi)

  2. Eğer bu konuşma için yeni bir söz verilirse, bu dinlenmez.

  3. Jami’nin başlangıcı ve repo hala mevcutsa, konuşma müşterilere duyurulmaz.

  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. Birisinin senkronize edildiğinden emin olduğumuz zaman, silinmiş=time::now() kaldırın ve diğer kullanıcıların cihazlarıyla senkronize edin

  6. Kullanıcıya ait tüm cihazlar artık deposu ve ilgili dosyaları silebilir

Modu nasıl belirlenebilir

Bu modlar zaman içinde değiştirilemez. ya da başka bir sohbet. Bu nedenle, bu veriler ilk commit mesajında depolanır. commit mesajı aşağıdaki gibi olacaktır:

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

Şimdilik “mod” değerleri kabul eder 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:

Bu işlem hala aynıdır, bir hesap addContact üzerinden bir iletişim ekleyebilir, sonra DHT üzerinden bir güven talebi gönderebilir.

  1. TrustRequest, çağrıyı kabul ederken hangi konuşmayı klonlaması gerektiğini eşlerine bildirmek için bir “conversationId” ekler.

  2. TrustRequest, bağlantı çevrimiçi olduğunda tekrar deneniyor. Bu gün durum böyle değildir (eğer bir rekabet ilkini atarsa yeni bir TrustRequest oluşturmak istemeyiz). Bu nedenle, bir hesap güven talebi alırsa, ilgili bir konuşma ile ilgili bir talebi reddedilirse otomatik olarak göz ardı edilir (convRequests senkronize edildiği için)

Sonra, bir iletişim isteği kabul ettiğinde, bir senkronizasyon süresi gereklidir, çünkü iletişim artık konuşmayı klonlamalıdır.

removeContact() bağlantıyı ve ilgili 1:1 sohbetlerini (bir sohbet kaldırmak gibi aynı işlemle) kaldırır. Burada tek not, bir bağlantıyı yasaklarsak senkronize beklemiyoruz, tüm ilgili dosyaları kaldırıyoruz.

Zor senaryolar

Bazı durumlarda iki konuşma yapılabilir.

  1. Alice adds Bob.

  2. Bob accepts.

  3. Alice removes Bob.

  4. Alice adds Bob.

veya

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

Önemli

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() senkronize edilirse {{“sinkronlama”: “gerçek”}} gönderir.

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

Konuşmalar, spesifikasyon talep ediyor

Konuşma istekleri aşağıdaki tuşlarla Map<String, String> ile temsil edilir:

  • id: the conversation ID

  • from: URI of the sender

  • Alındı: Zaman damgası

  • Başlık: (İsteğe bağlı) konuşma adı

  • Açıklama: (İsteğe bağlı)

  • avatar: (optional) the profile picture

Konuşma profilini senkronize et

Bir konuşmanın tanımlanabilmesi için genellikle bir başlık (örneğin Jami), bir açıklama (örneğin: bazı bağlantılar, proje nedir vb.) ve bir görüntü (projenin logosu) gibi bazı metadata ihtiyaç vardır.

Depoda depolanmak

Konuşmanın profilleri, klasik bir vCard dosyasında kök (/profile.vcf) gibi saklanır:

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

Senkronizasyon

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

Son Gösterilen

Sinkronleşmiş verilerde, her cihaz diğer cihazlara konuşmaların durumunu gönderir. Bu durumda, son görüntülenen gönderilir. Ancak, her cihazın her konuşma için kendi durumuna sahip olabileceği ve muhtemelen aynı son commit olmadan bir noktada, dikkate alınması gereken birkaç senaryo vardır:

5 senaryo desteklenir:

  • Eğer diğer cihazlar tarafından gönderilen son görüntü mevcut olanla aynı ise, hiçbir şey yapılmaz.

  • Eğer mevcut cihaz için son görüntülenmemişse, uzaktan görüntülenen mesaj kullanılır.

  • Eğer son görüntülenen uzaktan mesafe repo’da bulunmazsa, commit daha sonra alınır demektir, bu yüzden sonuç önbelleğe alınır

  • Eğer uzaktan uzaktan ayarlanmışsa, son gösterilen yerel geçmişte daha önce olup olmadığını kontrol ederek değiştiririz.

  • Son olarak, aynı yazardan bir mesaj duyurulursa, son görüntülenmiş mesajı güncelleme ihtiyacımız olduğu anlamına gelir.

Tercihler

Her konuşmada kullanıcı tarafından belirlenen tercihler eklenmiştir. Bu tercihler kullanıcı cihazları arasında senkronize edilir. Bu, kullanıcı bildirimleri görmezden gelmek istiyorsa konuşmanın rengi olabilir, dosya transfer boyut sınırı vb.

  • “color” - the color of the conversation (#RRGGBB format)

  • “İgnoreNotifications” - bu konuşmada yeni mesajlar için bildirimleri görmezden gelmek

  • “simbol” - varsayılan bir emoji tanımlamak için.

Bu tercihler MapStringString paketinde depolanır, accountDir/conversation_data/conversationId/preferences’de depolanır ve yalnızca aynı kullanıcının cihazları arasında SyncMsg üzerinden gönderilmektedir.

Tercihleri etkileşime geçiren API’ler:

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

Birleştirme çatışmaları yönetimi

İki yöneticinin aynı anda açıklamayı değiştirebileceği için profile.vcf’de bir birleşme çatışması meydana gelebilir. Bu durumda, daha yüksek hash (örneğin ffffff > 000000) ile commit seçilir.

API’ler

Kullanıcı konuşmanın metadatalarını almak ve ayarlamak için 2 yöntem elde etti:

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

info aşağıdaki tuşlarla map<str, str>’dir:

  • Mod: Sadece okunur

  • başlık

  • Açıklama

  • avatar: the profile picture

Kullanılan protokoller

Git

Neden bu seçimi

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

  1. Mesajları senkronize etmek ve sipariş etmek zorundayız. Merkle Ağacı bunu yapmak için mükemmel bir yapı ve dalları birleştirerek doğrusal hale getirilebilir. Dahası, Git tarafından büyük ölçüde kullanıldığı için, cihazlar arasında senkronize etmek kolaydır.

  2. Distributed by nature. Massively used. Lots of backends and pluggable.

  3. Haklar ve büyük ölçüde kullanılan kripto aracılığıyla commits doğrulayabilir

  4. Gerekirse bir veritabanında depolanır

  5. Çatışmaların önlenmesi için dosyaları değil, commit mesajları kullanılır.

Neyi onaylamalıyız

  • Performans? git.lock düşük olabilir

  • Libgit2’de kaçaqlar

  • Aynı anda birden fazla çekim mi?

Sınırlar

Tarih silinemez. Bir konuşmayı silmek için cihaz konuşmayı terk edip başka bir konuşma oluşturmalıdır.

Bununla birlikte, kalıcı olmayan mesajlar (örneğin sadece birkaç dakika okunur mesajlar) DRT üzerinden özel bir mesaj (örneğin Yazma veya Oku bildirimleri) ile gönderilebilir.

Yapı

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

Dosya aktarımı

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

Gönder, sohbette aşağıdaki biçimle yeni bir commit ekler:

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

ve ${data_path}/conversation_data/${conversation_id}/${file_id}’de bir bağlantı oluşturur.

Ardından, alıcı şimdi dosyayı barındıran cihazlarla iletişim kurarak dosyayı indirerek name="data-transfer://" + conversationId + "/" + currentDeviceId() + "/" + fileId ile bir kanal açabilir ve dosyanın beklediği bilgiyi ${data_path}/conversation_data/${conversation_id}/waiting

Bağlantıyı alan cihaz, dosyanın gönderilebileceğini doğrulayarak kanalı kabul eder (sha3sum doğruysa ve dosya varsa). Alıcı ilk açılan kanalı tutar, diğerlerini kapatır ve gelen tüm verileri bir dosyaya yazar (yurtananla aynı yolla: ${data_path}/conversation_data/${conversation_id}/${file_id}).

Transfer tamamlandığında veya kanal kapatıldığında, dosyanın doğru olduğunu doğrulamak için sha3sum doğrulanır (ya da silinir). Eğer geçerli ise, dosya bekleme sırasında silinecektir.

Başarısızlık durumunda, konuşmanın bir cihazı tekrar çevrimiçi olduğunda, tüm bekleme dosyalarını aynı şekilde isteyeceğiz.

Call in Swarm

Fikir

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

“accountUri/deviceId/conversationId/confId” hesabUri/deviceId’in barındırmayı tanımladığı yer.

Ev sahibi iki şekilde belirlenebilir:

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

  • Ya da ilk arayan.

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)

Böylece her birim bir çağrı başladığı bilgileri alacak ve çağrı yaparak ona katılabilecek.

Saldırı mı?

  • Avoid Git bombs

Notlar

Bir commit’in zaman damgasına güvenebilirsiniz çünkü düzenlenebilir. Sadece kullanıcının zaman damgasına güvenebilirsiniz.

TLS

Git işlemleri, kontrol mesajları, dosyalar ve diğer şeyler, PFS’i garanti eden sadece şifre ile p2p TLS v1.3 bağlantısını kullanacak.

DHT (UDP)

Cep telefonları için mesaj göndermek (push bildirimlerini tetiklemek) ve TCP bağlantıları başlatmak için kullanılır.

Ağ faaliyeti

Birini davet etme süreci

Alice Bob’u davet etmek istiyor:

  1. Alice konuşmaya Bob’u ekliyor.

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

  3. Mesajı göndermek için iki olasılık a. Eğer bağlantılı değilse, DHT b. Yoksa Alice SIP kanalı üzerinden gönderir

  4. Bob için iki olasılık a. davet alıyor, bir sinyal gönderilir istemci b. Bağlı değil, bu yüzden asla isteği almayacak çünkü Alice Bob’un Alice’i görmezden geldiğini veya engellediğini bilmemesi gerekir. Tek yol yeni bir mesaj aracılığıyla yeni bir davet yeniden üretmektir (bakınız sonraki senaryo)

Birine mesaj gönderme süreci

Alice Bob’a bir mesaj göndermek istiyor:

  1. Alice, repo’ya bir mesaj ekliyor, kimlik veriyor.

  2. Alice başarılı olursa bir mesaj alır

  3. İki olasılık, Alice ve Bob bağlantılı veya bağlantılı değil. Her iki durumda da bir mesaj oluşturulur: { “application/im-gitmessage-id” : “{“id”:”\(convId", "commit":"\)commitId”, “deviceId”: “$alice_device_hash”}”}.

  4. Bob için dört olasılık: a. Bob Alice’e bağlanmamıştır, bu yüzden Alice’e güvenirse, yeni bir bağlantı isteyin ve b. b’ye gidin. Eğer bağlanmışsa, Alice’den getir ve yeni mesajlar duyurun. c. Bob bu konuşmayı bilmiyor.

Uygulama

Şekil: Swarm sohbet dersleri

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

Çağrılar

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

!! Eski taslak!!

Not

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

Kripto gelişmeleri.

Ciddi bir grup sohbet özelliği için, ciddi kripto da gerekir. mevcut tasarımla, bir konuşmanın önceki DHT değerleri olarak bir sertifika çalındığında, konuşma şifreli hale gelebilir. Belki de ** Double ratchet** gibi bir şeye gitmemiz gerekir.

Not

A lib might exist to implement group conversations.

OpenDHT’de ECC desteğine ihtiyaç duyuyor

Kullanım

Roller ekle?

Grup sohbetleri için iki önemli kullanım alanı vardır:

  1. Özel kanallar ve bazı roller (admin/seyirci/bot/b.d.) veya eğitim için (sadece birkaç kişinin aktif olduğu) bir şirkette bir Mattermost gibi bir şey.

  2. Düzsel konuşmalar arkadaşlar arasındaki konuşma gibi.

Jami will be for which one?

Uygulama fikri

Bir rol için bayraklı bir kullanıcı imzalayan bir grup için bir sertifika.

Bir sohbete katılın.

  • Sadece doğrudan davet yoluyla

  • Bağlantı/QR kodu/her ne olursa olsun

  • Bir oda adı ile mi?

Neye ihtiyacımız var

  • Gizlilik: grup sohbetinden dışındaki üyeleri gruptaki mesajları okuyamamalıdır

  • Önceki gizlilik: Eğer gruptan herhangi bir anahtar tehlikeye girerse, önceki mesajlar gizli kalmalıdır (mümkün olduğunca)

  • Mesaj düzenlemesi: Mesajların doğru sırada olması gerekir

  • Senkronizasyon: Tüm mesajların mümkün olduğunca kısa sürede ulaştığını da emin olmak gerekir.

  • Persistence: Actually, a message on the DHT lives only 10 minutes. Because it’s the best timing calculated for this kind of DHT. To persist data, the node must re-put the value on the DHT every 10 minutes. Another way to do when the node is offline is to let nodes re-put the data. But, if after 10 minutes, 8 nodes are still here, they will do 64 requests (and it’s exponential). The current way to avoid spamming for that is queried. This will still do 64 requests but limit the max redundancy to 8 nodes.

Diğer dağıtılı yollar

  • IPFS: Biraz soruşturma gerekiyor

  • Biraz soruşturma lazım.

  • Biraz soruşturma lazım.

Şu anda yaptığımız işlere dayanarak

Grup sohbetleri, çoklu cihazlar için zaten yaptığımız aynı çalışmaya dayanarak yapılabilir.

  1. Bu veri tabanını istemciden daemon’a taşıyor.

  2. Eğer kimse bağlanmıyorsa senkronizasyon yapılmaz ve kişi konuşmayı asla görmez.

Başka bir özel DHT

Bir DHT’nin süper kullanıcısı gibi.

What’s next for file transfers

Currently, the file transfer algorithm is based on a TURN connection (See Dosya aktarımı). 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)

Kaynaklar