/**
 * 
 * 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.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.List;
import java.util.zip.GZIPOutputStream;

import org.apache.log4j.Logger;

import com.cloud.console.AuthenticationException;
import com.cloud.console.ConsoleCanvas;
import com.cloud.console.ConsoleCanvas2;
import com.cloud.console.ITileScanListener;
import com.cloud.console.Region;
import com.cloud.console.RfbProto;
import com.cloud.console.RfbProtoAdapter;
import com.cloud.console.RfbViewer;
import com.cloud.console.TileInfo;
import com.cloud.console.TileTracker;

public class ConsoleProxyViewer implements java.lang.Runnable, RfbViewer, RfbProtoAdapter, ITileScanListener {
	private static final Logger s_logger = Logger.getLogger(ConsoleProxyViewer.class);
	
	public final static int STATUS_ERROR = -1;
	public final static int STATUS_UNINITIALIZED = 0;
	public final static int STATUS_CONNECTING = 1;
	public final static int STATUS_INITIALIZING = 2;
	public final static int STATUS_NORMAL_OPERATION = 3;
	public final static int STATUS_AUTHENTICATION_FAILURE = 100;
	
	public final static int SHIFT_KEY_MASK = 64;
	public final static int CTRL_KEY_MASK = 128;
	public final static int META_KEY_MASK = 256;
	public final static int ALT_KEY_MASK = 512;
	
	int id = getNextId();
	boolean compressServerMessage = false;
	long createTime = System.currentTimeMillis();
	long lastUsedTime = System.currentTimeMillis();
	int status;
	boolean dropMe = false;
	boolean viewerInReuse = false; 
	
	String host;
	int port;
	String tag = "";
	
	RfbProto rfb;
	Thread rfbThread;
	OutputStream clientStream;
	String clientStreamInfo;
	String passwordParam;
	
	ViewerOptions options;
	Frame vncFrame;
	ConsoleCanvas vc;
	Container vncContainer;
	
	boolean ajaxViewer = false;
	long ajaxSessionId = 0;
	TileTracker tracker;
	Object tileDirtyEvent;
	boolean dirtyFlag = false;
	boolean justCreated = true;
	AjaxFIFOImageCache ajaxImageCache = new AjaxFIFOImageCache(2);
	
	String cursorUpdatesDef;
	String eightBitColorsDef;
	
	int deferScreenUpdates;
	int deferCursorUpdates;
	int deferUpdateRequests;
	
	int[] encodingsSaved;
	int nEncodingsSaved;

	boolean framebufferResized = false;
	int resizedFramebufferWidth;
	int resizedFramebufferHeight;
	
	boolean cursorMoved = false;
	int lastCursorPosX;
	int lastCursorPosY;
	
	boolean cursorShapeChanged = false;
	int lastCursorShapeEncodingType;
	int lastCursorShapeHotX;
	int lastCursorShapeHotY;
	int lastCursorShapeWidth;
	int lastCursorShapeHeight;
	byte[] lastCursorShapeData;
	
	static int id_count = 1;
	synchronized static int getNextId() {
		return id_count++;
	}

	public void init() {
		initProxy();
	}
	
	private void initProxy() {
		options = new ViewerOptions();
		options.viewOnly = true;

		cursorUpdatesDef = null;
		eightBitColorsDef = null;
		
		tracker = new TileTracker();
		tracker.initTracking(64, 64, 800, 600);

		if(rfbThread != null) {
			if(rfbThread.isAlive()) {
				dropMe = true;
				viewerInReuse = true;
				if(rfb != null)
					rfb.close();
				
				try {
					rfbThread.join();
				} catch (InterruptedException e) {
					s_logger.warn("InterruptedException while waiting for RFB thread to exit");
				}
				viewerInReuse = false;
			}
		}
		
		dropMe = false;
		rfbThread = new Thread(this);
		rfbThread.setName("RFB Thread " + rfbThread.getId() + " >" + host + ":" + port);
		rfbThread.start();

		tileDirtyEvent = new Object();
	}
	
	public synchronized boolean justCreated() {
		if(justCreated) {
			justCreated = false;
			return true;
		}
		return false;
	}
	
	public boolean isDropped() {
		return dropMe;
	}
	
	public void run() {
		createCanvas(0, 0);

		int retries = 0;
		while (!dropMe) {
			try {
				s_logger.info("Connecting to VNC server");
				status = STATUS_CONNECTING;
				connectAndAuthenticate();
				retries = 0; // reset the retry count
				status = STATUS_INITIALIZING;
				doProtocolInitialisation();
				vc.rfb = rfb;
				vc.setPixelFormat();

				// if we have a client current connected, when we have reconnected to the server and
				// received a new ServerInit info (in doProtocolInitialisation()), we will
				// convert it into frame buffer size change to make sure following on updates
				// don't fall out of range
				//
				if(clientStream != null) {
					// 128 bytes will be enough for this single PDU
					s_logger.info("Send init framebuffer size (" + rfb.framebufferWidth + ", " + rfb.framebufferHeight + ")");
					
					ByteArrayOutputStream bos = new ByteArrayOutputStream(128);
					try {
						vc.encodeFramebufferResize(rfb.framebufferWidth, rfb.framebufferHeight, bos);
					} catch(IOException e) {
					}
					writeToClientStream(bos.toByteArray());
				}
				
				vc.rfb.writeFramebufferUpdateRequest(0, 0,
						vc.rfb.framebufferWidth, vc.rfb.framebufferHeight,
						true);
				status = STATUS_NORMAL_OPERATION;
				vc.processNormalProtocol();
			} catch (AuthenticationException e) {
				status = STATUS_AUTHENTICATION_FAILURE;
				String msg = e.getMessage();
				s_logger.warn("Authentication exception, msg: " + msg + "sid: " + this.passwordParam);
			} catch (Exception e) {
				status = STATUS_ERROR;
				s_logger.error("Unexpected exception ", e);
			} finally {
				// String oldName = Thread.currentThread().getName();
				encodingsSaved = null;
				nEncodingsSaved = 0;
				
				s_logger.info("Close current RFB");
				synchronized (this) {
					if (rfb != null) {
						rfb.close();
					}
				}
			}
			if (dropMe) {
				break;
			}
			if (status == STATUS_AUTHENTICATION_FAILURE) {
				break;
			} else {
				retries++;
				if(retries > ConsoleProxy.reconnectMaxRetry) {
					s_logger.info("Exception caught, retry has reached to maximum : " + retries + ", will give up and disconnect client");
					break;
				}
				
				s_logger.info("Exception caught, retrying in 1 second, current retry:" + retries);
				
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// ignored
				}
			}
		}
		
		// make sure we remove it from the management map upon main thread termination
		dropMe = true;
		
		// if we are reusing the viewer object, we shouldn't remove it from the map
		// this can also prevent deadlock in initProxy() while initProxy tries to join
		// the thread, as initProxy() is called with ConsoleProxy.connectionMap being locked
		// while CoonsoleProxy.removeViewer() here will attempt to lock it from another thread
		if(!viewerInReuse)		
			ConsoleProxy.removeViewer(this);
		s_logger.info("RFB thread terminating");
	}
	
	void connectAndAuthenticate() throws Exception {
		s_logger.info("Initializing...");
		
		s_logger.info("Ensure ip route towards host " + host);
		ConsoleProxy.ensureRoute(host);		
		
		s_logger.info("Connecting to " + host + ", port " + port + "...");
		rfb = new RfbProto(host, port, this);
		s_logger.info("Connected to server");

		rfb.readVersionMsg();
		s_logger.info("RFB server supports protocol version "
				+ rfb.serverMajor + "." + rfb.serverMinor);

		rfb.writeVersionMsg();
		s_logger.info("Using RFB protocol version " + rfb.clientMajor
				+ "." + rfb.clientMinor);

		int secType = rfb.negotiateSecurity();
		int authType;
		if (secType == RfbProto.SecTypeTight) {
			s_logger.info("Enabling TightVNC protocol extensions");
			rfb.initCapabilities();
			rfb.setupTunneling();
			authType = rfb.negotiateAuthenticationTight();
		} else {
			authType = secType;
		}

		switch (authType) {
		case RfbProto.AuthNone:
			s_logger.info("No authentication needed");
			rfb.authenticateNone();
			break;
		case RfbProto.AuthVNC:
			s_logger.info("Performing standard VNC authentication");
			if (passwordParam != null) {
				rfb.authenticateVNC(passwordParam);
			} else {
				throw new AuthenticationException("Bad password");
			}
			break;
		default:
			throw new Exception("Unknown authentication scheme " + authType);
		}
	}
	
	static void authenticationExternally(String host, String port, String tag, String sid, String ticket) throws AuthenticationException {
/*		
		if(ConsoleProxy.management_host != null) {
			try {
				boolean success = false;
				URL url = new URL(ConsoleProxy.management_host + "/console?cmd=auth&vm=" + getTag() + "&sid=" + passwordParam);
				
				URLConnection conn = url.openConnection();
				
				// setting TIMEOUTs to avoid possible waiting until death situations
				conn.setConnectTimeout(5000);
				conn.setReadTimeout(5000);
				
		        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
		        String inputLine;
		        if ((inputLine = in.readLine()) != null) { 
		            if(inputLine.equals("success"))
		            	success = true;
		        }
		        in.close();
		        
		        if(!success) {
		        	if(s_logger.isInfoEnabled())
		        		s_logger.info("External authenticator failed authencation request for vm " + getTag() + " with sid " + passwordParam);
		        	
					throw new AuthenticationException("Unable to contact external authentication source " + ConsoleProxy.management_host);
		        }
			} catch (MalformedURLException e) {
				s_logger.error("Unexpected exception " + e.getMessage(), e);
			} catch(IOException e) {
				s_logger.error("Unable to contact external authentication source due to " + e.getMessage(), e);
				throw new AuthenticationException("Unable to contact external authentication source " + ConsoleProxy.management_host);
			}
		} else {
			s_logger.warn("No external authentication source being setup.");
		}
*/
		if(!ConsoleProxy.authenticateConsoleAccess(host, port, tag, sid, ticket)) {
    		s_logger.warn("External authenticator failed authencation request for vm " + tag + " with sid " + sid);
        	
			throw new AuthenticationException("External authenticator failed request for vm " + tag + " with sid " + sid);
		}
	}
	
	void doProtocolInitialisation() throws IOException {
		rfb.writeClientInit();
		rfb.readServerInit();
		setEncodings();
	}
	
	void setEncodings() {
		setEncodings(false);
	}
	
	void setEncodings(boolean autoSelectOnly) {
		if (options == null || rfb == null || !rfb.inNormalProtocol)
			return;

		options.preferredEncoding = RfbProto.EncodingHextile;
		
		int preferredEncoding = options.preferredEncoding;
		if (preferredEncoding == -1) {
			long kbitsPerSecond = rfb.kbitsPerSecond();
			if (nEncodingsSaved < 1) {
				// Choose Tight or ZRLE encoding for the very first update.
				// Logger.log(Logger.INFO, "Using Tight/ZRLE encodings");
				preferredEncoding = RfbProto.EncodingTight;
			} else if (kbitsPerSecond > 2000
					&& encodingsSaved[0] != RfbProto.EncodingHextile) {
				// Switch to Hextile if the connection speed is above 2Mbps.
				s_logger.info("Throughput " + kbitsPerSecond
						+ " kbit/s - changing to Hextile encoding");
				preferredEncoding = RfbProto.EncodingHextile;
			} else if (kbitsPerSecond < 1000
					&& encodingsSaved[0] != RfbProto.EncodingTight) {
				// Switch to Tight/ZRLE if the connection speed is below 1Mbps.
				s_logger.info("Throughput " + kbitsPerSecond
						+ " kbit/s - changing to Tight/ZRLE encodings");
				preferredEncoding = RfbProto.EncodingTight;
			} else {
				// Don't change the encoder.
				if (autoSelectOnly)
					return;
				preferredEncoding = encodingsSaved[0];
			}
		} else {
			// Auto encoder selection is not enabled.
			if (autoSelectOnly)
				return;
		}

		int[] encodings = new int[20];
		int nEncodings = 0;

		encodings[nEncodings++] = preferredEncoding;
		if (options.useCopyRect) {
			encodings[nEncodings++] = RfbProto.EncodingCopyRect;
		}

		if (preferredEncoding != RfbProto.EncodingTight) {
			encodings[nEncodings++] = RfbProto.EncodingTight;
		}
		if (preferredEncoding != RfbProto.EncodingZRLE) {
			encodings[nEncodings++] = RfbProto.EncodingZRLE;
		}
		if (preferredEncoding != RfbProto.EncodingHextile) {
			encodings[nEncodings++] = RfbProto.EncodingHextile;
		}
		if (preferredEncoding != RfbProto.EncodingZlib) {
			encodings[nEncodings++] = RfbProto.EncodingZlib;
		}
		if (preferredEncoding != RfbProto.EncodingCoRRE) {
			encodings[nEncodings++] = RfbProto.EncodingCoRRE;
		}
		if (preferredEncoding != RfbProto.EncodingRRE) {
			encodings[nEncodings++] = RfbProto.EncodingRRE;
		}

		if (options.compressLevel >= 0 && options.compressLevel <= 9) {
			encodings[nEncodings++] = RfbProto.EncodingCompressLevel0
					+ options.compressLevel;
		}
		if (options.jpegQuality >= 0 && options.jpegQuality <= 9) {
			encodings[nEncodings++] = RfbProto.EncodingQualityLevel0
					+ options.jpegQuality;
		}

		if (options.requestCursorUpdates) {
			encodings[nEncodings++] = RfbProto.EncodingXCursor;
			encodings[nEncodings++] = RfbProto.EncodingRichCursor;
			if (!options.ignoreCursorUpdates)
				encodings[nEncodings++] = RfbProto.EncodingPointerPos;
		}

		encodings[nEncodings++] = RfbProto.EncodingLastRect;
		encodings[nEncodings++] = RfbProto.EncodingNewFBSize;

		boolean encodingsWereChanged = false;
		if (nEncodings != nEncodingsSaved) {
			encodingsWereChanged = true;
		} else {
			for (int i = 0; i < nEncodings; i++) {
				if (encodings[i] != encodingsSaved[i]) {
					encodingsWereChanged = true;
					break;
				}
			}
		}

		if (encodingsWereChanged) {
			try {
				rfb.writeSetEncodings(encodings, nEncodings);
				if (vc != null) {
					vc.softCursorFree();
				}
			} catch (Exception e) {
				s_logger.error(e.toString(), e);
			}
			encodingsSaved = encodings;
			nEncodingsSaved = nEncodings;
		}
	}

	protected void startRecording() throws IOException {
	}
	
	protected void stopRecording() throws IOException {
	}
	
	void createCanvas(int maxWidth, int maxHeight) {
		vc = new ConsoleCanvas2(this, maxWidth, maxHeight);
		
	    if (!options.viewOnly)
	        vc.enableInput(true);
	}
	
	synchronized void writeToClientStream(byte[] bs) {
		// writeToClientStream swallows exceptions to make sure problems writing
		// to client stream do not impact the main loop
		if (clientStream != null) {
			try {
				lastUsedTime = System.currentTimeMillis();
				synchronized (clientStream) {
					clientStream.write(bs);
					clientStream.flush();
				}
			} catch (IOException e) {
				if(s_logger.isDebugEnabled()) {
					s_logger.debug("Writing to client stream failed, reason: " + e.getMessage());
				}
				try {
					clientStream.close();
				} catch (IOException ioe){
					// ignore
				}
				clientStream = null;
				clientStreamInfo = null;
			  }
		}
	}
	
	//
	// Implement RfbViewer interface
	//
	public boolean isProxy() {
		return true;
	}
	
	public boolean hasClientConnection() {
		// always return false if the viewer is AJAX viewer
		if(ajaxViewer)
			return false;
		
		return clientStream != null;
	}
	
	public RfbProto getRfb() {
		return rfb;
	}
	
	public Dimension getScreenSize() {
		return (new Frame()).getToolkit().getScreenSize();
		// return vncFrame.getToolkit().getScreenSize();
	}
	
	public Dimension getFrameSize() {
		// return vncFrame.getSize();
		return getScreenSize();
	}
	
	public int getScalingFactor() {
		return options.scalingFactor;
	}
	
	public int getCursorScaleFactor() {
		return options.scaleCursor;
	}
	
	public boolean ignoreCursorUpdate() {
		return options.ignoreCursorUpdates;
	}
	
	public int getDeferCursorUpdateTimeout() {
		return 0;
		// return deferCursorUpdates; 
	}
	
	public int getDeferScreenUpdateTimeout() {
		return 0;
		// return deferScreenUpdates;
	}
	
	public int getDeferUpdateRequestTimeout() {
		return 0;
		//return deferUpdateRequests;
	}
	
	public int setPixelFormat(RfbProto rfb) throws IOException {
		if (options.eightBitColors) {
	        rfb.writeSetPixelFormat(8, 8, false, true, 7, 7, 3, 0, 3, 6);
	        return 1;
		} else {
			rfb.writeSetPixelFormat(32, 24, false, true, 255, 255, 255, 16, 8, 0);
			return 4;
		}
	}
	
	public void onInputEnabled(boolean enable) {
		// do nothing in proxy viewer
	}
	
	public void onFramebufferSizeChange(int w, int h) {
		tracker.resize(vc.scaledWidth, vc.scaledHeight);

		synchronized(this) {
			framebufferResized = true;
			resizedFramebufferWidth = w;
			resizedFramebufferHeight = h;
		}
		
		signalTileDirtyEvent();
	}
	
	public void onFramebufferUpdate(int x, int y, int w, int h) {
		if(s_logger.isTraceEnabled())
			s_logger.trace("Frame buffer update {" + x + "," + y + "," + w + "," + h + "}");
		tracker.invalidate(new Rectangle(x, y, w, h));
		
		signalTileDirtyEvent();
	}
	
	public void onFramebufferCursorMove(int x, int y) {
		synchronized(this) {
			cursorMoved = true;
			lastCursorPosX = x;
			lastCursorPosY = y;
		}
		
		signalTileDirtyEvent();
	}
	
	public void onFramebufferCursorShapeChange(int encodingType,
		    int xhot, int yhot, int width, int height, byte[] cursorData) {

		synchronized(this) {
			cursorShapeChanged = true;
			
			lastCursorShapeEncodingType = encodingType;
			lastCursorShapeHotX = xhot;
			lastCursorShapeHotY = yhot;
			lastCursorShapeWidth = width;
			lastCursorShapeHeight = height;
			lastCursorShapeData = cursorData;
		}
		
		signalTileDirtyEvent();
	}
	
	public void onDesktopResize() {
		if(vncFrame != null)
			vncFrame.pack();
	}
	
	public void onFrameResize(Dimension newSize) {
		if(vncFrame != null)
			vncFrame.setSize(newSize);
	}
	
	public void onDisconnectMessage() {
		// do nothing in viewer mode
	}
	
	public void onBellMessage() {
		Toolkit.getDefaultToolkit().beep();
	}
	
	public void onPreProtocolProcess(byte[] bs) throws IOException {
		
		if(s_logger.isTraceEnabled())
			s_logger.trace("Send " + (bs != null ? bs.length  : 0) + " bytes (original) to client");

		if (!ajaxViewer && bs != null && clientStream != null) {
			if(s_logger.isInfoEnabled())
				s_logger.info("getSplit got " + bs.length + " bytes");
			if (compressServerMessage && bs.length > 10000) {
				ByteArrayOutputStream bos = new ByteArrayOutputStream(256000);
				GZIPOutputStream gos = new GZIPOutputStream(bos, 65536);
				gos.write(bs);
				gos.finish();
				byte[] nbs = bos.toByteArray();
				gos.close();
				int n = nbs.length;
				
				if(s_logger.isInfoEnabled())
					s_logger.info("Compressed " + bs.length + "=>" + n);
				
				byte[] b = new byte[6];
				b[0] = (byte) 250;
				b[1] = 2;
				b[2] = (byte) ((n >> 24) & 0xff);
				b[3] = (byte) ((n >> 16) & 0xff);
				b[4] = (byte) ((n >> 8) & 0xff);
				b[5] = (byte) (n & 0xff);
				
				// make sure two seperated writes completed atomically
				synchronized(clientStream) {
					writeToClientStream(b);
					writeToClientStream(nbs);
				}
			} else {
				if(s_logger.isInfoEnabled())
					s_logger.info("Send uncompressed " + bs.length + " bytes to client");
				
				writeToClientStream(bs);
			}
		} else {
			if(s_logger.isTraceEnabled())
				s_logger.trace("Client is not connected, ignore forwarding " + (bs != null ? bs.length : 0) + " bytes to client");
		}
		
	    rfb.sis.setSplit();
	}
	
	public boolean onPostFrameBufferUpdateProcess(boolean cursorPosReceived) throws IOException {
		boolean fullUpdateNeeded = false;
		
		// Defer framebuffer update request if necessary. But wake up
		// immediately on keyboard or mouse event. Also, don't sleep
		// if there is some data to receive, or if the last update
		// included a PointerPos message.
		if (deferUpdateRequests > 0 && rfb.is.available() == 0 && !cursorPosReceived) {
		  synchronized(vc.rfb) {
		    try {
		      vc.rfb.wait(deferUpdateRequests);
		    } catch (InterruptedException e) {
		    }
		  }
		}

		// Before requesting framebuffer update, check if the pixel
		// format should be changed. If it should, request full update
		// instead of an incremental one.
		if (options.eightBitColors != (vc.bytesPixel == 1)) {
			vc.setPixelFormat();
			fullUpdateNeeded = true;
		}

		return fullUpdateNeeded;
	}
	
	public void onProtocolProcessException(IOException e) {
		byte[] bs = new byte[2];
		bs[0] = (byte)250;
		bs[1] = 1;
		writeToClientStream(bs);
	}
	
	public Socket createConnection(String host, int port) throws IOException {
		Socket sock = new Socket();
		sock.setSoTimeout(ConsoleProxy.readTimeoutSeconds*1000);
		sock.setKeepAlive(true);
		sock.connect(new InetSocketAddress(host, port), 30000);
		return sock;
	}
	
	public void writeInit(OutputStream os) throws IOException {
	    if (options.shareDesktop) {
	        os.write(1);
	    } else {
	    	os.write(0);
	    }
	}
	
	public void swapMouseButton(Integer[] masks) {
	    if (options.reverseMouseButtons2And3) {
	    	Integer temp = masks[1];
	    	masks[1] = masks[0];
	    	masks[0] = temp;
	      }
	}
	
	public boolean onTileChange(Rectangle rowMergedRect, int row, int col) {
		// currently we don't do scan-based client update
		return true;
	}
	
	public void onRegionChange(List<Region> regionList) {
		// obsolute
	}
	
	private void signalTileDirtyEvent() {
		synchronized(tileDirtyEvent) {
			dirtyFlag = true;
			tileDirtyEvent.notifyAll();
		}
	}
	
	public String getTag() {
		return tag;
	}
	
	public void setTag(String tag) {
		this.tag = tag;
	}
	
	//
	// AJAX Image manipulation 
	//
	public void copyTile(Graphics2D g, int x, int y, Rectangle rc) {
		if(vc != null && vc.memImage != null) {
			synchronized(vc.memImage) {
				g.drawImage(vc.memImage, x, y, x + rc.width, y + rc.height, 
					rc.x, rc.y, rc.x + rc.width, rc.y + rc.height, null);
			}
		}
	}
	
	public byte[] getFrameBufferJpeg() {
		int width = 800;
		int height = 600;
		if(vc != null) {
			width = vc.scaledWidth;
			height = vc.scaledHeight;
		}
		
		if(s_logger.isTraceEnabled())
			s_logger.trace("getFrameBufferJpeg, w: " + width + ", h: " + height);
		
		BufferedImage bufferedImage = new BufferedImage(width, height,
				BufferedImage.TYPE_3BYTE_BGR);
		if(vc != null && vc.memImage != null) {
			synchronized(vc.memImage) {
				Graphics2D g = bufferedImage.createGraphics();
				g.drawImage(vc.memImage, 0, 0, width, height, 0, 0, width, height, null);
			}
		}
		
		byte[] imgBits = null;
		try {
			imgBits = jpegFromImage(bufferedImage);
		} catch (IOException e) {
		}
		return imgBits;
	}
	
	public byte[] getTilesMergedJpeg(List<TileInfo> tileList, int tileWidth, int tileHeight) {
		
		int width = Math.max(tileWidth, tileWidth*tileList.size());
		BufferedImage bufferedImage = new BufferedImage(width, tileHeight,
			BufferedImage.TYPE_3BYTE_BGR);
		
		if(s_logger.isTraceEnabled())
			s_logger.trace("Create merged image, w: " + width + ", h: " + tileHeight);
		
		if(vc != null && vc.memImage != null) {
			synchronized(vc.memImage) {
				Graphics2D g = bufferedImage.createGraphics();
				int i = 0;
				for(TileInfo tile : tileList) {
					Rectangle rc = tile.getTileRect();
					
					if(s_logger.isTraceEnabled())
						s_logger.trace("Merge tile into jpeg from (" + rc.x + "," + rc.y + "," + (rc.x + rc.width) + "," + (rc.y + rc.height) + ") to (" + i*tileWidth + ",0)" );
					
					g.drawImage(vc.memImage, i*tileWidth, 0, i*tileWidth + rc.width, rc.height, 
						rc.x, rc.y, rc.x + rc.width, rc.y + rc.height, null);
					
					i++;
				}
			}
		}
		
		byte[] imgBits = null;
		try {
			imgBits = jpegFromImage(bufferedImage);
			
			if(s_logger.isTraceEnabled())
				s_logger.trace("Merge jpeg image size: " + imgBits.length + ", tiles: " + tileList.size());
		} catch (IOException e) {
		}
		return imgBits;
	}
	
	public byte[] jpegFromImage(BufferedImage image) throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream(128000);
		javax.imageio.ImageIO.write(image, "jpg", bos);
		
		byte[] jpegBits = bos.toByteArray();
		bos.close();
		return jpegBits;
	}
	
	private String prepareAjaxImage(List<TileInfo> tiles, boolean init) {
		byte[] imgBits;
		if(init)
			imgBits = getFrameBufferJpeg();
		else 
			imgBits = getTilesMergedJpeg(tiles, tracker.getTileWidth(), tracker.getTileHeight());
		
		if(imgBits == null) {
			s_logger.warn("Unable to generate jpeg image");
		} else {
			if(s_logger.isTraceEnabled())
				s_logger.trace("Generated jpeg image size: " + imgBits.length);
		}
		
		int key = ajaxImageCache.putImage(imgBits);
		StringBuffer sb = new StringBuffer("/ajaximg?host=");
		sb.append(host).append("&port=").append(port).append("&sid=").append(passwordParam);
		sb.append("&key=").append(key).append("&ts=").append(System.currentTimeMillis());
		return sb.toString(); 
	}
	
	private String prepareAjaxSession(boolean init) {
		StringBuffer sb = new StringBuffer();
		
		if(init)
			ajaxSessionId++;
		
		sb.append("/ajax?host=").append(host).append("&port=").append(port);
		sb.append("&sid=").append(passwordParam).append("&sess=").append(ajaxSessionId);
		return sb.toString();
	}

	public String onAjaxClientKickoff() {
		return "onKickoff();";
	}
	
	private boolean waitForViewerReady() {
		long startTick = System.currentTimeMillis();
		while(System.currentTimeMillis() - startTick < 5000) {
			if(this.status == ConsoleProxyViewer.STATUS_NORMAL_OPERATION)
				return true;
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
			}
		}
		return false;
	}
	
	private String onAjaxClientConnectFailed() {
		return "<html><head></head><body><div id=\"main_panel\" tabindex=\"1\"><p>" + 
			"Unable to start console session as connection is refused by the machine you are accessing" +
			"</p></div></body></html>";
	}
	
	public String onAjaxClientStart(String title, List<String> languages, String guest) {
		if(!waitForViewerReady())
			return onAjaxClientConnectFailed();

		// make sure we switch to AJAX view on start
		setAjaxViewer(true);
			
		int tileWidth = tracker.getTileWidth();
		int tileHeight = tracker.getTileHeight();
		int width = tracker.getTrackWidth();
		int height = tracker.getTrackHeight();
		
		if(s_logger.isTraceEnabled())
			s_logger.trace("Ajax client start, frame buffer w: " + width + ", " + height);
		
		synchronized(this) {
			if(framebufferResized) {
				framebufferResized = false;
			}
		}
		
		int retry = 0;
		if(justCreated()) {
			tracker.initCoverageTest();
			
			try {
				rfb.writeFramebufferUpdateRequest(0, 0, tracker.getTrackWidth(), tracker.getTrackHeight(), false);
			
				while(!tracker.hasFullCoverage() && retry < 10) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
					}
					retry++;
				}
			} catch (IOException e1) {
				s_logger.warn("Connection was broken ");
			}
		}
		
		List<TileInfo> tiles = tracker.scan(true);
		String imgUrl = prepareAjaxImage(tiles, true);
		String updateUrl = prepareAjaxSession(true);
		
		StringBuffer sbTileSequence = new StringBuffer();
		int i = 0;
		for(TileInfo tile : tiles) {
			sbTileSequence.append("[").append(tile.getRow()).append(",").append(tile.getCol()).append("]");
			if(i < tiles.size() - 1)
				sbTileSequence.append(",");
			
			i++;
		}

/*		
		SimpleHash model = new SimpleHash();
		model.put("tileSequence", sbTileSequence.toString());
		model.put("imgUrl", imgUrl);
		model.put("updateUrl", updateUrl);
		model.put("width", String.valueOf(width));
		model.put("height", String.valueOf(height));
		model.put("tileWidth", String.valueOf(tileWidth));
		model.put("tileHeight", String.valueOf(tileHeight));
		model.put("title", title);
		model.put("rawKeyboard", ConsoleProxy.keyboardType == ConsoleProxy.KEYBOARD_RAW ? "true" : "false");
		
		StringWriter writer = new StringWriter();
		try {
			ConsoleProxy.processTemplate("viewer.ftl", model, writer);
		} catch (IOException e) {
			s_logger.warn("Unexpected exception in processing template.", e);
		} catch (TemplateException e) {
			s_logger.warn("Unexpected exception in processing template.", e);
		}
		StringBuffer sb = writer.getBuffer();
		if(s_logger.isTraceEnabled())
			s_logger.trace("onAjaxClientStart response: " + sb.toString());
		return sb.toString();
	*/
		return getAjaxViewerPageContent(sbTileSequence.toString(), imgUrl, 
				updateUrl, width, height, tileWidth, tileHeight, title, 
				ConsoleProxy.keyboardType == ConsoleProxy.KEYBOARD_RAW, languages, guest);
	}
	
	private String getAjaxViewerPageContent(String tileSequence, String imgUrl, String updateUrl, int width,
		int height, int tileWidth, int tileHeight, String title, boolean rawKeyboard, List<String> languages, String guest) {

		StringBuffer sbLanguages = new StringBuffer("");
		if(languages != null) {
			for(String lang : languages) {
				if(sbLanguages.length() > 0) {
					sbLanguages.append(",");
				}
				sbLanguages.append(lang);
			}
		}
		
		boolean linuxGuest = true;
		if(guest != null && guest.equalsIgnoreCase("windows"))
			linuxGuest = false;
		
		String[] content = new String[] {
			"<html>",
			"<head>",
			"<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/jquery.js\"></script>",
			"<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/cloud.logger.js\"></script>",
			"<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/ajaxviewer.js\"></script>",
			"<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/handler.js\"></script>",
			"<link rel=\"stylesheet\" type=\"text/css\" href=\"/resource/css/ajaxviewer.css\"></link>",
			"<link rel=\"stylesheet\" type=\"text/css\" href=\"/resource/css/logger.css\"></link>",
			"<title>" + title + "</title>",
			"</head>",
			"<body>",
			"<div id=\"toolbar\">",
			"<ul>",
				"<li>", 
					"<a href=\"#\" cmd=\"sendCtrlAltDel\">", 
						"<span><img align=\"left\" src=\"/resource/images/cad.gif\" alt=\"Ctrl-Alt-Del\" />Ctrl-Alt-Del</span>", 
					"</a>", 
				"</li>",
				"<li>", 
					"<a href=\"#\" cmd=\"sendCtrlEsc\">", 
						"<span><img align=\"left\" src=\"/resource/images/winlog.png\" alt=\"Ctrl-Esc\" style=\"width:16px;height:16px\"/>Ctrl-Esc</span>",
					"</a>", 
				"</li>",
				
				"<li class=\"pulldown\">", 
					"<a href=\"#\">", 
						"<span><img align=\"left\" src=\"/resource/images/winlog.png\" alt=\"Keyboard\" style=\"width:16px;height:16px\"/>Keyboard</span>",
					"</a>", 
					"<ul>",
		    			"<li><a href=\"#\" cmd=\"keyboard_en\"><span>Standard (US) keyboard</span></a></li>",
		    			"<li><a href=\"#\" cmd=\"keyboard_jp_en_os_to_en_vm\"><span>Japanese keyboard EN OS -> EN VM</span></a></li>",
		    			"<li><a href=\"#\" cmd=\"keyboard_jp_jp_os_to_en_vm\"><span>Japanese keyboard JP OS -> EN VM</span></a></li>",
			    		"<li><a href=\"#\" cmd=\"keyboard_jp_en_os_to_jp_vm\"><span>Japanese keyboard EN OS -> JP VM</span></a></li>",
			    		"<li><a href=\"#\" cmd=\"keyboard_jp_jp_os_to_jp_vm\"><span>Japanese keyboard JP OS -> JP VM</span></a></li>",
					"</ul>",
				"</li>",
			"</ul>",
			"<span id=\"light\" class=\"dark\" cmd=\"toggle_logwin\"></span>", 
			"</div>",
			"<div id=\"main_panel\" tabindex=\"1\"></div>",
			"<script language=\"javascript\">",
			"var acceptLanguages = '" + sbLanguages.toString() + "';",
			"var tileMap = [ " + tileSequence + " ];",
			"var ajaxViewer = new AjaxViewer('main_panel', '" + imgUrl + "', '" + updateUrl + "', tileMap, ", 
				String.valueOf(width) + ", " + String.valueOf(height) + ", " + String.valueOf(tileWidth) + ", " + String.valueOf(tileHeight) 
					+ ", " + (rawKeyboard ? "true" : "false") + ", " + (linuxGuest ? "true" : "false") + ");",

			"$(function() {",
				"ajaxViewer.start();",
			"});",

			"</script>",
			"</body>",
			"</html>"	
		};
		
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i < content.length; i++)
			sb.append(content[i]);
		
		return sb.toString();
	}
	
	public String onAjaxClientDisconnected() {
		return "onDisconnect();";
	}
	
	public String onAjaxClientUpdate() {
		if(!waitForViewerReady())
			return onAjaxClientDisconnected();
		
		synchronized(tileDirtyEvent) {
			if(!dirtyFlag) {
				try {
					tileDirtyEvent.wait(3000);
				} catch(InterruptedException e) {
				}
			}
		}
		
		boolean doResize = false;
		synchronized(this) {
			if(framebufferResized) {
				framebufferResized = false;
				doResize = true;
			}
		}
		
		List<TileInfo> tiles;
		
		if(doResize)
			tiles = tracker.scan(true);
		else
			tiles = tracker.scan(false);
		dirtyFlag = false;
		
		String imgUrl = prepareAjaxImage(tiles, false);
		StringBuffer sbTileSequence = new StringBuffer();
		int i = 0;
		for(TileInfo tile : tiles) {
			sbTileSequence.append("[").append(tile.getRow()).append(",").append(tile.getCol()).append("]");
			if(i < tiles.size() - 1)
				sbTileSequence.append(",");
			
			i++;
		}

/*		
		SimpleHash model = new SimpleHash();
		model.put("tileSequence", sbTileSequence.toString());
		model.put("resized", doResize);
		model.put("imgUrl", imgUrl);
		model.put("width", String.valueOf(resizedFramebufferWidth));
		model.put("height", String.valueOf(resizedFramebufferHeight));
		model.put("tileWidth", String.valueOf(tracker.getTileWidth()));
		model.put("tileHeight", String.valueOf(tracker.getTileHeight()));
		
		StringWriter writer = new StringWriter();
		try {
			ConsoleProxy.processTemplate("viewer-update.ftl", model, writer);
		} catch (IOException e) {
			s_logger.warn("Unexpected exception in processing template.", e);
		} catch (TemplateException e) {
			s_logger.warn("Unexpected exception in processing template.", e);
		}
		StringBuffer sb = writer.getBuffer();
		
		if(s_logger.isTraceEnabled())
			s_logger.trace("onAjaxClientUpdate response: " + sb.toString());
		
		return sb.toString();
*/
		return getAjaxViewerUpdatePageContent(sbTileSequence.toString(), imgUrl, doResize, resizedFramebufferWidth,
			resizedFramebufferHeight, tracker.getTileWidth(), tracker.getTileHeight());
	}
	
	private String getAjaxViewerUpdatePageContent(String tileSequence, String imgUrl, boolean resized, int width,
		int height, int tileWidth, int tileHeight) {
		
		String[] content = new String[] {
			"tileMap = [ " + tileSequence + " ];",
			resized ? "ajaxViewer.resize('main_panel', " + width + ", " + height + " , " + tileWidth + ", " + tileHeight + ");" : "", 
			"ajaxViewer.refresh('" + imgUrl + "', tileMap, false);"
		};
		
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i < content.length; i++)
			sb.append(content[i]);
		
		return sb.toString();
	}
	
	
	public long getAjaxSessionId() {
		return this.ajaxSessionId;
	}
	
	public AjaxFIFOImageCache getAjaxImageCache() {
		return ajaxImageCache;
	}
	
	public boolean isAjaxViewer() {
		return ajaxViewer;
	}

	public synchronized void setAjaxViewer(boolean ajaxViewer) {
		if(this.ajaxViewer != ajaxViewer) {
			if(this.ajaxViewer) {
				// previous session was AJAX session
				this.ajaxSessionId++;		// increase the session id so that it will disconnect existing AJAX viewer
			} else {
				// close java client session
				if(clientStream != null) {
					byte[] bs = new byte[2];
					bs[0] = (byte)250;
					bs[1] = 1;
					writeToClientStream(bs);
					
					try {
						clientStream.close();
					} catch (IOException e) {
					}
					clientStream = null;
				}
			}
			this.ajaxViewer = ajaxViewer;
		}
	}
	
	public void writeServer(byte[] b, int off, int len) {
		synchronized (this) {
			if (!rfb.closed()) {
				try {
					// We lock the viewer to avoid race condition when connecting one 
					// client forces the current client to disconnect.
					rfb.os.write(b, off, len);
					rfb.os.flush();
				} catch (IOException e) {
					// Swallow the exception because we want the client connection to sustain
					// even when server connection is severed and reestablished.
					s_logger.info("Ignore exception when writing to server: " + e);
					rfb.close();
				}
			} else {
				s_logger.info("Dropping client event because server connection is closed ");
			}
		}
	}
	
	public void sendClientMouseEvent(int event, int x, int y, int code, int modifiers) {
		if(code == 2)
			modifiers |= MouseEvent.BUTTON3_MASK;
		else
			modifiers |= MouseEvent.BUTTON1_MASK;

		int id = 0; 
		if(event == 1)
			id = MouseEvent.MOUSE_MOVED;
		else if(event == 2)
			id = MouseEvent.MOUSE_PRESSED;
		else if(event == 3)
			id = MouseEvent.MOUSE_RELEASED;
		else if(event == 8)
			id = MouseEvent.MOUSE_PRESSED;

		long curTicks = System.currentTimeMillis();
		MouseEvent mouseEvent = new MouseEvent(vc, id,
			curTicks, modifiers, x, y, 1, false);
		
		synchronized (this) {
			if (rfb != null && !rfb.closed()) {
				try {
					rfb.writePointerEvent(mouseEvent);
					if(event == 8) {
						if(s_logger.isTraceEnabled())
							s_logger.trace("Replay mouse double click event at " + x + "," + y);

						mouseEvent = new MouseEvent(vc, MouseEvent.MOUSE_RELEASED,
								curTicks, modifiers, x, y, 1, false);
						rfb.writePointerEvent(mouseEvent);
						
						mouseEvent = new MouseEvent(vc, MouseEvent.MOUSE_PRESSED,
								curTicks, modifiers, x, y, 1, false);
						rfb.writePointerEvent(mouseEvent);
						
						mouseEvent = new MouseEvent(vc, MouseEvent.MOUSE_RELEASED,
								curTicks, modifiers, x, y, 1, false);
						rfb.writePointerEvent(mouseEvent);
					}
				} catch (IOException e) {
					s_logger.warn("Exception while sending mouse event. ", e);
				}
			}
		}
	}

	public void sendClientRawKeyboardEvent(int event, int code, int modifiers) {
		code = ConsoleProxyAjaxKeyMapper.getInstance().getJvmKeyCode(code);
		switch(event) {
		case 4 : 	// Key press
			//
			// special handling for ' and " (keycode: 222, char code : 39 and 34)
			//
			if(code == 39 || code == 34) {
				writeKeyboardEvent(KeyEvent.KEY_PRESSED, 222, (char)code, getAwtModifiers(modifiers));
			}
			break;

		case 5 :	// Key down
			if((modifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0 && (modifiers & ConsoleProxyViewer.ALT_KEY_MASK) != 0 && code == KeyEvent.VK_INSERT) {
				code = KeyEvent.VK_DELETE;
			}
			
			if(code != 222) {
				writeKeyboardEvent(KeyEvent.KEY_PRESSED, code, 
					ConsoleProxyAjaxKeyMapper.getInstance().shiftedKeyCharFromKeyCode(code, (modifiers & ConsoleProxyViewer.SHIFT_KEY_MASK) != 0), 
					getAwtModifiers(modifiers));
			}
			break;
			
		case 6 :	// Key Up
			writeKeyboardEvent(KeyEvent.KEY_RELEASED, code, 
				ConsoleProxyAjaxKeyMapper.getInstance().shiftedKeyCharFromKeyCode(code, (modifiers & ConsoleProxyViewer.SHIFT_KEY_MASK) != 0), 
				getAwtModifiers(modifiers));
			break;
		}
	}
	
/*
	public void sendClientRawKeyboardEvent(int event, int code, int modifiers) {
		// code = ConsoleProxyAjaxKeyMapper.getInstance().getJvmKeyCode(code);
		switch(event) {
		case 4 : 	// Key press
			break;

		case 5 :	// Key down
			if((modifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0 && (modifiers & ConsoleProxyViewer.ALT_KEY_MASK) != 0 && code == KeyEvent.VK_INSERT) {
				code = KeyEvent.VK_DELETE;
			}
			
			writeKeyboardEvent(KeyEvent.KEY_PRESSED, code, 
				(char)code, 
				getAwtModifiers(modifiers));
			break;
			
		case 6 :	// Key Up
			writeKeyboardEvent(KeyEvent.KEY_RELEASED, code, 
				(char)code,  
				getAwtModifiers(modifiers));
			break;
		}
	}
*/
	public void sendClientKeyboardEvent(int event, int code, int modifiers) {
		int vkCode;
		switch(event) {
		case 4 : 	// Key press
			if(code == 0 || (modifiers & (ConsoleProxyViewer.CTRL_KEY_MASK | ConsoleProxyViewer.META_KEY_MASK | ConsoleProxyViewer.ALT_KEY_MASK)) != 0) {
				// if code is extend keys or has ctrl, alt, meta being pressed, ignore javascript key-press event
				return;
			}
			
			vkCode = ConsoleProxyAjaxKeyMapper.getInstance().getRegularCharVkCode(code);
			if(vkCode > 0) {
				writeKeyboardEvent(KeyEvent.KEY_PRESSED, vkCode, (char)code, 0); 
				writeKeyboardEvent(KeyEvent.KEY_RELEASED, vkCode, (char)code, 0);
			}
			break;

		case 5 :	// Key down
			vkCode = ConsoleProxyAjaxKeyMapper.getInstance().getActionCharVkCode(code);
			if(vkCode >= 0 || (modifiers & (ConsoleProxyViewer.CTRL_KEY_MASK | ConsoleProxyViewer.META_KEY_MASK | ConsoleProxyViewer.ALT_KEY_MASK)) != 0) {
				if(vkCode < 0) {
					vkCode = ConsoleProxyAjaxKeyMapper.getInstance().getRegularCharVkCode(code);
					
					if((modifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0) {  	// if control-key is pressed, always use lower-case char-code
						if(vkCode >= (int)'A' && vkCode <= (int)'Z')
							vkCode = (int)'a' + (vkCode - (int)'A');
					}
				}
				
				if((modifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0 && (modifiers & ConsoleProxyViewer.ALT_KEY_MASK) != 0 && vkCode == KeyEvent.VK_INSERT) {
					vkCode = KeyEvent.VK_DELETE;
				}
				
				writeKeyboardEvent(KeyEvent.KEY_PRESSED, vkCode, (char)vkCode,
					getAwtModifiers(modifiers));
			}
			break;
			
		case 6 :	// Key Up
			vkCode = ConsoleProxyAjaxKeyMapper.getInstance().getActionCharVkCode(code);
			if(vkCode >= 0 || (modifiers & (ConsoleProxyViewer.CTRL_KEY_MASK | ConsoleProxyViewer.META_KEY_MASK | ConsoleProxyViewer.ALT_KEY_MASK)) != 0) {
				if(vkCode < 0) {
					vkCode = ConsoleProxyAjaxKeyMapper.getInstance().getRegularCharVkCode(code);

					if((modifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0) {	// if control-key is pressed, always use lower-case char-code
						if(vkCode >= (int)'A' && vkCode <= (int)'Z')
							vkCode = (int)'a' + (vkCode - (int)'A');
					}
					
					if((modifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0 && (modifiers & ConsoleProxyViewer.ALT_KEY_MASK) != 0 && vkCode == KeyEvent.VK_INSERT) {
						vkCode = KeyEvent.VK_DELETE;
					}
				}

				writeKeyboardEvent(KeyEvent.KEY_RELEASED, vkCode, (char)vkCode,
					getAwtModifiers(modifiers));
			}
			break;
		}
	}
	
	private static int getAwtModifiers(int jsModifiers) {
		int awtModifiers = 0;
		
		if((jsModifiers & ConsoleProxyViewer.SHIFT_KEY_MASK) != 0) {
			awtModifiers |= InputEvent.SHIFT_DOWN_MASK;
		}
		
		if((jsModifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0) {
			awtModifiers |= InputEvent.CTRL_DOWN_MASK;
		}
		
		if((jsModifiers & ConsoleProxyViewer.ALT_KEY_MASK) != 0) {
			awtModifiers |= InputEvent.ALT_DOWN_MASK;
		}
		
		return awtModifiers;
	}
	
	private void writeKeyboardEvent(int keyEventType, int code, char keyChar, int modifiers) {
		KeyEvent keyEvent;
		try {
			keyEvent = new KeyEvent(vc, keyEventType, 
				System.currentTimeMillis(), modifiers, code, keyChar);
		} catch(Exception e) {
			s_logger.warn("Unable to construct KeyEvent object, key code: " + code + ", keyChar: " + keyChar + " ", e);
			return;
		}
		
		synchronized (this) {
			if (rfb != null && !rfb.closed()) {
				try {
					rfb.writeKeyEvent(keyEvent);
				} catch (IOException e) {
					s_logger.warn("Exception while sending keyboard event. ", e);
				}
			}
		}
	}
}
