/*******************************************************************************
* Copyright (c) 2008 Jerome Negre.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl-3.0-standalone.html
*
* Contributors:
* Jerome Negre - initial API and implementation
******************************************************************************/
package org.jnegre.redpill;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import org.jnegre.redpill.analyzer.SessionAnalyzer;
public class SessionThread extends Thread {
private final Socket socket;
private final SessionManager sm;
private final Session session;
private SessionContextImpl context = new SessionContextImpl();
private ArrayList<SessionAnalyzer> sessionAnalyzers = new ArrayList<SessionAnalyzer>();
public SessionThread(final Socket socket, final SessionManager sm) {
super();
this.socket = socket;
this.sm = sm;
this.session = sm.newSession();
List<Class<SessionAnalyzer>> analyzers = ServiceProvider.getServices(SessionAnalyzer.class);
for(Class<SessionAnalyzer> analyzer : analyzers) {
try {
SessionAnalyzer instance = analyzer.newInstance();
sessionAnalyzers.add(instance);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
try {
//security check
if(!socket.getInetAddress().isLoopbackAddress()) {
System.out.println("Abort, connection from "+socket.getInetAddress().getHostAddress());
socket.close();
return;
}
BufferedInputStream socketIn = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream socketOut = new BufferedOutputStream(socket.getOutputStream());
HttpRequest request = new HttpRequest(socketIn);
request.parseBody(socketIn);
session.setRequest(request);
HttpResponse forgedResponse = null;
for(SessionAnalyzer analyzer: sessionAnalyzers) {
forgedResponse = analyzer.onRequest(request, context);
if(forgedResponse != null) {
context.markResponseForged();
}
}
sm.notifyOnRequest(session);
if(forgedResponse != null) {
session.setResponse(forgedResponse);
sm.notifyOnResponse(session);
forgedResponse.writeTo(socketOut);
} else {
Socket outSocket;
try {
outSocket = new Socket(request.getHost(), request.getPort());
} catch(IOException e) {
System.err.println("Failed to open a socket to "+request.getHost()+" port "+request.getPort());
throw e;
}
BufferedOutputStream outOut = new BufferedOutputStream(outSocket.getOutputStream());
BufferedInputStream outIn = new BufferedInputStream(outSocket.getInputStream());
request.writeTo(outOut);
HttpResponse response = new HttpResponse(outIn);
for(SessionAnalyzer analyzer: sessionAnalyzers) {
analyzer.onStartResponse(request, response, context);
}
try {
response.parseBody(outIn);
} catch(IOException e){
e.printStackTrace();
}
for(SessionAnalyzer analyzer: sessionAnalyzers) {
forgedResponse = analyzer.onEndResponse(request, response, context);
if(forgedResponse!=null && context.isResponseDelayed()) {
response = forgedResponse;
context.markResponseForged();
}
}
session.setResponse(response);
sm.notifyOnResponse(session);
response.writeTo(socketOut);
outIn.close();
outOut.close();
outSocket.close();
}
socketIn.close();
socketOut.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
//whatever...
}
}
}
}