You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
3.7 KiB
108 lines
3.7 KiB
/* |
|
* chat_core_priv.h — внутренний заголовок для под-модулей chat_core |
|
* |
|
* Предоставляет доступ к глобальному состоянию g_cc и общим хелперам. |
|
* Не включать извне chat/ — только для chat_core*.c. |
|
*/ |
|
|
|
#ifndef CHAT_CORE_PRIV_H |
|
#define CHAT_CORE_PRIV_H |
|
|
|
#include "chat_core.h" |
|
|
|
#include "db_sync.h" |
|
#include "../../lib/debug_config.h" |
|
|
|
#include <sqlite3.h> |
|
#include <string.h> |
|
#include <stdio.h> |
|
#include <stdint.h> |
|
|
|
#define CC_ID "chat_core" |
|
|
|
/* ── Base64 encode/decode (URL-safe, used for msg "d" field prefix) ── */ |
|
|
|
static const char B64_ALPHABET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; |
|
|
|
static inline int b64_decode_char(char c) { |
|
if (c >= 'A' && c <= 'Z') return c - 'A'; |
|
if (c >= 'a' && c <= 'z') return c - 'a' + 26; |
|
if (c >= '0' && c <= '9') return c - '0' + 52; |
|
if (c == '-') return 62; |
|
if (c == '_') return 63; |
|
return -1; |
|
} |
|
|
|
static inline size_t b64_encode(const uint8_t* src, size_t src_len, char* dst, size_t dst_cap) { |
|
size_t out = 0; |
|
for (size_t i = 0; i < src_len; i += 3) { |
|
if (out + 4 > dst_cap) break; |
|
uint32_t v = (uint32_t)src[i] << 16; |
|
if (i + 1 < src_len) v |= (uint32_t)src[i + 1] << 8; |
|
if (i + 2 < src_len) v |= (uint32_t)src[i + 2]; |
|
dst[out++] = B64_ALPHABET[(v >> 18) & 0x3F]; |
|
dst[out++] = B64_ALPHABET[(v >> 12) & 0x3F]; |
|
dst[out++] = (i + 1 < src_len) ? B64_ALPHABET[(v >> 6) & 0x3F] : '='; |
|
dst[out++] = (i + 2 < src_len) ? B64_ALPHABET[v & 0x3F] : '='; |
|
} |
|
return out; |
|
} |
|
|
|
static inline size_t b64_decode(const char* src, size_t src_len, uint8_t* dst, size_t dst_cap) { |
|
size_t out = 0; |
|
int vals[4]; size_t vi = 0; |
|
for (size_t i = 0; i < src_len && out < dst_cap; i++) { |
|
if (src[i] == '=') break; |
|
int v = b64_decode_char(src[i]); |
|
if (v < 0) continue; |
|
vals[vi++] = v; |
|
if (vi == 4) { |
|
dst[out++] = (uint8_t)((vals[0] << 2) | (vals[1] >> 4)); |
|
if (out < dst_cap) dst[out++] = (uint8_t)((vals[1] << 4) | (vals[2] >> 2)); |
|
if (out < dst_cap) |
|
dst[out++] = (uint8_t)((vals[2] << 6) | vals[3]); |
|
vi = 0; |
|
} |
|
} |
|
if (vi == 3 && out < dst_cap) { |
|
dst[out++] = (uint8_t)((vals[0] << 2) | (vals[1] >> 4)); |
|
if (out < dst_cap) dst[out++] = (uint8_t)((vals[1] << 4) | (vals[2] >> 2)); |
|
} else if (vi == 2 && out < dst_cap) { |
|
dst[out++] = (uint8_t)((vals[0] << 2) | (vals[1] >> 4)); |
|
} |
|
return out; |
|
} |
|
|
|
/* ── Глобальное состояние (определено в chat_core.c) ── */ |
|
|
|
struct chat_core_ctx { |
|
struct UTUN_INSTANCE* inst; |
|
sqlite3* db; |
|
char db_path[512]; |
|
uint8_t shared_db; |
|
uint64_t my_node_id; |
|
struct DB_SYNC_INSTANCE** si; |
|
char** si_ch_id; |
|
int si_count, si_capacity; |
|
uint8_t initialized; |
|
}; |
|
|
|
extern struct chat_core_ctx g_cc; |
|
|
|
/* ── Хелперы ── */ |
|
|
|
void sanitize_ch_id(const char* ch_id, char* out, size_t out_sz); |
|
void msg_table_name(const char* ch_id, char* buf, size_t sz); |
|
void peers_table_name(const char* ch_id, char* buf, size_t sz); |
|
int db_exec(const char* sql); |
|
|
|
/* ── db_sync registry (chat_core.c) ── */ |
|
|
|
struct DB_SYNC_INSTANCE* si_find(const char* ch_id); |
|
void si_register(struct DB_SYNC_INSTANCE* si, const char* ch_id); |
|
|
|
/* ── db_sync callback (chat_msg.c) ── */ |
|
|
|
void on_msg_inserted(struct DB_SYNC_INSTANCE* si, uint64_t record_ts, const char* data, size_t len, uint64_t author, void* arg); |
|
|
|
#endif /* CHAT_CORE_PRIV_H */
|
|
|