ActionReceiver.java

00001 package edu.stanford.hci.r3.actions.remote;
00002 
00003 import java.io.BufferedReader;
00004 import java.io.IOException;
00005 import java.io.InputStream;
00006 import java.io.InputStreamReader;
00007 import java.net.InetAddress;
00008 import java.net.ServerSocket;
00009 import java.net.Socket;
00010 import java.net.UnknownHostException;
00011 import java.util.ArrayList;
00012 import java.util.Arrays;
00013 import java.util.HashSet;
00014 import java.util.List;
00015 import java.util.Set;
00016 
00017 import com.thoughtworks.xstream.XStream;
00018 
00019 import edu.stanford.hci.r3.actions.R3Action;
00020 import edu.stanford.hci.r3.config.Configuration;
00021 import edu.stanford.hci.r3.config.Constants;
00022 import edu.stanford.hci.r3.util.DebugUtils;
00023 import edu.stanford.hci.r3.util.networking.ClientServerType;
00024 
00036 public class ActionReceiver {
00037 
00041         public static final String CONFIG_FILE_KEY = "actionreceiver.trustedsenders";
00042 
00046         public static final String CONFIG_FILE_VALUE = "/config/ActionReceiver.xml";
00047 
00051         public static final int DEFAULT_JAVA_PORT = Constants.Ports.ACTION_RECEIVER_JAVA;
00052 
00056         public static final int DEFAULT_PLAINTEXT_PORT = Constants.Ports.ACTION_RECEIVER_PLAINTEXT;
00057 
00061         private static ActionReceiver javaDaemon;
00062 
00066         private static final String PROPERTY_NAME = "trustedClients";
00067 
00071         private static ActionReceiver textDaemon;
00072 
00076         public static void startDaemons() {
00077                 startDaemons(DEFAULT_JAVA_PORT, DEFAULT_PLAINTEXT_PORT);
00078         }
00079 
00084         public static void startDaemons(int tcpipPortJava, int tcpipPortPlainText) {
00085                 if (javaDaemon == null) {
00086                         javaDaemon = new ActionReceiver(tcpipPortJava, ClientServerType.JAVA);
00087                 }
00088                 if (textDaemon == null) {
00089                         textDaemon = new ActionReceiver(tcpipPortPlainText, ClientServerType.PLAINTEXT);
00090                 }
00091         }
00092 
00096         public static void stopDaemons() {
00097                 DebugUtils.println("Stopping Action Receiver Daemons.");
00098                 if (javaDaemon != null) {
00099                         javaDaemon.stopDaemon();
00100                         javaDaemon = null;
00101                 }
00102 
00103                 if (textDaemon != null) {
00104                         textDaemon.stopDaemon();
00105                         textDaemon = null;
00106                 }
00107         }
00108 
00112         private List<ActionHandler> actionHandlers = new ArrayList<ActionHandler>();
00113 
00117         private List<Socket> clients = new ArrayList<Socket>();
00118 
00122         private ActionReceiverConnectionListener connectionListener;
00123 
00127         private boolean exitFlag = false;
00128 
00132         private String hostAddress;
00133 
00137         private String hostName;
00138 
00142         private int serverPort;
00143 
00147         private ServerSocket serverSocket;
00148 
00152         private ClientServerType serverType;
00153 
00157         private Set<String> trustedSenders = new HashSet<String>();
00158 
00165         public ActionReceiver(int tcpipPort, ClientServerType type) {
00166                 this(tcpipPort, type, "localhost");
00167         }
00168 
00173         public ActionReceiver(int tcpipPort, ClientServerType type, String... trusted) {
00174                 trustedSenders.addAll(Arrays.asList(trusted));
00175                 readTrustedClientsFromConfigFile();
00176                 DebugUtils.println("Trusted Client Set: " + trustedSenders);
00177 
00178                 try {
00179                         serverSocket = new ServerSocket(tcpipPort);
00180                 } catch (IOException e) {
00181                         System.out.println("Error with server socket: " + e.getLocalizedMessage());
00182                 }
00183                 serverType = type;
00184 
00185                 // the server port
00186                 serverPort = serverSocket.getLocalPort();
00187 
00188                 try {
00189                         hostAddress = InetAddress.getLocalHost().getHostAddress();
00190                         hostName = InetAddress.getLocalHost().getHostName();
00191                 } catch (UnknownHostException e) {
00192                         e.printStackTrace();
00193                 }
00194 
00195                 // start thread to accept connections
00196                 getDaemonThread().start();
00197         }
00198 
00204         public void addActionHandler(ActionHandler handler) {
00205                 actionHandlers.add(handler);
00206         }
00207 
00213         private Thread getDaemonThread() {
00214                 return new Thread() {
00215 
00216                         public void run() {
00217                                 while (true) {
00218                                         Socket client = null;
00219                                         try {
00220                                                 if (exitFlag) {
00221                                                         System.out.println("Closing Action Receiver Daemon.");
00222                                                         break;
00223                                                 }
00224 
00225                                                 log("ActionReceiver :: Waiting for a " + serverType + " connection on port ["
00226                                                                 + serverPort + "]");
00227 
00228                                                 client = serverSocket.accept();
00229 
00230                                                 final InetAddress inetAddress = client.getInetAddress();
00231                                                 final String ipAddr = inetAddress.toString();
00232                                                 final String dnsName = inetAddress.getHostName();
00233 
00234                                                 // we got a connection with the client
00235                                                 log("ActionReceiver :: Got a connection on server port " + serverPort);
00236                                                 log("               from client: " + ipAddr + " :: " + dnsName);
00237                                                 if (connectionListener != null) {
00238                                                         connectionListener.newConnectionFrom(dnsName, ipAddr);
00239                                                 }
00240 
00241                                                 // check whether it's ok to get messages from this remote machine...
00242                                                 boolean clientIsOK = false;
00243                                                 for (String nameOrAddress : trustedSenders) {
00244                                                         if (nameOrAddress.contains("*")) {
00245                                                                 // 128.15.*.* --> 128.15.
00246                                                                 nameOrAddress = nameOrAddress.substring(0, nameOrAddress.indexOf("*"));
00247                                                         }
00248 
00249                                                         if (dnsName.toLowerCase().endsWith(nameOrAddress)
00250                                                                         || ipAddr.startsWith(nameOrAddress)) {
00251                                                                 // .stanford.edu
00252                                                                 // 128.15.
00253                                                                 // good enough for us!
00254                                                                 DebugUtils.println("This is a trusted client. Matched: " + nameOrAddress);
00255                                                                 clientIsOK = true;
00256                                                         } else {
00257                                                                 DebugUtils.println("Did not match our client. Filter [" + nameOrAddress
00258                                                                                 + "] does not match " + dnsName + " next!");
00259                                                         }
00260                                                 }
00261                                                 if (!clientIsOK) {
00262                                                         client.close();
00263                                                         continue;
00264                                                 }
00265 
00266                                                 // keep it around
00267                                                 clients.add(client);
00268                                         } catch (IOException ioe) {
00269                                                 log("ActionReceiver :: Error with server socket: " + ioe.getLocalizedMessage());
00270                                         }
00271 
00272                                         if (client != null) {
00273                                                 if (serverType == ClientServerType.PLAINTEXT) {
00274                                                         getTextClientHandlerThread(client).start();
00275                                                 } else { // serverType == Java Server
00276                                                         getJavaClientHandlerThread(client).start();
00277                                                 }
00278                                         }
00279                                 }
00280                         }
00281                 };
00282         }
00283 
00287         public String getHostAddress() {
00288                 return hostAddress;
00289         }
00290 
00294         public String getHostName() {
00295                 return hostName;
00296         }
00297 
00302         private Thread getJavaClientHandlerThread(final Socket clientSocket) {
00303                 return new Thread() {
00304                         private BufferedReader br;
00305 
00306                         public void run() {
00307                                 try {
00308                                         final InputStream inputStream = clientSocket.getInputStream();
00309                                         br = new BufferedReader(new InputStreamReader(inputStream));
00310                                         String line = null;
00311                                         final XStream xml = new XStream();
00312                                         while ((line = br.readLine()) != null) {
00313                                                 // System.out.println(line);
00314 
00315                                                 if (exitFlag) {
00316                                                         break;
00317                                                 }
00318 
00319                                                 // reconstruct the action
00320                                                 final R3Action action = (R3Action) xml.fromXML(line);
00321 
00322                                                 // tell my listeners!
00323                                                 for (ActionHandler ah : actionHandlers) {
00324                                                         ah.receivedAction(action);
00325                                                 }
00326                                         }
00327                                 } catch (IOException e) {
00328                                         DebugUtils.println(e);
00329                                         DebugUtils.println("The client " + clientSocket.getInetAddress().getHostName()
00330                                                         + " has probably disconnected...");
00331                                 }
00332                         }
00333                 };
00334         }
00335 
00340         private Thread getTextClientHandlerThread(final Socket clientSocket) {
00341                 return new Thread() {
00342                         private BufferedReader br;
00343 
00344                         public synchronized void disconnect() {
00345                                 try {
00346                                         if (!clientSocket.isClosed()) {
00347                                                 clientSocket.close();
00348                                         }
00349                                         if (br != null) {
00350                                                 br.close();
00351                                                 br = null;
00352                                         }
00353                                 } catch (IOException e) {
00354                                         e.printStackTrace();
00355                                 }
00356                         }
00357 
00358                         public void run() {
00359                                 try {
00360                                         final InputStream inputStream = clientSocket.getInputStream();
00361                                         br = new BufferedReader(new InputStreamReader(inputStream));
00362                                         String line = null;
00363                                         while ((line = br.readLine()) != null) {
00364                                                 System.out.println(line);
00365 
00366                                                 if (line.toLowerCase().equals("[[exit]]")) {
00367                                                         break;
00368                                                 }
00369 
00370                                                 // the server's exit flag
00371                                                 // it can kill all clients at the same time
00372                                                 if (exitFlag) {
00373                                                         break;
00374                                                 }
00375 
00376                                                 // tell my listeners!
00377                                                 for (ActionHandler ah : actionHandlers) {
00378                                                         ah.receivedActionText(line);
00379                                                 }
00380                                         }
00381                                 } catch (IOException e) {
00382                                         e.printStackTrace();
00383                                 }
00384                                 disconnect();
00385                         }
00386 
00387                 };
00388         }
00389 
00395         private void log(String msg) {
00396                 System.out.println(msg);
00397         }
00398 
00402         private void readTrustedClientsFromConfigFile() {
00403                 final String trustedClients = Configuration.getPropertyFromConfigFile(PROPERTY_NAME,
00404                                 CONFIG_FILE_KEY);
00405                 final String[] clients = trustedClients.split("[,]");
00406                 for (String client : clients) {
00407                         trustedSenders.add(client.trim());
00408                 }
00409         }
00410 
00414         public void setConnectionListener(ActionReceiverConnectionListener listener) {
00415                 connectionListener = listener;
00416         }
00417 
00421         public void stopDaemon() {
00422                 try {
00423                         exitFlag = true;
00424                         for (Socket client : clients) {
00425                                 client.close();
00426                         }
00427                         System.out.println("ActionReceiver :: " + serverType + " on port "
00428                                         + serverSocket.getLocalPort() + " is stopping...");
00429                         serverSocket.close();
00430                 } catch (IOException e) {
00431                         e.printStackTrace();
00432                 }
00433         }
00434 }

Generated on Sat Apr 14 18:21:33 2007 for R3 Paper Toolkit by  doxygen 1.4.7