code wiki / (root) / nx_metainfo.nx

nx_metainfo.nx source

↩ module page · 65 lines · 2450 B

1// nx_metainfo.nx -- .torrent metainfo loader (bits-up), reuses bencode + sha1. 2// 3// module: nishi-core.torrent.metainfo 4// depends: nx_syscalls.nx, nx_bencode.nx, nx_sha1.nx 5// capability: CORE_COMPUTE 6// wired_status: FULLY_WIRED 7// 8// Parse a .torrent: announce URL, info dict (name, piece length, total length), 9// and the INFO-HASH = SHA-1 over the raw bencoded `info` dict bytes (BEP-3) -- 10// the identity used in tracker announces + peer handshakes. Reuses nx_bencode 11// (parse) + sha1 (hash); zero new crypto. The info-dict byte bounds come from 12// nx_bc_skip so the hash is over the exact on-wire bytes. 13 14import "nx_syscalls.nx" 15import "nx_bencode.nx" 16import "nx_sha1.nx" 17 18struct NxMetainfo { 19 announce_off: i64, 20 announce_len: i64, 21 name_off: i64, 22 name_len: i64, 23 piece_length: i64, 24 total_length: i64, 25 info_off: i64, 26 info_len: i64, 27} 28const NX_METAINFO_BYTES: i64 = 64 // 8 * 8 29const NX_MI_OK: i64 = 1 30const NX_MI_BAD: i64 = 0 31 32// Parse metainfo buf[0..n) into mi; write the 20-byte info-hash to ih_out. 33func nx_metainfo_parse(buf: *u8, n: i64, mi: *NxMetainfo, ih_out: *u8) -> i64 { 34 if nx_bc_type(buf, 0, n) != NX_BC_DICT { return NX_MI_BAD } 35 let so: *i64 = sys_mmap(8) as *i64 36 let sl: *i64 = sys_mmap(8) as *i64 37 let iv: *i64 = sys_mmap(8) as *i64 38 39 let ann: i64 = nx_bc_dict_get(buf, 0, n, "announce", 8) 40 if ann < 0 { return NX_MI_BAD } 41 if nx_bc_str(buf, ann, n, so, sl) < 0 { return NX_MI_BAD } 42 mi.announce_off = so[0] 43 mi.announce_len = sl[0] 44 45 let info: i64 = nx_bc_dict_get(buf, 0, n, "info", 4) 46 if info < 0 { return NX_MI_BAD } 47 let info_end: i64 = nx_bc_skip(buf, info, n) 48 if info_end < 0 { return NX_MI_BAD } 49 mi.info_off = info 50 mi.info_len = info_end - info 51 // info-hash = SHA-1 of the raw info-dict bytes 52 sha1(((buf as i64) + info) as *u8, mi.info_len, ih_out) 53 54 let nm: i64 = nx_bc_dict_get(buf, info, n, "name", 4) 55 if nm >= 0 { nx_bc_str(buf, nm, n, so, sl); mi.name_off = so[0]; mi.name_len = sl[0] } 56 else { mi.name_off = 0 - 1; mi.name_len = 0 } 57 58 let pl: i64 = nx_bc_dict_get(buf, info, n, "piece length", 12) 59 if pl >= 0 { nx_bc_int(buf, pl, n, iv); mi.piece_length = iv[0] } else { mi.piece_length = 0 } 60 61 let ln: i64 = nx_bc_dict_get(buf, info, n, "length", 6) 62 if ln >= 0 { nx_bc_int(buf, ln, n, iv); mi.total_length = iv[0] } else { mi.total_length = 0 } 63 64 return NX_MI_OK 65}