bool udp_tracker_connection::on_connect_response(span<char const> buf) { // ignore packets smaller than 16 bytes if (buf.size() < 16) return false; restart_read_timeout(); // skip header buf = buf.subspan(8); // reset transaction update_transaction_id(); std::uint64_t const connection_id = aux::read_int64(buf); std::lock_guard<std::mutex> l(m_cache_mutex); connection_cache_entry& cce = m_connection_cache[m_target.address()]; cce.connection_id = connection_id; cce.expires = aux::time_now() + seconds(m_man.settings().get_int(settings_pack::udp_tracker_token_expiry)); if (0 == (tracker_req().kind & tracker_request::scrape_request)) send_udp_announce(); else if (0 != (tracker_req().kind & tracker_request::scrape_request)) send_udp_scrape(); return true; }
void update(span<char const> data) { if (CryptHashData(m_hash, reinterpret_cast<BYTE const*>(data.data()), int(data.size()), 0) == false) { throw_ex<system_error>(error_code(GetLastError(), system_category())); } }
int count_trailing_ones_hw(span<std::uint32_t const> buf) { auto const num = int(buf.size()); std::uint32_t const* ptr = buf.data(); TORRENT_ASSERT(num >= 0); TORRENT_ASSERT(ptr != nullptr); for (int i = num - 1; i >= 0; i--) { if (ptr[i] == 0xffffffff) continue; #if TORRENT_HAS_BUILTIN_CTZ std::uint32_t const v = ~aux::network_to_host(ptr[i]); return (num - i - 1) * 32 + __builtin_ctz(v); #elif defined _MSC_VER std::uint32_t const v = ~aux::network_to_host(ptr[i]); DWORD pos; _BitScanForward(&pos, v); return (num - i - 1) * 32 + pos; #else TORRENT_ASSERT_FAIL(); return -1; #endif } return num * 32; }
void random_bytes(span<char> buffer) { #ifdef TORRENT_BUILD_SIMULATOR // simulator for (auto& b : buffer) b = char(random(0xff)); #elif TORRENT_USE_CRYPTOAPI // windows aux::crypt_gen_random(buffer); #elif TORRENT_USE_DEV_RANDOM // /dev/random static dev_random dev; dev.read(buffer); #elif defined TORRENT_USE_LIBCRYPTO // openssl int r = RAND_bytes(reinterpret_cast<unsigned char*>(buffer.data()) , int(buffer.size())); if (r != 1) aux::throw_ex<system_error>(errors::no_entropy); #else // fallback for (auto& b : buffer) b = char(random(0xff)); #endif }
ImageFileInfo DetectImageFormat(span<uint8_t> data) { ImageFileInfo info; stbi__context ctx; stbi__start_mem(&ctx, &data[0], data.size_bytes()); int comp; if (stbi__bmp_info(&ctx, &info.width, &info.height, &comp)) { info.hasAlpha = (comp == 4); info.format = ImageFileFormat::BMP; return info; } TjDecompressHandle handle; if (tjDecompressHeader(handle, &data[0], data.size_bytes(), &info.width, &info.height) == 0) { info.hasAlpha = false; info.format = ImageFileFormat::JPEG; return info; } if (DetectTga(data, info)) { return info; } // Not a very good heuristic if (data.size() == 256 * 256) { info.width = 256; info.height = 256; info.hasAlpha = true; info.format = ImageFileFormat::FNTART; return info; } return info; }
void iterate_every_other_element(span<int, dynamic_range> av) { // pick every other element auto length = av.size() / 2; #if _MSC_VER > 1800 auto bounds = strided_bounds<1>({ length }, { 2 }); #else auto bounds = strided_bounds<1>(index<1>{ length }, index<1>{ 2 }); #endif strided_span<int, 1> strided(&av.data()[1], av.size() - 1, bounds); CHECK(strided.size() == length); CHECK(strided.bounds().index_bounds()[0] == length); for (auto i = 0; i < strided.size(); ++i) { CHECK(strided[i] == av[2 * i + 1]); } int idx = 0; for (auto num : strided) { CHECK(num == av[2 * idx + 1]); idx++; } }
bool CommObject::SendFrame(span<const std::uint8_t> frame) { if (frame.size() > CommMaxFrameSize) { LOGF(LOG_LEVEL_ERROR, "Frame payload is too long. Allowed: %d, Requested: '%d'.", CommMaxFrameSize, frame.size()); return false; } uint8_t cmd[ComPrefferedBufferSize]; cmd[0] = TransmitterSendFrame; memcpy(cmd + 1, frame.data(), frame.size()); uint8_t remainingBufferSize; const bool status = (this->_low.WriteRead(CommTransmitter, // span<const uint8_t>(cmd, 1 + frame.size()), // span<uint8_t>(&remainingBufferSize, 1) // ) == I2CResult::OK); if (!status) { LOG(LOG_LEVEL_ERROR, "[comm] Failed to send frame"); } if (remainingBufferSize == 0xff) { LOG(LOG_LEVEL_ERROR, "[comm] Frame was not accepted by the transmitter."); } return status && remainingBufferSize != 0xff; }
explicit enumerated_value_range(span<const T> v) noexcept : _begin(v.data()) , _end(v.data()+v.size()) { assert(_begin <= _end); }
inline void crypt_gen_random(span<char> buffer) { static HCRYPTPROV provider = crypt_acquire_provider(PROV_RSA_FULL); if (!CryptGenRandom(provider, int(buffer.size()) , reinterpret_cast<BYTE*>(buffer.data()))) { throw_ex<system_error>(error_code(GetLastError(), system_category())); } }
// allocate an uninitialized buffer of the specified size // and copy the initialization range into the start of the buffer buffer(std::size_t const size, span<char const> initialize) : buffer(size) { TORRENT_ASSERT(initialize.size() <= size); if (!initialize.empty()) { std::memcpy(m_begin, initialize.data(), (std::min)(initialize.size(), size)); } }
allocation_slot stack_allocator::copy_buffer(span<char const> buf) { int const ret = int(m_storage.size()); int const size = int(buf.size()); if (size < 1) return {}; m_storage.resize(ret + size); std::memcpy(&m_storage[ret], buf.data(), numeric_cast<std::size_t>(size)); return allocation_slot(ret); }
entry::entry(span<char const> v) : m_type(undefined_t) { #if TORRENT_USE_ASSERTS m_type_queried = true; #endif new(&data) string_type(v.data(), v.size()); m_type = string_t; }
void GLVertexBuffer::upload(span<const byte> a_data) { assert(GLStateBuffer::isBegun()); assert(m_initialized); if (!a_data.empty()) { glBindBuffer(GLenum(m_bufferType), m_id); glBufferData(GLenum(m_bufferType), a_data.length_bytes(), a_data.data(), GLenum(m_drawUsage)); } }
entry bdecode(span<char const> buffer) { entry e; bool err = false; auto it = buffer.begin(); detail::bdecode_recursive(it, buffer.end(), e, err, 0); TORRENT_ASSERT(e.m_type_queried == false); if (err) return entry(); return e; }
void update(span<char const> data) { if (CryptHashData(m_hash, reinterpret_cast<BYTE const*>(data.data()), int(data.size()), 0) == false) { #ifndef BOOST_NO_EXCEPTIONS throw system_error(error_code(GetLastError(), system_category())); #else std::terminate(); #endif } }
void item::assign(entry v, span<char const> salt , sequence_number const seq , public_key const& pk, signature const& sig) { m_pk = pk; m_sig = sig; m_salt.assign(salt.data(), salt.size()); m_seq = seq; m_mutable = true; m_value = std::move(v); }
inline void crypt_gen_random(span<char> buffer) { static HCRYPTPROV provider = crypt_acquire_provider(PROV_RSA_FULL); if (!CryptGenRandom(provider, int(buffer.size()) , reinterpret_cast<BYTE*>(buffer.data()))) { #ifndef BOOST_NO_EXCEPTIONS throw system_error(error_code(GetLastError(), system_category())); #else std::terminate(); #endif } }
// this has to be thread safe and atomic. i.e. on posix systems it has to be // turned into a series of pread() calls std::int64_t file::readv(std::int64_t file_offset, span<iovec_t const> bufs , error_code& ec, open_mode_t flags) { if (m_file_handle == INVALID_HANDLE_VALUE) { #ifdef TORRENT_WINDOWS ec = error_code(ERROR_INVALID_HANDLE, system_category()); #else ec = error_code(boost::system::errc::bad_file_descriptor, generic_category()); #endif return -1; } TORRENT_ASSERT((m_open_mode & open_mode::rw_mask) == open_mode::read_only || (m_open_mode & open_mode::rw_mask) == open_mode::read_write); TORRENT_ASSERT(!bufs.empty()); TORRENT_ASSERT(is_open()); #if TORRENT_USE_PREADV TORRENT_UNUSED(flags); std::int64_t ret = iov(&::preadv, native_handle(), file_offset, bufs, ec); #else // there's no point in coalescing single buffer writes if (bufs.size() == 1) { flags &= ~open_mode::coalesce_buffers; } iovec_t tmp; span<iovec_t const> tmp_bufs = bufs; if (flags & open_mode::coalesce_buffers) { if (!coalesce_read_buffers(tmp_bufs, tmp)) // ok, that failed, don't coalesce this read flags &= ~open_mode::coalesce_buffers; } #if TORRENT_USE_PREAD std::int64_t ret = iov(&::pread, native_handle(), file_offset, tmp_bufs, ec); #else std::int64_t ret = iov(&::read, native_handle(), file_offset, tmp_bufs, ec); #endif if (flags & open_mode::coalesce_buffers) coalesce_read_buffers_end(bufs , tmp.data(), !ec); #endif return ret; }
std::unique_ptr<uint8_t[]> DecodeJpeg(const span<uint8_t> data) { TjDecompressHandle handle; int w, h; tjDecompressHeader(handle, &data[0], data.size_bytes(), &w, &h); std::unique_ptr<uint8_t[]> result(new uint8_t[w * h * 4]); auto status = tjDecompress2(handle, &data[0], data.size_bytes(), &result[0], w, w * 4, h, TJPF_BGRX, 0); if (status != 0) { throw TempleException("Unable to decompress jpeg image: {}", tjGetErrorStr()); } return result; }
void item::assign(entry v, span<char const> salt , sequence_number const seq, public_key const& pk, secret_key const& sk) { char buffer[1000]; int bsize = bencode(buffer, v); TORRENT_ASSERT(bsize <= 1000); m_sig = sign_mutable_item(span<char const>(buffer, bsize) , salt, seq, pk, sk); m_salt.assign(salt.data(), salt.size()); m_pk = pk; m_seq = seq; m_mutable = true; m_value = std::move(v); }
bool udp_tracker_connection::on_scrape_response(span<char const> buf) { using namespace libtorrent::aux; restart_read_timeout(); int const action = aux::read_int32(buf); std::uint32_t const transaction = read_uint32(buf); if (transaction != m_transaction_id) { fail(error_code(errors::invalid_tracker_transaction_id)); return false; } if (action == action_error) { fail(error_code(errors::tracker_failure), -1 , std::string(buf.data(), buf.size()).c_str()); return true; } if (action != action_scrape) { fail(error_code(errors::invalid_tracker_action)); return true; } if (buf.size() < 12) { fail(error_code(errors::invalid_tracker_response_length)); return true; } int const complete = aux::read_int32(buf); int const downloaded = aux::read_int32(buf); int const incomplete = aux::read_int32(buf); boost::shared_ptr<request_callback> cb = requester(); if (!cb) { close(); return true; } cb->tracker_scrape_response(tracker_req() , complete, incomplete, downloaded, -1); close(); return true; }
void random_bytes(span<char> buffer) { #if TORRENT_USE_CRYPTOAPI HCRYPTPROV prov; if (!CryptAcquireContext(&prov, NULL, NULL , PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { #ifndef BOOST_NO_EXCEPTIONS throw system_error(error_code(GetLastError(), system_category())); #else std::terminate(); #endif } if (!CryptGenRandom(prov, int(buffer.size()) , reinterpret_cast<BYTE*>(buffer.data()))) { CryptReleaseContext(prov, 0); #ifndef BOOST_NO_EXCEPTIONS throw system_error(error_code(GetLastError(), system_category())); #else std::terminate(); #endif } CryptReleaseContext(prov, 0); #elif defined TORRENT_USE_LIBCRYPTO #ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif int r = RAND_bytes(reinterpret_cast<unsigned char*>(buffer.data()) , int(buffer.size())); if (r != 1) { #ifndef BOOST_NO_EXCEPTIONS throw system_error(error_code(int(::ERR_get_error()), system_category())); #else std::terminate(); #endif } #ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO #pragma clang diagnostic pop #endif #else for (auto& b : buffer) b = char(random(0xff)); #endif }
void disk_buffer_pool::free_multiple_buffers(span<char*> bufvec) { // sort the pointers in order to maximize cache hits std::sort(bufvec.begin(), bufvec.end()); std::unique_lock<std::mutex> l(m_pool_mutex); for (char* buf : bufvec) { TORRENT_ASSERT(is_disk_buffer(buf, l)); free_buffer_impl(buf, l); remove_buffer_in_use(buf); } check_buffer_level(l); }
void iterate_second_slice(span<int, dynamic_range, dynamic_range, dynamic_range> av) { int expected[6] = { 2,3,10,11,18,19 }; auto section = av.section({ 0,1,0 }, { 3,1,2 }); for (auto i = 0; i < section.extent<0>(); ++i) { for (auto j = 0; j < section.extent<1>(); ++j) for (auto k = 0; k < section.extent<2>(); ++k) { auto idx = index<3>{ i,j,k }; // avoid braces in the CHECK macro CHECK(section[idx] == expected[2 * i + 2 * j + k]); } } for (auto i = 0; i < section.extent<0>(); ++i) { for (auto j = 0; j < section.extent<1>(); ++j) for (auto k = 0; k < section.extent<2>(); ++k) CHECK(section[i][j][k] == expected[2 * i + 2 * j + k]); } int i = 0; for (auto num : section) { CHECK(num == expected[i]); i++; } }
DecodedImage DecodeImage(const span<uint8_t> data) { DecodedImage result; result.info = DetectImageFormat(data); stbi__context ctx; stbi__start_mem(&ctx, &data[0], data.size_bytes()); int w, h, comp; switch (result.info.format) { case ImageFileFormat::BMP: result.data.reset(stbi__bmp_load(&ctx, &w, &h, &comp, 4)); break; case ImageFileFormat::JPEG: result.data = DecodeJpeg(data); break; case ImageFileFormat::TGA: result.data = DecodeTga(data); break; case ImageFileFormat::FNTART: return DecodeFontArt(data); default: case ImageFileFormat::Unknown: throw TempleException("Unrecognized image format."); } return result; }
bool tracker_manager::incoming_packet(char const* hostname , span<char const> const buf) { TORRENT_ASSERT(is_single_thread()); // ignore packets smaller than 8 bytes if (buf.size() < 16) return false; // the first word is the action, if it's not [0, 3] // it's not a valid udp tracker response span<const char> ptr = buf; std::uint32_t const action = aux::read_uint32(ptr); if (action > 3) return false; std::uint32_t const transaction = aux::read_uint32(ptr); auto const i = m_udp_conns.find(transaction); if (i == m_udp_conns.end()) { #ifndef TORRENT_DISABLE_LOGGING // now, this may not have been meant to be a tracker response, // but chances are pretty good, so it's probably worth logging m_ses.session_log("incoming UDP tracker packet from %s has invalid " "transaction ID (%x)", hostname, int(transaction)); #endif return false; } std::shared_ptr<udp_tracker_connection> const p = i->second; // on_receive() may remove the tracker connection from the list return p->on_receive_hostname(hostname, buf); }
bool item::assign(bdecode_node const& v, span<char const> salt , sequence_number const seq, public_key const& pk, signature const& sig) { TORRENT_ASSERT(v.data_section().size() <= 1000); if (!verify_mutable_item(v.data_section(), salt, seq, pk, sig)) return false; m_pk = pk; m_sig = sig; if (salt.size() > 0) m_salt.assign(salt.data(), salt.size()); else m_salt.clear(); m_seq = seq; m_mutable = true; m_value = v; return true; }
bool tracker_manager::incoming_packet(udp::endpoint const& ep , span<char const> const buf) { TORRENT_ASSERT(is_single_thread()); // ignore packets smaller than 8 bytes if (buf.size() < 8) { #ifndef TORRENT_DISABLE_LOGGING if (m_ses.should_log()) { m_ses.session_log("incoming packet from %s, not a UDP tracker message " "(%d Bytes)", print_endpoint(ep).c_str(), int(buf.size())); } #endif return false; } // the first word is the action, if it's not [0, 3] // it's not a valid udp tracker response span<const char> ptr = buf; std::uint32_t const action = aux::read_uint32(ptr); if (action > 3) return false; std::uint32_t const transaction = aux::read_uint32(ptr); auto const i = m_udp_conns.find(transaction); if (i == m_udp_conns.end()) { #ifndef TORRENT_DISABLE_LOGGING if (m_ses.should_log()) { m_ses.session_log("incoming UDP tracker packet from %s has invalid " "transaction ID (%x)", print_endpoint(ep).c_str() , transaction); } #endif return false; } std::shared_ptr<udp_tracker_connection> const p = i->second; // on_receive() may remove the tracker connection from the list return p->on_receive(ep, buf); }
void CopeOtExtSender::setBaseOts(span<block> baseRecvOts, const BitVector & choices) { if (baseRecvOts.size() != gOtExtBaseOtCount || choices.size() != gOtExtBaseOtCount) throw std::runtime_error("not supported/implemented"); mBaseChoiceBits = choices; for (u64 i = 0; i < gOtExtBaseOtCount; i++) { mGens[i].SetSeed(baseRecvOts[i]); } }
int count_trailing_ones_sw(span<std::uint32_t const> buf) { auto const num = int(buf.size()); std::uint32_t const* ptr = buf.data(); TORRENT_ASSERT(num >= 0); TORRENT_ASSERT(ptr != nullptr); for (int i = num - 1; i >= 0; i--) { if (ptr[i] == 0xffffffff) continue; std::uint32_t v = ~aux::network_to_host(ptr[i]); for (int k = 0; k < 32; ++k, v >>= 1) { if ((v & 1) == 0) continue; return (num - i - 1) * 32 + k; } } return num * 32; }