Schar

Wichtig

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

Synospis

Ziel dieses Dokuments ist es, zu beschreiben, wie Gruppenchats (auch bekannt als Schwarm-Chat**) in Jami umgesetzt werden.

Eine swarm ist eine Gruppe, die ohne Zentralautorität auf widerstandsfähige Weise diskutieren kann. Wenn zwei Personen keine Verbindung zum Rest der Gruppe haben (d. h. Internetunterbrochen), aber sie sich gegenseitig kontaktieren können (z. B. in einem LAN oder einem Subnetzwerk), können sie sich gegenseitig Nachrichten senden und dann, wenn möglich, mit dem Rest der Gruppe synchronisieren.

Die Schaum wird also definiert:

  1. Fähigkeit, sich nach der Verbindung zu trennen und zu verschmelzen.

  2. Jeder muss eine Nachricht an die ganze Gruppe senden können.

  3. Keine zentrale Behörde, kann sich nicht auf einen Server verlassen.

  4. Nicht-Verweigerung: Geräte müssen in der Lage sein, die Gültigkeit alter Nachrichten zu überprüfen und die gesamte Geschichte wiederzufinden.

  5. Die Speicherung wird vom Gerät verwaltet.

Die Idee ist, einen synchronisierten Merkle-Baum mit den Teilnehmern zu bekommen.

Wir haben vier Modi für Schwarm-Chat identifiziert, die wir implementieren wollen:

  • EINER_ZU EINER, im Grunde der Fall, den wir heute haben, wenn Sie mit einem Freund diskutieren

  • ADMIN_INVITES_ONLY im Allgemeinen eine Klasse, in der der Lehrer Menschen einladen kann, aber nicht die Schüler

  • INVITES_ONLY eine private Gruppe von Freunden

  • Publikum ist im Grunde ein offenes Forum

Szenarien

Schaffen Sie eine Schar

Bob will einen neuen Schwarm schaffen.

  1. Bob creates a local Git repository.

  2. Dann erstellt er eine erste unterzeichnete Verpflichtung mit folgenden Worten:

    • Sein öffentlicher Schlüssel in /admins

    • Sein Gerätesertifikaat in ̀ /geräte `

    • Seine CRL in ̀ /crls`

  3. Das Hash des ersten Kommits wird zum ID des Gesprächs.

  4. Bob kündigt seinen anderen Geräten an, dass er eine neue Konversation erstellt.

Ein Zusatz

Alice fügt Bob hinzu.

  1. Alice fügt Bob zum Repo hinzu:

    • Fügt den eingeladenen URI in /invited hinzu

    • Zugabe der CRL in /crls

  2. Alice schickt eine Anfrage zum DHT.

Einladung zu empfangen

Alice wird eingeladen, sich dem vorher geschaffenen Schwarm anzuschließen.

  1. Sie nimmt die Einladung an (wenn sie ablehnt, tut nichts, bleibt sie in der Einladung und Alice wird nie eine Nachricht erhalten)

  2. Eine Peer-to-Peer-Verbindung zwischen Alice und Bob ist geschehen.

  3. Alice pull the Git repo of Bob. WARNING this means that messages need a connection, not from the DHT like today.

  4. Alice bestätigt die Verpflichtungen von Bob

  5. Um zu bestätigen, dass Alice Mitglied ist, entfernt sie die Einladung aus dem Verzeichnis /invited und fügt ihr Zertifikat dann in das Verzeichnis /members hinzu.

  6. Sobald alle Kommitte validiert und auf ihrem Gerät, werden andere Mitglieder der Gruppe von Alice entdeckt. Mit diesen Peers, sie wird die DRT (unterhalb erklärt) mit Bob als Bootstrap zu konstruieren.

Eine Nachricht senden

Alice schickt eine Nachricht

Eine Nachricht zu senden ist ziemlich einfach. Alice schreibt eine Kommit-Message in folgendem Format:

{
    "type": "text/plain",
    "body": "coucou"
}

and adds her device and CRL to the repository if missing (others must be able to verify the commit). Merge conflicts are avoided because we are mostly based on commit messages, not files (unless CRLS + certificates but they are located). Then she announces the new commit via the DRT with a service message (explained later) and pings the DHT for mobile devices (they must receive a push notification).

Für das Pinging anderer Geräte sendet der Absender einem anderen Mitglied eine SIP-Nachricht mit einem Mimetype = „Application/im-gitmessage-id“ mit einem JSON mit der „deviceId“, die die Nachricht sendet, dem „id“ des Gesprächs und der „commit“

Eine Nachricht empfangen

Bob erhält die Nachricht von Alice

  1. Bob do a Git pull on Alice

  2. Die Verpflichtungen müssen über einen Haken überprüft werden

  3. Wenn alle Commits gültig sind, werden die Commits gespeichert und angezeigt.

  4. If all commits are not valid, pull is canceled. Alice must reestablish her state to a correct state.

Validierung eines Verpflichtungsbestimmungsbereichs

Um zu vermeiden, dass Benutzer einige unerwünschte Kommitte (mit Konflikten, falschen Nachrichten usw.) durchführen, muss jedes Kommitte (von dem ältesten bis zum neuesten) vor der Verschmelzung einer Remote-Fläche validiert werden:

Bemerkung

  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.

  • Überprüfen Sie für jede Verpflichtung, ob das Gerät, das die Verpflichtung senden will, zur Zeit zugelassen ist und die Zertifikate vorhanden sind (in Geräten für das Gerät und in Mitgliedern oder Administratoren für den Emittenten).

  • Das Kommit hat 2 Eltern, also ist es eine Fusion, nichts mehr zu bestätigen hier

  • Das Commit hat 0 Eltern, es ist das Anfangscommit:

    • Überprüfen Sie, ob admin-Certifikat hinzugefügt wurde

    • Überprüfen Sie, ob das Gerät-Cert hinzugefügt ist

    • Kontroll-CRLs hinzugefügt

    • Überprüfen Sie, ob keine andere Datei hinzugefügt wird

  • Das commit hat 1 Mutter, das commit-Message ist ein JSON mit einem Typ:

    • Wenn Text (oder ein anderer Mime-Typ, der keine Dateien ändert)

      • Überprüfungsunterzeichnung aus dem Zertifikat im Repo

      • Überprüfen Sie, ob keine seltsame Datei außerhalb des Gerätes Cert hinzugefügt oder entfernt wird

    • Wenn sie stimmen

      • Überprüfen Sie, ob voteType unterstützt wird (Verbot, Unban)

      • Überprüfen Sie, ob die Stimme für den Benutzer bestimmt ist, der das Kommit unterschreibt.

      • Check that vote is from an admin and device present and not banned

      • Überprüfen Sie, ob keine seltsamen Dateien hinzugefügt oder entfernt werden

    • Wenn Mitglied

      • Wenn hinzugefügt

        • Überprüfen Sie, ob die Verpflichtung korrekt unterzeichnet ist

        • Überprüfen Sie, ob das Zertifikat in /invited hinzugefügt ist

        • Überprüfen Sie, ob keine seltsamen Dateien hinzugefügt oder entfernt werden

        • Wenn ONE_TO_ONE, überprüfen Sie, dass wir nur einen Administrator, ein Mitglied haben

        • Wenn ADMIN_INVITES_ONLY, überprüfen Sie, dass die Einladung von einem Admin

      • Wenn sich

        • Überprüfen Sie, ob die Verpflichtung korrekt unterzeichnet ist

        • Überprüfen Sie, ob das Gerät hinzugefügt wurde

        • Überprüfen Sie, ob die Einladung an Mitglieder weitergeleitet wird

        • Überprüfen Sie, ob keine seltsamen Dateien hinzugefügt oder entfernt werden

      • Wenn verboten

        • Überprüfen Sie, ob die Abstimmung gültig ist.

        • Überprüfen Sie, ob der Benutzer über einen Admin verboten ist

        • Überprüfen Sie, ob das Mitglied- oder Gerätesertifika auf Verbot/

        • Überprüfen Sie, ob nur die mit der Abstimmung verbundenen Dateien entfernt werden

        • Überprüfen Sie, ob keine seltsamen Dateien hinzugefügt oder entfernt werden

    • Benutzerin kann mit einer alten Version oder dem Peer versucht werden, unerwünschte Kommits zu senden

Verbot eines Geräts

Alice, Bob, Carla, Denys sind in einem Schwarm.

Das ist eines der schwierigsten Szenarien in unserem Kontext.

  1. Zeitstempel der erzeugten Verpflichtungen

  2. Wenn mehrere Admin-Geräte vorhanden sind und wenn Alice mit Bob sprechen kann, aber nicht mit Denys und Carla; Carla mit Denys sprechen kann; Denys verbietet Alice, Alice verbietet Denys, wie wird es aussehen, wenn die 4 Mitglieder die Gespräche fusionieren.

  3. Ein Gerät kann kompromittiert, gestohlen oder sein Zertifikat verfallen. Wir sollten ein Gerät verbieten und vermeiden, dass es über sein Verlauf lügt oder in der Vergangenheit Nachrichten sendet (durch Änderung seines Zertifikats oder des Zeitstauchers seines Kommitments).

Ähnliche Systeme (mit verteilten Gruppensystemen) sind nicht so viel, aber hier sind einige Beispiele:

  • [mpOTR definiert nicht, wie man jemanden verbietet]

  • Signal, ohne einen zentralen Server für Gruppenchat (EDIT: Sie ändern diesen Punkt kürzlich), gibt nicht die Möglichkeit, jemanden aus einer Gruppe zu verbieten.

Dieses Stimmsystem benötigt eine menschliche Aktion, um jemanden zu verbieten oder muss sich auf die CRL-Informationen aus dem Repository stützen (weil wir externen CRLs nicht vertrauen können).

Entfernen Sie ein Gerät aus einem Gespräch

Das ist der einzige Teil, an dem ein Konsens besteht, um eine Spaltung zu vermeiden. Wenn sich zwei Mitglieder aus dem Gespräch treten, was wird dann das dritte sehen?

Dies ist notwendig, um widerrufene Geräte zu erkennen oder einfach zu vermeiden, dass unerwünschte Personen in einem öffentlichen Raum vorhanden sind.

Alice entfernt Bob.

Wichtig

Alice MUST be an admin to vote.

  • Erstens stimmt sie für das Verbot von Bob. Dazu erstellt sie die Datei in /votes/ban/members/uri_bob/uri_alice (Mitglieder können durch Geräte für ein Gerät ersetzt werden, oder für Einladungen oder Admin für Admin eingeladen werden) und verpflichtet sich,

  • Dann überprüft sie, ob die Abstimmung gelöst ist. Das bedeutet, dass >50% der Admin bereit sind, Bob zu verbieten (wenn sie allein ist, ist es sicher mehr als 50%).

  • Wenn die Abstimmung gelöst ist, können Dateien in /votes/ban entfernt werden, alle Dateien für Bob in /members, /admins, /invited, /CRLs, /devices entfernt werden (oder nur in /devices, wenn es sich um ein Gerät handelt, das verboten ist) und Bobs Zertifikat kann in /banned/members/bob_uri.crt (oder /banned/devices/uri.crt, wenn ein Gerät verboten ist) platziert und dem repo übertragen werden

  • Dann informiert Alice andere Benutzer (außer 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

  • Dann überprüft sie, ob die Abstimmung gelöst ist. Das bedeutet, dass >50% der Admin bereit sind, Bob zu verbieten (wenn sie allein ist, ist es sicher mehr als 50%).

  • Wenn die Abstimmung gelöst ist, können Dateien in /votes/unban entfernt werden, alle Dateien für Bob in /members, /admins, /invited, /CRLs, können neu hinzugefügt werden (oder nur in /devices, wenn es sich um ein Gerät handelt, das nicht verboten ist) und dem Repo verpflichtet werden

Entfernen Sie ein Gespräch

  1. Speichern Sie in convInfos removed=time::now() (wie removeKontakt speichert in Kontakten) dass die Konversation entfernt und mit den Geräten anderer Benutzer synchronisiert wird

  2. Wenn ein neuer Kompromiss für dieses Gespräch eingegangen ist, wird er ignoriert.

  3. Wenn Jami noch in Betrieb ist, wird das Gespräch nicht bekannt gegeben.

  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. Wenn wir sicher sind, dass jemand synchronisiert ist, entfernen wir erledigt=zeit::now() und synchronisieren wir mit den Geräten anderer Benutzer

  6. Alle Geräte des Benutzers können das Repository und die damit verbundenen Dateien löschen

Wie ein Modus angegeben wird

Die Modus können nicht im Laufe der Zeit geändert werden. Oder es ist ein anderes Gespräch. Also werden diese Daten in der ersten Kommit-Nachricht gespeichert.

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

Derzeit akzeptiert „Mode“ Werte 0 (ONE_TO_ONE), 1 (ADMIN_INVITES_ONLY), 2 (INVITES_ONLY), 3 (PUBLIC)

Processes for 1:1 swarms

Das Ziel ist es, die alte API (addContact/removeContact, sendTrustRequest/acceptTrustRequest/discardTrustRequest) zu erhalten, um einen Schwarm mit einem Peer und seinem Kontakt zu generieren. Dies bedeutet immer noch einige Änderungen, die wir nicht ignorieren können:

Der Prozess ist immer noch derselbe, ein Konto kann einen Kontakt über addContact hinzufügen und dann eine TrustRequest über die DHT senden.

  1. Die TrustRequest enthält eine „ConversationId“, um dem Peer zu mitteilen, welche Konversation er klonen soll, wenn er die Anfrage akzeptiert

  2. TrustRequest wird erneut versucht, wenn der Kontakt online zurückkehrt. Das ist heute nicht der Fall (da wir keinen neuen TrustRequest erstellen wollen, wenn der Peer den ersten entfernt). Wenn also ein Konto eine Vertrauensanfrage erhält, wird es automatisch ignoriert, wenn die Anfrage mit einem verwandten Gespräch abgelehnt wird (da convRequests synchronisiert werden)

Wenn ein Kontakt die Anfrage akzeptiert, ist eine Synchronisierungsperiode notwendig, denn der Kontakt muss jetzt das Gespräch klonen.

removeContact() wird den Kontakt und die damit verbundenen 1:1-Gespräche entfernen (mit dem gleichen Prozess wie „Entfernen Sie eine Konversation“).

Schwierige Szenarien

Es gibt einige Fälle, in denen zwei Gespräche erfolgen können.

  1. Alice adds Bob.

  2. Bob accepts.

  3. Alice removes Bob.

  4. Alice adds Bob.

oder

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

In diesem Fall werden zwei Gespräche erzeugt. Wir wollen keine Nachrichten von Benutzern entfernen oder hier eine Konversation auswählen. So wird manchmal zwei 1:1-Schwarm zwischen den gleichen Mitgliedern angezeigt. Es wird einige Fehler während der Übergangszeit erzeugen (da wir nicht API brechen wollen, wird die abgeleitete Konversation eine der beiden gezeigten Gespräche sein, aber für jetzt ist es „ok-ish“, wird behoben, wenn die Kunden KonversationId für alle APIs (Anrufe, Dateitransfer, etc.) vollständig verarbeiten).

Wichtig

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() wird {{„Synchronisierung“: „Wahr“}} zurückgeben, wenn sie synchronisiert wird.

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

Gespräche verlangen eine Spezifikation

Die Gesprächsanfragen werden durch eine Map<String, String> mit folgenden Tasten dargestellt:

  • id: the conversation ID

  • from: URI of the sender

  • Empfang: Zeitstempel

  • Titel: (optional) Name für das Gespräch

  • Beschreibung: (optional)

  • Avatar: (optional)

Synchronisierung des Gesprächsprofilen

Um zu identifizieren, benötigt ein Gespräch im Allgemeinen einige Metadaten, wie einen Titel (z.B. Jami), eine Beschreibung (z.B. einige Links, was das Projekt ist, etc.) und ein Bild (das Logo des Projekts). Diese Metadaten sind optional, werden jedoch an alle Mitglieder geteilt, daher müssen sie synchronisiert und in die Anfragen aufgenommen werden.

Speicherung im Repository

Das Konversationsprofil wird in einer klassischen vCard-Datei an der Basis (/profile.vcf) gespeichert, wie:

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

Synchronisierung

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

Zuletzt angezeigt

In den synchronisierten Daten sendet jedes Gerät den Status der Gespräche an andere Geräte. In diesem Zustand wird der letzte angezeigte gesendet. Da jedoch jedes Gerät seinen eigenen Zustand für jedes Gespräch haben kann und wahrscheinlich ohne dasselbe letzte Kommit zu einem bestimmten Zeitpunkt, gibt es mehrere Szenarien zu berücksichtigen:

Es werden fünf Szenarien unterstützt:

  • Wenn die letzte von anderen Geräten gesendete Anzeige die gleiche ist wie die aktuelle, ist nichts zu tun.

  • wenn für das aktuelle Gerät keine letzte Anzeige vorhanden ist, wird die Fernanzeigungsnachricht verwendet.

  • Wenn die letzte Remote nicht im Repo vorhanden ist, bedeutet dies, dass das Commit später abgerufen wird, also wird das Ergebnis in Cache gebracht

  • Wenn die Fernbedienung bereits abgerufen ist, überprüfen wir, ob die letzte angezeigte Lokalvorrichtung in der Geschichte ist, um sie zu ersetzen

  • Wenn schließlich eine Nachricht vom gleichen Autor angekündigt wird, bedeutet dies, dass wir die letzte angezeigte Nachricht aktualisieren müssen.

Einstellungen

Jedes Gespräch hat die von dem Benutzer festgelegten Präferenzen angeschlossen. Diese Präferenzen werden über die Geräte des Benutzers synchronisiert. Dies kann die Farbe des Gesprächs sein, wenn der Benutzer Benachrichtigungen ignorieren möchte, Dateigrößenbeschränkung usw.

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

  • „ignoreNotifications“ - die Benachrichtigungen für neue Nachrichten in diesem Gespräch zu ignorieren

  • „Symbol“ - um ein Standard-Emoji zu definieren.

Diese Präferenzen werden in einem MapStringString-Paket gespeichert, in accountDir/conversation_data/conversationId/preferences gespeichert und nur über SyncMsg über Geräte des gleichen Benutzers gesendet.

Die API zur Interaktion mit den Präferenzen sind:

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

Konfliktmanagement durch Fusion

Da zwei Admin die Beschreibung gleichzeitig ändern können, kann auf profile.vcf ein Fusionkonflikt auftreten. In diesem Fall wird das Commit mit dem höheren Hash (z.B. ffffff > 000000) gewählt.

API

Der Benutzer hat 2 Methoden zur Erfassung und Einstellung der Metadaten der Konversation:

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

wo infos eine map<str, str> mit folgenden Tasten ist:

  • Modus: Lese-Nur

  • Titel

  • Beschreibung

  • Avatar

Gebrauchsprotokolle

Git

Warum diese Wahl

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

  1. Wir müssen Nachrichten synchronisieren und bestellen. Der Merkle Tree ist die perfekte Struktur dafür und kann durch das Zusammenspielen von Zweigen linearisiert werden. Außerdem, weil es von Git massiv verwendet wird, ist es einfach, zwischen Geräten zu synchronisieren.

  2. Wird in der Natur verteilt, massiv verwendet, viele Backends und Plug-ins.

  3. Kann über Haken und massiv genutzte Krypto-Verbindungen überprüfen

  4. Kann bei Bedarf in einer Datenbank gespeichert werden

  5. Konflikte werden vermieden, indem man mit Kommit-Nachrichten, nicht mit Dateien, arbeitet.

Was wir bestätigen müssen

  • Leistung? git.lock kann niedrig sein

  • Anschläge in Libgit2

  • Mehrfach gleichzeitig?

Grenzen

Um eine Konversation zu löschen, muss das Gerät die Konversation verlassen und eine andere erstellen.

Nicht dauerhafte Nachrichten (z. B. Nachrichten, die nur für einige Minuten gelesen werden können) können jedoch über eine spezielle Nachricht über die DRT (z. B. Notifikationen zum Tippen oder Lesen) gesendet werden.

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

Dateifügelübertragung

Swarm ändert den Dateitransfer massiv. Jetzt synchronisiert sich die gesamte Geschichte, so dass alle Geräte im Gespräch alte Dateien leicht abrufen können. Diese Änderungen ermöglichen es uns, von einer Logik zu wechseln, in der der Absender die Datei auf andere Geräte verschoben hat, über das Versuchen, sich mit ihren Geräten zu verbinden (das war schlecht, weil es nicht wirklich gegen Verbindungsänderungen / Fehler bestand und benötigte einen manuellen erneuten Versuch), zu einer Logik, in der der Absender anderen Geräten erlauben, herunterzuladen.

Protokoll

Der Absender fügt in die Unterhaltung ein neues Commit hinzu:

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

und erstellt einen Link in ${data_path}/conversation_data/${conversation_id}/${file_id} wo file_id=${commitid}_${value["Tid"]}.${extension}

Dann kann der Empfänger nun die Dateien herunterladen, indem er die Geräte kontaktiert, die die Datei beherbergen, indem er einen Kanal mit name="data-transfer://" + conversationId + "/" + currentDeviceId() + "/" + fileId öffnet und die Informationen speichert, dass die Datei in ${data_path}/conversation_data/${conversation_id}/waiting

Das Anschlussgerät akzeptiert den Kanal, indem es überprüft, ob die Datei gesendet werden kann (wenn sha3sum korrekt ist und wenn Datei existiert). Der Empfänger hält den ersten geöffneten Kanal, schließt die anderen und schreibt in eine Datei (mit dem gleichen Weg wie der Absender: ${data_path}/conversation_data/${conversation_id}/${file_id}) alle eingehenden Daten.

Wenn die Übertragung abgeschlossen ist oder der Kanal geschlossen ist, wird die sha3sum überprüft, um zu bestätigen, dass die Datei korrekt ist (andernfalls wird sie gelöscht).

Im Falle eines Ausfalls, wenn ein Gerät des Gesprächs wieder online ist, bitten wir alle Wartedateien auf die gleiche Weise.

Ruf in Schwarm

Idee

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

„accountUri/deviceId/conversationId/confId“ wo accountUri/deviceId den Host beschreibt.

Der Gastgeber kann auf zwei Arten bestimmt werden:

  • In der Metadatenmasse, wo sie wie der Titel/Desk/Avatar des Raumes gespeichert sind.

  • Oder der erste Anrufer.

Bei der Anleitung eines Anrufs wird der Gastgeber dem Schwarm ein neues Commit hinzufügen, wobei der URI (AccountUri/DeviceId/ConversationId/confId) angeschlossen werden soll.

Jeder Teil wird die Information erhalten, dass ein Anruf gestartet wurde und kann sich daran beteiligen, indem er es anruft.

Angriffe?

  • Avoid Git bombs

Anmerkungen

Der Zeitstempel eines Commits ist zuverlässig, weil er bearbeitet werden kann. Nur dem Zeitstempel des Nutzers kann man vertrauen.

TLS

Git-Operationen, Steuerungsnachrichten, Dateien und andere Dinge verwenden einen P2p TLS v1.3-Link mit nur Verschlüsselungen, die PFS garantieren.

DHT (UDP)

Verwendet zur Absendung von Nachrichten für Mobiltelefone (um Push-Benachrichtigungen auszulösen) und zur Einleitung von TCP-Verbindungen.

Netzwerkaktivität

Ein Einladungsprozess

Alice will Bob einladen:

  1. Alice fügt Bob zu einem Gespräch hinzu.

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

  3. Zwei Möglichkeiten zum Versenden der Nachricht a. Wenn nicht verbunden, über die DHT b. Anders, Alice sendet auf dem SIP-Kanal

  4. Zwei Möglichkeiten für Bob a. Erhält die Einladung, ein Signal wird für den Client b. Nicht verbunden, so wird nie die Anfrage erhalten, weil Alice nicht wissen muss, ob Bob einfach ignoriert oder blockiert Alice.

Prozess, um jemandem eine Nachricht zu senden

Alice will Bob eine Nachricht senden:

  1. Alice fügt eine Nachricht in die Repo hinzu, gibt eine ID

  2. Alice erhält eine Nachricht (von sich selbst) wenn sie erfolgreich ist

  3. In beiden Fällen wird eine Nachricht erstellt: { „Application/im-gitmessage-id“ : „{„id“:“\(convId", "commit":"\)commitId“, „deviceId“: „$alice_device_hash“}“}. a. Wenn nicht verbunden ist, über den DHT b. Anders sendet Alice auf dem SIP-Kanal

  4. Vier Möglichkeiten für Bob: a. Bob ist nicht mit Alice verbunden, also wenn er Alice vertraut, bitten Sie um eine neue Verbindung und gehen Sie zu b. b. Wenn verbunden, holen Sie von Alice und kündigen Sie neue Nachrichten an c. Bob kennt dieses Gespräch nicht. Bitten Sie über die DHT, um zuerst eine Einladung zu erhalten, um dieses Gespräch zu akzeptieren ({„Anwendung/Einladung“, GesprächId}) d. Bob ist getrennt (kein Netzwerk, oder einfach geschlossen). Er wird die neue Nachricht nicht erhalten, sondern versuchen, zu synchronisieren, wenn die nächste Verbindung auftritt

Durchführung

! [Diagramm: Schwarm-Chat-Klassen]

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

Anrufe

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

!! Altes Entwurf!!

Bemerkung

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

Krypto-Verbesserungen.

Für eine ernsthafte Gruppen-Chat-Funktion brauchen wir auch ernsthafte Krypto. Wenn ein Zertifikat als die vorherigen DHT-Werte einer Konversation gestohlen wird, kann die Konversation entschlüsselt werden. Vielleicht müssen wir zu etwas wie Double Ratchet gehen.

Bemerkung

A lib might exist to implement group conversations.

ECC-Unterstützung in OpenDHT benötigt

Verwendung

Add Roles?

Es gibt zwei wichtige Anwendungsfälle für Gruppenchats:

  1. Etwas wie ein Mattermost in einem Unternehmen, mit privaten Kanälen und einigen Rollen (Admin/Spectator/Bot/etc) oder für Bildung (wo nur wenige aktiv sind).

  2. Horizontale Gespräche wie ein Gespräch zwischen Freunden.

Jami will be for which one?

Umsetzungsinterpretation

Ein Zertifikat für eine Gruppe, die Benutzer mit einer Flagge für eine Rolle unterschreiben.

Komm mit in ein Gespräch.

  • Nur über eine direkte Einladung

  • Über einen Link/QR-Code/was auch immer

  • Über einen Zimmernamen?

Was wir brauchen

  • Vertraulichkeit: Mitglieder außerhalb des Gruppenchats dürfen keine Nachrichten in der Gruppe lesen

  • Weiterhin geheim gehalten: Wenn ein Schlüssel der Gruppe gefährdet ist, sollten frühere Nachrichten vertraulich bleiben (soweit möglich)

  • Nachrichtenordnung: Nachrichten müssen in der richtigen Reihenfolge angeordnet werden

  • Synchronisierung: Es ist auch notwendig, sicherzustellen, dass alle Nachrichten so schnell wie möglich vorhanden sind.

  • Persistenz: Eigentlich ist eine Nachricht auf der DHT nur 10 Minuten lang. Weil es die beste Zeit ist, die für diese Art von DHT berechnet wird. Um Daten zu erhalten, muss der Knoten den Wert auf der DHT alle 10 Minuten neu setzen. Eine andere Möglichkeit, wenn der Knoten offline ist, ist es, Knoten die Daten neu zu setzen. Aber wenn nach 10 Minuten, 8 Knoten sind noch hier, werden sie 64 Anfragen machen (und es ist exponentiell). Der aktuelle Weg, Spamming zu vermeiden, ist abfragt. Dies wird immer noch 64 Anfragen tun, aber die maximale Redundanz auf 8 Knoten begrenzen.

Andere verteilte Wege

  • IPFS: Ich brauche eine Untersuchung.

  • Ich brauche eine Untersuchung.

  • Ich brauche eine Untersuchung.

Auf der Grundlage der aktuellen Arbeit, die wir haben

Gruppen-Chat kann auf der gleichen Arbeit basieren, die wir bereits für mehrere Geräte haben (aber hier mit einem Gruppenzertifikat).

  1. Hier muss die Datenbank vom Client in den Daemon verschoben werden.

  2. Wenn niemand mit dem Netzwerk verbunden ist, kann die Synchronisierung nicht durchgeführt werden, und die Person wird das Gespräch nie sehen

Ein weiterer spezieller DHT

Wie ein DHT mit einem Superbenutzer.

Dateifügelübertragung

Derzeit basiert der Dateitransferalgorithmus auf einer TURN-Verbindung (siehe Dateifügelübertragung). Bei einer großen Gruppe wird dies schlecht sein.

Ein anderes Problem: derzeit gibt es keine Implementierung von TCP-Unterstützung für ICE in PJSIP.

Ressourcen

  • Die Kommission hat die Kommission mit der Erteilung der Angabe der Kommission über die Durchführung der Verordnung (EG) Nr. 1271/2006 über die Verarbeitung von Informationen über die Verarbeitung von Daten zur Verfügung gestellt.

  • Robuste verteilte Synchronisierung vernetzter linearer Systeme mit intermittierender Information (Sean Phillips und Ricardo G. Sanfelice)