示例#1
0
size_t StringStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
{
	size_t i = UnsignedMin(m_length, m_count+begin);
	size_t len = UnsignedMin(m_length-i, end-begin);
	size_t blockedBytes = target.ChannelPut2(channel, m_store+i, len, 0, blocking);
	if (!blockedBytes)
		begin += len;
	return blockedBytes;
}
示例#2
0
bool WindowsPipeReceiver::Receive(byte* buf, size_t bufLen)
{
	CRYPTOPP_ASSERT(!m_resultPending && !m_eofReceived);

	HANDLE h = GetHandle();
	// don't queue too much at once, or we might use up non-paged memory
	if (ReadFile(h, buf, UnsignedMin((DWORD)128*1024, bufLen), &m_lastResult, &m_overlapped))
	{
		if (m_lastResult == 0)
			m_eofReceived = true;
	}
	else
	{
		switch (GetLastError())
		{
		default:
			CheckAndHandleError("ReadFile", false);
		case ERROR_BROKEN_PIPE:
		case ERROR_HANDLE_EOF:
			m_lastResult = 0;
			m_eofReceived = true;
			break;
		case ERROR_IO_PENDING:
			m_resultPending = true;
		}
	}
	return !m_resultPending;
}
示例#3
0
	std::vector<word16> * operator()() const
	{
		const unsigned int maxPrimeTableSize = 3511;

		std::auto_ptr<std::vector<word16> > pPrimeTable(new std::vector<word16>);
		std::vector<word16> &primeTable = *pPrimeTable;
		primeTable.reserve(maxPrimeTableSize);

		primeTable.push_back(2);
		unsigned int testEntriesEnd = 1;
		
		for (unsigned int p=3; p<=s_lastSmallPrime; p+=2)
		{
			unsigned int j;
			for (j=1; j<testEntriesEnd; j++)
				if (p%primeTable[j] == 0)
					break;
			if (j == testEntriesEnd)
			{
				primeTable.push_back(p);
				testEntriesEnd = UnsignedMin(54U, primeTable.size());
			}
		}

		return pPrimeTable.release();
	}
示例#4
0
	inline size_t TransferTo(BufferedTransformation &target, lword transferMax, const std::string &channel=DEFAULT_CHANNEL)
	{
		size_t len = UnsignedMin(m_tail-m_head, transferMax);
		target.ChannelPutModifiable(channel, buf+m_head, len);
		m_head += len;
		return len;
	}
示例#5
0
bool SocketReceiver::Receive(byte* buf, size_t bufLen)
{
	CRYPTOPP_ASSERT(!m_resultPending && !m_eofReceived);

	DWORD flags = 0;
	// don't queue too much at once, or we might use up non-paged memory
	WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (char *)buf};
	if (WSARecv(m_s, &wsabuf, 1, &m_lastResult, &flags, &m_overlapped, NULL) == 0)
	{
		if (m_lastResult == 0)
			m_eofReceived = true;
	}
	else
	{
		switch (WSAGetLastError())
		{
		default:
			m_s.CheckAndHandleError_int("WSARecv", SOCKET_ERROR);
		case WSAEDISCON:
			m_lastResult = 0;
			m_eofReceived = true;
			break;
		case WSA_IO_PENDING:
			m_resultPending = true;
		}
	}
	return !m_resultPending;
}
示例#6
0
unsigned int Socket::Receive(byte* buf, size_t bufLen, int flags)
{
	CRYPTOPP_ASSERT(m_s != INVALID_SOCKET);
	int result = recv(m_s, (char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
	CheckAndHandleError_int("recv", result);
	return result;
}
示例#7
0
unsigned int Socket::Send(const byte* buf, size_t bufLen, int flags)
{
	CRYPTOPP_ASSERT(m_s != INVALID_SOCKET);
	int result = send(m_s, (const char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
	CheckAndHandleError_int("send", result);
	return result;
}
示例#8
0
lword NonblockingSink::TimedFlush(unsigned long maxTime, size_t targetSize)
{
	m_blockedBySpeedLimit = false;

	size_t curBufSize = GetCurrentBufferSize();
	if (curBufSize <= targetSize && (targetSize || !EofPending()))
		return 0;

	if (!GetMaxBytesPerSecond())
		return DoFlush(maxTime, targetSize);

	bool forever = (maxTime == INFINITE_TIME);
	unsigned long timeToGo = maxTime;
	Timer timer(Timer::MILLISECONDS, forever);
	lword totalFlushed = 0;

	timer.StartTimer();

	while (true)
	{	
		size_t flushSize = UnsignedMin(curBufSize - targetSize, ComputeCurrentTransceiveLimit());
		if (flushSize || EofPending())
		{
			if (!forever) timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime());
			size_t ret = (size_t)DoFlush(timeToGo, curBufSize - flushSize);
			if (ret)
			{
				NoteTransceive(ret);
				curBufSize -= ret;
				totalFlushed += ret;
			}
		}

		if (curBufSize <= targetSize && (targetSize || !EofPending()))
			break;

		if (!forever)
		{
			timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime());
			if (!timeToGo)
				break;
		}

		double waitTime = TimeToNextTransceive();
		if (!forever && waitTime > timeToGo)
		{
			m_blockedBySpeedLimit = true;
			break;
		}

		WaitObjectContainer container;
		LimitedBandwidth::GetWaitObjects(container, CallStack("NonblockingSink::TimedFlush() - speed limit", 0));
		container.Wait((unsigned long)waitTime);
	}

	return totalFlushed;
}
示例#9
0
size_t NetworkSink::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
{
	if (m_eofState == EOF_DONE)
	{
		if (length || messageEnd)
			throw Exception(Exception::OTHER_ERROR, "NetworkSink::Put2() being called after EOF had been sent");

		return 0;
	}

	if (m_eofState > EOF_NONE)
		goto EofSite;

	{
		if (m_skipBytes)
		{
			assert(length >= m_skipBytes);
			inString += m_skipBytes;
			length -= m_skipBytes;
		}

		m_buffer.Put(inString, length);

		if (!blocking || m_buffer.CurrentSize() > m_autoFlushBound)
			TimedFlush(0, 0);

		size_t targetSize = messageEnd ? 0 : m_maxBufferSize;
		if (blocking)
			TimedFlush(INFINITE_TIME, targetSize);

		if (m_buffer.CurrentSize() > targetSize)
		{
			assert(!blocking);
			m_wasBlocked = true;
			m_skipBytes += length;
			size_t blockedBytes = UnsignedMin(length, m_buffer.CurrentSize() - targetSize);
			return STDMAX<size_t>(blockedBytes, 1);
		}

		m_wasBlocked = false;
		m_skipBytes = 0;
	}

	if (messageEnd)
	{
		m_eofState = EOF_PENDING_SEND;

	EofSite:
		TimedFlush(blocking ? INFINITE_TIME : 0, 0);
		if (m_eofState != EOF_DONE)
			return 1;
	}

	return 0;
}
示例#10
0
void RandomizedTransfer(BufferedTransformation &source, BufferedTransformation &target, bool finish, const std::string &channel=DEFAULT_CHANNEL)
{
	while (source.MaxRetrievable() > (finish ? 0 : 4096))
	{
		byte buf[4096+64];
		size_t start = GlobalRNG().GenerateWord32(0, 63);
		size_t len = GlobalRNG().GenerateWord32(1, UnsignedMin(4096U, 3*source.MaxRetrievable()/2));
		len = source.Get(buf+start, len);
		target.ChannelPut(channel, buf+start, len);
	}
}
示例#11
0
void OldRandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
{
	while (size > 0)
	{
		if (getPos == pool.size())
				Stir();
		size_t t = UnsignedMin(pool.size() - getPos, size);
		target.ChannelPut(channel, pool+getPos, t);
		size -= t;
		getPos += t;
	}}
示例#12
0
void RandomNumberGenerator::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
{
	FixedSizeSecBlock<byte, 256> buffer;
	while (length)
	{
		size_t len = UnsignedMin(buffer.size(), length);
		GenerateBlock(buffer, len);
		target.ChannelPut(channel, buffer, len);
		length -= len;
	}
}
示例#13
0
size_t RandomNumberStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
{
	if (!blocking)
		throw NotImplemented("RandomNumberStore: nonblocking transfer is not implemented by this object");

	transferBytes = UnsignedMin(transferBytes, m_length - m_count);
	m_rng->GenerateIntoBufferedTransformation(target, channel, transferBytes);
	m_count += transferBytes;

	return 0;
}
示例#14
0
文件: Crc.cpp 项目: lcs2/carpg
inline unsigned int GetAlignmentOf(T *dummy=NULL)	// VC60 workaround
{
#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
	if (sizeof(T) < 16)
		return 1;
#endif

#if (_MSC_VER >= 1300)
	return __alignof(T);
#elif defined(__GNUC__)
	return __alignof__(T);
#elif CRYPTOPP_BOOL_SLOW_WORD64
	return UnsignedMin(4U, sizeof(T));
#else
	return sizeof(T);
#endif
}
示例#15
0
void Inflator::OutputString(const byte *string, size_t length)
{
    while (length)
    {
        size_t len = UnsignedMin(length, m_window.size() - m_current);
        memcpy(m_window + m_current, string, len);
        m_current += len;
        if (m_current == m_window.size())
        {
            ProcessDecompressedData(m_window + m_lastFlush, m_window.size() - m_lastFlush);
            m_lastFlush = 0;
            m_current = 0;
            m_wrappedAround = true;
        }
        string += len;
        length -= len;
    }
}
示例#16
0
void WindowsPipeSender::Send(const byte* buf, size_t bufLen)
{
	DWORD written = 0;
	HANDLE h = GetHandle();
	// don't queue too much at once, or we might use up non-paged memory
	if (WriteFile(h, buf, UnsignedMin((DWORD)128*1024, bufLen), &written, &m_overlapped))
	{
		m_resultPending = false;
		m_lastResult = written;
	}
	else
	{
		if (GetLastError() != ERROR_IO_PENDING)
			CheckAndHandleError("WriteFile", false);

		m_resultPending = true;
	}
}
示例#17
0
void CMAC_Base::Update(const byte *input, size_t length)
{
	assert((input && length) || !(input || length));
	if (!length)
		return;

	BlockCipher &cipher = AccessCipher();
	unsigned int blockSize = cipher.BlockSize();

	if (m_counter > 0)
	{
		const unsigned int len = UnsignedMin(blockSize - m_counter, length);
		if (len)
		{
			xorbuf(m_reg+m_counter, input, len);
			length -= len;
			input += len;
			m_counter += len;
		}

		if (m_counter == blockSize && length > 0)
		{
			cipher.ProcessBlock(m_reg);
			m_counter = 0;
		}
	}

	if (length > blockSize)
	{
		assert(m_counter == 0);
		size_t leftOver = 1 + cipher.AdvancedProcessBlocks(m_reg, input, m_reg, length-1, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
		input += (length - leftOver);
		length = leftOver;
	}

	if (length > 0)
	{
		assert(m_counter + length <= blockSize);
		xorbuf(m_reg+m_counter, input, length);
		m_counter += (unsigned int)length;
	}

	assert(m_counter > 0);
}
示例#18
0
void CTR_ModePolicy::OperateKeystream(KeystreamOperation /*operation*/, byte *output, const byte *input, size_t iterationCount)
{
	CRYPTOPP_ASSERT(m_cipher->IsForwardTransformation());	// CTR mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
	unsigned int s = BlockSize();
	unsigned int inputIncrement = input ? s : 0;

	while (iterationCount)
	{
		byte lsb = m_counterArray[s-1];
		size_t blocks = UnsignedMin(iterationCount, 256U-lsb);
		m_cipher->AdvancedProcessBlocks(m_counterArray, input, output, blocks*s, BlockTransformation::BT_InBlockIsCounter|BlockTransformation::BT_AllowParallel);
		if ((m_counterArray[s-1] = lsb + (byte)blocks) == 0)
			IncrementCounterBy256();

		output += blocks*s;
		input += blocks*inputIncrement;
		iterationCount -= blocks;
	}
}
示例#19
0
void SocketSender::Send(const byte* buf, size_t bufLen)
{
	CRYPTOPP_ASSERT(!m_resultPending);
	DWORD written = 0;
	// don't queue too much at once, or we might use up non-paged memory
	WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (char *)buf};
	if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULL) == 0)
	{
		m_resultPending = false;
		m_lastResult = written;
	}
	else
	{
		if (WSAGetLastError() != WSA_IO_PENDING)
			m_s.CheckAndHandleError_int("WSASend", SOCKET_ERROR);

		m_resultPending = true;
	}
}
示例#20
0
size_t RubyIOStore::TransferTo2(BufferedTransformation& target, CryptoPP::lword& transferBytes, const std::string& channel, bool blocking)
{
  if (!m_stream) {
    transferBytes = 0;
    return 0;
  }

  lword size = transferBytes;
  transferBytes = 0;

  if (m_waiting) {
    goto output;
  }

  while (size && !RTEST(rb_funcall(*m_stream, rb_intern("eof?"), 0))) {
    {
      VALUE buffer;
      size_t spaceSize = 1024;
      m_space = HelpCreatePutSpace(target, channel, 1, UnsignedMin(size_t(0) - 1, size), spaceSize);

      buffer = rb_funcall(*m_stream, rb_intern("read"), 1, UINT2NUM(STDMIN(size, (lword) spaceSize)));
      if (TYPE(buffer) != T_STRING) {
        throw ReadErr();
      }
      memcpy(m_space, StringValuePtr(buffer), RSTRING_LEN(buffer));
      m_len = RSTRING_LEN(buffer);
    }
    size_t blockedBytes;
    output:
      blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len, 0, blocking);
      m_waiting = blockedBytes > 0;
      if (m_waiting) {
        return blockedBytes;
      }
      size -= m_len;
      transferBytes += m_len;
  }
  if (!RTEST(rb_funcall(*m_stream, rb_intern("eof?"), 0))) {
    throw ReadErr();
  }
  return 0;
}
size_t FileStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
{
	if (!m_stream)
	{
		transferBytes = 0;
		return 0;
	}

	lword size=transferBytes;
	transferBytes = 0;

	if (m_waiting)
		goto output;

	while (size && m_stream->good())
	{
		{
		size_t spaceSize = 1024;
		m_space = HelpCreatePutSpace(target, channel, 1, UnsignedMin(size_t(SIZE_MAX), size), spaceSize);

		m_stream->read((char *)m_space, (unsigned int)STDMIN(size, (lword)spaceSize));
		}
		m_len = (size_t)m_stream->gcount();
		size_t blockedBytes;
output:
		blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len, 0, blocking);
		m_waiting = blockedBytes > 0;
		if (m_waiting)
			return blockedBytes;
		size -= m_len;
		transferBytes += m_len;
	}

	if (!m_stream->good() && !m_stream->eof())
		throw ReadErr();

	return 0;
}
示例#22
0
void RandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
{
	if (size > 0)
	{
		if (!m_keySet)
			m_pCipher->SetKey(m_key, 32);

		CRYPTOPP_COMPILE_ASSERT(sizeof(TimerWord) <= 16);
		CRYPTOPP_COMPILE_ASSERT(sizeof(time_t) <= 8);

		Timer timer;
		TimerWord tw = timer.GetCurrentTimerValue();

		*(TimerWord *)(void*)m_seed.data() += tw;
		time_t t = time(NULLPTR);

		// UBsan finding: signed integer overflow: 1876017710 + 1446085457 cannot be represented in type 'long int'
		// *(time_t *)(m_seed.data()+8) += t;
		word64 tt1 = 0, tt2 = (word64)t;
		::memcpy(&tt1, m_seed.data()+8, 8);
		::memcpy(m_seed.data()+8, &(tt2 += tt1), 8);

		// Wipe the intermediates
		*((volatile TimerWord*)&tw) = 0;
		*((volatile word64*)&tt1) = 0;
		*((volatile word64*)&tt2) = 0;

		do
		{
			m_pCipher->ProcessBlock(m_seed);
			size_t len = UnsignedMin(16, size);
			target.ChannelPut(channel, m_seed, len);
			size -= len;
		} while (size > 0);
	}
}
示例#23
0
size_t SecretSharing::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
{
	if (!blocking)
		throw BlockingInputOnly("SecretSharing");

	SecByteBlock buf(UnsignedMin(256, length));
	unsigned int threshold = m_ida.GetThreshold();
	while (length > 0)
	{
		size_t len = STDMIN(length, buf.size());
		m_ida.ChannelData(0xffffffff, begin, len, false);
		for (unsigned int i=0; i<threshold-1; i++)
		{
			m_rng.GenerateBlock(buf, len);
			m_ida.ChannelData(i, buf, len, false);
		}
		length -= len;
		begin += len;
	}

	if (messageEnd)
	{
		m_ida.SetAutoSignalPropagation(messageEnd-1);
		if (m_pad)
		{
			SecretSharing::Put(1);
			while (m_ida.InputBuffered(0xffffffff) > 0)
				SecretSharing::Put(0);
		}
		m_ida.ChannelData(0xffffffff, NULL, 0, true);
		for (unsigned int i=0; i<m_ida.GetThreshold()-1; i++)
			m_ida.ChannelData(i, NULL, 0, true);
	}

	return 0;
}
示例#24
0
void MD2::Update(const byte *buf, size_t len)
{
	static const byte S[256] = {
		41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
		19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
		76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
		138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
		245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
		148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
		39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
		181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
		150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
		112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
		96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
		85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
		234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
		129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
		8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
		203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
		166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
		31, 26, 219, 153, 141, 51, 159, 17, 131, 20
	};

	while (len) 
    {
		unsigned int L = UnsignedMin(16U-m_count, len);
		memcpy(m_buf+m_count, buf, L);
		m_count+=L;
		buf+=L;
		len-=L;
		if (m_count==16) 
		{
			byte t;
			int i,j;
			
			m_count=0;
			memcpy(m_X+16, m_buf, 16);
			t=m_C[15];
			for(i=0; i<16; i++)
			{
				m_X[32+i]=m_X[16+i]^m_X[i];
				t=m_C[i]^=S[m_buf[i]^t];
			}
			
			t=0;
			for(i=0; i<18; i++)
			{
				for(j=0; j<48; j+=8)
				{
					t=m_X[j+0]^=S[t];
					t=m_X[j+1]^=S[t];
					t=m_X[j+2]^=S[t];
					t=m_X[j+3]^=S[t];
					t=m_X[j+4]^=S[t];
					t=m_X[j+5]^=S[t];
					t=m_X[j+6]^=S[t];
					t=m_X[j+7]^=S[t];
				}
				t=(t+i) & 0xFF;
			}
		}
    }
}
示例#25
0
size_t NonblockingSource::GeneralPump2(
	lword& byteCount, bool blockingOutput,
	unsigned long maxTime, bool checkDelimiter, byte delimiter)
{
	m_blockedBySpeedLimit = false;

	if (!GetMaxBytesPerSecond())
	{
		size_t ret = DoPump(byteCount, blockingOutput, maxTime, checkDelimiter, delimiter);
		m_doPumpBlocked = (ret != 0);
		return ret;
	}

	bool forever = (maxTime == INFINITE_TIME);
	unsigned long timeToGo = maxTime;
	Timer timer(Timer::MILLISECONDS, forever);
	lword maxSize = byteCount;
	byteCount = 0;

	timer.StartTimer();

	while (true)
	{
		lword curMaxSize = UnsignedMin(ComputeCurrentTransceiveLimit(), maxSize - byteCount);

		if (curMaxSize || m_doPumpBlocked)
		{
			if (!forever) timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime());
			size_t ret = DoPump(curMaxSize, blockingOutput, timeToGo, checkDelimiter, delimiter);
			m_doPumpBlocked = (ret != 0);
			if (curMaxSize)
			{
				NoteTransceive(curMaxSize);
				byteCount += curMaxSize;
			}
			if (ret)
				return ret;
		}

		if (maxSize != ULONG_MAX && byteCount >= maxSize)
			break;

		if (!forever)
		{
			timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime());
			if (!timeToGo)
				break;
		}

		double waitTime = TimeToNextTransceive();
		if (!forever && waitTime > timeToGo)
		{
			m_blockedBySpeedLimit = true;
			break;
		}

		WaitObjectContainer container;
		LimitedBandwidth::GetWaitObjects(container, CallStack("NonblockingSource::GeneralPump2() - speed limit", 0));
		container.Wait((unsigned long)waitTime);
	}

	return 0;
}
示例#26
0
bool WaitObjectContainer::Wait(unsigned long milliseconds)
{
	if (m_noWait || (m_handles.empty() && !m_firstEventTime))
	{
		SetLastResult(LASTRESULT_NOWAIT);
		return true;
	}

	bool timeoutIsScheduledEvent = false;

	if (m_firstEventTime)
	{
		double timeToFirstEvent = SaturatingSubtract(m_firstEventTime, m_eventTimer.ElapsedTimeAsDouble());

		if (timeToFirstEvent <= milliseconds)
		{
			milliseconds = (unsigned long)timeToFirstEvent;
			timeoutIsScheduledEvent = true;
		}

		if (m_handles.empty() || !milliseconds)
		{
			if (milliseconds)
				Sleep(milliseconds);
			SetLastResult(timeoutIsScheduledEvent ? LASTRESULT_SCHEDULED : LASTRESULT_TIMEOUT);
			return timeoutIsScheduledEvent;
		}
	}

	if (m_handles.size() > MAXIMUM_WAIT_OBJECTS)
	{
		// too many wait objects for a single WaitForMultipleObjects call, so use multiple threads
		static const unsigned int WAIT_OBJECTS_PER_THREAD = MAXIMUM_WAIT_OBJECTS-1;
		unsigned int nThreads = (unsigned int)((m_handles.size() + WAIT_OBJECTS_PER_THREAD - 1) / WAIT_OBJECTS_PER_THREAD);
		if (nThreads > MAXIMUM_WAIT_OBJECTS)	// still too many wait objects, maybe implement recursive threading later?
			throw Err("WaitObjectContainer: number of wait objects exceeds limit");
		CreateThreads(nThreads);
		DWORD error = S_OK;
		
		for (unsigned int i=0; i<m_threads.size(); i++)
		{
			WaitingThreadData &thread = *m_threads[i];
			while (!thread.waitingToWait)	// spin until thread is in the initial "waiting to wait" state
				Sleep(0);
			if (i<nThreads)
			{
				thread.waitHandles = &m_handles[i*WAIT_OBJECTS_PER_THREAD];
				thread.count = UnsignedMin(WAIT_OBJECTS_PER_THREAD, m_handles.size() - i*WAIT_OBJECTS_PER_THREAD);
				thread.error = &error;
			}
			else
				thread.count = 0;
		}

		ResetEvent(m_stopWaiting);
		PulseEvent(m_startWaiting);

		DWORD result = ::WaitForSingleObject(m_stopWaiting, milliseconds);
		if (result == WAIT_OBJECT_0)
		{
			if (error == S_OK)
				return true;
			else
				throw Err("WaitObjectContainer: WaitForMultipleObjects in thread failed with error " + IntToString(error));
		}
		SetEvent(m_stopWaiting);
		if (result == WAIT_TIMEOUT)
		{
			SetLastResult(timeoutIsScheduledEvent ? LASTRESULT_SCHEDULED : LASTRESULT_TIMEOUT);
			return timeoutIsScheduledEvent;
		}
		else
			throw Err("WaitObjectContainer: WaitForSingleObject failed with error " + IntToString(::GetLastError()));
	}
	else
	{
#if TRACE_WAIT
		static Timer t(Timer::MICROSECONDS);
		static unsigned long lastTime = 0;
		unsigned long timeBeforeWait = t.ElapsedTime();
#endif
		DWORD result = ::WaitForMultipleObjects((DWORD)m_handles.size(), &m_handles[0], FALSE, milliseconds);
#if TRACE_WAIT
		if (milliseconds > 0)
		{
			unsigned long timeAfterWait = t.ElapsedTime();
			OutputDebugString(("Handles " + IntToString(m_handles.size()) + ", Woke up by " + IntToString(result-WAIT_OBJECT_0) + ", Busied for " + IntToString(timeBeforeWait-lastTime) + " us, Waited for " + IntToString(timeAfterWait-timeBeforeWait) + " us, max " + IntToString(milliseconds) + "ms\n").c_str());
			lastTime = timeAfterWait;
		}
#endif
		if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + m_handles.size())
		{
			if (result == m_lastResult)
				m_sameResultCount++;
			else
			{
				m_lastResult = result;
				m_sameResultCount = 0;
			}
			return true;
		}
		else if (result == WAIT_TIMEOUT)
		{
			SetLastResult(timeoutIsScheduledEvent ? LASTRESULT_SCHEDULED : LASTRESULT_TIMEOUT);
			return timeoutIsScheduledEvent;
		}
		else
			throw Err("WaitObjectContainer: WaitForMultipleObjects failed with error " + IntToString(::GetLastError()));
	}
}
示例#27
0
size_t NetworkSource::DoPump(lword &byteCount, bool blockingOutput, unsigned long maxTime, bool checkDelimiter, byte delimiter)
{
	NetworkReceiver &receiver = AccessReceiver();

	lword maxSize = byteCount;
	byteCount = 0;
	bool forever = maxTime == INFINITE_TIME;
	Timer timer(Timer::MILLISECONDS, forever);
	BufferedTransformation *t = AttachedTransformation();

	if (m_outputBlocked)
		goto DoOutput;

	while (true)
	{
		if (m_dataBegin == m_dataEnd)
		{
			if (receiver.EofReceived())
				break;

			if (m_waitingForResult)
			{
				if (receiver.MustWaitForResult() &&
					!receiver.Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()),
						CallStack("NetworkSource::DoPump() - wait receive result", 0)))
					break;

				unsigned int recvResult = receiver.GetReceiveResult();
#if CRYPTOPP_TRACE_NETWORK
				OutputDebugString((IntToString((unsigned int)this) + ": Received " + IntToString(recvResult) + " bytes\n").c_str());
#endif
				m_dataEnd += recvResult;
				m_waitingForResult = false;

				if (!receiver.MustWaitToReceive() && !receiver.EofReceived() && m_dataEnd != m_buf.size())
					goto ReceiveNoWait;
			}
			else
			{
				m_dataEnd = m_dataBegin = 0;

				if (receiver.MustWaitToReceive())
				{
					if (!receiver.Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()),
							CallStack("NetworkSource::DoPump() - wait receive", 0)))
						break;

					receiver.Receive(m_buf+m_dataEnd, m_buf.size()-m_dataEnd);
					m_waitingForResult = true;
				}
				else
				{
ReceiveNoWait:
					m_waitingForResult = true;
					// call Receive repeatedly as long as data is immediately available,
					// because some receivers tend to return data in small pieces
#if CRYPTOPP_TRACE_NETWORK
					OutputDebugString((IntToString((unsigned int)this) + ": Receiving " + IntToString(m_buf.size()-m_dataEnd) + " bytes\n").c_str());
#endif
					while (receiver.Receive(m_buf+m_dataEnd, m_buf.size()-m_dataEnd))
					{
						unsigned int recvResult = receiver.GetReceiveResult();
#if CRYPTOPP_TRACE_NETWORK
						OutputDebugString((IntToString((unsigned int)this) + ": Received " + IntToString(recvResult) + " bytes\n").c_str());
#endif
						m_dataEnd += recvResult;
						if (receiver.EofReceived() || m_dataEnd > m_buf.size() /2)
						{
							m_waitingForResult = false;
							break;
						}
					}
				}
			}
		}
		else
		{
			m_putSize = UnsignedMin(m_dataEnd - m_dataBegin, maxSize - byteCount);

			if (checkDelimiter)
				m_putSize = std::find(m_buf+m_dataBegin, m_buf+m_dataBegin+m_putSize, delimiter) - (m_buf+m_dataBegin);

DoOutput:
			size_t result = t->PutModifiable2(m_buf+m_dataBegin, m_putSize, 0, forever || blockingOutput);
			if (result)
			{
				if (t->Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()),
						CallStack("NetworkSource::DoPump() - wait attachment", 0)))
					goto DoOutput;
				else
				{
					m_outputBlocked = true;
					return result;
				}
			}
			m_outputBlocked = false;

			byteCount += m_putSize;
			m_dataBegin += m_putSize;
			if (checkDelimiter && m_dataBegin < m_dataEnd && m_buf[m_dataBegin] == delimiter)
				break;
			if (maxSize != ULONG_MAX && byteCount == maxSize)
				break;
			// once time limit is reached, return even if there is more data waiting
			// but make 0 a special case so caller can request a large amount of data to be
			// pumped as long as it is immediately available
			if (maxTime > 0 && timer.ElapsedTime() > maxTime)
				break;
		}
	}

	return 0;
}
示例#28
0
bool Inflator::DecodeBody()
{
    bool blockEnd = false;
    switch (m_blockType)
    {
    case 0:	// stored
        assert(m_reader.BitsBuffered() == 0);
        while (!m_inQueue.IsEmpty() && !blockEnd)
        {
            size_t size;
            const byte *block = m_inQueue.Spy(size);
            size = UnsignedMin(m_storedLen, size);
            OutputString(block, size);
            m_inQueue.Skip(size);
            m_storedLen -= (word16)size;
            if (m_storedLen == 0)
                blockEnd = true;
        }
        break;
    case 1:	// fixed codes
    case 2:	// dynamic codes
        static const unsigned int lengthStarts[] = {
            3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
            35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
        };
        static const unsigned int lengthExtraBits[] = {
            0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
            3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
        };
        static const unsigned int distanceStarts[] = {
            1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
            257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
            8193, 12289, 16385, 24577
        };
        static const unsigned int distanceExtraBits[] = {
            0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
            7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
            12, 12, 13, 13
        };

        const HuffmanDecoder& literalDecoder = GetLiteralDecoder();
        const HuffmanDecoder& distanceDecoder = GetDistanceDecoder();

        switch (m_nextDecode)
        {
        case LITERAL:
            while (true)
            {
                if (!literalDecoder.Decode(m_reader, m_literal))
                {
                    m_nextDecode = LITERAL;
                    break;
                }
                if (m_literal < 256)
                    OutputByte((byte)m_literal);
                else if (m_literal == 256)	// end of block
                {
                    blockEnd = true;
                    break;
                }
                else
                {
                    if (m_literal > 285)
                        throw BadBlockErr();
                    unsigned int bits;
                case LENGTH_BITS:
                    bits = lengthExtraBits[m_literal-257];
                    if (!m_reader.FillBuffer(bits))
                    {
                        m_nextDecode = LENGTH_BITS;
                        break;
                    }
                    m_literal = m_reader.GetBits(bits) + lengthStarts[m_literal-257];
                case DISTANCE:
                    if (!distanceDecoder.Decode(m_reader, m_distance))
                    {
                        m_nextDecode = DISTANCE;
                        break;
                    }
                case DISTANCE_BITS:
                    bits = distanceExtraBits[m_distance];
                    if (!m_reader.FillBuffer(bits))
                    {
                        m_nextDecode = DISTANCE_BITS;
                        break;
                    }
                    m_distance = m_reader.GetBits(bits) + distanceStarts[m_distance];
                    OutputPast(m_literal, m_distance);
                }
            }
        }
    }
    if (blockEnd)
    {
        if (m_eof)
        {
            FlushOutput();
            m_reader.SkipBits(m_reader.BitsBuffered()%8);
            if (m_reader.BitsBuffered())
            {
                // undo too much lookahead
                SecBlockWithHint<byte, 4> buffer(m_reader.BitsBuffered() / 8);
                for (unsigned int i=0; i<buffer.size(); i++)
                    buffer[i] = (byte)m_reader.GetBits(8);
                m_inQueue.Unget(buffer, buffer.size());
            }
            m_state = POST_STREAM;
        }
        else
            m_state = WAIT_HEADER;
    }
    return blockEnd;
}