package net.i2p.i2ptunnel.udp;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import net.i2p.I2PAppContext;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionListener;
import net.i2p.client.datagram.I2PDatagramDissector;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
*
* @author welterde
*/
public class I2PSource implements Source, Runnable {
public I2PSource(I2PSession sess) {
this(sess, true, false);
}
public I2PSource(I2PSession sess, boolean verify) {
this(sess, verify, false);
}
public I2PSource(I2PSession sess, boolean verify, boolean raw) {
this.sess = sess;
this.verify = verify;
this.raw = raw;
// create queue
this.queue = new ArrayBlockingQueue<Integer>(256);
// create listener
this.sess.setSessionListener(new Listener());
// create thread
this.thread = new I2PAppThread(this);
}
public void setSink(Sink sink) {
this.sink = sink;
}
public void start() {
this.thread.start();
}
public void run() {
// create dissector
I2PDatagramDissector diss = new I2PDatagramDissector();
_running = true;
while (_running) {
try {
// get id
int id = this.queue.take();
// receive message
byte[] msg = this.sess.receiveMessage(id);
if(!this.raw) {
// load datagram into it
diss.loadI2PDatagram(msg);
// now call sink
if(this.verify)
this.sink.send(diss.getSender(), diss.getPayload());
else
this.sink.send(diss.extractSender(), diss.extractPayload());
} else {
// verify is ignored
this.sink.send(null, msg);
}
//System.out.print("r");
} catch(Exception e) {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
if (log.shouldWarn())
log.warn("error sending", e);
break;
}
}
}
protected class Listener implements I2PSessionListener {
public void messageAvailable(I2PSession sess, int id, long size) {
try {
queue.put(id);
} catch(Exception e) {
// ignore
}
}
public void reportAbuse(I2PSession arg0, int arg1) {
// ignore
}
public void disconnected(I2PSession arg0) {
_running = false;
thread.interrupt();
}
public void errorOccurred(I2PSession arg0, String arg1, Throwable arg2) {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
log.error(arg1, arg2);
_running = false;
thread.interrupt();
}
}
protected final I2PSession sess;
protected final BlockingQueue<Integer> queue;
protected Sink sink;
protected final Thread thread;
protected final boolean verify;
protected final boolean raw;
private volatile boolean _running;
}