forked from I2P_Developers/i2p.i2p
SSU2: Bundle RI with peer test messages 2 and 4 if possible
similar to previous checkin for relay intro
This commit is contained in:
@@ -728,8 +728,31 @@ class PacketBuilder2 {
|
||||
* @return ready to send packet, non-null
|
||||
*/
|
||||
public UDPPacket buildPeerTestToAlice(int code, Hash charlieHash, byte[] signedData, PeerState2 alice) {
|
||||
return buildPeerTestToAlice(code, charlieHash, signedData, null, alice);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a packet as Bob to Alice, with the response from Charlie,
|
||||
* or a rejection by Bob.
|
||||
* In-session, message 4.
|
||||
*
|
||||
* @param charlieHash fake hash (all zeros) if rejected by bob
|
||||
* @param riBlock to include, may be null
|
||||
* @return ready to send packet, non-null
|
||||
* @since 0.9.57
|
||||
*/
|
||||
public UDPPacket buildPeerTestToAlice(int code, Hash charlieHash, byte[] signedData, Block riBlock, PeerState2 alice) {
|
||||
Block block = new SSU2Payload.PeerTestBlock(4, code, charlieHash, signedData);
|
||||
UDPPacket rv = buildPacket(Collections.<Fragment>emptyList(), Collections.singletonList(block), alice);
|
||||
List<Block> blocks;
|
||||
if (riBlock != null) {
|
||||
// RouterInfo must be first
|
||||
blocks = new ArrayList<Block>(2);
|
||||
blocks.add(riBlock);
|
||||
blocks.add(block);
|
||||
} else {
|
||||
blocks = Collections.singletonList(block);
|
||||
}
|
||||
UDPPacket rv = buildPacket(Collections.<Fragment>emptyList(), blocks, alice);
|
||||
rv.setMessageType(TYPE_TTA);
|
||||
return rv;
|
||||
}
|
||||
@@ -761,11 +784,21 @@ class PacketBuilder2 {
|
||||
* Build a packet as Bob to Charlie to help test Alice.
|
||||
* In-session, message 2.
|
||||
*
|
||||
* @param riBlock to include, may be null
|
||||
* @return ready to send packet, non-null
|
||||
*/
|
||||
public UDPPacket buildPeerTestToCharlie(Hash aliceHash, byte[] signedData, PeerState2 charlie) {
|
||||
public UDPPacket buildPeerTestToCharlie(Hash aliceHash, byte[] signedData, Block riBlock, PeerState2 charlie) {
|
||||
Block block = new SSU2Payload.PeerTestBlock(2, 0, aliceHash, signedData);
|
||||
UDPPacket rv = buildPacket(Collections.<Fragment>emptyList(), Collections.singletonList(block), charlie);
|
||||
List<Block> blocks;
|
||||
if (riBlock != null) {
|
||||
// RouterInfo must be first
|
||||
blocks = new ArrayList<Block>(2);
|
||||
blocks.add(riBlock);
|
||||
blocks.add(block);
|
||||
} else {
|
||||
blocks = Collections.singletonList(block);
|
||||
}
|
||||
UDPPacket rv = buildPacket(Collections.<Fragment>emptyList(), blocks, charlie);
|
||||
rv.setMessageType(TYPE_TBC);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1193,16 +1193,8 @@ class PeerTestManager {
|
||||
// send alice RI to charlie
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Send Alice RI and msg 2 to charlie on " + state);
|
||||
// TODO see if Alide RI will compress enough to fit in the peer test packet
|
||||
DatabaseStoreMessage dbsm = new DatabaseStoreMessage(_context);
|
||||
dbsm.setEntry(aliceRI);
|
||||
dbsm.setMessageExpiration(now + 10*1000);
|
||||
_transport.send(dbsm, charlie);
|
||||
// forward to charlie, don't bother to validate signed data
|
||||
UDPPacket packet = _packetBuilder2.buildPeerTestToCharlie(alice, data, (PeerState2) charlie);
|
||||
// delay because dbsm is queued, we want it to get there first
|
||||
new DelaySend(packet, 100);
|
||||
charlie.setLastSendTime(now);
|
||||
sendRIandPT(aliceRI, -1, alice, data, (PeerState2) charlie, now);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1328,15 +1320,7 @@ class PeerTestManager {
|
||||
_log.info("Charlie response " + status + " picked a new one " + charlie + " on " + state);
|
||||
state.setCharlie(charlie.getRemoteIPAddress(), charlie.getRemotePort(), charlie.getRemotePeer());
|
||||
state.setLastSendTime(now);
|
||||
// TODO see if Alice RI will compress enough to fit in the peer test packet
|
||||
DatabaseStoreMessage dbsm = new DatabaseStoreMessage(_context);
|
||||
dbsm.setEntry(aliceRI);
|
||||
dbsm.setMessageExpiration(now + 10*1000);
|
||||
_transport.send(dbsm, charlie);
|
||||
UDPPacket packet = _packetBuilder2.buildPeerTestToCharlie(alice, state.getTestData(), (PeerState2) charlie);
|
||||
// delay because dbsm is queued, we want it to get there first
|
||||
new DelaySend(packet, 100);
|
||||
charlie.setLastSendTime(now);
|
||||
sendRIandPT(aliceRI, -1, alice, state.getTestData(), (PeerState2) charlie, now);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1353,11 +1337,6 @@ class PeerTestManager {
|
||||
// Alice would need it to verify sig, but not worth the bandwidth
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Send Charlie RI to alice on " + state);
|
||||
// TODO see if Charlie RI will compress enough to fit in the peer test packet
|
||||
DatabaseStoreMessage dbsm = new DatabaseStoreMessage(_context);
|
||||
dbsm.setEntry(charlieRI);
|
||||
dbsm.setMessageExpiration(now + 10*1000);
|
||||
_transport.send(dbsm, alice);
|
||||
if (true) {
|
||||
// Debug - validate signed data
|
||||
// we forward it to alice even on failure
|
||||
@@ -1377,13 +1356,7 @@ class PeerTestManager {
|
||||
// FIXME this will probably get there before the RI
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Send msg 4 status " + status + " to alice on " + state);
|
||||
UDPPacket packet = _packetBuilder2.buildPeerTestToAlice(status, charlie, data, alice);
|
||||
// delay because dbsm is queued, we want it to get there first
|
||||
if (charlieRI != null)
|
||||
new DelaySend(packet, 100);
|
||||
else
|
||||
_transport.send(packet);
|
||||
alice.setLastSendTime(now);
|
||||
sendRIandPT(charlieRI, status, charlie, data, alice, now);
|
||||
// overwrite alice-signed test data with charlie-signed data in case we need to retransmit
|
||||
state.setStatus(status);
|
||||
state.setSendAliceTime(now);
|
||||
@@ -2126,6 +2099,67 @@ class PeerTestManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send RI and Peer Test. SSU2 only. We are Bob.
|
||||
*
|
||||
* Msg 2 Bob to Charlie with Alice's RI
|
||||
* Msg 4 Bob to Alice with Charlie's RI
|
||||
*
|
||||
* @param ri may be null, but hopefully not
|
||||
* @param status -1 for msg 2, nonnegative for msg 4
|
||||
* @param hash alice for msg 2, charlie for msg 4
|
||||
* @param data signed peer test data
|
||||
* @param to charlie for msg 2, alice for msg 4
|
||||
* @since 0.9.57
|
||||
*/
|
||||
private void sendRIandPT(RouterInfo ri, int status, Hash hash, byte[] data, PeerState2 to, long now) {
|
||||
boolean delay = false;
|
||||
SSU2Payload.RIBlock riblock = null;
|
||||
if (ri != null) {
|
||||
// See if the RI will compress enough to fit in the peer test packet,
|
||||
// as this makes everything go smoother and faster.
|
||||
// Overhead total is 183 via IPv4, 203 via IPv6 (w/ IPv4 addr in data)
|
||||
// Overhead total is 195 via IPv4, 215 via IPv6 (w/ IPv6 addr in data)
|
||||
int avail = to.getMTU() -
|
||||
((to.isIPv6() ? PacketBuilder2.MIN_IPV6_DATA_PACKET_OVERHEAD : PacketBuilder2.MIN_DATA_PACKET_OVERHEAD) +
|
||||
SSU2Payload.BLOCK_HEADER_SIZE + // peer test block header
|
||||
3 + // peer test block msgnum/code/flag
|
||||
Hash.HASH_LENGTH + // peer test block hash
|
||||
data.length + // peer test block signed data
|
||||
SSU2Payload.BLOCK_HEADER_SIZE + // RI block header
|
||||
2 // RI block flag/frag bytes
|
||||
);
|
||||
byte[] info = ri.toByteArray();
|
||||
byte[] gzipped = DataHelper.compress(info, 0, info.length, DataHelper.MAX_COMPRESSION);
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("RI: " + info.length + " bytes uncompressed, " + gzipped.length +
|
||||
" compressed, MTU " + to.getMTU() + ", available " + avail);
|
||||
boolean gzip = gzipped.length < info.length;
|
||||
if (gzip)
|
||||
info = gzipped;
|
||||
if (info.length <= avail) {
|
||||
riblock = new SSU2Payload.RIBlock(info, 0, info.length, false, gzip, 0, 1);
|
||||
} else {
|
||||
DatabaseStoreMessage dbsm = new DatabaseStoreMessage(_context);
|
||||
dbsm.setEntry(ri);
|
||||
dbsm.setMessageExpiration(now + 10*1000);
|
||||
_transport.send(dbsm, to);
|
||||
delay = true;
|
||||
}
|
||||
}
|
||||
UDPPacket packet;
|
||||
if (status < 0)
|
||||
packet = _packetBuilder2.buildPeerTestToCharlie(hash, data, riblock, to);
|
||||
else
|
||||
packet = _packetBuilder2.buildPeerTestToAlice(status, hash, data, riblock, to);
|
||||
// delay because dbsm is queued, we want it to get there first
|
||||
if (delay)
|
||||
new DelaySend(packet, 100);
|
||||
else
|
||||
_transport.send(packet);
|
||||
to.setLastSendTime(now);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple fix for RI getting there before PeerTest.
|
||||
* SSU2 only. We are Bob, for delaying msg sent after RI to Alice or Charlie.
|
||||
|
||||
Reference in New Issue
Block a user