explicit enumerated_value_range(span<const T> v) noexcept : _begin(v.data()) , _end(v.data()+v.size()) { assert(_begin <= _end); }
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 }
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; }
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 }
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())); } }
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 udp_tracker_connection::on_announce_response(span<char const> buf) { if (buf.size() < 20) return false; buf = buf.subspan(8); restart_read_timeout(); tracker_response resp; resp.interval = aux::read_int32(buf); resp.min_interval = 60; resp.incomplete = aux::read_int32(buf); resp.complete = aux::read_int32(buf); int const num_peers = int(buf.size()) / 6; if ((buf.size() % 6) != 0) { fail(error_code(errors::invalid_tracker_response_length)); return false; } boost::shared_ptr<request_callback> cb = requester(); #ifndef TORRENT_DISABLE_LOGGING if (cb) { cb->debug_log("<== UDP_TRACKER_RESPONSE [ url: %s ]", tracker_req().url.c_str()); } #endif if (!cb) { close(); return true; } std::vector<peer_entry> peer_list; resp.peers4.reserve(num_peers); for (int i = 0; i < num_peers; ++i) { ipv4_peer_entry e; memcpy(&e.ip[0], buf.data(), 4); buf = buf.subspan(4); e.port = aux::read_uint16(buf); resp.peers4.push_back(e); } std::list<address> ip_list; for (std::vector<tcp::endpoint>::const_iterator i = m_endpoints.begin() , end(m_endpoints.end()); i != end; ++i) { ip_list.push_back(i->address()); } cb->tracker_response(tracker_req(), m_target.address(), ip_list , resp); close(); return true; }
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())); } }
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; }
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); }
// 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)); } }
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)); } }
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 } }
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 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 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; }
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; }
void BufferObject::set_subdata(GLintptr offset, span<const gsl::byte> data) { bind(); GL(glBufferSubData(GLenum(target_), offset, data.size(), data.data())); }
void assign(span<char const> s) { TORRENT_ASSERT(s.size() >= N / 8); size_t const sl = s.size() < size() ? s.size() : size(); std::memcpy(m_number, s.data(), sl); }
bool udp_tracker_connection::on_receive(udp::endpoint const& ep , span<char const> const buf) { #ifndef TORRENT_DISABLE_LOGGING boost::shared_ptr<request_callback> cb = requester(); #endif // ignore resposes before we've sent any requests if (m_state == action_error) { #ifndef TORRENT_DISABLE_LOGGING if (cb) cb->debug_log("<== UDP_TRACKER [ m_action == error ]"); #endif return false; } if (m_abort) { #ifndef TORRENT_DISABLE_LOGGING if (cb) cb->debug_log("<== UDP_TRACKER [ aborted]"); #endif return false; } // ignore packet not sent from the tracker // if m_target is inaddr_any, it suggests that we // sent the packet through a proxy only knowing // the hostname, in which case this packet might be for us if (!is_any(m_target.address()) && m_target != ep) { #ifndef TORRENT_DISABLE_LOGGING if (cb) cb->debug_log("<== UDP_TRACKER [ unexpected source IP: %s " "expected: %s ]" , print_endpoint(ep).c_str() , print_endpoint(m_target).c_str()); #endif return false; } #ifndef TORRENT_DISABLE_LOGGING if (cb) cb->debug_log("<== UDP_TRACKER_PACKET [ size: %d ]" , int(buf.size())); #endif // ignore packets smaller than 8 bytes if (buf.size() < 8) return false; span<const char> ptr = buf; int const action = aux::read_int32(ptr); std::uint32_t const transaction = aux::read_uint32(ptr); #ifndef TORRENT_DISABLE_LOGGING if (cb) cb->debug_log("*** UDP_TRACKER_PACKET [ action: %d ]", action); #endif // ignore packets with incorrect transaction id if (m_transaction_id != transaction) { #ifndef TORRENT_DISABLE_LOGGING if (cb) cb->debug_log("*** UDP_TRACKER_PACKET [ tid: %x ]" , int(transaction)); #endif return false; } if (action == action_error) { fail(error_code(errors::tracker_failure), -1 , std::string(buf.data(), buf.size()).c_str()); return true; } // ignore packets that's not a response to our message if (action != m_state) { #ifndef TORRENT_DISABLE_LOGGING if (cb) cb->debug_log("*** UDP_TRACKER_PACKET [ unexpected action: %d " " expected: %d ]", action, m_state); #endif return false; } restart_read_timeout(); #ifndef TORRENT_DISABLE_LOGGING if (cb) cb->debug_log("*** UDP_TRACKER_RESPONSE [ tid: %x ]" , int(transaction)); #endif switch (m_state) { case action_connect: return on_connect_response(buf); case action_announce: return on_announce_response(buf); case action_scrape: return on_scrape_response(buf); default: break; } return false; }
void CopeOtExtSender::send( span<ZpNumber> messages, Channel& chl) { auto fieldSize = messages[0].mField->bitCount(); // round up u64 numOtExt = roundUpTo(messages.size() * fieldSize, 128); u64 numSuperBlocks = (numOtExt / 128 + copeSuperBlkSize - 1) / copeSuperBlkSize; //u64 numBlocks = numSuperBlocks * copeSuperBlkSize; // a uNum that will be used to transpose the sender's matrix std::array<block, copeSuperBlkSize> t; std::vector<std::array<block, copeSuperBlkSize>> u(128 * copeCommStepSize); //std::array<block, 128> choiceMask; block delta = *(block*)mBaseChoiceBits.data(); //for (u64 i = 0; i < 128; ++i) //{ // if (mBaseChoiceBits[i]) choiceMask[i] = AllOneBlock; // else choiceMask[i] = ZeroBlock; //} auto* mIter = messages.data(); block * uIter = (block*)u.data() + copeSuperBlkSize * 128 * copeCommStepSize; block * uEnd = uIter; ZpField field; field.setParameters(ZpParam128); std::vector<ZpNumber> g; //qq.reserve(copeSuperBlkSize * field.bitCount()); //for (u64 i = 0; i < copeSuperBlkSize * field.bitCount(); ++i) // qq.emplace_back(field); std::cout << IoStream::lock; g.reserve(field.bitCount()); for (u64 i = 0; i < field.bitCount(); ++i) { g.emplace_back(field, 2); g[i].powEq(i); std::cout << "g[" << i << "] " << g[i] << std::endl; } std::cout << IoStream::unlock; std::array<ZpNumber, copeSuperBlkSize> q { ZpNumber(field),ZpNumber(field),ZpNumber(field),ZpNumber(field), ZpNumber(field), ZpNumber(field), ZpNumber(field), ZpNumber(field) }; ZpNumber uNum(field); for (u64 superBlkIdx = 0; superBlkIdx < numSuperBlocks; ++superBlkIdx) { if (uIter == uEnd) { u64 step = std::min<u64>(numSuperBlocks - superBlkIdx, (u64)copeCommStepSize); chl.recv((u8*)u.data(), step * copeSuperBlkSize * 128 * sizeof(block)); uIter = (block*)u.data(); } for (u64 j = 0; j < copeSuperBlkSize; ++j) { //qq[j] = 0; mIter[j] = 0; } std::cout << IoStream::lock; // transpose 128 columns at at time. Each column will be 128 * copeSuperBlkSize = 1024 bits long. for (u64 colIdx = 0; colIdx < 128; ++colIdx) { // generate the columns using AES-NI in counter mode. mGens[colIdx].mAes.ecbEncCounterMode(mGens[colIdx].mBlockIdx, copeSuperBlkSize, t.data()); mGens[colIdx].mBlockIdx += copeSuperBlkSize; for (u64 i = 0; i < copeSuperBlkSize; ++i) { q[i].fromBytes((u8*)&t[i]); } if (this->mBaseChoiceBits[colIdx]) { for (u64 i = 0; i < copeSuperBlkSize; ++i) { uNum.fromBytes((u8*)&uIter[i]); q[i] -= uNum; } } for (u64 i = 0; i < copeSuperBlkSize; ++i) { //std::cout << (mBaseChoiceBits[colIdx]? "t0x" : "t0 ") <<"[" << i << "][" << colIdx << "] = " << q[i] <<" " << mBaseChoiceBits[colIdx] << "\n\n"<<std::endl; std::cout << "q[" << colIdx << "][" << i << "] = " << q[i] << std::endl; q[i] *= g[colIdx]; mIter[i] += q[i]; } uIter += 8; } std::cout << IoStream::unlock; mIter += 8; } static_assert(gOtExtBaseOtCount == 128, "expecting 128"); }
bool utp_socket_manager::incoming_packet(std::weak_ptr<utp_socket_interface> socket , udp::endpoint const& ep, span<char const> p) { // UTP_LOGV("incoming packet size:%d\n", size); if (p.size() < sizeof(utp_header)) return false; utp_header const* ph = reinterpret_cast<utp_header const*>(p.data()); // UTP_LOGV("incoming packet version:%d\n", int(ph->get_version())); if (ph->get_version() != 1) return false; const time_point receive_time = clock_type::now(); // parse out connection ID and look for existing // connections. If found, forward to the utp_stream. std::uint16_t id = ph->connection_id; // first test to see if it's the same socket as last time // in most cases it is if (m_last_socket && utp_match(m_last_socket, ep, id)) { return utp_incoming_packet(m_last_socket, p, ep, receive_time); } std::pair<socket_map_t::iterator, socket_map_t::iterator> r = m_utp_sockets.equal_range(id); for (; r.first != r.second; ++r.first) { if (!utp_match(r.first->second, ep, id)) continue; bool ret = utp_incoming_packet(r.first->second, p, ep, receive_time); if (ret) m_last_socket = r.first->second; return ret; } // UTP_LOGV("incoming packet id:%d source:%s\n", id, print_endpoint(ep).c_str()); if (!m_sett.get_bool(settings_pack::enable_incoming_utp)) return false; // if not found, see if it's a SYN packet, if it is, // create a new utp_stream if (ph->get_type() == ST_SYN) { // possible SYN flood. Just ignore if (int(m_utp_sockets.size()) > m_sett.get_int(settings_pack::connections_limit) * 2) return false; // UTP_LOGV("not found, new connection id:%d\n", m_new_connection); std::shared_ptr<socket_type> c(new (std::nothrow) socket_type(m_ios)); if (!c) return false; TORRENT_ASSERT(m_new_connection == -1); // create the new socket with this ID m_new_connection = id; instantiate_connection(m_ios, aux::proxy_settings(), *c , m_ssl_context, this, true, false); utp_stream* str = nullptr; #ifdef TORRENT_USE_OPENSSL if (is_ssl(*c)) str = &c->get<ssl_stream<utp_stream>>()->next_layer(); else #endif str = c->get<utp_stream>(); TORRENT_ASSERT(str); int link_mtu, utp_mtu; mtu_for_dest(ep.address(), link_mtu, utp_mtu); utp_init_mtu(str->get_impl(), link_mtu, utp_mtu); utp_init_socket(str->get_impl(), socket); bool ret = utp_incoming_packet(str->get_impl(), p, ep, receive_time); if (!ret) return false; m_cb(c); // the connection most likely changed its connection ID here // we need to move it to the correct ID return true; } if (ph->get_type() == ST_RESET) return false; // #error send reset return false; }
constexpr span(const span<OtherElementType, OtherExtent> &other) : data_(reinterpret_cast<pointer>(other.data())), size_(other.size()) { assert(extent == dynamic_extent || other.size() == extent); }
bool dht_tracker::incoming_packet(udp::endpoint const& ep , span<char const> const buf) { int const buf_size = int(buf.size()); if (buf_size <= 20 || buf.front() != 'd' || buf.back() != 'e') return false; m_counters.inc_stats_counter(counters::dht_bytes_in, buf_size); // account for IP and UDP overhead m_counters.inc_stats_counter(counters::recv_ip_overhead_bytes , ep.address().is_v6() ? 48 : 28); m_counters.inc_stats_counter(counters::dht_messages_in); if (m_settings.ignore_dark_internet && ep.address().is_v4()) { address_v4::bytes_type b = ep.address().to_v4().to_bytes(); // these are class A networks not available to the public // if we receive messages from here, that seems suspicious static std::uint8_t const class_a[] = { 3, 6, 7, 9, 11, 19, 21, 22, 25 , 26, 28, 29, 30, 33, 34, 48, 51, 56 }; if (std::find(std::begin(class_a), std::end(class_a), b[0]) != std::end(class_a)) { m_counters.inc_stats_counter(counters::dht_messages_in_dropped); return true; } } if (!m_blocker.incoming(ep.address(), clock_type::now(), m_log)) { m_counters.inc_stats_counter(counters::dht_messages_in_dropped); return true; } TORRENT_ASSERT(buf_size > 0); int pos; error_code err; int ret = bdecode(buf.data(), buf.data() + buf_size, m_msg, err, &pos, 10, 500); if (ret != 0) { m_counters.inc_stats_counter(counters::dht_messages_in_dropped); #ifndef TORRENT_DISABLE_LOGGING m_log->log_packet(dht_logger::incoming_message, buf, ep); #endif return false; } if (m_msg.type() != bdecode_node::dict_t) { m_counters.inc_stats_counter(counters::dht_messages_in_dropped); #ifndef TORRENT_DISABLE_LOGGING m_log->log_packet(dht_logger::incoming_message, buf, ep); #endif // it's not a good idea to send a response to an invalid messages return false; } #ifndef TORRENT_DISABLE_LOGGING m_log->log_packet(dht_logger::incoming_message, buf, ep); #endif libtorrent::dht::msg m(m_msg, ep); m_dht.incoming(m); #if TORRENT_USE_IPV6 m_dht6.incoming(m); #endif return true; }
void DrrnPsiClient::recv(Channel s0, Channel s1, span<block> inputs) { if (inputs.size() != mClientSetSize) throw std::runtime_error(LOCATION); Matrix<u64> bins(mNumSimpleBins, mBinSize); std::vector<u64> binSizes(mNumSimpleBins); u64 cuckooSlotsPerBin = (mCuckooParams.numBins() + mNumSimpleBins) / mNumSimpleBins; // Simple hashing with a PRP std::vector<block> hashs(inputs.size()); AES hasher(mHashingSeed); u64 numCuckooBins = mCuckooParams.numBins(); for (u64 i = 0; i < u64(inputs.size());) { auto min = std::min<u64>(inputs.size() - i, 8); auto end = i + min; hasher.ecbEncBlocks(inputs.data() + i, min, hashs.data() + i); for (; i < end; ++i) { hashs[i] = hashs[i] ^ inputs[i]; for (u64 j = 0; j < mCuckooParams.mNumHashes; ++j) { u64 idx = CuckooIndex<>::getHash(hashs[i], j, numCuckooBins) * mNumSimpleBins / mCuckooParams.numBins(); // insert this item in this bin. pack together the hash index and input index bins(idx, binSizes[idx]++) = (j << 56) | i; } //if (!i) //{ // ostreamLock(std::cout) << "cinput[" << i << "] = " << inputs[i] << " -> " << hashs[i] << " (" // << CuckooIndex<>::getHash(hashs[i], 0, numCuckooBins) << ", " // << CuckooIndex<>::getHash(hashs[i], 1, numCuckooBins) << ", " // << CuckooIndex<>::getHash(hashs[i], 2, numCuckooBins) << ")" // << std::endl; //} } } // power of 2 u64 numLeafBlocks = (cuckooSlotsPerBin + mBigBlockSize * 128 - 1) / (mBigBlockSize * 128); u64 gDepth = 2; u64 kDepth = std::max<u64>(gDepth, log2floor(numLeafBlocks)) - gDepth; u64 groupSize = (numLeafBlocks + (u64(1) << kDepth) - 1) / (u64(1) << kDepth); if (groupSize > 8) throw std::runtime_error(LOCATION); //std::cout << "kDepth: " << kDepth << std::endl; //std::cout << "mBinSize: " << mBinSize << std::endl; u64 numQueries = mNumSimpleBins * mBinSize; auto permSize = numQueries * mBigBlockSize; // mask generation block rSeed = CCBlock;// mPrng.get<block>(); AES rGen(rSeed); std::vector<block> shares(mClientSetSize * mCuckooParams.mNumHashes), r(permSize), piS1(permSize), s(permSize); //std::vector<u32> rIdxs(numQueries); //std::vector<u64> sharesIdx(shares.size()); //TODO("use real masks"); //memset(r.data(), 0, r.size() * sizeof(block)); rGen.ecbEncCounterMode(r.size() * 0, r.size(), r.data()); rGen.ecbEncCounterMode(r.size() * 1, r.size(), piS1.data()); rGen.ecbEncCounterMode(r.size() * 2, r.size(), s.data()); //auto encIter = enc.begin(); auto shareIter = shares.begin(); //auto shareIdxIter = sharesIdx.begin(); u64 queryIdx = 0, dummyPermIdx = mClientSetSize * mCuckooParams.mNumHashes; std::unordered_map<u64, u64> inputMap; inputMap.reserve(mClientSetSize * mCuckooParams.mNumHashes); std::vector<u32> pi(permSize); auto piIter = pi.begin(); u64 keySize = kDepth + 1 + groupSize; u64 mask = (u64(1) << 56) - 1; auto binIter = bins.begin(); for (u64 bIdx = 0; bIdx < mNumSimpleBins; ++bIdx) { u64 i = 0; auto binOffset = (bIdx * numCuckooBins + mNumSimpleBins - 1) / mNumSimpleBins; std::vector<block> k0(keySize * mBinSize), k1(keySize * mBinSize); //std::vector<u64> idx0(mBinSize), idx1(mBinSize); auto k0Iter = k0.data(), k1Iter = k1.data(); //auto idx0Iter = idx0.data(), idx1Iter = idx1.data(); for (; i < binSizes[bIdx]; ++i) { span<block> kk0(k0Iter, kDepth + 1), g0(k0Iter + kDepth + 1, groupSize), kk1(k1Iter, kDepth + 1), g1(k1Iter + kDepth + 1, groupSize); k0Iter += keySize; k1Iter += keySize; u8 hashIdx = *binIter >> 56; u64 itemIdx = *binIter & mask; u64 cuckooIdx = CuckooIndex<>::getHash(hashs[itemIdx], hashIdx, numCuckooBins) - binOffset; ++binIter; auto bigBlockoffset = cuckooIdx % mBigBlockSize; auto bigBlockIdx = cuckooIdx / mBigBlockSize; BgiPirClient::keyGen(bigBlockIdx, mPrng.get<block>(), kk0, g0, kk1, g1); // the index of the mask that will mask this item auto rIdx = *piIter = itemIdx * mCuckooParams.mNumHashes + hashIdx * mBigBlockSize + bigBlockoffset; // the masked value that will be inputted into the PSI *shareIter = r[rIdx] ^ inputs[itemIdx]; //*shareIter = inputs[itemIdx]; //if (itemIdx == 0) // ostreamLock(std::cout) // << "item[" << i << "] bin " << bIdx // << " block " << bigBlockIdx // << " offset " << bigBlockoffset // << " psi " << *shareIter << std::endl; // This will be used to map itemed items in the intersection back to their input item inputMap.insert({ queryIdx, itemIdx }); ++shareIter; ++piIter; ++queryIdx; } u64 rem = mBinSize - i; binIter += rem; for (u64 i = 0; i < rem; ++i) { *piIter++ = dummyPermIdx++; } //s0.asyncSendCopy(k0); //s0.asyncSendCopy(k1); //s1.asyncSendCopy(k1); //s1.asyncSendCopy(k0); s0.asyncSend(std::move(k0)); s1.asyncSend(std::move(k1)); } std::vector<u32> pi1(permSize), pi0(permSize), pi1Inv(permSize); for (u32 i = 0; i < pi1.size(); ++i) pi1[i] = i; PRNG prng(rSeed ^ OneBlock); std::random_shuffle(pi1.begin(), pi1.end(), prng); //std::vector<block> pi1RS(pi.size()); for (u64 i = 0; i < permSize; ++i) { //auto pi1i = pi1[i]; //pi1RS[i] = r[pi1i] ^ s[pi1i]; pi1Inv[pi1[i]] = i; //std::cout << "pi1(r + s)[" << i << "] " << pi1RS[i] << std::endl; } std::vector<block> piS0(r.size()); for (u64 i = 0; i < permSize; ++i) { //std::cout << "r[" << i << "] " << r[i] << std::endl; //std::cout << "pi(r + s)[" << i << "]=" << (r[pi[i]] ^ s[pi[i]]) << std::endl; pi0[i] = pi1Inv[pi[i]]; piS0[i] = piS1[i] ^ s[pi[i]]; //std::cout << "pi (r + s)[" << i << "] = " << (r[pi[i]] ^ s[pi[i]]) << " = " << r[pi[i]] << " ^ " << s[pi[i]] << " c " << pi[i] << std::endl; //std::cout << "pi`(r + s)[" << i << "] = " << pi1RS[pi0[i]] <<" c " << pi0[pi1[i]] << std::endl; } s0.asyncSend(std::move(pi0)); s0.asyncSend(std::move(piS0)); //rGen.ecbEncBlocks(r.data(), r.size(), r.data()); //for (u64 i = 0; i < shares.size(); ++i) //{ // std::cout << IoStream::lock << "cshares[" << i << "] " << shares[i] << " input[" << sharesIdx[i]<<"]" << std::endl << IoStream::unlock; //} mPsi.sendInput(shares, s0); mIntersection.reserve(mPsi.mIntersection.size()); for (u64 i = 0; i < mPsi.mIntersection.size(); ++i) { // divide index by #hashes mIntersection.emplace(inputMap[mPsi.mIntersection[i]]); } }
item::item(public_key const& pk, span<char const> salt) : m_salt(salt.data(), salt.size()) , m_pk(pk) , m_seq(0) , m_mutable(true) {}
TORRENT_EXTRA_EXPORT void xml_parse(span<char const> input , std::function<void(int,char const*,int,char const*,int)> callback) { char const* p = input.data(); char const* end = input.data() + input.size(); for(;p != end; ++p) { char const* start = p; int token; // look for tag start for(; p != end && *p != '<'; ++p); if (p != start) { token = xml_string; const int name_len = p - start; callback(token, start, name_len, nullptr, 0); } if (p == end) break; // skip '<' ++p; if (p != end && p+8 < end && string_begins_no_case("![CDATA[", p)) { // CDATA. match '![CDATA[' p += 8; start = p; while (p != end && !string_begins_no_case("]]>", p-2)) ++p; // parse error if (p == end) { token = xml_parse_error; start = "unexpected end of file"; callback(token, start, int(strlen(start)), nullptr, 0); break; } token = xml_string; const int name_len = p - start - 2; callback(token, start, name_len, nullptr, 0); continue; } // parse the name of the tag. for (start = p; p != end && *p != '>' && !is_space(*p); ++p); char const* tag_name_end = p; // skip the attributes for now for (; p != end && *p != '>'; ++p); // parse error if (p == end) { token = xml_parse_error; start = "unexpected end of file"; callback(token, start, int(strlen(start)), nullptr, 0); break; } TORRENT_ASSERT(*p == '>'); char const* tag_end = p; if (*start == '/') { ++start; token = xml_end_tag; const int name_len = tag_name_end - start; callback(token, start, name_len, nullptr, 0); } else if (*(p-1) == '/') { token = xml_empty_tag; const int name_len = (std::min)(tag_name_end - start, p - start - 1); callback(token, start, name_len, nullptr, 0); tag_end = p - 1; } else if (*start == '?' && *(p-1) == '?') { ++start; token = xml_declaration_tag; const int name_len = (std::min)(tag_name_end - start, p - start - 1); callback(token, start, name_len, nullptr, 0); tag_end = p - 1; } else if (start + 5 < p && std::memcmp(start, "!--", 3) == 0 && std::memcmp(p-2, "--", 2) == 0) { start += 3; token = xml_comment; const int name_len = tag_name_end - start - 2; callback(token, start, name_len, nullptr, 0); tag_end = p - 2; continue; } else { token = xml_start_tag; const int name_len = tag_name_end - start; callback(token, start, name_len, nullptr, 0); } // parse attributes for (char const* i = tag_name_end; i < tag_end; ++i) { char const* val_start = nullptr; // find start of attribute name for (; i != tag_end && is_space(*i); ++i); if (i == tag_end) break; start = i; // find end of attribute name for (; i != tag_end && *i != '=' && !is_space(*i); ++i); const int name_len = i - start; // look for equality sign for (; i != tag_end && *i != '='; ++i); // no equality sign found. Report this as xml_tag_content // instead of a series of key value pairs if (i == tag_end) { token = xml_tag_content; callback(token, start, i - start, nullptr, 0); break; } ++i; for (; i != tag_end && is_space(*i); ++i); // check for parse error (values must be quoted) if (i == tag_end || (*i != '\'' && *i != '\"')) { token = xml_parse_error; start = "unquoted attribute value"; callback(token, start, int(strlen(start)), nullptr, 0); break; } char quote = *i; ++i; val_start = i; for (; i != tag_end && *i != quote; ++i); // parse error (missing end quote) if (i == tag_end) { token = xml_parse_error; start = "missing end quote on attribute"; callback(token, start, int(strlen(start)), nullptr, 0); break; } const int val_len = i - val_start; token = xml_attribute; callback(token, start, name_len, val_start, val_len); } } }