/** connect to the given destination */ I2PSocket connect(PeerID peer) throws IOException { I2PSocketManager mgr = _manager; if (mgr == null) throw new IOException("No socket manager"); Destination addr = peer.getAddress(); if (addr == null) throw new IOException("Null address"); if (addr.equals(getMyDestination())) throw new IOException("Attempt to connect to myself"); Hash dest = addr.calculateHash(); if (_banlist.contains(dest)) throw new IOException("Not trying to contact " + dest.toBase64() + ", as they are banlisted"); try { // TODO opts.setPort(xxx); connect(addr, opts) // DHT moved above 6881 in 0.9.9 I2PSocket rv = _manager.connect(addr); if (rv != null) _banlist.remove(dest); return rv; } catch (I2PException ie) { _banlist.add(dest); _context.simpleScheduler().addEvent(new Unbanlist(dest), 10 * 60 * 1000); IOException ioe = new IOException("Unable to reach the peer " + peer); ioe.initCause(ie); throw ioe; } }
/** * 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, or null if there was a timeout or the handler was shut down */ public Connection accept(long timeoutMs) { 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())) return null; if (!_active) { // fail all the ones we had queued up while (true) { Packet packet = _synQueue.poll(); // fails immediately if empty if (packet == null || packet.getOptionalDelay() == PoisonPacket.POISON_MAX_DELAY_REQUEST) break; sendReset(packet); } return null; } 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 { syn = _synQueue.take(); // waits forever } catch (InterruptedException ie) { } // { break;} } else { long remaining = expiration - _context.clock().now(); // (dont think this applies anymore for LinkedBlockingQueue) // BUGFIX // The specified amount of real time has elapsed, more or less. // If timeout is zero, however, then real time is not taken into consideration // and the thread simply waits until notified. if (remaining < 1) break; try { syn = _synQueue.poll(remaining, TimeUnit.MILLISECONDS); // waits the specified time max } catch (InterruptedException ie) { } break; } } if (syn != null) { if (syn.getOptionalDelay() == PoisonPacket.POISON_MAX_DELAY_REQUEST) return null; // deal with forged / invalid syn packets in _manager.receiveConnection() // 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) { // His ID not guaranteed to be unique to us, but probably is... // 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... } }