Open fixed DEVICE or GROUPS conversations through the core

This commit is contained in:
evgeny committed 2026-11-03 12:33:57 +01:00
1 parent 7e508f720d
commit 8f4fec4247
2 files changed
+29 -5

No files matched your search

+27 -4
View File
@@ -823,13 +823,21 @@ done:
/* Открыть существующую беседу либо создать при подтверждённом отсутствии записи. */
int dm_start(struct UTUN_INSTANCE* inst, uint64_t peer_node_id,
const uint8_t peer_x25519[32], const uint8_t peer_ed25519[32],
const char* peer_name, const char* source_ch_id) {
const char* peer_name, const char* source_ch_id, enum dm_mode mode, uint64_t* result_conv) {
if (!inst || !peer_node_id || !peer_x25519 || !peer_ed25519) return -1;
if (peer_node_id == inst->node_id) return -1;
struct dm_state* dm = dm_of(inst);
if (!dm || !dm->initialized) return -1;
uint64_t conv_num = dm_derive_conv_id(inst->node_id, peer_node_id);
struct dm_party parties[2] = {{0}};
if (mode == DM_MODE_GROUPS) {
if (dm_party_resolve(inst, inst->node_id, mode, parties) || dm_party_resolve(inst, peer_node_id, mode, parties + 1)) return -1;
conv_num = dm_identity_conv_id(mode, parties);
if (!conv_num) return -1;
} else if (mode != DM_MODE_DEVICE) {
DEBUG_ERROR(DEBUG_CATEGORY_DM, "DM start: invalid mode=%d", mode); return -1;
}
char conv_id[64];
snprintf(conv_id, sizeof(conv_id), "%llu", (unsigned long long)conv_num);
@@ -837,6 +845,10 @@ int dm_start(struct UTUN_INSTANCE* inst, uint64_t peer_node_id,
enum dm_conv_result loaded = dm_conv_load(dm, conv_id, &c);
if (loaded == DM_CONV_ERROR) return -1;
if (loaded == DM_CONV_FOUND) {
if (c.mode != mode || (mode == DM_MODE_DEVICE && c.peer_node_id != peer_node_id) ||
(mode == DM_MODE_GROUPS && (!dm_party_equal(c.parties, parties) || !dm_party_equal(c.parties + 1, parties + 1)))) {
DEBUG_ERROR(DEBUG_CATEGORY_DM, "DM start: conversation identity collision conv=%s", conv_id); return -1;
}
/* Беседа уже есть, но могла быть авто-создана с group_id=0 — дописываем из source_ch_id,
* чтобы маршрутизация шла через группу (а не только прямое соединение). */
if (c.group_id == 0 && source_ch_id && source_ch_id[0]) {
@@ -853,12 +865,21 @@ int dm_start(struct UTUN_INSTANCE* inst, uint64_t peer_node_id,
} else {
memset(&c, 0, sizeof(c));
snprintf(c.conv_id, sizeof(c.conv_id), "%s", conv_id);
c.mode = mode;
c.peer_node_id = peer_node_id;
memcpy(c.peer_x25519, peer_x25519, 32);
memcpy(c.peer_ed25519, peer_ed25519, 32);
dm_copy_peer_name(c.peer_name, peer_name, peer_name ? strlen(peer_name) : 0, conv_id);
c.group_id = source_ch_id ? strtoull(source_ch_id, NULL, 10) : 0;
if (dm_derive_content_key(inst->my_keys.private_key, c.peer_x25519, c.content_key) != 0) return -1;
if (mode == DM_MODE_GROUPS) {
memcpy(c.parties, parties, sizeof(parties));
memcpy(c.peer_x25519, parties[1].x, 32); memcpy(c.peer_ed25519, parties[1].ed, 32);
uint8_t private_key[32];
if (dm_party_private(inst, parties, private_key)) return -1;
int error = dm_derive_content_key(private_key, parties[1].x, c.content_key);
OPENSSL_cleanse(private_key, sizeof(private_key));
if (error) return -1;
} else if (dm_derive_content_key(inst->my_keys.private_key, c.peer_x25519, c.content_key) != 0) return -1;
if (dm_conv_save(dm, &c) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_DM, "%s: conv_save failed conv=%s", DM_ID, conv_id);
@@ -881,6 +902,7 @@ int dm_start(struct UTUN_INSTANCE* inst, uint64_t peer_node_id,
memcpy(evt + 1 + cl, &generation, 8);
chat_event_post(inst, CHAT_EVT_DM_CONV_UPDATED, evt, 1 + (int)cl + 8);
}
if (result_conv) *result_conv = conv_num;
return 0;
}
@@ -1159,6 +1181,7 @@ void dm_start_trampoline(void* arg) {
struct dm_start_req* req = (struct dm_start_req*)arg;
if (!req) return;
struct UTUN_INSTANCE* inst = req->inst;
enum dm_mode mode = req->mode;
uint64_t peer = req->peer_node_id;
char src[64]; strncpy(src, req->source_ch_id, sizeof(src) - 1); src[sizeof(src) - 1] = '\0';
char name[128]; strncpy(name, req->peer_name, sizeof(name) - 1); name[sizeof(name) - 1] = '\0';
@@ -1177,7 +1200,7 @@ void dm_start_trampoline(void* arg) {
DM_ID, (unsigned long long)peer);
return;
}
if (dm_start(inst, peer, x25519, ed25519, name[0] ? name : NULL, src[0] ? src : NULL) != 0)
if (dm_start(inst, peer, x25519, ed25519, name[0] ? name : NULL, src[0] ? src : NULL, mode, NULL) != 0)
DEBUG_ERROR(DEBUG_CATEGORY_DM, "%s: dm_start_trampoline — dm_start failed peer=0x%016llx",
DM_ID, (unsigned long long)peer);
}
@@ -1293,7 +1316,7 @@ void dm_invite_trampoline(void* arg) {
if (loaded == DM_CONV_NOT_FOUND) {
uint8_t x25519[32], ed25519[32];
if (dm_node_pubkeys(dm, req->peer_node_id, x25519, ed25519) != 0 ||
dm_start(req->inst, req->peer_node_id, x25519, ed25519, req->peer_name, req->source_ch_id) != 0) {
dm_start(req->inst, req->peer_node_id, x25519, ed25519, req->peer_name, req->source_ch_id, DM_MODE_DEVICE, NULL) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_DM, "invite PM: conversation failed peer=%llu", (unsigned long long)req->peer_node_id);
dm_invite_done(req, DM_INVITE_START_ERROR); return;
}
+2 -1
View File
@@ -92,7 +92,7 @@ void dm_core_destroy(struct UTUN_INSTANCE* inst);
* Создание разрешено только после успешного SELECT без строки; существующие seq сохраняются. */
int dm_start(struct UTUN_INSTANCE* inst, uint64_t peer_node_id,
const uint8_t peer_x25519[32], const uint8_t peer_ed25519[32],
const char* peer_name, const char* source_ch_id);
const char* peer_name, const char* source_ch_id, enum dm_mode mode, uint64_t* result_conv);
/* Отправить сообщение в беседу. Шифрует, подписывает, сохраняет локально и
* доставляет (прямое соединение при доступности пира, иначе mailbox).
@@ -143,6 +143,7 @@ struct dm_start_req {
uint64_t peer_node_id; /* Другой участник общей группы; ключи читаются из nodes. */
char source_ch_id[64]; /* Десятичный ID общей группы либо пустая строка. */
char peer_name[128]; /* UTF-8 имя с NUL; dm_start ограничит до 63 байт. */
enum dm_mode mode; /* Один переключатель DEVICE/GROUPS для обеих сторон. */
};
void dm_start_trampoline(void* arg);