/** * Copyright (c) 1996,1997,1998 Sun Microsystems, Inc. All Rights Reserved. * * Permission to use, copy, modify, and distribute this software * and its documentation for NON-COMMERCIAL purposes and without * fee is hereby granted provided that this copyright notice * appears in all copies. Please refer to the file "copyright.html" * for further important copyright and licensing information. * * The Java source code is the confidential and proprietary information * of Sun Microsystems, Inc. ("Confidential Information"). You shall * not disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. */ import java.io.*; import java.net.*; import java.util.*; /** * Implementation of a basic HTTP server for Firewall * tunneling. The server supports both Client->Server and * Server->Client communication. */ public class HttpServer implements Runnable { // Accept socket private ServerSocket _serverSocket; // Server Listener private HttpServerListener _listener; // Thread accepting connections private Thread _acceptTID; // Handler threads private Pool _pool; // Client sockets private Vector _clients; // Default HTTP Response private String _httpResponse; /** * Creates a new HttpServer instance * @param port Port to listen on * @param poolSize Number of handler threads * @throws IOException Thrown if the accept socket cannot be opended */ public HttpServer (int port, int poolSize) throws IOException { _serverSocket = new ServerSocket (port); _httpResponse = "HTTP/1.0 200 MyServer \nCache-Control: no-cache\nPragma: no-cache \r\n\r\n"; try { _pool = new Pool (poolSize, HttpServerWorker.class); } catch (Exception e) { e.printStackTrace(); throw new InternalError (e.getMessage()); } _clients = new Vector(); _acceptTID = new Thread(this); _acceptTID.start(); } /** * Adds a new client * @param s Socket * @return void */ synchronized void addClient (Socket s) { _clients.addElement(s); } /** * Adds a new HttpServerListener. Only one listener can * be added * @param l HttpServerListener * @return void * @throws TooManyListenersException Thrown if more then one listener is added */ public void addHttpServerListener (HttpServerListener l) throws TooManyListenersException { if ( _listener == null ) { _listener = l; } else { throw new TooManyListenersException(); } } /** * Removes a new HttpServerListener. * be added * @param l HttpServerListener * @return void */ public void removeHttpServerListener (HttpServerListener l) { _listener = null; } /** * Notifies the listener when a message arrives * @param data Message data * @param out Stream to write results too * @return void */ synchronized void notifyListener (InputStream data, OutputStream out) { if ( _listener != null ) { _listener.service (data, out); } } /** * Simple implementation that sends data to all clients * @param data Array of bytes containing data to send * @return void */ synchronized public void send (byte data[]) { Enumeration elements = _clients.elements(); while ( elements.hasMoreElements() ) { Socket s = (Socket)elements.nextElement(); try { DataOutputStream output = new DataOutputStream( new BufferedOutputStream (s.getOutputStream())); int length; writeResponse (output); output.writeInt (data.length); output.write (data); output.flush(); output.close(); } catch (IOException e) { e.printStackTrace(); } finally { try { s.close(); } catch (IOException e) { } } } _clients.removeAllElements(); } /** * Thread to accept connections * @return void */ public void run() { while (true) { try { Socket s = _serverSocket.accept(); Hashtable data = new Hashtable(); data.put ("Socket", s); data.put ("HttpServer", this); _pool.performWork (data); } catch (Exception e) { e.printStackTrace(); } } } /** * Convience method to write the HTTP Response header * @param out Stream to write the response too * @return void * @throws IOException Thrown if response can't be written */ void writeResponse (DataOutputStream out) throws IOException { out.writeBytes (_httpResponse); } }