Skarmo
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.
Neniu centra aŭtoritato.
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.
La ĉefa ideo estas akiri sinkronigitan Merkle-arbon kun la partoprenantoj.
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).
Scenarioj
Kreu amason
Bob volas krei novan sorbon
Bob creates a local Git repository.
Poste, li kreas komencan subskribitan engaĝiĝon kun la sekva:
Lia publika ŝlosilo en
/admins
Lia aparato atestilo en ̀ /aparatoj `
Lia CRL en ̀ /crls`
La haŝaĵo de la unua komisio iĝas la ID de la konversacio
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.
Aldoni iun
Bob adds Alice
Bob adds Alice to the repo:
Aldonas la invititan URI en
/invited
Aldonas la CRL al
/crls
Bob sends a request on the DHT.
Ricevi inviton
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.
Sendante mesaĝon
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).
Note
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.
Ricevi mesaĝon
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.
Valido de engaĝiĝo
Por eviti uzantojn puŝantajn kelkajn nedeziratajn kompromisojn (kun konfliktoj, falsaj mesaĝoj, ktp.), ĉi tiel ĉiu kompromiso (de la plej malnova ĝis la plej nova) MUS esti validita antaŭ kunfandi malproksiman branĉon:
Note
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.
Malpermesu aparaton
Important
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.
Similaj sistemoj (kun distribuitaj grupsistemoj) ne estas tiom multaj, sed ĉi tiuj estas kelkaj ekzemploj:
[mpOTR ne difinas kiel malpermesi iun]
Signalo, sen iu centra servilo por grupĉatado (EDIT: ili ĵus ŝanĝis tiun punkton), ne donas la kapablon malpermesi iun el grupo.
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).
Forigu aparaton el konversacio
Jen la nura parto, en kiu oni devas konsenti, por eviti la disigon de la konversacio, kiel se du membroj elpuŝas unu la alian el la konversacio, kio okazos al la tria?
Tio estas necesa por detekti revokitajn aparatojn, aŭ simple eviti havi nedeziratajn homojn ĉeestantajn en publika ĉambro. La procezo estas tre simila inter membro kaj aparato:
Alice forigas Bobon
Important
Alice MUST be an admin to vote.
Unue, ŝi voĉdonas por malpermeso de Bob. Por fari tion, ŝi kreas la dosieron en /votes/ban/members/uri_bob/uri_alice (membroj povas esti anstataŭigitaj per aparatoj por aparato, aŭ invititaj por invitoj aŭ administrantoj por administrantoj) kaj engaĝas
Poste ŝi kontrolas, ĉu la voĉdono estas solvita. Tio signifas, ke > 50% de la administrantoj konsentas malpermesi Bobon (se ŝi estas sola, certe ĝi estas pli ol 50%).
Se la voĉdono estas solvita, dosieroj en /votes/ban povas esti forigitaj, ĉiuj dosieroj por Bob en /membroj, /admins, /invited, /CRLs, /aparatoj povas esti forigitaj (aŭ nur en /aparatoj se ĝi estas aparato kiu estas malpermesita) kaj la atesto de Bob povas esti metita en /banned/members/bob_uri.crt (aŭ /banned/devices/uri.crt se aparato estas malpermesita) kaj dediĉita al la repo
Poste, Alice informas aliajn uzantojn (ekstere de 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
Poste ŝi kontrolas, ĉu la voĉdono estas solvita. Tio signifas, ke > 50% de la administrantoj konsentas malpermesi Bobon (se ŝi estas sola, certe ĝi estas pli ol 50%).
Se la voĉdono estas solvita, dosieroj en /votes/unban povas esti forigita, ĉiuj dosieroj por Bob en /membroj, /admins, /invited, /CRLs, povas esti re- aldonita (aŭ nur en /aparatoj se ĝi estas aparato kiu estas sen malpermeso) kaj dediĉita al la repo
Forigu konversacion
Savu en convInfos removed=time::now() (kiel removeKontakto savas en kontaktoj) ke la konversacio estas forigita kaj sinkronigita kun aliaj uzanto aparatoj
Se nova mesaĝo estas ricevita por tiu ĉi konversacio, ĝi estas ignorata.
Se Jamie ankoraŭ startigas la negocon, la klientoj ne ricevos la mesaĝon.
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.
Kiam ni estas certa ke iu estas sinkronigita, forigu forviŝita=tempo::now() kaj sinkronigu kun la aparatoj de aliaj uzantoj
Ĉiuj aparatoj posedataj de la uzanto nun povas forviŝi la repository kaj rilataj dosieroj
Kiel precizi reĝimon
La modoj ne povas esti ŝanĝitaj tra la tempo. Aŭ ĝi estas alia konversacio. Do, ĉi tiuj datumoj estas stokitaj en la komenca komenta mesaĝo.
{
"type": "initial",
"mode": 0,
}
Por nun, “modo” akceptas valorojn 0 (ONE_TO_ONE), 1 (ADMIN_INVITES_ONLY), 2 (INVITES_ONLY), 3 (Publiko)
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:
La procezo estas ankoraŭ la sama, konto povas aldoni kontakton per addContact, tiam sendi TrustRequest per la DHT. Sed du ŝanĝoj estas necesaj:
La TrustRequest enmetas “konversacioId” por informi la kunulo kiu konversacio kloni kiam akceptante la peton
TrustRequest estas retrovita kiam kontakto revenas rete. Tio ne estas la kazo hodiaŭ (kiel ni ne volas generi novan TrustRequest se la egalulo forĵetas la unuan). Do, se konto ricevas fidon peton, ĝi estos aŭtomate ignorita se la peto kun rilata konversacio estas malakceptita (kiel convRequests estas sinkronigita)
Tiam, kiam kontakto akceptas la peton, estas necesa periodo de sinkronigo, ĉar la kontakto nun bezonas kloni la konversacion.
removeContact() forigos la kontakton kaj rilatajn 1:1 konversaciojn (kun la sama procezo kiel “Forigi konversacion”). La sola noto ĉi tie estas ke se ni malpermesas kontakton, ni ne atendas sinkronizon, ni simple forigas ĉiujn rilatajn dosierojn.
Trifaj scenaroj
Ekzistas kelkaj kazoj, kie eblas krei du konversaciojn.
Alice adds Bob.
Bob accepts.
Alice removes Bob.
Alice adds Bob.
aŭ
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)).
Important
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() redonos {{“similado”: “vera”}} se sinkronigado.
ConfigurationManager::getConversationMembers() will return a map of two URIs (the current account and the peer who sent the request).
Konversacioj petas specifojn
La petoj por konversacioj estas reprezentitaj per Mapo<String, String> kun la sekvaj ŝlosiloj:
id: the conversation ID
from: URI of the sender
ricevita: tempostampo
titolo: (favora) nomo por la konversacio
priskribo: (favora)
avatar: (optional) the profile picture
La konversacia sinkronizado de la profilo
Por esti identigebla, konversacio ĝenerale bezonas kelkajn metadatumojn, kiel titolo (ekz: Jami), priskribo (ekz: kelkaj ligiloj, kio estas la projekto, ktp), kaj bildo (la emblemo de la projekto). Tiuj metadatenoj estas laŭvolaj sed dividitaj inter ĉiuj membroj, do necesas sinkronigi kaj integri en la petoj.
La stokado en la deponejo
La profilo de la konversacio estas stokita en klasika vCard dosiero ĉe la radiko (/profile.vcf
) kiel:
BEGIN:VCARD
VERSION:2.1
FN:TITLE
DESCRIPTION:DESC
END:VCARD
Sinkronigo
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).
La lasta montrita
En la sinkronigitaj datumoj, ĉiu aparato sendas al aliaj aparatoj la staton de la konversacioj. En tiu stato, la lasta montrita estas sendita. Tamen, ĉar ĉiu aparato povas havi sian propran staton por ĉiu konversacio, kaj verŝajne sen la sama lasta engaĝiĝo en iu punkto, ekzistas pluraj scenaroj por konsideri:
Estas 5 scenaroj subtenataj:
se la lasta montrita de aliaj aparatoj estas la sama kiel la nuna, estas nenio farenda.
se ne estas lasta montrita por la aktuala aparato, la malproksima montrita mesaĝo estas uzata.
se la malproksima lasta montrita ne estas ĉeestanta en la repo, ĝi signifas ke la komiti estos alportita poste, do kaŝu la rezulton
se la malproksima estas jam prenita, ni kontrolu ke la loka lasta montrita estas antaŭ en la historio por anstataŭigi ĝin
Finfine, se mesaĝo estas sciigita de la sama aŭtoro, ĝi signifas ke ni devas ĝisdatigi la lastaj montritaj.
Preferencoj
Ĉiu konversacio havas aldonitajn preferojn fiksitajn de la uzanto. Tiuj preferoj sinkronigas tra la aparatoj de la uzanto. Tio povas esti la koloro de la konversacio, se la uzanto volas ignori mesaĝojn, dosiertransferan grandeclimon, ktp.
“color” - the color of the conversation (#RRGGBB format)
“ignoreNotifications” - ignori novajn mesaĝojn en ĉi tiu konversacio
“simbolio” - por difini defaŭltan emozion.
Tiuj preferoj estas stokitaj en paketo MapStringString, stokitaj en accountDir/conversation_data/conversationId/preferences
kaj nur senditaj tra la aparatoj de la sama uzanto per SyncMsg.
La API por interagi kun la preferoj estas:
// 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*/);
};
Kunfandkonflikto-administrado
Ĉar du administrantoj povas ŝanĝi la priskribon samtempe, kunfandi konflikton povas okazi sur profile.vcf
. En tiu kazo, la kunigo kun la pli alta hash (ekz. ffffff > 000000) estos elektita.
APIoj
La uzanto ricevis 2 metodojn por akiri kaj agordi la konversaciajn metadatumojn:
<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>
kie infos
estas map<str, str>
kun la sekvaj ŝlosiloj:
Modulo: Nur por legado
Titolo
priskribo
avatar: the profile picture
Reimportas konton (ligas/eksportas)
La arkivo MUS enhavi konversacioId por povi reakiri konversaciojn sur novaj komentoj post re-importado (ĉar ekzistas neniu invito en tiu punkto). Se komento venas por konversacio ne ĉeestas ekzistas du ebloj:
La konversacio estas tie, en ĉi tiu kazo, la demono povas re-kloni tiun konversacion
La konversacioId mankas, do la demono petas (per mesaĝo
{{"apliko/invito", konversacioId}}
) novan inviton, kiun la uzanto devas (re) akcepti
Important
A conversation can only be retrieved if a contact or another device is there, else it will be lost. There is no magic.
Uzuitaj protokoloj
La ŝtofo
Kial tiu elekto
Each conversation will be a Git repository. This choice is motivated by:
Ni devas sinkronigi kaj ordigi mesaĝojn. Merkle Tree estas la perfekta strukturo por fari tion kaj povas esti liniigita kunfandi branĉojn. Krome, ĉar ĝi estas vaste uzata de Git, estas facile sinkronigi inter aparatoj.
La naturo distribuas ĝin, ĝi estas vaste uzata, multe da retmesaĝoj kaj plumbaĵoj.
povas konfirmi engaĝiĝojn per haketoj kaj amasigita kripto
Ĝi povas esti stokita en datumbazo se necese
Konfliktoj estas evititaj uzante komercajn mesaĝojn, ne dosierojn.
Kion ni devas konfirmi
Performance?
git.lock
povas esti malaltaHaketoj en libgit2
Multaj tiroj samtempe?
Limitoj
Ne eblas forigi historion. Por forigi konversacion, la aparato devas forlasi la konversacion kaj krei alian.
Tamen, ne-permanentaj mesaĝoj (kiel mesaĝoj legeblaj nur dum kelkaj minutoj) povas esti senditaj per speciala mesaĝo per la DRT (kiel Tipado aŭ Legado de sciigoj).
Strukturo
/
- 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
Transdono de dosieroj
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.
Protokolo
La sendanto aldonas novan engaĝiĝon en la konversacio kun la sekva formato:
value["tid"] = "RANDOMID";
value["displayName"] = "DISPLAYNAME";
value["totalSize"] = "SIZE OF THE FILE";
value["sha3sum"] = "SHA3SUM OF THE FILE";
value["type"] = "application/data-transfer+json";
kaj kreas ligon en ${data_path}/conversation_data/${conversation_id}/${file_id}
kie file_id=${commitid}_${value["tempo"]}.${extension}
Tiam, la ricevanto povas nun elŝuti la dosierojn kontaktante la aparatojn gastigantajn la dosieron malfermante kanalon kun name="data-transfer://" + conversationId + "/" + currentDeviceId() + "/" + fileId
kaj stoki la informon ke la dosiero atendas en ${data_path}/conversation_data/${conversation_id}/waiting
La aparato ricevanta la konekton akceptos la kanalon per konfirmo ĉu la dosiero povas esti sendita (se sha3sum estas ĝusta kaj se dosiero ekzistas). La ricevanto konservos la unuan malfermitan kanalon, fermos la aliajn kaj skribos en dosieron (kun la sama vojo kiel la sendanto: ${data_path}/conversation_data/${conversation_id}/${file_id}
) ĉiujn alvenantajn datumojn.
Kiam la translokigo estas finita aŭ la kanalo fermita, la sha3sum estas konfirmita por validi ke la dosiero estas ĝusta (aŭ ĝi estas forigita). Se valida, la dosiero estos forigita de la atendado.
En kazo de fiasko, kiam la aparato de la konversacio estos reen al la reto, ni petos ĉiujn atendajn dosierojn laŭ la sama maniero.
Call in Swarm
Ideo
A swarm conversation can have multiple rendez-vous. A rendez-vous is defined by the following URI:
“kontoUri/aparatoId/konversacioId/konfId” kie kontoUri/aparatoId priskribas la gastiganton.
La gastiginto povas esti determinita per du manieroj:
In the swarm metadatas. Where it’s stored like the title/desc/avatar (profile picture) of the room
Aŭ la komencan vokanton.
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)
Do ĉiu parto ricevos la informon ke alvoko komenciĝis kaj povos aliĝi al ĝi alvokante ĝin.
Ĉu atakoj?
Avoid Git bombs
Notoj
La tempostemplo de engaĝiĝo povas esti fidinda ĉar ĝi estas redaktebla. Nur la tempostemplo de la uzanto povas esti fidinda.
TLS
Git-operacioj, kontrolmesaĝoj, dosieroj, kaj aliaj aĵoj uzos p2p TLS v1.3 ligilon kun nur ciferoj kiuj garantias PFS. Do ĉiu ŝlosilo estas renegociita por ĉiu nova konekto.
DHT (UDP)
Uzu por sendi mesaĝojn por poŝtelefonoj (por ekigi puŝnotifikojn) kaj por komenci TCP-konektojn.
Reto-agado
Procezo por inviti iun
Alice volas inviti Bob:
Alice aldonas Bobon al konversacio
Alice generates an invite: { “application/invite+json” : { “conversationId”: “$id”, “members”: [{…}] }}
Du ebloj por sendi la mesaĝon a. Se ne ligita, per la DHT b. Alie, Alice sendas sur la SIP kanalo
Du ebloj por Bob a. Ricevas la inviton, signalo estas elsendita por la kliento b. Ne konektita, do neniam ricevos la peton ĉar Alice ne devas scii ĉu Bob ĵus ignoris aŭ blokis Alice. La sola maniero estas regeneri novan inviton per nova mesaĝo (vidu sekvan scenaron)
Procezo por sendi mesaĝon al iu
Alice volas sendi mesaĝon al Bob:
Alice aldonas mesaĝon en la repo, donante identecon
Alice ricevas mesaĝon ricevita (de si mem) se sukcesa
Du ebloj, alice kaj bob estas ligitaj, aŭ ne. En ambaŭ kazoj mesaĝo estas kreita: { “apliko/im-gitmessage-id” : “{“id”:”\(convId", "kompromiso":"\)commitId”, “deviceId”: “$alice_device_hash”}”}. a. Se ne ligita, per la DHT b. Aliokaze, Alice sendas sur la SIP-kanalo
Kvar ebloj por Bob: a. Bob ne estas ligita al Alice, do se li fidas al Alice, petu novan ligon kaj iru al b. b. Se ligita, prenu de Alice kaj sciigu novajn mesaĝojn c. Bob ne scias tiun konversacion. Petu tra la DHT por akiri inviton unue por povi akcepti tiun konversacion ({“apliko/invito”, konversacioId}) d. Bob estas malligita (neniu reto, aŭ ĵus fermita). Li ne ricevos la novan mesaĝon sed provos sinkronigi kiam la venonta konekto okazos
Plenumado
! [Diagramo: aro de babilejoj](imagoj/ aro-babilejoj-klasoj-diagramo.jpg)
Supported messages
Initial message
{
"type": "initial",
"mode": 0,
"invited": "URI"
}
Represents the first commit of a repository and contains the mode:
enum class ConversationMode : int { ONE_TO_ONE = 0, ADMIN_INVITES_ONLY, INVITES_ONLY, PUBLIC }
and invited
if mode = 0.
Text message
{
"type": "text/plain",
"body": "content",
"react-to": "id (optional)"
}
Or for an edition:
{
"type": "application/edited-message",
"body": "content",
"edit": "id of the edited commit"
}
Vokoj
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"
}
!! Malnova DRAFT!!
Note
Following notes are not organized yet. Just some line of thoughts.
Kriptaj plibonigoj.
Por serioza grupĉatfunkcio, ni ankaŭ bezonas seriozan kripto. Kun la nuna dezajno, se atesto estas ŝtelita kiel la antaŭaj DHT valoroj de konversacio, la konversacio povas esti malĉifrita. Eble ni devas iri al io kiel ** Duobla ŝarĝo**.
Note
A lib might exist to implement group conversations.
Necesas ECC-subtenon en OpenDHT
Uzo
Ĉu aldoni rolojn?
Ekzistas du gravaj uzokazoj por grupĉatoj:
Io kiel Mattermost en kompanio, kun privataj kanaloj, kaj kelkaj roloj (admin/spektanto/boto/etc) aŭ por edukado (kie nur kelkaj estas aktivaj).
Horizontalaj konversacioj estas kiel konversacio inter amikoj.
Jami will be for which one?
Realigo-ideaĵo
Atestato por grupo kiu subskribas uzanton kun flago por rolo. Aldoni aŭ revoki ankaŭ povas esti farita.
Aliĝu al konversacio
Nur per rekta invito
Per ligo/QR-kodo/kial ajn
Per nom-ĉambro?
Kion ni bezonas
Konfidenca: membroj ekster la grupĉat ne devus povi legi mesaĝojn en la grupo
Sekreteco: se iu ŝlosilo de la grupo estas kompromitita, antaŭaj mesaĝoj devas resti konfidencaj (kiel eble plej multe)
Mesaĝordado: Estas bezono havi mesaĝojn en la ĝusta ordo
Sinkronigo: Estas ankaŭ bezono certigi havi ĉiujn mesaĝojn kiel eble plej baldaŭ.
Persisto: Fakte mesaĝo sur la DHT vivas nur 10 minutojn. Ĉar ĝi estas la plej bona tempokalkulo por tiu speco de DHT. Por persisti datumojn, la nodo devas reinstigi la valoron sur la DHT ĉiujn 10 minutojn. Alia maniero fari kiam la nodo estas forigita estas lasi nodojn reinstigi la datumojn. Sed, se post 10 minutoj, 8 nodoj daŭre estas ĉi tie, ili faros 64 petojn (kaj ĝi estas eksponenca). La nuna maniero eviti spamon por tio estas demandita. Tio daŭre faros 64 petojn sed limigos la maksimuman redundancon al 8 nodoj.
Aliaj distribuitaj manieroj
IPFS: Necesas iom da esplorado
Mi bezonas esploradon.
Mi bezonas esploron.
Surbaze de la nuna laboro ni havas
Grupĉatado povas esti bazita sur la sama laboro, kiun ni jam havas por pluraparatoj (sed ĉi tie, kun grupatesto).
Simkronigu historion. Tio devas movi la datumbazon de la kliento en la demonon.
Se neniu estas konektita, la sinkronigo ne povas esti farita, kaj la persono neniam vidos la konversacion
Alia dediĉita DHT
Kiel DHT kun superuzanto.
What’s next for file transfers
Currently, the file transfer algorithm is based on a TURN connection (See Transdono de dosieroj). 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)