diff --git a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java index b9aab6fdb..6e2c0a490 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java @@ -378,7 +378,9 @@ class PeerTestManager { if (!expired()) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Sending msg 6 to Charlie: " + test); - test.setLastSendTime(_context.clock().now()); + long now = _context.clock().now(); + test.setLastSendTime(now); + test.setSendCharlieTime(now); UDPPacket packet; if (test.getBob().getVersion() == 1) { packet = _packetBuilder.buildPeerTestFromAlice(test.getCharlieIP(), test.getCharliePort(), @@ -1059,6 +1061,7 @@ class PeerTestManager { _transport.send(packet); alice.setLastSendTime(now); state.setSendAliceTime(now); + state.setReceiveAliceTime(now); return; } else if (msg == 2) { if (_log.shouldDebug()) @@ -1067,15 +1070,20 @@ class PeerTestManager { UDPPacket packet = _packetBuilder2.buildPeerTestToBob(state.getStatus(), data, bob); _transport.send(packet); bob.setLastSendTime(now); + state.setReceiveBobTime(now); // should we retx msg 5 also? return; } else { // msg 1 but haven't heard from a good charlie yet - // TODO pick a new charlie + // TODO retransmit to the old charlie, or if it's been too long, pick a new charlie } } - if (_log.shouldWarn()) - _log.warn("Dup msg " + msg + " from " + fromPeer + " on " + state); + if (_log.shouldDebug()) + _log.debug("Dup msg " + msg + " from " + fromPeer + " on " + state); + if (msg == 1) + state.setReceiveAliceTime(now); + else + state.setReceiveBobTime(now); return; } if (_activeTests.size() >= MAX_ACTIVE_TESTS) { @@ -1521,6 +1529,22 @@ class PeerTestManager { _log.warn("Test nonce mismatch? " + nonce); return; } + if (test.getSendCharlieTime() > 0) { + // After sending msg 6, we will ignore any msg 5 received + // we ignore completely, including any ip/port mismatch + // Do not call setCharlieReceiveTime() + if (_log.shouldDebug()) + _log.debug("Ignoring msg 5 after sending msg 6, from Charlie " + from + " on " + test); + return; + } + long prev = test.getReceiveCharlieTime(); + test.setReceiveCharlieTime(now); + if (prev > 0) { + // we ignore completely, including any ip/port mismatch + if (_log.shouldDebug()) + _log.debug("Dup msg 5 from Charlie " + from + " on " + test); + return; + } InetAddress charlieIP = test.getCharlieIP(); if (charlieIP == null) { // msg 5 before msg 4 @@ -1566,7 +1590,6 @@ class PeerTestManager { } } } - test.setReceiveCharlieTime(now); // Do NOT set this here, only for msg 7, this is how testComplete() knows we got msg 7 //test.setAlicePortFromCharlie(testPort); try { @@ -1639,6 +1662,13 @@ class PeerTestManager { _log.warn("Test nonce mismatch? " + nonce); return; } + if (test.getReceiveBobTime() <= 0) { + // can't happen, we can't send msg 6 w/o msg 4 + if (_log.shouldWarn()) + _log.warn("Got msg 7 w/o msg 4??? on " + test); + testComplete(); + return; + } if (test.getReceiveCharlieTime() <= 0) { // ?? } @@ -1646,27 +1676,40 @@ class PeerTestManager { // Do NOT set this here, this is only for msg 5 //test.setReceiveCharlieTime(now); // i2pd did not send address block in msg 7 until 0.9.57 - if (addrBlockPort != 0) { - // use the IP/port from the address block - test.setAlicePortFromCharlie(addrBlockPort); + // Do basic validation of address block IP/port. + boolean bad = false; + if (addrBlockIP != null) { + if (_transport.isValid(addrBlockIP)) { + try { + InetAddress addr = InetAddress.getByAddress(addrBlockIP); + test.setAliceIPFromCharlie(addr); + } catch (UnknownHostException uhe) {} + } else { + bad = true; + } + } else { + // assume good + test.setAliceIPFromCharlie(test.getAliceIP()); + } + if (!bad && addrBlockPort != 0) { + if (addrBlockPort >= 1024) { + // use the IP/port from the address block + test.setAlicePortFromCharlie(addrBlockPort); + } else { + bad = true; + } } else if (!_transport.isSnatted()) { // assume good if we aren't snatted test.setAlicePortFromCharlie(test.getAlicePort()); } - if (addrBlockIP != null) { - try { - InetAddress addr = InetAddress.getByAddress(addrBlockIP); - test.setAliceIPFromCharlie(addr); - } catch (UnknownHostException uhe) { - if (_log.shouldWarn()) - _log.warn("Charlie @ " + from + " said we were an invalid IP address: " + uhe.getMessage(), uhe); - _context.statManager().addRateData("udp.testBadIP", 1); - } - } else { - test.setAliceIPFromCharlie(test.getAliceIP()); + if (bad) { + if (_log.shouldWarn()) + _log.warn("Charlie said we had an invalid IP/port: " + + Addresses.toString(addrBlockIP, addrBlockPort) + " on " + test); + _context.statManager().addRateData("udp.testBadIP", 1); + // TODO ban charlie or put on a list? } - if (test.getReceiveBobTime() > 0) - testComplete(); + testComplete(); break; } @@ -1766,8 +1809,8 @@ class PeerTestManager { state = new PeerTestState(CHARLIE, bob, sz == 16, nonce, now); } else { if (state.getReceiveBobTime() > now - (RESEND_TIMEOUT / 2)) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Too soon, not retransmitting: " + state); + if (_log.shouldDebug()) + _log.debug("Too soon, not retransmitting: " + state); return; } } diff --git a/router/java/src/net/i2p/router/transport/udp/PeerTestState.java b/router/java/src/net/i2p/router/transport/udp/PeerTestState.java index a2b82cbac..42ca22c0a 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerTestState.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerTestState.java @@ -43,6 +43,7 @@ class PeerTestState { private long _receiveBobTime; private long _receiveCharlieTime; private long _sendAliceTime; + private long _sendCharlieTime; private int _status; private final AtomicInteger _packetsRelayed = new AtomicInteger(); @@ -211,6 +212,18 @@ class PeerTestState { */ public void setSendAliceTime(long when) { _sendAliceTime = when; } + /** + * when did we send to Charlie, SSU2 Alice only + * @since 0.9.57 + */ + public long getSendCharlieTime() { return _sendCharlieTime; } + + /** + * when did we send to Charlie, SSU2 Alice only + * @since 0.9.57 + */ + public void setSendCharlieTime(long when) { _sendCharlieTime = when; } + /** * what code did we send to alice, SSU2 Bob only * @since 0.9.57 @@ -277,10 +290,14 @@ class PeerTestState { } if (_lastSendTime > 0) buf.append("; last send after ").append(_lastSendTime - _beginTime); + if (_sendAliceTime > 0) + buf.append("; last send to Alice ").append(DataHelper.formatTime(_sendAliceTime)); if (_receiveAliceTime > 0) buf.append("; rcvd from Alice after ").append(_receiveAliceTime - _beginTime); if (_receiveBobTime > 0) buf.append("; rcvd from Bob after ").append(_receiveBobTime - _beginTime); + if (_sendCharlieTime > 0) + buf.append("; last send to Charlie ").append(DataHelper.formatTime(_sendCharlieTime)); if (_receiveCharlieTime > 0) buf.append("; rcvd from Charlie after ").append(_receiveCharlieTime - _beginTime); buf.append("; pkts relayed: ").append(_packetsRelayed.get());