forked from I2P_Developers/i2p.i2p
* deal with writes > the packet size limit
* deal with window size > 1, especially before receiving the first ACK * disable congestion control for the moment (aka unlimited window size)
This commit is contained in:
@@ -93,7 +93,7 @@ public class Connection {
|
||||
* @return true if the packet should be sent
|
||||
*/
|
||||
boolean packetSendChoke() {
|
||||
//if (true) return true;
|
||||
if (true) return true;
|
||||
long writeExpire = _options.getWriteTimeout();
|
||||
if (writeExpire > 0)
|
||||
writeExpire += _context.clock().now();
|
||||
@@ -151,30 +151,6 @@ public class Connection {
|
||||
_outboundQueue.enqueue(packet);
|
||||
}
|
||||
|
||||
/*
|
||||
void flushPackets() {
|
||||
List toSend = null;
|
||||
synchronized (_outboundPackets) {
|
||||
for (Iterator iter = _outboundPackets.values().iterator(); iter.hasNext(); ) {
|
||||
PacketLocal packet = (PacketLocal)iter.next();
|
||||
long nextExpected = _options.getResendDelay() << packet.getNumSends();
|
||||
if (packet.getLastSend() + nextExpected <= _context.clock().now()) {
|
||||
// we need to resend
|
||||
if (toSend == null) toSend = new ArrayList(1);
|
||||
toSend.add(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (toSend != null) {
|
||||
for (int i = 0; i < toSend.size(); i++) {
|
||||
PacketLocal packet = (PacketLocal)toSend.get(i);
|
||||
_lastSendTime = _context.clock().now();
|
||||
_outboundQueue.enqueue(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
List ackPackets(long ackThrough, long nacks[]) {
|
||||
List acked = null;
|
||||
synchronized (_outboundPackets) {
|
||||
@@ -362,6 +338,15 @@ public class Connection {
|
||||
resend = true;
|
||||
}
|
||||
if ( (resend) && (_packet.getAckTime() < 0) ) {
|
||||
// revamp various fields, in case we need to ack more, etc
|
||||
_packet.setAckThrough(getInputStream().getHighestBlockId());
|
||||
_packet.setNacks(getInputStream().getNacks());
|
||||
_packet.setOptionalDelay(getOptions().getChoke());
|
||||
_packet.setOptionalMaxSize(getOptions().getMaxMessageSize());
|
||||
_packet.setResendDelay(getOptions().getResendDelay());
|
||||
_packet.setReceiveStreamId(_receiveStreamId);
|
||||
_packet.setSendStreamId(_sendStreamId);
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Resend packet " + _packet + " on " + Connection.this);
|
||||
_outboundQueue.enqueue(_packet);
|
||||
|
||||
@@ -35,16 +35,19 @@ public class ConnectionPacketHandler {
|
||||
if (nextTime <= 0) {
|
||||
con.setNextSendTime(con.getOptions().getSendAckDelay() + _context.clock().now());
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Scheduling ack in " + con.getOptions().getSendAckDelay() + "ms for received packet " + packet);
|
||||
_log.error("Scheduling ack in " + con.getOptions().getSendAckDelay() + "ms for received packet " + packet);
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Ack is already scheduled in " + nextTime + "ms, though we just received " + packet);
|
||||
_log.debug("Ack is already scheduled in " + (nextTime-_context.clock().now())
|
||||
+ "ms, though we just received " + packet);
|
||||
}
|
||||
} else {
|
||||
if (packet.getSequenceNum() > 0) {
|
||||
// take note of congestion
|
||||
con.getOptions().setResendDelay(con.getOptions().getResendDelay()*2);
|
||||
//con.getOptions().setWindowSize(con.getOptions().getWindowSize()/2);
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("congestion.. dup " + packet);
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("ACK only packet received: " + packet);
|
||||
|
||||
@@ -95,7 +95,7 @@ public class MessageInputStream extends InputStream {
|
||||
if (_notYetReadyBlocks.containsKey(l)) {
|
||||
// ACK
|
||||
} else {
|
||||
if (ids != null)
|
||||
if (ids == null)
|
||||
ids = new ArrayList(4);
|
||||
ids.add(l);
|
||||
}
|
||||
@@ -210,8 +210,8 @@ public class MessageInputStream extends InputStream {
|
||||
expiration = _readTimeout + System.currentTimeMillis();
|
||||
synchronized (_dataLock) {
|
||||
while (_readyDataBlocks.size() <= 0) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("read() with readyBlocks.size = " + _readyDataBlocks.size() + " on " + toString());
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("read() with readyBlocks.size = " + _readyDataBlocks.size() + " on " + toString());
|
||||
|
||||
if ( (_notYetReadyBlocks.size() <= 0) && (_closeReceived) ) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
@@ -244,8 +244,8 @@ public class MessageInputStream extends InputStream {
|
||||
}
|
||||
}
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("read() readyBlocks = " + _readyDataBlocks.size() + ": " + toString());
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("read() readyBlocks = " + _readyDataBlocks.size() + ": " + toString());
|
||||
|
||||
// either was already ready, or we wait()ed and it arrived
|
||||
ByteArray cur = (ByteArray)_readyDataBlocks.get(0);
|
||||
|
||||
@@ -20,7 +20,7 @@ public class MessageOutputStream extends OutputStream {
|
||||
private boolean _closed;
|
||||
|
||||
public MessageOutputStream(I2PAppContext ctx, DataReceiver receiver) {
|
||||
this(ctx, receiver, 64*1024);
|
||||
this(ctx, receiver, Packet.MAX_PAYLOAD_SIZE);
|
||||
}
|
||||
public MessageOutputStream(I2PAppContext ctx, DataReceiver receiver, int bufSize) {
|
||||
super();
|
||||
@@ -37,31 +37,38 @@ public class MessageOutputStream extends OutputStream {
|
||||
}
|
||||
|
||||
public void write(byte b[], int off, int len) throws IOException {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("write(b[], " + off + ", " + len + ")");
|
||||
synchronized (_dataLock) {
|
||||
int cur = off;
|
||||
int remaining = len;
|
||||
while (remaining > 0) {
|
||||
if (_valid + remaining < _buf.length) {
|
||||
// simply buffer the data, no flush
|
||||
System.arraycopy(b, off, _buf, _valid, remaining);
|
||||
System.arraycopy(b, cur, _buf, _valid, remaining);
|
||||
_valid += remaining;
|
||||
cur += remaining;
|
||||
remaining = 0;
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("write(...): appending valid = " + _valid + " remaining=" + remaining);
|
||||
} else {
|
||||
// buffer whatever we can fit then flush,
|
||||
// repeating until we've pushed all of the
|
||||
// data through
|
||||
int toWrite = _buf.length - _valid;
|
||||
System.arraycopy(b, off, _buf, _valid, toWrite);
|
||||
System.arraycopy(b, cur, _buf, _valid, toWrite);
|
||||
remaining -= toWrite;
|
||||
cur += toWrite;
|
||||
_valid = _buf.length;
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("write(b[], " + off + ", " + len + "): valid = " + _valid);
|
||||
_log.debug("write(...): flushing valid = " + _valid + " remaining=" + remaining);
|
||||
// this blocks until the packet is ack window is open. it
|
||||
// also throws InterruptedIOException if the write timeout
|
||||
// expires
|
||||
_dataReceiver.writeData(_buf, 0, _valid);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("write(b[], " + off + ", " + len + "): valid = " + _valid + " complete");
|
||||
_valid = 0;
|
||||
_log.debug("write(...): flushing complete valid = " + _valid + " remaining=" + remaining);
|
||||
_valid = 0;
|
||||
throwAnyError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ public class Packet {
|
||||
* ping reply (if receiveStreamId is set).
|
||||
*/
|
||||
public static final int FLAG_ECHO = (1 << 9);
|
||||
|
||||
|
||||
public static final int DEFAULT_MAX_SIZE = 32*1024;
|
||||
|
||||
/** what stream is this packet a part of? */
|
||||
@@ -195,9 +195,15 @@ public class Packet {
|
||||
public int getResendDelay() { return _resendDelay; }
|
||||
public void setResendDelay(int numSeconds) { _resendDelay = numSeconds; }
|
||||
|
||||
public static final int MAX_PAYLOAD_SIZE = 32*1024;
|
||||
|
||||
/** get the actual payload of the message. may be null */
|
||||
public byte[] getPayload() { return _payload; }
|
||||
public void setPayload(byte payload[]) { _payload = payload; }
|
||||
public void setPayload(byte payload[]) {
|
||||
_payload = payload;
|
||||
if ( (payload != null) && (payload.length > MAX_PAYLOAD_SIZE) )
|
||||
throw new IllegalArgumentException("Too large payload: " + payload.length);
|
||||
}
|
||||
|
||||
/** is a particular flag set on this packet? */
|
||||
public boolean isFlagSet(int flag) { return 0 != (_flags & flag); }
|
||||
@@ -323,7 +329,12 @@ public class Packet {
|
||||
}
|
||||
|
||||
if (_payload != null) {
|
||||
System.arraycopy(_payload, 0, buffer, cur, _payload.length);
|
||||
try {
|
||||
System.arraycopy(_payload, 0, buffer, cur, _payload.length);
|
||||
} catch (ArrayIndexOutOfBoundsException aioobe) {
|
||||
System.err.println("payload.length: " + _payload.length + " buffer.length: " + buffer.length + " cur: " + cur);
|
||||
throw aioobe;
|
||||
}
|
||||
cur += _payload.length;
|
||||
}
|
||||
|
||||
@@ -411,6 +422,8 @@ public class Packet {
|
||||
|
||||
// skip ahead to the payload
|
||||
_payload = new byte[offset + length - payloadBegin];
|
||||
if (_payload.length > MAX_PAYLOAD_SIZE)
|
||||
throw new IllegalArgumentException("length: " + length + " offset: " + offset + " begin: " + payloadBegin);
|
||||
System.arraycopy(buffer, payloadBegin, _payload, 0, _payload.length);
|
||||
|
||||
// ok now lets go back and deal with the options
|
||||
|
||||
@@ -93,15 +93,28 @@ public class PacketHandler {
|
||||
_log.warn("Syn packet reply on a stream we don't know about: " + packet);
|
||||
}
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Packet received on an unknown stream (and not a SYN): " + packet);
|
||||
if (packet.getSendStreamId() == null) {
|
||||
for (Iterator iter = _manager.listConnections().iterator(); iter.hasNext(); ) {
|
||||
Connection con = (Connection)iter.next();
|
||||
if (DataHelper.eq(con.getSendStreamId(), packet.getReceiveStreamId()) &&
|
||||
con.getAckedPackets() <= 0) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received additional packets before the syn on " + con + ": " + packet);
|
||||
receiveKnownCon(con, packet);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_log.shouldLog(Log.WARN)) {
|
||||
_log.warn("Packet received on an unknown stream (and not a SYN): " + packet);
|
||||
StringBuffer buf = new StringBuffer(128);
|
||||
Set cons = _manager.listConnections();
|
||||
for (Iterator iter = cons.iterator(); iter.hasNext(); ) {
|
||||
Connection con = (Connection)iter.next();
|
||||
buf.append(Base64.encode(con.getReceiveStreamId())).append(" ");
|
||||
}
|
||||
_log.warn("Other streams: " + buf.toString());
|
||||
_log.warn("Packet belongs to know other cons: " + packet + " connections: " + buf.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user