Cvirtual_binary Caud_file::decode() { Cvirtual_binary d; int cb_audio = get_cb_sample() * get_c_samples(); switch (header().compression) { case 1: { byte* w = d.write_start(cb_audio); for (int chunk_i = 0; w != d.data_end(); chunk_i++) { const t_aud_chunk_header& header = *get_chunk_header(chunk_i); aud_decode_ws_chunk(get_chunk_data(chunk_i), reinterpret_cast<char*>(w), header.size_in, header.size_out); w += header.size_out; } } break; case 0x63: { aud_decode decode; decode.init(); byte* w = d.write_start(cb_audio); for (int chunk_i = 0; w != d.data_end(); chunk_i++) { const t_aud_chunk_header* header = get_chunk_header(chunk_i); if (!header) break; decode.decode_chunk(get_chunk_data(chunk_i), reinterpret_cast<short*>(w), header->size_out / get_cb_sample()); w += header->size_out; } } break; } return d; }
Cvirtual_binary Cxif_key::vdata(bool fast) const { Cvirtual_binary d; int size = get_size(); int external_size = get_external_size(); if (fast) { t_xif_header_fast& header = *reinterpret_cast<t_xif_header_fast*>(d.write_start(sizeof(t_xif_header_fast) + size + external_size)); header.id = file_id; header.version = file_version_fast; header.size_uncompressed = 0; header.size_compressed = size; header.size_external = external_size; byte* w = d.data_edit() + sizeof(t_xif_header_fast); save(w); external_save(w); assert(d.data_end() == w); return d; } Cvirtual_binary s; byte* w = s.write_start(size); save(w); unsigned long cb_d = s.size() + (s.size() + 999) / 1000 + 12; t_xif_header_fast& header = *reinterpret_cast<t_xif_header_fast*>(d.write_start(sizeof(t_xif_header_fast) + cb_d + external_size)); compress(d.data_edit() + sizeof(t_xif_header_fast), &cb_d, s.data(), s.size()); w = d.data_edit() + sizeof(t_xif_header_fast) + cb_d; external_save(w); header.id = file_id; header.version = file_version_fast; header.size_uncompressed = size; header.size_compressed = cb_d; header.size_external = external_size; d.size(sizeof(t_xif_header_fast) + cb_d + external_size); return d; }
Cvirtual_binary Cbig_file_write::write() { int cb_header = sizeof(t_big_header); int cb_d = sizeof(t_big_header); for (auto& i : m_index) { cb_header += sizeof(t_big_index_entry) + i.first.length() + 1; cb_d += sizeof(t_big_index_entry) + i.first.length() + 1 + i.second.size(); } Cvirtual_binary d; byte* w = d.write_start(cb_d); t_big_header& header = *reinterpret_cast<t_big_header*>(w); header.id = big_id; header.size = d.size(); header.mc_files = reverse(m_index.size()); header.mcb_header = reverse(cb_header); byte* w2 = w + cb_header; w += sizeof(t_big_header); for (auto& i : m_index) { t_big_index_entry& e = *reinterpret_cast<t_big_index_entry*>(w); e.offset = reverse(w2 - d.data()); e.size = reverse(i.second.size()); w += sizeof(t_big_index_entry); memcpy(w, i.first.c_str(), i.first.length() + 1); w += i.first.length() + 1; w2 += i.second.read(w2); } assert(w2 == d.data_end()); return d; }
int Cxif_key::load_key(const byte* data, int size) { const byte* read_p = data; const t_xif_header_fast& header = *reinterpret_cast<const t_xif_header_fast*>(read_p); if (size < sizeof(t_xif_header_old) || header.id != file_id || header.version != file_version_old && header.version != file_version_new && header.version != file_version_fast) return 1; int error = 0; if (header.version == file_version_old) { read_p += sizeof(t_xif_header_old) - 4; load_old(read_p); error = size != read_p - data; } else { unsigned long cb_d = header.size_uncompressed; if (cb_d) { Cvirtual_binary d; if (header.version == file_version_new) error = Z_OK != uncompress(d.write_start(cb_d), &cb_d, data + sizeof(t_xif_header_old), size - sizeof(t_xif_header_old)); else { if (memcmp(data + sizeof(t_xif_header_fast), "BZh", 3)) error = Z_OK != uncompress(d.write_start(cb_d), &cb_d, data + sizeof(t_xif_header_fast), header.size_compressed); else error = BZ_OK != BZ2_bzBuffToBuffDecompress(reinterpret_cast<char*>(d.write_start(cb_d)), reinterpret_cast<unsigned int*>(&cb_d), const_cast<char*>(reinterpret_cast<const char*>(data + sizeof(t_xif_header_fast))), header.size_compressed, 0, 0); } // d.export("c:/temp/xif data.bin"); if (!error) { read_p = d.data(); load_new(read_p); error = read_p != d.data_end(); if (header.version == file_version_fast && !error) { read_p = data + sizeof(t_xif_header_fast) + header.size_compressed; load_external(read_p); error = size != read_p - data; } } } else { read_p = data + (header.version == file_version_fast ? sizeof(t_xif_header_fast) : sizeof(t_xif_header_old)); load_new(read_p); load_external(read_p); error = size != read_p - data; } } return error; }
Cvirtual_binary Cbt_tracker_accounts::dump() const { int cb_d = 4; for (const_iterator i = begin(); i != end(); i++) cb_d += i->pre_dump(); Cvirtual_binary d; Cstream_writer w(d.write_start(cb_d)); w.write_int(4, size()); for (const_iterator i = begin(); i != end(); i++) i->dump(w); assert(w.w() == d.data_end()); return d; }
int main(int argc, char* argv[]) { time_t t = time(NULL); if (argc < 2) { std::cerr << "Usage: " << argv[0] << " <file> <tracker> [--v1]" << std::endl; return 1; } std::string tracker = argc >= 3 ? argv[2] : "udp://localhost:2710"; bool use_merkle = argc >= 4 ? strcmp(argv[3], "--v1") : true; // set to false for a non-merkle torrent insert(argv[1]); // use 1 mbyte pieces by default int cb_piece = 1 << 20; if (!use_merkle) { // find optimal piece size for a non-merkle torrent long long cb_total = 0; for (t_map::const_iterator i = g_map.begin(); i != g_map.end(); i++) cb_total += i->second.size; cb_piece = 256 << 10; while (cb_total / cb_piece > 4 << 10) cb_piece <<= 1; } Cbvalue files; std::string pieces; Cvirtual_binary d; byte* w = d.write_start(cb_piece); for (t_map::const_iterator i = g_map.begin(); i != g_map.end(); i++) { int f = open(i->second.name.c_str(), O_BINARY | O_RDONLY); if (!f) continue; long long cb_f = 0; std::string merkle_hash; int cb_d; if (use_merkle) { // calculate merkle root hash as explained in XBT Make Merkle Tree.cpp typedef std::map<int, std::string> t_map; t_map map; char d[1025]; while (cb_d = read(f, d + 1, 1024)) { if (cb_d < 0) break; *d = 0; std::string h = Csha1(const_memory_range(d, cb_d + 1)).read(); *d = 1; int i; for (i = 0; map.find(i) != map.end(); i++) { memcpy(d + 1, map.find(i)->second.c_str(), 20); memcpy(d + 21, h.c_str(), 20); h = Csha1(const_memory_range(d, 41)).read(); map.erase(i); } map[i] = h; cb_f += cb_d; } *d = 1; while (map.size() > 1) { memcpy(d + 21, map.begin()->second.c_str(), 20); map.erase(map.begin()); memcpy(d + 1, map.begin()->second.c_str(), 20); map.erase(map.begin()); map[0] = Csha1(const_memory_range(d, 41)).read(); } if (!map.empty()) merkle_hash = map.begin()->second; } else { // calculate piece hashes while (cb_d = read(f, w, d.data_end() - w)) { if (cb_d < 0) break; w += cb_d; if (w == d.data_end()) { pieces += Csha1(const_memory_range(d, w - d)).read(); w = d.data_edit(); } cb_f += cb_d; } } close(f); // add file to files key files.l(merkle_hash.empty() ? Cbvalue().d(bts_length, cb_f).d(bts_path, Cbvalue().l(base_name(i->second.name))) : Cbvalue().d(bts_merkle_hash, merkle_hash).d(bts_length, cb_f).d(bts_path, Cbvalue().l(base_name(i->second.name)))); } if (w != d) pieces += Csha1(const_memory_range(d, w - d)).read(); Cbvalue info; info.d(bts_piece_length, cb_piece); if (!pieces.empty()) info.d(bts_pieces, pieces); if (g_map.size() == 1) { // single-file torrent if (use_merkle) info.d(bts_merkle_hash, files.l().front().d(bts_merkle_hash)); info.d(bts_length, files.l().front().d(bts_length)); info.d(bts_name, files.l().front().d(bts_path).l().front()); } else { // multi-file torrent info.d(bts_files, files); info.d(bts_name, g_name); } Cbvalue torrent; torrent.d(bts_announce, tracker); torrent.d(bts_info, info); Cvirtual_binary s = torrent.read(); if (use_merkle) s = gzip(s); s.save(g_name + ".torrent"); std::cout << time(NULL) - t << " s" << std::endl; return 0; }