use of net.i2p.data.TunnelId in project i2p.i2p by i2p.
the class HandleFloodfillDatabaseStoreMessageJob method sendAck.
private void sendAck(Hash storedKey) {
DeliveryStatusMessage msg = new DeliveryStatusMessage(getContext());
msg.setMessageId(_message.getReplyToken());
// Randomize for a little protection against clock-skew fingerprinting.
// But the "arrival" isn't used for anything, right?
// TODO just set to 0?
// TODO we have no session to garlic wrap this with, needs new message
msg.setArrival(getContext().clock().now() - getContext().random().nextInt(3 * 1000));
// may be null
TunnelId replyTunnel = _message.getReplyTunnel();
// A store of our own RI, only if we are not FF
DatabaseStoreMessage msg2;
if ((getContext().netDb().floodfillEnabled() && !getContext().router().gracefulShutdownInProgress()) || storedKey.equals(getContext().routerHash())) {
// don't send our RI if the store was our RI (from PeerTestJob)
msg2 = null;
} else {
// we aren't ff, send a go-away message
msg2 = new DatabaseStoreMessage(getContext());
RouterInfo me = getContext().router().getRouterInfo();
msg2.setEntry(me);
if (_log.shouldWarn())
_log.warn("Got a store w/ reply token, but we aren't ff: from: " + _from + " fromHash: " + _fromHash + " msg: " + _message, new Exception());
}
Hash toPeer = _message.getReplyGateway();
boolean toUs = getContext().routerHash().equals(toPeer);
// else through an exploratory tunnel.
if (toUs && replyTunnel != null) {
// if we are the gateway, act as if we received it
TunnelGatewayMessage tgm = new TunnelGatewayMessage(getContext());
tgm.setMessage(msg);
tgm.setTunnelId(replyTunnel);
tgm.setMessageExpiration(msg.getMessageExpiration());
getContext().tunnelDispatcher().dispatch(tgm);
if (msg2 != null) {
TunnelGatewayMessage tgm2 = new TunnelGatewayMessage(getContext());
tgm2.setMessage(msg2);
tgm2.setTunnelId(replyTunnel);
tgm2.setMessageExpiration(msg.getMessageExpiration());
getContext().tunnelDispatcher().dispatch(tgm2);
}
} else if (toUs || getContext().commSystem().isEstablished(toPeer)) {
Job send = new SendMessageDirectJob(getContext(), msg, toPeer, REPLY_TIMEOUT, MESSAGE_PRIORITY);
send.runJob();
if (msg2 != null) {
Job send2 = new SendMessageDirectJob(getContext(), msg2, toPeer, REPLY_TIMEOUT, MESSAGE_PRIORITY);
send2.runJob();
}
} else {
// pick tunnel with endpoint closest to toPeer
TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(toPeer);
if (outTunnel == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("No outbound tunnel could be found");
return;
}
getContext().tunnelDispatcher().dispatchOutbound(msg, outTunnel.getSendTunnelId(0), replyTunnel, toPeer);
if (msg2 != null)
getContext().tunnelDispatcher().dispatchOutbound(msg2, outTunnel.getSendTunnelId(0), replyTunnel, toPeer);
}
}
use of net.i2p.data.TunnelId in project i2p.i2p by i2p.
the class DeliveryInstructions method readBytes.
/**
* @deprecated unused
*/
@Deprecated
public void readBytes(InputStream in) throws DataFormatException, IOException {
long flags = DataHelper.readLong(in, 1);
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Read flags: " + flags + " mode: " + flagMode(flags));
/**
**
* if (flagEncrypted(flags)) {
* SessionKey k = new SessionKey();
* k.readBytes(in);
* setEncryptionKey(k);
* setEncrypted(true);
* } else {
* setEncrypted(false);
* }
***
*/
setDeliveryMode(flagMode(flags));
switch(flagMode(flags)) {
case FLAG_MODE_LOCAL:
break;
case FLAG_MODE_DESTINATION:
// Hash destHash = new Hash();
// destHash.readBytes(in);
Hash destHash = Hash.create(in);
setDestination(destHash);
break;
case FLAG_MODE_ROUTER:
// Hash routerHash = new Hash();
// routerHash.readBytes(in);
Hash routerHash = Hash.create(in);
setRouter(routerHash);
break;
case FLAG_MODE_TUNNEL:
// Hash tunnelRouterHash = new Hash();
// tunnelRouterHash.readBytes(in);
Hash tunnelRouterHash = Hash.create(in);
setRouter(tunnelRouterHash);
TunnelId id = new TunnelId();
id.readBytes(in);
setTunnelId(id);
break;
}
if (flagDelay(flags)) {
long delay = DataHelper.readLong(in, 4);
setDelayRequested(true);
setDelaySeconds(delay);
} else {
setDelayRequested(false);
}
}
use of net.i2p.data.TunnelId in project i2p.i2p by i2p.
the class DeliveryInstructions method readBytes.
public int readBytes(byte[] data, int offset) throws DataFormatException {
int cur = offset;
int flags = data[cur] & 0xff;
cur++;
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Read flags: " + flags + " mode: " + flagMode(flags));
/**
**
* if (flagEncrypted(flags)) {
* byte kd[] = new byte[SessionKey.KEYSIZE_BYTES];
* System.arraycopy(data, cur, kd, 0, SessionKey.KEYSIZE_BYTES);
* cur += SessionKey.KEYSIZE_BYTES;
* setEncryptionKey(new SessionKey(kd));
* setEncrypted(true);
* } else {
* setEncrypted(false);
* }
***
*/
setDeliveryMode(flagMode(flags));
switch(flagMode(flags)) {
case FLAG_MODE_LOCAL:
break;
case FLAG_MODE_DESTINATION:
// byte destHash[] = new byte[Hash.HASH_LENGTH];
// System.arraycopy(data, cur, destHash, 0, Hash.HASH_LENGTH);
Hash dh = Hash.create(data, cur);
cur += Hash.HASH_LENGTH;
setDestination(dh);
break;
case FLAG_MODE_ROUTER:
// byte routerHash[] = new byte[Hash.HASH_LENGTH];
// System.arraycopy(data, cur, routerHash, 0, Hash.HASH_LENGTH);
Hash rh = Hash.create(data, cur);
cur += Hash.HASH_LENGTH;
setRouter(rh);
break;
case FLAG_MODE_TUNNEL:
// byte tunnelRouterHash[] = new byte[Hash.HASH_LENGTH];
// System.arraycopy(data, cur, tunnelRouterHash, 0, Hash.HASH_LENGTH);
Hash trh = Hash.create(data, cur);
cur += Hash.HASH_LENGTH;
setRouter(trh);
setTunnelId(new TunnelId(DataHelper.fromLong(data, cur, 4)));
cur += 4;
break;
}
if (flagDelay(flags)) {
long delay = DataHelper.fromLong(data, cur, 4);
cur += 4;
setDelayRequested(true);
setDelaySeconds(delay);
} else {
setDelayRequested(false);
}
return cur - offset;
}
use of net.i2p.data.TunnelId in project i2p.i2p by i2p.
the class TunnelGatewayMessage method readMessage.
/**
* Note that for efficiency at the IBGW, this does not fully deserialize the included
* I2NP Message. It just puts it in an UnknownI2NPMessage.
*
* @param handler unused, may be null
*/
@Override
public void readMessage(byte[] data, int offset, int dataSize, int type, I2NPMessageHandler handler) throws I2NPMessageException {
if (type != MESSAGE_TYPE)
throw new I2NPMessageException("Message type is incorrect for this message");
int curIndex = offset;
_tunnelId = new TunnelId(DataHelper.fromLong(data, curIndex, 4));
curIndex += 4;
if (_tunnelId.getTunnelId() <= 0)
throw new I2NPMessageException("Invalid tunnel Id " + _tunnelId);
int len = (int) DataHelper.fromLong(data, curIndex, 2);
curIndex += 2;
if (len <= 1 || curIndex + len > data.length || len > dataSize - 6)
throw new I2NPMessageException("I2NP length in TGM: " + len + " but remaining bytes: " + Math.min(data.length - curIndex, dataSize - 6));
// OLD WAY full message parsing and instantiation
// handler.readMessage(data, curIndex);
// _msg = handler.lastRead();
// if (_msg == null)
// throw new I2NPMessageException("impossible? message read has no payload?!");
// NEW WAY save lots of effort at the IBGW by reading as an UnknownI2NPMessage instead
// This will save a lot of object churn and processing,
// primarily for unencrypted msgs (V)TBRM, DatabaseStoreMessage, and DSRMs.
// DatabaseStoreMessages in particluar are intensive for readBytes()
// since the RI is decompressed.
// For a zero-hop IB tunnel, where we do need the real thing,
// it is converted to a real message class in TunnelGatewayZeroHop
// using UnknownI2NPMessage.convert() in TunnelGatewayZeroHop.
// We also skip processing the checksum as it's covered by the TGM checksum.
// If a zero-hop, the checksum will be verified in convert().
int utype = data[curIndex++] & 0xff;
UnknownI2NPMessage umsg = new UnknownI2NPMessage(_context, utype);
umsg.readBytes(data, utype, curIndex);
_msg = umsg;
}
use of net.i2p.data.TunnelId in project i2p.i2p by i2p.
the class OutboundClientMessageJobHelper method buildAckClove.
/**
* Build a clove that sends a DeliveryStatusMessage to us.
* As of 0.9.12, the DSM is wrapped in a GarlicMessage.
* @param skm encrypt dsm with this skm non-null
* @return null on error
*/
private static PayloadGarlicConfig buildAckClove(RouterContext ctx, Hash from, TunnelInfo replyToTunnel, long replyToken, long expiration, SessionKeyManager skm) {
Log log = ctx.logManager().getLog(OutboundClientMessageJobHelper.class);
if (replyToTunnel == null) {
if (log.shouldLog(Log.WARN))
log.warn("Unable to send client message from " + from.toBase64() + ", as there are no inbound tunnels available");
return null;
}
// tunnel id on that gateway
TunnelId replyToTunnelId = replyToTunnel.getReceiveTunnelId(0);
// inbound tunnel gateway
Hash replyToTunnelRouter = replyToTunnel.getPeer(0);
if (log.shouldLog(Log.DEBUG))
log.debug("Ack for the data message will come back along tunnel " + replyToTunnelId + ": " + replyToTunnel);
DeliveryInstructions ackInstructions = new DeliveryInstructions();
ackInstructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_TUNNEL);
ackInstructions.setRouter(replyToTunnelRouter);
ackInstructions.setTunnelId(replyToTunnelId);
// defaults
// ackInstructions.setDelayRequested(false);
// ackInstructions.setDelaySeconds(0);
// ackInstructions.setEncrypted(false);
PayloadGarlicConfig ackClove = new PayloadGarlicConfig();
ackClove.setCertificate(Certificate.NULL_CERT);
ackClove.setDeliveryInstructions(ackInstructions);
ackClove.setExpiration(expiration);
ackClove.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
DeliveryStatusMessage dsm = buildDSM(ctx, replyToken);
GarlicMessage msg = wrapDSM(ctx, skm, dsm);
if (msg == null) {
if (log.shouldLog(Log.WARN))
log.warn("Failed to wrap ack clove");
return null;
}
ackClove.setPayload(msg);
return ackClove;
}
Aggregations