Example #1
0
File: Peer.java Project: hilbix/i2p
 /** @return socket debug string (for debug printing) */
 public String getSocket() {
   if (state != null) {
     String r = state.getRequests();
     if (r != null) return sock.toString() + "<br>Requests: " + r;
   }
   return sock.toString();
 }
Example #2
0
File: Peer.java Project: hilbix/i2p
  void disconnect() {
    PeerState s = state;
    if (s != null) {
      // try to save partial piece
      if (this.deregister) {
        PeerListener p = s.listener;
        if (p != null) {
          List<PartialPiece> pcs = s.returnPartialPieces();
          if (!pcs.isEmpty()) p.savePartialPieces(this, pcs);
          // now covered by savePartialPieces
          // p.markUnrequested(this);
        }
      }
      state = null;

      PeerConnectionIn in = s.in;
      if (in != null) in.disconnect();
      PeerConnectionOut out = s.out;
      if (out != null) out.disconnect();
      PeerListener pl = s.listener;
      if (pl != null) pl.disconnected(this);
    }
    I2PSocket csock = sock;
    sock = null;
    if ((csock != null) && (!csock.isClosed())) {
      try {
        csock.close();
      } catch (IOException ioe) {
        _log.warn("Error disconnecting " + toString(), ioe);
      }
    }
  }
Example #3
0
 protected void clientConnectionRun(Socket s) {
   I2PSocket i2ps = null;
   try {
     I2PSocketAddress addr = pickDestination();
     if (addr == null) throw new UnknownHostException("No valid destination configured");
     Destination clientDest = addr.getAddress();
     if (clientDest == null)
       throw new UnknownHostException("Could not resolve " + addr.getHostName());
     int port = addr.getPort();
     i2ps = createI2PSocket(clientDest, port);
     i2ps.setReadTimeout(readTimeout);
     new I2PTunnelRunner(s, i2ps, sockLock, null, mySockets);
   } catch (Exception ex) {
     if (_log.shouldLog(Log.INFO)) _log.info("Error connecting", ex);
     // l.log("Error connecting: " + ex.getMessage());
     closeSocket(s);
     if (i2ps != null) {
       synchronized (sockLock) {
         mySockets.remove(sockLock);
       }
     }
   }
 }
Example #4
0
File: Peer.java Project: hilbix/i2p
  /**
   * Incoming connection. Creates a unconnected peer from the input and output stream got from the
   * socket. Note that the complete handshake (which can take some time or block indefinitely) is
   * done in the calling Thread to get the remote peer id. To completely start the connection call
   * the connect() method.
   *
   * @param metainfo null if in magnet mode
   * @exception IOException when an error occurred during the handshake.
   */
  public Peer(
      final I2PSocket sock,
      InputStream in,
      OutputStream out,
      byte[] my_id,
      byte[] infohash,
      MetaInfo metainfo)
      throws IOException {
    this.my_id = my_id;
    this.infohash = infohash;
    this.metainfo = metainfo;
    this.sock = sock;

    byte[] id = handshake(in, out);
    this.peerID = new PeerID(id, sock.getPeerDestination());
    _id = ++__id;
    if (_log.shouldLog(Log.DEBUG))
      _log.debug("Creating a new peer " + peerID.toString(), new Exception("creating " + _id));
  }
Example #5
0
File: Peer.java Project: hilbix/i2p
 /** @since 0.8.4 */
 public Destination getDestination() {
   if (sock == null) return null;
   return sock.getPeerDestination();
 }
Example #6
0
File: Peer.java Project: hilbix/i2p
  /**
   * 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();
    }
  }
Example #7
0
  /**
   * Act as a SOCKS 5 client to connect to an outproxy
   *
   * @return open socket or throws error
   * @since 0.8.2
   */
  private I2PSocket outproxyConnect(I2PSOCKSTunnel tun, String proxy)
      throws IOException, SOCKSException, DataFormatException, I2PException {
    Properties overrides = new Properties();
    overrides.setProperty("option.i2p.streaming.connectDelay", "1000");
    I2PSocketOptions proxyOpts = tun.buildOptions(overrides);
    Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(proxy);
    if (dest == null) throw new SOCKSException("Outproxy not found");
    I2PSocket destSock =
        tun.createI2PSocket(
            I2PAppContext.getGlobalContext().namingService().lookup(proxy), proxyOpts);
    try {
      DataOutputStream out = new DataOutputStream(destSock.getOutputStream());
      boolean authAvail =
          Boolean.parseBoolean(props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH));
      String configUser = null;
      String configPW = null;
      if (authAvail) {
        configUser = props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_USER_PREFIX + proxy);
        configPW = props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_PW_PREFIX + proxy);
        if (configUser == null || configPW == null) {
          configUser = props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_USER);
          configPW = props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_PW);
          if (configUser == null || configPW == null) authAvail = false;
        }
      }

      // send the init
      out.writeByte(SOCKS_VERSION_5);
      if (authAvail) {
        out.writeByte(2);
        out.writeByte(Method.NO_AUTH_REQUIRED);
        out.writeByte(Method.USERNAME_PASSWORD);
      } else {
        out.writeByte(1);
        out.writeByte(Method.NO_AUTH_REQUIRED);
      }
      out.flush();

      // read init reply
      DataInputStream in = new DataInputStream(destSock.getInputStream());
      // is this right or should we not try to do 5-to-4 conversion?
      int hisVersion = in.readByte();
      if (hisVersion != SOCKS_VERSION_5 /* && addrtype == AddressType.DOMAINNAME */)
        throw new SOCKSException("SOCKS Outproxy is not Version 5");
      // else if (hisVersion != 4)
      //    throw new SOCKSException("Unsupported SOCKS Outproxy Version");

      int method = in.readByte();
      if (method == Method.NO_AUTH_REQUIRED) {
        // good
      } else if (method == Method.USERNAME_PASSWORD) {
        if (authAvail) {
          // send the auth
          out.writeByte(AUTH_VERSION);
          byte[] user = configUser.getBytes("UTF-8");
          byte[] pw = configPW.getBytes("UTF-8");
          out.writeByte(user.length);
          out.write(user);
          out.writeByte(pw.length);
          out.write(pw);
          out.flush();
          // read the auth reply
          if (in.readByte() != AUTH_VERSION)
            throw new SOCKSException("Bad auth version from outproxy");
          if (in.readByte() != AUTH_SUCCESS)
            throw new SOCKSException("Outproxy authorization failure");
        } else {
          throw new SOCKSException(
              "Outproxy requires authorization, please configure username/password");
        }
      } else {
        throw new SOCKSException("Outproxy authorization failure");
      }

      // send the connect command
      out.writeByte(SOCKS_VERSION_5);
      out.writeByte(Command.CONNECT);
      out.writeByte(0); // reserved
      out.writeByte(addressType);
      if (addressType == AddressType.IPV4) {
        out.write(InetAddress.getByName(connHostName).getAddress());
      } else if (addressType == AddressType.DOMAINNAME) {
        byte[] d = connHostName.getBytes("ISO-8859-1");
        out.writeByte(d.length);
        out.write(d);
      } else {
        // shouldn't happen
        throw new SOCKSException("Unknown address type for outproxy?");
      }
      out.writeShort(connPort);
      out.flush();

      // read the connect reply
      hisVersion = in.readByte();
      if (hisVersion != SOCKS_VERSION_5)
        throw new SOCKSException("Outproxy response is not Version 5");
      int reply = in.readByte();
      in.readByte(); // reserved
      int type = in.readByte();
      int count = 0;
      if (type == AddressType.IPV4) {
        count = 4;
      } else if (type == AddressType.DOMAINNAME) {
        count = in.readUnsignedByte();
      } else if (type == AddressType.IPV6) {
        count = 16;
      } else {
        throw new SOCKSException("Unsupported address type in outproxy response");
      }
      byte[] addr = new byte[count];
      in.readFully(addr); // address
      in.readUnsignedShort(); // port
      if (reply != Reply.SUCCEEDED)
        throw new SOCKSException("Outproxy rejected request, response = " + reply);
      // throw away the address in the response
      // todo pass the response through?
    } catch (IOException e) {
      try {
        destSock.close();
      } catch (IOException ioe) {
      }
      throw e;
    } catch (SOCKSException e) {
      try {
        destSock.close();
      } catch (IOException ioe) {
      }
      throw e;
    }
    // that's it, caller will send confirmation to our client
    return destSock;
  }