if(log.isErrorEnabled()) log.error("to " + dst_addr + ", exception is " + ex + ", stack trace:\n" + Util.printStackTrace(ex));
if(log.isErrorEnabled()) log.error("failure sending to " + dst_addr, ex);
        void doSend(Message msg) throws Exception {            IpAddress dst_addr=(IpAddress)msg.getDest();            byte[]    buffie=null;            if(dst_addr == null || dst_addr.getIpAddress() == null) {                if(log.isErrorEnabled()) log.error("the destination address is null; aborting send");                return;            }            try {                // set the source address if not yet set                if(msg.getSrc() == null)                    msg.setSrc(local_addr);                buffie=Util.objectToByteBuffer(msg);                if(buffie.length <= 0) {                    if(log.isErrorEnabled()) log.error("buffer.length is 0. Will not send message");                    return;                }                // we're using 'double-writes', sending the buffer to the destination in 2 pieces. this would                // ensure that, if the peer closed the connection while we were idle, we would get an exception.                // this won't happen if we use a single write (see Stevens, ch. 5.13).                if(out != null) {                    out.writeInt(buffie.length); // write the length of the data buffer first                    Util.doubleWrite(buffie, out);                    out.flush();  // may not be very efficient (but safe)                }            }            catch(Exception ex) {                if(log.isErrorEnabled()) log.error("to " + dst_addr + ", exception is " + ex + ", stack trace:\n" +                                                   Util.printStackTrace(ex));                remove(dst_addr);                throw ex;            }        }