/**
* OnionCoffee - Anonymous Communication through TOR Network
* Copyright (C) 2005-2007 RWTH Aachen University, Informatik IV
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package TorJava;
import java.io.DataInputStream;
import java.io.IOException;
import TorJava.Common.TorException;
/**
* reads data arriving at the TLS connection and dispatches it to the
* appropriate circuit or stream that it belongs to.
*
* @author Lexi Pimenidis
*/
class TLSDispatcher extends Thread {
DataInputStream sin;
TLSConnection tls;
boolean stopped;
TLSDispatcher(TLSConnection tls, DataInputStream sin) {
this.tls = tls;
this.sin = sin;
this.setName("TLSDispatcher for "+tls.server.nickname);
this.start();
}
public void close() {
this.stopped = true;
this.interrupt();
}
public void run() {
boolean dispatched = false;
while(!stopped) {
// read next data-packet
Cell cell = null;
try {
cell = new Cell(sin);
} catch (IOException e) {
Logger.logTLS(Logger.INFO,"TLSDispatcher.run: connection error: "+e.getMessage());
stopped = true;
break;
}
// padding cell?
if (cell.isTypePadding()) {
Logger.logCell(Logger.INFO, "TLSDispatcher.run: padding cell from from " + tls.server.nickname);
} else {
dispatched = false;
int cell_circID = cell.circID;
// dispatch according to circID
if (tls.circuits.containsKey(new Integer(cell_circID))) {
Circuit circ = (Circuit) tls.circuits.get(new Integer(cell_circID));
try { // admitted: this was not the original intent for queue handlers... but maye I'll find a better solution sometimes in the future
if (circ.qhFC!=null) circ.qhFC.handleCell(cell);
}catch(TorException e) {}
// check for destination in circuit
if (cell.isTypeRelay()) {
CellRelay relay = null;
try {
// found a relay-cell! Try to strip off
// symmetric encryption and check the content
relay = new CellRelay(circ, cell);
// dispatch to stream, if a stream-ID is given
if (relay.isTypeBegin()) {
//System.out.println("CELL BEGIN!");
circ.handleBegin(relay);
} else if (relay.streamID != 0) {
if (circ.streams.containsKey(new Integer(relay.streamID))) {
TCPStream stream = (TCPStream) circ.streams
.get(new Integer(relay.streamID));
dispatched = true;
Logger.logCell( Logger.VERBOSE, "TLSDispatcher.run: data from " + tls.server.nickname + " dispatched to circuit " + circ.ID + "/stream " + stream.ID);
stream.queue.add(relay);
}
} else {
// relay cell for stream id 0: dispatch to
// circuit
if (relay.isTypeIntroduce2()) {
if (circ.myHSProperties != null) {
Logger.logCell( Logger.VERBOSE, "TLSDispatcher.run: introduce2 from " + tls.server.nickname + " dispatched to circuit " + circ.ID + " (stream ID=0)");
try{
dispatched = circ.handleIntroduce2(relay);
}
catch(IOException e) {
Logger.logCell( Logger.INFO, "TLSDispatcher.run: error handling intro2-cell: "+e.getMessage());
}
}
} else {
dispatched = true;
Logger.logCell( Logger.VERBOSE, "TLSDispatcher.run: data from " + tls.server.nickname + " dispatched to circuit " + circ.ID + " (stream ID=0)");
circ.queue.add(relay);
}
}
} catch (TorException e) {
Logger.logCell(Logger.WARNING, "TLSDispatcher.run: TorException " + e.getMessage() + " during dispatching cell");
//e.printStackTrace();
/*
* if (relay != null)
* Logger.logCell(Logger.WARNING,"TLSDispatcher.run:
* "+relay.toString()); else
* Logger.logCell(Logger.WARNING,"TLSDispatcher.run:
* "+cell.toString());
*/
}
} else {
// no relay cell: cell is there to control circuit
if (cell.isTypeDestroy()) {
dispatched = true;
Logger.logCell(Logger.VERBOSE, "TLSDispatcher.run: received DESTROY-cell from " + tls.server.nickname + " for circuit " + circ.ID);
circ.close(true);
} else {
dispatched = true; Logger.logCell(Logger.VERBOSE, "TLSDispatcher.run: data from " + tls.server.nickname + " dispatched to circuit " + circ.ID);
circ.queue.add(cell);
}
}
} else {
Logger.logCircuit(Logger.INFO, "TLSDispatcher.run: received cell for circuit " + cell_circID + " from " + tls.server.nickname + ". But no such circuit exists.");
}
}
if (!dispatched) {
// used to be WARNING, but is given too often to be of $REAL value, like a warning should
Logger.logCell(Logger.VERBOSE, "TLSDispatcher.run: data from " + tls.server.nickname + " could not get dispatched");
Logger.logCell(Logger.RAW_DATA, "TLSDispatcher.run: " + cell.print());
}
}
}
}