Thủy
Quan trọng
Jami source code tends to use the terms (un)ban, while the user interface uses the terms (un)block.
Synospis
Mục tiêu của tài liệu này là mô tả cách trò chuyện nhóm (tên gọi là swarm chat) sẽ được triển khai ở Jami.
Một nhóm có thể thảo luận mà không có bất kỳ cơ quan trung ương nào theo cách kiên cường. Thật vậy, nếu hai người không có bất kỳ kết nối nào với phần còn lại của nhóm (ví dụ, mất điện Internet) nhưng họ có thể liên lạc với nhau (trong một LAN ví dụ hoặc trong một mạng phụ), họ sẽ có thể gửi tin nhắn cho nhau và sau đó, sẽ có thể đồng bộ với phần còn lại của nhóm khi có thể.
Vì vậy, "swarm" được định nghĩa bởi:
Khả năng chia và hợp nhất theo kết nối.
Bất cứ ai cũng có thể gửi thông điệp cho toàn bộ nhóm.
Không có cơ quan trung ương, không thể tin vào bất kỳ máy chủ nào.
Không phủ nhận. thiết bị phải có khả năng xác minh tính hợp lệ của tin nhắn cũ và để chơi lại toàn bộ lịch sử.
PFS trên vận chuyển.
Ý tưởng chính là có được một cây Merkle đồng bộ với các thành viên.
Chúng tôi đã xác định bốn chế độ cho trò chuyện đám đông mà chúng tôi muốn thực hiện:
**Mỗi người, về cơ bản là trường hợp chúng ta có hôm nay khi bạn thảo luận với một người bạn
ADMIN_INVITES_ONLY thường là một lớp học mà giáo viên có thể mời mọi người, nhưng không phải là sinh viên
Hãy mời một nhóm bạn riêng tư
Public về cơ bản là một diễn đàn mở
Các kịch bản
Tạo một nhóm
Bob muốn tạo ra một đám đông mới
Bob creates a local Git repository.
Sau đó, ông ta tạo ra một cam kết ban đầu được ký kết với những điều sau:
Chìa khóa công khai của anh ấy trong
/admins
Giấy chứng nhận thiết bị của anh ta trong ̀ / thiết bị `
CRL của anh ta trong ̀ /crls`
Hash của commit đầu tiên trở thành ID của cuộc trò chuyện
Bob thông báo cho các thiết bị khác của mình rằng anh ta tạo ra một cuộc trò chuyện mới. Điều này được thực hiện thông qua một lời mời để tham gia đám đông được gửi qua DHT đến các thiết bị khác liên kết với tài khoản đó.
Thêm ai đó
Alice adds Bob
Alice thêm Bob vào repo:
Thêm URI được mời vào
/invited
Thêm CRL vào
/crls
Alice gửi một yêu cầu về DHT
Nhận lời mời
Alice gets the invite to join the previously create swarm
Cô ấy chấp nhận lời mời (nếu từ chối, không làm gì, nó sẽ chỉ ở lại trong mời và Alice sẽ không bao giờ nhận được bất kỳ tin nhắn nào)
Một mối liên hệ giữa Alice và Bob đã được thực hiện.
Alice pull the Git repo of Bob. WARNING this means that messages need a connection, not from the DHT like today.
Alice xác nhận các cam kết từ Bob
Để xác nhận rằng Alice là thành viên, cô ấy xóa lời mời từ thư mục
/invited
, sau đó thêm chứng chỉ của mình vào thư mục/members
Khi tất cả các cam kết được xác nhận và trên thiết bị của mình, các thành viên khác của nhóm được Alice phát hiện. Với những người đồng nghiệp này, cô sẽ xây dựng DRT (được giải thích bên dưới) với Bob như một bootstrap.
Gửi tin nhắn
Alice sends a message
Gửi tin nhắn khá đơn giản. Alice viết tin nhắn tham gia theo định dạng sau:
{
"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).
Để ping các thiết bị khác, người gửi gửi gửi cho các thành viên khác một tin nhắn SIP với mimetype = "application/im-gitmessage-id" chứa một JSON với "deviceId" gửi tin nhắn, "id" của cuộc trò chuyện liên quan, và "commit"
Nhận tin nhắn
Bob nhận được tin nhắn từ Alice
Bob do a Git pull on Alice
Các cam kết phải được xác minh qua một cái nón
Nếu tất cả các commits là hợp lệ, các commits được lưu trữ và hiển thị. Sau đó Bob thông báo thông điệp qua DRT cho các thiết bị khác.
If all commits are not valid, pull is canceled. Alice must reestablish her state to a correct state.
Đăng bằng một cam kết
Để tránh người dùng đẩy một số cam kết không mong muốn (với xung đột, tin nhắn sai, vv), đây là cách mỗi cam kết (từ cũ nhất đến mới nhất) MUST được xác nhận trước khi sáp nhập một chi nhánh từ xa:
Ghi chú
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.
Đối với mỗi giao dịch, hãy kiểm tra rằng thiết bị cố gắng gửi giao dịch đã được ủy quyền tại thời điểm này và các chứng chỉ có mặt (trong các thiết bị cho thiết bị và trong các thành viên hoặc người quản lý cho nhà phát hành).
3 trường hợp. Commit có 2 cha mẹ, vì vậy đó là một sự hợp nhất, không có gì khác để xác nhận ở đây
Commit có 0 cha mẹ, đó là commit ban đầu:
Kiểm tra rằng admin certificate đã được thêm vào
Kiểm tra rằng thiết bị cert đã được thêm vào
Các CRL kiểm tra được thêm vào
Kiểm tra rằng không có tệp nào khác được thêm vào
Commit có 1 cha mẹ, tin nhắn commit là một JSON với một loại:
Nếu văn bản (hoặc loại mime khác không thay đổi các tệp)
Kiểm tra chữ ký từ chứng chỉ trong repo
Kiểm tra rằng không có tập tin kỳ lạ được thêm bên ngoài thiết bị chứng chỉ hoặc xóa
Nếu bỏ phiếu
Kiểm tra voteType được hỗ trợ (banned, unban)
Kiểm tra rằng phiếu là cho người dùng ký kết cam kết
Check that vote is from an admin and device present and not banned
Kiểm tra rằng không có tập tin kỳ lạ được thêm vào hoặc xóa
Nếu thành viên
Nếu thêm
Kiểm tra rằng cam kết đã được ký đúng
Kiểm tra chứng chỉ được thêm vào / mời
Kiểm tra rằng không có tập tin kỳ lạ được thêm vào hoặc xóa
Nếu ONE_TO_ONE, kiểm tra rằng chúng tôi chỉ có một admin, một thành viên
Nếu ADMIN_INVITES_ONLY, kiểm tra rằng lời mời là từ một admin
Nếu gia nhập
Kiểm tra rằng cam kết đã được ký đúng
Kiểm tra thiết bị được thêm vào
Kiểm tra xem lời mời được chuyển đến các thành viên
Kiểm tra rằng không có tập tin kỳ lạ được thêm vào hoặc xóa
Nếu bị cấm
Kiểm tra phiếu bầu có hợp lệ
Kiểm tra rằng người dùng bị cấm thông qua một admin
Kiểm tra xem chứng chỉ thành viên hoặc thiết bị đã được chuyển sang cấm/
Kiểm tra rằng chỉ có các tệp liên quan đến bỏ phiếu được xóa
Kiểm tra rằng không có tập tin kỳ lạ được thêm vào hoặc xóa
thông báo cho người dùng rằng họ có thể là với một phiên bản cũ hoặc người đồng nghiệp đã cố gắng gửi các commit không mong muốn
Thiết bị cấm
Alice, Bob, Carla, Denys đang trong đám đông.
Đây là một trong những kịch bản khó khăn nhất trong bối cảnh của chúng ta.
Các dấu thời gian của các cam kết được tạo ra
Nếu có nhiều thiết bị quản trị và nếu Alice có thể nói chuyện với Bob nhưng không phải Denys và Carla; Carla có thể nói chuyện với Denys; Denys cấm Alice, Alice cấm Denys, điều gì sẽ xảy ra khi 4 thành viên kết hợp các cuộc trò chuyện.
Một thiết bị có thể bị xâm nhập, bị đánh cắp hoặc chứng chỉ của nó có thể hết hạn. Chúng ta nên có thể cấm một thiết bị và tránh được việc nó nói dối về hết hạn của nó hoặc gửi tin nhắn trong quá khứ (bằng cách thay đổi chứng chỉ của nó hoặc dấu thời gian của cam kết của nó).
Các hệ thống tương tự (với hệ thống nhóm phân tán) không nhiều, nhưng đây là một số ví dụ:
[mpOTR không định nghĩa cách cấm một người nào đó]
Cấu hiệu, không có bất kỳ máy chủ trung tâm nào cho trò chuyện nhóm (EDIT: họ gần đây thay đổi điểm đó), không cung cấp khả năng cấm ai đó từ một nhóm.
Hệ thống bỏ phiếu này cần một hành động của con người để cấm một người hoặc phải dựa trên thông tin về CRL từ kho lưu trữ (vì chúng ta không thể tin tưởng vào CRL bên ngoài)
Tắt một thiết bị từ cuộc trò chuyện
Đây là phần duy nhất mà CHÀO phải có sự đồng thuận để tránh chia rẽ cuộc trò chuyện, như nếu hai thành viên đá nhau khỏi cuộc trò chuyện, cái gì sẽ thấy thứ ba?
Điều này là cần thiết để phát hiện các thiết bị bị bị hủy bỏ, hoặc đơn giản là tránh có những người không mong muốn ở trong một phòng công cộng.
Alice removes Bob
Quan trọng
Alice MUST be an admin to vote.
Trước tiên, cô bỏ phiếu cấm Bob. Để làm điều đó, cô tạo ra tệp trong /votes/ban/members/uri_bob/uri_alice (những thành viên có thể được thay thế bằng các thiết bị cho một thiết bị, hoặc được mời mời để mời hoặc quản trị viên cho quản trị viên) và cam kết
Sau đó cô ấy kiểm tra xem phiếu bầu đã được giải quyết hay không. Điều này có nghĩa là > 50% người quản trị đồng ý cấm Bob (nếu cô ấy là một mình, chắc chắn đó là hơn 50%).
Nếu bỏ phiếu được giải quyết, các tập tin vào /votes/ban có thể được xóa, tất cả các tập tin cho Bob trong /members, /admins, /invited, /CRLs, /devices có thể được xóa (hoặc chỉ trong /devices nếu đó là một thiết bị bị cấm) và chứng chỉ của Bob có thể được đặt vào /banned/members/bob_uri.crt (hoặc /banned/devices/uri.crt nếu một thiết bị bị bị cấm) và được cam kết với repo
Sau đó, Alice thông báo cho người dùng khác (ngoài 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
Sau đó cô ấy kiểm tra xem phiếu bầu đã được giải quyết hay không. Điều này có nghĩa là > 50% người quản trị đồng ý cấm Bob (nếu cô ấy là một mình, chắc chắn đó là hơn 50%).
Nếu bỏ phiếu được giải quyết, các tập tin vào /votes/unban có thể được xóa, tất cả các tập tin cho Bob trong /members, /admins, /invited, /CRLs, có thể được thêm lại (hoặc chỉ trong /devices nếu đó là một thiết bị không bị cấm) và cam kết cho repo
Tháo cuộc trò chuyện
Cung cấp trong convInfos removed=time::now() (như removeContact save in contacts) rằng cuộc trò chuyện được xóa và đồng bộ hóa với các thiết bị của người dùng khác
Nếu nhận được một lời mời mới cho cuộc trò chuyện này thì nó sẽ bị bỏ qua.
Bây giờ, nếu Jami khởi động và repo vẫn hiện diện, cuộc trò chuyện không được công bố cho khách hàng
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.
Khi chúng ta chắc chắn rằng ai đó đã đồng bộ hóa, xóa xóa=time::now() và đồng bộ hóa với các thiết bị của người dùng khác
Tất cả các thiết bị thuộc sở hữu của người dùng bây giờ có thể xóa kho và các tập tin liên quan
Làm thế nào để xác định chế độ
Các chế độ không thể thay đổi theo thời gian. hoặc đó là một cuộc trò chuyện khác. Vì vậy, dữ liệu này được lưu trữ trong thông điệp commit ban đầu. thông điệp commit sẽ như sau:
{
"type": "initial",
"mode": 0,
}
Hiện tại, "mode" chấp nhận các giá trị 0 (ONE_TO_ONE), 1 (ADMIN_INVITES_ONLY), 2 (INVITES_ONLY), 3 (PUBLIC)
Processes for 1:1 swarms
Mục tiêu ở đây là giữ cho API cũ (addContact/removeContact, sendTrustRequest/acceptTrustRequest/discardTrustRequest) để tạo ra đám đông với một người đồng nghiệp và liên lạc của nó. Điều này vẫn có nghĩa là một số thay đổi mà chúng ta không thể bỏ qua:
Quá trình vẫn giống nhau, một tài khoản có thể thêm một liên hệ thông qua addContact, sau đó gửi TrustRequest thông qua DHT.
TrustRequest nhúng một "conversationId" để thông báo cho người đồng nghiệp cuộc trò chuyện nào để sao chép khi chấp nhận yêu cầu
TrustRequest được thử lại khi liên lạc trở lại trực tuyến. Không phải là trường hợp ngày nay (chẳng muốn tạo TrustRequest mới nếu người đồng nghiệp loại bỏ thứ nhất). Vì vậy, nếu một tài khoản nhận được yêu cầu tin tưởng, nó sẽ được tự động bỏ qua nếu yêu cầu với một cuộc trò chuyện liên quan bị từ chối (vì convRequests được đồng bộ hóa)
Sau đó, khi một liên lạc chấp nhận yêu cầu, một thời gian đồng bộ là cần thiết, bởi vì liên lạc bây giờ cần phải nhân bản cuộc trò chuyện.
removeContact() sẽ xóa liên lạc và các cuộc trò chuyện 1: 1 liên quan (với cùng một quy trình như "Remove a conversation").
Các kịch bản khó khăn
Có một số trường hợp có thể tạo ra hai cuộc trò chuyện.
Alice adds Bob.
Bob accepts.
Alice removes Bob.
Alice adds Bob.
hoặc
Alice adds Bob and Bob adds Alice at the same time, but both are not connected together.
Trong trường hợp này, hai cuộc trò chuyện được tạo ra. Chúng tôi không muốn xóa tin nhắn từ người dùng hoặc chọn một cuộc trò chuyện ở đây. Vì vậy, đôi khi sẽ được hiển thị hai đám 1:1 giữa cùng một thành viên. Nó sẽ tạo ra một số lỗi trong thời gian chuyển đổi (vì chúng tôi không muốn phá vỡ API, cuộc trò chuyện được suy luận sẽ là một trong hai cuộc trò chuyện được hiển thị, nhưng cho đến bây giờ nó là "ok-ish", sẽ được sửa chữa khi khách hàng sẽ xử lý đầy đủ cuộc trò chuyệnId cho tất cả API (call, chuyển tập tin, vv)).
Quan trọng
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() sẽ trả lại {{"syncing": "true"}} nếu đồng bộ hóa.
ConfigurationManager::getConversationMembers() will return a map of two URIs (the current account and the peer who sent the request).
Các cuộc trò chuyện yêu cầu thông số kỹ thuật
Các yêu cầu trò chuyện được đại diện bởi một Map<String, String> với các phím sau:
id: the conversation ID
from: URI of the sender
nhận: dấu thời gian
Tiêu đề: (bắt buộc) tên cho cuộc trò chuyện
mô tả: (không chọn lựa)
avatar: (tự chọn)
Đồng bộ hóa hồ sơ của cuộc trò chuyện
Để được xác định, một cuộc trò chuyện thường cần một số siêu dữ liệu, chẳng hạn như tiêu đề (ví dụ: Jami), mô tả (ví dụ: một số liên kết, dự án là gì, v.v.), và một hình ảnh (chữ liệu biểu tượng của dự án).
Tạp lưu trữ trong kho
Profile của cuộc trò chuyện được lưu trữ trong tệp vCard cổ điển ở gốc (/profile.vcf
) như:
BEGIN:VCARD
VERSION:2.1
FN:TITLE
DESCRIPTION:DESC
END:VCARD
Đồng bộ hóa
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).
Tiếp theo được hiển thị
Trong dữ liệu đồng bộ, mỗi thiết bị gửi đến các thiết bị khác trạng thái của các cuộc trò chuyện. Trong trạng thái này, cuối cùng được hiển thị được gửi. Tuy nhiên, vì mỗi thiết bị có thể có trạng thái riêng cho mỗi cuộc trò chuyện, và có lẽ không có cùng một cam kết cuối cùng tại một thời điểm nào đó, có một số kịch bản cần tính:
5 kịch bản được hỗ trợ:
nếu màn hình cuối cùng được gửi bởi các thiết bị khác giống như màn hình hiện tại, không có gì để làm.
Nếu không có hiển thị cuối cùng cho thiết bị hiện tại, thông điệp hiển thị từ xa được sử dụng.
nếu từ xa lần cuối được hiển thị không có mặt trong repo, nó có nghĩa là commit sẽ được lấy sau đó, do đó cache kết quả
nếu điều khiển từ xa đã được lấy, chúng tôi kiểm tra rằng địa phương cuối cùng hiển thị là trước trong lịch sử để thay thế nó
Cuối cùng, nếu một thông điệp được công bố từ cùng một tác giả, nó có nghĩa là chúng ta cần phải cập nhật thông điệp cuối cùng được hiển thị.
Tự ưu tiên
Mỗi cuộc trò chuyện đều có tùy chọn được đặt bởi người dùng. Những tùy chọn đó được đồng bộ hóa trên các thiết bị của người dùng. Đây có thể là màu của cuộc trò chuyện, nếu người dùng muốn bỏ qua thông báo, giới hạn kích thước chuyển tập tin, vv. Cho đến nay, các khóa được công nhận là:
"color" - the color of the conversation (#RRGGBB format)
"ignoreNotifications" - để bỏ qua các thông báo cho các tin nhắn mới trong cuộc trò chuyện này
"symbol" - để xác định emoji mặc định.
Những sở thích đó được lưu trữ trong một gói MapStringString, được lưu trữ trong accountDir/conversation_data/conversationId/preferences
và chỉ được gửi qua các thiết bị của cùng một người dùng thông qua SyncMsg.
API để tương tác với các sở thích là:
// 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*/);
};
Quản lý xung đột sáp nhập
Bởi vì hai người quản trị có thể thay đổi mô tả cùng một lúc, một xung đột sáp nhập có thể xảy ra trên profile.vcf
. Trong trường hợp này, commit với hash cao hơn (ví dụ ffffff > 000000) sẽ được chọn.
API
Người dùng có 2 phương pháp để lấy và đặt metadata của cuộc trò chuyện:
<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>
nơi infos
là một map<str, str>
với các phím sau:
chế độ: Đọc chỉ
tiêu đề
mô tả
avatar
Nhập lại tài khoản (link/export)
Các lưu trữ MUST chứa conversationId để có thể lấy lại các cuộc trò chuyện trên các commit mới sau khi nhập lại (vì không có lời mời tại thời điểm này).
Cuộc trò chuyện có ở đó, trong trường hợp này, con quỷ có thể tái nhân bản cuộc trò chuyện này
ConversationId bị mất tích, do đó, con quỷ yêu cầu (cứ qua tin nhắn
{{" ứng dụng/ mời", conversationId}}
) một lời mời mới mà người dùng cần (tái) chấp nhận
Quan trọng
A conversation can only be retrieved if a contact or another device is there, else it will be lost. There is no magic.
Các giao thức được sử dụng
Git
Tại sao lựa chọn này
Each conversation will be a Git repository. This choice is motivated by:
Chúng ta cần đồng bộ hóa và sắp xếp các tin nhắn. Cây Merkle là cấu trúc hoàn hảo để làm điều đó và có thể được tuyến tính bằng cách sáp nhập các nhánh. Hơn nữa, vì nó được sử dụng rộng rãi bởi Git, nó dễ dàng đồng bộ hóa giữa các thiết bị.
Được phân phối bởi tự nhiên, được sử dụng rộng rãi, nhiều backend và có thể bật.
Có thể xác minh các cam kết thông qua các cái móng và tiền điện tử được sử dụng rộng rãi
Có thể được lưu trữ trong cơ sở dữ liệu nếu cần thiết
Các xung đột được tránh bằng cách sử dụng tin nhắn commit, không phải các tệp.
Những gì chúng ta phải xác nhận
Hiệu suất?
git.lock
có thể thấpCây đập trong libgit2
Nhiều lần kéo cùng một lúc?
Các giới hạn
Lịch sử không thể xóa. Để xóa một cuộc trò chuyện, thiết bị phải rời khỏi cuộc trò chuyện và tạo một cuộc trò chuyện khác.
Tuy nhiên, các thông điệp không thường xuyên (như thông điệp chỉ được đọc trong vài phút) có thể được gửi qua một thông điệp đặc biệt thông qua DRT (như thông báo nhập hoặc đọc).
Cấu trúc
/
- 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
Chuyển tập tin
Swarm thay đổi chuyển giao tệp một cách lớn. Bây giờ, tất cả lịch sử đang đồng bộ hóa, cho phép tất cả các thiết bị trong cuộc trò chuyện dễ dàng lấy lại các tệp cũ. Những thay đổi này cho phép chúng ta chuyển từ một logic nơi người gửi đẩy tệp trên các thiết bị khác, thông qua cố gắng kết nối với các thiết bị của họ (Đây là xấu vì không thực sự kháng với các thay đổi / thất bại kết nối và cần một thử lại thủ công) đến một logic nơi người gửi cho phép các thiết bị khác tải xuống. Hơn nữa, bất kỳ thiết bị nào có tệp có thể là chủ nhà cho các thiết bị khác, cho phép lấy tệp ngay cả khi người gửi không có ở đó.
Phương pháp
Người gửi thêm một commit mới trong cuộc trò chuyện với định dạng sau:
value["tid"] = "RANDOMID";
value["displayName"] = "DISPLAYNAME";
value["totalSize"] = "SIZE OF THE FILE";
value["sha3sum"] = "SHA3SUM OF THE FILE";
value["type"] = "application/data-transfer+json";
và tạo ra một liên kết trong ${data_path}/conversation_data/${conversation_id}/${file_id}
nơi file_id=${commitid}_${value["tide"]}.${extension}
Sau đó, người nhận có thể tải xuống các tệp bằng cách liên hệ với các thiết bị lưu trữ tệp bằng cách mở kênh với name="data-transfer://" + conversationId + "/" + currentDeviceId() + "/" + fileId
và lưu trữ thông tin rằng tệp đang chờ đợi trong ${data_path}/conversation_data/${conversation_id}/waiting
Thiết bị nhận kết nối sẽ chấp nhận kênh bằng cách xác minh liệu tệp có thể được gửi (nếu sha3sum là đúng và tệp có). Người nhận sẽ giữ kênh mở đầu tiên, đóng các kênh khác và ghi vào tệp (với cùng con đường như người gửi: ${data_path}/conversation_data/${conversation_id}/${file_id}
) tất cả dữ liệu nhập.
Khi chuyển giao hoàn thành hoặc kênh đóng, số lượng sha3 được xác minh để xác minh rằng tệp là đúng (hoặc nó đã bị xóa). Nếu hợp lệ, tệp sẽ được xóa khỏi chờ.
Trong trường hợp thất bại, khi thiết bị của cuộc trò chuyện sẽ trở lại trực tuyến, chúng tôi sẽ yêu cầu tất cả các tệp chờ theo cùng một cách.
Đưa ra đám đông
Ý tưởng
A swarm conversation can have multiple rendez-vous. A rendez-vous is defined by the following URI:
"accountUri/deviceId/conversationId/confId" nơi accountUri/deviceId mô tả máy chủ.
Người chủ có thể được xác định bằng hai cách:
Trong đám metadata, nơi nó được lưu trữ như tiêu đề/các bàn/tình ảnh của phòng
Hoặc là người gọi đầu tiên.
Khi bắt đầu cuộc gọi, chủ nhà sẽ thêm một cam kết mới vào đám đông, với URI để tham gia (accountUri/deviceId/conversationId/confId).
Vì vậy, mỗi phần sẽ nhận được thông tin rằng một cuộc gọi đã bắt đầu và sẽ có thể tham gia nó bằng cách gọi nó.
Chuyện tấn công?
Avoid Git bombs
Các ghi chú
Bức timestamp của một commit có thể được tin cậy bởi vì nó có thể chỉnh sửa. Chỉ có timestamp của người dùng có thể được tin cậy.
TLS
Các hoạt động Git, tin nhắn kiểm soát, tệp, và những thứ khác sẽ sử dụng một liên kết TLS v1.3 p2p chỉ có mã hóa đảm bảo PFS. Vì vậy mỗi khóa được đàm phán lại cho mỗi kết nối mới.
DHT (UDP)
Được sử dụng để gửi tin nhắn cho điện thoại di động (để kích hoạt thông báo đẩy) và để khởi động kết nối TCP.
Hoạt động mạng
Quá trình mời ai đó
Alice muốn mời Bob:
Alice thêm Bob vào cuộc trò chuyện
Alice generates an invite: { "application/invite+json" : { "conversationId": "$id", "members": [{...}] }}
Hai khả năng để gửi thông điệp a. Nếu không kết nối, qua DHT b. Nếu không, Alice gửi trên kênh SIP
Bob nhận được lời mời, một tín hiệu được phát ra cho khách hàng b. Không kết nối, vì vậy sẽ không bao giờ nhận được yêu cầu vì Alice không thể biết nếu Bob đã bỏ qua hoặc chặn Alice. Cách duy nhất là tái tạo lời mời mới thông qua một tin nhắn mới (xem kịch bản tiếp theo)
Quá trình để gửi tin nhắn cho ai đó
Alice muốn gửi tin nhắn cho Bob:
Alice thêm một tin nhắn vào repo, cho một ID
Alice nhận được một tin nhắn (từ chính mình) nếu thành công
Hai khả năng, alice và bob có kết nối, hoặc không. Trong cả hai trường hợp một thông điệp được tạo ra: { "application/im-gitmessage-id" : "{"id":"\(convId", "commit":"\)commitId", "deviceId": "$alice_device_hash"}"}.
Bốn khả năng cho Bob: a. Bob không kết nối với Alice, vì vậy nếu ông tin tưởng Alice, hãy yêu cầu kết nối mới và đi đến b. b. Nếu kết nối, hãy lấy từ Alice và thông báo tin mới c. Bob không biết cuộc trò chuyện đó. Hãy yêu cầu thông qua DHT để nhận được một lời mời trước tiên để có thể chấp nhận cuộc trò chuyện đó ({" ứng dụng/ mời", cuộc trò chuyệnId}) d. Bob bị ngắt kết nối (không có mạng, hoặc chỉ đóng).
Thực hiện
! [Chương trình: lớp học trò chuyện đám đông](hình ảnh/chương trình trò chuyện đám đông lớp học.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"
}
Calls
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"
}
!! DRAFT LÀN!!
Ghi chú
Following notes are not organized yet. Just some line of thoughts.
Những cải tiến về tiền điện tử.
Đối với một tính năng trò chuyện nhóm nghiêm túc, chúng ta cũng cần mã hóa nghiêm túc. Với thiết kế hiện tại, nếu một chứng chỉ bị đánh cắp như các giá trị DHT trước của một cuộc trò chuyện, cuộc trò chuyện có thể được giải mã. Có lẽ chúng ta cần phải đi đến một cái gì đó như ** Double ratchet**.
Ghi chú
A lib might exist to implement group conversations.
Cần hỗ trợ ECC trong OpenDHT
Sử dụng
Thêm vai trò?
Có hai trường hợp sử dụng chính cho trò chuyện nhóm:
Một cái gì đó như một Mattermost trong một công ty, với các kênh riêng, và một số vai trò (admin/spectator/bot/etc) hoặc cho giáo dục (nơi chỉ có một vài người hoạt động).
Những cuộc trò chuyện ngang ngang như một cuộc trò chuyện giữa bạn bè.
Jami will be for which one?
Ý tưởng thực hiện
Một chứng chỉ cho một nhóm ký tên người dùng với cờ cho một vai trò.
Tham gia cuộc trò chuyện
Chỉ qua lời mời trực tiếp
Thông qua một liên kết/QR Code/ bất cứ điều gì
Thông qua tên phòng?
Những gì chúng ta cần
Bảo mật: các thành viên bên ngoài trò chuyện nhóm không nên có thể đọc tin nhắn trong nhóm
Sự bí mật tiếp theo: nếu bất kỳ khóa nào từ nhóm bị xâm nhập, tin nhắn trước đó nên được giữ bí mật (tối đa khả năng)
Định hướng thông điệp: Có nhu cầu có thông điệp theo thứ tự đúng
Đồng bộ hóa: Ngoài ra còn cần phải đảm bảo có tất cả các tin nhắn càng sớm càng tốt.
Sự kiên trì: Thực tế, một tin nhắn trên DHT chỉ tồn tại 10 phút. Bởi vì đó là thời gian tốt nhất được tính toán cho loại DHT này. Để duy trì dữ liệu, nút phải đặt lại giá trị trên DHT mỗi 10 phút. Một cách khác để làm khi nút offline là để các nút đặt lại dữ liệu. Nhưng, nếu sau 10 phút, 8 nút vẫn ở đây, họ sẽ thực hiện 64 yêu cầu (và nó là tăng trưởng). Cách hiện tại để tránh spam cho điều đó là truy vấn. Điều này vẫn sẽ thực hiện 64 yêu cầu nhưng giới hạn sự dư thừa tối đa đến 8 nút.
Các phương thức phân phối khác
IPFS: cần một số điều tra
Bắt đầu điều tra
Tôi cần điều tra.
Dựa trên công việc hiện tại chúng ta có
Các trò chuyện nhóm có thể dựa trên cùng một công việc mà chúng ta đã có cho nhiều thiết bị (nhưng ở đây, với một chứng chỉ nhóm).
Điều này cần phải di chuyển cơ sở dữ liệu từ khách hàng sang con quỷ.
Nếu không ai kết nối, đồng bộ hóa không thể được thực hiện, và người đó sẽ không bao giờ thấy cuộc trò chuyện
Một DHT chuyên dụng khác
Giống như một DHT với một người dùng siêu.
Chuyển tập tin
Hiện tại, thuật toán chuyển giao tệp dựa trên kết nối TURN (xem Chuyển tập tin). Trong trường hợp của một nhóm lớn, điều này sẽ không tốt. Chúng ta cần đầu tiên một ứng dụng p2p cho chuyển giao tệp. Thực hiện RFC cho chuyển giao p2p.
Vấn đề khác: hiện tại không có sự triển khai hỗ trợ TCP cho ICE trong PJSIP. Điều này là bắt buộc cho điểm này (trong pjsip hoặc tự làm)
Tài nguyên
https://eprint.iacr.org/2017/666.pdf
Sự đồng bộ phân phối mạnh mẽ của các hệ thống tuyến tính được mạng hóa với thông tin gián đoạn (Sean Phillips và Ricardo G.Sanfelice)