package http;
import static http.global.HttpGlobal.CRLF;
import http.content.HttpContent;
import http.log.Log;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.Scanner;
/**
* An accepted {@link Socket} from the serversocket. This is where streams are
* handled. It starts by creating input and output streams, then parses input
* until a double carriage return is caught, then breaks the loop, closes the
* streams and the socket.
*
* @author Dennis Hedegaard
*
*/
public class HttpSocket extends Thread {
/**
* The {@link Socket} from {@link HttpServer}
*/
private Socket socket;
/**
* The output stream as a {@link DataOutputStream}, this wraps the
* {@link Socket} output stream.
*/
private DataOutputStream out;
/**
* The {@link Scanner} (or reader) for input, this wraps an
* {@link InputStreamReader} and the {@link Socket} input stream.
*/
private Scanner in;
/**
* Creates a new {@link HttpSocket}, which handles input and output for a
* socket between the server and http client (such as a browser).
*
* @param socket
*/
public HttpSocket(Socket socket) {
this.socket = socket;
Log.fine("socket established on: " + getIp() + ".");
start();
}
/**
* Gets the ip address from a {@link Socket}. If the socket is
* <code>null</code>, <code>null</code> is returned.
*
* @return The ip as a {@link String}, or <code>null</code> if the
* {@link Socket} is <code>null</code>.
*/
private String getIp() {
return socket == null ? null : socket.getInetAddress().getHostAddress();
}
@Override
public void run() {
/**
* Setup streams.
*/
try {
out = new DataOutputStream(new BufferedOutputStream(
socket.getOutputStream()));
} catch (IOException e) {
Log.fine("Unable to open output stream for " + getIp());
}
try {
in = new Scanner(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
Log.fine("Unable to open the input stream for: " + getIp());
}
boolean done = false;
String req = "";
/**
* Read until a double carriage return is recieved.
*/
while (!done && in.hasNextLine()) {
String line = in.nextLine();
/**
* If done, close input stream and break loop on the next iteration.
*/
if (line.length() == 0)
done = true;
else
req += line + CRLF;
}
/**
* Convert and parse input into the requested output, then write it.
*/
String[] lines = req.split(CRLF);
for (int i = 0; i < lines.length; i++) {
if (lines[i].startsWith("GET"))
new HttpContent(socket, lines[i]).write(out);
}
/**
* Flush and close output stream.
*/
in.close();
try {
out.flush();
out.close();
} catch (IOException e) {
if (!e.getMessage().equals("Socket closed")) {
e.printStackTrace();
Log.warning("Unable to close or flush output stream for: "
+ getIp());
}
}
/**
* Close the socket, and end the thread.
*/
try {
socket.close();
} catch (IOException e) {
Log.warning("Unable to close the socket for: " + getIp());
}
Log.fine("Closed connection for: " + getIp());
}
}