예제 #1
0
  /**
   * Validate an expected handshake on a connection.
   *
   * <p>Reads an expected handshake message from the given connected socket, parses it and validates
   * that the torrent hash_info corresponds to the torrent we're sharing, and that the peerId
   * matches the peer ID we expect to see coming from the remote peer.
   *
   * @param socket The connected socket to the remote peer.
   * @param peerId The peer ID we expect in the handshake. If <em>null</em>, any peer ID is accepted
   *     (this is the case for incoming connections).
   * @return The validated handshake message object.
   */
  private Handshake validateHandshake(Socket socket, byte[] peerId)
      throws IOException, ParseException {
    InputStream is = socket.getInputStream();

    // Read the handshake from the wire
    int pstrlen = is.read();
    byte[] data = new byte[Handshake.BASE_HANDSHAKE_LENGTH + pstrlen];
    data[0] = (byte) pstrlen;
    is.read(data, 1, data.length - 1);

    // Parse and check the handshake
    Handshake hs = Handshake.parse(ByteBuffer.wrap(data));
    if (!Arrays.equals(hs.getInfoHash(), this.torrent.getInfoHash())) {
      throw new ParseException(
          "Handshake for unknow torrent "
              + Torrent.byteArrayToHexString(hs.getInfoHash())
              + " from "
              + this.socketRepr(socket)
              + ".",
          pstrlen + 9);
    }

    if (peerId != null && !Arrays.equals(hs.getPeerId(), peerId)) {
      throw new ParseException(
          "Announced peer ID "
              + Torrent.byteArrayToHexString(hs.getPeerId())
              + " did not match expected peer ID "
              + Torrent.byteArrayToHexString(peerId)
              + ".",
          pstrlen + 29);
    }

    return hs;
  }
  /**
   * Creates the torrent file for the specified <code>srcFile</code> and announce URI. If such
   * torrent already exists, loads and returns it.
   */
  @Nullable
  public static File getOrCreateTorrent(
      @NotNull final File srcFile,
      @NotNull final String relativePath,
      @NotNull final File torrentsStore,
      @NotNull final URI announceURI) {
    setHashingThreadsCount();

    File torrentFile = new File(torrentsStore, relativePath + TORRENT_FILE_SUFFIX);
    if (torrentFile.isFile()) {
      try {
        Torrent t = loadTorrent(torrentFile);
        for (List<URI> uris : t.getAnnounceList()) {
          if (uris.contains(announceURI)) return torrentFile;
        }
      } catch (IOException e) {
        LOG.warn(
            "Failed to load existing torrent file: "
                + torrentFile.getAbsolutePath()
                + ", error: "
                + e.toString()
                + ". Will create new torrent file instead.");
      }
    }

    final Torrent torrent = createTorrent(srcFile, torrentFile, announceURI);
    return torrent != null ? torrentFile : null;
  }
예제 #3
0
    @Override
    public void run() {
      Socket socket = new Socket();
      InetSocketAddress address = new InetSocketAddress(this.peer.getIp(), this.peer.getPort());

      try {
        logger.info("Connecting to {}...", this.peer);
        socket.connect(address, 3 * 1000);

        this.handler.sendHandshake(socket);
        Handshake hs =
            this.handler.validateHandshake(
                socket, (this.peer.hasPeerId() ? this.peer.getPeerId().array() : null));
        logger.info(
            "Handshaked with {}, peer ID is {}.",
            this.peer,
            Torrent.byteArrayToHexString(hs.getPeerId()));
        this.handler.fireNewPeerConnection(socket, hs.getPeerId());
      } catch (IOException ioe) {
        try {
          socket.close();
        } catch (IOException e) {
        }
        this.handler.fireFailedConnection(this.peer, ioe);
      } catch (ParseException pe) {
        try {
          socket.close();
        } catch (IOException e) {
        }
        this.handler.fireFailedConnection(this.peer, pe);
      }
    }
  /** Creates the torrent file for the specified <code>srcFile</code> and announce URI. */
  @Nullable
  public static Torrent createTorrent(
      @NotNull File srcFile, @NotNull File torrentFile, @NotNull URI announceURI) {
    setHashingThreadsCount();

    try {
      Torrent t = Torrent.create(srcFile, announceURI, "TeamCity");
      t.save(torrentFile);
      return t;
    } catch (Exception e) {
      LOG.warnAndDebugDetails(
          String.format(
              "Unable to create torrent file from %s: %s", srcFile.getPath(), e.toString()),
          e);
    }

    return null;
  }
  /** Loads torrent from torrent file */
  @NotNull
  public static Torrent loadTorrent(@NotNull File torrentFile) throws IOException {
    setHashingThreadsCount();

    try {
      return Torrent.load(torrentFile);
    } catch (NoSuchAlgorithmException e) {
      ExceptionUtil.rethrowAsRuntimeException(e);
    }

    return null;
  }
 private static void setHashingThreadsCount() {
   Torrent.setHashingThreadsCount(2); // limit number of threads generating hashes for a file
 }