/*******************************************************************************
* gMix open source project - https://svs.informatik.uni-hamburg.de/gmix/
* Copyright (C) 2014 SVS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.httpPush_v0_001.exitClient;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import staticContent.framework.config.Settings;
import staticContent.framework.socket.socketInterfaces.StreamAnonSocketMix;
import userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.httpPush_v0_001.dataObjects.Connection;
/**
* This class represents the exit client. It handles all components.
*
* It starts the exitconnectionpool to communicate with the webserver.
*
* It builds up a connection with the mix.
*
* It also handles the improvement thread to improve a message to the mix and
* unimprove a message from the mix.
*
*
* @author bash
*
*/
public class ExitClient extends Thread {
private ConcurrentHashMap<Integer, Connection> connectionMap;
private MixExitConnection mixConnection;
private int improvmentThreadCounter;
private ExitConnectionPool connectionPool;
private InputStream fromControlStream;
private OutputStream toControlStream;
/**
* This queue contains the connection which contains data from the outside
*/
public LinkedBlockingQueue<Connection> readableConnections;
/**
* This queue contains the connection which contains data from the mix
*/
public LinkedBlockingQueue<Connection> writeableConnections;
private Settings settings;
private ExitDataToMix[] improvementThreads;
private ExitDataFromMix[] unImprovementThreads;
/**
* Constructor
*
* @param mixConnectionSocket
* @param settings
*/
public ExitClient(StreamAnonSocketMix mixConnectionSocket, Settings settings) {
this.readableConnections = new LinkedBlockingQueue<Connection>();
this.writeableConnections = new LinkedBlockingQueue<Connection>();
this.connectionMap = new ConcurrentHashMap<Integer, Connection>();
this.connectionPool = new ExitConnectionPool(settings.getPropertyAsInt("HP_BUFFER_SIZE"), readableConnections,
connectionMap, mixConnection, settings);
this.mixConnection = new MixExitConnection(mixConnectionSocket, connectionMap, connectionPool,
writeableConnections);
improvmentThreadCounter = settings.getPropertyAsInt("HP_THREAD_COUNTER");
this.connectionPool.start();
this.mixConnection.start();
this.settings = settings;
this.connectionPool.setMixConnection(mixConnection);
startImprovement();
/*establishControlChannel();
try {
checkControlStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Client Stopped!");*/
}
/**
* Method to start the thread to improve the messages
*/
public void startImprovement() {
improvementThreads = new ExitDataToMix[improvmentThreadCounter];
unImprovementThreads = new ExitDataFromMix[improvmentThreadCounter];
for (int i = 0; i < improvmentThreadCounter; i++) {
try {
improvementThreads[i] = new ExitDataToMix(readableConnections, mixConnection, settings);
improvementThreads[i].start();
unImprovementThreads[i] = new ExitDataFromMix(writeableConnections, settings);
unImprovementThreads[i].start();
} catch (ClassNotFoundException e) {
System.err.println("Plugin not found, please check path!");
e.printStackTrace();
} catch (InstantiationException e) {
System.err.println("Could not instatiate the plugin!");
e.printStackTrace();
} catch (IllegalAccessException e) {
System.err.println("Plugin not accessable, please check rights!");
e.printStackTrace();
}
}
}
public void resetConnectionPool() {
ConcurrentHashMap<Integer, Connection> pool = connectionPool.getConnectionMap();
for(Thread t: improvementThreads) {
t.interrupt()
;
}
for(Thread t: unImprovementThreads) {
t.interrupt();
}
startImprovement();
for (Connection con : pool.values()) {
try {
con.getServerSocket().close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
connectionPool.setConnectionMap(new ConcurrentHashMap<Integer, Connection>());
System.out.println("Control: Client reseted");
}
/*public void establishControlChannel() {
InetAddress address = null;
System.out.println("control: Awaits controlconnection via 4060");
try {
address = InetAddress.getByName("10.1.1.41");
ServerSocket anonServerSocket = new ServerSocket(4060, 30, address);
System.out.println("control: waiting for controlconnections on " + address + ": 4060"
);
Socket client = anonServerSocket.accept();
System.out.println("control: controlconnection accepted (from " + client.getInetAddress() + ":"
+ client.getPort() + ")");
fromControlStream = client.getInputStream();
toControlStream = client.getOutputStream();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
throw new RuntimeException("controlchannel could not bind" + address + ": 4060");
}
}
public void checkControlStream() throws IOException {
int readBytes;
boolean flow = true;
while(flow) {
int command = fromControlStream.read();
switch (command) {
case -1:
flow = false;
break;
case 1:
resetConnectionPool();
break;
case 2:
stopClient();
break;
default:
break;
}
}
}*/
public void stopClient() {
for(Thread t: improvementThreads) {
t.interrupt()
;
}
for(Thread t: unImprovementThreads) {
t.interrupt();
}
mixConnection.stopConnection();
connectionPool.stop();
System.exit(0);
}
}