use of net.i2p.data.ByteArray in project i2p.i2p by i2p.
the class MessageInputStream method closeReceived.
/**
* There is no more data coming from the I2P side.
* Does NOT clear pending data.
* messageReceived() MUST have been called previously with the messageId of the CLOSE packet.
*/
public void closeReceived() {
synchronized (_dataLock) {
if (_log.shouldLog(Log.DEBUG)) {
StringBuilder buf = new StringBuilder(128);
buf.append("Close received, ready bytes: ");
long available = 0;
for (int i = 0; i < _readyDataBlocks.size(); i++) available += _readyDataBlocks.get(i).getValid();
available -= _readyDataBlockIndex;
buf.append(available);
buf.append(" blocks: ").append(_readyDataBlocks.size());
buf.append(" not ready blocks: ");
long notAvailable = 0;
for (Long id : _notYetReadyBlocks.keySet()) {
ByteArray ba = _notYetReadyBlocks.get(id);
buf.append(id).append(" ");
if (ba != null)
notAvailable += ba.getValid();
}
buf.append("not ready bytes: ").append(notAvailable);
buf.append(" highest ready block: ").append(_highestReadyBlockId);
_log.debug(buf.toString(), new Exception("Input stream closed"));
}
_closeReceived = true;
_dataLock.notifyAll();
}
}
use of net.i2p.data.ByteArray in project i2p.i2p by i2p.
the class MessageInputStream method getTotalReadySize.
/**
* How many bytes are queued up for reading (or sitting in the out-of-order
* buffer)?
*
* @return Count of bytes waiting to be read
*/
/**
* public int getTotalQueuedSize() {
* synchronized (_dataLock) {
* if (_locallyClosed) return 0;
* int numBytes = 0;
* for (int i = 0; i < _readyDataBlocks.size(); i++) {
* ByteArray cur = _readyDataBlocks.get(i);
* if (i == 0)
* numBytes += cur.getValid() - _readyDataBlockIndex;
* else
* numBytes += cur.getValid();
* }
* for (ByteArray cur : _notYetReadyBlocks.values()) {
* numBytes += cur.getValid();
* }
* return numBytes;
* }
* }
**
*/
/**
* Same as available() but doesn't throw IOE
*/
public int getTotalReadySize() {
synchronized (_dataLock) {
if (_locallyClosed)
return 0;
int numBytes = 0;
for (int i = 0; i < _readyDataBlocks.size(); i++) {
ByteArray cur = _readyDataBlocks.get(i);
numBytes += cur.getValid();
if (i == 0)
numBytes -= _readyDataBlockIndex;
}
return numBytes;
}
}
use of net.i2p.data.ByteArray in project i2p.i2p by i2p.
the class MessageInputStream method close.
@Override
public void close() {
synchronized (_dataLock) {
if (_log.shouldLog(Log.DEBUG)) {
StringBuilder buf = new StringBuilder(128);
buf.append("close(), ready bytes: ");
long available = 0;
for (int i = 0; i < _readyDataBlocks.size(); i++) available += _readyDataBlocks.get(i).getValid();
available -= _readyDataBlockIndex;
buf.append(available);
buf.append(" blocks: ").append(_readyDataBlocks.size());
buf.append(" not ready blocks: ");
long notAvailable = 0;
for (Long id : _notYetReadyBlocks.keySet()) {
ByteArray ba = _notYetReadyBlocks.get(id);
buf.append(id).append(" ");
if (ba != null)
notAvailable += ba.getValid();
}
buf.append("not ready bytes: ").append(notAvailable);
buf.append(" highest ready block: ").append(_highestReadyBlockId);
_log.debug(buf.toString());
}
// while (_readyDataBlocks.size() > 0)
// _cache.release((ByteArray)_readyDataBlocks.remove(0));
_readyDataBlocks.clear();
// received, so we can ACK accordingly
for (ByteArray ba : _notYetReadyBlocks.values()) {
ba.setData(null);
// _cache.release(ba);
}
_locallyClosed = true;
_dataLock.notifyAll();
}
}
use of net.i2p.data.ByteArray in project i2p.i2p by i2p.
the class PacketQueue method enqueue.
/**
* Add a new packet to be sent out ASAP.
* This updates the acks.
*
* keys and tags disabled since dropped in I2PSession
* @return true if sent
*/
public boolean enqueue(PacketLocal packet) {
if (_dead)
return false;
if (packet.getAckTime() > 0) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Not resending " + packet);
return false;
}
Connection con = packet.getConnection();
if (con != null) {
// this updates the ack/nack fields
con.getInputStream().updateAcks(packet);
}
ByteArray ba = _cache.acquire();
byte[] buf = ba.getData();
long begin = 0;
long end = 0;
boolean sent = false;
try {
int size = 0;
// long beforeWrite = System.currentTimeMillis();
if (packet.shouldSign())
size = packet.writeSignedPacket(buf, 0);
else
size = packet.writePacket(buf, 0);
// last chance to short circuit...
if (packet.getAckTime() > 0)
return false;
// this should not block!
begin = _context.clock().now();
long expires = 0;
Connection.ResendPacketEvent rpe = (Connection.ResendPacketEvent) packet.getResendEvent();
if (rpe != null)
// we want the router to expire it a little before we do,
// so if we retransmit it will use a new tunnel/lease combo
expires = rpe.getNextSendTime() - 500;
SendMessageOptions options = new SendMessageOptions();
if (expires > 0)
options.setDate(expires);
boolean listenForStatus = false;
// FINAL trumps INITIAL, in the case of SYN+CLOSE
if (packet.isFlagSet(FLAGS_FINAL_TAGS)) {
if (packet.isFlagSet(Packet.FLAG_ECHO)) {
// Send LS for PING, not for PONG
if (// pong
packet.getSendStreamId() <= 0)
options.setSendLeaseSet(false);
} else {
options.setSendLeaseSet(false);
}
int sendTags = FINAL_TAGS_TO_SEND;
int tagThresh = FINAL_TAG_THRESHOLD;
if (con != null) {
ConnectionOptions copts = con.getOptions();
int cSendTags = copts.getTagsToSend();
int cTagThresh = copts.getTagThreshold();
if (cSendTags < sendTags)
sendTags = cSendTags;
if (cTagThresh < tagThresh)
tagThresh = cTagThresh;
}
options.setTagsToSend(sendTags);
options.setTagThreshold(tagThresh);
} else if (packet.isFlagSet(FLAGS_INITIAL_TAGS)) {
if (con != null) {
if (con.isInbound())
options.setSendLeaseSet(false);
else if (ENABLE_STATUS_LISTEN)
listenForStatus = true;
}
int sendTags = INITIAL_TAGS_TO_SEND;
int tagThresh = MIN_TAG_THRESHOLD;
if (con != null) {
ConnectionOptions copts = con.getOptions();
int cSendTags = copts.getTagsToSend();
int cTagThresh = copts.getTagThreshold();
if (cSendTags < sendTags)
sendTags = cSendTags;
if (cTagThresh < tagThresh)
tagThresh = cTagThresh;
}
options.setTagsToSend(sendTags);
options.setTagThreshold(tagThresh);
} else {
if (con != null) {
if (con.isInbound() && con.getLifetime() < 2 * 60 * 1000)
options.setSendLeaseSet(false);
// increase threshold with higher window sizes to prevent stalls
// after tag delivery failure
ConnectionOptions copts = con.getOptions();
int wdw = copts.getWindowSize();
int thresh = Math.max(MIN_TAG_THRESHOLD, wdw * TAG_WINDOW_FACTOR);
int cTagThresh = copts.getTagThreshold();
if (cTagThresh < thresh)
thresh = cTagThresh;
options.setTagThreshold(thresh);
}
}
I2PSession session = packet.getSession();
if (listenForStatus) {
long id = session.sendMessage(packet.getTo(), buf, 0, size, I2PSession.PROTO_STREAMING, packet.getLocalPort(), packet.getRemotePort(), options, this);
_messageStatusMap.put(Long.valueOf(id), con);
sent = true;
} else {
sent = session.sendMessage(packet.getTo(), buf, 0, size, I2PSession.PROTO_STREAMING, packet.getLocalPort(), packet.getRemotePort(), options);
}
end = _context.clock().now();
if ((end - begin > 1000) && (_log.shouldLog(Log.WARN)))
_log.warn("Took " + (end - begin) + "ms to sendMessage(...) " + packet);
_context.statManager().addRateData("stream.con.sendMessageSize", size, packet.getLifetime());
if (packet.getNumSends() > 1)
_context.statManager().addRateData("stream.con.sendDuplicateSize", size, packet.getLifetime());
if (con != null) {
con.incrementBytesSent(size);
if (packet.getNumSends() > 1)
con.incrementDupMessagesSent(1);
}
} catch (I2PSessionException ise) {
if (_log.shouldLog(Log.WARN))
_log.warn("Unable to send the packet " + packet, ise);
}
_cache.release(ba);
if (!sent) {
if (_log.shouldLog(Log.WARN))
_log.warn("Send failed for " + packet);
if (// handle race on b0rk
con != null)
con.disconnect(false);
} else {
// packet.setKeyUsed(keyUsed);
// packet.setTagsSent(tagsSent);
packet.incrementSends();
if (con != null && _log.shouldDebug()) {
String suffix = "wsize " + con.getOptions().getWindowSize() + " rto " + con.getOptions().getRTO();
con.getConnectionManager().getPacketHandler().displayPacket(packet, "SEND", suffix);
}
if (I2PSocketManagerFull.pcapWriter != null && _context.getBooleanProperty(I2PSocketManagerFull.PROP_PCAP))
packet.logTCPDump();
}
if ((packet.getSequenceNum() == 0) && (!packet.isFlagSet(Packet.FLAG_SYNCHRONIZE))) {
// ack only, so release it asap
packet.releasePayload();
} else if (packet.isFlagSet(Packet.FLAG_ECHO) && !packet.isFlagSet(Packet.FLAG_SIGNATURE_INCLUDED)) {
// pong
packet.releasePayload();
} else if (packet.isFlagSet(Packet.FLAG_RESET)) {
// reset
packet.releasePayload();
}
return sent;
}
use of net.i2p.data.ByteArray in project i2p.i2p by i2p.
the class MessageInputStreamTest method testGetHighestReadyBlockId.
@Test
public void testGetHighestReadyBlockId() {
assertThat(in.getHighestReadyBlockId(), is((long) -1));
in.messageReceived(0, new ByteArray());
assertThat(in.getHighestReadyBlockId(), is((long) 0));
in.messageReceived(2, new ByteArray());
assertThat(in.getHighestReadyBlockId(), is((long) 0));
in.messageReceived(1, new ByteArray());
assertThat(in.getHighestReadyBlockId(), is((long) 2));
}
Aggregations