 /*
  * (C) 2003-2004 Columbia University Departments of Computer Science and
  * Electrical Engineering
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, is permitted provided the original authors give
  * written consent and the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above
  *    copyright notice, this list of conditions and the following
  *    disclaimer in the documentation and/or other materials
  *    provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  */
package client;

import settings.Settings;
import util.Utilities;
import util.Debug;
import java.applet.Applet;
import java.awt.*;
import java.net.*;
import java.io.*;
import java.util.Map;


/**
 * BrowserToProxySSLApplet.java
 *
 * BrowserToProxySSLApplet contains a server socket that listens to all incoming connections from the browser
 * provided that the browser points its proxy configuration to this server socket.  Supports HTML and SSL requests.
 *
 */
public class BrowserToProxySSLApplet extends Applet
{

    private ServerSocket _serverSocket = null;
    private Map _settings = Settings.instance();
    private boolean _isListening = true;
    private boolean _isDebugMode = Debug.isEnabled(BrowserToProxySSLApplet.class.getName());
    private SSLSocketClient _socketClient;

    /**
     * initializes the applet
     */
    public void init()
    {
	try {
	    // initializes the server socket, which accepts the requests from the browser and the client SSLSocket
	    _serverSocket = new ServerSocket(((Integer)_settings.get(Settings.APPLET_PORT)).intValue());
	    _socketClient = new SSLSocketClient();
	    //centerWindowOnScreen(this);

	    if (_isDebugMode) {
		Debug.writeln(getClass().getName() + ": started applet server socket on port " + ((Integer)_settings.get(Settings.APPLET_PORT)).intValue());
	    }
	}
	catch(Exception e) {
	    if (_isDebugMode) {
		Debug.writeln(getClass().getName() + ": Error - could not open server socket - " + e.getMessage());
	    }
	    // could not open server socket, exiting
	    System.exit(1);
	}
    }


    /**
     * executes this method after initialization
     */
    public void start()
    {
	while (_isListening) {
	    if (_isDebugMode) {
		Debug.writeln(getClass().getName() + ": started Applet");
	    }
	    
	    try {
		final Socket socket = _serverSocket.accept();
		
		if (_isDebugMode) {
		    Debug.writeln(getClass().getName() + ": creating a new thread to take care of requests from the browser");
		}	    
		Thread thread = new Thread(new Runnable() {
			public void run() {
			    try {
			 	DataInputStream inFromBrowser = new DataInputStream(socket.getInputStream());
				DataOutputStream outToBrowser = new DataOutputStream(socket.getOutputStream());
			
				// forwarding streams to SSLSocketClient
				socket.setSoTimeout(5000);	
				_socketClient.sendRequest(inFromBrowser, outToBrowser);
				socket.close();
				if (_isDebugMode){
					Debug.writeln(getClass().getName()+": Socket closed");
				}	
			    } 
			    catch(Exception e) {
				if (_isDebugMode) {
				    Debug.writeln(getClass().getName() + ": Error - " + e.getMessage());
				}
			    }
			}
		    });
		thread.start();
	    }
	    catch (Exception e) {
		if (_isDebugMode) {
		    Debug.writeln(getClass().getName() + ": Error - " + e.getMessage());
		}
	    }
	}
    }


    /**
     * stops applet execution
     */
    public void stop()
    {
	try {
	    _serverSocket.close();
	}
	catch (Exception e) {
	    if (_isDebugMode) {
		Debug.writeln(getClass().getName() + ": Error - closing server socket - " + e.getMessage());
	    }
	}
    }
 

}
