@Override
  public void handle(Address address, ByteBuffer buffer) {
    if ((cipher == null) || (mac == null)) {
      sequence++;
      wrappee.handle(address, buffer);
      return;
    }

    ByteBuffer sequenceBuffer = ByteBuffer.allocate(Ints.BYTES);
    sequenceBuffer.putInt(sequence);
    sequence++;
    sequenceBuffer.flip();

    mac.reset();
    mac.update(sequenceBuffer);
    int p = buffer.position();
    mac.update(buffer);
    buffer.position(p);

    byte[] calculatedMac = new byte[mac.getMacLength()];
    try {
      mac.doFinal(calculatedMac, 0);
    } catch (ShortBufferException e) {
      throw new RuntimeException(e);
    } catch (IllegalStateException e) {
      throw new RuntimeException(e);
    }

    ByteBuffer b = ByteBuffer.allocate(buffer.remaining() + calculatedMac.length);
    try {
      cipher.update(buffer, b);
    } catch (ShortBufferException e) {
      throw new RuntimeException(e);
    }
    b.put(calculatedMac);
    b.flip();

    wrappee.handle(address, b);
  }
 @Override
 public void close() {
   wrappee.close();
 }