Zwerm
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:
Ability to split and merge based on network connectivity.
History synchronization. Every participant must be able to send a message to the entire group.
Geen centrale autoriteit, geen server.
Non-repudiation. Devices must be able to verify past messages’ validity and to replay the entire history.
Perfect Forward Secrecy (PFS) is provided on the transport channels. Storage is handled by each device.
Het belangrijkste idee is om een synchroniseerde Merkle boom te krijgen met de deelnemers.
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).
Scenario’s
Een Zwerm maken
Bob wil een nieuwe zwerm maken.
Bob creates a local Git repository.
Vervolgens maakt hij een initiële ondertekende verplichting met het volgende:
Zijn publieke sleutel in
/admins
Zijn apparaatcertificaat in ̀ /apparaten `
Zijn CRL in ̀ /crls`
De hash van de eerste commit wordt de ID van het gesprek
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.
Iemand toevoegen
Bob adds Alice
Bob adds Alice to the repo:
Voegt de uitgenodigde URI toe in
/invited
Voegt de CRL toe aan
/crls
Bob sends a request on the DHT.
Een uitnodiging ontvangen
Alice gets the invite to join the previously created swarm
Alice accepts the invite (if she declines, nothing happens; she will remain in the “invited” list, and will never receive any messages)
A peer-to-peer connection is established between Alice and Bob.
Alice pulls the Git repository from Bob. WARNING this means that messages require a connection, not from the DHT as it is today.
Alice validates the commits from Bob.
To validate that Alice is a member, she removes the invite from
/invited
directory, then adds her certificate to the/members
directoryOnce 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.
Een bericht sturen
Alice sends a message to Bob
Alice creates a commit message. She constructs a JSON payload containing the MIME type and message body. For example:
{
"type": "text/plain",
"body": "hello"
}
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.
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).
Alice announces the commit via the DRT with a service message and pings the DHT for mobile devices (they must receive a push notification).
Notitie
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.
Een bericht ontvangen
Bob receives a message from Alice
Bob performs a Git pull on Alice’s repository.
All incoming commits MUST be verified by a hook.
If all commits are valid, commits are stored and displayed.Bob then announces the message via the DRT for other devices.
If any commit is invalid, pull is aborted. Alice must restore her repository to a correct state before retrying.
Validering van een verplichting
Om te voorkomen dat gebruikers ongewenste commits (met conflicten, valse berichten, enz.) uitvoeren, moet elk commit (van het oudste tot het nieuwste) worden gevalideerd voordat een afstandsfiliaal wordt samengevoegd:
Notitie
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.
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 eachtype
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.
Verbod op een apparaat
Belangrijk
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:
Untrusted Timestamps: Commit timestamps cannot be relied upon for ordering ban events, as any device can forge or replay commits with arbitrary dates.
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.
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.
Gelijkaardige systemen (met gedistribueerde groepssystemen) zijn niet zo veel, maar hier zijn enkele voorbeelden:
[mpOTR definieert niet hoe iemand wordt verboden]
Signal, zonder centrale server voor groepchat (EDIT: ze hebben onlangs dat punt veranderd), geeft niet de mogelijkheid om iemand uit een groep te verbieden.
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).
Verwijder een apparaat uit een gesprek
Dit is het enige deel dat een consensus moet hebben om een gesprek te vermijden, als twee leden elkaar uit het gesprek schoppen, wat zal de derde zien?
Dit is nodig om herroepde apparaten te detecteren, of om ongewenste personen in een openbare ruimte te voorkomen.
Alice verwijdert Bob.
Belangrijk
Alice MUST be an admin to vote.
Om dat te doen, maakt ze het bestand in /votes/ban/members/uri_bob/uri_alice (leden kunnen worden vervangen door apparaten voor een apparaat, of worden uitgenodigd voor uitnodigingen of admins voor admins) en verbindt
Dan controleert ze of de stemming is opgelost. Dit betekent dat >50% van de administratoren het ermee eens is om Bob te verbieden (als ze alleen is, is het zeker meer dan 50%).
Als de stemming is opgelost, kunnen bestanden in /votes/ban worden verwijderd, alle bestanden voor Bob in /members, /admins, /invited, /CRLs, /devices kunnen worden verwijderd (of alleen in /devices als het een apparaat is dat is verboden) en het certificaat van Bob kan worden geplaatst in /banned/members/bob_uri.crt (of /banned/devices/uri.crt als een apparaat is verboden) en toegezegd aan de repo
Dan informeert Alice andere gebruikers (buiten 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
Dan controleert ze of de stemming is opgelost. Dit betekent dat >50% van de administratoren het ermee eens is om Bob te verbieden (als ze alleen is, is het zeker meer dan 50%).
Als de stemming is opgelost, kunnen bestanden in /votes/unban worden verwijderd, alle bestanden voor Bob in /members, /admins, /invited, /CRLs, kunnen worden toegevoegd (of alleen in /devices als het een apparaat is dat is ongebannen) en toegezegd aan de repo
Verwijder een gesprek
Save in convInfos removed=time::now() (zoals removeContact save in contacten) dat de conversatie wordt verwijderd en wordt gesynchroniseerd met andere apparaten van de gebruiker
Als er een nieuwe commissie wordt ontvangen voor dit gesprek, wordt het genegeerd.
Als Jami opstart en de repo nog aanwezig is, wordt het gesprek niet bekendgemaakt aan klanten.
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.
Als we zeker zijn dat iemand is gesynchroniseerd, verwijder de gesloten = tijd:: nu() en synchroniseren met andere gebruikers apparaten
Alle apparaten die eigendom zijn van de gebruiker kunnen nu het opslagplaats en de bijbehorende bestanden wissen
Hoe een modus wordt gespecificeerd
De modus kan niet worden gewijzigd door de tijd. Of het is een ander gesprek. Dus, deze gegevens worden opgeslagen in de eerste commit bericht.
{
"type": "initial",
"mode": 0,
}
Vooralsnog accepteert “mode” waarden 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:
Het proces is nog steeds hetzelfde, een account kan een contact via addContact toevoegen, en vervolgens een TrustRequest via de DHT sturen.
De TrustRequest bevat een “conversationId” om de peer te informeren welke gesprek te klonen wanneer hij het verzoek accepteert
TrustRequest wordt opnieuw geprobeerd wanneer contact online komt. Het is niet het geval vandaag (omdat we geen nieuwe TrustRequest willen genereren als de peer de eerste verwijdert). Als een account een vertrouwensverzoek ontvangt, wordt het automatisch genegeerd als het verzoek met een gerelateerd gesprek wordt afgewezen (aangesien convRequests worden gesynchroniseerd)
Wanneer een contact het verzoek aanvaardt, is een synchronisatieperiode nodig, omdat het contact nu het gesprek moet klonen.
removeContact() verwijdert het contact en de gerelateerde 1:1 gesprekken (met hetzelfde proces als “Remove a conversation”).
Moeilijke scenario’s
Er zijn sommige gevallen waarin twee gesprekken kunnen worden gecreëerd.
Alice adds Bob.
Bob accepts.
Alice removes Bob.
Alice adds Bob.
of
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)).
Belangrijk
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() zal {{“sync”: “true”}} teruggeven als het wordt gesynchroniseerd.
ConfigurationManager::getConversationMembers() will return a map of two URIs (the current account and the peer who sent the request).
Gesprekken vragen om specificatie
De gesprekken worden aangevraagd door een Map<String, String> met de volgende sleutels:
id: the conversation ID
from: URI of the sender
ontvangen: tijdstempel
titel: (optioneel) naam voor het gesprek
beschrijving: (optioneel)
avatar: (optional) the profile picture
Synchronisatie van het gespreksprofiel
Om te kunnen worden geïdentificeerd, heeft een gesprek over het algemeen metadata nodig, zoals een titel (bijv. Jami), een beschrijving (bijv. enkele links, wat het project is, enz.) en een afbeelding (het logo van het project).
Opberging in de opslagplaats
Het profiel van het gesprek wordt opgeslagen in een klassiek vCard-bestand bij de root (/profile.vcf
) zoals:
BEGIN:VCARD
VERSION:2.1
FN:TITLE
DESCRIPTION:DESC
END:VCARD
Synchronisatie
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).
Laatste weergave
In de gesynchroniseerde gegevens stuurt elk apparaat de staat van de gesprekken naar andere apparaten. In deze staat wordt de laatste weergegeven gestuurd.
Er worden vijf scenario’s ondersteund:
Als de laatste weergave die door andere apparaten is verzonden, dezelfde is als de huidige, is er niets te doen.
indien er geen laatste weergave voor het huidige apparaat is, wordt het bericht dat op afstand wordt weergegeven gebruikt.
Als de laatste afstandsbediening niet aanwezig is in de repo, betekent dit dat de commit later wordt opgehaald, dus cache het resultaat
Als de afstandsbediening al is opgehaald, controleren we of de laatste lokale weergave eerder is in de geschiedenis om het te vervangen
Ten slotte, als er een bericht van dezelfde auteur wordt aangekondigd, betekent dit dat we het laatste bericht moeten bijwerken.
Voorkeuren
Bij elke conversatie zijn voorkeuren bijgevoegd die door de gebruiker zijn ingesteld. Deze voorkeuren worden gesynchroniseerd op de apparaten van de gebruiker. Dit kan de kleur van het gesprek zijn, als de gebruiker meldingen wil negeren, bestandsgrootte limiet, enz. Voorlopig zijn de herkenbare sleutels:
“color” - the color of the conversation (#RRGGBB format)
“ignore notifications” - om in dit gesprek notificaties voor nieuwe berichten te negeren
“symbool” - om een standaard emoji te definiëren.
Deze voorkeuren worden opgeslagen in een MapStringString-pakket, opgeslagen in accountDir/conversation_data/conversationId/preferences
en alleen via SyncMsg via dezelfde gebruikersapparatuur verzonden.
De API om met de voorkeuren te communiceren is:
// 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*/);
};
Conflictenbeheer bij fusie
Omdat twee beheerders de beschrijving tegelijkertijd kunnen wijzigen, kan er op profile.vcf
een fusieconflict optreden. In dit geval wordt de commit met de hogere hash (bijv. ffffff > 000000) gekozen.
API’s
De gebruiker heeft 2 methoden om metadata van gesprekken te krijgen en te instellen:
<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>
waar infos
een map<str, str>
is met de volgende sleutels:
Mode: ONLY-LEES
titel
beschrijving
avatar: the profile picture
Een account opnieuw importeren (link/export)
Het archief MUST conversationId bevatten om gesprekken op nieuwe commits na een opnieuw-import te kunnen ophalen (omdat er op dit moment geen uitnodiging is).
Het gesprek is er, in dit geval kan de demon dit gesprek opnieuw klonen.
De conversatieId is ontbrekend, dus de daemon vraagt (via een bericht
{{"toepassing/uitnodiging", conversatieId}}
) een nieuwe uitnodiging die de gebruiker moet (her) accepteren
Belangrijk
A conversation can only be retrieved if a contact or another device is there, else it will be lost. There is no magic.
Gebruikte protocollen
Git
Waarom deze keuze
Each conversation will be a Git repository. This choice is motivated by:
We moeten berichten synchroniseren en bestellen. De Merkle Tree is de perfecte structuur om dat te doen en kan worden lineair gemaakt door takken te smelten. Bovendien, omdat het massaal wordt gebruikt door Git, is het gemakkelijk om te synchroniseren tussen apparaten.
Uit de natuur verspreid, veel gebruikt, veel backends en pluggable.
Kan commits verifiëren via haakjes en massaal gebruikte crypto
Kan indien nodig worden opgeslagen in een database
Conflicten worden vermeden door gebruik te maken van commit-berichten, niet van bestanden.
Wat we moeten bevestigen
Performance?
git.lock
kan laag zijnHooks in libgit2
Meerdere trekkingen tegelijk?
Beperkingen
Om een gesprek te verwijderen, moet het apparaat het gesprek verlaten en een ander gesprek maken.
Niet-permanente berichten (zoals berichten die slechts enkele minuten kunnen worden gelezen) kunnen echter via een speciaal bericht via de DRT (zoals meldingen voor typen of lezen) worden verzonden.
Structuur
/
- 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
File overdracht
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.
Protocol
De afzender voegt een nieuwe commit toe in het gesprek met het volgende formaat:
value["tid"] = "RANDOMID";
value["displayName"] = "DISPLAYNAME";
value["totalSize"] = "SIZE OF THE FILE";
value["sha3sum"] = "SHA3SUM OF THE FILE";
value["type"] = "application/data-transfer+json";
en creëert een link in ${data_path}/conversation_data/${conversation_id}/${file_id}
waar file_id=${commitid}_${value["tid"]}.${extension}
De ontvanger kan de bestanden dan nu downloaden door contact op te nemen met de apparaten die het bestand hosten door een kanaal te openen met name="data-transfer://" + conversationId + "/" + currentDeviceId() + "/" + fileId
en de informatie opslaan dat het bestand wacht in ${data_path}/conversation_data/${conversation_id}/waiting
Het apparaat dat de verbinding ontvangt, accepteert het kanaal door te controleren of het bestand kan worden verzonden (als sha3sum correct is en als het bestand bestaat). De ontvanger houdt het eerste geopende kanaal, sluit de anderen en schrijft in een bestand (met hetzelfde pad als de afzender: ${data_path}/conversation_data/${conversation_id}/${file_id}
) alle inkomende gegevens.
Wanneer de overdracht is voltooid of het kanaal gesloten, wordt de sha3sum geverifieerd om te bevestigen dat het bestand correct is (of het is verwijderd).
In geval van falen, wanneer een apparaat van het gesprek weer online is, vragen we alle wachtbestanden op dezelfde manier.
Call in Swarm
Idee
A swarm conversation can have multiple rendez-vous. A rendez-vous is defined by the following URI:
“accountUri/deviceId/conversationId/confId” waar accountUri/deviceId de host beschrijft.
De gastheer kan op twee manieren worden bepaald:
In the swarm metadatas. Where it’s stored like the title/desc/avatar (profile picture) of the room
Of de eerste beller.
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)
Elke deel zal de informatie ontvangen dat een oproep is gestart en kan zich erbij aansluiten door het op te roepen.
Aanvallen?
Avoid Git bombs
Notities
De tijdstempel van een commit is betrouwbaar omdat het bewerkbaar is. Alleen de tijdstempel van de gebruiker kan worden vertrouwd.
TLS
Git-operaties, controlberichten, bestanden en andere dingen gebruiken een p2p TLS v1.3-link met alleen ciphers die PFS garanderen.
DHT (UDP)
Gebruikt om berichten te sturen voor mobiele telefoons (om push-meldingen te laten starten) en TCP-verbindingen te starten.
Netwerkactiviteit
Proces om iemand uit te nodigen
Alice wil Bob uitnodigen:
Alice voegt Bob toe aan een gesprek
Alice generates an invite: { “application/invite+json” : { “conversationId”: “$id”, “members”: [{…}] }}
Twee mogelijkheden voor het verzenden van de boodschap a. Als niet verbonden, via de DHT b. Anders, Alice stuurt op het SIP-kanaal
Twee mogelijkheden voor Bob a. Ontvangt de uitnodiging, wordt een signaal uitgezonden voor de cliënt b. Niet verbonden, dus zal nooit het verzoek ontvangen omdat Alice niet moet weten of Bob gewoon genegeerd of geblokkeerd Alice. De enige manier is om een nieuwe uitnodiging te regenereren via een nieuw bericht (zie volgende scenario)
Proces om een bericht naar iemand te sturen
Alice wil een boodschap naar Bob sturen:
Alice voegt een bericht toe in de repo, geeft een ID
Alice krijgt een bericht ontvangen (van zichzelf) als succesvol
In beide gevallen wordt een bericht gemaakt: { “applicatie/im-gitmessage-id” : “{“id”:”\(convId", "commit":"\)commitId”, “deviceId”: “$alice_device_hash”}”}. a. Als het niet is aangesloten, via de DHT b. Anders stuurt Alice op het SIP-kanaal
Bob heeft vier mogelijkheden: a. Bob is niet verbonden met Alice, dus als hij Alice vertrouwt, vraag dan een nieuwe verbinding en ga naar b. b. Als hij verbonden is, haal dan van Alice en kondig nieuwe berichten aan c. Bob kent dat gesprek niet. Vraag via de DHT om eerst een uitnodiging te krijgen om dat gesprek te kunnen accepteren ({“toepassing/invite”, conversatieId}) d. Bob is afgesloten (geen netwerk, of gewoon gesloten). Hij zal het nieuwe bericht niet ontvangen, maar zal proberen te synchroniseren wanneer de volgende verbinding zal plaatsvinden
Uitvoering
[Diagram: swarm chat-classes]
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"
}
Oproepen
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"
}
!! OUD DRAFT!!
Notitie
Following notes are not organized yet. Just some line of thoughts.
Crypto verbeteringen.
Voor een serieuze groepshatsfunctie hebben we ook serieuze crypto nodig. Met het huidige ontwerp, als een certificaat wordt gestolen als de vorige DHT-waarden van een gesprek, kan het gesprek worden gedecodeerd. Misschien moeten we naar iets als Double Ratchet gaan.
Notitie
A lib might exist to implement group conversations.
Voor de opstelling van een ECC-ondersteuning in OpenDHT
Gebruik
Rol toevoegen?
Er zijn twee belangrijke gebruiksgevallen voor groepschatten:
Iets als een Mattermost in een bedrijf, met privé-kanalen, en sommige rollen (admin/spectator/bot/etc) of voor onderwijs (waar slechts een paar actief zijn).
Horizontale gesprekken zijn als een gesprek tussen vrienden.
Jami will be for which one?
Uitvoeringsidee
Een certificaat voor een groep die gebruikers met een vlag voor een rol ondertekent.
Neem deel aan een gesprek
Alleen via een directe uitnodiging
Via een link/QR-code/wat dan ook
Via een kamernaam?
Wat we nodig hebben
Geheime informatie: leden buiten de groepsklets mogen geen berichten in de groep lezen
Geheimheid: indien een sleutel van de groep wordt gecompromitteerd, moeten eerdere berichten vertrouwelijk blijven (zo veel mogelijk)
Boodschappenorderen: Boodschappen moeten in de juiste volgorde zijn
Synchronisatie: Er is ook een noodzaak om ervoor te zorgen dat alle berichten zo snel mogelijk beschikbaar zijn.
De tijdsduur van een bericht op de DHT is slechts 10 minuten. Omdat het de beste tijdsduur is die is berekend voor dit soort DHT. Om gegevens te behouden, moet de knoop de waarde van de DHT elke 10 minuten opnieuw zetten. Een andere manier om te doen wanneer de knoop offline is, is om knooppunten de gegevens opnieuw te laten zetten. Maar als na 10 minuten, 8 knooppunten nog steeds hier zijn, zullen ze 64 verzoeken doen (en het is exponentieel). De huidige manier om spam te voorkomen daarvoor wordt gevraagd. Dit zal nog steeds 64 verzoeken doen, maar beperkt de maximale redundantie tot 8 knooppunten.
Andere verdeelde wegen
IPFS: Ik heb onderzoek nodig.
Ik heb onderzoek nodig.
Ik heb onderzoek nodig.
Op basis van het huidige werk dat we hebben
Groepchat kan gebaseerd zijn op hetzelfde werk dat we al hebben voor multi-apparaten (maar hier, met een groepscertificaat).
Hiermee moet de database van de client naar de daemon worden verplaatst.
Als niemand is aangesloten, kan de synchronisatie niet worden gedaan, en de persoon zal het gesprek nooit zien
Een andere DHT-afdeling
Net als een DHT met een supergebruiker.
What’s next for file transfers
Currently, the file transfer algorithm is based on a TURN connection (See File overdracht). 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)