/** * WTFPL * Version 2, December 2004 * * Copyright (C) sponge * Planet Earth * * See... * * http://sam.zoy.org/wtfpl/ * and * http://en.wikipedia.org/wiki/WTFPL * * ...for any additional details and license questions. */ package net.i2p.BOB; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.concurrent.atomic.AtomicBoolean; import net.i2p.client.streaming.I2PSocket; import net.i2p.data.DataHelper; import net.i2p.util.I2PAppThread; /** * Process I2P->TCP * * @author sponge */ public class I2PtoTCP implements Runnable { private I2PSocket I2P; private final NamedDB info, database; private Socket sock; private final AtomicBoolean lives; /** * Constructor * * @param I2Psock * @param info * @param database */ I2PtoTCP(I2PSocket I2Psock, NamedDB info, NamedDB database, AtomicBoolean lives) { this.I2P = I2Psock; this.info = info; this.database = database; this.lives = lives; } private void rlock() { database.getReadLock(); info.getReadLock(); } private void runlock() { info.releaseReadLock(); database.releaseReadLock(); } /** * I2P stream to TCP stream thread starter * */ public void run() { String host; int port; boolean tell; InputStream in = null; OutputStream out = null; InputStream Iin = null; OutputStream Iout = null; Thread t = null; Thread q = null; try { die: { try { rlock(); try { host = info.get("OUTHOST").toString(); port = Integer.parseInt(info.get("OUTPORT").toString()); tell = info.get("QUIET").equals(Boolean.FALSE); } catch (Exception e) { break die; } finally { runlock(); } sock = new Socket(host, port); sock.setKeepAlive(true); // make readers/writers in = sock.getInputStream(); out = sock.getOutputStream(); Iin = I2P.getInputStream(); Iout = I2P.getOutputStream(); I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default if (tell) { // tell who is connecting out.write(DataHelper.getASCII(I2P.getPeerDestination().toBase64())); out.write(10); // nl out.flush(); // not really needed, but... } // setup to cross the streams TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPioA"); q = new I2PAppThread(conn_a, Thread.currentThread().getName() + " TCPioB"); // Fire! t.start(); q.start(); while (t.isAlive() && q.isAlive() && lives.get()) { // AND is used here to kill off the other thread try { Thread.sleep(10); //sleep for 10 ms } catch (InterruptedException e) { break die; } } // System.out.println("I2PtoTCP: Going away..."); } catch (Exception e) { // System.out.println("I2PtoTCP: Owch! damn!"); break die; } } // die } finally { try { in.close(); } catch (Exception ex) { } try { out.close(); } catch (Exception ex) { } try { Iin.close(); } catch (Exception ex) { } try { Iout.close(); } catch (Exception ex) { } try { t.interrupt(); } catch (Exception e) { } try { q.interrupt(); } catch (Exception e) { } try { // System.out.println("I2PtoTCP: Close I2P"); I2P.close(); } catch (Exception e) { tell = false; } //System.out.println("I2PtoTCP: Closed I2P"); try { // System.out.println("I2PtoTCP: Close sock"); sock.close(); } catch (Exception e) { tell = false; } // System.out.println("I2PtoTCP: Done"); } } }