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); } } }
/** * 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; }