net.i2p.client.streaming.impl

## Class ConnectionDataReceiver

- java.lang.Object
- - net.i2p.client.streaming.impl.ConnectionDataReceiver

- All Implemented Interfaces:
    MessageOutputStream.DataReceiver

      class ConnectionDataReceiver
      extends Object
      implements MessageOutputStream.DataReceiver

  Receive data from the MessageOutputStream, build a packet, and send it through a connection. The write calls on this do NOT block, but they also do not necessary imply immediate delivery, or even the generation of a new packet. This class is the only one that builds useful outbound Packet objects.

  MessageOutputStream -> ConnectionDataReceiver -> Connection -> PacketQueue -> I2PSession

  There's one of these per MessageOutputStream. It stores no state. It sends everything to the Connection unless the Connection is closed,

- - ### Constructor Summary

    Constructors
    Constructor and Description
    `ConnectionDataReceiver(I2PAppContext ctx, Connection con)`

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `(package private) void` | `destroy()`
    `PacketLocal` | `send(byte[] buf, int off, int size)` Send some data through the connection, attaching any appropriate flags onto the packet.
    `PacketLocal` | `send(byte[] buf, int off, int size, boolean forceIncrement)` Called externally from Connection with args (null, 0, 0, true) to send an empty data packet
    `MessageOutputStream.WriteStatus` | `writeData(byte[] buf, int off, int size)` Send some data through the connection, or if there is no new data, this may generate a packet with a plain ACK/NACK or CLOSE, or nothing whatsoever if there's nothing new to send.
    `boolean` | `writeInProcess()` This tells the flusher in MessageOutputStream whether to flush.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

    - #### ConnectionDataReceiver

          public ConnectionDataReceiver(I2PAppContext ctx,
                                        Connection con)

      Parameters:
        `con` - non-null

  - ### Method Detail

    - #### destroy

          void destroy()

    - #### send

          public PacketLocal send(byte[] buf,
                                  int off,
                                  int size)

      Send some data through the connection, attaching any appropriate flags onto the packet. Called externally from Connection with args (null, 0, 0) to send an ack
      Parameters:
        `buf` - data to be sent - may be null
        `off` - offset into the buffer to start writing from
        `size` - how many bytes of the buffer to write (may be 0)
      Returns:
        the packet sent

    - #### send

          public PacketLocal send(byte[] buf,
                                  int off,
                                  int size,
                                  boolean forceIncrement)

      Called externally from Connection with args (null, 0, 0, true) to send an empty data packet
      Parameters:
        `buf` - data to be sent - may be null
        `off` - offset into the buffer to start writing from
        `size` - how many bytes of the buffer to write (may be 0)
        `forceIncrement` - even if the buffer is empty, increment the packetId so we get an ACK back
      Returns:
        the packet sent

    - #### writeData

          public MessageOutputStream.WriteStatus writeData(byte[] buf,
                                                           int off,
                                                           int size)

      Send some data through the connection, or if there is no new data, this may generate a packet with a plain ACK/NACK or CLOSE, or nothing whatsoever if there's nothing new to send. This is called from MessageOutputStream, i.e. data from the client.
      Specified by:
        `writeData` in interface `MessageOutputStream.DataReceiver`
      Parameters:
        `buf` - data to be sent - may be null
        `off` - offset into the buffer to start writing from
        `size` - how many bytes of the buffer to write (may be 0)
      Returns:
        an object to allow optional blocking for data acceptance or delivery.

    - #### writeInProcess

          public boolean writeInProcess()

      This tells the flusher in MessageOutputStream whether to flush. It won't flush if this returns true. It was: return con.getUnackedPacketsSent() > 0 (i.e. Nagle) But then, for data that fills more than one packet, the last part of the data isn't sent until all the previous packets are acked. Which is very slow. The poor interaction of Nagle and Delayed Acknowledgements is well-documented. So let's send data along unless the outbound window is full. (i.e. no-Nagle or TCP_NODELAY) Probably should have a configuration option for this.
      Specified by:
        `writeInProcess` in interface `MessageOutputStream.DataReceiver`
      Returns:
        !flush