private void x_startTorrent() { boolean ok = _util.connect(); if (!ok) fatal("Unable to connect to I2P"); if (coordinator == null) { I2PServerSocket serversocket = _util.getServerSocket(); if (serversocket == null) fatal("Unable to listen for I2P connections"); else { Destination d = serversocket.getManager().getSession().getMyDestination(); if (_log.shouldLog(Log.INFO)) _log.info( "Listening on I2P destination " + d.toBase64() + " / " + d.calculateHash().toBase64()); } if (_log.shouldLog(Log.INFO)) _log.info("Starting PeerCoordinator, ConnectionAcceptor, and TrackerClient"); activity = "Collecting pieces"; coordinator = new PeerCoordinator(_util, id, infoHash, meta, storage, this, this); coordinator.setUploaded(savedUploaded); if (_peerCoordinatorSet != null) { // multitorrent _peerCoordinatorSet.add(coordinator); } else { // single torrent acceptor = new ConnectionAcceptor(_util, new PeerAcceptor(coordinator)); } // TODO pass saved closest DHT nodes to the tracker? or direct to the coordinator? trackerclient = new TrackerClient(_util, meta, additionalTrackerURL, coordinator, this); } // ensure acceptor is running when in multitorrent if (_peerCoordinatorSet != null && acceptor != null) { acceptor.startAccepting(); } stopped = false; if (coordinator.halted()) { coordinator.restart(); if (_peerCoordinatorSet != null) _peerCoordinatorSet.add(coordinator); } if (!trackerclient.started()) { trackerclient.start(); } else if (trackerclient.halted()) { if (storage != null) { try { storage.reopen(); } catch (IOException ioe) { try { storage.close(); } catch (IOException ioee) { ioee.printStackTrace(); } fatal("Could not reopen storage", ioe); } } trackerclient.start(); } else { if (_log.shouldLog(Log.INFO)) _log.info("NOT starting TrackerClient???"); } }
/** * Runs the connection to the other peer. This method does not return until the connection is * terminated. * * <p>When the connection is correctly started the connected() method of the given PeerListener is * called. If the connection ends or the connection could not be setup correctly the * disconnected() method is called. * * <p>If the given BitField is non-null it is send to the peer as first message. */ public void runConnection( I2PSnarkUtil util, PeerListener listener, BitField bitfield, MagnetState mState) { if (state != null) throw new IllegalStateException("Peer already started"); if (_log.shouldLog(Log.DEBUG)) _log.debug("Running connection to " + peerID.toString(), new Exception("connecting")); try { // Do we need to handshake? if (din == null) { // Outgoing connection sock = util.connect(peerID); if (_log.shouldLog(Log.DEBUG)) _log.debug("Connected to " + peerID + ": " + sock); if ((sock == null) || (sock.isClosed())) { throw new IOException("Unable to reach " + peerID); } InputStream in = sock.getInputStream(); OutputStream out = sock.getOutputStream(); byte[] id = handshake(in, out); byte[] expected_id = peerID.getID(); if (expected_id == null) { peerID.setID(id); } else if (Arrays.equals(expected_id, id)) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Handshake got matching IDs with " + toString()); } else { throw new IOException( "Unexpected peerID '" + PeerID.idencode(id) + "' expected '" + PeerID.idencode(expected_id) + "'"); } } else { // Incoming connection if (_log.shouldLog(Log.DEBUG)) _log.debug("Already have din [" + sock + "] with " + toString()); } // bad idea? if (metainfo == null && (options & OPTION_EXTENSION) == 0) { if (_log.shouldLog(Log.INFO)) _log.info("Peer does not support extensions and we need metainfo, dropping"); throw new IOException("Peer does not support extensions and we need metainfo, dropping"); } PeerConnectionIn in = new PeerConnectionIn(this, din); PeerConnectionOut out = new PeerConnectionOut(this, dout); PeerState s = new PeerState(this, listener, metainfo, in, out); if ((options & OPTION_EXTENSION) != 0) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Peer supports extensions, sending reply message"); int metasize = metainfo != null ? metainfo.getInfoBytes().length : -1; out.sendExtension(0, ExtensionHandler.getHandshake(metasize)); } if ((options & OPTION_I2P_DHT) != 0 && util.getDHT() != null) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Peer supports DHT, sending PORT message"); int port = util.getDHT().getPort(); out.sendPort(port); } // Send our bitmap if (bitfield != null) s.out.sendBitfield(bitfield); // We are up and running! state = s; magnetState = mState; listener.connected(this); if (_log.shouldLog(Log.DEBUG)) _log.debug("Start running the reader with " + toString()); // Use this thread for running the incomming connection. // The outgoing connection creates its own Thread. out.startup(); Thread.currentThread().setName("Snark reader from " + peerID); s.in.run(); } catch (IOException eofe) { // Ignore, probably just the other side closing the connection. // Or refusing the connection, timing out, etc. if (_log.shouldLog(Log.DEBUG)) _log.debug(this.toString(), eofe); } catch (Throwable t) { _log.error(this + ": " + t.getMessage(), t); if (t instanceof OutOfMemoryError) throw (OutOfMemoryError) t; } finally { if (deregister) listener.disconnected(this); disconnect(); } }