Files
utun2/src/chat/chat_attachment.h
T

111 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* chat_attachment — вложения канала с шифрованием и ручной выдачей ключа автором.
* send готовит контейнер и публикует сообщение; downloaded/want запускают получение ключа и расшифровку.
* Автор отвечает на запрос через decide. Ключи и очередь доставки сохраняются в локальной БД.
* Все вызовы, кроме identity, — uasync. init после media_async; quiesce до остановки workers, destroy после них.
* Обмен ключами подписан и зашифрован; для доставки нужен живой маршрут обеих сторон.
* Ответы REQUEST_ACK/GRANT/DENY/RESULT_ACK атомарно меняют ключ, запрос и outbox собственной транзакцией.
* Внешняя транзакция для ответов запрещена. GRANT/DENY подтверждаются только после проверенного commit;
* повтор с тем же результатом допустим, конфликтующий ключ/решение отклоняется. Отказ SQL сохраняет прежнее состояние.
* Приём REQUEST владеет собственной транзакцией проверки идентичности/прав и сохранения запроса/повтора ответа.
* Внешняя транзакция отклоняется без изменений; ACK/событие — после commit. Дубликат сохраняет решение и дату:
* state=0 ждёт автора, 2/4 повторяют GRANT, 3 повторяет DENY; чужое направление и другие состояния отклоняются.
* Исходящий REQUEST сохраняется собственной транзакцией request+outbox после повторной проверки состояния.
* Уведомление/отправка следуют после commit; внешняя транзакция откладывает весь проход файлов и очереди.
* Перед сетевой попыткой отдельно фиксируется retry_at; отказ SQL не отправляет команду и сохраняет очередь/дату.
* Пустая очередь завершается без commit hook. retry_at отодвигается на5с; tick каждые10с, до16 команд за проход.
* Расшифровка стартует после commit decrypting=1. До commit метаданных завершение остаётся у модуля:
* таймер повторяет SQL без нового worker; не более 16 активных/ожидающих завершения файлов на instance.
* quiesce останавливает повторы, destroy после workers освобождает также отложенные завершения.
* Незавершённый rollback отключает модуль и запрашивает остановку ядра владельцем вне callback. */
#ifndef CHAT_ATTACHMENT_H
#define CHAT_ATTACHMENT_H
#include "../media_async/attachment.h"
#include "../media_async/encrypted_file.h"
#ifdef __cplusplus
extern "C" {
#endif
struct UTUN_INSTANCE;
// ── Жизненный цикл модуля ──
// Подключить таблицы, router-сервис и обработку сохранённых задач; 0/-1. Внешняя транзакция запрещена.
int chat_attachment_init(struct UTUN_INSTANCE* inst);
// Запретить новые подготовки и остановить таймер; запущенные workers завершаются отдельно.
void chat_attachment_quiesce(struct UTUN_INSTANCE* inst);
// После workers убрать незавершённые подготовки; открытая транзакция откладывает recovery, сохраняя файлы.
void chat_attachment_destroy(struct UTUN_INSTANCE* inst);
// ── Отправка и учёт вложений ──
/* Асинхронно отправить подготовленный файл; channel — десятичный ID, reply — 32 байта ID ответа либо нули.
* Аргументы копируются. 0 — задача принята, source передан задаче и будет удалён даже при ошибке подготовки.
* -1 — отказ до принятия, source остаётся у вызывающего, события MSG_SUBMITTED здесь нет.
* Ключ/UUID/метаданные фиксируются собственной SQL-транзакцией до передачи source и запуска worker.
* Внешняя транзакция запрещена и остаётся нетронутой при отказе. Ошибка rollback с открытой транзакцией
* запрещает новые задачи модуля и запрашивает остановку ядра; уничтожение выполняет владелец вне callback.
* Ненулевой request возвращается в единственном CHAT_EVT_MSG_SUBMITTED; отказ media_async_submit может
* дать его синхронно, до возврата 0. Commit не усиливает установленную ядром политику SQLite synchronous. */
/* type проверяется encrypted_file_validate_type до выделения задачи, генерации UUID/ключа и записи в БД. */
int chat_attachment_send(struct UTUN_INSTANCE* inst, const char* channel, const char* source,
const struct attachment_info* info, const char* type, const uint8_t reply[32], uint64_t request);
// Прочитать UUID из канонического base64-префикса тела медиа; 0/-1, id меняется только при успехе. Подпись проверяет вызывающий.
int chat_attachment_identity(const char* body, size_t length, uint8_t id[16]);
/* Собственной транзакцией связать авторский ключ с ID сообщения и SHA256 контейнера до публикации; 0/-1.
* Массивы копируются в БД. Повтор той же пары допустим, её изменение запрещено; отказ сохраняет прежние поля.
* Внешняя транзакция отклоняется без изменений; все SQL-этапы и commit проверяются. */
int chat_attachment_bind(struct UTUN_INSTANCE* inst, const char* channel, const uint8_t id[16],
const uint8_t message[32], const uint8_t hash[32]);
/* Учесть проверенное db_sync сообщение собственной транзакцией, не меняя ключ/состояние существующей идентичности.
* 0 — записано/точный дубликат/обычное сообщение, -1 — SQL/OOM-отказ для повтора, -2 — неверный manifest/коллизия.
* Внешняя транзакция запрещена. Подпись проверяет вызывающий; JSON заимствован до возврата. */
int chat_attachment_observe(struct UTUN_INSTANCE* inst, const char* channel, const uint8_t message[32],
uint64_t author, const char* json, size_t length);
// ── Получение файла и выдача доступа ──
/* После загрузки/наличия сохранённого контейнера: своей транзакцией сохранить downloaded и policy wanted.
* 0/-1; запись observe обязательна. Повтор неизменного состояния не даёт события. Криптографию проверит worker.
* verified_download!=0 — новая проверенная передача, также сбрасывает прежний error; 0 — найденный cache, error сохраняется.
* Внешняя транзакция запрещена, SQL-отказ сохраняет прежние поля, событие — после commit. */
int chat_attachment_downloaded(struct UTUN_INSTANCE* inst, const char* channel, const uint8_t message[32], int verified_download);
/* Ручная загрузка, включая storage: одной транзакцией установить wanted, сбросить error и ready отсутствующего cache.
* 0/-1; запись observe обязательна. Внешняя транзакция запрещена, отказ сохраняет прежние поля. */
int chat_attachment_want(struct UTUN_INSTANCE* inst, const char* channel, const uint8_t message[32]);
/* Сохранить решение автора по ожидающему запросу peer: approve!=0 — выдать ключ, 0 — отказать.
* 0 — собственная транзакция решения+outbox завершена, затем послано одно уведомление изменения;
* -1 — ошибка/нет прав или ожидающего запроса, прежнее состояние сохранено. Доставка идёт позже.
* Внешняя транзакция отклоняется без изменений; проверка прав выполняется внутри собственной.
* Открытая после отказа rollback транзакция требует остановки/закрытия БД владельцем после poll. */
int chat_attachment_decide(struct UTUN_INSTANCE* inst, const char* channel, const uint8_t message[32], uint64_t peer, int approve);
// ── Команда интерфейса ──
struct chat_attachment_decision {
struct UTUN_INSTANCE* inst;
char channel[32];
uint8_t message[32];
uint64_t peer;
int approve;
};
// arg — u_malloc/u_calloc chat_attachment_decision, освобождается здесь; успех уже уведомлён decide, ошибка — событие с success=0.
void chat_attachment_decision_trampoline(void* arg);
// ── Локальное удаление канала ──
/* После commit удаления канала убрать собственные UUID.file; 0/-1, при I/O-ошибке можно повторить.
* Ключи/запросы/outbox удаляет SQLite-trigger атомарно с channels; SQL-отказ сохраняет все записи.
* Внешняя транзакция или существующий канал запрещают файловую очистку; завершения workers видят удаление через БД. */
int chat_attachment_delete_channel(struct UTUN_INSTANCE* inst, const char* channel);
#ifdef __cplusplus
}
#endif
#endif