use of net.i2p.router.OutNetMessage in project i2p.i2p by i2p.
the class TestJob method runJob.
public void runJob() {
if (_pool == null || !_pool.isAlive())
return;
long lag = getContext().jobQueue().getMaxLag();
if (lag > 3000) {
if (_log.shouldLog(Log.WARN))
_log.warn("Deferring test of " + _cfg + " due to job lag = " + lag);
getContext().statManager().addRateData("tunnel.testAborted", _cfg.getLength(), 0);
scheduleRetest();
return;
}
if (getContext().router().gracefulShutdownInProgress())
// don't reschedule
return;
_found = false;
// note: testing with exploratory tunnels always, even if the tested tunnel
// is a client tunnel (per _cfg.getDestination())
// should we test with the tunnel that we exposed the creation with?
// (accessible as _cfg.getPairedTunnel())
_replyTunnel = null;
_outTunnel = null;
if (_cfg.isInbound()) {
_replyTunnel = _cfg;
// TODO if testing is re-enabled, pick closest to far end
_outTunnel = getContext().tunnelManager().selectOutboundTunnel();
_otherTunnel = (PooledTunnelCreatorConfig) _outTunnel;
} else {
// TODO if testing is re-enabled, pick closest to far end
_replyTunnel = getContext().tunnelManager().selectInboundTunnel();
_outTunnel = _cfg;
_otherTunnel = (PooledTunnelCreatorConfig) _replyTunnel;
}
if ((_replyTunnel == null) || (_outTunnel == null)) {
if (_log.shouldLog(Log.WARN))
_log.warn("Insufficient tunnels to test " + _cfg + " with: " + _replyTunnel + " / " + _outTunnel);
getContext().statManager().addRateData("tunnel.testAborted", _cfg.getLength(), 0);
scheduleRetest();
} else {
int testPeriod = getTestPeriod();
long testExpiration = getContext().clock().now() + testPeriod;
DeliveryStatusMessage m = new DeliveryStatusMessage(getContext());
m.setArrival(getContext().clock().now());
m.setMessageExpiration(testExpiration);
m.setMessageId(getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE));
ReplySelector sel = new ReplySelector(getContext(), m.getMessageId(), testExpiration);
OnTestReply onReply = new OnTestReply(getContext());
OnTestTimeout onTimeout = new OnTestTimeout(getContext());
OutNetMessage msg = getContext().messageRegistry().registerPending(sel, onReply, onTimeout);
onReply.setSentMessage(msg);
sendTest(m);
}
}
use of net.i2p.router.OutNetMessage in project i2p.i2p by i2p.
the class InboundGatewayReceiver method receiveEncrypted.
public long receiveEncrypted(byte[] encrypted, boolean alreadySearched) {
if (!alreadySearched)
_config.incrementProcessedMessages();
if (_target == null) {
_target = _context.netDb().lookupRouterInfoLocally(_config.getSendTo());
if (_target == null) {
// It should be rare to forget the router info for the next peer
ReceiveJob j = null;
if (alreadySearched)
_context.statManager().addRateData("tunnel.inboundLookupSuccess", 0);
else
j = new ReceiveJob(_context, encrypted);
_context.netDb().lookupRouterInfo(_config.getSendTo(), j, j, MAX_LOOKUP_TIME);
return -1;
}
}
if (alreadySearched)
_context.statManager().addRateData("tunnel.inboundLookupSuccess", 1);
// We do this before the preprocessor now (i.e. before fragmentation)
// if (_context.tunnelDispatcher().shouldDropParticipatingMessage("IBGW", encrypted.length))
// return -1;
// _config.incrementSentMessages();
_context.bandwidthLimiter().sentParticipatingMessage(1024);
TunnelDataMessage msg = new TunnelDataMessage(_context);
msg.setData(encrypted);
msg.setTunnelId(_config.getSendTunnel());
OutNetMessage out = new OutNetMessage(_context, msg, msg.getMessageExpiration(), PRIORITY, _target);
_context.outNetMessagePool().add(out);
return msg.getUniqueId();
}
use of net.i2p.router.OutNetMessage in project i2p.i2p by i2p.
the class NTCPConnection method enqueueInfoMessage.
/**
* Inject a DatabaseStoreMessage with our RouterInfo
*/
public void enqueueInfoMessage() {
int priority = INFO_PRIORITY;
// }
if (_log.shouldLog(Log.INFO))
_log.info("SENDING INFO message pri. " + priority + ": " + toString());
DatabaseStoreMessage dsm = new DatabaseStoreMessage(_context);
dsm.setEntry(_context.router().getRouterInfo());
// We are injecting directly, so we can use a null target.
OutNetMessage infoMsg = new OutNetMessage(_context, dsm, _context.clock().now() + 10 * 1000, priority, null);
infoMsg.beginSend();
// _context.statManager().addRateData("ntcp.infoMessageEnqueued", 1);
send(infoMsg);
}
use of net.i2p.router.OutNetMessage in project i2p.i2p by i2p.
the class NTCPConnection method prepareNextWriteFast.
/**
******** nobody's tried this one in years
* private void prepareNextWriteSmall() {
* if (_log.shouldLog(Log.DEBUG))
* _log.debug("prepare next write w/ isInbound? " + _isInbound + " established? " + _established);
* if (!_isInbound && !_established) {
* if (_establishState == null) {
* _establishState = new EstablishState(_context, _transport, this);
* _establishState.prepareOutbound();
* } else {
* if (_log.shouldLog(Log.DEBUG))
* _log.debug("prepare next write, but we have already prepared the first outbound and we are not yet established..." + toString());
* }
* return;
* }
*
* if (_nextMetaTime <= System.currentTimeMillis()) {
* sendMeta();
* _nextMetaTime = System.currentTimeMillis() + _context.random().nextInt(META_FREQUENCY);
* }
*
* OutNetMessage msg = null;
* synchronized (_outbound) {
* if (_currentOutbound != null) {
* if (_log.shouldLog(Log.WARN))
* _log.warn("attempt for multiple outbound messages with " + System.identityHashCode(_currentOutbound) + " already waiting and " + _outbound.size() + " queued");
* return;
* }
* //throw new RuntimeException("We should not be preparing a write while we still have one pending");
* if (!_outbound.isEmpty()) {
* msg = (OutNetMessage)_outbound.remove(0);
* _currentOutbound = msg;
* } else {
* return;
* }
* }
*
* msg.beginTransmission();
* msg.beginPrepare();
* long begin = System.currentTimeMillis();
* // prepare the message as a binary array, then encrypt it w/ a checksum
* // and add it to the _writeBufs
* // E(sizeof(data)+data+pad+crc, sessionKey, prevEncrypted)
* I2NPMessage m = msg.getMessage();
* int sz = m.getMessageSize();
* int min = 2 + sz + 4;
* int rem = min % 16;
* int padding = 0;
* if (rem > 0)
* padding = 16 - rem;
*
* byte unencrypted[] = new byte[min+padding];
* byte base[] = m.toByteArray();
* DataHelper.toLong(unencrypted, 0, 2, sz);
* System.arraycopy(base, 0, unencrypted, 2, base.length);
* if (padding > 0) {
* byte pad[] = new byte[padding];
* _context.random().nextBytes(pad);
* System.arraycopy(pad, 0, unencrypted, 2+sz, padding);
* }
*
* long serialized = System.currentTimeMillis();
* Adler32 crc = new Adler32();
* crc.reset();
* crc.update(unencrypted, 0, unencrypted.length-4);
* long val = crc.getValue();
* DataHelper.toLong(unencrypted, unencrypted.length-4, 4, val);
*
* if (_log.shouldLog(Log.DEBUG))
* _log.debug("Outbound message " + _messagesWritten + " has crc " + val);
*
* long crced = System.currentTimeMillis();
* byte encrypted[] = new byte[unencrypted.length];
* _context.aes().encrypt(unencrypted, 0, encrypted, 0, _sessionKey, _prevWriteEnd, 0, unencrypted.length);
* System.arraycopy(encrypted, encrypted.length-16, _prevWriteEnd, 0, _prevWriteEnd.length);
* long encryptedTime = System.currentTimeMillis();
* msg.prepared();
* if (_log.shouldLog(Log.DEBUG)) {
* _log.debug("prepared outbound " + System.identityHashCode(msg)
* + " serialize=" + (serialized-begin)
* + " crc=" + (crced-serialized)
* + " encrypted=" + (encryptedTime-crced)
* + " prepared=" + (encryptedTime-begin));
* }
* //if (_log.shouldLog(Log.DEBUG))
* // _log.debug("Encrypting " + msg + " [" + System.identityHashCode(msg) + "] crc=" + crc.getValue() + "\nas: "
* // + Base64.encode(encrypted, 0, 16) + "...\ndecrypted: "
* // + Base64.encode(unencrypted, 0, 16) + "..." + "\nIV=" + Base64.encode(_prevWriteEnd, 0, 16));
* _transport.getPumper().wantsWrite(this, encrypted);
*
* // for every 6-12 hours that we are connected to a peer, send them
* // our updated netDb info (they may not accept it and instead query
* // the floodfill netDb servers, but they may...)
* if (_nextInfoTime <= System.currentTimeMillis()) {
* enqueueInfoMessage();
* _nextInfoTime = System.currentTimeMillis() + (INFO_FREQUENCY / 2) + _context.random().nextInt(INFO_FREQUENCY);
* }
* }
*********
*/
/**
* prepare the next i2np message for transmission. this should be run from
* the Writer thread pool.
*
* Caller must synchronize.
* @param buf a PrepBuffer to use as scratch space
*/
private void prepareNextWriteFast(PrepBuffer buf) {
if (_closed.get())
return;
// enqueueInfoMessage() is called at end of IB establishment.
if (!isEstablished()) {
return;
}
long now = _context.clock().now();
if (_nextMetaTime <= now) {
sendMeta();
_nextMetaTime = now + (META_FREQUENCY / 2) + _context.random().nextInt(META_FREQUENCY / 2);
}
OutNetMessage msg = null;
// Todo: figure out how to remove the synchronization
synchronized (_outbound) {
if (_currentOutbound != null) {
if (_log.shouldLog(Log.INFO))
_log.info("attempt for multiple outbound messages with " + System.identityHashCode(_currentOutbound) + " already waiting and " + _outbound.size() + " queued");
return;
}
/**
**
* //throw new RuntimeException("We should not be preparing a write while we still have one pending");
* if (queueTime() > 3*1000) { // don't stall low-priority messages
***
*/
msg = _outbound.poll();
if (msg == null)
return;
/**
**
* } else {
* // FIXME
* // This is a linear search to implement a priority queue, O(n**2)
* // Also race with unsynchronized removal in close() above
* // Either implement a real (concurrent?) priority queue or just comment out all of this,
* // as it isn't clear how effective the priorities on a per-connection basis are.
* int slot = 0; // only for logging
* Iterator<OutNetMessage> it = _outbound.iterator();
* for (int i = 0; it.hasNext() && i < 75; i++) { //arbitrary bound
* OutNetMessage mmsg = it.next();
* if (msg == null || mmsg.getPriority() > msg.getPriority()) {
* msg = mmsg;
* slot = i;
* }
* }
* if (msg == null)
* return;
* // if (_outbound.indexOf(msg) > 0)
* // _log.debug("Priority message sent, pri = " + msg.getPriority() + " pos = " + _outbound.indexOf(msg) + "/" +_outbound.size());
* if (_log.shouldLog(Log.INFO))
* _log.info("Type " + msg.getMessage().getType() + " pri " + msg.getPriority() + " slot " + slot);
* boolean removed = _outbound.remove(msg);
* if ((!removed) && _log.shouldLog(Log.WARN))
* _log.warn("Already removed??? " + msg.getMessage().getType());
* }
***
*/
_currentOutbound = msg;
}
// long begin = System.currentTimeMillis();
bufferedPrepare(msg, buf);
_context.aes().encrypt(buf.unencrypted, 0, buf.encrypted, 0, _sessionKey, _prevWriteEnd, 0, buf.unencryptedLength);
System.arraycopy(buf.encrypted, buf.encrypted.length - 16, _prevWriteEnd, 0, _prevWriteEnd.length);
// long encryptedTime = System.currentTimeMillis();
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Encrypting " + msg + " [" + System.identityHashCode(msg) + "] crc=" + crc.getValue() + "\nas: "
// + Base64.encode(encrypted, 0, 16) + "...\ndecrypted: "
// + Base64.encode(unencrypted, 0, 16) + "..." + "\nIV=" + Base64.encode(_prevWriteEnd, 0, 16));
_transport.getPumper().wantsWrite(this, buf.encrypted);
// the floodfill netDb servers, but they may...)
if (_nextInfoTime <= now) {
// perhaps this should check to see if we are bw throttled, etc?
enqueueInfoMessage();
_nextInfoTime = now + (INFO_FREQUENCY / 2) + _context.random().nextInt(INFO_FREQUENCY);
}
}
use of net.i2p.router.OutNetMessage 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();
}
}
*/
}
}
Aggregations