گروه

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. هيچ مقام مركزي وجود نداره، نمي تونم به هيچ سروري اعتماد کنم

  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.

ایده اصلی اینه که یک درخت مرکل هم وقت ساز با شرکت کنندگان داشته باشیم.

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

سناریوهای

یک گروه را ایجاد کنید

بوب ميخواد يه دسته جديد بسازد

  1. Bob creates a local Git repository.

  2. بعد، او یک تعهد اولیه امضا می کند که شامل موارد زیر است:

    • کلید عمومی اش در /admins

    • گواهی دستگاهش در ̀ / دستگاه `

    • CRLش در ̀ /crls`

  3. هشتگ اولي که انجام ميده، به اسم "ID" صحبت مي کنه

  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.

اضافه کردن کسی

Bob adds Alice

  1. Bob adds Alice to the repo:

    • اضافه کردن URI دعوت شده به /invited

    • اضافه کردن CRL به /crls

  2. Bob sends a request on the DHT.

دعوت گرفتن

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.

ارسال پيام

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

توجه

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.

دریافت یک پیام

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.

اعتبارگذاری تعهد

برای جلوگیری از اینکه کاربران برخی از تعهدات ناخواسته را (با تعارضات، پیام های غلط و غیره) فشار دهند، این گونه هر تعهد (از قدیمی ترین تا جدیدترین) باید قبل از ادغام شاخه های دور از خود تأیید شود:

توجه

  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.

دستگاه رو ممنوع کن

مهم

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.

سیستم های مشابه (با سیستم های گروه توزیع شده) زیاد نیستند، اما اینها چند مثال هستند:

  • [mpOTR نمی داند چگونه به شخص ممنوعیت]

  • سیگنال، بدون هیچ سرور مرکزی برای چت گروهی (EDIT: اخیراً این نکته را تغییر داده اند) ، توانایی ممنوعیت کسی از یک گروه را نمی دهد.

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

دستگاهی را از مکالمه حذف کنید

اين تنها بخشيه که بايد توافق داشته باشيم تا از تفرقه ي مکالمه اجتناب کنيم مثل اين که اگر دو عضو از مکالمه همديگه رو رد کنن، چه چيزي به سومين نفر مياد؟

این برای تشخیص دستگاه های منسوخ شده یا به سادگی جلوگیری از حضور افراد ناخواسته در یک اتاق عمومی مورد نیاز است. این فرآیند بین یک عضو و یک دستگاه بسیار مشابه است:

"آليس" باب رو از دست داد

مهم

Alice MUST be an admin to vote.

  • اول، او برای ممنوعیت باب رای می دهد. برای انجام این کار، او فایل را در /votes/ban/members/uri_bob/uri_alice ایجاد می کند (متعلمان می توانند با دستگاه های یک دستگاه جایگزین شوند، یا برای دعوت ها یا مدیران برای مدیران دعوت شوند) و تعهدات را انجام می دهد

  • بعد او بررسی می کند که آیا رای گیری حل شده است. این بدان معنی است که >50٪ از مدیران موافق به ممنوعیت باب هستند (اگر او تنها باشد، مطمئناً بیش از 50٪ است).

  • اگر رای گیری حل شود، فایل های داخل /votes/ban می توانند حذف شوند، تمام فایل های برای باب در /members، /admins، /invited، /CRLs، /devices می توانند حذف شوند (یا فقط در /devices اگر دستگاهی است که ممنوع است) و گواهی باب می تواند در /banned/members/bob_uri.crt (یا /banned/devices/uri.crt اگر دستگاهی ممنوع است) قرار داده شود و به repo اختصاص داده شود

  • بعد، آلیس کاربران دیگر را (به جز باب) اطلاع می دهد

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

  • بعد او بررسی می کند که آیا رای گیری حل شده است. این بدان معنی است که >50٪ از مدیران موافق به ممنوعیت باب هستند (اگر او تنها باشد، مطمئناً بیش از 50٪ است).

  • اگر رای گیری حل شود، فایل های داخل /votes/unban می توانند حذف شوند، تمام فایل های برای Bob در /members، /admins، /invited، /CRLs، می توانند دوباره اضافه شوند (یا فقط در /devices اگر دستگاهی است که ممنوع است) و به repo اختصاص داده می شود

مکالمه رو حذف کن

  1. ذخیره کردن در convInfos removed=time::now() (مانند حذفContact در تماس ها ذخیره می کند) که مکالمه حذف شده و با دستگاه های کاربر دیگر همگام است

  2. حالا اگه يه پيام جديد براي اين مکالمه به دست مياد اون نادیده گرفته ميشه

  3. حالا، اگه جامي شروع کرده و بازي بازي هنوز موجود باشه، اين مکالمه به مشتريان اعلام نمي شه

  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. وقتی مطمئن هستیم که کسی هم وقت سازی شده است، حذف حذف شده=زمان::حالا() و هم وقت سازی با دستگاه های کاربر دیگر

  6. تمام دستگاه های متعلق به کاربر اکنون می توانند مخزن و فایل های مرتبط را پاک کنند

نحوه مشخص کردن حالت

در زمان نمی توان حالت را تغییر داد. یا این یک مکالمه دیگر است. بنابراین، این داده ها در پیام شروعاتی ذخیره می شوند. پیام شروعاتی به انجام این کار خواهد بود:

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

در حال حاضر، "موډ" مقادیر 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:

فرآیند هنوز همان است، یک حساب می تواند یک تماس را از طریق addContact اضافه کند، سپس یک درخواست اعتماد را از طریق DHT ارسال کند. اما دو تغییر ضروری است:

  1. TrustRequest یک "گوششId" را برای اطلاع دادن به همسال که چه مکالمه ای را برای کلان کردن در هنگام پذیرش درخواست

  2. TrustRequest زمانی که تماس به اینترنت باز می گردد دوباره آزمایش می شود. این امروز مورد نیست (چون ما نمی خواهیم یک TrustRequest جدید ایجاد کنیم اگر همتایان اولین مورد را رد کنند). بنابراین، اگر یک حساب درخواست اعتماد را دریافت کند، اگر درخواست با یک مکالمه مرتبط رد شود، به طور خودکار نادیده گرفته می شود (چون convRequests هم وقت ساز می شود)

سپس، وقتی یک تماس درخواست را قبول می کند، یک دوره همگام سازی لازم است، زیرا تماس اکنون نیاز به کلون مکالمه دارد.

حذف کنتاکت (Contact) تماس و مکالمات مربوطه 1:1 را حذف می کند (با همان فرآیند "کابراتوار را حذف کنید"). تنها نکته اینجا این است که اگر یک تماس را ممنوع کنیم، منتظر همگام سازی نیستیم، فقط تمام فایل های مرتبط را حذف می کنیم.

سناریوهای پیچیده

در بعضی موارد می توان دو مکالمه ایجاد کرد. این حداقل دو مورد از این سناریو ها است:

  1. Alice adds Bob.

  2. Bob accepts.

  3. Alice removes Bob.

  4. Alice adds Bob.

یا

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

مهم

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() اگر هم وقت سازی شود {{"موافق سازی": "واقعی"}} را بازمی گرداند.

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

گفتگوها درخواست مشخصه

درخواست های مکالمه با Map<String, String> با کلید های زیر نمایش داده می شوند:

  • id: the conversation ID

  • from: URI of the sender

  • دریافت: زمان

  • عنوان: (اختيار) نام مکالمه

  • توضیحات: (اختیاری)

  • آواتار: (اختیاری)

همگام سازی پروفایل مکالمه

برای شناسایی، مکالمه به طور کلی به برخی از متاداتا نیاز دارد، مانند عنوان (به عنوان مثال: Jami) ، توصیف (به عنوان مثال: برخی از لینک ها، پروژه چیست و غیره) و یک تصویر (لوگو پروژه). این متاداتا اختیاری است اما در میان همه اعضای به اشتراک گذاشته می شود، بنابراین باید هماهنگ و در درخواست ها گنجانده شود.

ذخیره سازی در مخزن

پروفایل مکالمه در یک فایل vCard کلاسیک در ریشه (/profile.vcf) ذخیره می شود مانند:

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

هم زمان سازی

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

آخرین نمایش

در داده های همگام سازی، هر دستگاه به دستگاه های دیگر وضعیت مکالمه را ارسال می کند. در این حالت، آخرین نمایش داده شده ارسال می شود. با این حال، از آنجا که هر دستگاه می تواند برای هر مکالمه وضعیت خاص خود را داشته باشد و احتمالا بدون همان تعهد آخر در برخی موارد، چندین سناریو وجود دارد که باید در نظر گرفته شود:

5 سناریو پشتیبانی می شود:

  • اگر آخرین نمایش داده شده توسط دستگاه های دیگر مشابه دستگاه فعلی باشد، کاری نیست.

  • اگر آخرین نمایش برای دستگاه فعلی وجود نداشته باشد، پیام نمایش در راه دور استفاده می شود.

  • اگر آخرین راه دور نمایش داده شده در repo وجود ندارد، این بدان معنی است که کمیت بعداً به دست می آید، بنابراین نتیجه را ذخیره کنید

  • اگر راه دور قبلاً به دست آمده باشد، ما بررسی می کنیم که آخرین نمایش محلی قبل از تاریخچه است تا جایگزین آن شود

  • در نهایت اگر یک پیام از همان نویسنده اعلام شود، این بدان معنی است که ما باید آخرین پیام نمایش داده شده را به روز کنیم.

اولویت ها

هر مکالمه دارای اولویت هایی است که توسط کاربر تنظیم شده است. این اولویت ها در سراسر دستگاه های کاربر همگام سازی می شوند. این می تواند رنگ مکالمه باشد، اگر کاربر می خواهد به اطلاعیه ها، محدودیت اندازه انتقال فایل ها و غیره نادیده بگیرد. برای حال، کلید های شناخته شده عبارتند از:

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

  • "ignoreNotifications" - برای نادیده گرفتن اطلاعیه های پیام های جدید در این مکالمه

  • "سمبول" - برای تعریف یک اموجی پیش فرض.

این اولویت ها در یک بسته MapStringString ذخیره می شوند، در `accountDir/conversation_data/conversationId/preferences]] ذخیره می شوند و تنها از طریق SyncMsg از طریق دستگاه های همان کاربر ارسال می شوند.

API برای تعامل با اولویت ها عبارتند از:

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

مدیریت درگیری های ادغام

از آنجا که دو مدیر می توانند توصیف را همزمان تغییر دهند، می تواند در profile.vcf یک تضاد ادغام ایجاد شود. در این صورت، commit با hash بالاتر (به عنوان مثال ffffff > 000000) انتخاب می شود.

API ها

کاربر دو روش برای بدست آوردن و تنظیم متادتا مکالمه را دارد:

       <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 یک map<str, str> با کلید های زیر است:

  • حالت: فقط برای خواندن

  • عنوان

  • توضیحات

  • اوتار

پروتکل های مورد استفاده

گیت

چرا اين انتخاب

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

  1. ما باید پیام ها را همگام سازی کنیم و ترتیب دهیم. درخت مرکل ساختار عالی برای انجام این کار است و می تواند با ادغام شاخه ها خطی شود. علاوه بر این، از آنجا که توسط Git به طور گسترده ای استفاده می شود، همگام سازی بین دستگاه ها آسان است.

  2. از طرف طبیعت پخش شده، به طور گسترده ای استفاده شده، پشت سرانه های زیادی و قابل وصل.

  3. می تواند از طریق هک ها و رمزنگاری های گسترده ای که استفاده می شود، تعهدات را تأیید کند

  4. در صورت لزوم می تواند در یک پایگاه داده ذخیره شود

  5. از طریق استفاده از پیام های متعهد، نه فایل ها از تعارض جلوگیری می شود.

آنچه که باید تایید کنیم

  • عملکرد؟ git.lock می تواند کم باشد

  • هک ها در libgit2

  • چند تا کشش همزمان؟

محدودیت ها

برای حذف مکالمه، دستگاه باید مکالمه را ترک کند و مکالمه دیگری ایجاد کند.

با این حال، پیام های غیر دائمی (مانند پیام هایی که فقط برای چند دقیقه قابل خواندن هستند) می توانند از طریق یک پیام ویژه از طریق DRT (مانند اطلاعیه تایپ یا خواندن) ارسال شوند.

ساختار

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

انتقال فایل

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.

پروتکل

فرستنده یک تعهد جدید را در مکالمه با فرمت زیر اضافه می کند:

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

و یک لینک را در ${data_path}/conversation_data/${conversation_id}/${file_id} ایجاد می کند که file_id=${commitid}_${value["tid"]}.${extension}

سپس، گیرنده می تواند اکنون فایل ها را با تماس با دستگاه های میزبان فایل با باز کردن کانال با name="data-transfer://" + conversationId + "/" + currentDeviceId() + "/" + fileId دانلود کند و اطلاعات را که فایل در انتظار است در ${data_path}/conversation_data/${conversation_id}/waiting ذخیره کند

دستگاه دریافت کننده اتصال کانال را با تأیید اینکه آیا می توان فایل را ارسال کرد (اگر sha3sum درست است و اگر فایل وجود دارد) پذیرفته می شود. گیرنده اولین کانال باز شده را نگه می دارد، بقیه را می کند و در یک فایل می نویسد (با همان مسیر فرستنده: ${data_path}/conversation_data/${conversation_id}/${file_id}) تمام داده های وارد شده.

وقتی انتقال به پایان رسیده یا کانال بسته شده است، sha3sum برای تأیید اینکه فایل درست است (یا حذف شده است) تأیید می شود. اگر معتبر باشد، فایل از انتظار حذف می شود.

در صورت شکست، وقتی دستگاه مکالمه دوباره به کار می رود، از همه فایل های منتظر به همان روش درخواست می کنیم.

Call in Swarm

ایده

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

"accountUri/deviceId/conversationId/confId" جایی که accountUri/deviceId میزبان را توصیف می کند.

میزبان را می توان از طریق دو روش مشخص کرد:

  • در ميتا اطلاعات سوره اي که مثل عنوان / ميز / اوتار اتاق ذخیره شده

  • یا اولین تماس گیرنده

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)

بنابراین هر بخش اطلاعات را دریافت می کند که تماس شروع شده است و می تواند با تماس با آن به آن پیوسته شود.

حمله؟

  • Avoid Git bombs

یادداشت ها

زمان بندی یک کامیت قابل اعتماد است چون قابل ویرایش است. تنها زمان بندی کاربر قابل اعتماد است.

TLS

عملیات Git، پیام های کنترل، فایل ها و چیزهای دیگر از یک پی 2 پی TLS v1.3 لینک با فقط رمزگذاری که تضمین PFS استفاده می کنند. بنابراین هر کلید برای هر اتصال جدید تجدید نظر می شود.

DHT (UDP)

برای ارسال پیام ها برای تلفن همراه (برای تگ کردن اطلاعیه های پش) و برای شروع اتصال های TCP استفاده می شود.

فعالیت شبکه

پروسه دعوت کردن کسی

آليس مي خواد باب رو دعوت کنه:

  1. آليس باب رو به مکالمه مي افزايد

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

  3. دو امکان برای ارسال پیام a. اگر متصل نباشد، از طریق DHT b. در غیر این صورت، آلیس از طریق کانال SIP ارسال می کند

  4. دو امکان برای باب a. دعوت دریافت می کند، سیگنال برای مشتری b. متصل نیست، بنابراین هرگز درخواست را دریافت نخواهد کرد زیرا آلیس نباید بداند که آیا باب آلیس را نادیده گرفته یا مسدود کرده است. تنها راه بازسازی دعوت جدید از طریق یک پیام جدید است (بخش به سناریو بعدی)

پروسه ارسال پيام به کسي

آليس مي خواد پيامي به باب بفرستد

  1. آليس يه پيام اضافه ميکنه توي بازپرداخت، يه شناسايي ميده

  2. آليس پيامي ميگيره (از خودش) اگر موفق بشه

  3. دو احتمال، آلیس و باب متصل هستند یا نه. در هر دو مورد یک پیام ایجاد می شود: { "برنامه / im-gitmessage-id" : "{"id":"\(convId"، "commit":"\)commitId"، "deviceId": "$alice_device_hash"}"}.

  4. چهار امکان برای باب: a. باب با آلیس متصل نیست، بنابراین اگر به آلیس اعتماد کند، از یک اتصال جدید بخواهید و به b. b بروید. اگر متصل باشد، از آلیس بخواهید و پیام های جدیدی را اعلام کنید c. باب این مکالمه را نمی داند. از طریق DHT بخواهید تا ابتدا دعوت نامه دریافت کنید تا بتوانید این مکالمه را بپذیرید ({"تطبيق/دعوت"، مکالمهId}) d. باب قطع شده است (هیچ شبکه ای، یا فقط بسته شده است). او پیام جدید را دریافت نخواهد کرد اما سعی خواهد کرد هنگام اتصال بعدی همگام سازی کند

اجرای

! [ نمودار: کلاس های چت سوار ]

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

تماس‌ها

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

!! مسودات قدیمی!!

توجه

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

بهبودي در رمزنگاري

برای یک ویژگی چت گروهی جدی، ما همچنین به رمزنگاری جدی نیاز داریم. با طراحی فعلی، اگر گواهی به عنوان ارزش های DHT قبلی یک مکالمه دزدیده شود، مکالمه می تواند رمزگذاری شود. شاید ما باید به چیزی مانند ** دوگانه ratchet** برویم.

توجه

A lib might exist to implement group conversations.

نیاز به حمایت ECC در OpenDHT

استفاده

نقش اضافه کردن؟

دو مورد مهم برای چت های گروهی وجود دارد:

  1. چیزی شبیه یک Mattermost در یک شرکت، با کانال های خصوصی، و برخی نقش ها (admin/spectator/bot/etc) یا برای آموزش (که فقط چند نفر فعال هستند).

  2. مکالمهاي افقي مثل مکالمهاي بين دوستان

Jami will be for which one?

ایده اجرای

گواهی برای گروهی که کاربر را با پرچم برای یک نقش امضا می کند. اضافه کردن یا لغو نیز می تواند انجام شود.

به حرف زدن پیوست

  • فقط از طریق دعوت مستقیم

  • از طریق لینک/ کد QR/ هرچیزی

  • از طریق نام اتاق؟

آنچه که ما نیاز داریم

  • رازداری: اعضای خارج از چت گروه نباید بتوانند پیام ها را در گروه بخوانند

  • رازداری: اگر هر کلید از گروه به خطر افتاده باشد، پیام های قبلی باید محرمانه باقی بمانند (در هر اندازه ممکن)

  • دستور پیام: نیاز به ترتیب پیام ها وجود دارد

  • هم زمان سازی: همچنین لازم است مطمئن شوید که تمام پیام ها به زودی به دست می آیند.

  • دوام: در واقع، یک پیام در DHT تنها 10 دقیقه طول می کشد. چون بهترین زمان محاسبه شده برای این نوع DHT است. برای حفظ داده ها، گره باید هر 10 دقیقه ارزش DHT را دوباره وارد کند. راه دیگری برای انجام آن زمانی که گره غیر فعال است، اجازه دادن به گره ها برای وارد کردن داده ها است. اما اگر پس از 10 دقیقه، 8 گره هنوز در اینجا هستند، آنها 64 درخواست را انجام می دهند (و این نمایی است). راه فعلی برای جلوگیری از اسپام برای آن سوال شده است. این هنوز 64 درخواست را انجام می دهد اما حداکثر بازخورد به 8 گره را محدود می کند.

سایر روش های توزیع شده

  • IPFS: به يه تحقیق نياز دارم

  • بايد يه کم تحقيق کنيم

  • .بايد يه کم تحقيق کنيم

بر اساس کار فعلی که داریم

چت گروهی می تواند بر اساس همان کار ما در حال حاضر برای دستگاه های متعدد (اما در اینجا، با گواهی گروهی) است. مشکلات برای حل:

  1. هم وقت سازي تاريخ اين بايد ديتابيس رو از كلينده به ديمون منتقل کنه

  2. اگر هیچ کس متصل نباشد، همگام سازی نمی تواند انجام شود و فرد هرگز مکالمه را نمی بیند

يه DHT ديگه اختصاصي

مثل يه DHT با يه سوپر کاربری

انتقال فایل

در حال حاضر الگوریتم انتقال فایل بر اساس اتصال TURN (ببینید انتقال فایل) است. در مورد یک گروه بزرگ، این کار بد خواهد بود. ما ابتدا برای انتقال فایل به یک ابزار p2p نیاز داریم. RFC را برای انتقال p2p پیاده سازی کنید.

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

منابع

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

  • همگام سازی توزیع شده قوی سیستم های خطی شبکه ای با اطلاعات متقطع (Sean Phillips و Ricardo G.Sanfelice)