long xferUID = sendTo(next);
if(xferUID == -1) continue;
hasForwarded = true;
Message msg = null;
while(true) {
/**
* What are we waiting for?
* FNPAccepted - continue
* FNPRejectedLoop - go to another node
* FNPRejectedOverload - go to another node
*/
MessageFilter mfAccepted = MessageFilter.create().setSource(next).setField(DMT.UID, uid).setTimeout(ACCEPTED_TIMEOUT).setType(DMT.FNPAccepted);
MessageFilter mfRejectedLoop = MessageFilter.create().setSource(next).setField(DMT.UID, uid).setTimeout(ACCEPTED_TIMEOUT).setType(DMT.FNPRejectedLoop);
MessageFilter mfRejectedOverload = MessageFilter.create().setSource(next).setField(DMT.UID, uid).setTimeout(ACCEPTED_TIMEOUT).setType(DMT.FNPRejectedOverload);
MessageFilter mfOpennetDisabled = MessageFilter.create().setSource(next).setField(DMT.UID, uid).setTimeout(ACCEPTED_TIMEOUT).setType(DMT.FNPOpennetDisabled);
// mfRejectedOverload must be the last thing in the or
// So its or pointer remains null
// Otherwise we need to recreate it below
MessageFilter mf = mfAccepted.or(mfRejectedLoop.or(mfRejectedOverload.or(mfOpennetDisabled)));
try {
msg = node.usm.waitFor(mf, this);
if(logMINOR) Logger.minor(this, "first part got "+msg);
} catch (DisconnectedException e) {
Logger.normal(this, "Disconnected from "+next+" while waiting for Accepted on "+uid);
break;
}
if(msg == null) {
if(logMINOR) Logger.minor(this, "Timeout waiting for Accepted");
// Try next node
msg = null;
break;
}
if(msg.getSpec() == DMT.FNPRejectedLoop) {
if(logMINOR) Logger.minor(this, "Rejected loop");
// Find another node to route to
msg = null;
break;
}
if(msg.getSpec() == DMT.FNPRejectedOverload) {
if(logMINOR) Logger.minor(this, "Rejected: overload");
// Give up on this one, try another
msg = null;
break;
}
if(msg.getSpec() == DMT.FNPOpennetDisabled) {
if(logMINOR) Logger.minor(this, "Opennet disabled");
msg = null;
break;
}
if(msg.getSpec() != DMT.FNPAccepted) {
Logger.error(this, "Unrecognized message: "+msg);
continue;
}
break;
}
if((msg == null) || (msg.getSpec() != DMT.FNPAccepted)) {
// Try another node
continue;
}
if(logMINOR) Logger.minor(this, "Got Accepted");
if(cb != null)
cb.acceptedSomewhere();
// Send the rest
try {
sendRest(next, xferUID);
} catch (NotConnectedException e1) {
if(logMINOR)
Logger.minor(this, "Not connected while sending noderef on "+next);
continue;
}
// Otherwise, must be Accepted
// So wait...
while(true) {
MessageFilter mfAnnounceCompleted = MessageFilter.create().setSource(next).setField(DMT.UID, uid).setTimeout(ANNOUNCE_TIMEOUT).setType(DMT.FNPOpennetAnnounceCompleted);
MessageFilter mfRouteNotFound = MessageFilter.create().setSource(next).setField(DMT.UID, uid).setTimeout(ANNOUNCE_TIMEOUT).setType(DMT.FNPRouteNotFound);
MessageFilter mfRejectedOverload = MessageFilter.create().setSource(next).setField(DMT.UID, uid).setTimeout(ANNOUNCE_TIMEOUT).setType(DMT.FNPRejectedOverload);
MessageFilter mfAnnounceReply = MessageFilter.create().setSource(next).setField(DMT.UID, uid).setTimeout(ANNOUNCE_TIMEOUT).setType(DMT.FNPOpennetAnnounceReply);
MessageFilter mfOpennetDisabled = MessageFilter.create().setSource(next).setField(DMT.UID, uid).setTimeout(ANNOUNCE_TIMEOUT).setType(DMT.FNPOpennetDisabled);
MessageFilter mfNotWanted = MessageFilter.create().setSource(next).setField(DMT.UID, uid).setTimeout(ANNOUNCE_TIMEOUT).setType(DMT.FNPOpennetAnnounceNodeNotWanted);
MessageFilter mfOpennetNoderefRejected = MessageFilter.create().setSource(next).setField(DMT.UID, uid).setTimeout(ANNOUNCE_TIMEOUT).setType(DMT.FNPOpennetNoderefRejected);
MessageFilter mf = mfAnnounceCompleted.or(mfRouteNotFound.or(mfRejectedOverload.or(mfAnnounceReply.or(mfOpennetDisabled.or(mfNotWanted.or(mfOpennetNoderefRejected))))));
try {
msg = node.usm.waitFor(mf, this);
} catch (DisconnectedException e) {
Logger.normal(this, "Disconnected from "+next+" while waiting for announcement");
break;
}
if(logMINOR) Logger.minor(this, "second part got "+msg);
if(msg == null) {
// Fatal timeout, must be terminal (IS_LOCAL==true)
timedOut(next);
return;
}
if(msg.getSpec() == DMT.FNPOpennetNoderefRejected) {
int reason = msg.getInt(DMT.REJECT_CODE);
Logger.normal(this, "Announce rejected by "+next+" : "+DMT.getOpennetRejectedCode(reason));
msg = null;
break;
}
if(msg.getSpec() == DMT.FNPOpennetAnnounceCompleted) {
// Send the completion on immediately. We don't want to accumulate 30 seconds per hop!
complete();
mfAnnounceReply.setTimeout(END_TIMEOUT).setTimeoutRelativeToCreation(true);
mfNotWanted.setTimeout(END_TIMEOUT).setTimeoutRelativeToCreation(true);
mfAnnounceReply.clearOr();
mfNotWanted.clearOr();
mf = mfAnnounceReply.or(mfNotWanted);
while(true) {
try {
msg = node.usm.waitFor(mf, this);
} catch (DisconnectedException e) {
return;
}
if(msg == null) return;
if(msg.getSpec() == DMT.FNPOpennetAnnounceReply) {
validateForwardReply(msg, next);
continue;
}
if(msg.getSpec() == DMT.FNPOpennetAnnounceNodeNotWanted) {
if(cb != null)
cb.nodeNotWanted();
if(source != null) {
try {
sendNotWanted();
} catch (NotConnectedException e) {
Logger.warning(this, "Lost connection to source (announce completed)");
return;
}
}
continue;
}
}
}
if(msg.getSpec() == DMT.FNPRouteNotFound) {
// Backtrack within available hops
short newHtl = msg.getShort(DMT.HTL);
if(newHtl < 0) newHtl = 0;
if(newHtl < htl) htl = newHtl;
break;
}
if(msg.getSpec() == DMT.FNPRejectedOverload) {
// Give up on this one, try another
break;
}
if(msg.getSpec() == DMT.FNPOpennetDisabled) {
Logger.minor(this, "Opennet disabled");
msg = null;
break;
}
if(msg.getSpec() == DMT.FNPOpennetAnnounceReply) {
validateForwardReply(msg, next);
continue; // There may be more
}
if(msg.getSpec() == DMT.FNPOpennetAnnounceNodeNotWanted) {
if(cb != null)
cb.nodeNotWanted();
if(source != null) {
try {
sendNotWanted();