private void handleIncomingConfirmableCoapResponse(ChannelHandlerContext ctx, MessageEvent me) {
    InetSocketAddress remoteEndpoint = (InetSocketAddress) me.getRemoteAddress();
    CoapResponse coapResponse = (CoapResponse) me.getMessage();

    writeEmptyAcknowledgement(remoteEndpoint, coapResponse.getMessageID());

    ctx.sendUpstream(me);
  }
  private void handleOutgoingCoapResponse(ChannelHandlerContext ctx, MessageEvent me) {

    CoapResponse coapResponse = (CoapResponse) me.getMessage();
    InetSocketAddress remoteEndpoint = (InetSocketAddress) me.getRemoteAddress();

    IncomingMessageExchange messageExchange;
    synchronized (monitor) {
      messageExchange = ongoingMessageExchanges.remove(remoteEndpoint, coapResponse.getMessageID());
    }

    if (messageExchange instanceof IncomingReliableMessageExchange) {

      // if the ongoing message exchange is reliable and the empty ACK was not yet sent make
      // response piggy-
      // backed and suppress scheduled empty ACK
      if (!((IncomingReliableMessageExchange) messageExchange).isAcknowledgementSent()) {
        coapResponse.setMessageType(MessageType.Name.ACK.getNumber());
        ((IncomingReliableMessageExchange) messageExchange).setAcknowledgementSent();
      }
    }

    ctx.sendDownstream(me);
  }