/**
 *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
 * 
 * This software is licensed under the GNU General Public License v3 or later.
 * 
 * It is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 * 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, see <http://www.gnu.org/licenses/>.
 * 
 */
package com.cloud.consoleproxy;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

import javax.net.ssl.SSLServerSocket;

import org.apache.log4j.xml.DOMConfigurator;

import com.cloud.console.AuthenticationException;
import com.cloud.console.Logger;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.sun.net.httpserver.HttpServer;

public class ConsoleProxy {
	private static final Logger s_logger = Logger.getLogger(ConsoleProxy.class);
	
	public static final int KEYBOARD_RAW = 0;
	public static final int KEYBOARD_COOKED = 1;

	public static Object context;
	
	// this has become more ugly, to store keystore info passed from management server (we now use management server managed keystore to support
	// dynamically changing to customer supplied certificate)
	public static byte[] ksBits;
	public static String ksPassword;
	
	public static Method authMethod;
	public static Method reportMethod;
	public static Method ensureRouteMethod;

	static Hashtable<String, ConsoleProxyViewer> connectionMap = new Hashtable<String, ConsoleProxyViewer>();
	static int tcpListenPort = 5999;
	static int httpListenPort = 80;
	static int httpCmdListenPort = 8001;
	static String jarDir = "./applet/";
	static boolean compressServerMessage = true;
	static int viewerLinger = 180;
	static int reconnectMaxRetry = 5;
	static int readTimeoutSeconds = 90;
	static int keyboardType = KEYBOARD_RAW;
	static String factoryClzName;
	static boolean standaloneStart = false;

	private static void configLog4j() {
		URL configUrl = System.class.getResource("/conf/log4j-cloud.xml");
		if(configUrl == null)
			configUrl = System.class.getClassLoader().getSystemResource("log4j-cloud.xml");
		
		if(configUrl == null)
			configUrl = System.class.getClassLoader().getSystemResource("conf/log4j-cloud.xml");
			
		if(configUrl != null) {
			try {
				System.out.println("Configure log4j using " + configUrl.toURI().toString());
			} catch (URISyntaxException e1) {
				e1.printStackTrace();
			}

			try {
				File file = new File(configUrl.toURI());
				
				System.out.println("Log4j configuration from : " + file.getAbsolutePath());
				DOMConfigurator.configureAndWatch(file.getAbsolutePath(), 10000);
			} catch (URISyntaxException e) {
				System.out.println("Unable to convert log4j configuration Url to URI");
			}
			// DOMConfigurator.configure(configUrl);
		} else {
			System.out.println("Configure log4j with default properties");
		}
	}

	private static void configProxy(Properties conf) {
		s_logger.info("Configure console proxy...");
		for(Object key : conf.keySet()) {
			s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key));
		}
		
		String s = conf.getProperty("consoleproxy.tcpListenPort");
		if (s!=null) {
			tcpListenPort = Integer.parseInt(s);
			s_logger.info("Setting tcpListenPort=" + s);
		}
		
		s = conf.getProperty("consoleproxy.httpListenPort");
		if (s!=null) {
			httpListenPort = Integer.parseInt(s);
			s_logger.info("Setting httpListenPort=" + s);
		}
		
		s = conf.getProperty("premium");
		if(s != null && s.equalsIgnoreCase("true")) {
			s_logger.info("Premium setting will override settings from consoleproxy.properties, listen at port 443");
			httpListenPort = 443;
			factoryClzName = "com.cloud.consoleproxy.ConsoleProxySecureServerFactoryImpl";
		} else {
			factoryClzName = ConsoleProxyBaseServerFactoryImpl.class.getName();
		}
		
		s = conf.getProperty("consoleproxy.httpCmdListenPort");
		if (s!=null) {
			httpCmdListenPort = Integer.parseInt(s);
			s_logger.info("Setting httpCmdListenPort=" + s);
		}
		s = conf.getProperty("consoleproxy.jarDir");
		if (s!=null) {
			jarDir = s;
			s_logger.info("Setting jarDir=" + s);
		}
		s = conf.getProperty("consoleproxy.viewerLinger");
		if (s!=null) {
			viewerLinger = Integer.parseInt(s);
			s_logger.info("Setting viewerLinger=" + s);
		}
		s = conf.getProperty("consoleproxy.compressServerMessage");
		if (s!=null) {
			compressServerMessage = Boolean.parseBoolean(s);
			s_logger.info("Setting compressServerMessage=" + s);
		}
		
		s = conf.getProperty("consoleproxy.reconnectMaxRetry");
		if (s!=null) {
			reconnectMaxRetry = Integer.parseInt(s);
			s_logger.info("Setting reconnectMaxRetry=" + reconnectMaxRetry);
		}
		
		s = conf.getProperty("consoleproxy.readTimeoutSeconds");
		if (s!=null) {
			readTimeoutSeconds = Integer.parseInt(s);
			s_logger.info("Setting readTimeoutSeconds=" + readTimeoutSeconds);
		}
	}
	
	public static ConsoleProxyServerFactory getHttpServerFactory() {
		try {
			Class<?> clz = Class.forName(factoryClzName);
			try {
				ConsoleProxyServerFactory factory = (ConsoleProxyServerFactory)clz.newInstance();
				factory.init(ConsoleProxy.ksBits, ConsoleProxy.ksPassword);
				return factory;
			} catch (InstantiationException e) {
				s_logger.error(e.getMessage(), e);
				return null;
			} catch (IllegalAccessException e) {
				s_logger.error(e.getMessage(), e);
				return null;
			}
		} catch (ClassNotFoundException e) {
			s_logger.warn("Unable to find http server factory class: " + factoryClzName);
			return new ConsoleProxyBaseServerFactoryImpl();
		}
	}
	
	public static boolean authenticateConsoleAccess(String host, String port, String vmId, String sid, String ticket) {
		if(standaloneStart)
			return true;
		
		if(authMethod != null) {
			Object result;
			try {
				result = authMethod.invoke(ConsoleProxy.context, host, port, vmId, sid, ticket);
			} catch (IllegalAccessException e) {
				s_logger.error("Unable to invoke authenticateConsoleAccess due to IllegalAccessException" + " for vm: " + vmId, e);
				return false;
			} catch (InvocationTargetException e) {
				s_logger.error("Unable to invoke authenticateConsoleAccess due to InvocationTargetException " + " for vm: " + vmId, e);
				return false;
			}
			
			if(result != null && result instanceof Boolean) {
				return ((Boolean)result).booleanValue();
			} else {
				s_logger.error("Invalid authentication return object " + result + " for vm: " + vmId + ", decline the access");
				return false;
			}
			
		} else {
			s_logger.warn("Private channel towards management server is not setup. Switch to offline mode and allow access to vm: " + vmId);
			return true;
		}
	}
	
	public static void reportLoadInfo(String gsonLoadInfo) {
		if(reportMethod != null) {
			try {
				reportMethod.invoke(ConsoleProxy.context, gsonLoadInfo);
			} catch (IllegalAccessException e) {
				s_logger.error("Unable to invoke reportLoadInfo due to " + e.getMessage());
			} catch (InvocationTargetException e) {
				s_logger.error("Unable to invoke reportLoadInfo due to " + e.getMessage());
			}
		} else {
			s_logger.warn("Private channel towards management server is not setup. Switch to offline mode and ignore load report");
		}
	}
	
	public static void ensureRoute(String address) {
		if(ensureRouteMethod != null) {
			try {
				ensureRouteMethod.invoke(ConsoleProxy.context, address);
			} catch (IllegalAccessException e) {
				s_logger.error("Unable to invoke ensureRoute due to " + e.getMessage());
			} catch (InvocationTargetException e) {
				s_logger.error("Unable to invoke ensureRoute due to " + e.getMessage());
			}
		} else {
			s_logger.warn("Unable to find ensureRoute method, console proxy agent is not up to date");
		}
	}
	
	public static void startWithContext(Properties conf, Object context, byte[] ksBits, String ksPassword) {
		s_logger.info("Start console proxy with context");
		if(conf != null) {
			for(Object key : conf.keySet()) {
				s_logger.info("Context property " + (String)key + ": " + conf.getProperty((String)key));
			}
		}
		
		configLog4j();
		Logger.setFactory(new ConsoleProxyLoggerFactory());
		
		// Using reflection to setup private/secure communication channel towards management server
		ConsoleProxy.context = context;
		ConsoleProxy.ksBits = ksBits;
		ConsoleProxy.ksPassword = ksPassword;
		try {
			Class<?> contextClazz = Class.forName("com.cloud.agent.resource.consoleproxy.ConsoleProxyResource");
			authMethod = contextClazz.getDeclaredMethod("authenticateConsoleAccess", String.class, String.class, String.class, String.class, String.class);
			reportMethod = contextClazz.getDeclaredMethod("reportLoadInfo", String.class);
			ensureRouteMethod = contextClazz.getDeclaredMethod("ensureRoute", String.class);
		} catch (SecurityException e) {
			s_logger.error("Unable to setup private channel due to SecurityException", e);
		} catch (NoSuchMethodException e) {
			s_logger.error("Unable to setup private channel due to NoSuchMethodException", e);
		} catch (IllegalArgumentException e) {
			s_logger.error("Unable to setup private channel due to IllegalArgumentException", e);
		} catch(ClassNotFoundException e) {
			s_logger.error("Unable to setup private channel due to ClassNotFoundException", e);
		}
		
		// merge properties from conf file
		InputStream confs = ConsoleProxy.class.getResourceAsStream("/conf/consoleproxy.properties");
		Properties props = new Properties();
		if (confs == null) {
			s_logger.info("Can't load consoleproxy.properties from classpath, will use default configuration");
		} else {
			try {
				props.load(confs);
				
				for(Object key : props.keySet()) {
					// give properties passed via context high priority, treat properties from consoleproxy.properties
					// as default values
					if(conf.get(key) == null)
						conf.put(key, props.get(key));
				}
			}  catch (Exception e) {
				s_logger.error(e.toString(), e);
			}
		}
		
		start(conf);
	}

	public static void start(Properties conf) {
		System.setProperty("java.awt.headless", "true");
		
		configProxy(conf);
		
		ConsoleProxyServerFactory factory = getHttpServerFactory();
		if(factory == null) {
			s_logger.error("Unable to load console proxy server factory");
			System.exit(1);
		}
		
		if(httpListenPort != 0) {
			startupHttpMain();
		} else {
			s_logger.error("A valid HTTP server port is required to be specified, please check your consoleproxy.httpListenPort settings");
			System.exit(1);
		}
		
	    if(httpCmdListenPort > 0) {
	    	startupHttpCmdPort();
	    } else {
	    	s_logger.info("HTTP command port is disabled");
	    }
	    
		ViewerGCThread cthread = new ViewerGCThread(connectionMap);
		cthread.setName("Viewer GC Thread");
		cthread.start();
		
		if(tcpListenPort > 0) {
			SSLServerSocket srvSock = null;
			try {
				srvSock = factory.createSSLServerSocket(tcpListenPort);
			    s_logger.info("Listening for TCP on port " + tcpListenPort);
			} catch (IOException ioe) {
				s_logger.error(ioe.toString(), ioe);
				System.exit(1);
			}
			
			if(srvSock != null) {
				while (true) {
				    Socket conn = null;
				    try {
				        conn = srvSock.accept();
				        String srcinfo = conn.getInetAddress().getHostAddress() + ":" + conn.getPort();
				        s_logger.info("Accepted connection from " + srcinfo);
				        conn.setSoLinger(false,0);
				        ConsoleProxyClientHandler worker = new ConsoleProxyClientHandler(conn);
				        worker.setName("Proxy Thread " + worker.getId() + " <" + srcinfo);
				        worker.start();
				    } catch (IOException ioe2) {
						s_logger.error(ioe2.toString(), ioe2);
						try {
						    if (conn != null) {
						        conn.close();
						    }
						} catch (IOException ioe) {}
				    } catch (Throwable e) {
				    	// Something really bad happened
				    	// Terminate the program
				    	s_logger.error(e.toString(), e);
				    	System.exit(1);
				    }
				}
			} else {
		    	s_logger.warn("TCP port is enabled in configuration but we are not able to instantiate server socket.");
			}
		} else {
	    	s_logger.info("TCP port is disabled for applet viewers");
		}
	}
	
	private static void startupHttpMain() {
		try {
			ConsoleProxyServerFactory factory = getHttpServerFactory();
			if(factory == null) {
				s_logger.error("Unable to load HTTP server factory");
				System.exit(1);
			}
			
			HttpServer server = factory.createHttpServerInstance(httpListenPort);
			server.createContext("/getscreen", new ConsoleProxyThumbnailHandler());
			server.createContext("/resource/", new ConsoleProxyResourceHandler());
			server.createContext("/ajax", new ConsoleProxyAjaxHandler());
			server.createContext("/ajaximg", new ConsoleProxyAjaxImageHandler());
			server.setExecutor(new ThreadExecutor()); // creates a default executor
			server.start();
		} catch(Exception e) {
			s_logger.error(e.getMessage(), e);
			System.exit(1);
		}
	}
	
	private static void startupHttpCmdPort() {
		try {
		    s_logger.info("Listening for HTTP CMDs on port " + httpCmdListenPort);
			HttpServer cmdServer = HttpServer.create(new InetSocketAddress(httpCmdListenPort), 2);
			cmdServer.createContext("/cmd", new ConsoleProxyCmdHandler());
			cmdServer.setExecutor(new ThreadExecutor()); // creates a default executor
			cmdServer.start();
		} catch(Exception e) {
			s_logger.error(e.getMessage(), e);
			System.exit(1);
		}
	}
	
	public static void main(String[] argv) {
		standaloneStart = true;
		configLog4j();
		Logger.setFactory(new ConsoleProxyLoggerFactory());
		
		InputStream confs = ConsoleProxy.class.getResourceAsStream("/conf/consoleproxy.properties");
		Properties conf = new Properties();
		if (confs == null) {
			s_logger.info("Can't load consoleproxy.properties from classpath, will use default configuration");
		} else {
			try {
				conf.load(confs);
			}  catch (Exception e) {
				s_logger.error(e.toString(), e);
			}
		}
		start(conf);
	}

	static ConsoleProxyViewer createViewer() {
		ConsoleProxyViewer viewer = new ConsoleProxyViewer();
		viewer.compressServerMessage = compressServerMessage;
		return viewer;
	}
	
	static void initViewer(ConsoleProxyViewer viewer, String host, int port, String tag, String sid, String ticket) throws AuthenticationException {
		ConsoleProxyViewer.authenticationExternally(host, String.valueOf(port), tag, sid, ticket);
		
		viewer.host = host;
		viewer.port = port;
		viewer.tag = tag;
		viewer.passwordParam = sid;
		
		viewer.init();
	}
	
	static ConsoleProxyViewer getVncViewer(String host, int port, String sid, String tag, String ticket) throws Exception {
		ConsoleProxyViewer viewer = null;
		
		boolean reportLoadChange = false;
		synchronized (connectionMap) {
			viewer = connectionMap.get(host + ":" + port);
			if (viewer == null) {
				viewer = createViewer();
				initViewer(viewer, host, port, tag, sid, ticket);
				connectionMap.put(host + ":" + port, viewer);
				s_logger.info("Added viewer object " + viewer);
				
				reportLoadChange = true;
			} else if (!viewer.rfbThread.isAlive()) {
				s_logger.info("The rfb thread died, reinitializing the viewer " +
						viewer);
				initViewer(viewer, host, port, tag, sid, ticket);
				
				reportLoadChange = true;
			} else if (!sid.equals(viewer.passwordParam)) {
				s_logger.warn("Bad sid detected(VNC port may be reused). sid in session: " + viewer.passwordParam + ", sid in request: " + sid);
				initViewer(viewer, host, port, tag, sid, ticket);
				
				reportLoadChange = true;
					
				/*
				throw new AuthenticationException ("Cannot use the existing viewer " +
						viewer + ": bad sid");
				*/
			}
		}
		
		if(viewer != null) {
			if (viewer.status == ConsoleProxyViewer.STATUS_NORMAL_OPERATION) {
				// Do not update lastUsedTime if the viewer is in the process of starting up
				// or if it failed to authenticate.
				viewer.lastUsedTime = System.currentTimeMillis();
			}
		}
		
		if(reportLoadChange) {
			ConsoleProxyStatus status = new ConsoleProxyStatus();
			status.setConnections(ConsoleProxy.connectionMap);
			Gson gson = new GsonBuilder().setPrettyPrinting().create();
			String loadInfo = gson.toJson(status);
			
			ConsoleProxy.reportLoadInfo(loadInfo);
			if(s_logger.isDebugEnabled())
				s_logger.debug("Report load change : " + loadInfo);
		}
		
		return viewer;
	}
	
	static ConsoleProxyViewer getAjaxVncViewer(String host, int port, String sid, String tag, String ticket, String ajaxSession) throws Exception {
		boolean reportLoadChange = false;
		synchronized (connectionMap) {
			ConsoleProxyViewer viewer = connectionMap.get(host + ":" + port);
//			s_logger.info("view lookup " + host + ":" + port + " = " + viewer);

			if (viewer == null) {
				viewer = createViewer();
				viewer.ajaxViewer = true;
				
				initViewer(viewer, host, port, tag, sid, ticket);
				connectionMap.put(host + ":" + port, viewer);
				s_logger.info("Added viewer object " + viewer);
				reportLoadChange = true;
			} else if (!viewer.rfbThread.isAlive()) {
				s_logger.info("The rfb thread died, reinitializing the viewer " +
						viewer);
				initViewer(viewer, host, port, tag, sid, ticket);
				reportLoadChange = true;
			} else if (!sid.equals(viewer.passwordParam)) {
				s_logger.warn("Bad sid detected(VNC port may be reused). sid in session: " + viewer.passwordParam + ", sid in request: " + sid);
				initViewer(viewer, host, port, tag, sid, ticket);
				reportLoadChange = true;
				
				/*
				throw new AuthenticationException ("Cannot use the existing viewer " +
						viewer + ": bad sid");
				*/
			} else {
				if(ajaxSession == null || ajaxSession.isEmpty())
					ConsoleProxyViewer.authenticationExternally(host, String.valueOf(port), tag, sid, ticket);
			}
			
			if (viewer.status == ConsoleProxyViewer.STATUS_NORMAL_OPERATION) {
				// Do not update lastUsedTime if the viewer is in the process of starting up
				// or if it failed to authenticate.
				viewer.lastUsedTime = System.currentTimeMillis();
			}
			
			if(reportLoadChange) {
				ConsoleProxyStatus status = new ConsoleProxyStatus();
				status.setConnections(ConsoleProxy.connectionMap);
				Gson gson = new GsonBuilder().setPrettyPrinting().create();
				String loadInfo = gson.toJson(status);
				
				ConsoleProxy.reportLoadInfo(loadInfo);
				if(s_logger.isDebugEnabled())
					s_logger.debug("Report load change : " + loadInfo);
			}
			return viewer;
		}
	}
	
	public static void removeViewer(ConsoleProxyViewer viewer) {
		synchronized (connectionMap) {
			for(Map.Entry<String, ConsoleProxyViewer> entry : connectionMap.entrySet()) {
				if(entry.getValue() == viewer) {
					connectionMap.remove(entry.getKey());
					return;
				}
			}
		}
	}
	
	static void waitForViewerToStart(ConsoleProxyViewer viewer) throws Exception {
		if (viewer.status == ConsoleProxyViewer.STATUS_NORMAL_OPERATION) {
			return;
		}

		Long startTime = System.currentTimeMillis();
		int delay = 500;
		
		while (System.currentTimeMillis() < startTime + 30000 &&
				viewer.status != ConsoleProxyViewer.STATUS_NORMAL_OPERATION) {
			if (viewer.status == ConsoleProxyViewer.STATUS_AUTHENTICATION_FAILURE) {
				throw new Exception ("Authentication failure");
			}
			try {
				Thread.sleep(delay);
			} catch (InterruptedException e) {
				// ignore
			}
			delay = (int)(delay * 1.5);
		}
		
		if (viewer.status != ConsoleProxyViewer.STATUS_NORMAL_OPERATION) {
			throw new Exception ("Cannot start VncViewer");
		}
		
		s_logger.info("Waited " +
				(System.currentTimeMillis() - startTime) + "ms for VncViewer to start");
	}

	static class ThreadExecutor implements Executor {
	     public void execute(Runnable r) {
	         new Thread(r).start();
	     }
	}

    static class ViewerGCThread extends Thread {
    	Hashtable<String, ConsoleProxyViewer> connMap;
    	long lastLogScan = 0L;
    	
    	public ViewerGCThread(Hashtable<String, ConsoleProxyViewer> connMap) {
    		this.connMap = connMap;
    	}
    	
		private void cleanupLogging() {
			if(lastLogScan != 0 && System.currentTimeMillis() - lastLogScan < 3600000)
				return;
			lastLogScan = System.currentTimeMillis();
			
			File logDir = new File("./logs");
			File files[] = logDir.listFiles();
			if(files != null) {
				for(File file : files) {
					if(System.currentTimeMillis() - file.lastModified() >= 86400000L) {
						try {
							file.delete();
						} catch(Throwable e) {
						}
					}
				}
			}
		}
    	
    	@Override
        public void run() {
    		while (true) {
    			cleanupLogging();
    			
    			s_logger.info("connMap=" + connMap);
    			Enumeration<String> e = connMap.keys();
    		    while (e.hasMoreElements()) {
    		    	String key;
    		    	ConsoleProxyViewer viewer;
    		    	
    		    	synchronized (connMap) {
	    		        key  = e.nextElement();
	    		        viewer  = connMap.get(key);
    		    	}

	    		    long seconds_unused =
	    		        (System.currentTimeMillis() - viewer.lastUsedTime) / 1000;
	    		         
	    		    if (seconds_unused > viewerLinger / 2 && viewer.clientStream != null) {
	    		    	s_logger.info("Pinging client for " + viewer +
	    		    			" which has not been used for " + seconds_unused + "sec");
	    		    	byte[] bs = new byte[2];
	    		        bs[0] = (byte)250;
	    		        bs[1] = 3;
	    		        viewer.writeToClientStream(bs);
	    		    }
	    		    
	    		    if (seconds_unused < viewerLinger) {
	    		      	continue;
	    		    }
	    		    
    		    	synchronized (connMap) {
    		    		connMap.remove(key);
    		    	}
	    		    // close the server connection
	    		    s_logger.info("Dropping " + viewer +
	    		        		 " which has not been used for " +
	    		        		 seconds_unused + " seconds");
	    		    viewer.dropMe = true;
	    		    synchronized (viewer) {
		    		    if (viewer.clientStream != null) {
		    		    	try {
		    		    		viewer.clientStream.close();
		    		    	} catch (IOException ioe) {
		    		    		// ignored
		    		    	}
				    		viewer.clientStream = null;
				    		viewer.clientStreamInfo = null;
		    		    }
	    		        if (viewer.rfb != null) {
	    		        	viewer.rfb.close();
	    		        }
    		    	}

	    		    // report load change for removal of the viewer
    				ConsoleProxyStatus status = new ConsoleProxyStatus();
    				status.setConnections(ConsoleProxy.connectionMap);
    				Gson gson = new GsonBuilder().setPrettyPrinting().create();
    				String loadInfo = gson.toJson(status);
    				
    				ConsoleProxy.reportLoadInfo(loadInfo);
    				if(s_logger.isDebugEnabled())
    					s_logger.debug("Report load change : " + loadInfo);
    		    }
    			try {
    				Thread.sleep(30000);
    			} catch (InterruptedException exp) {
    				// Ignore
    			}
    		}
    	}
    }
}
