use of net.i2p.data.i2np.DatabaseSearchReplyMessage in project i2p.i2p by i2p.
the class FloodOnlyLookupMatchJob method setMessage.
public void setMessage(I2NPMessage message) {
if (message instanceof DatabaseSearchReplyMessage) {
// DSRM processing now in FloodOnlyLookupSelector instead of here,
// a dsrm is only passed in when there are no more lookups remaining
// so that all DSRM's are processed, not just the last one.
_search.failed();
return;
}
try {
DatabaseStoreMessage dsm = (DatabaseStoreMessage) message;
if (_log.shouldLog(Log.INFO))
_log.info(_search.getJobId() + ": got a DSM for " + dsm.getKey().toBase64());
// Should we just pass the DataStructure directly back to somebody?
if (dsm.getEntry().getType() == DatabaseEntry.KEY_TYPE_LEASESET) {
// Since HFDSMJ wants to setReceivedAsPublished(), we have to
// set a flag saying this was really the result of a query,
// so don't do that.
LeaseSet ls = (LeaseSet) dsm.getEntry();
ls.setReceivedAsReply();
getContext().netDb().store(dsm.getKey(), ls);
} else {
getContext().netDb().store(dsm.getKey(), (RouterInfo) dsm.getEntry());
}
} catch (UnsupportedCryptoException uce) {
_search.failed();
return;
} catch (IllegalArgumentException iae) {
if (_log.shouldLog(Log.WARN))
_log.warn(_search.getJobId() + ": Received an invalid store reply", iae);
}
}
use of net.i2p.data.i2np.DatabaseSearchReplyMessage in project i2p.i2p by i2p.
the class SearchUpdateReplyFoundJob method runJob.
public void runJob() {
if (_isFloodfillPeer)
_job.decrementOutstandingFloodfillSearches();
I2NPMessage message = _message;
if (_log.shouldLog(Log.INFO))
_log.info(getJobId() + ": Reply from " + _peer.toBase64() + " with message " + message.getClass().getSimpleName());
long howLong = System.currentTimeMillis() - _sentOn;
// assume requests are 1KB (they're almost always much smaller, but tunnels have a fixed size)
int msgSize = 1024;
if (_replyTunnel != null) {
for (int i = 0; i < _replyTunnel.getLength(); i++) getContext().profileManager().tunnelDataPushed(_replyTunnel.getPeer(i), howLong, msgSize);
_replyTunnel.incrementVerifiedBytesTransferred(msgSize);
}
if (_outTunnel != null) {
for (int i = 0; i < _outTunnel.getLength(); i++) getContext().profileManager().tunnelDataPushed(_outTunnel.getPeer(i), howLong, msgSize);
_outTunnel.incrementVerifiedBytesTransferred(msgSize);
}
if (message instanceof DatabaseStoreMessage) {
long timeToReply = _state.dataFound(_peer);
DatabaseStoreMessage msg = (DatabaseStoreMessage) message;
DatabaseEntry entry = msg.getEntry();
try {
_facade.store(msg.getKey(), entry);
getContext().profileManager().dbLookupSuccessful(_peer, timeToReply);
} catch (UnsupportedCryptoException iae) {
// don't blame the peer
getContext().profileManager().dbLookupSuccessful(_peer, timeToReply);
_state.abort();
// searchNext() will call fail()
} catch (IllegalArgumentException iae) {
if (_log.shouldLog(Log.WARN))
_log.warn("Peer " + _peer + " sent us invalid data: ", iae);
// blame the peer
getContext().profileManager().dbLookupReply(_peer, 0, 0, 1, 0, timeToReply);
}
} else if (message instanceof DatabaseSearchReplyMessage) {
_job.replyFound((DatabaseSearchReplyMessage) message, _peer);
} else {
if (_log.shouldLog(Log.ERROR))
_log.error(getJobId() + ": What?! Reply job matched a strange message: " + message);
return;
}
_job.searchNext();
}
use of net.i2p.data.i2np.DatabaseSearchReplyMessage in project i2p.i2p by i2p.
the class InboundMessageDistributor method handleClove.
/**
* Handle a clove removed from the garlic message
*/
public void handleClove(DeliveryInstructions instructions, I2NPMessage data) {
int type = data.getType();
switch(instructions.getDeliveryMode()) {
case DeliveryInstructions.DELIVERY_MODE_LOCAL:
if (_log.shouldLog(Log.DEBUG))
_log.debug("local delivery instructions for clove: " + data.getClass().getSimpleName());
if (type == GarlicMessage.MESSAGE_TYPE) {
_receiver.receive((GarlicMessage) data);
} else if (type == DatabaseStoreMessage.MESSAGE_TYPE) {
// Treat db store explicitly here (not in HandleFloodfillDatabaseStoreMessageJob),
// since we don't want to republish (or flood)
// unnecessarily. Reply tokens ignored.
DatabaseStoreMessage dsm = (DatabaseStoreMessage) data;
// Ensure the reply info is cleared, just in case
dsm.setReplyToken(0);
dsm.setReplyTunnel(null);
dsm.setReplyGateway(null);
if (dsm.getEntry().getType() == DatabaseEntry.KEY_TYPE_LEASESET) {
// Case 1:
// store of our own LS.
// This is almost certainly a response to a FloodfillVerifyStoreJob search.
// We must send to the InNetMessagePool so the message can be matched
// and the verify marked as successful.
// Case 2:
// Store of somebody else's LS.
// This could be an encrypted response to an IterativeSearchJob search.
// We must send to the InNetMessagePool so the message can be matched
// and the search marked as successful.
// Or, it's a normal LS bundled with data and a MessageStatusMessage.
// ... and inject it.
((LeaseSet) dsm.getEntry()).setReceivedAsReply();
if (_log.shouldLog(Log.INFO))
_log.info("Storing garlic LS down tunnel for: " + dsm.getKey() + " sent to: " + _client);
_context.inNetMessagePool().add(dsm, null, null);
} else {
if (_client != null) {
// drop it, since the data we receive shouldn't include router
// references, as that might get us to talk to them (and therefore
// open an attack vector)
_context.statManager().addRateData("tunnel.dropDangerousClientTunnelMessage", 1, DatabaseStoreMessage.MESSAGE_TYPE);
_log.error("Dropped dangerous message down a tunnel for " + _client + ": " + dsm, new Exception("cause"));
return;
}
// ... and inject it.
if (_log.shouldLog(Log.INFO))
_log.info("Storing garlic RI down tunnel for: " + dsm.getKey() + " sent to: " + _client);
_context.inNetMessagePool().add(dsm, null, null);
}
} else if (_client != null && type == DatabaseSearchReplyMessage.MESSAGE_TYPE) {
// DSRMs show up here now that replies are encrypted
// TODO: Strip in IterativeLookupJob etc. instead, depending on
// LS or RI and client or expl., so that we can safely follow references
// in a reply to a LS lookup over client tunnels.
// ILJ would also have to follow references via client tunnels
DatabaseSearchReplyMessage orig = (DatabaseSearchReplyMessage) data;
/**
**
* if (orig.getNumReplies() > 0) {
* if (_log.shouldLog(Log.INFO))
* _log.info("Removing replies from a garlic DSRM down a tunnel for " + _client + ": " + data);
* DatabaseSearchReplyMessage newMsg = new DatabaseSearchReplyMessage(_context);
* newMsg.setFromHash(orig.getFromHash());
* newMsg.setSearchKey(orig.getSearchKey());
* orig = newMsg;
* }
***
*/
_context.inNetMessagePool().add(orig, null, null);
} else if (type == DataMessage.MESSAGE_TYPE) {
// a data message targetting the local router is how we send load tests (real
// data messages target destinations)
_context.statManager().addRateData("tunnel.handleLoadClove", 1);
data = null;
// _context.inNetMessagePool().add(data, null, null);
} else if (_client != null && type != DeliveryStatusMessage.MESSAGE_TYPE) {
// drop it, since the data we receive shouldn't include other stuff,
// as that might open an attack vector
_context.statManager().addRateData("tunnel.dropDangerousClientTunnelMessage", 1, data.getType());
_log.error("Dropped dangerous message down a tunnel for " + _client + ": " + data, new Exception("cause"));
} else {
_context.inNetMessagePool().add(data, null, null);
}
return;
case DeliveryInstructions.DELIVERY_MODE_DESTINATION:
Hash to = instructions.getDestination();
// Can we route UnknownI2NPMessages to a destination too?
if (type != DataMessage.MESSAGE_TYPE) {
if (_log.shouldLog(Log.ERROR))
_log.error("cant send a " + data.getClass().getSimpleName() + " to a destination");
} else if (_client != null && _client.equals(to)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("data message came down a tunnel for " + _client);
DataMessage dm = (DataMessage) data;
Payload payload = new Payload();
payload.setEncryptedData(dm.getData());
ClientMessage m = new ClientMessage(_client, payload);
_context.clientManager().messageReceived(m);
} else if (_client != null) {
// Shared tunnel?
TunnelPoolSettings tgt = _context.tunnelManager().getInboundSettings(to);
if (tgt != null && _client.equals(tgt.getAliasOf())) {
// same as above, just different log
if (_log.shouldLog(Log.DEBUG))
_log.debug("data message came down a tunnel for " + _client + " targeting shared " + to);
DataMessage dm = (DataMessage) data;
Payload payload = new Payload();
payload.setEncryptedData(dm.getData());
ClientMessage m = new ClientMessage(to, payload);
_context.clientManager().messageReceived(m);
} else {
if (_log.shouldLog(Log.ERROR))
_log.error("Data message came down a tunnel for " + _client + " but targetted " + to);
}
} else {
if (_log.shouldLog(Log.ERROR))
_log.error("Data message came down an exploratory tunnel targeting " + to);
}
return;
// fall through
case DeliveryInstructions.DELIVERY_MODE_ROUTER:
case DeliveryInstructions.DELIVERY_MODE_TUNNEL:
if (_log.shouldLog(Log.INFO))
_log.info("clove targetted " + instructions.getRouter() + ":" + instructions.getTunnelId() + ", treat recursively to prevent leakage");
distribute(data, instructions.getRouter(), instructions.getTunnelId());
return;
default:
if (_log.shouldLog(Log.ERROR))
_log.error("Unknown instruction " + instructions.getDeliveryMode() + ": " + instructions);
return;
}
}
use of net.i2p.data.i2np.DatabaseSearchReplyMessage in project i2p.i2p by i2p.
the class HandleDatabaseLookupMessageJob method sendClosest.
protected void sendClosest(Hash key, Set<Hash> routerHashes, Hash toPeer, TunnelId replyTunnel) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Sending closest routers to key " + key + ": # peers = " + routerHashes.size() + " tunnel " + replyTunnel);
DatabaseSearchReplyMessage msg = new DatabaseSearchReplyMessage(getContext());
msg.setFromHash(getContext().routerHash());
msg.setSearchKey(key);
int i = 0;
for (Hash h : routerHashes) {
msg.addReply(h);
if (++i >= MAX_ROUTERS_RETURNED)
break;
}
getContext().statManager().addRateData("netDb.lookupsHandled", 1);
// should this go via garlic messages instead?
sendMessage(msg, toPeer, replyTunnel);
}
use of net.i2p.data.i2np.DatabaseSearchReplyMessage in project i2p.i2p by i2p.
the class FloodOnlyLookupSelector method isMatch.
public boolean isMatch(I2NPMessage message) {
if (message == null)
return false;
if (message instanceof DatabaseStoreMessage) {
DatabaseStoreMessage dsm = (DatabaseStoreMessage) message;
// is it worth making sure the reply came in on the right tunnel?
if (_search.getKey().equals(dsm.getKey())) {
_search.decrementRemaining();
_matchFound = true;
return true;
}
} else if (message instanceof DatabaseSearchReplyMessage) {
DatabaseSearchReplyMessage dsrm = (DatabaseSearchReplyMessage) message;
if (_search.getKey().equals(dsrm.getSearchKey())) {
// TODO - dsrm.getFromHash() can't be trusted - check against the list of
// those we sent the search to in _search ?
// assume 0 new, all old, 0 invalid, 0 dup
_context.profileManager().dbLookupReply(dsrm.getFromHash(), 0, dsrm.getNumReplies(), 0, 0, System.currentTimeMillis() - _search.getCreated());
// Only process if we don't know enough floodfills or are starting up
if (_search.shouldProcessDSRM()) {
if (_log.shouldLog(Log.INFO))
_log.info(_search.getJobId() + ": Processing DSRM via SingleLookupJob, apparently from " + dsrm.getFromHash());
// Chase the hashes from the reply
_context.jobQueue().addJob(new SingleLookupJob(_context, dsrm));
} else if (_log.shouldLog(Log.INFO)) {
int remaining = _search.getLookupsRemaining();
_log.info(_search.getJobId() + ": got a DSRM apparently from " + dsrm.getFromHash() + " when we were looking for " + _search.getKey() + ", with " + remaining + " outstanding searches");
}
// if no more left, time to fail
int remaining = _search.decrementRemaining(dsrm.getFromHash());
return remaining <= 0;
}
}
return false;
}
Aggregations