use of net.i2p.client.streaming.RouterRestartException in project i2p.i2p by i2p.
the class ConnectionHandler method accept.
/**
* Receive an incoming connection (built from a received SYN)
* Non-SYN packets with a zero SendStreamID may also be queued here so
* that they don't get thrown away while the SYN packet before it is queued.
*
* @param timeoutMs max amount of time to wait for a connection (if less
* than 1ms, wait indefinitely)
* @return connection received. Prior to 0.9.17, or null if there was a timeout or the
* handler was shut down. As of 0.9.17, never null.
* @throws RouterRestartException (extends I2PException) if the router is apparently restarting, since 0.9.34
* @throws ConnectException since 0.9.17, returned null before;
* if the I2PServerSocket is closed, or if interrupted.
* @throws SocketTimeoutException since 0.9.17, returned null before;
* if a timeout was previously set with setSoTimeout and the timeout has been reached.
*/
public Connection accept(long timeoutMs) throws RouterRestartException, ConnectException, SocketTimeoutException {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Accept(" + timeoutMs + ") called");
long expiration = timeoutMs + _context.clock().now();
while (true) {
if ((timeoutMs > 0) && (expiration < _context.clock().now()))
throw new SocketTimeoutException("accept() timed out");
if (!_active) {
// fail all the ones we had queued up
while (true) {
// fails immediately if empty
Packet packet = _synQueue.poll();
if (packet == null || packet.getOptionalDelay() == PoisonPacket.POISON_MAX_DELAY_REQUEST)
break;
sendReset(packet);
}
if (_restartPending)
throw new RouterRestartException();
throw new ConnectException("ServerSocket closed");
}
Packet syn = null;
while (_active && syn == null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Accept(" + timeoutMs + "): active=" + _active + " queue: " + _synQueue.size());
if (timeoutMs <= 0) {
try {
// waits forever
syn = _synQueue.take();
} catch (InterruptedException ie) {
ConnectException ce = new ConnectException("Interrupted accept()");
ce.initCause(ie);
throw ce;
}
} else {
long remaining = expiration - _context.clock().now();
// and the thread simply waits until notified.
if (remaining < 1)
break;
try {
// waits the specified time max
syn = _synQueue.poll(remaining, TimeUnit.MILLISECONDS);
} catch (InterruptedException ie) {
ConnectException ce = new ConnectException("Interrupted accept()");
ce.initCause(ie);
throw ce;
}
break;
}
}
if (syn != null) {
if (syn.getOptionalDelay() == PoisonPacket.POISON_MAX_DELAY_REQUEST) {
if (_restartPending)
throw new RouterRestartException();
throw new ConnectException("ServerSocket closed");
}
// Handle both SYN and non-SYN packets in the queue
if (syn.isFlagSet(Packet.FLAG_SYNCHRONIZE)) {
// We are single-threaded here, so this is
// a good place to check for dup SYNs and drop them
Destination from = syn.getOptionalFrom();
if (from == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("Dropping SYN packet with no FROM: " + syn);
// drop it
continue;
}
Connection oldcon = _manager.getConnectionByOutboundId(syn.getReceiveStreamId());
if (oldcon != null) {
// only drop it on a destination match too
if (from.equals(oldcon.getRemotePeer())) {
if (_log.shouldLog(Log.WARN))
_log.warn("Dropping dup SYN: " + syn);
continue;
}
}
Connection con = _manager.receiveConnection(syn);
if (con != null)
return con;
} else {
reReceivePacket(syn);
// ... and keep looping
}
}
// keep looping...
}
}
use of net.i2p.client.streaming.RouterRestartException in project i2p.i2p by i2p.
the class I2PTunnelServer method run.
/**
* If usePool is set, this starts the executor pool.
* Then, do the accept() loop, and either
* hands each I2P socket to the executor or runs it in-line.
*/
public void run() {
i2pss = sockMgr.getServerSocket();
if (_log.shouldLog(Log.WARN)) {
if (_usePool)
_log.warn("Starting executor with " + getHandlerCount() + " threads max");
else
_log.warn("Threads disabled, running blockingHandles inline");
}
if (_usePool) {
_executor = new CustomThreadPoolExecutor(getHandlerCount(), "ServerHandler pool " + remoteHost + ':' + remotePort);
}
TunnelControllerGroup tcg = TunnelControllerGroup.getInstance();
if (tcg != null) {
_clientExecutor = tcg.getClientExecutor();
} else {
// Fallback in case TCG.getInstance() is null, never instantiated
// and we were not started by TCG.
// Maybe a plugin loaded before TCG? Should be rare.
// Never shut down.
_clientExecutor = new TunnelControllerGroup.CustomThreadPoolExecutor();
}
I2PSocket i2ps = null;
while (open) {
try {
i2ps = null;
I2PServerSocket ci2pss = i2pss;
if (ci2pss == null)
throw new I2PException("I2PServerSocket closed");
// returns non-null as of 0.9.17
i2ps = ci2pss.accept();
if (_usePool) {
try {
_executor.execute(new Handler(i2ps));
} catch (RejectedExecutionException ree) {
try {
i2ps.reset();
} catch (IOException ioe) {
}
if (open)
_log.logAlways(Log.WARN, "ServerHandler queue full, dropping incoming connection to " + remoteHost + ':' + remotePort + "; increase server max threads or " + PROP_HANDLER_COUNT + "; current is " + getHandlerCount());
}
} else {
// use only for standard servers that can't get slowlorissed! Not for http or irc
blockingHandle(i2ps);
}
} catch (RouterRestartException rre) {
// Delay and loop if router is soft restarting
_log.logAlways(Log.WARN, "Waiting for router restart");
if (i2ps != null)
try {
i2ps.close();
} catch (IOException ioe) {
}
try {
Thread.sleep(2 * 60 * 1000);
} catch (InterruptedException ie) {
}
// This should be the same as before, but we have to call getServerSocket()
// so sockMgr will call ConnectionManager.setAllowIncomingConnections(true) again
i2pss = sockMgr.getServerSocket();
} catch (I2PException ipe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting - KILLING THE TUNNEL SERVER", ipe);
open = false;
if (i2ps != null)
try {
i2ps.close();
} catch (IOException ioe) {
}
break;
} catch (ConnectException ce) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting", ce);
open = false;
if (i2ps != null)
try {
i2ps.close();
} catch (IOException ioe) {
}
break;
} catch (SocketTimeoutException ste) {
// ignored, we never set the timeout
if (i2ps != null)
try {
i2ps.close();
} catch (IOException ioe) {
}
} catch (RuntimeException e) {
// streaming borkage
if (_log.shouldLog(Log.ERROR))
_log.error("Uncaught exception accepting", e);
if (i2ps != null)
try {
i2ps.close();
} catch (IOException ioe) {
}
// not killing the server..
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
if (_executor != null && !_executor.isTerminating() && !_executor.isShutdown())
_executor.shutdownNow();
}
Aggregations