use of net.i2p.data.router.RouterIdentity in project i2p.i2p by i2p.
the class EstablishmentManager method handleInbound.
/**
* Drive through the inbound establishment states, adjusting one of them
* as necessary. Called from Establisher thread only.
* @return next requested time or -1
*/
private long handleInbound() {
long now = _context.clock().now();
long nextSendTime = -1;
InboundEstablishState inboundState = null;
boolean expired = false;
for (Iterator<InboundEstablishState> iter = _inboundStates.values().iterator(); iter.hasNext(); ) {
InboundEstablishState cur = iter.next();
if (cur.getState() == IB_STATE_CONFIRMED_COMPLETELY) {
// completely received (though the signature may be invalid)
iter.remove();
inboundState = cur;
// _log.debug("Removing completely confirmed inbound state");
break;
} else if (cur.getLifetime() > MAX_IB_ESTABLISH_TIME) {
// took too long
iter.remove();
inboundState = cur;
// _context.statManager().addRateData("udp.inboundEstablishFailedState", cur.getState(), cur.getLifetime());
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Removing expired inbound state");
expired = true;
break;
} else if (cur.getState() == IB_STATE_FAILED) {
iter.remove();
// _context.statManager().addRateData("udp.inboundEstablishFailedState", cur.getState(), cur.getLifetime());
} else {
if (cur.getNextSendTime() <= now) {
// our turn...
inboundState = cur;
// _log.debug("Processing inbound that wanted activity");
break;
} else {
// nothin to do but wait for them to send us
// stuff, so lets move on to the next one being
// established
long when = -1;
if (cur.getNextSendTime() <= 0) {
when = cur.getEstablishBeginTime() + MAX_IB_ESTABLISH_TIME;
} else {
when = cur.getNextSendTime();
}
if (when < nextSendTime)
nextSendTime = when;
}
}
}
if (inboundState != null) {
// _log.debug("Processing for inbound: " + inboundState);
synchronized (inboundState) {
switch(inboundState.getState()) {
case IB_STATE_REQUEST_RECEIVED:
if (expired)
processExpired(inboundState);
else
sendCreated(inboundState);
break;
// fallthrough
case IB_STATE_CREATED_SENT:
case IB_STATE_CONFIRMED_PARTIALLY:
if (expired) {
sendDestroy(inboundState);
processExpired(inboundState);
} else if (inboundState.getNextSendTime() <= now) {
sendCreated(inboundState);
}
break;
case IB_STATE_CONFIRMED_COMPLETELY:
RouterIdentity remote = inboundState.getConfirmedIdentity();
if (remote != null) {
if (_context.banlist().isBanlistedForever(remote.calculateHash())) {
if (_log.shouldLog(Log.WARN))
_log.warn("Dropping inbound connection from permanently banlisted peer: " + remote.calculateHash());
// So next time we will not accept the con, rather than doing the whole handshake
_context.blocklist().add(inboundState.getSentIP());
inboundState.fail();
processExpired(inboundState);
} else {
handleCompletelyEstablished(inboundState);
}
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("confirmed with invalid? " + inboundState);
inboundState.fail();
processExpired(inboundState);
}
break;
// fall through
case IB_STATE_COMPLETE:
case // leak here if fail() was called in IES???
IB_STATE_FAILED:
// already removed;
break;
case IB_STATE_UNKNOWN:
// Can't happen, always call receiveSessionRequest() before putting in map
if (_log.shouldLog(Log.ERROR))
_log.error("hrm, state is unknown for " + inboundState);
}
}
// ok, since there was something to do, we want to loop again
nextSendTime = now;
}
return nextSendTime;
}
use of net.i2p.data.router.RouterIdentity in project i2p.i2p by i2p.
the class InboundEstablishState method buildIdentity.
/**
* Construct Alice's RouterIdentity.
* Must have received all fragments.
* Sets _receivedUnconfirmedIdentity, unless invalid.
*
* Caller must synch on this.
*
* @since 0.9.16 was in verifyIdentity()
*/
private void buildIdentity() {
if (_receivedUnconfirmedIdentity != null)
// dup pkt?
return;
int frags = _receivedIdentity.length;
byte[] ident;
if (frags > 1) {
int identSize = 0;
for (int i = 0; i < _receivedIdentity.length; i++) identSize += _receivedIdentity[i].length;
ident = new byte[identSize];
int off = 0;
for (int i = 0; i < _receivedIdentity.length; i++) {
int len = _receivedIdentity[i].length;
System.arraycopy(_receivedIdentity[i], 0, ident, off, len);
off += len;
}
} else {
// no need to copy
ident = _receivedIdentity[0];
}
ByteArrayInputStream in = new ByteArrayInputStream(ident);
RouterIdentity peer = new RouterIdentity();
try {
peer.readBytes(in);
_receivedUnconfirmedIdentity = peer;
} catch (DataFormatException dfe) {
if (_log.shouldLog(Log.WARN))
_log.warn("Improperly formatted yet fully received ident", dfe);
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
_log.warn("Improperly formatted yet fully received ident", ioe);
}
}
use of net.i2p.data.router.RouterIdentity in project i2p.i2p by i2p.
the class NTCPTransport method outboundMessageReady.
protected void outboundMessageReady() {
OutNetMessage msg = getNextMessage();
if (msg != null) {
RouterInfo target = msg.getTarget();
RouterIdentity ident = target.getIdentity();
Hash ih = ident.calculateHash();
NTCPConnection con = null;
boolean isNew = false;
boolean fail = false;
synchronized (_conLock) {
con = _conByIdent.get(ih);
if (con == null) {
isNew = true;
RouterAddress addr = getTargetAddress(target);
if (addr != null) {
con = new NTCPConnection(_context, this, ident, addr);
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Send on a new con: " + con + " at " + addr + " for " + ih);
// Note that outbound conns go in the map BEFORE establishment
_conByIdent.put(ih, con);
} else {
// race, RI changed out from under us
// call afterSend below outside of conLock
fail = true;
}
}
}
if (fail) {
// race, RI changed out from under us, maybe SSU can handle it
if (_log.shouldLog(Log.WARN))
_log.warn("we bid on a peer who doesn't have an ntcp address? " + target);
afterSend(msg, false);
return;
}
if (isNew) {
// doesn't do anything yet, just enqueues it
con.send(msg);
// As of 0.9.12, don't send our info if the first message is
// doing the same (common when connecting to a floodfill).
// Also, put the info message after whatever we are trying to send
// (it's a priority queue anyway and the info is low priority)
// Prior to 0.9.12, Bob would not send his RI unless he had ours,
// but that's fixed in 0.9.12.
boolean shouldSkipInfo = false;
I2NPMessage m = msg.getMessage();
if (m.getType() == DatabaseStoreMessage.MESSAGE_TYPE) {
DatabaseStoreMessage dsm = (DatabaseStoreMessage) m;
if (dsm.getKey().equals(_context.routerHash())) {
shouldSkipInfo = true;
}
}
if (!shouldSkipInfo) {
con.enqueueInfoMessage();
} else if (_log.shouldLog(Log.INFO)) {
_log.info("SKIPPING INFO message: " + con);
}
try {
SocketChannel channel = SocketChannel.open();
con.setChannel(channel);
channel.configureBlocking(false);
_pumper.registerConnect(con);
con.getEstablishState().prepareOutbound();
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error opening a channel", ioe);
_context.statManager().addRateData("ntcp.outboundFailedIOEImmediate", 1);
con.close();
}
} else {
con.send(msg);
}
/*
NTCPConnection con = getCon(ident);
remove the race here
if (con != null) {
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Send on an existing con: " + con);
con.send(msg);
} else {
RouterAddress addr = msg.getTarget().getTargetAddress(STYLE);
if (addr != null) {
NTCPAddress naddr = new NTCPAddress(addr);
con = new NTCPConnection(_context, this, ident, naddr);
Hash ih = ident.calculateHash();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Send on a new con: " + con + " at " + addr + " for " + ih.toBase64());
NTCPConnection old = null;
synchronized (_conLock) {
old = (NTCPConnection)_conByIdent.put(ih, con);
}
if (old != null) {
if (_log.shouldLog(Log.WARN))
_log.warn("Multiple connections on out ready, closing " + old + " and keeping " + con);
old.close();
}
con.enqueueInfoMessage(); // enqueues a netDb store of our own info
con.send(msg); // doesn't do anything yet, just enqueues it
try {
SocketChannel channel = SocketChannel.open();
con.setChannel(channel);
channel.configureBlocking(false);
_pumper.registerConnect(con);
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error opening a channel", ioe);
con.close();
}
} else {
con.close();
}
}
*/
}
}
use of net.i2p.data.router.RouterIdentity in project i2p.i2p by i2p.
the class TransportManager method getNextBid.
TransportBid getNextBid(OutNetMessage msg) {
int unreachableTransports = 0;
Hash peer = msg.getTarget().getIdentity().calculateHash();
Set<String> failedTransports = msg.getFailedTransports();
TransportBid rv = null;
for (Transport t : _transports.values()) {
if (t.isUnreachable(peer)) {
unreachableTransports++;
// this keeps GetBids() from banlisting for "no common transports"
// right after we banlisted for "unreachable on any transport" below...
msg.transportFailed(t.getStyle());
continue;
}
if (failedTransports.contains(t.getStyle())) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Skipping transport " + t.getStyle() + " as it already failed");
continue;
}
// we always want to try all transports, in case there is a faster bidirectional one
// already connected (e.g. peer only has a public PHTTP address, but they've connected
// to us via TCP, send via TCP)
TransportBid bid = t.bid(msg.getTarget(), msg.getMessageSize());
if (bid != null) {
if (bid.getLatencyMs() == TransportBid.TRANSIENT_FAIL)
// this keeps GetBids() from banlisting for "no common transports"
msg.transportFailed(t.getStyle());
else if ((rv == null) || (rv.getLatencyMs() > bid.getLatencyMs()))
rv = bid;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Transport " + t.getStyle() + " bid: " + bid + " currently winning? " + (rv == bid) + " (winning latency: " + rv.getLatencyMs() + " / " + rv + ")");
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Transport " + t.getStyle() + " did not produce a bid");
if (t.isUnreachable(peer))
unreachableTransports++;
}
}
if (unreachableTransports >= _transports.size()) {
if (msg.getTarget().getIdentity().getSigningPublicKey().getType() == null) {
// we don't support his crypto
_context.statManager().addRateData("transport.banlistOnUnsupportedSigType", 1);
_context.banlist().banlistRouterForever(peer, _x("Unsupported signature type"));
} else if (unreachableTransports >= _transports.size() && countActivePeers() > 0) {
// Don't banlist if we aren't talking to anybody, as we may have a network connection issue
boolean incompat = false;
RouterInfo us = _context.router().getRouterInfo();
if (us != null) {
RouterIdentity id = us.getIdentity();
if (id.getSigType() != SigType.DSA_SHA1) {
String v = msg.getTarget().getVersion();
// NTCP is earlier than SSU, use that one
if (VersionComparator.comp(v, NTCPTransport.MIN_SIGTYPE_VERSION) < 0)
incompat = true;
}
}
if (incompat) {
// they don't support our crypto
_context.statManager().addRateData("transport.banlistOnUnsupportedSigType", 1);
_context.banlist().banlistRouter(peer, _x("No support for our signature type"), null, null, _context.clock().now() + SIGTYPE_BANLIST_DURATION);
} else {
_context.statManager().addRateData("transport.banlistOnUnreachable", msg.getLifetime(), msg.getLifetime());
_context.banlist().banlistRouter(peer, _x("Unreachable on any transport"));
}
}
} else if (rv == null) {
_context.statManager().addRateData("transport.noBidsYetNotAllUnreachable", unreachableTransports, msg.getLifetime());
}
return rv;
}
use of net.i2p.data.router.RouterIdentity in project i2p.i2p by i2p.
the class LoadRouterInfoJob method readKeyData.
/**
* @param rkf1 in router.keys format, tried second
* @param rkf2 in eepPriv.dat format, tried first
* @return non-null, throws IOE if neither exisits
* @since 0.9.16
*/
public static KeyData readKeyData(File rkf1, File rkf2) throws DataFormatException, IOException {
RouterIdentity ri;
PrivateKey privkey;
SigningPrivateKey signingPrivKey;
if (rkf2.exists()) {
RouterPrivateKeyFile pkf = new RouterPrivateKeyFile(rkf2);
ri = pkf.getRouterIdentity();
if (!pkf.validateKeyPairs())
throw new DataFormatException("Key pairs invalid");
privkey = pkf.getPrivKey();
signingPrivKey = pkf.getSigningPrivKey();
} else {
InputStream fis = null;
try {
fis = new BufferedInputStream(new FileInputStream(rkf1));
privkey = new PrivateKey();
privkey.readBytes(fis);
signingPrivKey = new SigningPrivateKey();
signingPrivKey.readBytes(fis);
PublicKey pubkey = new PublicKey();
pubkey.readBytes(fis);
SigningPublicKey signingPubKey = new SigningPublicKey();
signingPubKey.readBytes(fis);
// validate
try {
if (!pubkey.equals(KeyGenerator.getPublicKey(privkey)))
throw new DataFormatException("Key pairs invalid");
if (!signingPubKey.equals(KeyGenerator.getSigningPublicKey(signingPrivKey)))
throw new DataFormatException("Key pairs invalid");
} catch (IllegalArgumentException iae) {
throw new DataFormatException("Key pairs invalid", iae);
}
ri = new RouterIdentity();
ri.setPublicKey(pubkey);
ri.setSigningPublicKey(signingPubKey);
ri.setCertificate(Certificate.NULL_CERT);
} finally {
if (fis != null)
try {
fis.close();
} catch (IOException ioe) {
}
}
}
return new KeyData(ri, privkey, signingPrivKey);
}
Aggregations