Header readHeader() throws IOException {
    try (final ByteBufferSharing sharedBuffer = readAtLeast(Connection.MSG_HEADER_BYTES)) {
      ByteBuffer unwrappedBuffer = sharedBuffer.getBuffer();

      Assert.assertTrue(unwrappedBuffer.remaining() >= Connection.MSG_HEADER_BYTES);

      try {
        int nioMessageLength = unwrappedBuffer.getInt();
        /* nioMessageVersion = */
        Connection.calcHdrVersion(nioMessageLength);
        nioMessageLength = Connection.calcMsgByteSize(nioMessageLength);
        byte nioMessageType = unwrappedBuffer.get();
        short nioMsgId = unwrappedBuffer.getShort();

        boolean directAck = (nioMessageType & Connection.DIRECT_ACK_BIT) != 0;
        if (directAck) {
          nioMessageType &= ~Connection.DIRECT_ACK_BIT; // clear the ack bit
        }

        header.setFields(nioMessageLength, nioMessageType, nioMsgId);

        return header;
      } catch (BufferUnderflowException e) {
        throw e;
      }
    }

  }
This class is currently used for reading direct ack responses It should probably be used for all
of the reading done in Connection.
geode-core/src/main/java/org/apache/geode/internal/tcp/MsgReader.java