Пример #1
0
  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();
    }
  }