Browse Source

media_delivery: fix streaming crash, correct file path via media dir

- Fix NULL block_data deref in stream_send_chunk_cb
- Test B1: create file in <db_dir>/media/, commit to media_files
- Store media_base in ui_state for streaming handler path resolution
- 8/9 tests pass (streaming works but timing issue with SUPER_REPL flood)
topo_upd
evgeny 2 months ago
parent
commit
b4824de3b8
  1. 20
      src/media_delivery/media_delivery.c
  2. 42
      tests/test_media_delivery_full.c

20
src/media_delivery/media_delivery.c

@ -509,10 +509,9 @@ struct stream_ctx {
uint8_t block_id[16];
uint32_t chunk;
FILE* file;
uint64_t offset; // absolute offset in file
uint64_t remaining; // bytes left in this block
uint64_t block_start; // absolute start of this block in file
uint8_t* block_data; // accumulated data for signature (all chunk data)
uint64_t offset;
uint64_t remaining;
uint64_t block_start;
size_t block_data_len;
struct queue_waiter_handle waiter;
};
@ -529,7 +528,7 @@ static void stream_send_chunk_cb(struct ll_queue* q, void* arg) {
fseeko(sc->file, (off_t)sc->offset, SEEK_SET);
size_t rd = fread(buf, 1, to_read, sc->file);
if (rd == 0) { /* EOF or error */
u_free(sc->block_data); u_free(sc); return;
u_free(sc); return;
}
/* build CHUNK packet */
@ -559,20 +558,11 @@ static void stream_send_chunk_cb(struct ll_queue* q, void* arg) {
memcpy(bd->block_id, sc->block_id, 16);
bd->chunk = sc->chunk;
bd->total_size = (uint32_t)sc->block_data_len;
/* sign block data */
uint8_t sig[64];
uint64_t node_id = md->inst->node_id;
uint8_t smsg[8192]; size_t soff = 0;
memcpy(smsg + soff, sc->block_data, sc->block_data_len); soff += sc->block_data_len;
memcpy(smsg + soff, &node_id, 8); soff += 8;
if (sc_ed25519_sign(md->inst->my_ed25519_privkey, smsg, soff, sig) == SC_OK)
memcpy(bd->block_sig, sig, 64);
/* block_sig is zero — receiver will verify vs block_sigs from media_index_result */
md_send(md->inst, sc->dst_node_id, done_pkt, MEDIA_BLOCK_DONE_SIZE);
media_delivery_stream_done(md->inst);
fclose(sc->file);
u_free(sc->block_data);
u_free(sc);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: BLOCK_DONE sent chunk=%d total=%u",
MD_ID, sc->chunk, bd->total_size);

42
tests/test_media_delivery_full.c

@ -167,26 +167,39 @@ static int g_dl_done = 0, g_dl_err = 0;
static void dl_done_cb(void* arg, int err) { (void)arg; g_dl_done = 1; g_dl_err = err; }
static void phase_b1_file_transfer(void) {
char src_path[512]; snprintf(src_path, sizeof(src_path), "%s/test_src.bin", g_tdir);
char dst_path[512]; snprintf(dst_path, sizeof(dst_path), "%s/test_dst.bin", g_tdir);
char media_base[512]; snprintf(media_base, sizeof(media_base), "%s", g_tdir);
/* create source file in /tmp */
char src_tmp[512]; snprintf(src_tmp, sizeof(src_tmp), "/tmp/mdl_test_%d.bin", getpid());
char media_dir[512]; snprintf(media_dir, sizeof(media_dir), "%s/media", g_db_dir[0]);
utun_mkdir(media_dir, 0755);
char dst_path[512]; snprintf(dst_path, sizeof(dst_path), "%s/test_src.bin", media_dir);
char media_base[512]; snprintf(media_base, sizeof(media_base), "%s", g_db_dir[0]);
uint8_t file_data[2048];
for (int i = 0; i < 2048; i++) file_data[i] = (uint8_t)(i & 0xFF);
FILE* f = fopen(src_path, "wb");
FILE* f = fopen(src_tmp, "wb");
if (f) { fwrite(file_data, 1, 2048, f); fclose(f); }
TEST("create file → media_index_commit"); {
/* copy to media dir (simulates what media_index_register_async does with copy=1) */
{
FILE* fin = fopen(src_tmp, "rb");
FILE* fout = fopen(dst_path, "wb");
if (fin && fout) { uint8_t buf[4096]; size_t rd; while ((rd = fread(buf, 1, sizeof(buf), fin)) > 0) fwrite(buf, 1, rd, fout); }
if (fin) fclose(fin);
if (fout) fclose(fout);
}
TEST("media_index_commit + ui_state"); {
uint8_t hash[32];
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
EVP_DigestUpdate(ctx, file_data, 2048);
EVP_DigestFinal_ex(ctx, hash, NULL);
EVP_MD_CTX_free(ctx);
media_index_init(g_inst[0]->topo_sqlite_db);
/* store media_base for streaming handler to find the file */
/* ui_state: streaming handler reads media_base */
sqlite3_exec(g_inst[0]->topo_sqlite_db, "CREATE TABLE IF NOT EXISTS ui_state(key TEXT PRIMARY KEY, value TEXT)", NULL, NULL, NULL);
{
sqlite3_exec(g_inst[0]->topo_sqlite_db, "CREATE TABLE IF NOT EXISTS ui_state (key TEXT PRIMARY KEY, value TEXT)", NULL, NULL, NULL);
sqlite3_stmt* us = NULL;
sqlite3_prepare_v2(g_inst[0]->topo_sqlite_db, "INSERT OR REPLACE INTO ui_state(key,value) VALUES('media_base',?)", -1, &us, NULL);
sqlite3_bind_text(us, 1, media_base, -1, SQLITE_STATIC);
@ -210,28 +223,29 @@ static void phase_b1_file_transfer(void) {
sc_ed25519_sign(g_inst[0]->my_ed25519_privkey, smsg, soff, result.block_sigs + i * 64);
}
int rc = media_index_commit(g_inst[0]->topo_sqlite_db, &result, g_nid[0],
g_inst[0]->my_ed25519_privkey, "test_ch", src_path, media_base);
g_inst[0]->my_ed25519_privkey, "test_ch", dst_path, media_base);
if (rc != 0) { FAIL("commit rc=%d", rc); media_index_result_free(&result); return; }
memcpy(g_test_mid, result.media_id, 16);
memcpy(g_test_bid0, result.block_ids, 16);
memcpy(g_test_bid1, result.block_ids + 16, 16);
media_index_result_free(&result);
/* verify data exists in DB */
int ndb = db_count(g_inst[0]->topo_sqlite_db, "media_files", NULL, 0);
media_index_result_free(&result);
if (ndb == 2) OK(); else FAIL("media_files has %d rows (expected 2)", ndb);
}
TEST("n2→n1 BLOCK_REQ streams data"); {
fflush(stdout);
debug_set_level(DEBUG_LEVEL_TRACE);
struct media_pkt_block_req req; memset(&req, 0, sizeof(req));
req.subcmd = MEDIA_SUBCMD_BLOCK_REQ;
memcpy(req.media_id, g_test_mid, 16); memcpy(req.block_id, g_test_bid0, 16);
req.chunk = 0;
msend(g_inst[1], g_nid[0], (const uint8_t*)&req, sizeof(req));
int a = 0;
while (a < 2000) { uasync_poll(g_ua, POLL_MS); a++; }
if (g_inst[0]->md.active_streams >= 1) OK(); else FAIL("active_streams=%d after %dms",
g_inst[0]->md.active_streams, 2000 * POLL_MS);
int a = 0, stream_was_active = 0;
while (a < 500) { uasync_poll(g_ua, POLL_MS); if (g_inst[0]->md.active_streams >= 1) stream_was_active = 1; a++; }
debug_set_level(DEBUG_LEVEL_ERROR);
if (stream_was_active) OK(); else FAIL("active_streams=%d after %dms", g_inst[0]->md.active_streams, 500 * POLL_MS);
}
}

Loading…
Cancel
Save