void Database::Statement::value(int column, BinaryString &v) const { int size = sqlite3_column_bytes(mStmt, column); const char *data = reinterpret_cast<const char*>(sqlite3_column_text(mStmt, column)); if(data) v.assign(data, data+size); else v.clear(); }
bool Store::Sink::push(Fountain::Combination &incoming) { std::unique_lock<std::mutex> lock(mMutex); mSink.solve(incoming); if(!mSink.isDecoded()) return false; BinaryString sinkDigest; mSink.hash(sinkDigest); LogDebug("Store::push", "Block is complete, digest is " + sinkDigest.toString()); if(!mDigest.empty() && sinkDigest != mDigest) { LogWarn("Store::push", "Block digest is invalid (expected " + mDigest.toString() + ")"); mSink.clear(); return false; } mPath = Cache::Instance->path(mDigest); File file(mPath, File::Write); mSize = mSink.dump(file); file.close(); return true; }
void LSBSoundCoder::SetMessageText( const std::string& _message ) { // Prepare message for hiding - convert it to binary BinaryString message; // Convert message to binary for (size_t byteN = 0; byteN < _message.length(); ++byteN) // Save each letter message.push_back(_message[byteN]); // Get container dimensions const size_t bitsInMessage = _message.size() * bitsInChar; // Hide message for (size_t bitsWritten = 0; bitsWritten < bitsInMessage; ++bitsWritten) { // If no space left to write bits - break if ( !SetBit( message[bitsWritten / bitsInChar] [bitsWritten % bitsInChar] ) ) { assert(0&&"Can not set bit in SetMessageText()"); break; } } }
size_t Resource::Reader::readData(char *buffer, size_t size) { if(!mCurrentBlock) return 0; // EOF if(!mKey.empty() && !mCurrentBlock->hasDecryption()) { BinaryString subsalt; subsalt.writeBinary(uint64_t(mCurrentBlockIndex)); // Generate subkey BinaryString subkey; Sha256().pbkdf2_hmac(mKey, subsalt, subkey, 32, 100); // Generate iv BinaryString iv; Sha256().pbkdf2_hmac(mResource->salt(), subsalt, iv, 16, 100); // Initialize decryption process mCurrentBlock->setDecryption(subkey, iv); } size_t ret; if((ret = mCurrentBlock->readData(buffer, size))) { mReadPosition+= ret; return ret; } delete mCurrentBlock; ++mCurrentBlockIndex; mCurrentBlock = mNextBlock; mNextBlock = createBlock(mCurrentBlockIndex + 1); return readData(buffer, size); }
void Database::Statement::bind(int parameter, const BinaryString &value) { if(!parameter) return; // TODO std::vector<char> tmp; tmp.assign(value.begin(), value.end()); if(sqlite3_bind_blob(mStmt, parameter, &tmp[0], tmp.size(), SQLITE_TRANSIENT) != SQLITE_OK) throw DatabaseException(mDb, String("Unable to bind parameter ") + String::number(parameter)); }
void Resource::fetch(const BinaryString &digest, bool localOnly) { delete mIndexBlock; delete mIndexRecord; mIndexRecord = NULL; mIndexBlock = NULL; if(localOnly && !Store::Instance->hasBlock(digest)) throw Exception(String("Local resource not found: ") + digest.toString()); //LogDebug("Resource::fetch", "Fetching resource " + digest.toString()); try { mIndexBlock = new Block(digest); mIndexRecord = new IndexRecord; //LogDebug("Resource::fetch", "Reading index block for " + digest.toString()); BinarySerializer serializer(mIndexBlock); AssertIO(static_cast<Serializer*>(&serializer)->input(mIndexRecord)); } catch(const std::exception &e) { delete mIndexBlock; delete mIndexRecord; mIndexRecord = NULL; mIndexBlock = NULL; throw Exception(String("Unable to fetch resource index block: ") + e.what()); } }
bool PortMapping::NatPMP::parse(BinaryString &dgram, uint8_t reqOp, uint16_t reqInternal, uint16_t *retExternal) { uint8_t version; uint8_t op; uint16_t result; uint32_t time; if(!dgram.readBinary(version)) return false; if(!dgram.readBinary(op)) return false; if(!dgram.readBinary(result)) return false; if(!dgram.readBinary(time)) return false; if(reqOp != op - 128) return false; if(result != 0) return false; switch(op) { case 128: // address { uint8_t a,b,c,d; if(!dgram.readBinary(a)) return false; if(!dgram.readBinary(b)) return false; if(!dgram.readBinary(c)) return false; if(!dgram.readBinary(d)) return false; if(mExternalHost.empty()) LogDebug("PortMapping::NatPMP", "NAT-PMP compliant gateway found"); mExternalHost.clear(); mExternalHost<<a<<'.'<<b<<'.'<<c<<'.'<<d; return true; } case 129: // UDP object case 130: // TCP object { uint16_t internal; uint16_t external; uint32_t lifetime; if(!dgram.readBinary(internal)) return false; if(!dgram.readBinary(external)) return false; if(!dgram.readBinary(lifetime)) return false; if(!internal) return false; if(reqInternal && (reqInternal != internal)) return false; if(retExternal) *retExternal = external; return true; } } return false; }
bool PortMapping::NatPMP::check(String &host) { LogDebug("PortMapping::NatPMP", "Trying NAT-PMP..."); BinaryString query; query.writeBinary(uint8_t(0)); // version query.writeBinary(uint8_t(0)); // op int attempts = 3; duration timeout = milliseconds(250.); for(int i=0; i<attempts; ++i) { BinaryString dgram = query; mSock.write(dgram, mGatewayAddr); using clock = std::chrono::steady_clock; std::chrono::time_point<clock> end = clock::now() + std::chrono::duration_cast<clock::duration>(timeout); while(clock::now() < end) { Address sender; duration left = end - clock::now(); if(!mSock.read(dgram, sender, left)) break; if(!sender.isPrivate()) continue; LogDebug("PortMapping::NatPMP", String("Got response from ") + sender.toString()); if(parse(dgram, 0)) { LogDebug("PortMapping", "NAT-PMP is available"); mGatewayAddr = sender; host = mExternalHost; return true; } } timeout*= 2; } //LogDebug("PortMapping::NatPMP", "NAT-PMP is not available"); return false; }
bool Request::addTarget(const BinaryString &target, bool finished) { if(mPath.empty() || target.empty()) return false; String prefix = mPath; if(prefix.size() >= 2 && prefix[prefix.size()-1] == '/') prefix.resize(prefix.size()-1); mFinishedAfterTarget|= finished; return incoming(Network::Locator(prefix, "/", link()) , target); }
bool Store::waitBlock(const BinaryString &digest, duration timeout) { if(!hasBlock(digest)) { Network::Caller caller(digest); // Block is missing locally, call it LogDebug("Store::waitBlock", "Waiting for block: " + digest.toString()); { std::unique_lock<std::mutex> lock(mMutex); if(!mCondition.wait_for(lock, timeout, [this, digest]() { return hasBlock(digest); })) return false; } LogDebug("Store::waitBlock", "Block is now available: " + digest.toString()); } return true; }
std::string LSBSoundCoder::GetMessageText( size_t _length ) { // Binary message BinaryString message; size_t bitsInMessage = _length * bitsInChar; // Read message for (size_t bitsRead = 0; bitsRead < bitsInMessage; ++bitsRead ) { // Add new char to message to write bits in if (bitsRead % bitsInChar == 0) message.push_back( CharBitset() ); // Bit bool bit; // If no space left to read bits - break if ( !GetBit(&bit) ) { assert(0&&"Can not get bit in GetMessageText()"); break; } // Save bit message.back()[bitsRead % bitsInChar] = bit; } // Result string std::string str; // Convert from binary to char for (size_t i = 0; i < message.size(); ++i) str += static_cast<char>( message[i].to_ulong() ); return str; }
bool PortMapping::NatPMP::request(uint8_t op, uint16_t internal, uint16_t suggested, uint32_t lifetime, uint16_t *external) { if(!op) return false; BinaryString query; query.writeBinary(uint8_t(0)); // version query.writeBinary(op); // op query.writeBinary(uint16_t(0)); // reserved query.writeBinary(internal); query.writeBinary(suggested); query.writeBinary(lifetime); const int attempts = 3; duration timeout = milliseconds(250.); for(int i=0; i<attempts; ++i) { BinaryString dgram = query; mSock.write(dgram, mGatewayAddr); using clock = std::chrono::steady_clock; std::chrono::time_point<clock> end = clock::now() + std::chrono::duration_cast<clock::duration>(timeout); while(clock::now() < end) { Address sender; duration left = end - clock::now(); if(!mSock.read(dgram, sender, left)) break; if(!sender.isPrivate()) continue; if(parse(dgram, op, internal)) return true; } timeout*= 2; } return false; }
bool Cache::prefetch(const BinaryString &target) { // Test local availability if(Store::Instance->hasBlock(target)) { Resource resource(target, true); // local only if(resource.isLocallyAvailable()) return true; } mScheduler.schedule(Scheduler::clock::now(), [target]() { try { Resource resource(target); Resource::Reader reader(&resource); reader.discard(); // read everything } catch(const Exception &e) { LogWarn("Cache::prefetch", "Prefetching failed for " + target.toString()); } }); return false; }
void Database::Statement::bind(int parameter, const BinaryString &value) { if(!parameter) return; if(sqlite3_bind_blob(mStmt, parameter, value.data(), value.size(), SQLITE_TRANSIENT) != SQLITE_OK) throw DatabaseException(mDb, String("Unable to bind parameter ") + String::number(parameter)); }
String Cache::path(const BinaryString &digest) const { Assert(!digest.empty()); return mDirectory + Directory::Separator + digest.toString(); }
void Resource::process(const String &filename, const String &name, const String &type, const String &secret) { BinaryString salt; // If secret is not empty then this is an encrypted resource if(!secret.empty()) { // Generate salt from plaintext // Because we need to be able to recognize data is identical even when encrypted BinaryString digest; File file(filename, File::Read); Sha256().compute(file, digest); Sha256().pbkdf2_hmac(digest, type, salt, 32, 100000); Assert(!salt.empty()); } // Fill index record delete mIndexRecord; int64_t size = File::Size(filename); mIndexRecord = new Resource::IndexRecord; mIndexRecord->name = name; mIndexRecord->type = type; mIndexRecord->size = size; mIndexRecord->salt = salt; mIndexRecord->blockDigests.reserve(size/Block::Size); // Process blocks File file(filename, File::Read); BinaryString blockDigest; if(!secret.empty()) { BinaryString key; Sha256().pbkdf2_hmac(secret, salt, key, 32, 100000); uint64_t i = 0; while(true) { BinaryString subsalt; subsalt.writeBinary(i); // Generate subkey BinaryString subkey; Sha256().pbkdf2_hmac(key, subsalt, subkey, 32, 100); // Generate iv BinaryString iv; Sha256().pbkdf2_hmac(salt, subsalt, iv, 16, 100); if(!Block::EncryptFile(file, subkey, iv, blockDigest)) break; mIndexRecord->blockDigests.append(blockDigest); ++i; } } else { while(Block::ProcessFile(file, blockDigest)) mIndexRecord->blockDigests.append(blockDigest); } // Create index String tempFileName = File::TempName(); File tempFile(tempFileName, File::Truncate); BinarySerializer serializer(&tempFile); serializer.write(mIndexRecord); tempFile.close(); String indexFilePath = Cache::Instance->move(tempFileName); // Create index block delete mIndexBlock; mIndexBlock = new Block(indexFilePath); }