void cancel(boolean sequenced, int oldtag) { // cancel stuff from the pending packet queue _pendingPacketQueue.cancel(sequenced, oldtag); // cancel stuff from the outstanding packet queue TSNRangeHandler rh = new TSNRangeHandler(false, sequenced); _outstandingPacketQueue.cancel(sequenced, oldtag, rh); ACKInformation ai = new ACKInformation(); rh.fillACKInformation(ai); // send control packet containing cancelled packets chunk MessagePacket p = new MessagePacket(); p.setFlags(MessagePacket.HEADER_FLAG_CONTROL); CancelledPacketsChunk cpChk = new CancelledPacketsChunk(ai); p.addChunk(cpChk); MessagePacketInfo pi = new MessagePacketInfo( p, TxParams.MAX_PRIORITY, 0, 0, MessageMocket.DEFAULT_RETRANSMISSION_TIMEOUT); transmitPacket(pi); }
void send( boolean reliable, boolean sequenced, byte[] buf, int off, int len, int tag, int priority, long enqueue_timeout, long retry_timeout) throws IOException { /* we accept data only if the connection is not closed */ if (_status.currentState() != MessageStateMachine.ESTABLISHED) throw new IOException("Connection closed!"); /* this is the space we can use for data in each packet * (provided we have only a single DATA chunk in each packet) */ int availSize = _mocket.getMTU() - (MessagePacket.HEADER_SIZE + DataChunk.DATA_CHUNK_HEADER_SIZE); if (_mocket.isCrossSequencingEnabled()) availSize -= DeliveryPrerequisites.DELIVERY_PREREQUISITES_SIZE; _logger.fine( "MessageTransmitter::send " + (reliable ? "R " : "") + (sequenced ? "S " : "") + "len = " + len + " tag = " + tag); int toSend = len; int sent = 0; int fragmentNum = 0; boolean fragmentationNeeded = len > availSize; if (fragmentationNeeded) _logger.info("fragmentation needed!!!"); // build and enqueue message packet(s) while (toSend > 0) { int cc = Math.min(toSend, availSize); MessagePacket p = new MessagePacket(); if (reliable) p.setFlags(MessagePacket.HEADER_FLAG_RELIABLE); if (sequenced) p.setFlags(MessagePacket.HEADER_FLAG_SEQUENCED); if (fragmentationNeeded) p.allocateSpaceForDeliveryPrerequisites(); DataChunk chk = new DataChunk(tag, buf, off + sent, cc); if (!p.addChunk(chk)) { // this should never happen throw new IOException("Buffer size too big"); } toSend -= cc; if (fragmentationNeeded) { assert toSend >= 0; if (toSend == 0) { p.setFlags(MessagePacket.HEADER_FLAG_LAST_FRAGMENT); } else { if (fragmentNum == 0) { p.setFlags(MessagePacket.HEADER_FLAG_FIRST_FRAGMENT); } p.setFlags(MessagePacket.HEADER_FLAG_MORE_FRAGMENTS); } } // enqueue message packet if (!enqueueMessagePacket(p, priority, enqueue_timeout, retry_timeout)) { throw new IOException("Pending packet queue is full."); } ++fragmentNum; sent += cc; } transmitNextPacket(); // wake up transmitter thread synchronized (this) { notifyAll(); } }