forked from I2P_Developers/i2p.i2p
I2CP: Prevent loopback messages to same session (i2pd Github #2005)
This commit is contained in:
@@ -117,6 +117,9 @@ public class I2PSocketException extends SocketException {
|
||||
case MessageStatusMessage.STATUS_SEND_FAILURE_META_LEASESET:
|
||||
return "Meta lease set";
|
||||
|
||||
case MessageStatusMessage.STATUS_SEND_FAILURE_LOOPBACK:
|
||||
return "local loopback denied, set i2cp.disableLoopback=true to test sending to yourself through tunnels";
|
||||
|
||||
case SendMessageStatusListener.STATUS_CANCELLED:
|
||||
return _x("Local destination shutdown");
|
||||
|
||||
|
@@ -324,6 +324,7 @@ class PacketQueue implements SendMessageStatusListener, Closeable {
|
||||
case MessageStatusMessage.STATUS_SEND_FAILURE_DESTINATION:
|
||||
case MessageStatusMessage.STATUS_SEND_FAILURE_BAD_LEASESET:
|
||||
case MessageStatusMessage.STATUS_SEND_FAILURE_EXPIRED_LEASESET:
|
||||
case MessageStatusMessage.STATUS_SEND_FAILURE_LOOPBACK:
|
||||
case SendMessageStatusListener.STATUS_CANCELLED:
|
||||
if (con.getHighestAckedThrough() >= 0) {
|
||||
// a retxed SYN succeeded before the first SYN failed
|
||||
|
@@ -157,6 +157,7 @@ class MessageState {
|
||||
case MessageStatusMessage.STATUS_SEND_FAILURE_EXPIRED_LEASESET:
|
||||
case MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET:
|
||||
case MessageStatusMessage.STATUS_SEND_FAILURE_META_LEASESET:
|
||||
case MessageStatusMessage.STATUS_SEND_FAILURE_LOOPBACK:
|
||||
case SendMessageStatusListener.STATUS_CANCELLED:
|
||||
// does not trump success
|
||||
if (_state != State.SUCCESS)
|
||||
|
@@ -189,6 +189,13 @@ public class MessageStatusMessage extends I2CPMessageImpl {
|
||||
*/
|
||||
public final static int STATUS_SEND_FAILURE_META_LEASESET = 22;
|
||||
|
||||
/**
|
||||
* Message was attempted to be sent to the same Destination.
|
||||
* This is a guaranteed failure.
|
||||
* @since 0.9.62
|
||||
*/
|
||||
public final static int STATUS_SEND_FAILURE_LOOPBACK = 23;
|
||||
|
||||
// NOTE:
|
||||
// Add any new status codes to handlers in:
|
||||
// net.i2p.client.impl.MessageState
|
||||
|
@@ -806,7 +806,7 @@ class ClientConnectionRunner {
|
||||
// the following blocks as described above
|
||||
Destination fromDest = getDestination(message.getSessionId());
|
||||
if (fromDest != null)
|
||||
_manager.distributeMessage(fromDest, dest, payload,
|
||||
_manager.distributeMessage(this, fromDest, dest, payload,
|
||||
id, message.getNonce(), expiration, flags);
|
||||
// else log error?
|
||||
//long timeToDistribute = _context.clock().now() - beforeDistribute;
|
||||
|
@@ -451,11 +451,13 @@ class ClientManager {
|
||||
|
||||
/**
|
||||
* Distribute message to a local or remote destination.
|
||||
*
|
||||
* @param sender non-null
|
||||
* @param msgId the router's ID for this message
|
||||
* @param messageNonce the client's ID for this message
|
||||
* @param flags ignored for local
|
||||
*/
|
||||
void distributeMessage(Destination fromDest, Destination toDest, Payload payload,
|
||||
void distributeMessage(ClientConnectionRunner sender, Destination fromDest, Destination toDest, Payload payload,
|
||||
MessageId msgId, long messageNonce, long expiration, int flags) {
|
||||
ClientConnectionRunner runner;
|
||||
if (_ctx.getBooleanProperty(PROP_DISABLE_LOOPBACK)) {
|
||||
@@ -467,22 +469,19 @@ class ClientManager {
|
||||
if (runner != null) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Message " + msgId + " is targeting a local destination. distribute it as such");
|
||||
ClientConnectionRunner sender = getRunner(fromDest);
|
||||
if (sender == null) {
|
||||
// sender went away
|
||||
return;
|
||||
if (runner != sender) {
|
||||
// run this inline so we don't clog up the job queue
|
||||
Job j = new DistributeLocal(toDest, runner, sender, fromDest, payload, msgId, messageNonce);
|
||||
//_ctx.jobQueue().addJob(j);
|
||||
j.runJob();
|
||||
} else {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Loopback attempt from client " + fromDest.getHash());
|
||||
int rc = MessageStatusMessage.STATUS_SEND_FAILURE_LOOPBACK;
|
||||
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, rc);
|
||||
}
|
||||
// run this inline so we don't clog up the job queue
|
||||
Job j = new DistributeLocal(toDest, runner, sender, fromDest, payload, msgId, messageNonce);
|
||||
//_ctx.jobQueue().addJob(j);
|
||||
j.runJob();
|
||||
} else if (!_metaDests.isEmpty() && _metaDests.contains(toDest)) {
|
||||
// meta dests don't have runners but are local, and you can't send to them
|
||||
ClientConnectionRunner sender = getRunner(fromDest);
|
||||
if (sender == null) {
|
||||
// sender went away
|
||||
return;
|
||||
}
|
||||
int rc = MessageStatusMessage.STATUS_SEND_FAILURE_BAD_LEASESET;
|
||||
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, rc);
|
||||
} else {
|
||||
|
@@ -56,19 +56,16 @@ class LocalClientManager extends ClientManager {
|
||||
* @param flags ignored for local
|
||||
*/
|
||||
@Override
|
||||
void distributeMessage(Destination fromDest, Destination toDest, Payload payload,
|
||||
void distributeMessage(ClientConnectionRunner sender, Destination fromDest, Destination toDest, Payload payload,
|
||||
MessageId msgId, long messageNonce, long expiration, int flags) {
|
||||
// check if there is a runner for it
|
||||
ClientConnectionRunner sender = getRunner(fromDest);
|
||||
ClientConnectionRunner runner = getRunner(toDest);
|
||||
if (runner != null) {
|
||||
if (dropX1000 > 0) {
|
||||
if (100 * 1000 * _ctx.random().nextFloat() < dropX1000) {
|
||||
System.out.println("Message " + msgId + " DROPPED randomly");
|
||||
if (sender != null) {
|
||||
// pretend success
|
||||
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, MessageStatusMessage.STATUS_SEND_GUARANTEED_SUCCESS);
|
||||
}
|
||||
// pretend success
|
||||
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, MessageStatusMessage.STATUS_SEND_GUARANTEED_SUCCESS);
|
||||
}
|
||||
}
|
||||
if (latency > 0 || jitter > 0) {
|
||||
@@ -83,15 +80,12 @@ class LocalClientManager extends ClientManager {
|
||||
}
|
||||
}
|
||||
boolean ok = runner.receiveMessage(toDest, fromDest, payload);
|
||||
if (sender != null) {
|
||||
int rc = ok ? MessageStatusMessage.STATUS_SEND_SUCCESS_LOCAL : MessageStatusMessage.STATUS_SEND_FAILURE_LOCAL;
|
||||
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, rc);
|
||||
}
|
||||
int rc = ok ? MessageStatusMessage.STATUS_SEND_SUCCESS_LOCAL : MessageStatusMessage.STATUS_SEND_FAILURE_LOCAL;
|
||||
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, rc);
|
||||
} else {
|
||||
// remote. ignore.
|
||||
System.out.println("Message " + msgId + " is targeting a REMOTE destination - DROPPED");
|
||||
if (sender != null)
|
||||
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, MessageStatusMessage.STATUS_SEND_GUARANTEED_FAILURE);
|
||||
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, MessageStatusMessage.STATUS_SEND_GUARANTEED_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,10 +107,8 @@ class LocalClientManager extends ClientManager {
|
||||
|
||||
public void timeReached() {
|
||||
boolean ok = r.receiveMessage(td, fd, pl);
|
||||
if (s != null) {
|
||||
int rc = ok ? MessageStatusMessage.STATUS_SEND_SUCCESS_LOCAL : MessageStatusMessage.STATUS_SEND_FAILURE_LOCAL;
|
||||
s.updateMessageDeliveryStatus(fd, id, nonce, rc);
|
||||
}
|
||||
int rc = ok ? MessageStatusMessage.STATUS_SEND_SUCCESS_LOCAL : MessageStatusMessage.STATUS_SEND_FAILURE_LOCAL;
|
||||
s.updateMessageDeliveryStatus(fd, id, nonce, rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user