boolean mustSend = false;
long now = System.currentTimeMillis();
NewPacketFormatKeyContext keyContext = sessionKey.packetContext;
AddedAcks moved = keyContext.addAcks(packet, maxPacketSize, now, useCumulativeAcks);
if(moved != null && moved.anyUrgentAcks) {
if(logDEBUG) Logger.debug(this, "Must send because urgent acks");
mustSend = true;
}
int numAcks = packet.countAcks();
if(numAcks > MAX_ACKS) {
mustSend = true;
}
if(numAcks > 0) {
if(logDEBUG) Logger.debug(this, "Added acks for "+this+" for "+pn.shortToString());
}
byte[] haveAddedStatsBulk = null;
byte[] haveAddedStatsRT = null;
if(!ackOnly) {
boolean addedFragments = false;
while(true) {
boolean addStatsBulk = false;
boolean addStatsRT = false;
synchronized(sendBufferLock) {
// Always finish what we have started before considering sending more packets.
// Anything beyond this is beyond the scope of NPF and is PeerMessageQueue's job.
addOldLoop: for(int i = 0; i < startedByPrio.size(); i++) {
HashMap<Integer, MessageWrapper> started = startedByPrio.get(i);
//Try to finish messages that have been started
Iterator<MessageWrapper> it = started.values().iterator();
while(it.hasNext() && packet.getLength() < maxPacketSize) {
MessageWrapper wrapper = it.next();
while(packet.getLength() < maxPacketSize) {
MessageFragment frag = wrapper.getMessageFragment(maxPacketSize - packet.getLength());
if(frag == null) break;
mustSend = true;
addedFragments = true;
packet.addMessageFragment(frag);
sentPacket.addFragment(frag);
if(wrapper.allSent()) {
if((haveAddedStatsBulk == null) && wrapper.getItem().sendLoadBulk) {
addStatsBulk = true;
// Add the lossy message outside the lock.
break addOldLoop;
}
if((haveAddedStatsRT == null) && wrapper.getItem().sendLoadRT) {
addStatsRT = true;
// Add the lossy message outside the lock.
break addOldLoop;
}
}
}
}
}
}
if(!(addStatsBulk || addStatsRT)) break;
if(addStatsBulk) {
MessageItem item = pn.makeLoadStats(false, false, true);
if(item != null) {
byte[] buf = item.getData();
haveAddedStatsBulk = buf;
// FIXME if this fails, drop some messages.
packet.addLossyMessage(buf, maxPacketSize);
}
}
if(addStatsRT) {
MessageItem item = pn.makeLoadStats(true, false, true);
if(item != null) {
byte[] buf = item.getData();
haveAddedStatsRT = buf;
// FIXME if this fails, drop some messages.
packet.addLossyMessage(buf, maxPacketSize);
}
}
}
if(addedFragments) {
if(logDEBUG) Logger.debug(this, "Added fragments for "+this+" (must send)");
}
}
if((!mustSend) && packet.getLength() >= (maxPacketSize * 4 / 5)) {
if(logDEBUG) Logger.debug(this, "Must send because packet is big on acks alone");
// Lots of acks to send, send a packet.
mustSend = true;
}
if((!ackOnly) && (!mustSend)) {
if(messageQueue.mustSendNow(now) || messageQueue.mustSendSize(packet.getLength(), maxPacketSize)) {
if(logDEBUG) Logger.debug(this, "Must send because of message queue");
mustSend = true;
}
}
if((!mustSend) && numAcks > 0) {
int maxSendBufferSize = maxSendBufferSize();
synchronized(sendBufferLock) {
if(sendBufferUsed > maxSendBufferSize / 2) {
if(logDEBUG) Logger.debug(this, "Must send because other side buffer size is "+sendBufferUsed);
mustSend = true;
}
}
}
boolean checkedCanSend = false;
boolean cantSend = false;
boolean mustSendKeepalive = false;
if(DO_KEEPALIVES) {
synchronized(this) {
if(!mustSend) {
if(now - timeLastSentPacket > Node.KEEPALIVE_INTERVAL)
mustSend = true;
}
if((!ackOnly) && now - timeLastSentPayload > Node.KEEPALIVE_INTERVAL &&
packet.getFragments().isEmpty())
mustSendKeepalive = true;
}
}
if(mustSendKeepalive) {
if(!checkedCanSend)
cantSend = !canSend(sessionKey);
checkedCanSend = true;
if(!cantSend) {
mustSend = true;
}
}
if(!mustSend) {
if(moved != null) {
moved.abort();
}
return null;
}
boolean sendStatsBulk = false, sendStatsRT = false;