void ReceivedMessageArgumentIterator::Advance() { if( !value_.typeTag_ ) return; switch( *value_.typeTag_++ ){ case '\0': // don't advance past end --value_.typeTag_; break; case TRUE_TYPE_TAG: case FALSE_TYPE_TAG: case NIL_TYPE_TAG: case INFINITUM_TYPE_TAG: case ARRAY_START_TYPE_TAG: case ARRAY_END_TYPE_TAG: // zero length break; case INT32_TYPE_TAG: case FLOAT_TYPE_TAG: case CHAR_TYPE_TAG: case RGBA_COLOR_TYPE_TAG: case MIDI_MESSAGE_TYPE_TAG: value_.argument_ += 4; break; case INT64_TYPE_TAG: case TIME_TAG_TYPE_TAG: case DOUBLE_TYPE_TAG: value_.argument_ += 8; break; case STRING_TYPE_TAG: case SYMBOL_TYPE_TAG: // we use the unsafe function FindStr4End(char*) here because all of // the arguments have already been validated in // ReceivedMessage::Init() below. value_.argument_ = FindStr4End( value_.argument_ ); break; case BLOB_TYPE_TAG: { uint32 blobSize = ToUInt32( value_.argument_ ); value_.argument_ = value_.argument_ + 4 + RoundUp4( (unsigned long)blobSize ); } break; default: // unknown type tag // don't advance --value_.typeTag_; break; } }
Errors OutboundPacketStream::CheckForAvailableArgumentSpace( std::size_t argumentLength ) { // plus three for extra type tag, comma and null terminator std::size_t required = (argumentCurrent_ - data_) + argumentLength + RoundUp4( (end_ - typeTagsCurrent_) + 3 ); return (required > Capacity()) ? OUT_OF_BUFFER_MEMORY_ERROR : SUCCESS; }
Errors OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern ) { // plus 4 for at least four bytes of type tag std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0) + RoundUp4(std::strlen(addressPattern) + 1) + 4; return (required > Capacity()) ? OUT_OF_BUFFER_MEMORY_ERROR : SUCCESS; }
void OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern ) { // plus 4 for at least four bytes of type tag unsigned long required = Size() + ((ElementSizeSlotRequired()) ? 4 : 0) + RoundUp4(static_cast<unsigned long>(strlen(addressPattern)) + 1) + 4; if( required > Capacity() ) throw OutOfBufferMemoryException(); }
void NxDeviceOscOutputMessage::CheckForAvailableMessageSpace( const char *addressPattern ) { // plus 4 for at least four bytes of type tag unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0) + RoundUp4(strlen(addressPattern) + 1) + 4; if( required > Capacity() ) throw OutOfBufferMemoryException(); }
void OutboundPacketStream::CheckForAvailableArgumentSpace( long argumentLength ) { // plus three for extra type tag, comma and null terminator unsigned long required = (argumentCurrent_ - data_) + argumentLength + RoundUp4( (end_ - typeTagsCurrent_) + 3 ); if( required > Capacity() ) throw OutOfBufferMemoryException(); }
int GetPropertyReplyStore::decodeIdentity(DecodeBuffer &decodeBuffer, unsigned char *&buffer, unsigned int &size, int bigEndian, WriteBuffer *writeBuffer, ChannelCache *channelCache) const { ServerCache *serverCache = (ServerCache *) channelCache; #ifdef DEBUG *logofs << name() << ": Decoding full message identity.\n" << logofs_flush; #endif unsigned char format; decodeBuffer.decodeCachedValue(format, 8, serverCache -> getPropertyFormatCache); unsigned int length; decodeBuffer.decodeValue(length, 32, 9); unsigned int numBytes = length; if (format == 16) { numBytes <<= 1; } else if (format == 32) { numBytes <<= 2; } size = 32 + RoundUp4(numBytes); buffer = writeBuffer -> addMessage(size); *(buffer + 1) = format; PutULONG(length, buffer + 16, bigEndian); unsigned int value; decodeBuffer.decodeCachedValue(value, 29, serverCache -> getPropertyTypeCache, 9); PutULONG(value, buffer + 8, bigEndian); decodeBuffer.decodeValue(value, 32, 9); PutULONG(value, buffer + 12, bigEndian); #ifdef DEBUG *logofs << name() << ": Decoded full message identity.\n" << logofs_flush; #endif return 1; }
unsigned int OutboundPacketStream::Size() const { unsigned int result = argumentCurrent_ - data_; if( IsMessageInProgress() ){ // account for the length of the type tag string. the total type tag // includes an initial comma, plus at least one terminating \0 result += RoundUp4( (end_ - typeTagsCurrent_) + 2 ); } return result; }
OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator& rhs ) { (void) rhs; if( !IsMessageInProgress() ) throw MessageNotInProgressException(); int typeTagsCount = end_ - typeTagsCurrent_; if( typeTagsCount ){ char *tempTypeTags = (char*)alloca(typeTagsCount); memcpy( tempTypeTags, typeTagsCurrent_, typeTagsCount ); // slot size includes comma and null terminator int typeTagSlotSize = RoundUp4( typeTagsCount + 2 ); uint32 argumentsSize = argumentCurrent_ - messageCursor_; memmove( messageCursor_ + typeTagSlotSize, messageCursor_, argumentsSize ); messageCursor_[0] = ','; // copy type tags in reverse (really forward) order for( int i=0; i < typeTagsCount; ++i ) messageCursor_[i+1] = tempTypeTags[ (typeTagsCount-1) - i ]; char *p = messageCursor_ + 1 + typeTagsCount; for( int i=0; i < (typeTagSlotSize - (typeTagsCount + 1)); ++i ) *p++ = '\0'; typeTagsCurrent_ = end_; // advance messageCursor_ for next message messageCursor_ += typeTagSlotSize + argumentsSize; }else{ // send an empty type tags string memcpy( messageCursor_, ",\0\0\0", 4 ); // advance messageCursor_ for next message messageCursor_ += 4; } argumentCurrent_ = messageCursor_; EndElement( messageCursor_ ); messageIsInProgress_ = false; return *this; }
int SetUnpackColormapStore::decodeIdentity(DecodeBuffer &decodeBuffer, unsigned char *&buffer, unsigned int &size, int bigEndian, WriteBuffer *writeBuffer, ChannelCache *channelCache) const { ClientCache *clientCache = (ClientCache *) channelCache; #ifdef DEBUG *logofs << name() << ": Decoding full message identity.\n" << logofs_flush; #endif unsigned int value; unsigned char cValue; // SrcLength. decodeBuffer.decodeValue(value, 32, 9); size = RoundUp4(value) + 16; buffer = writeBuffer -> addMessage(size); PutULONG(value, buffer + 8, bigEndian); // Client. decodeBuffer.decodeCachedValue(cValue, 8, clientCache -> resourceCache); *(buffer + 1) = cValue; // Method. decodeBuffer.decodeCachedValue(cValue, 8, clientCache -> methodCache); *(buffer + 4) = cValue; // DstLength. decodeBuffer.decodeValue(value, 32, 9); PutULONG(value, buffer + 12, bigEndian); #ifdef DEBUG *logofs << name() << ": Decoded full message identity.\n" << logofs_flush; #endif return 1; }
OutboundPacketStream& OutboundPacketStream::operator<<(const char* rhs) { CheckForAvailableArgumentSpace(RoundUp4(static_cast<long>(strlen(rhs)) + 1)); *--typeTagsCurrent_ = STRING_TYPE_TAG; strcpy(argumentCurrent_, rhs); unsigned long rhsLength = static_cast<unsigned long>(strlen(rhs)); argumentCurrent_ += rhsLength + 1; // zero pad to 4-byte boundary unsigned long i = rhsLength + 1; while (i & 0x3) { *argumentCurrent_++ = '\0'; ++i; } return *this; }
NxDeviceOscOutputMessage& NxDeviceOscOutputMessage::operator<<( const char *rhs ) { CheckForAvailableArgumentSpace( RoundUp4(strlen(rhs) + 1) ); *(--typeTagsCurrent_) = STRING_TYPE_TAG; strcpy( argumentCurrent_, rhs ); unsigned long rhsLength = strlen(rhs); argumentCurrent_ += rhsLength + 1; // zero pad to 4-byte boundary unsigned long i = rhsLength + 1; while( i & 0x3 ){ *argumentCurrent_++ = '\0'; ++i; } return *this; }
OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs ) { CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) ); *(--typeTagsCurrent_) = STRING_TYPE_TAG; std::strcpy( argumentCurrent_, rhs ); std::size_t rhsLength = std::strlen(rhs); argumentCurrent_ += rhsLength + 1; // zero pad to 4-byte boundary std::size_t i = rhsLength + 1; while( i & 0x3 ){ *argumentCurrent_++ = '\0'; ++i; } return *this; }
OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs ) { CheckForAvailableArgumentSpace( RoundUp4(strlen(rhs) + 1) ); *(--typeTagsCurrent_) = SYMBOL_TYPE_TAG; strcpy( argumentCurrent_, rhs ); unsigned long rhsLength = strlen(rhs); argumentCurrent_ += rhsLength + 1; // zero pad to 4-byte boundary unsigned long i = rhsLength + 1; while( i & 0x3 ){ *argumentCurrent_++ = '\0'; ++i; } return *this; }
OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs ) { CheckForAvailableArgumentSpace( 4 + RoundUp4(rhs.size) ); *(--typeTagsCurrent_) = BLOB_TYPE_TAG; FromUInt32( argumentCurrent_, rhs.size ); argumentCurrent_ += 4; memcpy( argumentCurrent_, rhs.data, rhs.size ); argumentCurrent_ += rhs.size; // zero pad to 4-byte boundary unsigned long i = rhs.size; while( i & 0x3 ){ *argumentCurrent_++ = '\0'; ++i; } return *this; }
OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs ) { state_ = CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) ); if(state_ == SUCCESS) { *(--typeTagsCurrent_) = SYMBOL_TYPE_TAG; std::strcpy( argumentCurrent_, rhs ); std::size_t rhsLength = std::strlen(rhs); argumentCurrent_ += rhsLength + 1; // zero pad to 4-byte boundary std::size_t i = rhsLength + 1; while( i & 0x3 ){ *argumentCurrent_++ = '\0'; ++i; } } return *this; }
static int32 RoundUpForPixelSize (uint32 x, uint32 pixelSize) { switch (pixelSize) { case 1: return RoundUp16 (x); case 2: return RoundUp8 (x); case 4: return RoundUp4 (x); case 8: return RoundUp2 (x); default: return RoundUp16 (x); } }
void ReceivedMessageArgumentIterator::Advance() { if( !value_.typeTag_ ) return; switch( *value_.typeTag_++ ){ case '\0': // don't advance past end --value_.typeTag_; break; case TRUE_TYPE_TAG: case FALSE_TYPE_TAG: case NIL_TYPE_TAG: case INFINITUM_TYPE_TAG: // zero length break; case INT32_TYPE_TAG: case FLOAT_TYPE_TAG: case CHAR_TYPE_TAG: case RGBA_COLOR_TYPE_TAG: case MIDI_MESSAGE_TYPE_TAG: value_.argument_ += 4; break; case INT64_TYPE_TAG: case TIME_TAG_TYPE_TAG: case DOUBLE_TYPE_TAG: value_.argument_ += 8; break; case STRING_TYPE_TAG: case SYMBOL_TYPE_TAG: // we use the unsafe function FindStr4End(char*) here because all of // the arguments have already been validated in // ReceivedMessage::Init() below. value_.argument_ = FindStr4End( value_.argument_ ); break; case BLOB_TYPE_TAG: { uint32 blobSize = ToUInt32( value_.argument_ ); value_.argument_ = value_.argument_ + 4 + RoundUp4( (unsigned long)blobSize ); } break; default: // unknown type tag // don't advance --value_.typeTag_; break; // not handled: // [ Indicates the beginning of an array. The tags following are for // data in the Array until a close brace tag is reached. // ] Indicates the end of an array. } }
void ReceivedMessage::Init( const char *message, unsigned long size ) { if( size == 0 ) throw MalformedMessageException( "zero length messages not permitted" ); if( (size & 0x03L) != 0 ) throw MalformedMessageException( "message size must be multiple of four" ); const char *end = message + size; typeTagsBegin_ = FindStr4End( addressPattern_, end ); if( typeTagsBegin_ == 0 ){ // address pattern was not terminated before end throw MalformedMessageException( "unterminated address pattern" ); } if( typeTagsBegin_ == end ){ // message consists of only the address pattern - no arguments or type tags. typeTagsBegin_ = 0; typeTagsEnd_ = 0; arguments_ = 0; }else{ if( *typeTagsBegin_ != ',' ) throw MalformedMessageException( "type tags not present" ); if( *(typeTagsBegin_ + 1) == '\0' ){ // zero length type tags typeTagsBegin_ = 0; typeTagsEnd_ = 0; arguments_ = 0; }else{ // check that all arguments are present and well formed arguments_ = FindStr4End( typeTagsBegin_, end ); if( arguments_ == 0 ){ throw MalformedMessageException( "type tags were not terminated before end of message" ); } ++typeTagsBegin_; // advance past initial ',' const char *typeTag = typeTagsBegin_; const char *argument = arguments_; do{ switch( *typeTag ){ case TRUE_TYPE_TAG: case FALSE_TYPE_TAG: case NIL_TYPE_TAG: case INFINITUM_TYPE_TAG: case ARRAY_START_TYPE_TAG: case ARRAY_END_TYPE_TAG: // zero length break; case INT32_TYPE_TAG: case FLOAT_TYPE_TAG: case CHAR_TYPE_TAG: case RGBA_COLOR_TYPE_TAG: case MIDI_MESSAGE_TYPE_TAG: if( argument == end ) throw MalformedMessageException( "arguments exceed message size" ); argument += 4; if( argument > end ) throw MalformedMessageException( "arguments exceed message size" ); break; case INT64_TYPE_TAG: case TIME_TAG_TYPE_TAG: case DOUBLE_TYPE_TAG: if( argument == end ) throw MalformedMessageException( "arguments exceed message size" ); argument += 8; if( argument > end ) throw MalformedMessageException( "arguments exceed message size" ); break; case STRING_TYPE_TAG: case SYMBOL_TYPE_TAG: if( argument == end ) throw MalformedMessageException( "arguments exceed message size" ); argument = FindStr4End( argument, end ); if( argument == 0 ) throw MalformedMessageException( "unterminated string argument" ); break; case BLOB_TYPE_TAG: { if( argument + 4 > end ) MalformedMessageException( "arguments exceed message size" ); uint32 blobSize = ToUInt32( argument ); argument = argument + 4 + RoundUp4( (unsigned long)blobSize ); if( argument > end ) MalformedMessageException( "arguments exceed message size" ); } break; default: throw MalformedMessageException( "unknown type tag" ); // not handled: // [ Indicates the beginning of an array. The tags following are for // data in the Array until a close brace tag is reached. // ] Indicates the end of an array. } }while( *++typeTag != '\0' ); typeTagsEnd_ = typeTag; } } }
int ClientReadBuffer::locateMessage(const unsigned char *start, const unsigned char *end, unsigned int &controlLength, unsigned int &dataLength, unsigned int &trailerLength) { unsigned int size = end - start; #ifdef TEST *logofs << "ClientReadBuffer: Locating message for FD#" << transport_ -> fd() << " with " << size << " bytes.\n" << logofs_flush; #endif if (firstMessage_) { if (size < 12) { remaining_ = 12 - size; #ifdef TEST *logofs << "ClientReadBuffer: No message was located " << "with remaining " << remaining_ << ".\n" << logofs_flush; #endif return 0; } if (*start == 0x42) { bigEndian_ = 1; } else { bigEndian_ = 0; } channel_ -> setBigEndian(bigEndian_); dataLength = 12 + RoundUp4(GetUINT(start + 6, bigEndian_)) + RoundUp4(GetUINT(start + 8, bigEndian_)); // // Send the data immediately if this is unlikely // to be a X connection attempt. // if (dataLength > 4096) { #ifdef WARNING *logofs << "ClientReadBuffer: WARNING! Flushing suspicious X " << "connection with first request of " << dataLength << " bytes.\n" << logofs_flush; #endif dataLength = size; } } else { if (size < 4) { remaining_ = 4 - size; #ifdef TEST *logofs << "ClientReadBuffer: No message was located " << "with remaining " << remaining_ << ".\n" << logofs_flush; #endif return 0; } dataLength = (GetUINT(start + 2, bigEndian_) << 2); if (dataLength < 4) { #ifdef TEST *logofs << "ClientReadBuffer: WARNING! Assuming length 4 " << "for suspicious message of length " << dataLength << ".\n" << logofs_flush; #endif dataLength = 4; } } #ifdef TEST *logofs << "ClientReadBuffer: Length of the next message is " << dataLength << ".\n" << logofs_flush; #endif if (size < dataLength) { remaining_ = dataLength - size; #ifdef TEST *logofs << "ClientReadBuffer: No message was located " << "with remaining " << remaining_ << ".\n" << logofs_flush; #endif return 0; } firstMessage_ = 0; controlLength = 0; trailerLength = 0; remaining_ = 0; #ifdef TEST *logofs << "ClientReadBuffer: Located message with " << "remaining " << remaining_ << ".\n" << logofs_flush; #endif return 1; }
void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size ) { if( !IsValidElementSizeValue(size) ) throw MalformedMessageException( "invalid message size" ); if( size == 0 ) throw MalformedMessageException( "zero length messages not permitted" ); if( !IsMultipleOf4(size) ) throw MalformedMessageException( "message size must be multiple of four" ); const char *end = message + size; typeTagsBegin_ = FindStr4End( addressPattern_, end ); if( typeTagsBegin_ == 0 ){ // address pattern was not terminated before end throw MalformedMessageException( "unterminated address pattern" ); } if( typeTagsBegin_ == end ){ // message consists of only the address pattern - no arguments or type tags. typeTagsBegin_ = 0; typeTagsEnd_ = 0; arguments_ = 0; }else{ if( *typeTagsBegin_ != ',' ) throw MalformedMessageException( "type tags not present" ); if( *(typeTagsBegin_ + 1) == '\0' ){ // zero length type tags typeTagsBegin_ = 0; typeTagsEnd_ = 0; arguments_ = 0; }else{ // check that all arguments are present and well formed arguments_ = FindStr4End( typeTagsBegin_, end ); if( arguments_ == 0 ){ throw MalformedMessageException( "type tags were not terminated before end of message" ); } ++typeTagsBegin_; // advance past initial ',' const char *typeTag = typeTagsBegin_; const char *argument = arguments_; unsigned int arrayLevel = 0; do{ switch( *typeTag ){ case TRUE_TYPE_TAG: case FALSE_TYPE_TAG: case NIL_TYPE_TAG: case INFINITUM_TYPE_TAG: // zero length break; // [ Indicates the beginning of an array. The tags following are for // data in the Array until a close brace tag is reached. // ] Indicates the end of an array. case ARRAY_BEGIN_TYPE_TAG: ++arrayLevel; // (zero length argument data) break; case ARRAY_END_TYPE_TAG: --arrayLevel; // (zero length argument data) break; case INT32_TYPE_TAG: case FLOAT_TYPE_TAG: case CHAR_TYPE_TAG: case RGBA_COLOR_TYPE_TAG: case MIDI_MESSAGE_TYPE_TAG: if( argument == end ) throw MalformedMessageException( "arguments exceed message size" ); argument += 4; if( argument > end ) throw MalformedMessageException( "arguments exceed message size" ); break; case INT64_TYPE_TAG: case TIME_TAG_TYPE_TAG: case DOUBLE_TYPE_TAG: if( argument == end ) throw MalformedMessageException( "arguments exceed message size" ); argument += 8; if( argument > end ) throw MalformedMessageException( "arguments exceed message size" ); break; case STRING_TYPE_TAG: case SYMBOL_TYPE_TAG: if( argument == end ) throw MalformedMessageException( "arguments exceed message size" ); argument = FindStr4End( argument, end ); if( argument == 0 ) throw MalformedMessageException( "unterminated string argument" ); break; case BLOB_TYPE_TAG: { if( argument + osc::OSC_SIZEOF_INT32 > end ) MalformedMessageException( "arguments exceed message size" ); // treat blob size as an unsigned int for the purposes of this calculation uint32 blobSize = ToUInt32( argument ); argument = argument + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize ); if( argument > end ) MalformedMessageException( "arguments exceed message size" ); } break; default: throw MalformedMessageException( "unknown type tag" ); } }while( *++typeTag != '\0' ); typeTagsEnd_ = typeTag; if( arrayLevel != 0 ) throw MalformedMessageException( "array was not terminated before end of message (expected ']' end of array tag)" ); } // These invariants should be guaranteed by the above code. // we depend on them in the implementation of ArgumentCount() #ifndef NDEBUG std::ptrdiff_t argumentCount = typeTagsEnd_ - typeTagsBegin_; assert( argumentCount >= 0 ); assert( argumentCount <= OSC_INT32_MAX ); #endif } }
void ReceivedMessageArgumentIterator::Advance() { if( !value_.typeTagPtr_ ) return; switch( *value_.typeTagPtr_++ ){ case '\0': // don't advance past end --value_.typeTagPtr_; break; case TRUE_TYPE_TAG: case FALSE_TYPE_TAG: case NIL_TYPE_TAG: case INFINITUM_TYPE_TAG: // zero length break; case INT32_TYPE_TAG: case FLOAT_TYPE_TAG: case CHAR_TYPE_TAG: case RGBA_COLOR_TYPE_TAG: case MIDI_MESSAGE_TYPE_TAG: value_.argumentPtr_ += 4; break; case INT64_TYPE_TAG: case TIME_TAG_TYPE_TAG: case DOUBLE_TYPE_TAG: value_.argumentPtr_ += 8; break; case STRING_TYPE_TAG: case SYMBOL_TYPE_TAG: // we use the unsafe function FindStr4End(char*) here because all of // the arguments have already been validated in // ReceivedMessage::Init() below. value_.argumentPtr_ = FindStr4End( value_.argumentPtr_ ); break; case BLOB_TYPE_TAG: { // treat blob size as an unsigned int for the purposes of this calculation uint32 blobSize = ToUInt32( value_.argumentPtr_ ); value_.argumentPtr_ = value_.argumentPtr_ + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize ); } break; case ARRAY_BEGIN_TYPE_TAG: case ARRAY_END_TYPE_TAG: // [ Indicates the beginning of an array. The tags following are for // data in the Array until a close brace tag is reached. // ] Indicates the end of an array. // zero length, don't advance argument ptr break; default: // unknown type tag // don't advance --value_.typeTagPtr_; break; } }