Example #1
0
        public static Data DeocdeHeader(AlternativeCompositeByteBuf buffer, ISignatureFactory signatureFactory)
        {
            // 2 is the smallest packet size, we could start if we know 1 byte to
            // decode the header, but we always need a second byte. Thus, we are waiting for at least 2 bytes.
            if (buffer.ReadableBytes < 2 * Utils.Utils.ByteByteSize)
            {
                return(null);
            }
            int      header = buffer.GetUByte(buffer.ReaderIndex);
            DataType type   = Type(header);

            // length
            int length;
            int indexLength = Utils.Utils.ByteByteSize;
            int indexTtl;

            switch (type)
            {
            case DataType.Small:
                length   = buffer.GetUByte(buffer.ReaderIndex + indexLength);
                indexTtl = indexLength + Utils.Utils.ByteByteSize;
                break;

            case DataType.Large:
                indexTtl = indexLength + Utils.Utils.IntegerByteSize;
                if (buffer.ReadableBytes < indexTtl)
                {
                    return(null);
                }
                length = buffer.GetInt(buffer.ReaderIndex + indexLength);
                break;

            default:
                throw new ArgumentException("Unknown DataType.");
            }

            // TTL
            int ttl;
            int indexBasedOnNr;

            if (CheckHasTtl(header))
            {
                indexBasedOnNr = indexTtl + Utils.Utils.IntegerByteSize;
                if (buffer.ReadableBytes < indexBasedOnNr)
                {
                    return(null);
                }
                ttl = buffer.GetInt(buffer.ReaderIndex + indexTtl);
            }
            else
            {
                indexBasedOnNr = indexTtl;
                ttl            = -1;
            }

            // nr basedOn + basedOn
            int numBasedOn;
            int indexPublicKeySize;
            int indexBasedOn;
            var basedOn = new List <Number160>();

            if (CheckHasBasedOn(header))
            {
                // get nr of basedOn keys
                indexBasedOn = indexBasedOnNr + Utils.Utils.ByteByteSize;
                if (buffer.ReadableBytes < indexBasedOn)
                {
                    return(null);
                }
                numBasedOn         = buffer.GetUByte(buffer.ReaderIndex + indexBasedOn) + 1;
                indexPublicKeySize = indexBasedOn + (numBasedOn * Number160.ByteArraySize);
                if (buffer.ReadableBytes < indexPublicKeySize)
                {
                    return(null);
                }

                // get basedOn
                int index = buffer.ReaderIndex + indexBasedOnNr + Utils.Utils.ByteByteSize;
                var me    = new sbyte[Number160.ByteArraySize];
                for (int i = 0; i < numBasedOn; i++)
                {
                    buffer.GetBytes(index, me);
                    index += Number160.ByteArraySize;
                    basedOn.Add(new Number160(me));
                }
            }
            else
            {
                indexPublicKeySize = indexBasedOnNr;
                numBasedOn         = 0;
            }

            // public key + size
            int        publicKeySize;
            int        indexPublicKey;
            int        indexEnd;
            IPublicKey publicKey;

            if (CheckHasPublicKey(header))
            {
                // get public key size
                indexPublicKey = indexPublicKeySize + Utils.Utils.ShortByteSize;
                if (buffer.ReadableBytes < indexPublicKey)
                {
                    return(null);
                }
                publicKeySize = buffer.GetUShort(buffer.ReaderIndex + indexPublicKeySize);
                indexEnd      = indexPublicKey + publicKeySize;
                if (buffer.ReadableBytes < indexEnd)
                {
                    return(null);
                }

                // get public key
                buffer.SkipBytes(indexPublicKeySize);
                publicKey = signatureFactory.DecodePublicKey(buffer);
            }
            else
            {
                publicKeySize  = 0;
                indexPublicKey = indexPublicKeySize;
                buffer.SkipBytes(indexPublicKey);
                publicKey = null;
            }

            // now, we have read the header and the length
            var data = new Data(header, length);

            data.TtlSeconds = ttl;
            data.BasedOnSet = basedOn;
            data.PublicKey  = publicKey;
            return(data);
        }
Example #2
0
        private bool DecodePayload(AlternativeCompositeByteBuf buffer)
        {
            Logger.Debug("About to pass message {0} to {1}. Buffer to read: {2}.", Message, Message.SenderSocket, buffer.ReadableBytes);

            if (!Message.HasContent())
            {
                return(true);
            }

            int        size;
            IPublicKey receivedPublicKey;

            while (_contentTypes.Count > 0)
            {
                Message.Content content = _contentTypes.Peek();
                Logger.Debug("Go for content: {0}.", content);

                switch (content)
                {
                case Message.Content.Integer:
                    if (buffer.ReadableBytes < Utils.Utils.IntegerByteSize)
                    {
                        return(false);
                    }
                    Message.SetIntValue(buffer.ReadInt());
                    LastContent = _contentTypes.Dequeue();
                    break;

                case Message.Content.Long:
                    if (buffer.ReadableBytes < Utils.Utils.LongByteSize)
                    {
                        return(false);
                    }
                    Message.SetLongValue(buffer.ReadLong());
                    LastContent = _contentTypes.Dequeue();
                    break;

                case Message.Content.Key:
                    if (buffer.ReadableBytes < Number160.ByteArraySize)
                    {
                        return(false);
                    }
                    var keyBytes = new sbyte[Number160.ByteArraySize];
                    buffer.ReadBytes(keyBytes);
                    Message.SetKey(new Number160(keyBytes));
                    LastContent = _contentTypes.Dequeue();
                    break;

                case Message.Content.BloomFilter:
                    if (buffer.ReadableBytes < Utils.Utils.ShortByteSize)
                    {
                        return(false);
                    }
                    size = buffer.GetUShort(buffer.ReaderIndex);
                    if (buffer.ReadableBytes < size)
                    {
                        return(false);
                    }
                    Message.SetBloomFilter(new SimpleBloomFilter <Number160>(buffer));
                    LastContent = _contentTypes.Dequeue();
                    break;

                case Message.Content.SetNeighbors:
                    if (_neighborSize == -1 && buffer.ReadableBytes < Utils.Utils.ByteByteSize)
                    {
                        return(false);
                    }
                    if (_neighborSize == -1)
                    {
                        _neighborSize = buffer.ReadByte();
                    }
                    if (_neighborSet == null)
                    {
                        _neighborSet = new NeighborSet(-1, new List <PeerAddress>(_neighborSize));
                    }
                    for (int i = _neighborSet.Size; i < _neighborSize; i++)
                    {
                        if (buffer.ReadableBytes < Utils.Utils.ShortByteSize)
                        {
                            return(false);
                        }
                        int header = buffer.GetUShort(buffer.ReaderIndex);
                        size = PeerAddress.CalculateSize(header);
                        if (buffer.ReadableBytes < size)
                        {
                            return(false);
                        }
                        var pa = new PeerAddress(buffer);
                        _neighborSet.Add(pa);
                    }
                    Message.SetNeighborSet(_neighborSet);
                    LastContent   = _contentTypes.Dequeue();
                    _neighborSize = -1;     // TODO why here? not in prepareFinish()?
                    _neighborSet  = null;
                    break;

                case Message.Content.SetPeerSocket:
                    if (_peerSocketAddressSize == -1 && buffer.ReadableBytes < Utils.Utils.ByteByteSize)
                    {
                        return(false);
                    }
                    if (_peerSocketAddressSize == -1)
                    {
                        _peerSocketAddressSize = buffer.ReadUByte();
                    }
                    if (_peerSocketAddresses == null)
                    {
                        _peerSocketAddresses = new List <PeerSocketAddress>(_peerSocketAddressSize);
                    }
                    for (int i = _peerSocketAddresses.Count; i < _peerSocketAddressSize; i++)
                    {
                        if (buffer.ReadableBytes < Utils.Utils.ByteByteSize)
                        {
                            return(false);
                        }
                        int  header = buffer.GetUByte(buffer.ReaderIndex);
                        bool isIPv4 = header == 0;     // TODO check if works
                        size = PeerSocketAddress.Size(isIPv4);
                        if (buffer.ReadableBytes < size + Utils.Utils.ByteByteSize)
                        {
                            return(false);
                        }
                        // skip the ipv4/ipv6 header
                        buffer.SkipBytes(1);
                        _peerSocketAddresses.Add(PeerSocketAddress.Create(buffer, isIPv4));
                    }
                    Message.SetPeerSocketAddresses(_peerSocketAddresses);
                    LastContent            = _contentTypes.Dequeue();
                    _peerSocketAddressSize = -1;     // TODO why here? not in prepareFinish()?
                    _peerSocketAddresses   = null;
                    break;

                case Message.Content.SetKey640:
                    if (_keyCollectionSize == -1 && buffer.ReadableBytes < Utils.Utils.IntegerByteSize)
                    {
                        return(false);
                    }
                    if (_keyCollectionSize == -1)
                    {
                        _keyCollectionSize = buffer.ReadInt();
                    }
                    if (_keyCollection == null)
                    {
                        _keyCollection = new KeyCollection(new List <Number640>(_keyCollectionSize));
                    }
                    for (int i = _keyCollection.Size; i < _keyCollectionSize; i++)
                    {
                        if (buffer.ReadableBytes < 4 * Number160.ByteArraySize)
                        {
                            return(false);
                        }
                        var me = new sbyte[Number160.ByteArraySize];

                        buffer.ReadBytes(me);
                        var locationKey = new Number160(me);

                        buffer.ReadBytes(me);
                        var domainKey = new Number160(me);

                        buffer.ReadBytes(me);
                        var contentKey = new Number160(me);

                        buffer.ReadBytes(me);
                        var versionKey = new Number160(me);

                        _keyCollection.Add(new Number640(locationKey, domainKey, contentKey, versionKey));
                    }
                    Message.SetKeyCollection(_keyCollection);
                    LastContent        = _contentTypes.Dequeue();
                    _keyCollectionSize = -1;     // TODO why here? not in prepareFinish()?
                    _keyCollection     = null;
                    break;

                case Message.Content.MapKey640Data:
                    if (_mapSize == -1 && buffer.ReadableBytes < Utils.Utils.IntegerByteSize)
                    {
                        return(false);
                    }
                    if (_mapSize == -1)
                    {
                        _mapSize = buffer.ReadInt();
                    }
                    if (_dataMap == null)
                    {
                        _dataMap = new DataMap(new Dictionary <Number640, Data>(2 * _mapSize));
                    }
                    if (_data != null)
                    {
                        if (!_data.DecodeBuffer(buffer))
                        {
                            return(false);
                        }
                        if (!_data.DecodeDone(buffer, Message.PublicKey(0), _signatureFactory))
                        {
                            return(false);
                        }
                        _data = null;     // TODO why here? not in prepareFinish()?
                        _key  = null;
                    }
                    for (int i = _dataMap.Size; i < _mapSize; i++)
                    {
                        if (_key == null)
                        {
                            if (buffer.ReadableBytes < 4 * Number160.ByteArraySize)
                            {
                                return(false);
                            }
                            var me = new sbyte[Number160.ByteArraySize];
                            buffer.ReadBytes(me);
                            var locationKey = new Number160(me);
                            buffer.ReadBytes(me);
                            var domainKey = new Number160(me);
                            buffer.ReadBytes(me);
                            var contentKey = new Number160(me);
                            buffer.ReadBytes(me);
                            var versionKey = new Number160(me);

                            _key = new Number640(locationKey, domainKey, contentKey, versionKey);
                        }
                        _data = Data.DeocdeHeader(buffer, _signatureFactory);
                        if (_data == null)
                        {
                            return(false);
                        }
                        _dataMap.BackingDataMap.Add(_key, _data);

                        if (!_data.DecodeBuffer(buffer))
                        {
                            return(false);
                        }
                        if (!_data.DecodeDone(buffer, Message.PublicKey(0), _signatureFactory))
                        {
                            return(false);
                        }
                        // if we have signed the message, set the public key anyway, but only if we indicated so
                        if (Message.IsSign && Message.PublicKey(0) != null && _data.HasPublicKey &&
                            (_data.PublicKey == null || _data.PublicKey == PeerBuilder.EmptyPublicKey))
                        // TODO check empty key condition
                        {
                            _data.SetPublicKey(Message.PublicKey(0));
                        }
                        _data = null;     // TODO why here? not in prepareFinish()?
                        _key  = null;
                    }

                    Message.SetDataMap(_dataMap);
                    LastContent = _contentTypes.Dequeue();
                    _mapSize    = -1;  // TODO why here? not in prepareFinish()?
                    _dataMap    = null;
                    break;

                case Message.Content.MapKey640Keys:
                    if (_keyMap640KeysSize == -1 && buffer.ReadableBytes < Utils.Utils.IntegerByteSize)
                    {
                        return(false);
                    }
                    if (_keyMap640KeysSize == -1)
                    {
                        _keyMap640KeysSize = buffer.ReadInt();
                    }
                    if (_keyMap640Keys == null)
                    {
                        _keyMap640Keys = new KeyMap640Keys(new SortedDictionary <Number640, ICollection <Number160> >());
                        // TODO check TreeMap equivalent
                    }

                    const int meta = 4 * Number160.ByteArraySize;

                    for (int i = _keyMap640Keys.Size; i < _keyMap640KeysSize; i++)
                    {
                        if (buffer.ReadableBytes < meta + Utils.Utils.ByteByteSize)
                        {
                            return(false);
                        }
                        size = buffer.GetUByte(buffer.ReaderIndex + meta);

                        if (buffer.ReadableBytes <
                            meta + Utils.Utils.ByteByteSize + (size * Number160.ByteArraySize))
                        {
                            return(false);
                        }
                        var me = new sbyte[Number160.ByteArraySize];
                        buffer.ReadBytes(me);
                        var locationKey = new Number160(me);
                        buffer.ReadBytes(me);
                        var domainKey = new Number160(me);
                        buffer.ReadBytes(me);
                        var contentKey = new Number160(me);
                        buffer.ReadBytes(me);
                        var versionKey = new Number160(me);

                        int numBasedOn = buffer.ReadByte();
                        var value      = new HashSet <Number160>();
                        for (int j = 0; j < numBasedOn; j++)
                        {
                            buffer.ReadBytes(me);
                            var basedOnKey = new Number160(me);
                            value.Add(basedOnKey);
                        }

                        _keyMap640Keys.Put(new Number640(locationKey, domainKey, contentKey, versionKey), value);
                    }

                    Message.SetKeyMap640Keys(_keyMap640Keys);
                    LastContent        = _contentTypes.Dequeue();
                    _keyMap640KeysSize = -1;     // TODO why here? not in prepareFinish()?
                    _keyMap640Keys     = null;
                    break;

                case Message.Content.MapKey640Byte:
                    if (_keyMapByteSize == -1 && buffer.ReadableBytes < Utils.Utils.IntegerByteSize)
                    {
                        return(false);
                    }
                    if (_keyMapByteSize == -1)
                    {
                        _keyMapByteSize = buffer.ReadInt();
                    }
                    if (_keyMapByte == null)
                    {
                        _keyMapByte = new KeyMapByte(new Dictionary <Number640, sbyte>(2 * _keyMapByteSize));
                    }

                    for (int i = _keyMapByte.Size; i < _keyMapByteSize; i++)
                    {
                        if (buffer.ReadableBytes < 4 * Number160.ByteArraySize + 1)
                        {
                            return(false);
                        }
                        var me = new sbyte[Number160.ByteArraySize];
                        buffer.ReadBytes(me);
                        var locationKey = new Number160(me);
                        buffer.ReadBytes(me);
                        var domainKey = new Number160(me);
                        buffer.ReadBytes(me);
                        var contentKey = new Number160(me);
                        buffer.ReadBytes(me);
                        var versionKey = new Number160(me);

                        sbyte value = buffer.ReadByte();
                        _keyMapByte.Put(new Number640(locationKey, domainKey, contentKey, versionKey), value);
                    }

                    Message.SetKeyMapByte(_keyMapByte);
                    LastContent     = _contentTypes.Dequeue();
                    _keyMapByteSize = -1;     // TODO why here? not in prepareFinish()?
                    _keyMapByte     = null;
                    break;

                case Message.Content.ByteBuffer:
                    if (_bufferSize == -1 && buffer.ReadableBytes < Utils.Utils.IntegerByteSize)
                    {
                        return(false);
                    }
                    if (_bufferSize == -1)
                    {
                        _bufferSize = buffer.ReadInt();
                    }
                    if (_buffer == null)
                    {
                        _buffer = new DataBuffer();
                    }

                    int already   = _buffer.AlreadyTransferred;
                    int remaining = _bufferSize - already;
                    // already finished
                    if (remaining != 0)
                    {
                        int read = _buffer.TransferFrom(buffer, remaining);
                        if (read != remaining)
                        {
                            Logger.Debug(
                                "Still looking for data. Indicating that its not finished yet. Already Transferred = {0}, Size = {1}.",
                                _buffer.AlreadyTransferred, _bufferSize);
                            return(false);
                        }
                    }

                    ByteBuf buf2 = AlternativeCompositeByteBuf.CompBuffer(_buffer.ToByteBufs());
                    Message.SetBuffer(new Buffer(buf2, _bufferSize));
                    LastContent = _contentTypes.Dequeue();
                    _bufferSize = -1;
                    _buffer     = null;
                    break;

                case Message.Content.SetTrackerData:
                    if (_trackerDataSize == -1 && buffer.ReadableBytes < Utils.Utils.ByteByteSize)
                    {
                        return(false);
                    }
                    if (_trackerDataSize == -1)
                    {
                        _trackerDataSize = buffer.ReadUByte();
                    }
                    if (_trackerData == null)
                    {
                        _trackerData = new TrackerData(new Dictionary <PeerAddress, Data>(2 * _trackerDataSize));
                    }
                    if (_currentTrackerData != null)
                    {
                        if (!_currentTrackerData.DecodeBuffer(buffer))
                        {
                            return(false);
                        }
                        if (!_currentTrackerData.DecodeDone(buffer, Message.PublicKey(0), _signatureFactory))
                        {
                            return(false);
                        }
                        _currentTrackerData = null;
                    }
                    for (int i = _trackerData.Size; i < _trackerDataSize; i++)
                    {
                        if (buffer.ReadableBytes < Utils.Utils.ShortByteSize)
                        {
                            return(false);
                        }

                        int header = buffer.GetUShort(buffer.ReaderIndex);
                        size = PeerAddress.CalculateSize(header);
                        if (buffer.ReadableBytes < Utils.Utils.ShortByteSize)
                        {
                            return(false);
                        }
                        var pa = new PeerAddress(buffer);

                        _currentTrackerData = Data.DeocdeHeader(buffer, _signatureFactory);
                        if (_currentTrackerData == null)
                        {
                            return(false);
                        }
                        _trackerData.PeerAddresses.Add(pa, _currentTrackerData);
                        if (Message.IsSign)
                        {
                            _currentTrackerData.SetPublicKey(Message.PublicKey(0));
                        }
                        if (!_currentTrackerData.DecodeBuffer(buffer))
                        {
                            return(false);
                        }
                        if (!_currentTrackerData.DecodeDone(buffer, Message.PublicKey(0), _signatureFactory))
                        {
                            return(false);
                        }
                        _currentTrackerData = null;     // TODO why here?
                    }

                    Message.SetTrackerData(_trackerData);
                    LastContent      = _contentTypes.Dequeue();
                    _trackerDataSize = -1;
                    _trackerData     = null;
                    break;

                case Message.Content.PublicKey:     // fall-through
                case Message.Content.PublicKeySignature:
                    receivedPublicKey = _signatureFactory.DecodePublicKey(buffer);
                    if (content == Message.Content.PublicKeySignature)
                    {
                        if (receivedPublicKey == PeerBuilder.EmptyPublicKey)     // TODO check if works
                        {
                            // TODO throw InvalidKeyException
                            throw new SystemException("The public key cannot be empty.");
                        }
                    }
                    if (receivedPublicKey == null)
                    {
                        return(false);
                    }

                    Message.SetPublicKey(receivedPublicKey);
                    LastContent = _contentTypes.Dequeue();
                    break;

                default:
                    break;
                }
            }

            if (Message.IsSign)
            {
                var signatureEncode = _signatureFactory.SignatureCodec;
                size = signatureEncode.SignatureSize;
                if (buffer.ReadableBytes < size)
                {
                    return(false);
                }

                signatureEncode.Read(buffer);
                Message.SetReceivedSignature(signatureEncode);
            }
            return(true);
        }