Reject failed feedback page and hash reads and report transaction error codes
This commit is contained in:
1 parent
fc94fa0bfd
commit
96a3d05c74
1 file changed
+35
-13
+35
-13
@@ -258,13 +258,17 @@ static void fb_committed(struct UTUN_INSTANCE* inst, const char* channel, const
|
||||
static int fb_finish_transaction(struct UTUN_INSTANCE* inst, const char* channel, int result) {
|
||||
sqlite3* db = inst->topo_sqlite_db;
|
||||
if (result >= 0) {
|
||||
if (sqlite3_exec(db, "COMMIT /* feedback update */", NULL, NULL, NULL) == SQLITE_OK) return result;
|
||||
fb_db_error(inst, channel, "commit");
|
||||
int rc = sqlite3_exec(db, "COMMIT /* feedback update */", NULL, NULL, NULL);
|
||||
if (rc == SQLITE_OK) return result;
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: commit failed ch=%s rc=%d (%s) db=%s", channel, rc, sqlite3_errstr(rc), sqlite3_errmsg(db));
|
||||
}
|
||||
if (!sqlite3_get_autocommit(db) && sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) != SQLITE_OK)
|
||||
fb_db_error(inst, channel, "rollback");
|
||||
if (!sqlite3_get_autocommit(db)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: transaction remains open ch=%s; owner must stop core and close DB after callback", channel);
|
||||
int rc = sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL);
|
||||
if (rc != SQLITE_OK) DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: rollback failed ch=%s rc=%d (%s) db=%s",
|
||||
channel, rc, sqlite3_errstr(rc), sqlite3_errmsg(db));
|
||||
}
|
||||
if (!sqlite3_get_autocommit(db)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: transaction remains open ch=%s; requesting core stop and owner DB close after callback", channel);
|
||||
utun_instance_stop(inst);
|
||||
}
|
||||
return -1;
|
||||
@@ -332,16 +336,22 @@ finish:
|
||||
static int fb_page(void* ctx, const char* channel, uint64_t prefix, int av, const merkle_key_t* after,
|
||||
uint8_t* data, size_t* len, merkle_key_t* next, int* more) {
|
||||
struct UTUN_INSTANCE* inst = ctx; char table[40], sql[384]; uint64_t id;
|
||||
if (fb_table(inst, channel, table, &id) < 0 || *len < 2) {
|
||||
if (fb_table(inst, channel, table, &id) < 0 || !len || *len < 2 || !after || !data || !next || !more) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: invalid page capacity"); return -1;
|
||||
}
|
||||
merkle_key_t cursor = *after; memset(next, 0, sizeof(*next)); *more = 0;
|
||||
snprintf(sql, sizeof(sql), "SELECT message_id,node_id,kind,ver,data,signature,record_key,bucket FROM %s"
|
||||
" WHERE bucket=? AND (?=0 OR record_key>?) ORDER BY record_key", table);
|
||||
sqlite3_stmt* st = NULL;
|
||||
if (sqlite3_prepare_v2(inst->topo_sqlite_db, sql, -1, &st, NULL) != SQLITE_OK) return fb_db_error(inst, channel, "page");
|
||||
sqlite3_bind_int64(st, 1, (sqlite3_int64)(prefix >> 39)); sqlite3_bind_int(st, 2, av);
|
||||
sqlite3_bind_blob(st, 3, cursor.bytes, 32, SQLITE_STATIC);
|
||||
int rc = sqlite3_prepare_v2(inst->topo_sqlite_db, sql, -1, &st, NULL);
|
||||
if (rc == SQLITE_OK) rc = sqlite3_bind_int64(st, 1, (sqlite3_int64)(prefix >> 39));
|
||||
if (rc == SQLITE_OK) rc = sqlite3_bind_int(st, 2, av);
|
||||
if (rc == SQLITE_OK) rc = sqlite3_bind_blob(st, 3, cursor.bytes, 32, SQLITE_STATIC);
|
||||
if (rc != SQLITE_OK) {
|
||||
int final = sqlite3_finalize(st);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: page query failed ch=%s rc=%d finalize=%d db=%s",
|
||||
channel, rc, final, sqlite3_errmsg(inst->topo_sqlite_db)); return -1;
|
||||
}
|
||||
size_t off = 2; unsigned count = 0; int step, result = 0;
|
||||
while ((step = sqlite3_step(st)) == SQLITE_ROW) {
|
||||
struct chat_feedback_record r; uint8_t wire[FB_WIRE_MAX];
|
||||
@@ -358,7 +368,11 @@ static int fb_page(void* ctx, const char* channel, uint64_t prefix, int av, cons
|
||||
memcpy(next->bytes, sqlite3_column_blob(st, 6), 32);
|
||||
}
|
||||
if (result == 0 && !*more && step != SQLITE_DONE) result = fb_db_error(inst, channel, "page step");
|
||||
sqlite3_finalize(st); data[0] = count >> 8; data[1] = count & 255; *len = off; return result;
|
||||
int final = sqlite3_finalize(st);
|
||||
if (final != SQLITE_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: page finalize failed ch=%s rc=%d", channel, final); result = -1;
|
||||
}
|
||||
data[0] = count >> 8; data[1] = count & 255; *len = off; return result;
|
||||
}
|
||||
|
||||
/* Хеширует подписанные тела: разные валидные подписи одного тела не меняют корень. */
|
||||
@@ -370,8 +384,13 @@ static int fb_hash(void* ctx, const char* channel, uint8_t level, uint64_t prefi
|
||||
snprintf(sql, sizeof(sql), "SELECT message_id,node_id,kind,ver,data,signature,record_key,bucket"
|
||||
" FROM %s WHERE bucket=? ORDER BY record_key", table);
|
||||
sqlite3_stmt* st = NULL;
|
||||
if (sqlite3_prepare_v2(inst->topo_sqlite_db, sql, -1, &st, NULL) != SQLITE_OK) return fb_db_error(inst, channel, "hash");
|
||||
sqlite3_bind_int64(st, 1, (sqlite3_int64)(prefix >> 39));
|
||||
int rc = sqlite3_prepare_v2(inst->topo_sqlite_db, sql, -1, &st, NULL);
|
||||
if (rc == SQLITE_OK) rc = sqlite3_bind_int64(st, 1, (sqlite3_int64)(prefix >> 39));
|
||||
if (rc != SQLITE_OK) {
|
||||
int final = sqlite3_finalize(st);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: hash query failed ch=%s rc=%d finalize=%d db=%s",
|
||||
channel, rc, final, sqlite3_errmsg(inst->topo_sqlite_db)); return -1;
|
||||
}
|
||||
int step, count = 0;
|
||||
while ((step = sqlite3_step(st)) == SQLITE_ROW) {
|
||||
struct chat_feedback_record r; uint8_t wire[FB_WIRE_MAX];
|
||||
@@ -384,7 +403,10 @@ static int fb_hash(void* ctx, const char* channel, uint8_t level, uint64_t prefi
|
||||
}
|
||||
count++;
|
||||
}
|
||||
sqlite3_finalize(st);
|
||||
int final = sqlite3_finalize(st);
|
||||
if (final != SQLITE_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: hash finalize failed ch=%s rc=%d", channel, final); return -1;
|
||||
}
|
||||
if (count >= 0 && step != SQLITE_DONE) return fb_db_error(inst, channel, "hash step");
|
||||
return count;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user