/*******************************************************************************
* 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.util.Hashtable;
import java.util.concurrent.LinkedBlockingQueue;
import staticContent.framework.config.Settings;
import staticContent.framework.util.Util;
import userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.httpPush_v0_001.dataObjects.Connection;
import userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.httpPush_v0_001.dataObjects.HttpInfo;
import userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.httpPush_v0_001.dataObjects.HttpPartType;
import userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.httpPush_v0_001.dataObjects.SynchronizedBuffer;
import userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.httpPush_v0_001.helper.HttpParser;
import userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.httpPush_v0_001.improvement.ExitImprovement;
import userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.httpPush_v0_001.mix.DataToMix;
import userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.httpPush_v0_001.mix.MixWriteInterface;
/**
* @author bash
*
* This class is a subclass from DataToMix
* It handles specific message
* transfer on the exitside from the mix to the webserver. It holds
* methods adjusted for this purpose.
*
* It implements the abstract methods from the superclass
*
*
*/
public class ExitDataToMix extends DataToMix {
private ExitImprovement improvement;
/**
* @param readableConnections
* @param mixTunnel
* @throws IllegalAccessException
* @throws InstantiationException
* @throws ClassNotFoundException
*/
public ExitDataToMix(LinkedBlockingQueue<Connection> readableConnections, MixWriteInterface mixTunnel,
Settings settings) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
super(readableConnections, mixTunnel, settings);
improvement = new ExitImprovement(settings.getProperty("HP_PLUGIN"));
}
/*
* (non-Javadoc)
* @see mix.DataToMix#headerHandling(dataObjects.Connection)
*/
public void headerHandling(Connection readableConnection) {
SynchronizedBuffer buffer = readableConnection.getConnectionBuffer();
String headerString = readableConnection.getSendBuffer();
String headerLine;
if(headerString.endsWith("\r")){
headerLine = new String(buffer.removeBytes(1));
} else {
headerLine = buffer.getHeaderString();
}
while (headerLine != null) {
headerString += headerLine;
if (headerString.endsWith("\r\n\r\n")) {
readableConnection.getStatusHTTPFromApp().setHeaderComplete(true);
break;
}
headerLine = buffer.getHeaderString();
}
if (readableConnection.getStatusHTTPFromApp().isHeaderComplete()) {
Hashtable<String, String> header = HttpParser.parseHeader(headerString);
readableConnection.setSendBuffer("");
readableConnection.getStatusHTTPFromApp().setHeader(header);
byte[] mixMessage = headerString.getBytes();
mixMessage = improvement.improveHeader(mixMessage, readableConnection);
short hlength = (short) mixMessage.length;
// System.out.println("------" + headerString);
readableConnection.getStatusHTTPFromApp().setBodyImprovable(
improvement.isBodyToMixImproveable(header, readableConnection));
mixMessage = Util.concatArrays(Util.shortToByteArray(hlength), mixMessage);
// Add method to method queue
String method = readableConnection.returnMethodFromQueue();
int bodyExistens = HttpParser.determineBodyType(header, method);
switch (bodyExistens) {
case 0:
readableConnection.getStatusHTTPFromApp().setType(HttpPartType.Header);
if (mixMessage != null) {
writeChunkToMix(readableConnection.getId(), mixMessage);
}
break;
case 1:
readableConnection.getStatusHTTPFromApp().setType(HttpPartType.Body);
int bodyLength = HttpParser.getBodyLengthFromHeader(header);
readableConnection.getStatusHTTPFromApp().setLength(bodyLength);
if (mixMessage != null) {
readableConnection.setHeaderBuffer(mixMessage);
}
break;
case 2:
readableConnection.getStatusHTTPFromApp().setType(HttpPartType.BodyChunk);
readableConnection.getStatusHTTPFromApp().setLength(-1);
if (mixMessage.length > 500){
readableConnection.getStatusHTTPFromApp().setType(HttpPartType.Header);
}
if (mixMessage != null) {
readableConnection.setHeaderBuffer(mixMessage);
}
break;
default:
break;
}
// readableConnection.logger.logEntryReqHead(readableConnection.getId(),
// readableConnection.incrementPackageCounter(), mixMessage.length,
// readableConnection
// .getStatusHTTPFromApp().getType().toString());
} else {
readableConnection.setSendBuffer(headerString);
}
}
/*
* (non-Javadoc)
* @see mix.DataToMix#bodyHandling(dataObjects.Connection)
*/
public void bodyHandling(Connection readableConnection) {
byte[] mixMessage;
readableConnection.getId();
SynchronizedBuffer buffer = readableConnection.getConnectionBuffer();
int bodyLength = readableConnection.getStatusHTTPFromApp().getLength();
if (bodyLength >= buffer.getByteSize()) {
mixMessage = buffer.removeBytes(buffer.getByteSize());
} else {
mixMessage = buffer.removeBytes(bodyLength);
}
boolean improveable = readableConnection.getStatusHTTPFromApp().isBodyImprovable();
// readableConnection.logger.logEntryReqBody(readableConnection.getId(),
// readableConnection.inspectPackageCounterTail(), mixMessage.length,
// null);
if (improveable) {
mixMessage = improvement.improveBody(mixMessage, readableConnection);
if (mixMessage != null) {
bodyRelayWrite(mixMessage, readableConnection);
}
} else {
bodyRelayWrite(mixMessage, readableConnection);
}
}
/*
*
* (non-Javadoc)
* @see mix.DataToMix#bodyChunkHandling(dataObjects.Connection)
*/
public void bodyChunkHandling(Connection connection) {
byte[] mixMessage;
SynchronizedBuffer buffer = connection.getConnectionBuffer();
connection.getId();
boolean improveable = connection.getStatusHTTPFromApp().isBodyImprovable();
if ((connection.getStatusHTTPFromApp().getLength() <= 0) && (!connection.getStatusHTTPFromApp().isLastChunk())) {
if (buffer.peekBuffer() == null) {
return;
}
String headline = buffer.getChunkHeaderLine();
if(headline== null){
connection.setConnectionMessageIncomplete(true);
return;
}
int bodySize = HttpParser.getBodyLengthFromHeadLine(headline);
if(bodySize == 0){
connection.getStatusHTTPFromApp().setLastChunk(true);
}
connection.getStatusHTTPFromApp().setLength((bodySize + headline.getBytes().length + 2));
}
int bodySize = connection.getStatusHTTPFromApp().getLength();
if (connection.getStatusHTTPFromApp().isLastChunk()) {
if(bodySize > buffer.getByteSize()){
connection.setConnectionMessageIncomplete(true);
return;
}
connection.setStatusHTTPFromApp(new HttpInfo(HttpPartType.Header, 0));
mixMessage = buffer.removeBytes(bodySize);
// mixMessage = improvement.improveBody(mixMessage, connection);
bodyRelayWrite(mixMessage, connection);
return;
}
if (improveable) {
if (bodySize > buffer.getByteSize()) {
// mixMessage =buffer.removeBytes(buffer.getByteSize());
// readableConnections.add(connection);
// return;
// mixMessage = buffer.removeBytes(buffer.getByteSize());
connection.setConnectionMessageIncomplete(true);
return;
} else {
mixMessage = buffer.removeBytes(bodySize);
}
mixMessage = improvement.improveBody(mixMessage, connection);
if (mixMessage != null) {
bodyRelayWrite(mixMessage, connection);
}
} else {
if (buffer.getByteSize() < bodySize) {
mixMessage = buffer.removeBytes(buffer.getByteSize());
} else {
mixMessage = buffer.removeBytes(bodySize);
}
bodyRelayWrite(mixMessage, connection);
}
}
}