From 757294d769a7defe6a531a09fba9674cc6b388f7 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Thu, 27 Oct 2011 19:53:48 -0400 Subject: Import boxbackup_0.11.1~r2837.orig.tar.gz [dgit import orig boxbackup_0.11.1~r2837.orig.tar.gz] --- lib/server/Protocol.cpp | 1160 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1160 insertions(+) create mode 100644 lib/server/Protocol.cpp (limited to 'lib/server/Protocol.cpp') diff --git a/lib/server/Protocol.cpp b/lib/server/Protocol.cpp new file mode 100644 index 00000000..5dc5d0b1 --- /dev/null +++ b/lib/server/Protocol.cpp @@ -0,0 +1,1160 @@ +// -------------------------------------------------------------------------- +// +// File +// Name: Protocol.cpp +// Purpose: Generic protocol support +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- + +#include "Box.h" + +#include + +#include +#include + +#include + +#include "Protocol.h" +#include "ProtocolWire.h" +#include "IOStream.h" +#include "ServerException.h" +#include "PartialReadStream.h" +#include "ProtocolUncertainStream.h" +#include "Logging.h" + +#include "MemLeakFindOn.h" + +#ifdef BOX_RELEASE_BUILD + #define PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK 1024 +#else +// #define PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK 1024 + #define PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK 4 +#endif + +#define UNCERTAIN_STREAM_SIZE_BLOCK (64*1024) + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Protocol(IOStream &rStream) +// Purpose: Constructor +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +Protocol::Protocol(IOStream &rStream) + : mrStream(rStream), + mHandshakeDone(false), + mMaxObjectSize(PROTOCOL_DEFAULT_MAXOBJSIZE), + mTimeout(PROTOCOL_DEFAULT_TIMEOUT), + mpBuffer(0), + mBufferSize(0), + mReadOffset(-1), + mWriteOffset(-1), + mValidDataSize(-1), + mLastErrorType(NoError), + mLastErrorSubType(NoError) +{ + BOX_TRACE("Send block allocation size is " << + PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::~Protocol() +// Purpose: Destructor +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +Protocol::~Protocol() +{ + // Free buffer? + if(mpBuffer != 0) + { + free(mpBuffer); + mpBuffer = 0; + } +} + + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::GetLastError(int &, int &) +// Purpose: Returns true if there was an error, and type and subtype if there was. +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +bool Protocol::GetLastError(int &rTypeOut, int &rSubTypeOut) +{ + if(mLastErrorType == NoError) + { + // no error. + return false; + } + + // Return type and subtype in args + rTypeOut = mLastErrorType; + rSubTypeOut = mLastErrorSubType; + + // and unset them + mLastErrorType = NoError; + mLastErrorSubType = NoError; + + return true; +} + + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Handshake() +// Purpose: Handshake with peer (exchange ident strings) +// Created: 2003/08/20 +// +// -------------------------------------------------------------------------- +void Protocol::Handshake() +{ + // Already done? + if(mHandshakeDone) + { + THROW_EXCEPTION(CommonException, Internal) + } + + // Make handshake block + PW_Handshake hsSend; + ::memset(&hsSend, 0, sizeof(hsSend)); + // Copy in ident string + ::strncpy(hsSend.mIdent, GetIdentString(), sizeof(hsSend.mIdent)); + + // Send it + mrStream.Write(&hsSend, sizeof(hsSend)); + mrStream.WriteAllBuffered(); + + // Receive a handshake from the peer + PW_Handshake hsReceive; + ::memset(&hsReceive, 0, sizeof(hsReceive)); + char *readInto = (char*)&hsReceive; + int bytesToRead = sizeof(hsReceive); + while(bytesToRead > 0) + { + // Get some data from the stream + int bytesRead = mrStream.Read(readInto, bytesToRead, mTimeout); + if(bytesRead == 0) + { + THROW_EXCEPTION(ConnectionException, Conn_Protocol_Timeout) + } + readInto += bytesRead; + bytesToRead -= bytesRead; + } + ASSERT(bytesToRead == 0); + + // Are they the same? + if(::memcmp(&hsSend, &hsReceive, sizeof(hsSend)) != 0) + { + THROW_EXCEPTION(ConnectionException, Conn_Protocol_HandshakeFailed) + } + + // Mark as done + mHandshakeDone = true; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::CheckAndReadHdr(void *) +// Purpose: Check read for recieve call and get object header from stream. +// Don't use type here to avoid dependency in .h file. +// Created: 2003/08/26 +// +// -------------------------------------------------------------------------- +void Protocol::CheckAndReadHdr(void *hdr) +{ + // Check usage + if(mValidDataSize != -1 || mWriteOffset != -1 || mReadOffset != -1) + { + THROW_EXCEPTION(ServerException, Protocol_BadUsage) + } + + // Handshake done? + if(!mHandshakeDone) + { + Handshake(); + } + + // Get some data into this header + if(!mrStream.ReadFullBuffer(hdr, sizeof(PW_ObjectHeader), 0 /* not interested in bytes read if this fails */, mTimeout)) + { + THROW_EXCEPTION(ConnectionException, Conn_Protocol_Timeout) + } +} + + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Recieve() +// Purpose: Recieves an object from the stream, creating it from the factory object type +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +std::auto_ptr Protocol::Receive() +{ + // Get object header + PW_ObjectHeader objHeader; + CheckAndReadHdr(&objHeader); + + // Hope it's not a stream + if(ntohl(objHeader.mObjType) == SPECIAL_STREAM_OBJECT_TYPE) + { + THROW_EXCEPTION(ConnectionException, Conn_Protocol_StreamWhenObjExpected) + } + + // Check the object size + u_int32_t objSize = ntohl(objHeader.mObjSize); + if(objSize < sizeof(objHeader) || objSize > mMaxObjectSize) + { + THROW_EXCEPTION(ConnectionException, Conn_Protocol_ObjTooBig) + } + + // Create a blank object + std::auto_ptr obj(MakeProtocolObject(ntohl(objHeader.mObjType))); + + // Make sure memory is allocated to read it into + EnsureBufferAllocated(objSize); + + // Read data + if(!mrStream.ReadFullBuffer(mpBuffer, objSize - sizeof(objHeader), 0 /* not interested in bytes read if this fails */, mTimeout)) + { + THROW_EXCEPTION(ConnectionException, Conn_Protocol_Timeout) + } + + // Setup ready to read out data from the buffer + mValidDataSize = objSize - sizeof(objHeader); + mReadOffset = 0; + + // Get the object to read its properties from the data recieved + try + { + obj->SetPropertiesFromStreamData(*this); + } + catch(...) + { + // Make sure state is reset! + mValidDataSize = -1; + mReadOffset = -1; + throw; + } + + // Any data left over? + bool dataLeftOver = (mValidDataSize != mReadOffset); + + // Unset read state, so future read calls don't fail + mValidDataSize = -1; + mReadOffset = -1; + + // Exception if not all the data was consumed + if(dataLeftOver) + { + THROW_EXCEPTION(ConnectionException, Conn_Protocol_BadCommandRecieved) + } + + return obj; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Send() +// Purpose: Send an object to the other side of the connection. +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Send(const ProtocolObject &rObject) +{ + // Check usage + if(mValidDataSize != -1 || mWriteOffset != -1 || mReadOffset != -1) + { + THROW_EXCEPTION(ServerException, Protocol_BadUsage) + } + + // Handshake done? + if(!mHandshakeDone) + { + Handshake(); + } + + // Make sure there's a little bit of space allocated + EnsureBufferAllocated(((sizeof(PW_ObjectHeader) + PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK - 1) / PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK) * PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK); + ASSERT(mBufferSize >= (int)sizeof(PW_ObjectHeader)); + + // Setup for write operation + mValidDataSize = 0; // Not used, but must not be -1 + mWriteOffset = sizeof(PW_ObjectHeader); + + try + { + rObject.WritePropertiesToStreamData(*this); + } + catch(...) + { + // Make sure state is reset! + mValidDataSize = -1; + mWriteOffset = -1; + throw; + } + + // How big? + int writtenSize = mWriteOffset; + + // Reset write state + mValidDataSize = -1; + mWriteOffset = -1; + + // Make header in the existing block + PW_ObjectHeader *pobjHeader = (PW_ObjectHeader*)(mpBuffer); + pobjHeader->mObjSize = htonl(writtenSize); + pobjHeader->mObjType = htonl(rObject.GetType()); + + // Write data + mrStream.Write(mpBuffer, writtenSize); + mrStream.WriteAllBuffered(); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::EnsureBufferAllocated(int) +// Purpose: Private. Ensures the buffer is at least the size requested. +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::EnsureBufferAllocated(int Size) +{ + if(mpBuffer != 0 && mBufferSize >= Size) + { + // Nothing to do! + return; + } + + // Need to allocate, or reallocate, the block + if(mpBuffer != 0) + { + // Reallocate + void *b = realloc(mpBuffer, Size); + if(b == 0) + { + throw std::bad_alloc(); + } + mpBuffer = (char*)b; + mBufferSize = Size; + } + else + { + // Just allocate + mpBuffer = (char*)malloc(Size); + if(mpBuffer == 0) + { + throw std::bad_alloc(); + } + mBufferSize = Size; + } +} + + +#define READ_START_CHECK \ + if(mValidDataSize == -1 || mWriteOffset != -1 || mReadOffset == -1) \ + { \ + THROW_EXCEPTION(ServerException, Protocol_BadUsage) \ + } + +#define READ_CHECK_BYTES_AVAILABLE(bytesRequired) \ + if((mReadOffset + (int)(bytesRequired)) > mValidDataSize) \ + { \ + THROW_EXCEPTION(ConnectionException, Conn_Protocol_BadCommandRecieved) \ + } + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Read(void *, int) +// Purpose: Read raw data from the stream (buffered) +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Read(void *Buffer, int Size) +{ + READ_START_CHECK + READ_CHECK_BYTES_AVAILABLE(Size) + + // Copy data out + ::memmove(Buffer, mpBuffer + mReadOffset, Size); + mReadOffset += Size; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Read(std::string &, int) +// Purpose: Read raw data from the stream (buffered), into a std::string +// Created: 2003/08/26 +// +// -------------------------------------------------------------------------- +void Protocol::Read(std::string &rOut, int Size) +{ + READ_START_CHECK + READ_CHECK_BYTES_AVAILABLE(Size) + + rOut.assign(mpBuffer + mReadOffset, Size); + mReadOffset += Size; +} + + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Read(int64_t &) +// Purpose: Read a value from the stream (buffered) +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Read(int64_t &rOut) +{ + READ_START_CHECK + READ_CHECK_BYTES_AVAILABLE(sizeof(int64_t)) + +#ifdef HAVE_ALIGNED_ONLY_INT64 + int64_t nvalue; + memcpy(&nvalue, mpBuffer + mReadOffset, sizeof(int64_t)); +#else + int64_t nvalue = *((int64_t*)(mpBuffer + mReadOffset)); +#endif + rOut = box_ntoh64(nvalue); + + mReadOffset += sizeof(int64_t); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Read(int32_t &) +// Purpose: Read a value from the stream (buffered) +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Read(int32_t &rOut) +{ + READ_START_CHECK + READ_CHECK_BYTES_AVAILABLE(sizeof(int32_t)) + +#ifdef HAVE_ALIGNED_ONLY_INT32 + int32_t nvalue; + memcpy(&nvalue, mpBuffer + mReadOffset, sizeof(int32_t)); +#else + int32_t nvalue = *((int32_t*)(mpBuffer + mReadOffset)); +#endif + rOut = ntohl(nvalue); + mReadOffset += sizeof(int32_t); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Read(int16_t &) +// Purpose: Read a value from the stream (buffered) +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Read(int16_t &rOut) +{ + READ_START_CHECK + READ_CHECK_BYTES_AVAILABLE(sizeof(int16_t)) + + rOut = ntohs(*((int16_t*)(mpBuffer + mReadOffset))); + mReadOffset += sizeof(int16_t); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Read(int8_t &) +// Purpose: Read a value from the stream (buffered) +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Read(int8_t &rOut) +{ + READ_START_CHECK + READ_CHECK_BYTES_AVAILABLE(sizeof(int8_t)) + + rOut = *((int8_t*)(mpBuffer + mReadOffset)); + mReadOffset += sizeof(int8_t); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Read(std::string &) +// Purpose: Read a value from the stream (buffered) +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Read(std::string &rOut) +{ + // READ_START_CHECK implied + int32_t size; + Read(size); + + READ_CHECK_BYTES_AVAILABLE(size) + + // initialise string + rOut.assign(mpBuffer + mReadOffset, size); + mReadOffset += size; +} + + + + +#define WRITE_START_CHECK \ + if(mValidDataSize == -1 || mWriteOffset == -1 || mReadOffset != -1) \ + { \ + THROW_EXCEPTION(ServerException, Protocol_BadUsage) \ + } + +#define WRITE_ENSURE_BYTES_AVAILABLE(bytesToWrite) \ + if(mWriteOffset + (int)(bytesToWrite) > mBufferSize) \ + { \ + EnsureBufferAllocated((((mWriteOffset + (int)(bytesToWrite)) + PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK - 1) / PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK) * PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK); \ + ASSERT(mWriteOffset + (int)(bytesToWrite) <= mBufferSize); \ + } + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Write(const void *, int) +// Purpose: Writes the contents of a buffer to the stream +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Write(const void *Buffer, int Size) +{ + WRITE_START_CHECK + WRITE_ENSURE_BYTES_AVAILABLE(Size) + + ::memmove(mpBuffer + mWriteOffset, Buffer, Size); + mWriteOffset += Size; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Write(int64_t) +// Purpose: Writes a value to the stream +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Write(int64_t Value) +{ + WRITE_START_CHECK + WRITE_ENSURE_BYTES_AVAILABLE(sizeof(int64_t)) + + int64_t nvalue = box_hton64(Value); +#ifdef HAVE_ALIGNED_ONLY_INT64 + memcpy(mpBuffer + mWriteOffset, &nvalue, sizeof(int64_t)); +#else + *((int64_t*)(mpBuffer + mWriteOffset)) = nvalue; +#endif + mWriteOffset += sizeof(int64_t); +} + + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Write(int32_t) +// Purpose: Writes a value to the stream +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Write(int32_t Value) +{ + WRITE_START_CHECK + WRITE_ENSURE_BYTES_AVAILABLE(sizeof(int32_t)) + + int32_t nvalue = htonl(Value); +#ifdef HAVE_ALIGNED_ONLY_INT32 + memcpy(mpBuffer + mWriteOffset, &nvalue, sizeof(int32_t)); +#else + *((int32_t*)(mpBuffer + mWriteOffset)) = nvalue; +#endif + mWriteOffset += sizeof(int32_t); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Write(int16_t) +// Purpose: Writes a value to the stream +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Write(int16_t Value) +{ + WRITE_START_CHECK + WRITE_ENSURE_BYTES_AVAILABLE(sizeof(int16_t)) + + *((int16_t*)(mpBuffer + mWriteOffset)) = htons(Value); + mWriteOffset += sizeof(int16_t); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Write(int8_t) +// Purpose: Writes a value to the stream +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Write(int8_t Value) +{ + WRITE_START_CHECK + WRITE_ENSURE_BYTES_AVAILABLE(sizeof(int8_t)) + + *((int8_t*)(mpBuffer + mWriteOffset)) = Value; + mWriteOffset += sizeof(int8_t); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::Write(const std::string &) +// Purpose: Writes a value to the stream +// Created: 2003/08/19 +// +// -------------------------------------------------------------------------- +void Protocol::Write(const std::string &rValue) +{ + // WRITE_START_CHECK implied + Write((int32_t)(rValue.size())); + + WRITE_ENSURE_BYTES_AVAILABLE(rValue.size()) + Write(rValue.c_str(), rValue.size()); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::ReceieveStream() +// Purpose: Receive a stream from the remote side +// Created: 2003/08/26 +// +// -------------------------------------------------------------------------- +std::auto_ptr Protocol::ReceiveStream() +{ + // Get object header + PW_ObjectHeader objHeader; + CheckAndReadHdr(&objHeader); + + // Hope it's not an object + if(ntohl(objHeader.mObjType) != SPECIAL_STREAM_OBJECT_TYPE) + { + THROW_EXCEPTION(ConnectionException, Conn_Protocol_ObjWhenStreamExpected) + } + + // Get the stream size + u_int32_t streamSize = ntohl(objHeader.mObjSize); + + // Inform sub class + InformStreamReceiving(streamSize); + + // Return a stream object + if(streamSize == ProtocolStream_SizeUncertain) + { + BOX_TRACE("Receiving stream, size uncertain"); + return std::auto_ptr( + new ProtocolUncertainStream(mrStream)); + } + else + { + BOX_TRACE("Receiving stream, size " << streamSize << " bytes"); + return std::auto_ptr( + new PartialReadStream(mrStream, streamSize)); + } +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::SendStream(IOStream &) +// Purpose: Send a stream to the remote side +// Created: 2003/08/26 +// +// -------------------------------------------------------------------------- +void Protocol::SendStream(IOStream &rStream) +{ + // Check usage + if(mValidDataSize != -1 || mWriteOffset != -1 || mReadOffset != -1) + { + THROW_EXCEPTION(ServerException, Protocol_BadUsage) + } + + // Handshake done? + if(!mHandshakeDone) + { + Handshake(); + } + + // How should this be streamed? + bool uncertainSize = false; + IOStream::pos_type streamSize = rStream.BytesLeftToRead(); + if(streamSize == IOStream::SizeOfStreamUnknown + || streamSize > 0x7fffffff) + { + // Can't send this using the fixed size header + uncertainSize = true; + } + + // Inform sub class + InformStreamSending(streamSize); + + // Make header + PW_ObjectHeader objHeader; + objHeader.mObjSize = htonl(uncertainSize?(ProtocolStream_SizeUncertain):streamSize); + objHeader.mObjType = htonl(SPECIAL_STREAM_OBJECT_TYPE); + + // Write header + mrStream.Write(&objHeader, sizeof(objHeader)); + // Could be sent in one of two ways + if(uncertainSize) + { + // Don't know how big this is going to be -- so send it in chunks + + // Allocate memory + uint8_t *blockA = (uint8_t *)malloc(UNCERTAIN_STREAM_SIZE_BLOCK + sizeof(int)); + if(blockA == 0) + { + throw std::bad_alloc(); + } + uint8_t *block = blockA + sizeof(int); // so that everything is word aligned for reading, but can put the one byte header before it + + try + { + int bytesInBlock = 0; + while(rStream.StreamDataLeft()) + { + // Read some of it + bytesInBlock += rStream.Read(block + bytesInBlock, UNCERTAIN_STREAM_SIZE_BLOCK - bytesInBlock); + + // Send as much as we can out + bytesInBlock -= SendStreamSendBlock(block, bytesInBlock); + } + + // Everything recieved from stream, but need to send whatevers left in the block + while(bytesInBlock > 0) + { + bytesInBlock -= SendStreamSendBlock(block, bytesInBlock); + } + + // Send final byte to finish the stream + BOX_TRACE("Sending end of stream byte"); + uint8_t endOfStream = ProtocolStreamHeader_EndOfStream; + mrStream.Write(&endOfStream, 1); + BOX_TRACE("Sent end of stream byte"); + } + catch(...) + { + free(blockA); + throw; + } + + // Clean up + free(blockA); + } + else + { + // Fixed size stream, send it all in one go + if(!rStream.CopyStreamTo(mrStream, mTimeout, 4096 /* slightly larger buffer */)) + { + THROW_EXCEPTION(ConnectionException, Conn_Protocol_TimeOutWhenSendingStream) + } + } + // Make sure everything is written + mrStream.WriteAllBuffered(); + +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::SendStreamSendBlock(uint8_t *, int) +// Purpose: Sends as much of the block as can be sent, moves the remainer down to the beginning, +// and returns the number of bytes sent. WARNING: Will write to Block[-1] +// Created: 5/12/03 +// +// -------------------------------------------------------------------------- +int Protocol::SendStreamSendBlock(uint8_t *Block, int BytesInBlock) +{ + // Quick sanity check + if(BytesInBlock == 0) + { + BOX_TRACE("Zero size block, not sending anything"); + return 0; + } + + // Work out the header byte + uint8_t header = 0; + int writeSize = 0; + if(BytesInBlock >= (64*1024)) + { + header = ProtocolStreamHeader_SizeIs64k; + writeSize = (64*1024); + } + else + { + // Scan the table to find the most that can be written + for(int s = ProtocolStreamHeader_MaxEncodedSizeValue; s > 0; --s) + { + if(sProtocolStreamHeaderLengths[s] <= BytesInBlock) + { + header = s; + writeSize = sProtocolStreamHeaderLengths[s]; + break; + } + } + } + ASSERT(header > 0); + BOX_TRACE("Sending header byte " << (int)header << " plus " << + writeSize << " bytes to stream"); + + // Store the header + Block[-1] = header; + + // Write everything out + mrStream.Write(Block - 1, writeSize + 1); + + BOX_TRACE("Sent " << (writeSize+1) << " bytes to stream"); + // move the remainer to the beginning of the block for the next time round + if(writeSize != BytesInBlock) + { + ::memmove(Block, Block + writeSize, BytesInBlock - writeSize); + } + + return writeSize; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::InformStreamReceiving(u_int32_t) +// Purpose: Informs sub classes about streams being received +// Created: 2003/10/27 +// +// -------------------------------------------------------------------------- +void Protocol::InformStreamReceiving(u_int32_t Size) +{ + // Do nothing +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Protocol::InformStreamSending(u_int32_t) +// Purpose: Informs sub classes about streams being sent +// Created: 2003/10/27 +// +// -------------------------------------------------------------------------- +void Protocol::InformStreamSending(u_int32_t Size) +{ + // Do nothing +} + + +/* +perl code to generate the table below + +#!/usr/bin/perl +use strict; +open OUT,">protolengths.txt"; +my $len = 0; +for(0 .. 255) +{ + print OUT "\t$len,\t// $_\n"; + my $inc = 1; + $inc = 8 if $_ >= 64; + $inc = 16 if $_ >= 96; + $inc = 32 if $_ >= 112; + $inc = 64 if $_ >= 128; + $inc = 128 if $_ >= 135; + $inc = 256 if $_ >= 147; + $inc = 512 if $_ >= 159; + $inc = 1024 if $_ >= 231; + $len += $inc; +} +close OUT; + +*/ +const uint16_t Protocol::sProtocolStreamHeaderLengths[256] = +{ + 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 + 14, // 14 + 15, // 15 + 16, // 16 + 17, // 17 + 18, // 18 + 19, // 19 + 20, // 20 + 21, // 21 + 22, // 22 + 23, // 23 + 24, // 24 + 25, // 25 + 26, // 26 + 27, // 27 + 28, // 28 + 29, // 29 + 30, // 30 + 31, // 31 + 32, // 32 + 33, // 33 + 34, // 34 + 35, // 35 + 36, // 36 + 37, // 37 + 38, // 38 + 39, // 39 + 40, // 40 + 41, // 41 + 42, // 42 + 43, // 43 + 44, // 44 + 45, // 45 + 46, // 46 + 47, // 47 + 48, // 48 + 49, // 49 + 50, // 50 + 51, // 51 + 52, // 52 + 53, // 53 + 54, // 54 + 55, // 55 + 56, // 56 + 57, // 57 + 58, // 58 + 59, // 59 + 60, // 60 + 61, // 61 + 62, // 62 + 63, // 63 + 64, // 64 + 72, // 65 + 80, // 66 + 88, // 67 + 96, // 68 + 104, // 69 + 112, // 70 + 120, // 71 + 128, // 72 + 136, // 73 + 144, // 74 + 152, // 75 + 160, // 76 + 168, // 77 + 176, // 78 + 184, // 79 + 192, // 80 + 200, // 81 + 208, // 82 + 216, // 83 + 224, // 84 + 232, // 85 + 240, // 86 + 248, // 87 + 256, // 88 + 264, // 89 + 272, // 90 + 280, // 91 + 288, // 92 + 296, // 93 + 304, // 94 + 312, // 95 + 320, // 96 + 336, // 97 + 352, // 98 + 368, // 99 + 384, // 100 + 400, // 101 + 416, // 102 + 432, // 103 + 448, // 104 + 464, // 105 + 480, // 106 + 496, // 107 + 512, // 108 + 528, // 109 + 544, // 110 + 560, // 111 + 576, // 112 + 608, // 113 + 640, // 114 + 672, // 115 + 704, // 116 + 736, // 117 + 768, // 118 + 800, // 119 + 832, // 120 + 864, // 121 + 896, // 122 + 928, // 123 + 960, // 124 + 992, // 125 + 1024, // 126 + 1056, // 127 + 1088, // 128 + 1152, // 129 + 1216, // 130 + 1280, // 131 + 1344, // 132 + 1408, // 133 + 1472, // 134 + 1536, // 135 + 1664, // 136 + 1792, // 137 + 1920, // 138 + 2048, // 139 + 2176, // 140 + 2304, // 141 + 2432, // 142 + 2560, // 143 + 2688, // 144 + 2816, // 145 + 2944, // 146 + 3072, // 147 + 3328, // 148 + 3584, // 149 + 3840, // 150 + 4096, // 151 + 4352, // 152 + 4608, // 153 + 4864, // 154 + 5120, // 155 + 5376, // 156 + 5632, // 157 + 5888, // 158 + 6144, // 159 + 6656, // 160 + 7168, // 161 + 7680, // 162 + 8192, // 163 + 8704, // 164 + 9216, // 165 + 9728, // 166 + 10240, // 167 + 10752, // 168 + 11264, // 169 + 11776, // 170 + 12288, // 171 + 12800, // 172 + 13312, // 173 + 13824, // 174 + 14336, // 175 + 14848, // 176 + 15360, // 177 + 15872, // 178 + 16384, // 179 + 16896, // 180 + 17408, // 181 + 17920, // 182 + 18432, // 183 + 18944, // 184 + 19456, // 185 + 19968, // 186 + 20480, // 187 + 20992, // 188 + 21504, // 189 + 22016, // 190 + 22528, // 191 + 23040, // 192 + 23552, // 193 + 24064, // 194 + 24576, // 195 + 25088, // 196 + 25600, // 197 + 26112, // 198 + 26624, // 199 + 27136, // 200 + 27648, // 201 + 28160, // 202 + 28672, // 203 + 29184, // 204 + 29696, // 205 + 30208, // 206 + 30720, // 207 + 31232, // 208 + 31744, // 209 + 32256, // 210 + 32768, // 211 + 33280, // 212 + 33792, // 213 + 34304, // 214 + 34816, // 215 + 35328, // 216 + 35840, // 217 + 36352, // 218 + 36864, // 219 + 37376, // 220 + 37888, // 221 + 38400, // 222 + 38912, // 223 + 39424, // 224 + 39936, // 225 + 40448, // 226 + 40960, // 227 + 41472, // 228 + 41984, // 229 + 42496, // 230 + 43008, // 231 + 44032, // 232 + 45056, // 233 + 46080, // 234 + 47104, // 235 + 48128, // 236 + 49152, // 237 + 50176, // 238 + 51200, // 239 + 52224, // 240 + 53248, // 241 + 54272, // 242 + 55296, // 243 + 56320, // 244 + 57344, // 245 + 58368, // 246 + 59392, // 247 + 60416, // 248 + 61440, // 249 + 62464, // 250 + 63488, // 251 + 64512, // 252 + 0, // 253 = 65536 / 64k + 0, // 254 = special (reserved) + 0 // 255 = special (reserved) +}; + + + + -- cgit v1.2.3