| // Copyright 2012 Citrix Systems, Inc. Licensed under the |
| // Apache License, Version 2.0 (the "License"); you may not use this |
| // file except in compliance with the License. Citrix Systems, Inc. |
| // reserves all rights not expressly granted by the License. |
| // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| // Automatically generated by addcopyright.py at 04/03/2012 |
| package com.cloud.consoleproxy;
|
|
|
| import java.io.IOException;
|
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.UnknownHostException;
|
|
|
| import org.apache.log4j.Logger;
|
|
|
| import com.cloud.consoleproxy.vnc.FrameBufferCanvas;
|
| import com.cloud.consoleproxy.vnc.RfbConstants;
|
| import com.cloud.consoleproxy.vnc.VncClient;
|
|
|
| /**
|
| *
|
| * @author Kelven Yang
|
| * ConsoleProxyVncClient bridges a VNC engine with the front-end AJAX viewer
|
| *
|
| */
|
| public class ConsoleProxyVncClient extends ConsoleProxyClientBase {
|
| private static final Logger s_logger = Logger.getLogger(ConsoleProxyVncClient.class);
|
|
|
| private VncClient client;
|
| private Thread worker;
|
| private boolean workerDone = false;
|
|
|
| public ConsoleProxyVncClient() {
|
| }
|
|
|
| public boolean isHostConnected() {
|
| if(client != null)
|
| return client.isHostConnected();
|
|
|
| return false;
|
| }
|
|
|
| @Override
|
| public boolean isFrontEndAlive() {
|
| if(workerDone || System.currentTimeMillis() - getClientLastFrontEndActivityTime() > ConsoleProxy.VIEWER_LINGER_SECONDS*1000) {
|
| s_logger.info("Front end has been idle for too long"); |
| return false; |
| }
|
| return true;
|
| }
|
|
|
| @Override
|
| public void initClient(ConsoleProxyClientParam param) { |
| setClientParam(param);
|
| |
| client = new VncClient(this);
|
| worker = new Thread(new Runnable() {
|
| public void run() {
|
| String tunnelUrl = getClientParam().getClientTunnelUrl(); |
| String tunnelSession = getClientParam().getClientTunnelSession(); |
| |
| for(int i = 0; i < 15; i++) {
|
| try { |
| if(tunnelUrl != null && !tunnelUrl.isEmpty() && tunnelSession != null && !tunnelSession.isEmpty()) { |
| URI uri = new URI(tunnelUrl); |
| s_logger.info("Connect to VNC server via tunnel. url: " + tunnelUrl + ", session: " + tunnelSession); |
| |
| ConsoleProxy.ensureRoute(uri.getHost()); |
| client.connectTo( |
| uri.getHost(), uri.getPort(), |
| uri.getPath() + "?" + uri.getQuery(), |
| tunnelSession, "https".equalsIgnoreCase(uri.getScheme()), |
| getClientHostPassword()); |
| } else { |
| s_logger.info("Connect to VNC server directly. host: " + getClientHostAddress() + ", port: " + getClientHostPort()); |
| ConsoleProxy.ensureRoute(getClientHostAddress()); |
| client.connectTo(getClientHostAddress(), getClientHostPort(), getClientHostPassword()); |
| }
|
| } catch (UnknownHostException e) {
|
| s_logger.error("Unexpected exception (will retry until timeout)", e); |
| } catch (IOException e) {
|
| s_logger.error("Unexpected exception (will retry until timeout) ", e);
|
| } catch (Throwable e) { |
| s_logger.error("Unexpected exception (will retry until timeout) ", e); |
| }
|
|
|
| try {
|
| Thread.sleep(1000);
|
| } catch (InterruptedException e) {
|
| } |
| |
| if(tunnelUrl != null && !tunnelUrl.isEmpty() && tunnelSession != null && !tunnelSession.isEmpty()) { |
| ConsoleProxyAuthenticationResult authResult = ConsoleProxy.reAuthenticationExternally(getClientParam()); |
| if(authResult != null && authResult.isSuccess()) { |
| if(authResult.getTunnelUrl() != null && !authResult.getTunnelUrl().isEmpty() && |
| authResult.getTunnelSession() != null && !authResult.getTunnelSession().isEmpty()) { |
| tunnelUrl = authResult.getTunnelUrl(); |
| tunnelSession = authResult.getTunnelSession(); |
| |
| s_logger.info("Reset XAPI session. url: " + tunnelUrl + ", session: " + tunnelSession); |
| } |
| } |
| } |
| }
|
| |
| s_logger.info("Receiver thread stopped."); |
| workerDone = true; |
| client.getClientListener().onClientClose(); |
| } |
| });
|
|
|
| worker.setDaemon(true);
|
| worker.start();
|
| }
|
|
|
| @Override
|
| public void closeClient() {
|
| if(client != null)
|
| client.shutdown();
|
| }
|
|
|
| @Override
|
| public void onClientConnected() {
|
| }
|
|
|
| public void onClientClose() { |
| s_logger.info("Received client close indication. remove viewer from map."); |
|
|
| ConsoleProxy.removeViewer(this);
|
| }
|
|
|
| @Override
|
| public void onFramebufferUpdate(int x, int y, int w, int h) {
|
| super.onFramebufferUpdate(x, y, w, h);
|
| client.requestUpdate(false);
|
| }
|
|
|
| public void sendClientRawKeyboardEvent(InputEventType event, int code, int modifiers) {
|
| if(client == null)
|
| return;
|
|
|
| updateFrontEndActivityTime();
|
|
|
| switch(event) {
|
| case KEY_DOWN :
|
| client.sendClientKeyboardEvent(RfbConstants.KEY_DOWN, code, 0);
|
| break;
|
|
|
| case KEY_UP :
|
| client.sendClientKeyboardEvent(RfbConstants.KEY_UP, code, 0);
|
| break;
|
|
|
| case KEY_PRESS :
|
| break;
|
|
|
| default :
|
| assert(false);
|
| break;
|
| }
|
| }
|
|
|
| public void sendClientMouseEvent(InputEventType event, int x, int y, int code, int modifiers) {
|
| if(client == null)
|
| return;
|
|
|
| updateFrontEndActivityTime();
|
|
|
| int pointerMask = 0;
|
| int mask = 1;
|
| if(code == 2)
|
| mask = 4;
|
| if(event == InputEventType.MOUSE_DOWN) {
|
| pointerMask = mask;
|
| }
|
|
|
| client.sendClientMouseEvent(pointerMask, x, y, code, modifiers);
|
| }
|
|
|
| @Override
|
| protected FrameBufferCanvas getFrameBufferCavas() {
|
| if(client != null)
|
| return client.getFrameBufferCanvas();
|
| return null;
|
| }
|
| }
|