Пример #1
0
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();
}
Пример #2
0
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;
}
Пример #3
0
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;
        }
    }
}
Пример #4
0
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);
}
Пример #5
0
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));  
}
Пример #6
0
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());
	}

}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
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);
}
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
0
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));
}
Пример #15
0
String Cache::path(const BinaryString &digest) const
{
	Assert(!digest.empty());
	return mDirectory + Directory::Separator + digest.toString();
}
Пример #16
0
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);
}