use of net.i2p.data.Hash in project i2p.i2p by i2p.
the class EstablishmentManager method establish.
/**
* @param queueIfMaxExceeded true normally, false if called from locked_admit so we don't loop
* @since 0.9.2
*/
private void establish(OutNetMessage msg, boolean queueIfMaxExceeded) {
RouterInfo toRouterInfo = msg.getTarget();
RouterAddress ra = _transport.getTargetAddress(toRouterInfo);
if (ra == null) {
_transport.failed(msg, "Remote peer has no address, cannot establish");
return;
}
RouterIdentity toIdentity = toRouterInfo.getIdentity();
Hash toHash = toIdentity.calculateHash();
if (toRouterInfo.getNetworkId() != _networkID) {
_context.banlist().banlistRouter(toHash);
_transport.markUnreachable(toHash);
_transport.failed(msg, "Remote peer is on the wrong network, cannot establish");
return;
}
UDPAddress addr = new UDPAddress(ra);
RemoteHostId maybeTo = null;
InetAddress remAddr = addr.getHostAddress();
int port = addr.getPort();
// claimed address (which we won't be using if indirect)
if (remAddr != null && port > 0 && port <= 65535) {
maybeTo = new RemoteHostId(remAddr.getAddress(), port);
if ((!_transport.isValid(maybeTo.getIP())) || (Arrays.equals(maybeTo.getIP(), _transport.getExternalIP()) && !_transport.allowLocal())) {
_transport.failed(msg, "Remote peer's IP isn't valid");
_transport.markUnreachable(toHash);
// _context.banlist().banlistRouter(msg.getTarget().getIdentity().calculateHash(), "Invalid SSU address", UDPTransport.STYLE);
_context.statManager().addRateData("udp.establishBadIP", 1);
return;
}
InboundEstablishState inState = _inboundStates.get(maybeTo);
if (inState != null) {
// we have an inbound establishment in progress, queue it there instead
synchronized (inState) {
switch(inState.getState()) {
case IB_STATE_UNKNOWN:
case IB_STATE_REQUEST_RECEIVED:
case IB_STATE_CREATED_SENT:
case IB_STATE_CONFIRMED_PARTIALLY:
case IB_STATE_CONFIRMED_COMPLETELY:
// queue it
inState.addMessage(msg);
if (_log.shouldLog(Log.WARN))
_log.debug("OB msg queued to IES");
break;
case IB_STATE_COMPLETE:
// race, send it out (but don't call _transport.send() again and risk a loop)
_transport.sendIfEstablished(msg);
break;
case IB_STATE_FAILED:
// race, failed
_transport.failed(msg, "OB msg failed during IB establish");
break;
}
}
return;
}
}
RemoteHostId to;
boolean isIndirect = addr.getIntroducerCount() > 0 || maybeTo == null;
if (isIndirect) {
to = new RemoteHostId(toHash);
} else {
to = maybeTo;
}
OutboundEstablishState state = null;
int deferred = 0;
boolean rejected = false;
int queueCount = 0;
state = _outboundStates.get(to);
if (state == null) {
state = _outboundByHash.get(toHash);
if (state != null && _log.shouldLog(Log.INFO))
_log.info("Found by hash: " + state);
}
if (state == null) {
if (queueIfMaxExceeded && _outboundStates.size() >= getMaxConcurrentEstablish()) {
if (_queuedOutbound.size() >= MAX_QUEUED_OUTBOUND && !_queuedOutbound.containsKey(to)) {
rejected = true;
} else {
List<OutNetMessage> newQueued = new ArrayList<OutNetMessage>(MAX_QUEUED_PER_PEER);
List<OutNetMessage> queued = _queuedOutbound.putIfAbsent(to, newQueued);
if (queued == null) {
queued = newQueued;
if (_log.shouldLog(Log.WARN))
_log.warn("Queueing outbound establish to " + to + ", increase " + PROP_MAX_CONCURRENT_ESTABLISH);
}
// There are still races possible but this should prevent AIOOBE and NPE
synchronized (queued) {
queueCount = queued.size();
if (queueCount < MAX_QUEUED_PER_PEER) {
queued.add(msg);
// increment for the stat below
queueCount++;
} else {
rejected = true;
}
deferred = _queuedOutbound.size();
}
}
} else {
// must have a valid session key
byte[] keyBytes = addr.getIntroKey();
if (keyBytes == null) {
_transport.markUnreachable(toHash);
_transport.failed(msg, "Peer has no key, cannot establish");
return;
}
SessionKey sessionKey;
try {
sessionKey = new SessionKey(keyBytes);
} catch (IllegalArgumentException iae) {
_transport.markUnreachable(toHash);
_transport.failed(msg, "Peer has bad key, cannot establish");
return;
}
boolean allowExtendedOptions = VersionComparator.comp(toRouterInfo.getVersion(), VERSION_ALLOW_EXTENDED_OPTIONS) >= 0 && !_context.getBooleanProperty(PROP_DISABLE_EXT_OPTS);
// w/o ext options, it's always 'requested', no need to set
// don't ask if they are indirect
boolean requestIntroduction = allowExtendedOptions && !isIndirect && _transport.introducersMaybeRequired();
state = new OutboundEstablishState(_context, maybeTo, to, toIdentity, allowExtendedOptions, requestIntroduction, sessionKey, addr, _transport.getDHFactory());
OutboundEstablishState oldState = _outboundStates.putIfAbsent(to, state);
boolean isNew = oldState == null;
if (isNew) {
if (isIndirect && maybeTo != null)
_outboundByClaimedAddress.put(maybeTo, state);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Adding new " + state);
} else {
// whoops, somebody beat us to it, throw out the state we just created
state = oldState;
}
}
}
if (state != null) {
state.addMessage(msg);
List<OutNetMessage> queued = _queuedOutbound.remove(to);
if (queued != null) {
// see comments above
synchronized (queued) {
for (OutNetMessage m : queued) {
state.addMessage(m);
}
}
}
}
if (rejected) {
if (_log.shouldLog(Log.WARN))
_log.warn("Too many pending, rejecting outbound establish to " + to);
_transport.failed(msg, "Too many pending outbound connections");
_context.statManager().addRateData("udp.establishRejected", deferred);
return;
}
if (queueCount >= MAX_QUEUED_PER_PEER) {
_transport.failed(msg, "Too many pending messages for the given peer");
_context.statManager().addRateData("udp.establishOverflow", queueCount, deferred);
return;
}
if (deferred > 0)
msg.timestamp("too many deferred establishers");
else if (state != null)
msg.timestamp("establish state already waiting");
notifyActivity();
}
use of net.i2p.data.Hash in project i2p.i2p by i2p.
the class DeliveryInstructionsTest method createDataStructure.
public DataStructure createDataStructure() throws DataFormatException {
DeliveryInstructions instructions = new DeliveryInstructions();
// instructions.setDelayRequested(true);
// instructions.setDelaySeconds(42);
instructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_TUNNEL);
// encryption key read/write disabled
// instructions.setEncrypted(true);
// SessionKey key = new SessionKey();
// byte keyData[] = new byte[SessionKey.KEYSIZE_BYTES];
// for (int i = 0; i < keyData.length; i++)
// keyData[i] = (byte)i;
// key.setData(keyData);
// instructions.setEncryptionKey(key);
Hash hash = new Hash();
byte[] hashData = new byte[32];
for (int i = 0; i < hashData.length; i++) hashData[i] = (byte) (i % 32);
hash.setData(hashData);
instructions.setRouter(hash);
TunnelId id = new TunnelId();
id.setTunnelId(666);
instructions.setTunnelId(id);
return instructions;
}
use of net.i2p.data.Hash in project i2p.i2p by i2p.
the class EstablishState method sendInboundConfirm.
/**
* We are Bob. Send message #4 to Alice.
*
* State must be VERIFIED.
* Caller must synch.
*/
private void sendInboundConfirm(RouterIdentity alice, long tsA) {
// send Alice E(S(X+Y+Alice.identHash+tsA+tsB), sk, prev)
byte[] toSign = new byte[XY_SIZE + XY_SIZE + 32 + 4 + 4];
int off = 0;
System.arraycopy(_X, 0, toSign, off, XY_SIZE);
off += XY_SIZE;
System.arraycopy(_Y, 0, toSign, off, XY_SIZE);
off += XY_SIZE;
Hash h = alice.calculateHash();
System.arraycopy(h.getData(), 0, toSign, off, 32);
off += 32;
DataHelper.toLong(toSign, off, 4, tsA);
off += 4;
DataHelper.toLong(toSign, off, 4, _tsB);
off += 4;
// handle variable signature size
Signature sig = _context.dsa().sign(toSign, _context.keyManager().getSigningPrivateKey());
int siglen = sig.length();
int rem = siglen % AES_SIZE;
int padding;
if (rem > 0)
padding = AES_SIZE - rem;
else
padding = 0;
byte[] preSig = new byte[siglen + padding];
System.arraycopy(sig.getData(), 0, preSig, 0, siglen);
if (padding > 0)
_context.random().nextBytes(preSig, siglen, padding);
_e_bobSig = new byte[preSig.length];
_context.aes().encrypt(preSig, 0, _e_bobSig, 0, _dh.getSessionKey(), _e_hXY_tsB, HXY_TSB_PAD_SIZE - AES_SIZE, _e_bobSig.length);
if (_log.shouldLog(Log.DEBUG))
_log.debug(prefix() + "Sending encrypted inbound confirmation");
_transport.getPumper().wantsWrite(_con, _e_bobSig);
}
use of net.i2p.data.Hash in project i2p.i2p by i2p.
the class NTCPTransport method bid.
public TransportBid bid(RouterInfo toAddress, long dataSize) {
if (!isAlive())
return null;
if (dataSize > NTCPConnection.MAX_MSG_SIZE) {
// let SSU deal with it
_context.statManager().addRateData("ntcp.noBidTooLargeI2NP", dataSize);
return null;
}
Hash peer = toAddress.getIdentity().calculateHash();
if (_context.banlist().isBanlisted(peer, STYLE)) {
// we aren't banlisted in general (since we are trying to get a bid), but we have
// recently banlisted the peer on the NTCP transport, so don't try it
_context.statManager().addRateData("ntcp.attemptBanlistedPeer", 1);
return null;
} else if (isUnreachable(peer)) {
_context.statManager().addRateData("ntcp.attemptUnreachablePeer", 1);
return null;
}
boolean established = isEstablished(toAddress.getIdentity());
if (established) {
// _log.debug("fast bid when trying to send to " + peer + " as its already established");
return _fastBid;
}
RouterAddress addr = getTargetAddress(toAddress);
if (addr == null) {
markUnreachable(peer);
return null;
}
// Check for supported sig type
SigType type = toAddress.getIdentity().getSigType();
if (type == null || !type.isAvailable()) {
markUnreachable(peer);
return null;
}
// Can we connect to them if we are not DSA?
RouterInfo us = _context.router().getRouterInfo();
if (us != null) {
RouterIdentity id = us.getIdentity();
if (id.getSigType() != SigType.DSA_SHA1) {
String v = toAddress.getVersion();
if (VersionComparator.comp(v, MIN_SIGTYPE_VERSION) < 0) {
markUnreachable(peer);
return null;
}
}
}
if (!allowConnection()) {
// _log.warn("no bid when trying to send to " + peer + ", max connection limit reached");
return _transientFail;
}
// _log.debug("slow bid when trying to send to " + peer);
if (haveCapacity()) {
if (addr.getCost() > DEFAULT_COST)
return _slowCostBid;
else
return _slowBid;
} else {
if (addr.getCost() > DEFAULT_COST)
return _nearCapacityCostBid;
else
return _nearCapacityBid;
}
}
use of net.i2p.data.Hash in project i2p.i2p by i2p.
the class NTCPTransport method inboundEstablished.
/**
* @param con that is established
* @return the previous connection to the same peer, must be closed by caller, null if no such.
*/
NTCPConnection inboundEstablished(NTCPConnection con) {
_context.statManager().addRateData("ntcp.inboundEstablished", 1);
Hash peer = con.getRemotePeer().calculateHash();
markReachable(peer, true);
// _context.banlist().unbanlistRouter(con.getRemotePeer().calculateHash());
NTCPConnection old;
synchronized (_conLock) {
old = _conByIdent.put(peer, con);
}
if (con.isIPv6()) {
_lastInboundIPv6 = con.getCreated();
_context.statManager().addRateData("ntcp.inboundIPv6Conn", 1);
} else {
_lastInboundIPv4 = con.getCreated();
_context.statManager().addRateData("ntcp.inboundIPv4Conn", 1);
}
return old;
}
Aggregations