private void transmitNextPacket() {
    // TODO: implement a serious bandwidth constraint mechanism

    synchronized (_pendingPacketQueue) {
      if (!_pendingPacketQueue.isEmpty()) {
        // _logger.info ("CHECKING PENDING PACKET QUEUE");
        MessagePacketInfo mpi = _pendingPacketQueue.peek();
        int available = Math.max(_remoteWindowSize - _outstandingPacketQueue.getSize(), 0);
        /*
        _logger.info ("2send from PPQ: " + mpi.getPacket().getSize() +
                      " available: " + available +
                      " (win: " + _remoteWindowSize +
                      " opq.size: " + _outstandingPacketQueue.getSize() +
                      ")");
        */

        if (mpi != null && (mpi.getPacket().getSizeWithoutSACKChunk() < available)) {
          // _logger.info ("XMIT FROM PENDING PACKET QUEUE");

          // transmit packet
          transmitPacket(mpi);
          MessagePacket p = mpi.getPacket();

          // update remote window size
          _remoteWindowSize -= p.getSizeWithoutSACKChunk();

          // update statistics
          int sent = p.getSize();

          ++_mocket.getStatistics()._sentPackets;
          _mocket.getStatistics()._sentBytes += sent;

          _logger.info(
              "XMITTED PACKET "
                  + p.getSequenceNumber()
                  + " SIZE "
                  + p.getSize()
                  + " FROM PENDING PACKET QUEUE");
          _pendingPacketQueue._dump(System.err);

          // move packet from the pending packet queue...
          _pendingPacketQueue.remove(mpi);

          _logger.info(
              "REMOVED PACKET "
                  + p.getSequenceNumber()
                  + " SIZE "
                  + p.getSize()
                  + " FROM PENDING PACKET QUEUE");
          _pendingPacketQueue._dump(System.err);

          // ...to the outstanding queue
          if (mpi.getPacket().isFlagSet(MessagePacket.HEADER_FLAG_RELIABLE)
              || mpi.getPacket().isFlagSet(MessagePacket.HEADER_FLAG_CONTROL)) {
            // remove SACK chunk from packet which is going to be inserted
            // in the outstanding packet queue
            p.unsetSACKChunk();
            _outstandingPacketQueue.insert(mpi);
          }

          // _logger.info ("END XMIT FROM PENDING PACKET QUEUE");
        }
      }
    }

    synchronized (_outstandingPacketQueue) {
      if (!_outstandingPacketQueue.isEmpty()) {
        // _logger.info ("CHECKING OUTSTANDING PACKET QUEUE");
        MessagePacketInfo mpi = _outstandingPacketQueue.extractIfTimeout();
        if (mpi != null) {
          // _logger.info ("XMIT FROM OUTSTANDING PACKET QUEUE");

          // retransmit packet
          MessagePacket p = mpi.getPacket();
          transmitDatagram(p, true);

          _logger.info(
              "XMITTED PACKET "
                  + p.getSequenceNumber()
                  + " SIZE "
                  + p.getSize()
                  + " FROM OUTSTANDING PACKET QUEUE");
          _outstandingPacketQueue._dump(System.err);

          // update statistics
          int sent = p.getSize();
          ++_mocket.getStatistics()._retransmittedPackets;
          _mocket.getStatistics()._sentBytes += sent;

          // remove SACK chunk from packet which is going to be reinserted
          // in the outstanding packet queue
          p.unsetSACKChunk();
          assert p.getSize() == p.getSizeWithoutSACKChunk();

          // reinsert mpi at the end of the outstanding packet queue
          _outstandingPacketQueue.insert(mpi);

          // _logger.info ("END XMIT FROM OUTSTANDING PACKET QUEUE");
        }
      }
    }
  }
 private void transmitPacket(MessagePacketInfo mpi) {
   MessagePacket p = mpi.getPacket();
   transmitMessagePacket(p, true);
   mpi.setLastIOOperationTime(System.currentTimeMillis());
 }