/** Handle "Datagram Acknowledged" message */
    @Override
    public void handleDatagramAcknowledged(DatagramAcknowledgedMessage msg, Connection sender) {
      // check if this is from right source & to us
      if (!(msg.getDestNodeID() != null
          && msg.getSourceNodeID() != null
          && msg.getDestNodeID().equals(message.getSourceNodeID())
          && message.getDestNodeID().equals(msg.getSourceNodeID()))) {
        // not for us, just forward
        toUpstream.put(msg, toUpstream);
        return;
      }
      endTimeout();
      // forward message upstream
      toUpstream.put(msg, toUpstream);

      // and allow sending another
      new Thread(new Consumer(queue)).start();
    }
 /** Handle "Datagram Rejected" message */
 @Override
 public void handleDatagramRejected(DatagramRejectedMessage msg, Connection sender) {
   // check if this is from right source & to us
   if (!(msg.getDestNodeID() != null
       && msg.getSourceNodeID() != null
       && msg.getDestNodeID().equals(message.getSourceNodeID())
       && message.getDestNodeID().equals(msg.getSourceNodeID()))) {
     // not for us, just forward
     toUpstream.put(msg, toUpstream);
     return;
   }
   endTimeout();
   // check if resend permitted
   if (msg.canResend()) {
     forwardDownstream();
   } else {
     // forward upstream to originator and let them sort it out
     toUpstream.put(msg, toUpstream);
     // and allow sending another
     new Thread(new Consumer(queue)).start();
   }
 }
 void forwardDownstream() {
   toDownstream.put(message, fromDownstream);
   startTimeout();
 }
 /** Accept a datagram message to be sent */
 @Override
 public void put(Message msg, Connection toUpstream) {
   if (msg instanceof DatagramMessage)
     queue.add(new MessageMemo((DatagramMessage) msg, toUpstream, toDownstream));
   else toDownstream.put(msg, fromDownstream);
 }