AsioSessionState::AsioSessionState(
    AsioServerTransport & transport,
    AsioIoService & ioService) :
    mIoService(ioService),
    mState(Ready),
    mIssueZeroByteRead(false),
    mReadBufferRemaining(),
    mWriteBufferRemaining(),
    mTransport(transport),
    mFilterAdapterPtr(new FilterAdapter(*this)),
    mCloseAfterWrite(),
    mReflecting()
{
    if (transport.mWireProtocol == Wp_Http || transport.mWireProtocol == Wp_Https)
    {
        mWireFilters.clear();
        mWireFilters.push_back( FilterPtr(new HttpFrameFilter()) );
    }

    if (transport.mWireProtocol == Wp_Https)
    {
        FilterPtr sslFilterPtr;

#if defined(BOOST_WINDOWS) && defined(RCF_USE_OPENSSL)

        if (transport.mpServer->getPreferSchannel())
        {
            sslFilterPtr = transport.mpServer->createFilter(RcfFilter_SspiSchannel);
        }
        else
        {
            sslFilterPtr = transport.mpServer->createFilter(RcfFilter_OpenSsl);
        }

#elif defined(BOOST_WINDOWS)

        sslFilterPtr = transport.mpServer->createFilter(RcfFilter_SspiSchannel);

#elif defined(RCF_USE_OPENSSL)

        sslFilterPtr = transport.mpServer->createFilter(RcfFilter_OpenSsl);

#endif

        if (!sslFilterPtr)
        {
            RCF_THROW( Exception(_RcfError_SslNotSupported()) );
        }

        mWireFilters.push_back( sslFilterPtr );
    }

    if (mWireFilters.size() > 0)
    {
        setTransportFilters( std::vector<FilterPtr>() );
    }
}
    void CallbackConnectionService::CreateCallbackConnection()
    {
        if ( !mOnCallbackConnectionCreated )
        {
            RCF_THROW( Exception(_RcfError_ServerCallbacksNotSupported()) );
        }

        RCF::convertRcfSessionToRcfClient( mOnCallbackConnectionCreated );
    }
Example #3
0
    void ClientStub::createFilterSequence(
        std::vector<FilterPtr> & filters)
    {
        filters.clear();
    
        // Setup compression if configured.
        if (mEnableCompression)
        {
#if RCF_FEATURE_ZLIB==1
            FilterPtr filterPtr( new ZlibStatefulCompressionFilter() );
            filters.push_back(filterPtr);
#else
            RCF_ASSERT(0);
#endif
        }

        FilterPtr filterPtr;
        if (mTransportProtocol != Tp_Clear && mTransportProtocol != Tp_Unspecified)
        {
            switch (mTransportProtocol)
            {
#if RCF_FEATURE_SSPI==1
            case Tp_Ntlm:       filterPtr.reset( new NtlmFilter(this) ); break;
            case Tp_Kerberos:   filterPtr.reset( new KerberosFilter(this) ); break;
            case Tp_Negotiate:  filterPtr.reset( new NegotiateFilter(this) ); break;
#endif

#if RCF_FEATURE_OPENSSL==1 && RCF_FEATURE_SSPI==1
            case Tp_Ssl:        if (mSslImplementation == Si_Schannel)
                                {
                                    filterPtr.reset( new SchannelFilter(this) ); 
                                }
                                else
                                {
                                    RCF_ASSERT(mSslImplementation == Si_OpenSsl);
                                    filterPtr.reset( new OpenSslEncryptionFilter(this) ); 
                                }
                                break;
#elif RCF_FEATURE_OPENSSL==1
            case Tp_Ssl:        filterPtr.reset( new OpenSslEncryptionFilter(this) ); break;
#elif RCF_FEATURE_SSPI==1
            case Tp_Ssl:        filterPtr.reset( new SchannelFilter(this) ); break;
#else
            // Single case just to keep the compiler warnings quiet.
            case Tp_Ssl:
#endif

            default:
                RCF_THROW( Exception( _RcfError_TransportProtocolNotSupported( getTransportProtocolName(mTransportProtocol)) ) );
            }
        }
        if (filterPtr)
        {
            filters.push_back(filterPtr);
        }
    }
Example #4
0
 T &deref()
 {
     boost::shared_ptr<T> tPtr(mTWeakPtr);
     if (tPtr.get())
     {
         return *tPtr;
     }
     Exception e(_RcfError_ServerStubExpired());
     RCF_THROW(e);
 }
Example #5
0
        void DeleteRemoteObject(const PbDeleteRemoteObject & request)
        {
            int error = mOfs.DeleteObject(request.token());

            if (error != RCF::RcfError_Ok)
            {
                RemoteException e(( Error(error) ));
                RCF_THROW(e);
            }
        }
Example #6
0
 inline void decodeTypedElements( BinaryPortable *, T *, DataPtr &data, T *t, int nCount)
 {
     if (data.length() != sizeof(T)*nCount)
     {
         RCF_THROW(RCF::Exception(RCF::SfError_DataFormat))(data.length())(nCount)(typeid(T).name());
     }
     T *buffer = reinterpret_cast<T *>(data.get());
     RCF::networkToMachineOrder(buffer, sizeof(T), nCount);
     memcpy(t, buffer, nCount*sizeof(T));
 }
        void CreateSessionObject(const PbCreateSessionObject & request)
        {
            int error = mSofs.CreateSessionObject(request.objectname());

            if (error != RCF::RcfError_Ok)
            {
                RemoteException e(( Error(error) ));
                RCF_THROW(e);
            }
        }
Example #8
0
 UInt32 OStream::write_byte(Byte8 byte)
 {
     mpOs->write(&byte, 1);
     if (mpOs->fail())
     {
         RCF::Exception e(RCF::_SfError_WriteFailure());
         RCF_THROW(e);
     }
     return 1;
 }
Example #9
0
 void IStream::end()
 {
     Byte8 byte;
     read_byte(byte);
     if (byte != End)
     {
         RCF::Exception e(RCF::_SfError_DataFormat(), "no end symbol");
         RCF_THROW(e)(byte);
     }
 }
Example #10
0
 UInt32 IStream::read(Byte8 *pBytes, UInt32 nLength)
 {
     mpIs->read(pBytes, nLength);
     if (mpIs->fail())
     {
         RCF::Exception e(RCF::_SfError_ReadFailure());
         RCF_THROW(e)(nLength)(mpIs->gcount());
     }
     return static_cast<UInt32>(mpIs->gcount());
 }
Example #11
0
 UInt32 OStream::writeRaw(const Byte8 *pBytes, UInt32 nLength)
 {
     mpOs->write(pBytes, nLength);
     if (mpOs->fail())
     {
         RCF::Exception e(RCF::_SfError_WriteFailure());
         RCF_THROW(e)(nLength);
     }
     return nLength;
 }
 Win32ThreadImpersonator(HANDLE hToken)
 {
     BOOL ok = SetThreadToken(NULL, hToken);
     if (!ok)
     {
         DWORD dwErr = GetLastError();
         RCF_THROW( Exception( 
             _RcfError_Win32ApiError("SetThreadToken()"), 
             dwErr) ); 
     }
 }
        void DeleteSessionObject(const PbDeleteSessionObject & request)
        {
            RCF_UNUSED_VARIABLE(request);

            int error = mSofs.DeleteSessionObject();

            if (error != RCF::RcfError_Ok)
            {
                RemoteException e(( Error(error) ));
                RCF_THROW(e);
            }
        }
Example #14
0
    UInt32 OStream::write_int(UInt32 n)
    {
        BOOST_STATIC_ASSERT( sizeof(n) == 4 );

        if (mRuntimeVersion < 9)
        {
            RCF::machineToNetworkOrder(&n, 4, 1);
            mpOs->write( reinterpret_cast<char*>(&n), 4);
            if (mpOs->fail())
            {
                RCF::Exception e(RCF::_SfError_WriteFailure());
                RCF_THROW(e)(n);
            }
            return 4;
        }
        else
        {
            // Integers less than 128 are stored as a single byte.
            if (0 <= n && n <= 127)
            {
                boost::uint8_t byte = static_cast<boost::uint8_t>(n);
                write_byte(byte);
                return 1;
            }
            else
            {
                boost::uint8_t byte = 128;
                write_byte(byte);
            
                RCF::machineToNetworkOrder(&n, 4, 1);
                mpOs->write( reinterpret_cast<char*>(&n), 4);
                if (mpOs->fail())
                {
                    RCF::Exception e(RCF::_SfError_WriteFailure());
                    RCF_THROW(e)(n);
                }
                return 5;
            }
        }
    }
    HttpsClientTransport::HttpsClientTransport(const HttpsEndpoint & httpsEndpoint) : 
        TcpClientTransport(httpsEndpoint.getIp(), httpsEndpoint.getPort())
    {
        std::vector<FilterPtr> wireFilters;

        // HTTP framing.
        wireFilters.push_back( FilterPtr( new HttpFrameFilter(
            getRemoteAddr().getIp(), 
            getRemoteAddr().getPort())));

        // SSL.
        ClientStub * pClientStub = getTlsClientStubPtr();
        RCF_ASSERT(pClientStub);

        FilterPtr sslFilterPtr;

#if RCF_FEATURE_SSPI==1 && RCF_FEATURE_OPENSSL==1

        if (pClientStub->getSslImplementation() == Si_Schannel)
        {
            sslFilterPtr.reset( new SchannelFilter(pClientStub) );
        }
        else
        {
            RCF_ASSERT(pClientStub->getSslImplementation() == Si_OpenSsl);
            sslFilterPtr.reset( new OpenSslEncryptionFilter(pClientStub) );
        }

#elif RCF_FEATURE_SSPI==1

        sslFilterPtr.reset( new SchannelFilter(pClientStub) );

#elif RCF_FEATURE_OPENSSL==1

        sslFilterPtr.reset( new OpenSslEncryptionFilter(pClientStub) );

#endif

        if (!sslFilterPtr)
        {
            RCF_THROW( Exception(_RcfError_SslNotSupported()) );
        }

        wireFilters.push_back(sslFilterPtr);

        // HTTP CONNECT filter for passing through a proxy.
        wireFilters.push_back( FilterPtr( new HttpConnectFilter(
            getRemoteAddr().getIp(), 
            getRemoteAddr().getPort())));

        setWireFilters(wireFilters);
    }
Example #16
0
 UInt32 OStream::write(const Byte8 *pBytes, UInt32 nLength)
 {
     UInt32 bytesWritten = 0;
     bytesWritten += write_int(nLength);
     mpOs->write(pBytes, nLength);
     if (mpOs->fail())
     {
         RCF::Exception e(RCF::_SfError_WriteFailure());
         RCF_THROW(e)(nLength);
     }
     bytesWritten += nLength;
     return bytesWritten;
 }
Example #17
0
    void Win32Certificate::exportToPfx(const std::string & pfxFilePath)
    {
        RCF::ByteBuffer pfxBuffer = exportToPfx();

        // Write the data to file.
        FILE * fp = fopen(pfxFilePath.c_str(), "wb");
        if (!fp)
        {
            RCF_THROW( Exception(_RcfError_FileOpenWrite(pfxFilePath)) );
        }
        fwrite(pfxBuffer.getPtr(), sizeof(char), pfxBuffer.getLength(), fp);
        fclose(fp);
    }
    void UdpSessionState::postWrite(
        std::vector<ByteBuffer> &byteBuffers)
    {
        // prepend data length and send the data

        boost::shared_ptr<std::vector<char> > &writeVecPtr = mWriteVecPtr;

        if (writeVecPtr.get() == NULL || !writeVecPtr.unique())
        {
            writeVecPtr.reset( new std::vector<char>());
        }

        std::vector<char> &writeBuffer = *writeVecPtr;

        unsigned int dataLength = static_cast<unsigned int>(
            lengthByteBuffers(byteBuffers));

        writeBuffer.resize(4+dataLength);
        memcpy( &writeBuffer[0], &dataLength, 4);
        machineToNetworkOrder(&writeBuffer[0], 4, 1);
        copyByteBuffers(byteBuffers, &writeBuffer[4]);
        byteBuffers.resize(0);

        const sockaddr_in &remoteAddr = remoteAddress.getSockAddr();
       
        int len = sendto(
            mTransport.mFd,
            &writeBuffer[0],
            static_cast<int>(writeBuffer.size()),
            0,
            (const sockaddr *) &remoteAddr,
            sizeof(remoteAddr));

        if (len != static_cast<int>(writeBuffer.size()))
        {
            int err = Platform::OS::BsdSockets::GetLastError();
            RCF_THROW(Exception(
                RcfError_Socket, err, RcfSubsystem_Os, "sendto() failed"))
                (mTransport.mFd)(len)(writeBuffer.size());
        }

        SessionStatePtr sessionStatePtr = getCurrentUdpSessionStatePtr();

        SessionPtr sessionPtr = sessionStatePtr->mSessionPtr;

        RcfSessionPtr rcfSessionPtr = 
            boost::static_pointer_cast<RcfSession>(sessionPtr);

        rcfSessionPtr->mIoState = RcfSession::Reading;
    }
Example #19
0
 void EncodingBinaryPortable_toObjectImpl(
     DataPtr &       data, 
     T *             t, 
     int             nCount)
 {
     if (data.length() != sizeof(T)*nCount)
     {
         RCF::Exception e(RCF::_SfError_DataFormat());
         RCF_THROW(e)(data.length())(nCount)(typeid(T).name());
     }
     T *buffer = reinterpret_cast<T *>(data.get());
     RCF::networkToMachineOrder(buffer, sizeof(T), nCount);
     memcpy(t, buffer, nCount*sizeof(T));
 }
Example #20
0
        PbCreateRemoteObjectResponse CreateRemoteObject(const PbCreateRemoteObject & request)
        {
            Token token;
            int error = mOfs.CreateObject(request.objectname(), token);

            if (error != RCF::RcfError_Ok)
            {
                RemoteException e(( Error(error) ));
                RCF_THROW(e);
            }

            PbCreateRemoteObjectResponse response;
            response.set_token( token.getId() );
            return response;
            //return PbCreateRemoteObjectResponse();
        }
    void UdpSessionState::postWrite(
        std::vector<ByteBuffer> &byteBuffers)
    {
        // prepend data length and send the data

        ReallocBufferPtr &writeVecPtr = mWriteVecPtr;

        if (writeVecPtr.get() == NULL || !writeVecPtr.unique())
        {
            writeVecPtr.reset( new ReallocBuffer());
        }

        ReallocBuffer &writeBuffer = *writeVecPtr;

        unsigned int dataLength = static_cast<unsigned int>(
            lengthByteBuffers(byteBuffers));

        writeBuffer.resize(4+dataLength);
        memcpy( &writeBuffer[0], &dataLength, 4);
        machineToNetworkOrder(&writeBuffer[0], 4, 1);
        copyByteBuffers(byteBuffers, &writeBuffer[4]);
        byteBuffers.resize(0);

        sockaddr * pRemoteAddr = NULL;
        Platform::OS::BsdSockets::socklen_t remoteAddrSize = 0;
        mRemoteAddress.getSockAddr(pRemoteAddr, remoteAddrSize);
       
        int len = sendto(
            mTransport.mFd,
            &writeBuffer[0],
            static_cast<int>(writeBuffer.size()),
            0,
            pRemoteAddr,
            remoteAddrSize);

        if (len != static_cast<int>(writeBuffer.size()))
        {
            int err = Platform::OS::BsdSockets::GetLastError();
            Exception e(_RcfError_Socket("sendto()"), err, RcfSubsystem_Os);
            RCF_THROW(e)(mTransport.mFd)(len)(writeBuffer.size());
        }

        SessionStatePtr sessionStatePtr = getTlsUdpSessionStatePtr();

        SessionPtr sessionPtr = sessionStatePtr->mSessionPtr;
    }
Example #22
0
 inline void decodeTypedElements( Text *, T *, DataPtr &data, T *t, int nCount)
 {
     if (data.length() == 0)
     {
         RCF_THROW(RCF::Exception(RCF::SfError_DataFormat));
     }
     std::string strData(reinterpret_cast<char *>(data.get()), data.length());
     std::istringstream istr(strData);
     istr >> t[0];
     for (int i=1; i<nCount; i++)
     {
         char ch;
         istr.get(ch);
         RCF_ASSERT( ch == chSeparator );
         istr >> t[i];
     }
 }
    void Win32NamedPipeNetworkSession::implTransferNativeFrom(ClientTransport & clientTransport)
    {
        
        Win32NamedPipeClientTransport * pPipeClientTransport =
            dynamic_cast<Win32NamedPipeClientTransport *>(&clientTransport);

        if (pPipeClientTransport == NULL)
        {
            Exception e("incompatible client transport");
            RCF_THROW(e)(typeid(clientTransport));
        }

        Win32NamedPipeClientTransport & pipeClientTransport = *pPipeClientTransport;

        pipeClientTransport.associateWithIoService(mIoService);
        mSocketPtr = pipeClientTransport.releaseSocket();
        mRemotePipeName = pipeClientTransport.getPipeName();
    }
Example #24
0
        void RequestTransportFilters(const PbRequestTransportFilters & request)
        {
            std::vector<boost::int32_t> filterIds;
            int filterCount = request.filterids_size();
            for (int i=0; i<filterCount; ++i)
            {
                filterIds.push_back(request.filterids(i));
            }

            int error = mFs.RequestTransportFilters(filterIds);

            if (error != RCF::RcfError_Ok)
            {
                Error err(error);
                RemoteException e(err);
                RCF_THROW(e);
            }
        }
Example #25
0
    I_SerializerAny &Registry::getAnySerializer(const std::string &which)
    {
        ReadLock lock(mReadWriteMutex); 
        RCF_UNUSED_VARIABLE(lock);
        if (mTypenameToRtti.find(which) != mTypenameToRtti.end())
        {
            Rtti rtti = mTypenameToRtti[which];

            RCF_VERIFY(
                mRttiToSerializerAny.find(rtti) != mRttiToSerializerAny.end(),
                RCF::Exception(RCF::_RcfError_AnySerializerNotFound(which)));

            return *mRttiToSerializerAny[rtti];
        }
        
        RCF::Exception e(RCF::_RcfError_AnySerializerNotFound(which));
        RCF_THROW(e);
        return * (I_SerializerAny *) NULL;
    }
        void read(T &t)
        {
            try
            {
                switch (mProtocol)
                {
                case 1: mInProtocol1 >> t; break;
                case 2: mInProtocol2 >> t; break;
                case 3: mInProtocol3 >> t; break;
                case 4: mInProtocol4 >> t; break;

#ifdef RCF_USE_BOOST_XML_SERIALIZATION
                case 5: mInProtocol5 >> boost::serialization::make_nvp("Dummy", t); break;
#else
                case 5: mInProtocol5 >> t; break;
#endif

                default: RCF_ASSERT(0)(mProtocol);
                }
            }
            catch(const RCF::Exception &e)
            {
                RCF_UNUSED_VARIABLE(e);
                throw;
            }
            catch(const std::exception &e)
            {
                std::ostringstream os;
                os
                    << "Deserialization error, object type: "
                    << typeid(t).name()
                    << ", error type: "
                    << typeid(e).name()
                    << ", error msg: "
                    << e.what();

                RCF_THROW(
                    RCF::SerializationException(
                        RcfError_Deserialization,
                        os.str()));
            }
        }
Example #27
0
 void EncodingText_toObjectImpl(
     DataPtr &       data, 
     T *             t, 
     int             nCount)
 {
     if (data.length() == 0)
     {
         RCF::Exception e(RCF::_SfError_DataFormat());
         RCF_THROW(e);
     }
     RCF::MemIstream istr(data.get(), data.length());
     istr >> t[0];
     for (int i=1; i<nCount; i++)
     {
         char ch;
         istr.get(ch);
         RCF_ASSERT_EQ( ch , chSeparator );
         istr >> t[i];
     }
 }
Example #28
0
    JsonRpcRequest::JsonRpcRequest(ByteBuffer message) : mMessageBuffer(message)
    {
        MemIstream is(message.getPtr(), message.getLength());
        bool parsedOk = json_spirit::read_stream(is, mJsonRequest);
        if (!parsedOk)
        {
            RCF_THROW(Exception(_RcfError_ParseJsonRpcRequest()));
        }
        json_spirit::Object obj = mJsonRequest.get_obj();

        for(json_spirit::Object::size_type i=0; i!=obj.size(); ++i)
        {
            const json_spirit::Pair & pair = obj[i];

            const std::string & name  = pair.name_;
            const json_spirit::Value &  value = pair.value_;

            if (name == "method")
            {
                mMethodName = value.get_str();
            }
            else if (name == "id")
            {
                if (value.is_null())
                {
                    mRequestId = 0;
                    mIsNotification = true;
                }
                else
                {
                    mRequestId = value.get_uint64();
                    mIsNotification = false;
                }
            }
            else if (name == "params")
            {
                mJsonParams = value.get_array();
            }
        }

    }
Example #29
0
    // serialization for boost::any
    void serialize(SF::Archive &ar, boost::any &a)
    {
        if (ar.isWrite())
        {
            std::string which = 
                SF::Registry::getSingleton().getTypeName(a.type());

            if (which.empty() && !a.empty())
            {
                RCF_THROW(RCF::Exception(RCF::_RcfError_AnyTypeNotRegistered(a.type().name())));
            }

            ar & which;

            if (!a.empty())
            {
                RCF_ASSERT(which.size() > 0);

                SF::Registry::getSingleton().getAnySerializer(which)
                    .serialize(ar, a);
            }
        }
        else
        {
            std::string which;
            ar & which;
            if (which.empty())
            {
                a = boost::any();
            }
            else
            {
                SF::Registry::getSingleton().getAnySerializer(which)
                    .serialize(ar, a);
            }
        }
    }
Example #30
0
    bool IStream::begin(Node &node)
    {
        while (true)
        {
            Byte8 byte = 0;
            read_byte(byte);

            switch (byte)
            {
            case Blank: 
                {
                    Byte8 count = 0;
                    read_byte(count);
                    std::vector<Byte8> buffer(count);
                    UInt32 bytesRead = read( &(buffer[0]), count);
                    if (bytesRead != static_cast<UInt32>(count))
                    {
                        RCF::Exception e(RCF::_SfError_DataFormat());
                        RCF_THROW(e)(bytesRead)(count);
                    }
                    continue;
                }

            case BeginArchiveMetadata:
                {
                    int runtimeVersion = 0;
                    int archiveVersion = 0;
                    bool pointerTrackingEnabled = false;
                    bool * pPointerTrackingEnabled = NULL;

                    const size_t BufferLen = 11;
                    char buffer[BufferLen] = {0};
                    RCF::ByteBuffer byteBuffer( &buffer[0], BufferLen);
                    std::size_t pos0 = static_cast<std::size_t>(mpIs->tellg());

#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( disable : 4996 )  // warning C4996: 'std::basic_istream<_Elem,_Traits>::readsome': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
#endif
                    std::size_t bytesRead = static_cast<std::size_t>(mpIs->readsome(buffer, BufferLen));

#ifdef _MSC_VER
#pragma warning( pop )
#endif
                    byteBuffer = RCF::ByteBuffer(byteBuffer, 0, bytesRead);
                    std::size_t pos1 = 0;
                    decodeInt(runtimeVersion, byteBuffer, pos1);
                    decodeInt(archiveVersion, byteBuffer, pos1);

                    if (runtimeVersion >= 10)
                    {
                        decodeBool(pointerTrackingEnabled, byteBuffer, pos1);
                        pPointerTrackingEnabled = &pointerTrackingEnabled;
                    }

                    mpIs->seekg(
                        static_cast<std::istream::off_type>(pos0 + pos1), 
                        std::ios_base::beg);

                    if (!mIgnoreVersionStamp)
                    {
                        if (runtimeVersion)
                        {
                            mRuntimeVersion = runtimeVersion;
                        }
                        if (archiveVersion)
                        {
                            mArchiveVersion = archiveVersion;
                        }
                    }

                    if (pPointerTrackingEnabled && !*pPointerTrackingEnabled)
                    {
                        getTrackingContext().setEnabled(false);
                    }

                    continue;
                }

            case Begin:
                {
                    read_byte( byte );
                    Byte8 attrSpec = byte;

                    // id
                    if (attrSpec & 1)
                    {
                        read_int(node.id);
                    }

                    // ref
                    attrSpec = attrSpec >> 1;
                    if (attrSpec & 1)
                    {
                        node.ref = 1;
                    }

                    // type
                    attrSpec = attrSpec >> 1;
                    if (attrSpec & 1)
                    {
                        UInt32 length = 0;
                        read_int(length);
                        node.type.allocate(length);
                        read(node.type.get(), length );
                    }

                    // label
                    attrSpec = attrSpec >> 1;
                    if (attrSpec & 1)
                    {
                        UInt32 length = 0;
                        read_int(length);
                        node.label.allocate(length);
                        read(node.label.get(), length);
                    }

                    return true;
                }

            default:
                {
                    RCF::Exception e(RCF::_SfError_DataFormat());
                    RCF_THROW(e)(byte);
                }
            }
        }

    }