diff --git a/src/media_delivery/media_delivery.c b/src/media_delivery/media_delivery.c index 7236451e..ae8a7b17 100644 --- a/src/media_delivery/media_delivery.c +++ b/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); diff --git a/tests/test_media_delivery_full.c b/tests/test_media_delivery_full.c index 0670e583..1459a07c 100644 --- a/tests/test_media_delivery_full.c +++ b/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); } }