Ejemplo n.º 1
0
  public OOOProtocolMessage parseMessage(TCByteBuffer[] data) throws TCProtocolException {
    int hdrLength = OOOProtocolMessageHeader.HEADER_LENGTH;
    if (hdrLength > data[0].limit()) {
      throw new TCProtocolException(
          "header not contained in first buffer: " + hdrLength + " > " + data[0].limit());
    }

    OOOProtocolMessageHeader header =
        new OOOProtocolMessageHeader(
            data[0].duplicate().limit(OOOProtocolMessageHeader.HEADER_LENGTH));
    header.validate();

    TCByteBuffer msgData[];
    if (header.getHeaderByteLength() < data[0].limit()) {
      msgData = new TCByteBuffer[data.length];
      System.arraycopy(data, 0, msgData, 0, msgData.length);

      TCByteBuffer firstPayloadBuffer = msgData[0].duplicate();
      firstPayloadBuffer.position(header.getHeaderByteLength());
      msgData[0] = firstPayloadBuffer.slice();
    } else {
      Assert.eval(data.length >= 1);
      msgData = new TCByteBuffer[data.length - 1];
      System.arraycopy(data, 1, msgData, 0, msgData.length);
    }

    return messageFactory.createNewMessage(header, msgData);
  }
  public void testGoodHeader() {
    byte[] data = getGoodHeader();
    TCByteBuffer buffer = TCByteBufferFactory.getInstance(false, WireProtocolHeader.MAX_LENGTH);
    buffer.put(data);
    buffer.flip();

    WireProtocolHeader header = new WireProtocolHeader(buffer);

    System.out.println(header);

    assertTrue(header.isChecksumValid());

    assertTrue(header.getVersion() == WireProtocolHeader.VERSION_2);
    assertTrue(header.getHeaderLength() == 8);
    assertTrue(header.getTypeOfService() == 2);
    assertTrue(header.getTimeToLive() == 3);

    assertTrue(header.getTotalPacketLength() == 255);
    assertTrue(header.getChecksum() == 2744585179L);
    assertTrue(
        Arrays.equals(
            header.getSourceAddress(), new byte[] {(byte) 0xFF, (byte) 1, (byte) 0xFF, (byte) 1}));
    assertTrue(
        Arrays.equals(
            header.getDestinationAddress(),
            new byte[] {(byte) 1, (byte) 0xFF, (byte) 1, (byte) 0xFF}));
    assertTrue(header.getSourcePort() == 43605);
    assertTrue(header.getDestinationPort() == 21930);
    assertTrue(header.getMessageCount() == 5);
    assertTrue(header.getOptions().length == 0);

    try {
      header.validate();
    } catch (WireProtocolHeaderFormatException e) {
      fail(e.getMessage());
    }

    // changing data in the header should cause the checksum to need to be recomputed
    header.setVersion((byte) (header.getVersion() + 1));
    assertFalse(header.isChecksumValid());

    // Fix and validate the checksum
    header.computeChecksum();
    assertTrue(header.isChecksumValid());
  }
  private TCNetworkMessage processPayloadData(TCConnection source, TCByteBuffer[] data)
      throws TCProtocolException {
    for (int i = 0; i < data.length; i++) {
      final TCByteBuffer buffer = data[i];

      if (!buffer.hasRemaining()) {
        buffer.flip();
        dataBytesNeeded -= buffer.limit();
        bufferIndex++;

        if (dataBytesNeeded < 0) {
          throw new TCProtocolException("More data in buffers than expected");
        }
      } else {
        break;
      }
    }

    if (0 == dataBytesNeeded) {
      if (bufferIndex != dataBuffers.length) {
        throw new TCProtocolException("Not all buffers consumed");
      }

      // message is complete!
      TCNetworkMessage msg = createMessage(source, header, dataBuffers);

      if (logger.isDebugEnabled()) {
        logger.debug("Message complete on connection " + source + ": " + msg.toString());
      }

      return msg;
    }

    Assert.eval(dataBytesNeeded > 0);

    // data portion not done, try again later
    return null;
  }
  private TCNetworkMessage processHeaderData(TCConnection source, TCByteBuffer[] data)
      throws TCProtocolException {
    Assert.eval(data.length == 1);
    Assert.eval(data[0] == this.header.getDataBuffer());

    if (!this.header.isHeaderLengthAvail()) {
      return null;
    }

    final TCByteBuffer buf = data[0];
    final int headerLength = this.header.getHeaderByteLength();
    final int bufferLength = buf.limit();

    if (headerLength == AbstractTCNetworkHeader.LENGTH_NOT_AVAIL) {
      return null;
    }

    if ((headerLength < header.minLength)
        || (headerLength > header.maxLength)
        || (headerLength < bufferLength)) {
      // header data is screwed
      throw new TCProtocolException(
          "Invalid Header Length: "
              + headerLength
              + ", min: "
              + header.minLength
              + ", max: "
              + header.maxLength
              + ", bufLen: "
              + bufferLength);
    }

    if (bufferLength != headerLength) {
      // maybe we should support a way to swap out the header buffer for a larger sized one
      // instead of always mandating that the backing buffer behind a header have
      // enough capacity for the largest possible header for the given protocol. Just a thought

      // protocol header is bigger than min length, adjust buffer limit and continue
      buf.limit(headerLength);
      return null;
    } else {
      Assert.eval(bufferLength == headerLength);

      if (buf.position() == headerLength) {
        this.header.validate();

        this.mode = MODE_DATA;
        this.dataBytesNeeded = computeDataLength(this.header);
        this.dataBuffers = null;

        if (this.dataBytesNeeded < 0) {
          throw new TCProtocolException("Negative data size detected: " + this.dataBytesNeeded);
        }

        // allow for message types with zero length data payload
        if (0 == this.dataBytesNeeded) {
          return createMessage(source, this.header, null);
        }

        return null;
      } else {
        // protocol header not completely read yet, do nothing
        return null;
      }
    }
  }