73 lines
3.8 KiB
C
73 lines
3.8 KiB
C
/* Файловый протокол участников CHAT-группы. Все числа на проводе little-endian.
|
|
* Группа и подписанный отправитель приходят от router; owner — UID каталога.
|
|
* version — непрозрачный снимок объекта, upload — случайный ID временного файла.
|
|
* Нулевая version в BEGIN означает создание; замена требует version из STAT.
|
|
* LIST: cursor — число уже выданных записей; version фиксирует снимок каталога.
|
|
* READ/WRITE: offset и size задают диапазон; WRITE.data_len обязан равняться size.
|
|
* COMMIT/MKDIR/RENAME/REMOVE: RESPONSE BUSY.cursor — срок до освобождения квитанции в0.1мс;
|
|
* 0 означает обычный повтор через5с. Общий клиентский срок120с не продлевается.
|
|
* Данные LIST — последовательность entry: name_len:2,type:1,size:8,mtime:8,version:16,name.
|
|
* Токены меняются при перезапуске сервера. Никаких ABI-зависимых структур в wire. */
|
|
#ifndef MEMBER_FILES_PROTOCOL_H
|
|
#define MEMBER_FILES_PROTOCOL_H
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define MF_BLOCK_SIZE 8192
|
|
#define MF_PROTOCOL_VERSION 4
|
|
#define MF_PATH_MAX 1024
|
|
#define MF_NAME_MAX 255
|
|
#define MF_WIRE_HEADER 125
|
|
#define MF_WIRE_MAX (MF_WIRE_HEADER + 2 * MF_PATH_MAX + MF_BLOCK_SIZE)
|
|
#define MF_ENTRY_HEADER 35
|
|
#define MF_QUOTA_BYTES 40 /* used/limit/reserved в байтах, files/directories; пять u64 LE */
|
|
#define MF_AVATAR_MAX_BYTES (1024 * 1024)
|
|
#define MF_AVATAR_ORIGINAL_MAX_BYTES (32 * 1024 * 1024)
|
|
#define MF_AVATAR_MANIFEST_MAX_BYTES 4096
|
|
int mf_avatar_file_valid(const char* file);
|
|
int mf_avatar_manifest_valid(const char* file);
|
|
uint64_t mf_avatar_file_limit(const char* file);
|
|
#define MF_IDLE_TB 100000ULL /* 10 секунд */
|
|
#define MF_REPLAY_TB 1200000ULL /* Окно повторов запроса/успешной квитанции:120с. */
|
|
#define MF_REQUEST 1
|
|
#define MF_RESPONSE 2
|
|
#define MF_FILE 1
|
|
#define MF_DIRECTORY 2
|
|
|
|
/* MF_REMOVE — системный макрос Win32; для удаления файла/каталога используем отдельное имя. */
|
|
enum mf_command {
|
|
MF_LIST = 1, MF_STAT, MF_READ, MF_BEGIN_WRITE, MF_WRITE, MF_COMMIT, MF_ABORT, MF_MKDIR, MF_RENAME, MF_REMOVE_PATH,
|
|
MF_STREAM_WRITE, MF_STREAM_READ, MF_STREAM_DATA, MF_STREAM_END, MF_STREAM_CANCEL, MF_QUOTA
|
|
};
|
|
enum mf_status {
|
|
MF_OK, MF_ACCESS_DENIED, MF_NOT_FOUND, MF_INVALID_PATH, MF_INVALID_RANGE, MF_EXISTS,
|
|
MF_BUSY, MF_STALE, MF_NO_SPACE, MF_IO_ERROR, MF_BAD_PACKET, MF_HASH_MISMATCH, MF_CANCELLED, MF_TIMEOUT, MF_DIRECTORY_NOT_EMPTY
|
|
};
|
|
|
|
struct mf_message {
|
|
uint8_t kind, command, type, more;
|
|
uint16_t status;
|
|
uint64_t request_id, owner, offset, size, cursor, mtime;
|
|
uint8_t version[16], upload[16], hash[32];
|
|
char path[MF_PATH_MAX + 1], target[MF_PATH_MAX + 1];
|
|
uint32_t data_len;
|
|
uint8_t data[MF_BLOCK_SIZE];
|
|
};
|
|
|
|
uint64_t mf_get64(const uint8_t* p);
|
|
void mf_put64(uint8_t* p, uint64_t value);
|
|
int mf_zero(const uint8_t* p, size_t n);
|
|
/* Проверка UTF-8 и переносимых компонентов. Пустой путь допустим только для корня. */
|
|
int mf_path_valid(const char* path, int root_allowed);
|
|
int mf_encode(const struct mf_message* message, uint8_t* wire, size_t capacity);
|
|
int mf_decode(const uint8_t* wire, size_t length, struct mf_message* message);
|
|
const char* mf_status_text(int status);
|
|
const char* mf_command_text(int command);
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif
|