Example #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;
  }
Example #2
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);
      }
    }
Example #3
0
  /**
   * Accept the next incoming connection.
   *
   * <p>When a new peer connects to this service, wait for it to send its handshake. We then parse
   * and check that the handshake advertises the torrent hash we expect, then reply with our own
   * handshake.
   *
   * <p>If everything goes according to plan, notify the <code>IncomingConnectionListener</code>s
   * with the connected socket and the parsed peer ID.
   */
  private void accept() throws IOException, SocketTimeoutException {
    Socket socket = this.socket.accept();

    try {
      logger.debug("New incoming connection ...");
      Handshake hs = this.validateHandshake(socket, null);
      this.sendHandshake(socket);
      this.fireNewPeerConnection(socket, hs.getPeerId());
    } catch (ParseException pe) {
      logger.debug("Invalid handshake from {}: {}", this.socketRepr(socket), pe.getMessage());
      try {
        socket.close();
      } catch (IOException e) {
      }
    } catch (IOException ioe) {
      logger.debug(
          "An error occured while reading an incoming " + "handshake: {}", ioe.getMessage());
      try {
        if (!socket.isClosed()) {
          socket.close();
        }
      } catch (IOException e) {
        // Ignore
      }
    }
  }