KProto протокол мессенджера DCC
KProto — это бинарный протокол прикладного уровня на базе Protocol Buffers (proto3), предназначенный для обмена сообщениями в реальном времени внутри экосистемы DCC.
Ключевые принципы
- Типизация: Использование строгих схем для исключения ошибок парсинга.
- Эффективность: Минимизация трафика через бинарную сериализацию.
- Непривязанность к транспорту: Работа поверх WebSocket, TCP или gRPC.
- Безопасность по умолчанию: Интеграция Noise Protocol Framework для обеспечения C2S и E2EE шифрования.
Система идентификаторов
Протокол оперирует тремя уровнями адресации:
user_id(fixed64): Глобальный аккаунт пользователя.device_id(fixed64): Конкретное устройство (используется для привязки ключей шифрования).session_id(fixed64): Идентификатор текущего сетевого соединения.
Transport (WebSocket / TCP) Also transport level encryption make possibility inside protocol to handle E2EE
↓
KProto (version, ids, kind)
↓
Protocol Layer:
- Auth
- Presence
- Contacts
- Conversations
- Messaging
↓
Extensions:
- Voice (UDP/WebRTC) KProto as signaling layer
- Files (Second socket) Chunking and retrying
- Streams (UDP/WebRTC) KProto as signaling layer
- etc.
Структура файлов протокола
main.kproto
syntax = "proto3";
package kproto;
message KProtoPacket {
// Заголовок контекста
fixed64 user_id = 1;
fixed64 device_id = 2;
fixed64 session_id = 3;
// Безопасный контейнер
oneof payload {
NoiseHandshake handshake = 4; // Этап обмена ключами
NoiseTransport transport = 5; // Зашифрованные данные (message.proto)
}
}
message NoiseHandshake {
bytes handshake_message = 1; // e, s, ee, se компоненты
uint32 version = 2; // Версия протокола
}
message NoiseTransport {
bytes encrypted_data = 1; // Зашифрованный Protobuf-пакет + MAC
fixed64 sequence_number = 2; // Порядковый номер (для защиты от повторов)
}
auth.proto
// action: auth.hello
// kind: REQUEST
message Hello {
string device_id = 1; // UUID (генерится и хранится)
string client_version = 2;
repeated string capabilities = 3;
}
message HelloAck {
string server_version = 1;
repeated string capabilities = 2;
string connection_id = 3; // опционально
}
// только при условии что нет oidc
// action: auth.login
// kind: REQUEST
message Login {
string login = 1; // username/email
string password = 2; // позже → hash/token
}
// на oidc это скипается и переход сразу к установке сессии
message LoginSuccess {
string user_id = 1;
string access_token = 2;
string refresh_token = 3;
int64 expires_at = 4;
}
message SessionStart {
string access_token = 1;
string device_id = 2;
}
message SessionStarted {
string session_id = 1;
string user_id = 2;
int64 server_time = 3;
}
//Восстановление сессии
message SessionResume {
string session_id = 1;
string access_token = 2;
}
message SessionResumed {
string session_id = 1;
}
// При невалид сессии закрытие соедиение с отправленным пустым KProto пакетом
// action: auth.session.invalid
message Refresh {
string refresh_token = 1;
}
message RefreshSuccess {
string access_token = 1;
int64 expires_at = 2;
}
KPR-1 Conversations + Messaging
SendMessage (REQUEST)
↓
SendMessageAck (RESPONSE)
↓
MessageEvent (EVENT всем участникам)
↓
ACK (опционально)
message.proto
message Message {
string message_id = 1;
string conversation_id = 2;
string sender_id = 3;
int64 timestamp = 4;
MessageContent content = 5;
MessageMeta meta = 6;
uint64 seq = 7;
}
message MessageContent {
oneof type {
TextContent text = 1;
FileContent file = 2;
SystemContent system = 3;
// future
bytes encrypted = 10;
}
}
message TextContent {
string text = 1;
}
message FileContent {
string file_id = 1;
string filename = 2;
}
message SystemContent {
string type = 1; // "user_joined", "title_changed"
map<string, string> data = 2;
}
message MessageMeta {
string client_msg_id = 1;
bool edited = 2;
bool deleted = 3;
string reply_to = 4;
}
// action: chat.send
// kind: REQUEST
message SendMessage {
string conversation_id = 1;
MessageContent content = 2;
string client_msg_id = 3;
}
// kind: RESPONSE
message SendMessageAck {
string message_id = 1;
string client_msg_id = 2;
int64 timestamp = 3;
}
// action: chat.message
// kind: EVENT
message MessageEvent {
Message message = 1;
}
// kind: ACK
// correlation_id: message_id
// action: chat.read
message MessageRead {
string conversation_id = 1;
string message_id = 2;
}
message GetHistory {
string conversation_id = 1;
int32 limit = 2;
string before_message_id = 3;
}
message History {
repeated Message messages = 1;
}