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.
 
 
 
 
 
 

151 lines
5.4 KiB

#ifndef DB_MANAGER_H
#define DB_MANAGER_H
#include <sqlite3.h>
#include <QString>
#include <QList>
#include <QMap>
#include <QObject>
#include <cstdint>
struct ChannelRow {
QString channelId;
QString name;
quint64 ownerNodeId = 0;
bool isDm = false;
QByteArray x25519_pubkey;
QByteArray x25519_privkey;
QByteArray ed25519_pubkey;
QByteArray ed25519_privkey;
QByteArray signature; // Ed25519 подпись всех полей записи privkey канала
qint64 lastReadMsgId = 0;
qint64 lastPosMsgId = 0;
qint64 createdAt = 0;
};
struct MessageRow {
qint64 id = 0;
quint64 authorNodeId = 0;
QString contentType;
QByteArray data;
qint64 timestamp = 0;
uint64_t datahash = 0;
QByteArray chainHash;
QByteArray signature;
bool isOutgoing = false;
bool isRead = false;
};
struct AccountRow {
quint64 nodeId = 0;
QString displayName;
QString avatarColor;
QString avatarLetter;
bool isContact = true;
};
struct NodeAddr {
quint64 nodeId = 0;
int family = 0;
int protocol = 0; // битмаска: 1=UDP, 2=TCP, 3=TCP+UDP
QByteArray address;
quint16 port = 0;
int rtt = 0;
bool isNat = false;
};
class DbManager : public QObject {
Q_OBJECT
public:
explicit DbManager(const QString& path, QObject* parent = nullptr);
~DbManager() override;
bool isOpen() const { return m_db != nullptr; }
quint64 myNodeId() const { return m_myNodeId; }
/* ── Каналы ── */
QList<ChannelRow> getChannels() const;
bool createChannel(const QString& chId, const QString& name,
quint64 ownerNodeId = 0,
const QByteArray& x25519pub = {}, const QByteArray& x25519priv = {},
const QByteArray& ed25519pub = {}, const QByteArray& ed25519priv = {});
bool deleteChannel(const QString& chId);
/* ── Сообщения (UI) ── */
QList<MessageRow> getMessages(const QString& chId, int limit = 50) const;
bool insertMessage(const QString& chId, quint64 nodeId,
const QString& contentType, const QByteArray& data,
qint64 timestamp, bool isOutgoing,
uint64_t* outDatahash, QByteArray* outChainHash);
/* ── Участники канала ── */
bool addPeer(const QString& chId, quint64 nodeId,
const QByteArray& joinSig, const QByteArray& creatorSig,
const QString& comment = {});
bool removePeer(const QString& chId, quint64 nodeId);
/* ── Узлы ── */
bool upsertNode(quint64 nodeId, const QString& name,
const QByteArray& x25519pub, const QByteArray& ed25519pub);
bool addNodeAddress(quint64 nodeId, int family, int protocol,
const QByteArray& addr, quint16 port, bool isNat);
QByteArray loadNodeInfo(quint64 nodeId) const;
QList<quint64> getOnlinePeers() const;
QByteArray getNodeEdPub(quint64 nodeId) const;
QList<NodeAddr> getOnlinePeerAddresses(quint64 excludeNodeId) const;
/* ── Аккаунты ── */
QList<AccountRow> getAccounts(bool contactsOnly = false) const;
AccountRow getAccount(quint64 nodeId) const;
/* ── UI state ── */
QString getUiState(const QString& key) const;
void setUiState(const QString& key, const QString& value);
/* ── Sync-операции (вызываются gui_bridge, в GUI-потоке) ── */
QByteArray syncListChannels() const;
QByteArray syncCount(const QString& chId) const;
QByteArray syncChainHashAt(const QString& chId, uint32_t pos) const;
QByteArray syncInsert(const QString& chId, const QByteArray& recData);
QByteArray syncCursorOpen(const QString& chId);
QByteArray syncCursorNext(uint32_t cursorId);
void syncCursorClose(uint32_t cursorId);
QByteArray syncMarkSent(const QString& chId, quint64 ts, quint64 dh, quint64 myNodeId);
QByteArray syncTtlDelete(const QString& chId, quint64 myNodeId, quint64 cutoffUs);
QByteArray syncListPeers(const QString& chId) const;
/* ── Уведомления из uasync ── */
void onSyncMessageReceived(const QString& chId);
void setNodeOnline(quint64 nodeId, bool online);
void setUasyncInstance(void* ua) { m_ua = ua; }
void* uasyncInstance() const { return m_ua; }
/* ── seed ── */
void seedStubData();
private:
void initTables();
sqlite3_stmt* prepareOrNull(const char* sql) const;
static QString colText(sqlite3_stmt* stmt, int col);
static QByteArray colBlob(sqlite3_stmt* stmt, int col);
QString msgTableName(const QString& chId) const;
QString peersTableName(const QString& chId) const;
static QString sanitizeTableName(const QString& chId);
static uint64_t computeDatahash(const QByteArray& data);
static QByteArray computeChainHash(const QByteArray& prevChain,
qint64 timestamp, uint64_t datahash);
QByteArray getLastChainHash(const QString& chId) const;
sqlite3* m_db = nullptr;
quint64 m_myNodeId = 0;
void* m_ua = nullptr;
/* Кэш открытых курсоров для sync-операций */
mutable QMap<uint32_t, sqlite3_stmt*> m_cursors;
mutable uint32_t m_nextCursorId = 1;
};
#endif