Example #1
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 #2
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
      }
    }
  }
  public static void main(String[] args) throws IOException {
    OutputStream outputStream = System.out;
    in = System.in;
    out = new PrintWriter(outputStream);

    Handshake a = new Handshake();
    a.solve();
    out.close();
  }
Example #4
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;
  }
 @Override
 public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
   Entry entry = channelMap.get(ctx.getChannel().getRemoteAddress());
   if (entry != null) {
     entry.channel.write(e.getMessage());
     return;
   }
   ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
   Handshake handshake = new Handshake(buffer);
   Client client = null;
   ByteString token = null;
   try {
     if (handshake.type() == Type.CLIENT_HELLO)
       token = new ByteString(((ClientHello) handshake.body()).sessionId());
   } catch (Exception x) {
   }
   client = ClientMap.INSTANCE.clientForToken(token);
   entry = new Entry();
   entry.client = client;
   entry.dataBuffers.add(buffer.copy());
   final Entry entry2 = entry;
   connectionClient
       .bootstrap()
       .connect(client.address())
       .addListener(
           new ChannelFutureListener() {
             @Override
             public void operationComplete(ChannelFuture future) throws Exception {
               Channel channel = future.getChannel();
               entry2.channel = channel;
               ChannelBuffer buffer = entry2.dataBuffers.poll();
               if (buffer != null) entry2.channel.write(buffer);
             }
           });
   channelMap.put(ctx.getChannel().getRemoteAddress(), entry);
 }
Example #6
0
  /** Create an {@code SSLSocket} and perform the TLS handshake and certificate validation. */
  private void upgradeToTls(TunnelRequest tunnelRequest) throws IOException {
    Platform platform = Platform.get();

    // Make an SSL Tunnel on the first message pair of each SSL + proxy connection.
    if (requiresTunnel()) {
      makeTunnel(tunnelRequest);
    }

    // Create the wrapper over connected socket.
    socket =
        route.address.sslSocketFactory.createSocket(
            socket, route.address.uriHost, route.address.uriPort, true /* autoClose */);
    SSLSocket sslSocket = (SSLSocket) socket;
    if (route.modernTls) {
      platform.enableTlsExtensions(sslSocket, route.address.uriHost);
    } else {
      platform.supportTlsIntolerantServer(sslSocket);
    }

    boolean useNpn =
        route.modernTls
            && ( // Contains a spdy variant.
            route.address.protocols.contains(Protocol.HTTP_2)
                || route.address.protocols.contains(Protocol.SPDY_3));

    if (useNpn) {
      if (route.address.protocols.contains(Protocol.HTTP_2) // Contains both spdy variants.
          && route.address.protocols.contains(Protocol.SPDY_3)) {
        platform.setNpnProtocols(sslSocket, Protocol.HTTP2_SPDY3_AND_HTTP);
      } else if (route.address.protocols.contains(Protocol.HTTP_2)) {
        platform.setNpnProtocols(sslSocket, Protocol.HTTP2_AND_HTTP_11);
      } else {
        platform.setNpnProtocols(sslSocket, Protocol.SPDY3_AND_HTTP11);
      }
    }

    // Force handshake. This can throw!
    sslSocket.startHandshake();

    // Verify that the socket's certificates are acceptable for the target host.
    if (!route.address.hostnameVerifier.verify(route.address.uriHost, sslSocket.getSession())) {
      throw new IOException("Hostname '" + route.address.uriHost + "' was not verified");
    }

    out = sslSocket.getOutputStream();
    in = sslSocket.getInputStream();
    handshake = Handshake.get(sslSocket.getSession());
    streamWrapper();

    ByteString maybeProtocol;
    if (useNpn && (maybeProtocol = platform.getNpnSelectedProtocol(sslSocket)) != null) {
      Protocol selectedProtocol = Protocol.find(maybeProtocol); // Throws IOE on unknown.
      if (selectedProtocol.spdyVariant) {
        sslSocket.setSoTimeout(0); // SPDY timeouts are set per-stream.
        spdyConnection =
            new SpdyConnection.Builder(route.address.getUriHost(), true, in, out)
                .protocol(selectedProtocol)
                .build();
        spdyConnection.sendConnectionHeader();
      }
    }
  }
Example #7
0
 /**
  * Send our handshake message to the socket.
  *
  * @param socket The socket to the remote peer.
  */
 private void sendHandshake(Socket socket) throws IOException {
   OutputStream os = socket.getOutputStream();
   os.write(
       Handshake.craft(this.torrent.getInfoHash(), this.id.getBytes(Torrent.BYTE_ENCODING))
           .getBytes());
 }
Example #8
0
  /** Create an {@code SSLSocket} and perform the TLS handshake and certificate validation. */
  private void upgradeToTls(TunnelRequest tunnelRequest) throws IOException {
    Platform platform = Platform.get();

    // Make an SSL Tunnel on the first message pair of each SSL + proxy connection.
    if (requiresTunnel()) {
      makeTunnel(tunnelRequest);
    }

    // Create the wrapper over connected socket.
    socket =
        route.address.sslSocketFactory.createSocket(
            socket, route.address.uriHost, route.address.uriPort, true /* autoClose */);
    SSLSocket sslSocket = (SSLSocket) socket;
    if (route.modernTls) {
      platform.enableTlsExtensions(sslSocket, route.address.uriHost);
    } else {
      platform.supportTlsIntolerantServer(sslSocket);
    }

    boolean useNpn =
        route.modernTls
            && (route.address.transports.contains("HTTP-draft-09/2.0")
                || route.address.transports.contains("spdy/3"));

    if (useNpn) {
      if (route.address.transports.contains("HTTP-draft-09/2.0")
          && route.address.transports.contains("spdy/3")) {
        platform.setNpnProtocols(sslSocket, ALL_PROTOCOLS);
      } else if (route.address.transports.contains("HTTP-draft-09/2.0")) {
        platform.setNpnProtocols(sslSocket, HTTP2_AND_HTTP);
      } else {
        platform.setNpnProtocols(sslSocket, SPDY3_AND_HTTP11);
      }
    }

    // Force handshake. This can throw!
    sslSocket.startHandshake();

    // Verify that the socket's certificates are acceptable for the target host.
    if (!route.address.hostnameVerifier.verify(route.address.uriHost, sslSocket.getSession())) {
      throw new IOException("Hostname '" + route.address.uriHost + "' was not verified");
    }

    out = sslSocket.getOutputStream();
    in = sslSocket.getInputStream();
    handshake = Handshake.get(sslSocket.getSession());
    streamWrapper();

    byte[] selectedProtocol;
    if (useNpn && (selectedProtocol = platform.getNpnSelectedProtocol(sslSocket)) != null) {
      if (Arrays.equals(selectedProtocol, HTTP_20_DRAFT_09)
          || Arrays.equals(selectedProtocol, SPDY3)) {
        SpdyConnection.Builder builder =
            new SpdyConnection.Builder(route.address.getUriHost(), true, in, out);
        if (Arrays.equals(selectedProtocol, HTTP_20_DRAFT_09)) builder.http20Draft09();
        sslSocket.setSoTimeout(0); // SPDY timeouts are set per-stream.
        spdyConnection = builder.build();
        spdyConnection.sendConnectionHeader();
      } else if (!Arrays.equals(selectedProtocol, HTTP_11)) {
        throw new IOException(
            "Unexpected NPN transport " + new String(selectedProtocol, "ISO-8859-1"));
      }
    }
  }