* Streaming:
- When an "immediate" ack is requested, do it within 250 ms (was 2000) - Request immediate acks when < 1/3 of window remains, or when < 3 packets remain in window, and every 8 packets (was when < 2 packets in window remain) - Change requested delay to RTT/2 (was RTO/2) - Log cleanup and javadoc
This commit is contained in:
@ -189,9 +189,9 @@ public class Connection {
|
|||||||
+ _activeResends + "), waiting " + timeLeft);
|
+ _activeResends + "), waiting " + timeLeft);
|
||||||
try { _outboundPackets.wait(Math.min(timeLeft,250l)); } catch (InterruptedException ie) { if (_log.shouldLog(Log.DEBUG)) _log.debug("InterruptedException while Outbound window is full (" + _outboundPackets.size() + "/" + _activeResends +")"); return false;}
|
try { _outboundPackets.wait(Math.min(timeLeft,250l)); } catch (InterruptedException ie) { if (_log.shouldLog(Log.DEBUG)) _log.debug("InterruptedException while Outbound window is full (" + _outboundPackets.size() + "/" + _activeResends +")"); return false;}
|
||||||
} else {
|
} else {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
//if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Outbound window is full (" + _outboundPackets.size() + "/" + _activeResends
|
// _log.debug("Outbound window is full (" + _outboundPackets.size() + "/" + _activeResends
|
||||||
+ "), waiting indefinitely");
|
// + "), waiting indefinitely");
|
||||||
try { _outboundPackets.wait(250); } catch (InterruptedException ie) {if (_log.shouldLog(Log.DEBUG)) _log.debug("InterruptedException while Outbound window is full (" + _outboundPackets.size() + "/" + _activeResends + ")"); return false;} //10*1000
|
try { _outboundPackets.wait(250); } catch (InterruptedException ie) {if (_log.shouldLog(Log.DEBUG)) _log.debug("InterruptedException while Outbound window is full (" + _outboundPackets.size() + "/" + _activeResends + ")"); return false;} //10*1000
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -297,37 +297,48 @@ public class Connection {
|
|||||||
|
|
||||||
if ( (packet.getSequenceNum() == 0) && (!packet.isFlagSet(Packet.FLAG_SYNCHRONIZE)) ) {
|
if ( (packet.getSequenceNum() == 0) && (!packet.isFlagSet(Packet.FLAG_SYNCHRONIZE)) ) {
|
||||||
ackOnly = true;
|
ackOnly = true;
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
//if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("No resend for " + packet);
|
// _log.debug("No resend for " + packet);
|
||||||
} else {
|
} else {
|
||||||
int remaining = 0;
|
int windowSize;
|
||||||
|
int remaining;
|
||||||
synchronized (_outboundPackets) {
|
synchronized (_outboundPackets) {
|
||||||
_outboundPackets.put(new Long(packet.getSequenceNum()), packet);
|
_outboundPackets.put(new Long(packet.getSequenceNum()), packet);
|
||||||
remaining = _options.getWindowSize() - _outboundPackets.size() ;
|
windowSize = _options.getWindowSize();
|
||||||
|
remaining = windowSize - _outboundPackets.size() ;
|
||||||
_outboundPackets.notifyAll();
|
_outboundPackets.notifyAll();
|
||||||
}
|
}
|
||||||
if (remaining < 0)
|
// the other end has no idea what our window size is, so
|
||||||
remaining = 0;
|
// help him out by requesting acks below the 1/3 point,
|
||||||
if (packet.isFlagSet(Packet.FLAG_CLOSE) || (remaining < 2)) {
|
// if remaining < 3, and every 8 minimum.
|
||||||
|
if (packet.isFlagSet(Packet.FLAG_CLOSE) ||
|
||||||
|
(remaining < (windowSize + 2) / 3) ||
|
||||||
|
(remaining < 3) ||
|
||||||
|
(packet.getSequenceNum() % 8 == 0)) {
|
||||||
packet.setOptionalDelay(0);
|
packet.setOptionalDelay(0);
|
||||||
packet.setFlag(Packet.FLAG_DELAY_REQUESTED);
|
packet.setFlag(Packet.FLAG_DELAY_REQUESTED);
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Requesting no ack delay for packet " + packet);
|
_log.debug("Requesting no ack delay for packet " + packet);
|
||||||
} else {
|
} else {
|
||||||
int delay = _options.getRTO() / 2;
|
// This is somewhat of a waste of time, unless the RTT < 4000,
|
||||||
|
// since the other end limits it to getSendAckDelay()
|
||||||
|
// which is always 2000, but it's good for diagnostics to see what the other end thinks
|
||||||
|
// the RTT is.
|
||||||
|
int delay = _options.getRTT() / 2;
|
||||||
packet.setOptionalDelay(delay);
|
packet.setOptionalDelay(delay);
|
||||||
if (delay > 0)
|
if (delay > 0)
|
||||||
packet.setFlag(Packet.FLAG_DELAY_REQUESTED);
|
packet.setFlag(Packet.FLAG_DELAY_REQUESTED);
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Requesting ack delay of " + delay + "ms for packet " + packet);
|
_log.debug("Requesting ack delay of " + delay + "ms for packet " + packet);
|
||||||
}
|
}
|
||||||
|
// WHY always set?
|
||||||
packet.setFlag(Packet.FLAG_DELAY_REQUESTED);
|
packet.setFlag(Packet.FLAG_DELAY_REQUESTED);
|
||||||
|
|
||||||
long timeout = _options.getRTO();
|
long timeout = _options.getRTO();
|
||||||
if (timeout > MAX_RESEND_DELAY)
|
if (timeout > MAX_RESEND_DELAY)
|
||||||
timeout = MAX_RESEND_DELAY;
|
timeout = MAX_RESEND_DELAY;
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Resend in " + timeout + " for " + packet, new Exception("Sent by"));
|
_log.debug("Resend in " + timeout + " for " + packet);
|
||||||
|
|
||||||
// schedules itself
|
// schedules itself
|
||||||
ResendPacketEvent rpe = new ResendPacketEvent(packet, timeout);
|
ResendPacketEvent rpe = new ResendPacketEvent(packet, timeout);
|
||||||
@ -370,6 +381,10 @@ public class Connection {
|
|||||||
}
|
}
|
||||||
*********/
|
*********/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the acks and nacks received in a packet
|
||||||
|
* @return List of packets acked or null
|
||||||
|
*/
|
||||||
List ackPackets(long ackThrough, long nacks[]) {
|
List ackPackets(long ackThrough, long nacks[]) {
|
||||||
if (ackThrough < _highestAckedThrough) {
|
if (ackThrough < _highestAckedThrough) {
|
||||||
// dupack which won't tell us anything
|
// dupack which won't tell us anything
|
||||||
@ -685,6 +700,14 @@ public class Connection {
|
|||||||
* @return the next time the scheduler will want to send a packet, or -1 if never.
|
* @return the next time the scheduler will want to send a packet, or -1 if never.
|
||||||
*/
|
*/
|
||||||
public long getNextSendTime() { return _nextSendTime; }
|
public long getNextSendTime() { return _nextSendTime; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the next send time is currently >= 0 (i.e. not "never"),
|
||||||
|
* this may make the next time sooner but will not make it later.
|
||||||
|
* If the next send time is currently < 0 (i.e. "never"),
|
||||||
|
* this will set it to the time specified, but not later than
|
||||||
|
* options.getSendAckDelay() from now (2000 ms)
|
||||||
|
*/
|
||||||
public void setNextSendTime(long when) {
|
public void setNextSendTime(long when) {
|
||||||
if (_nextSendTime >= 0) {
|
if (_nextSendTime >= 0) {
|
||||||
if (when < _nextSendTime)
|
if (when < _nextSendTime)
|
||||||
@ -699,12 +722,12 @@ public class Connection {
|
|||||||
_nextSendTime = max;
|
_nextSendTime = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_log.shouldLog(Log.DEBUG) && false) {
|
//if (_log.shouldLog(Log.DEBUG) && false) {
|
||||||
if (_nextSendTime <= 0)
|
// if (_nextSendTime <= 0)
|
||||||
_log.debug("set next send time to an unknown time", new Exception(toString()));
|
// _log.debug("set next send time to an unknown time", new Exception(toString()));
|
||||||
else
|
// else
|
||||||
_log.debug("set next send time to " + (_nextSendTime-_context.clock().now()) + "ms from now", new Exception(toString()));
|
// _log.debug("set next send time to " + (_nextSendTime-_context.clock().now()) + "ms from now", new Exception(toString()));
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** how many packets have we sent and the other side has ACKed?
|
/** how many packets have we sent and the other side has ACKed?
|
||||||
@ -742,7 +765,9 @@ public class Connection {
|
|||||||
|
|
||||||
public long getCongestionWindowEnd() { return _congestionWindowEnd; }
|
public long getCongestionWindowEnd() { return _congestionWindowEnd; }
|
||||||
public void setCongestionWindowEnd(long endMsg) { _congestionWindowEnd = endMsg; }
|
public void setCongestionWindowEnd(long endMsg) { _congestionWindowEnd = endMsg; }
|
||||||
|
/** @return the highest outbound packet we have recieved an ack for */
|
||||||
public long getHighestAckedThrough() { return _highestAckedThrough; }
|
public long getHighestAckedThrough() { return _highestAckedThrough; }
|
||||||
|
/** @deprecated unused */
|
||||||
public void setHighestAckedThrough(long msgNum) { _highestAckedThrough = msgNum; }
|
public void setHighestAckedThrough(long msgNum) { _highestAckedThrough = msgNum; }
|
||||||
|
|
||||||
public long getLastActivityOn() {
|
public long getLastActivityOn() {
|
||||||
@ -835,8 +860,8 @@ public class Connection {
|
|||||||
}
|
}
|
||||||
long howLong = _options.getInactivityTimeout();
|
long howLong = _options.getInactivityTimeout();
|
||||||
howLong += _randomWait; // randomize it a bit, so both sides don't do it at once
|
howLong += _randomWait; // randomize it a bit, so both sides don't do it at once
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
//if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Resetting the inactivity timer to " + howLong, new Exception(toString()));
|
// _log.debug("Resetting the inactivity timer to " + howLong);
|
||||||
// this will get rescheduled, and rescheduled, and rescheduled...
|
// this will get rescheduled, and rescheduled, and rescheduled...
|
||||||
_activityTimer.reschedule(howLong, false); // use the later of current and previous timeout
|
_activityTimer.reschedule(howLong, false); // use the later of current and previous timeout
|
||||||
}
|
}
|
||||||
@ -1087,6 +1112,8 @@ public class Connection {
|
|||||||
// we want to resend this packet, but there are already active
|
// we want to resend this packet, but there are already active
|
||||||
// resends in the air and we dont want to make a bad situation
|
// resends in the air and we dont want to make a bad situation
|
||||||
// worse. wait another second
|
// worse. wait another second
|
||||||
|
// BUG? seq# = 0, activeResends = 0, loop forever - why?
|
||||||
|
// also seen with seq# > 0. Is the _activeResends count reliable?
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info("Delaying resend of " + _packet + " as there are "
|
_log.info("Delaying resend of " + _packet + " as there are "
|
||||||
+ _activeResends + " active resends already in play");
|
+ _activeResends + " active resends already in play");
|
||||||
@ -1104,6 +1131,7 @@ public class Connection {
|
|||||||
_packet.setOptionalDelay(choke);
|
_packet.setOptionalDelay(choke);
|
||||||
if (choke > 0)
|
if (choke > 0)
|
||||||
_packet.setFlag(Packet.FLAG_DELAY_REQUESTED);
|
_packet.setFlag(Packet.FLAG_DELAY_REQUESTED);
|
||||||
|
// this seems unnecessary to send the MSS again:
|
||||||
_packet.setOptionalMaxSize(getOptions().getMaxMessageSize());
|
_packet.setOptionalMaxSize(getOptions().getMaxMessageSize());
|
||||||
// bugfix release 0.7.8, we weren't dividing by 1000
|
// bugfix release 0.7.8, we weren't dividing by 1000
|
||||||
_packet.setResendDelay(getOptions().getResendDelay() / 1000);
|
_packet.setResendDelay(getOptions().getResendDelay() / 1000);
|
||||||
|
@ -166,6 +166,7 @@ class ConnectionDataReceiver implements MessageOutputStream.DataReceiver {
|
|||||||
packet.setReceiveStreamId(con.getReceiveStreamId());
|
packet.setReceiveStreamId(con.getReceiveStreamId());
|
||||||
|
|
||||||
con.getInputStream().updateAcks(packet);
|
con.getInputStream().updateAcks(packet);
|
||||||
|
// note that the optional delay is usually rewritten in Connection.sendPacket()
|
||||||
int choke = con.getOptions().getChoke();
|
int choke = con.getOptions().getChoke();
|
||||||
packet.setOptionalDelay(choke);
|
packet.setOptionalDelay(choke);
|
||||||
if (choke > 0)
|
if (choke > 0)
|
||||||
@ -197,12 +198,9 @@ class ConnectionDataReceiver implements MessageOutputStream.DataReceiver {
|
|||||||
( (size > 0) || (con.getUnackedPacketsSent() <= 0) || (packet.getSequenceNum() > 0) ) ) {
|
( (size > 0) || (con.getUnackedPacketsSent() <= 0) || (packet.getSequenceNum() > 0) ) ) {
|
||||||
packet.setFlag(Packet.FLAG_CLOSE);
|
packet.setFlag(Packet.FLAG_CLOSE);
|
||||||
con.setCloseSentOn(_context.clock().now());
|
con.setCloseSentOn(_context.clock().now());
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
|
||||||
_log.debug("Closed is set for a new packet on " + con + ": " + packet);
|
|
||||||
} else {
|
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
|
||||||
_log.debug("Closed is not set for a new packet on " + _connection + ": " + packet);
|
|
||||||
}
|
}
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("New outbound packet on " + _connection + ": " + packet);
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ public class ConnectionOptions extends I2PSocketOptionsImpl {
|
|||||||
public static final String PROP_INITIAL_RESEND_DELAY = "i2p.streaming.initialResendDelay";
|
public static final String PROP_INITIAL_RESEND_DELAY = "i2p.streaming.initialResendDelay";
|
||||||
public static final String PROP_INITIAL_ACK_DELAY = "i2p.streaming.initialAckDelay";
|
public static final String PROP_INITIAL_ACK_DELAY = "i2p.streaming.initialAckDelay";
|
||||||
public static final String PROP_INITIAL_WINDOW_SIZE = "i2p.streaming.initialWindowSize";
|
public static final String PROP_INITIAL_WINDOW_SIZE = "i2p.streaming.initialWindowSize";
|
||||||
|
/** unused */
|
||||||
public static final String PROP_INITIAL_RECEIVE_WINDOW = "i2p.streaming.initialReceiveWindow";
|
public static final String PROP_INITIAL_RECEIVE_WINDOW = "i2p.streaming.initialReceiveWindow";
|
||||||
public static final String PROP_INACTIVITY_TIMEOUT = "i2p.streaming.inactivityTimeout";
|
public static final String PROP_INACTIVITY_TIMEOUT = "i2p.streaming.inactivityTimeout";
|
||||||
public static final String PROP_INACTIVITY_ACTION = "i2p.streaming.inactivityAction";
|
public static final String PROP_INACTIVITY_ACTION = "i2p.streaming.inactivityAction";
|
||||||
@ -58,6 +59,7 @@ public class ConnectionOptions extends I2PSocketOptionsImpl {
|
|||||||
static final int INITIAL_WINDOW_SIZE = 6;
|
static final int INITIAL_WINDOW_SIZE = 6;
|
||||||
static final int DEFAULT_MAX_SENDS = 8;
|
static final int DEFAULT_MAX_SENDS = 8;
|
||||||
public static final int DEFAULT_INITIAL_RTT = 8*1000;
|
public static final int DEFAULT_INITIAL_RTT = 8*1000;
|
||||||
|
public static final int DEFAULT_INITIAL_ACK_DELAY = 2*1000;
|
||||||
static final int MIN_WINDOW_SIZE = 1;
|
static final int MIN_WINDOW_SIZE = 1;
|
||||||
private static final boolean DEFAULT_ANSWER_PINGS = true;
|
private static final boolean DEFAULT_ANSWER_PINGS = true;
|
||||||
|
|
||||||
@ -217,7 +219,7 @@ public class ConnectionOptions extends I2PSocketOptionsImpl {
|
|||||||
setRTT(getInt(opts, PROP_INITIAL_RTT, DEFAULT_INITIAL_RTT));
|
setRTT(getInt(opts, PROP_INITIAL_RTT, DEFAULT_INITIAL_RTT));
|
||||||
setReceiveWindow(getInt(opts, PROP_INITIAL_RECEIVE_WINDOW, 1));
|
setReceiveWindow(getInt(opts, PROP_INITIAL_RECEIVE_WINDOW, 1));
|
||||||
setResendDelay(getInt(opts, PROP_INITIAL_RESEND_DELAY, 1000));
|
setResendDelay(getInt(opts, PROP_INITIAL_RESEND_DELAY, 1000));
|
||||||
setSendAckDelay(getInt(opts, PROP_INITIAL_ACK_DELAY, 2000));
|
setSendAckDelay(getInt(opts, PROP_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY));
|
||||||
setWindowSize(getInt(opts, PROP_INITIAL_WINDOW_SIZE, INITIAL_WINDOW_SIZE));
|
setWindowSize(getInt(opts, PROP_INITIAL_WINDOW_SIZE, INITIAL_WINDOW_SIZE));
|
||||||
setMaxResends(getInt(opts, PROP_MAX_RESENDS, DEFAULT_MAX_SENDS));
|
setMaxResends(getInt(opts, PROP_MAX_RESENDS, DEFAULT_MAX_SENDS));
|
||||||
setWriteTimeout(getInt(opts, PROP_WRITE_TIMEOUT, -1));
|
setWriteTimeout(getInt(opts, PROP_WRITE_TIMEOUT, -1));
|
||||||
@ -249,7 +251,7 @@ public class ConnectionOptions extends I2PSocketOptionsImpl {
|
|||||||
if (opts.containsKey(PROP_INITIAL_RESEND_DELAY))
|
if (opts.containsKey(PROP_INITIAL_RESEND_DELAY))
|
||||||
setResendDelay(getInt(opts, PROP_INITIAL_RESEND_DELAY, 1000));
|
setResendDelay(getInt(opts, PROP_INITIAL_RESEND_DELAY, 1000));
|
||||||
if (opts.containsKey(PROP_INITIAL_ACK_DELAY))
|
if (opts.containsKey(PROP_INITIAL_ACK_DELAY))
|
||||||
setSendAckDelay(getInt(opts, PROP_INITIAL_ACK_DELAY, 2000));
|
setSendAckDelay(getInt(opts, PROP_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY));
|
||||||
if (opts.containsKey(PROP_INITIAL_WINDOW_SIZE))
|
if (opts.containsKey(PROP_INITIAL_WINDOW_SIZE))
|
||||||
setWindowSize(getInt(opts, PROP_INITIAL_WINDOW_SIZE, INITIAL_WINDOW_SIZE));
|
setWindowSize(getInt(opts, PROP_INITIAL_WINDOW_SIZE, INITIAL_WINDOW_SIZE));
|
||||||
if (opts.containsKey(PROP_MAX_RESENDS))
|
if (opts.containsKey(PROP_MAX_RESENDS))
|
||||||
@ -295,6 +297,7 @@ public class ConnectionOptions extends I2PSocketOptionsImpl {
|
|||||||
* @return if we want signatures on all packets.
|
* @return if we want signatures on all packets.
|
||||||
*/
|
*/
|
||||||
public boolean getRequireFullySigned() { return _fullySigned; }
|
public boolean getRequireFullySigned() { return _fullySigned; }
|
||||||
|
/** unused, see above */
|
||||||
public void setRequireFullySigned(boolean sign) { _fullySigned = sign; }
|
public void setRequireFullySigned(boolean sign) { _fullySigned = sign; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -325,7 +328,7 @@ public class ConnectionOptions extends I2PSocketOptionsImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** after how many consecutive messages should we ack?
|
/** after how many consecutive messages should we ack?
|
||||||
* This doesn't appear to be used.
|
* @deprecated This doesn't appear to be used.
|
||||||
* @return receive window size.
|
* @return receive window size.
|
||||||
*/
|
*/
|
||||||
public int getReceiveWindow() { return _receiveWindow; }
|
public int getReceiveWindow() { return _receiveWindow; }
|
||||||
@ -405,6 +408,10 @@ public class ConnectionOptions extends I2PSocketOptionsImpl {
|
|||||||
* @return ACK delay in ms
|
* @return ACK delay in ms
|
||||||
*/
|
*/
|
||||||
public int getSendAckDelay() { return _sendAckDelay; }
|
public int getSendAckDelay() { return _sendAckDelay; }
|
||||||
|
/**
|
||||||
|
* Unused except here, so expect the default initial delay of 2000 ms unless set by the user
|
||||||
|
* to remain constant.
|
||||||
|
*/
|
||||||
public void setSendAckDelay(int delayMs) { _sendAckDelay = delayMs; }
|
public void setSendAckDelay(int delayMs) { _sendAckDelay = delayMs; }
|
||||||
|
|
||||||
/** What is the largest message we want to send or receive?
|
/** What is the largest message we want to send or receive?
|
||||||
|
@ -131,11 +131,14 @@ public class ConnectionPacketHandler {
|
|||||||
isNew = false;
|
isNew = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (packet.getSequenceNum() == 0) && (packet.getPayloadSize() > 0) ) {
|
//if ( (packet.getSequenceNum() == 0) && (packet.getPayloadSize() > 0) ) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
// if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("seq=0 && size=" + packet.getPayloadSize() + ": isNew? " + isNew
|
// _log.debug("seq=0 && size=" + packet.getPayloadSize() + ": isNew? " + isNew
|
||||||
+ " packet: " + packet + " con: " + con);
|
// + " packet: " + packet + " con: " + con);
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug((isNew ? "New" : "Dup or ack-only") + " inbound packet on " + con + ": " + packet);
|
||||||
|
|
||||||
// close *after* receiving the data, as well as after verifying the signatures / etc
|
// close *after* receiving the data, as well as after verifying the signatures / etc
|
||||||
if (packet.isFlagSet(Packet.FLAG_CLOSE) && packet.isFlagSet(Packet.FLAG_SIGNATURE_INCLUDED))
|
if (packet.isFlagSet(Packet.FLAG_CLOSE) && packet.isFlagSet(Packet.FLAG_SIGNATURE_INCLUDED))
|
||||||
@ -151,7 +154,9 @@ public class ConnectionPacketHandler {
|
|||||||
if (packet.isFlagSet(Packet.FLAG_DELAY_REQUESTED) && (packet.getOptionalDelay() <= 0) ) {
|
if (packet.isFlagSet(Packet.FLAG_DELAY_REQUESTED) && (packet.getOptionalDelay() <= 0) ) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Scheduling immediate ack for " + packet);
|
_log.debug("Scheduling immediate ack for " + packet);
|
||||||
con.setNextSendTime(_context.clock().now() + con.getOptions().getSendAckDelay());
|
//con.setNextSendTime(_context.clock().now() + con.getOptions().getSendAckDelay());
|
||||||
|
// honor request "almost" immediately
|
||||||
|
con.setNextSendTime(_context.clock().now() + 250);
|
||||||
} else {
|
} else {
|
||||||
int delay = con.getOptions().getSendAckDelay();
|
int delay = con.getOptions().getSendAckDelay();
|
||||||
if (packet.isFlagSet(Packet.FLAG_DELAY_REQUESTED)) // delayed ACK requested
|
if (packet.isFlagSet(Packet.FLAG_DELAY_REQUESTED)) // delayed ACK requested
|
||||||
@ -222,6 +227,10 @@ public class ConnectionPacketHandler {
|
|||||||
// con.fastRetransmit();
|
// con.fastRetransmit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the acks in a received packet, and adjust our window and RTT
|
||||||
|
* @return are we congested?
|
||||||
|
*/
|
||||||
private boolean ack(Connection con, long ackThrough, long nacks[], Packet packet, boolean isNew, boolean choke) {
|
private boolean ack(Connection con, long ackThrough, long nacks[], Packet packet, boolean isNew, boolean choke) {
|
||||||
if (ackThrough < 0) return false;
|
if (ackThrough < 0) return false;
|
||||||
//if ( (nacks != null) && (nacks.length > 0) )
|
//if ( (nacks != null) && (nacks.length > 0) )
|
||||||
@ -287,7 +296,7 @@ public class ConnectionPacketHandler {
|
|||||||
return adjustWindow(con, isNew, packet.getSequenceNum(), numResends, (acked != null ? acked.size() : 0), choke);
|
return adjustWindow(con, isNew, packet.getSequenceNum(), numResends, (acked != null ? acked.size() : 0), choke);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return are we congested? */
|
||||||
private boolean adjustWindow(Connection con, boolean isNew, long sequenceNum, int numResends, int acked, boolean choke) {
|
private boolean adjustWindow(Connection con, boolean isNew, long sequenceNum, int numResends, int acked, boolean choke) {
|
||||||
boolean congested = false;
|
boolean congested = false;
|
||||||
if ( (!isNew) && (sequenceNum > 0) ) {
|
if ( (!isNew) && (sequenceNum > 0) ) {
|
||||||
|
@ -42,7 +42,7 @@ import net.i2p.util.Log;
|
|||||||
* <li>{@link #FLAG_MAX_PACKET_SIZE_INCLUDED}: 2 byte integer</li>
|
* <li>{@link #FLAG_MAX_PACKET_SIZE_INCLUDED}: 2 byte integer</li>
|
||||||
* <li>{@link #FLAG_PROFILE_INTERACTIVE}: no option data</li>
|
* <li>{@link #FLAG_PROFILE_INTERACTIVE}: no option data</li>
|
||||||
* <li>{@link #FLAG_ECHO}: no option data</li>
|
* <li>{@link #FLAG_ECHO}: no option data</li>
|
||||||
* <li>{@link #FLAG_NO_ACK}: no option data</li>
|
* <li>{@link #FLAG_NO_ACK}: no option data - this appears to be unused, we always ack, even for the first packet</li>
|
||||||
* </ol>
|
* </ol>
|
||||||
*
|
*
|
||||||
* <p>If the signature is included, it uses the Destination's DSA key
|
* <p>If the signature is included, it uses the Destination's DSA key
|
||||||
|
Reference in New Issue
Block a user