/**
* 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.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import TorJava.Common.StreamsAndHTTP;
/**
* main class for directory server functionality
*
* @author Lexi Pimenidis
* @version unstable
*/
class DirectoryServer extends Thread {
Directory dir;
HashMap<String,HashMap<String,Object>> serviceDescriptors;
ServerSocket dir_server;
/**
* creates the server socket and installs a dispatcher for incoming data.
*
* @param dir_port
* the port to open for directory services
* @exception IOException
*/
DirectoryServer(Directory dir, int dir_port) throws IOException {
if (dir_port < 1)
throw new IOException("invalid port given");
if (dir_port > 0xffff)
throw new IOException("invalid port given");
this.dir = dir;
serviceDescriptors = new HashMap<String,HashMap<String,Object>>();
Logger.logGeneral(Logger.INFO,"DirectoryServer: starting directory server on port " + dir_port);
dir_server = new ServerSocket(dir_port);
this.start();
}
public void run() {
try {
while (true) {
// receive new connection
Socket client = dir_server.accept();
String descr = client.getInetAddress().getHostAddress() + ":" + client.getPort();
Logger.logDirectory(Logger.VERBOSE,"Incoming connection to directory from " + descr);
// handle connection
new DirectoryServerThread(dir, client, serviceDescriptors);
// close connection
}
} catch (IOException e) {
}
}
/**
* close down the directory server
*/
void close() {
Logger.logDirectory(Logger.VERBOSE, "DirectoryServer.close(): Closing directory server");
// close connections
try {
dir_server.close();
} catch (IOException e) {
}
}
}
class DirectoryServerThread extends Thread {
Directory dir;
HashMap<String,HashMap<String,Object>> sd;
Socket client;
public DirectoryServerThread(Directory dir, Socket client,
HashMap<String,HashMap<String,Object>> serviceDescriptoren) {
this.dir = dir;
this.client = client;
this.sd = serviceDescriptoren;
this.start();
}
public void run() {
try {
// read request
String query = StreamsAndHTTP.readHTTPFromStream(client.getInputStream());
PrintStream sout = new PrintStream(client.getOutputStream());
// parse request
Pattern p = Pattern.compile(
"^(GET|POST) ([^ ]+) HTTP.*?\r?\n\r?\n(.*)", Pattern.DOTALL
+ Pattern.MULTILINE + Pattern.CASE_INSENSITIVE
+ Pattern.UNIX_LINES);
Matcher m = p.matcher(query);
if (!m.find())
return;
String method = m.group(1);
String uri = m.group(2);
String body = m.group(3);
// main location to handle requests
String answer = null;
if (method.equals("GET")) {
if (uri.equals("/")) { // provide a directory listing
answer = dir.renderDirectory();
}
;
if (uri.startsWith("/tor/rendezvous/")) { // send a service
// descriptor
// - extract 'z'
String z = uri.substring(16);
// - check if stored service descriptor for 'z'
if (this.sd.containsKey(z))
answer = (String)(((HashMap<String,Object>) this.sd.get(z))
.get("original"));
}
}
;
if (method.equals("POST")) {
if (uri.equals("/tor/rendezvous/publish")) { // service
// descriptor is
// uploaded
try {
HashMap<String,Object> sd_ = new HashMap<String,Object>(); // store body
sd_.put("original", body);
// - parse body to ServiceDescriptor and store in
// HashMap
ServiceDescriptor serv_desc = new ServiceDescriptor("",
body.getBytes(), dir);
sd_.put("parsed", serv_desc);
// extract z and store sd_ in this.sd
String z = serv_desc.getURL();
this.sd.put(z, sd_);
// success
answer = "";
} catch (Exception e) {
Logger.logDirectory(Logger.WARNING,"strange data format detected or stuff");
answer = null;
}
}
;
}
;
// http-status-code
StringBuffer http;
if (answer != null) {
http = new StringBuffer("HTTP/1.0 200 yoo, peace man!\r\n");
} else {
http = new StringBuffer("HTTP/1.0 404 no way, man!\r\n");
answer = "";
}
;
// build answer
http.append("Content-Length: " + answer.length() + "\r\n");
http.append("\r\n");
http.append(answer);
// send answer
sout.print(http.toString());
} catch (IOException e) {
} finally {
try {
client.close();
} catch (IOException e) {
}
}
}
}