2001-10-06 14:13:28 +00:00
|
|
|
#include "CInputPacketStream.h"
|
|
|
|
#include "CLock.h"
|
|
|
|
|
|
|
|
//
|
|
|
|
// CInputPacketStream
|
|
|
|
//
|
|
|
|
|
2002-06-17 13:31:21 +00:00
|
|
|
CInputPacketStream::CInputPacketStream(IInputStream* stream, bool adopt) :
|
2002-06-10 22:06:45 +00:00
|
|
|
CInputStreamFilter(stream, adopt),
|
|
|
|
m_mutex(),
|
|
|
|
m_size(0),
|
|
|
|
m_buffer(&m_mutex, NULL)
|
2001-10-06 14:13:28 +00:00
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
CInputPacketStream::~CInputPacketStream()
|
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
2002-06-10 22:06:45 +00:00
|
|
|
void
|
|
|
|
CInputPacketStream::close()
|
2001-10-06 14:13:28 +00:00
|
|
|
{
|
|
|
|
getStream()->close();
|
|
|
|
}
|
|
|
|
|
2002-06-10 22:06:45 +00:00
|
|
|
UInt32
|
2002-06-17 13:31:21 +00:00
|
|
|
CInputPacketStream::read(void* buffer, UInt32 n)
|
2001-10-06 14:13:28 +00:00
|
|
|
{
|
|
|
|
CLock lock(&m_mutex);
|
|
|
|
|
|
|
|
// wait for entire message to be read. return immediately if
|
|
|
|
// stream hungup.
|
2002-06-26 13:31:06 +00:00
|
|
|
if (!waitForFullMessage()) {
|
2001-10-06 14:13:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// limit number of bytes to read to the number of bytes left in the
|
|
|
|
// current message.
|
|
|
|
if (n > m_size) {
|
|
|
|
n = m_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
// now read from our buffer
|
|
|
|
n = m_buffer.readNoLock(buffer, n);
|
|
|
|
assert(n <= m_size);
|
|
|
|
m_size -= n;
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2002-06-10 22:06:45 +00:00
|
|
|
UInt32
|
|
|
|
CInputPacketStream::getSize() const
|
2001-10-06 14:13:28 +00:00
|
|
|
{
|
|
|
|
CLock lock(&m_mutex);
|
|
|
|
return getSizeNoLock();
|
|
|
|
}
|
|
|
|
|
2002-06-10 22:06:45 +00:00
|
|
|
UInt32
|
|
|
|
CInputPacketStream::getSizeNoLock() const
|
2001-10-06 14:13:28 +00:00
|
|
|
{
|
2002-06-26 13:31:06 +00:00
|
|
|
while (!hasFullMessage() && getStream()->getSize() > 0) {
|
2001-10-06 14:13:28 +00:00
|
|
|
// read more data
|
2002-06-26 13:31:06 +00:00
|
|
|
if (!getMoreMessage()) {
|
|
|
|
// stream hungup
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_size;
|
|
|
|
}
|
2001-10-06 14:13:28 +00:00
|
|
|
|
2002-06-26 13:31:06 +00:00
|
|
|
bool
|
|
|
|
CInputPacketStream::waitForFullMessage() const
|
|
|
|
{
|
|
|
|
while (!hasFullMessage()) {
|
|
|
|
// read more data
|
|
|
|
if (!getMoreMessage()) {
|
|
|
|
// stream hungup
|
|
|
|
return false;
|
2001-10-06 14:13:28 +00:00
|
|
|
}
|
2002-06-26 13:31:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2001-10-06 14:13:28 +00:00
|
|
|
|
2002-06-26 13:31:06 +00:00
|
|
|
bool
|
|
|
|
CInputPacketStream::getMoreMessage() const
|
|
|
|
{
|
|
|
|
// read more data
|
|
|
|
char buffer[4096];
|
|
|
|
UInt32 n = getStream()->read(buffer, sizeof(buffer));
|
|
|
|
|
|
|
|
// return if stream hungup
|
|
|
|
if (n == 0) {
|
|
|
|
m_buffer.hangup();
|
|
|
|
return false;
|
2001-10-06 14:13:28 +00:00
|
|
|
}
|
|
|
|
|
2002-06-26 13:31:06 +00:00
|
|
|
// append to our buffer
|
|
|
|
m_buffer.write(buffer, n);
|
|
|
|
|
|
|
|
return true;
|
2001-10-06 14:13:28 +00:00
|
|
|
}
|
|
|
|
|
2002-06-10 22:06:45 +00:00
|
|
|
bool
|
|
|
|
CInputPacketStream::hasFullMessage() const
|
2001-10-06 14:13:28 +00:00
|
|
|
{
|
|
|
|
// get payload length if we don't have it yet
|
|
|
|
if (m_size == 0) {
|
|
|
|
// check if length field has been read yet
|
|
|
|
if (m_buffer.getSizeNoLock() < 4) {
|
|
|
|
// not enough data for payload length
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// save payload length
|
|
|
|
UInt8 buffer[4];
|
|
|
|
UInt32 n = m_buffer.readNoLock(buffer, sizeof(buffer));
|
|
|
|
assert(n == 4);
|
|
|
|
m_size = ((UInt32)buffer[0] << 24) |
|
|
|
|
((UInt32)buffer[1] << 16) |
|
|
|
|
((UInt32)buffer[2] << 8) |
|
|
|
|
(UInt32)buffer[3];
|
|
|
|
|
|
|
|
// if payload length is zero then discard null message
|
|
|
|
if (m_size == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(m_size > 0);
|
|
|
|
|
|
|
|
// we have the full message when we have at least m_size bytes in
|
|
|
|
// the buffer
|
|
|
|
return (m_buffer.getSizeNoLock() >= m_size);
|
|
|
|
}
|