示例#1
0
  public Enum<?> putConfirm(PublicKey publicKey, Number640 key, Data newData) {
    RangeLock<Number640>.Range lock = lock(key);
    try {
      if (!securityEntryCheck(
          key.locationAndDomainAndContentKey(),
          publicKey,
          newData.publicKey(),
          newData.isProtectedEntry())) {
        return PutStatus.FAILED_SECURITY;
      }

      final Data data = backend.get(key);
      if (data != null) {
        // remove prepare flag
        data.prepareFlag(false);

        data.validFromMillis(newData.validFromMillis());
        data.ttlSeconds(newData.ttlSeconds());

        long expiration = data.expirationMillis();
        // handle timeout
        backend.addTimeout(key, expiration);
        backend.put(key, data);
        // don't release data as we just update
        return PutStatus.OK;
      } else {
        return PutStatus.NOT_FOUND;
      }
    } finally {
      newData.release();
      lock.unlock();
    }
    // TODO: check for FORKS!
  }
 public static void main(String[] args) throws Exception {
   Peer master = null;
   try {
     Peer[] peers = ExampleUtils.createAndAttachNodes(100, 4001);
     master = peers[0];
     MyPeer myPeer = new MyPeer(master);
     ExampleUtils.bootstrap(peers);
     myPeer
         .put(
             "This is my location key",
             "This is my domain",
             "This is my content key",
             "And here comes the data")
         .awaitUninterruptibly();
     FutureDHT futureDHT =
         myPeer.get("This is my location key", "This is my domain", "This is my content key");
     futureDHT.awaitUninterruptibly();
     System.err.println(futureDHT.getFailedReason());
     Map<Number160, Data> map = futureDHT.getDataMap();
     for (Data data : map.values()) {
       MyData myData = (MyData) data.getObject();
       System.out.println(
           "key: "
               + myData.getKey()
               + ", domain: "
               + myData.getDomain()
               + ", content: "
               + myData.getContent()
               + ", data: "
               + myData.getData());
     }
   } finally {
     master.halt();
   }
 }
示例#3
0
  public NavigableMap<Number640, Data> removeReturnData(
      Number640 from, Number640 to, PublicKey publicKey) {
    RangeLock<Number640>.Range lock = rangeLock.lock(from, to);
    try {
      Map<Number640, Data> tmp = backend.subMap(from, to);
      NavigableMap<Number640, Data> result = new TreeMap<Number640, Data>();

      for (Number640 key : tmp.keySet()) {
        // fail fast, as soon as we want to remove 1 domain that we
        // cannot, abort
        if (!canClaimDomain(key.locationAndDomainKey(), publicKey)) {
          result.put(key, null);
        } else if (!canClaimEntry(key.locationAndDomainAndContentKey(), publicKey)) {
          result.put(key, null);
        } else {
          Data toRemove = backend.get(key);
          if (toRemove != null
              && (toRemove.publicKey() == null || toRemove.publicKey().equals(publicKey))) {
            backend.removeTimeout(key);
            Data removed = backend.remove(key, true);
            result.put(key, removed);
          }
        }
      }
      return result;
    } finally {
      lock.unlock();
    }
  }
示例#4
0
 public void checkTimeout() {
   long time = System.currentTimeMillis();
   Collection<Number640> toRemove = backend.subMapTimeout(time);
   for (Number640 key : toRemove) {
     RangeLock<Number640>.Range lock = lock(key);
     try {
       Data oldData = backend.remove(key, false);
       if (oldData != null) {
         oldData.release();
       }
       backend.removeTimeout(key);
       // remove responsibility if we don't have any data stored under
       // locationkey
       Number160 locationKey = key.locationKey();
       RangeLock<Number640>.Range lockResp = lockResponsibility(locationKey);
       try {
         if (isEmpty(locationKey)) {
           backend.removeResponsibility(locationKey);
         }
       } finally {
         lockResp.unlock();
       }
     } finally {
       lock.unlock();
     }
   }
 }
示例#5
0
 public static Data createData(
     final byte[] me,
     final int offset,
     final int length,
     final int ttl,
     boolean protectedEntry,
     PeerAddress originator) {
   Data data;
   // length may be 0 if data is only used for expiration
   if (length == 0) data = new Data(EMPTY_BYTE_ARRAY, originator);
   else {
     // check if its worth coping the buffer, or just take the one backed
     // by the bytebuffer. If the backing buffer is too big, then its a
     // waste of space and we should copy, otherwise, take the backing
     // array.
     // TODO: find good values for this. This is just a guess
     final boolean copy = true;
     // final boolean copy = me.length / length > 1;
     // we have to use copy if we use an exectution handler, otherwise
     // the buffer will have different data.
     if (copy) {
       final byte[] me2 = new byte[length];
       System.arraycopy(me, offset, me2, 0, length);
       data = new Data(me2, 0, length, originator);
     } else data = new Data(me, offset, length, originator);
   }
   data.setTTLSeconds(ttl);
   data.setProtectedEntry(protectedEntry);
   return data;
 }
示例#6
0
 private void get(Number160 key) {
   Data data = get(new Number640(key, Number160.ZERO, Number160.ZERO, Number160.ZERO));
   byte[] byteArray = new byte[0];
   if (data != null) {
     byteArray = (byte[]) data.toBytes();
   }
   LOG.debug("Got {} bytes", byteArray.length);
 }
示例#7
0
 private Data getInternal(Number640 key) {
   Data data = backend.get(key);
   if (data != null && !data.hasPrepareFlag()) {
     return data;
   } else {
     return null;
   }
 }
示例#8
0
 public static void inheritPublicKey(Message message, Data data) {
   if (message.isSign()
       && message.publicKey(0) != null
       && data.hasPublicKey()
       && (data.publicKey() == null || data.publicKey() == PeerBuilder.EMPTY_PUBLIC_KEY)) {
     data.publicKey(message.publicKey(0));
   }
 }
示例#9
0
 public Data get(Number640 key) {
   RangeLock<Number640>.Range lock = lock(key);
   try {
     Data tmp = getInternal(key);
     return tmp == null ? null : tmp.duplicate();
   } finally {
     lock.unlock();
   }
 }
示例#10
0
  private void add(Peer peer, byte[] key, byte[] value) throws InterruptedException {
    RoutingConfiguration rc = new RoutingConfiguration(1, 0, 10, 1);
    RequestP2PConfiguration pc = new RequestP2PConfiguration(3, 5, 0);
    ConfigurationStore cs = Configurations.defaultStoreConfiguration();
    cs.setRequestP2PConfiguration(pc);
    cs.setRoutingConfiguration(rc);

    Data data = new Data(value);
    data.setTTLSeconds(3);
    peer.add(new Number160(key), data, cs)
        .addListener(
            new BaseFutureAdapter<FutureDHT>() {
              @Override
              public void operationComplete(final FutureDHT future) throws Exception {
                System.out.println(future.getRawKeys());
              }
            });
  }
示例#11
0
 /* (non-Javadoc)
  * @see net.tomp2p.dht.DigestStorage#digest(java.util.Collection)
  */
 @Override
 public DigestInfo digest(Collection<Number640> number640s) {
   DigestInfo digestInfo = new DigestInfo();
   for (Number640 number640 : number640s) {
     RangeLock<Number640>.Range lock = lock(number640);
     try {
       if (backend.contains(number640)) {
         Data data = getInternal(number640);
         if (data != null) {
           digestInfo.put(number640, data.basedOnSet());
         }
       }
     } finally {
       lock.unlock();
     }
   }
   return digestInfo;
 }
示例#12
0
 // iterative version
 private NavigableMap<Number640, Data> deletePredecessors(
     Number640 key, NavigableMap<Number640, Data> sortedMap) {
   final List<Number640> toRemove = new ArrayList<Number640>();
   final NavigableMap<Number640, Data> removed = new TreeMap<Number640, Data>();
   toRemove.add(key);
   while (!toRemove.isEmpty()) {
     final Number640 key2 = toRemove.remove(0);
     final Data version = sortedMap.remove(key2);
     if (version != null) {
       removed.put(key2, version);
       // check if version has been already deleted && // check if version is initial version
       if (!version.basedOnSet().isEmpty()) {
         for (final Number160 basedOnKey : version.basedOnSet()) {
           toRemove.add(new Number640(key.locationAndDomainAndContentKey(), basedOnKey));
         }
       }
     }
   }
   return removed;
 }
示例#13
0
  public void release() {
    if (message != null) {
      message.release();
    }
    // release partial data
    if (data != null) {
      data.release();
    }
    if (dataMap != null) {
      for (Data data : dataMap.dataMap().values()) {
        data.release();
      }
    }
    if (buffer != null) {
      buffer.release();
    }

    if (currentTrackerData != null) {
      currentTrackerData.release();
    }
    if (trackerData != null) {
      for (Data data : trackerData.peerAddresses().values()) {
        data.release();
      }
    }
  }
示例#14
0
  public boolean put(Number640 key) {
    Data data = generateRandomData();
    long startTime = System.currentTimeMillis();
    FuturePut futurePut =
        peerDHT
            .put(key.locationKey())
            .domainKey(key.domainKey())
            .versionKey(key.versionKey())
            .data(key.contentKey(), data)
            .routingConfiguration(routingConfig)
            .requestP2PConfiguration(requestConfig)
            .start()
            .awaitUninterruptibly();
    putStats.report(System.currentTimeMillis() - startTime, futurePut.isSuccess());

    LOG.debug(
        "Put of {} bytes is success = {}. Reason: {}",
        data.length(),
        futurePut.isSuccess(),
        futurePut.failedReason());
    return futurePut.isSuccess();
  }
示例#15
0
 public Pair<Data, Enum<?>> remove(Number640 key, PublicKey publicKey, boolean returnData) {
   RangeLock<Number640>.Range lock = lock(key);
   try {
     if (!canClaimDomain(key.locationAndDomainKey(), publicKey)) {
       return new Pair<Data, Enum<?>>(null, PutStatus.FAILED_SECURITY);
     }
     if (!canClaimEntry(key.locationAndDomainAndContentKey(), publicKey)) {
       return new Pair<Data, Enum<?>>(null, PutStatus.FAILED_SECURITY);
     }
     if (!backend.contains(key)) {
       return new Pair<Data, Enum<?>>(null, PutStatus.NOT_FOUND);
     }
     backend.removeTimeout(key);
     Data removed = backend.remove(key, returnData);
     if (removed != null && !returnData) {
       removed.release();
     }
     // else -> it will be removed in the encoder
     return new Pair<Data, Enum<?>>(removed, PutStatus.OK);
   } finally {
     lock.unlock();
   }
 }
示例#16
0
 public static int encodeData(ProtocolChunkedInput input, final Message message, Data data) {
   int count = 4 + 4;
   // encode entry protection in millis as the sign bit. Thus the max value
   // of millis is 2^31, which is more than enough
   int seconds = data.getTTLSeconds();
   seconds = data.isProtectedEntry() ? seconds | 0x80000000 : seconds & 0x7FFFFFFF;
   input.copyToCurrent(seconds);
   input.copyToCurrent(data.getLength());
   // the real data
   input.copyToCurrent(data.getData(), data.getOffset(), data.getLength());
   count += data.getLength();
   return count;
 }
示例#17
0
  public Map<Number640, Enum<?>> putAll(
      final NavigableMap<Number640, Data> dataMap,
      PublicKey publicKey,
      boolean putIfAbsent,
      boolean domainProtection,
      boolean sendSelf) {
    if (dataMap.isEmpty()) {
      return Collections.emptyMap();
    }
    final Number640 min = dataMap.firstKey();
    final Number640 max = dataMap.lastKey();
    final Map<Number640, Enum<?>> retVal = new HashMap<Number640, Enum<?>>();
    final HashSet<Number480> keysToCheck = new HashSet<Number480>();
    final RangeLock<Number640>.Range lock = lock(min, max);
    try {
      for (Map.Entry<Number640, Data> entry : dataMap.entrySet()) {
        Number640 key = entry.getKey();
        keysToCheck.add(key.locationAndDomainAndContentKey());
        Data newData = entry.getValue();
        if (!securityDomainCheck(
            key.locationAndDomainKey(), publicKey, publicKey, domainProtection)) {
          retVal.put(key, PutStatus.FAILED_SECURITY);
          newData.release();
          continue;
        }

        // We need this check in case we did not use the encoder/decoder,
        // which is the case if we send the message to ourself. In that
        // case, the public key of the data is never set to the message
        // publick key, if the publick key of the data was null.
        final PublicKey dataKey;
        if (sendSelf && newData.publicKey() == null) {
          dataKey = publicKey;
        } else {
          dataKey = newData.publicKey();
        }

        if (!securityEntryCheck(
            key.locationAndDomainAndContentKey(), publicKey, dataKey, newData.isProtectedEntry())) {
          retVal.put(key, PutStatus.FAILED_SECURITY);
          newData.release();
          continue;
        }

        final Data oldDataGet = backend.get(key);
        if (oldDataGet != null) {
          if (putIfAbsent) {
            retVal.put(key, PutStatus.FAILED_NOT_ABSENT);
            newData.release();
            continue;
          }

          if (oldDataGet.isDeleted()) {
            retVal.put(key, PutStatus.DELETED);
            newData.release();
            continue;
          }
          if (!oldDataGet.basedOnSet().equals(newData.basedOnSet())) {
            retVal.put(key, PutStatus.VERSION_FORK);
            newData.release();
            continue;
          }
        }

        final Data oldDataPut = backend.put(key, newData);

        long expiration = newData.expirationMillis();
        // handle timeout
        backend.addTimeout(key, expiration);

        if (newData.hasPrepareFlag()) {
          retVal.put(key, PutStatus.OK_PREPARED);
        } else {
          retVal.put(key, PutStatus.OK);
        }
        if (oldDataPut != null && oldDataPut != newData) {
          oldDataPut.release();
        }
      }

      for (Number480 key : keysToCheck) {

        // now check for forks
        Number640 minVersion = new Number640(key, Number160.ZERO);
        Number640 maxVersion = new Number640(key, Number160.MAX_VALUE);
        NavigableMap<Number640, Data> tmp = backend.subMap(minVersion, maxVersion);
        tmp = filterCopyOrig(tmp, -1, true);
        NavigableMap<Number640, Data> heads = getLatestInternalOrig(tmp);

        final boolean forked = heads.size() > 1;
        for (final Map.Entry<Number640, Data> entry : heads.entrySet()) {
          if (forked) {
            if (retVal.containsKey(entry.getKey())) {
              retVal.put(entry.getKey(), PutStatus.VERSION_FORK);
            }
          }
        }

        // now remove old versions
        if (maxVersions > 0) {
          NavigableMap<Number640, Data> versions = backend.subMap(minVersion, maxVersion);

          while (!versions.isEmpty()
              && versions.firstKey().versionKey().timestamp() + maxVersions
                  <= versions.lastKey().versionKey().timestamp()) {
            Map.Entry<Number640, Data> entry = versions.pollFirstEntry();
            Data removed = backend.remove(entry.getKey(), true);
            if (removed != null) {
              removed.release();
            }
            backend.removeTimeout(entry.getKey());
          }
        }
      }
      return retVal;

    } finally {
      lock.unlock();
    }
  }
示例#18
0
 /**
  * Decodes the payload from a Netty buffer in a big switch
  *
  * @param content The content type
  * @param buffer The buffer to read from
  * @param message The message to store the results
  * @throws IndexOutOfBoundsException If a buffer is read beyond its limits
  * @throws NoSuchAlgorithmException
  * @throws SignatureException
  * @throws InvalidKeyException
  * @throws InvalidKeySpecException
  * @throws InvalidKeySpecException
  * @throws IOException
  * @throws DecoderException
  * @throws ASN1Exception
  * @throws UnsupportedEncodingException If UTF-8 is not there
  */
 public static boolean decodePayload(
     final Content content, final ChannelBuffer buffer, final Message message)
     throws InvalidKeyException, SignatureException, NoSuchAlgorithmException,
         InvalidKeySpecException, IOException, DecoderException {
   final int len;
   byte[] me;
   switch (content) {
     case KEY:
       if (buffer.readableBytes() < 20) return false;
       message.setKey0(readID(buffer));
       return true;
     case KEY_KEY:
       if (buffer.readableBytes() < 40) return false;
       message.setKeyKey0(readID(buffer), readID(buffer));
       return true;
     case MAP_KEY_DATA:
       if (buffer.readableBytes() < 4) return false;
       int size = buffer.readInt();
       Map<Number160, Data> result = new HashMap<Number160, Data>(size);
       for (int i = 0; i < size; i++) {
         if (buffer.readableBytes() < 20) return false;
         Number160 key = readID(buffer);
         final Data data = decodeData(new ChannelDecoder(buffer), message.getSender());
         if (data == null) return false;
         if (message.isRequest()) {
           if (data.isProtectedEntry() && message.getPublicKey() == null)
             throw new DecoderException(
                 "You indicated that you want to protect the data, but you did not provide or provided too late a public key.");
           data.setPublicKey(message.getPublicKey());
         }
         result.put(key, data);
       }
       message.setDataMap0(result);
       return true;
     case MAP_KEY_KEY:
       if (buffer.readableBytes() < 4) return false;
       len = buffer.readInt();
       if (buffer.readableBytes() < ((20 + 20) * len)) return false;
       final Map<Number160, Number160> keyMap = new HashMap<Number160, Number160>();
       for (int i = 0; i < len; i++) {
         final Number160 key1 = readID(buffer);
         final Number160 key2 = readID(buffer);
         keyMap.put(key1, key2);
       }
       message.setKeyMap0(keyMap);
       return true;
     case SET_KEYS:
       // can be 31bit long ~ 2GB
       if (buffer.readableBytes() < 4) return false;
       len = buffer.readInt();
       if (buffer.readableBytes() < (20 * len)) return false;
       final Collection<Number160> tmp = new ArrayList<Number160>(len);
       for (int i = 0; i < len; i++) {
         Number160 key = readID(buffer);
         tmp.add(key);
       }
       message.setKeys0(tmp);
       return true;
     case SET_NEIGHBORS:
       if (buffer.readableBytes() < 1) return false;
       len = buffer.readUnsignedByte();
       if (buffer.readableBytes() < (len * PeerAddress.SIZE_IPv4)) return false;
       final Collection<PeerAddress> neighbors = new ArrayList<PeerAddress>(len);
       for (int i = 0; i < len; i++) {
         PeerAddress peerAddress = readPeerAddress(buffer);
         if (peerAddress == null) return false;
         neighbors.add(peerAddress);
       }
       message.setNeighbors0(neighbors);
       return true;
     case SET_TRACKER_DATA:
       if (buffer.readableBytes() < 1) return false;
       len = buffer.readUnsignedByte();
       if (buffer.readableBytes() < (len * (PeerAddress.SIZE_IPv4 + 1))) return false;
       final Collection<TrackerData> trackerDatas = new ArrayList<TrackerData>(len);
       for (int i = 0; i < len; i++) {
         PeerAddress peerAddress = readPeerAddress(buffer);
         if (peerAddress == null) return false;
         byte[] attachment = null;
         int offset = 0;
         int length = 0;
         if (buffer.readableBytes() < 1) return false;
         byte miniHeader = buffer.readByte();
         if (miniHeader != 0) {
           if (buffer.readableBytes() < 4) return false;
           length = buffer.readInt();
           if (buffer.readableBytes() < length) return false;
           attachment = new byte[length];
           buffer.readBytes(attachment);
         }
         trackerDatas.add(
             new TrackerData(peerAddress, message.getSender(), attachment, offset, length));
       }
       message.setTrackerData0(trackerDatas);
       return true;
     case CHANNEL_BUFFER:
       if (buffer.readableBytes() < 4) return false;
       len = buffer.readInt();
       if (buffer.readableBytes() < len) return false;
       // you can only use slice if no execution handler is in place,
       // otherwise, you will overwrite stuff
       final ChannelBuffer tmpBuffer = buffer.slice(buffer.readerIndex(), len);
       buffer.skipBytes(len);
       message.setPayload0(tmpBuffer);
       return true;
     case LONG:
       if (buffer.readableBytes() < 8) return false;
       message.setLong0(buffer.readLong());
       return true;
     case INTEGER:
       if (buffer.readableBytes() < 4) return false;
       message.setInteger0(buffer.readInt());
       return true;
     case PUBLIC_KEY:
     case PUBLIC_KEY_SIGNATURE:
       if (buffer.readableBytes() < 2) return false;
       len = buffer.readUnsignedShort();
       me = new byte[len];
       if (buffer.readableBytes() < len) return false;
       message.setPublicKey0(decodePublicKey(new ChannelDecoder(buffer), me));
       if (content == Content.PUBLIC_KEY_SIGNATURE) {
         message.setHintSign(true);
       }
       return true;
     case EMPTY:
     case RESERVED1:
     case RESERVED2:
     case RESERVED3:
     default:
       return true;
   }
 }
示例#19
0
  public Enum<?> updateMeta(PublicKey publicKey, Number640 key, Data newData) {
    RangeLock<Number640>.Range lock = lock(key);
    try {
      if (!securityEntryCheck(
          key.locationAndDomainAndContentKey(),
          publicKey,
          newData.publicKey(),
          newData.isProtectedEntry())) {
        return PutStatus.FAILED_SECURITY;
      }

      final Data data = backend.get(key);
      boolean changed = false;
      if (data != null && newData.publicKey() != null) {
        data.publicKey(newData.publicKey());
        changed = true;
      }
      if (data != null && newData.isSigned()) {
        data.signature(newData.signature());
        changed = true;
      }
      if (data != null) {
        data.validFromMillis(newData.validFromMillis());
        data.ttlSeconds(newData.ttlSeconds());
        changed = true;
      }
      if (changed) {
        long expiration = data.expirationMillis();
        // handle timeout
        backend.addTimeout(key, expiration);
        // no release of old data, as we just update it
        backend.put(key, data);
        return PutStatus.OK;
      } else {
        return PutStatus.NOT_FOUND;
      }
    } finally {
      newData.release();
      lock.unlock();
    }
  }
示例#20
0
  public boolean decodePayload(final ByteBuf buf)
      throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
    LOG.debug(
        "About to pass message {} to {}. Buffer to read: {}.",
        message,
        message.senderSocket(),
        buf.readableBytes());
    if (!message.hasContent()) {
      return true;
    }

    // payload comes here
    int size;
    PublicKey receivedPublicKey;
    while (contentTypes.size() > 0) {
      Content content = contentTypes.peek();
      LOG.debug("Parse content: {} in message {}", content, message);
      switch (content) {
        case INTEGER:
          if (buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) {
            return false;
          }
          message.intValue(buf.readInt());
          lastContent = contentTypes.poll();
          break;
        case LONG:
          if (buf.readableBytes() < Utils.LONG_BYTE_SIZE) {
            return false;
          }
          message.longValue(buf.readLong());
          lastContent = contentTypes.poll();
          break;
        case KEY:
          if (buf.readableBytes() < Number160.BYTE_ARRAY_SIZE) {
            return false;
          }
          byte[] me = new byte[Number160.BYTE_ARRAY_SIZE];
          buf.readBytes(me);
          message.key(new Number160(me));
          lastContent = contentTypes.poll();
          break;
        case BLOOM_FILTER:
          if (buf.readableBytes() < Utils.SHORT_BYTE_SIZE) {
            return false;
          }
          size = buf.getUnsignedShort(buf.readerIndex());
          if (buf.readableBytes() < size) {
            return false;
          }
          message.bloomFilter(new SimpleBloomFilter<Number160>(buf));
          lastContent = contentTypes.poll();
          break;
        case SET_NEIGHBORS:
          if (neighborSize == -1 && buf.readableBytes() < Utils.BYTE_BYTE_SIZE) {
            return false;
          }
          if (neighborSize == -1) {
            neighborSize = buf.readUnsignedByte();
          }
          if (neighborSet == null) {
            neighborSet = new NeighborSet(-1, new ArrayList<PeerAddress>(neighborSize));
          }
          for (int i = neighborSet.size(); i < neighborSize; i++) {
            if (buf.readableBytes() < Utils.SHORT_BYTE_SIZE) {
              return false;
            }
            int header = buf.getUnsignedShort(buf.readerIndex());
            size = PeerAddress.size(header);
            if (buf.readableBytes() < size) {
              return false;
            }
            PeerAddress pa = new PeerAddress(buf);
            neighborSet.add(pa);
          }
          message.neighborsSet(neighborSet);
          lastContent = contentTypes.poll();
          neighborSize = -1;
          neighborSet = null;
          break;
        case SET_PEER_SOCKET:
          if (peerSocketAddressSize == -1 && buf.readableBytes() < Utils.BYTE_BYTE_SIZE) {
            return false;
          }
          if (peerSocketAddressSize == -1) {
            peerSocketAddressSize = buf.readUnsignedByte();
          }
          if (peerSocketAddresses == null) {
            peerSocketAddresses = new ArrayList<PeerSocketAddress>(peerSocketAddressSize);
          }
          for (int i = peerSocketAddresses.size(); i < peerSocketAddressSize; i++) {
            if (buf.readableBytes() < Utils.BYTE_BYTE_SIZE) {
              return false;
            }
            int header = buf.getUnsignedByte(buf.readerIndex());
            boolean isIPv4 = header == 0;
            size = PeerSocketAddress.size(isIPv4);
            if (buf.readableBytes() < size + Utils.BYTE_BYTE_SIZE) {
              return false;
            }
            // skip the ipv4/ipv6 header
            buf.skipBytes(1);
            peerSocketAddresses.add(PeerSocketAddress.create(buf, isIPv4));
          }
          message.peerSocketAddresses(peerSocketAddresses);
          lastContent = contentTypes.poll();
          peerSocketAddressSize = -1;
          peerSocketAddresses = null;
          break;
        case SET_KEY640:
          if (keyCollectionSize == -1 && buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) {
            return false;
          }
          if (keyCollectionSize == -1) {
            keyCollectionSize = buf.readInt();
          }
          if (keyCollection == null) {
            keyCollection = new KeyCollection(new ArrayList<Number640>(keyCollectionSize));
          }
          for (int i = keyCollection.size(); i < keyCollectionSize; i++) {
            if (buf.readableBytes()
                < Number160.BYTE_ARRAY_SIZE
                    + Number160.BYTE_ARRAY_SIZE
                    + Number160.BYTE_ARRAY_SIZE
                    + Number160.BYTE_ARRAY_SIZE) {
              return false;
            }
            byte[] me2 = new byte[Number160.BYTE_ARRAY_SIZE];
            buf.readBytes(me2);
            Number160 locationKey = new Number160(me2);
            buf.readBytes(me2);
            Number160 domainKey = new Number160(me2);
            buf.readBytes(me2);
            Number160 contentKey = new Number160(me2);
            buf.readBytes(me2);
            Number160 versionKey = new Number160(me2);
            keyCollection.add(new Number640(locationKey, domainKey, contentKey, versionKey));
          }
          message.keyCollection(keyCollection);
          lastContent = contentTypes.poll();
          keyCollectionSize = -1;
          keyCollection = null;
          break;
        case MAP_KEY640_DATA:
          if (mapSize == -1 && buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) {
            return false;
          }
          if (mapSize == -1) {
            mapSize = buf.readInt();
          }
          if (dataMap == null) {
            dataMap = new DataMap(new TreeMap<Number640, Data>());
          }
          if (data != null) {
            if (!data.decodeBuffer(buf)) {
              return false;
            }
            if (!data.decodeDone(buf, message.publicKey(0), signatureFactory)) {
              return false;
            }
            data = null;
            key = null;
          }
          for (int i = dataMap.size(); i < mapSize; i++) {
            if (key == null) {
              if (buf.readableBytes()
                  < Number160.BYTE_ARRAY_SIZE
                      + Number160.BYTE_ARRAY_SIZE
                      + Number160.BYTE_ARRAY_SIZE
                      + Number160.BYTE_ARRAY_SIZE) {
                return false;
              }
              byte[] me3 = new byte[Number160.BYTE_ARRAY_SIZE];
              buf.readBytes(me3);
              Number160 locationKey = new Number160(me3);
              buf.readBytes(me3);
              Number160 domainKey = new Number160(me3);
              buf.readBytes(me3);
              Number160 contentKey = new Number160(me3);
              buf.readBytes(me3);
              Number160 versionKey = new Number160(me3);
              key = new Number640(locationKey, domainKey, contentKey, versionKey);
            }
            LOG.debug("Key decoded in message {}, remaining {}", message, buf.readableBytes());
            data = Data.decodeHeader(buf, signatureFactory);
            if (data == null) {
              return false;
            }
            LOG.debug("Header decoded in message {}, remaining {}", message, buf.readableBytes());
            dataMap.dataMap().put(key, data);

            if (!data.decodeBuffer(buf)) {
              return false;
            }
            LOG.debug("Buffer decoded in message {}", message);
            if (!data.decodeDone(buf, message.publicKey(0), signatureFactory)) {
              return false;
            }
            LOG.debug("Done decoded in message {}", message);
            // if we have signed the message, set the public key anyway, but only if we indicated so
            inheritPublicKey(message, data);
            data = null;
            key = null;
          }

          message.setDataMap(dataMap);
          lastContent = contentTypes.poll();
          mapSize = -1;
          dataMap = null;
          break;
        case MAP_KEY640_KEYS:
          if (keyMap640KeysSize == -1 && buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) {
            return false;
          }
          if (keyMap640KeysSize == -1) {
            keyMap640KeysSize = buf.readInt();
          }
          if (keyMap640Keys == null) {
            keyMap640Keys = new KeyMap640Keys(new TreeMap<Number640, Collection<Number160>>());
          }

          final int meta =
              Number160.BYTE_ARRAY_SIZE
                  + Number160.BYTE_ARRAY_SIZE
                  + Number160.BYTE_ARRAY_SIZE
                  + Number160.BYTE_ARRAY_SIZE;

          for (int i = keyMap640Keys.size(); i < keyMap640KeysSize; i++) {
            if (buf.readableBytes() < meta + Utils.BYTE_BYTE_SIZE) {
              return false;
            }
            size = buf.getUnsignedByte(buf.readerIndex() + meta);

            if (buf.readableBytes()
                < meta + Utils.BYTE_BYTE_SIZE + (size * Number160.BYTE_ARRAY_SIZE)) {
              return false;
            }
            byte[] me3 = new byte[Number160.BYTE_ARRAY_SIZE];
            buf.readBytes(me3);
            Number160 locationKey = new Number160(me3);
            buf.readBytes(me3);
            Number160 domainKey = new Number160(me3);
            buf.readBytes(me3);
            Number160 contentKey = new Number160(me3);
            buf.readBytes(me3);
            Number160 versionKey = new Number160(me3);

            int numBasedOn = buf.readByte();
            Set<Number160> value = new HashSet<Number160>(numBasedOn);
            for (int j = 0; j < numBasedOn; j++) {
              buf.readBytes(me3);
              Number160 basedOnKey = new Number160(me3);
              value.add(basedOnKey);
            }

            keyMap640Keys.put(new Number640(locationKey, domainKey, contentKey, versionKey), value);
          }

          message.keyMap640Keys(keyMap640Keys);
          lastContent = contentTypes.poll();
          keyMap640KeysSize = -1;
          keyMap640Keys = null;
          break;
        case MAP_KEY640_BYTE:
          if (keyMapByteSize == -1 && buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) {
            return false;
          }
          if (keyMapByteSize == -1) {
            keyMapByteSize = buf.readInt();
          }
          if (keyMapByte == null) {
            keyMapByte = new KeyMapByte(new HashMap<Number640, Byte>(2 * keyMapByteSize));
          }

          for (int i = keyMapByte.size(); i < keyMapByteSize; i++) {
            if (buf.readableBytes()
                < Number160.BYTE_ARRAY_SIZE
                    + Number160.BYTE_ARRAY_SIZE
                    + Number160.BYTE_ARRAY_SIZE
                    + Number160.BYTE_ARRAY_SIZE
                    + 1) {
              return false;
            }
            byte[] me3 = new byte[Number160.BYTE_ARRAY_SIZE];
            buf.readBytes(me3);
            Number160 locationKey = new Number160(me3);
            buf.readBytes(me3);
            Number160 domainKey = new Number160(me3);
            buf.readBytes(me3);
            Number160 contentKey = new Number160(me3);
            buf.readBytes(me3);
            Number160 versionKey = new Number160(me3);
            byte value = buf.readByte();
            keyMapByte.put(new Number640(locationKey, domainKey, contentKey, versionKey), value);
          }

          message.keyMapByte(keyMapByte);
          lastContent = contentTypes.poll();
          keyMapByteSize = -1;
          keyMapByte = null;
          break;
        case BYTE_BUFFER:
          if (bufferSize == -1 && buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) {
            return false;
          }
          if (bufferSize == -1) {
            bufferSize = buf.readInt();
          }
          if (buffer == null) {
            buffer = new DataBuffer();
          }

          final int remaining = bufferSize - bufferTransferred;
          bufferTransferred += buffer.transferFrom(buf, remaining);

          if (bufferTransferred < bufferSize) {
            LOG.debug(
                "Still looking for data. Indicating that its not finished yet. Already Transferred = {}, Size = {}.",
                bufferTransferred,
                bufferSize);
            return false;
          }

          message.buffer(new Buffer(buffer.toByteBuf(), bufferSize));
          lastContent = contentTypes.poll();
          bufferSize = -1;
          bufferTransferred = 0;
          buffer = null;
          break;
        case SET_TRACKER_DATA:
          if (trackerDataSize == -1 && buf.readableBytes() < Utils.BYTE_BYTE_SIZE) {
            return false;
          }
          if (trackerDataSize == -1) {
            trackerDataSize = buf.readUnsignedByte();
          }
          if (trackerData == null) {
            trackerData = new TrackerData(new HashMap<PeerAddress, Data>(2 * trackerDataSize));
          }
          if (currentTrackerData != null) {
            if (!currentTrackerData.decodeBuffer(buf)) {
              return false;
            }
            if (!currentTrackerData.decodeDone(buf, message.publicKey(0), signatureFactory)) {
              return false;
            }
            currentTrackerData = null;
          }
          for (int i = trackerData.size(); i < trackerDataSize; i++) {

            if (buf.readableBytes() < Utils.SHORT_BYTE_SIZE) {
              return false;
            }

            int header = buf.getUnsignedShort(buf.readerIndex());

            size = PeerAddress.size(header);

            if (buf.readableBytes() < size) {
              return false;
            }
            PeerAddress pa = new PeerAddress(buf);

            currentTrackerData = Data.decodeHeader(buf, signatureFactory);
            if (currentTrackerData == null) {
              return false;
            }
            trackerData.peerAddresses().put(pa, currentTrackerData);
            if (message.isSign()) {
              currentTrackerData.publicKey(message.publicKey(0));
            }

            if (!currentTrackerData.decodeBuffer(buf)) {
              return false;
            }
            if (!currentTrackerData.decodeDone(buf, message.publicKey(0), signatureFactory)) {
              return false;
            }
            currentTrackerData = null;
          }

          message.trackerData(trackerData);
          lastContent = contentTypes.poll();
          trackerDataSize = -1;
          trackerData = null;
          break;
        case PUBLIC_KEY: // fall-through
        case PUBLIC_KEY_SIGNATURE:
          receivedPublicKey = signatureFactory.decodePublicKey(buf);
          if (content == Content.PUBLIC_KEY_SIGNATURE) {
            if (receivedPublicKey == PeerBuilder.EMPTY_PUBLIC_KEY) {
              throw new InvalidKeyException("The public key cannot be empty.");
            }
          }
          if (receivedPublicKey == null) {
            return false;
          }

          message.publicKey(receivedPublicKey);
          lastContent = contentTypes.poll();
          break;
        default:
          break;
      }
    }
    LOG.debug("Parsed content in message {}", message);
    if (message.isSign()) {
      size = signatureFactory.signatureSize();
      if (buf.readableBytes() < size) {
        return false;
      }

      SignatureCodec signatureEncode = signatureFactory.signatureCodec(buf);
      message.receivedSignature(signatureEncode);
    }
    return true;
  }