- All Implemented Interfaces:
MessageOutputStream.DataReceiver
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.
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static final classUsed if no new packet was sent.private static classFailed write status.Field Summary
FieldsModifier and TypeFieldDescriptionprivate final ConnectionStreaming connection.private final I2PAppContextApplication context.private static final MessageOutputStream.WriteStatusDummy status.private final LogClass logger.private static final ByteCachePayload cache.private static final ByteArrayReusable empty payload -- avoids per-packet ByteArray allocation for ACK-only packets.Constructor Summary
ConstructorsConstructorDescriptionConnectionDataReceiver(I2PAppContext ctx, Connection con) Create a data receiver for the given connection.Method Summary
Modifier and TypeMethodDescriptionprivate PacketLocalbuildPacket(byte[] buf, int off, int size, boolean forceIncrement) Compose a packet.(package private) voiddestroy()Release resources held by this receiver.private booleanisAckOnly(int size) Whether the packet carries no data and only serves to elicit an ACK.send(byte[] buf, int off, int size) Send some data through the connection, attaching any appropriate flags onto the packet.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.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.booleanThis tells the flusher in MessageOutputStream whether to flush.
Field Details
_context
Application context._log
Class logger._connection
Streaming connection._dummyStatus
Dummy status._payloadCache
Payload cache.EMPTY_PAYLOAD
Reusable empty payload -- avoids per-packet ByteArray allocation for ACK-only packets. Shared across all instances via _dataLock inMessageOutputStream.
Constructor Details
ConnectionDataReceiver
Create a data receiver for the given connection.- Parameters:
ctx- application context, used to look up this class's loggercon- non-null
Method Details
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:
writeInProcessin interfaceMessageOutputStream.DataReceiver- Returns:
- true while the outbound window is full, so nothing should be flushed yet
writeData
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:
writeDatain interfaceMessageOutputStream.DataReceiver- Parameters:
buf- data to be sent - may be nulloff- offset into the buffer to start writing fromsize- how many bytes of the buffer to write (may be 0)- Returns:
- an object to allow optional blocking for data acceptance or delivery.
send
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 nulloff- offset into the buffer to start writing fromsize- how many bytes of the buffer to write (may be 0)- Returns:
- the packet sent
send
Called externally from Connection with args (null, 0, 0, true) to send an empty data packet.- Parameters:
buf- data to be sent - may be nulloff- offset into the buffer to start writing fromsize- 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
isAckOnly
private boolean isAckOnly(int size) Whether the packet carries no data and only serves to elicit an ACK.- Parameters:
size- the payload size in bytes, 0 or less meaning no data- Returns:
- true if there is no data, this is not a SYN, and it is not the first CLOSE packet
buildPacket
Compose a packet. Most flags are set here; however, some are set inConnection.sendPacket(PacketLocal)andConnection.ResendPacketEvent.retransmit(). Take care not to set the same options both here and in Connection.- Parameters:
buf- data to be sent - may be nulloff- offset into the buffer to start writing fromsize- 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 to be sent
destroy
void destroy()Release resources held by this receiver.