forked from I2P_Developers/i2p.i2p
170 lines
3.7 KiB
Java
170 lines
3.7 KiB
Java
/**
|
|
* 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");
|
|
|
|
}
|
|
}
|
|
}
|