diff src/main/java/com/glavsoft/rfb/protocol/Protocol.java @ 0:4689cc86d6cb

create TreeViewer2 Repository
author Yu Taninari <you@cr.ie.u-ryukyu.ac.jp>
date Tue, 03 Jul 2012 13:20:49 +0900
parents
children e654b2e4de64 472a9bcacb21
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/com/glavsoft/rfb/protocol/Protocol.java	Tue Jul 03 13:20:49 2012 +0900
@@ -0,0 +1,278 @@
+// Copyright (C) 2010, 2011 GlavSoft LLC.
+// All rights reserved.
+//
+//-------------------------------------------------------------------------
+// This file is part of the TightVNC software.  Please visit our Web site:
+//
+//                       http://www.tightvnc.com/
+//
+// This program 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 2 of the License, or
+// (at your option) 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, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//-------------------------------------------------------------------------
+//
+
+package com.glavsoft.rfb.protocol;
+
+import com.glavsoft.core.SettingsChangedEvent;
+import com.glavsoft.exceptions.*;
+import com.glavsoft.rfb.*;
+import com.glavsoft.rfb.client.ClientToServerMessage;
+import com.glavsoft.rfb.client.FramebufferUpdateRequestMessage;
+import com.glavsoft.rfb.client.SetEncodingsMessage;
+import com.glavsoft.rfb.client.SetPixelFormatMessage;
+import com.glavsoft.rfb.encoding.PixelFormat;
+import com.glavsoft.rfb.encoding.decoder.DecodersContainer;
+import com.glavsoft.rfb.protocol.state.HandshakeState;
+import com.glavsoft.rfb.protocol.state.ProtocolState;
+import com.glavsoft.transport.Reader;
+import com.glavsoft.transport.Writer;
+
+import java.util.logging.Logger;
+
+public class Protocol implements ProtocolContext, IChangeSettingsListener {
+	private ProtocolState state;
+	private final Logger logger = Logger.getLogger("com.glavsoft.rfb.protocol");
+	private final IPasswordRetriever passwordRetriever;
+	private final ProtocolSettings settings;
+	private int fbWidth;
+	private int fbHeight;
+	private PixelFormat pixelFormat;
+	private final Reader reader;
+	private final Writer writer;
+	private String remoteDesctopName;
+	private MessageQueue messageQueue;
+	private final DecodersContainer decoders;
+	private SenderTask senderTask;
+	private ReceiverTask receiverTask;
+	private IRfbSessionListener rfbSessionListener;
+	private IRepaintController repaintController;
+	private PixelFormat serverPixelFormat;
+	private Thread senderThread;
+	private Thread receiverThread;
+
+	public Protocol(Reader reader, Writer writer,
+			IPasswordRetriever passwordRetriever, ProtocolSettings settings) {
+		this.reader = reader;
+		this.writer = writer;
+		this.passwordRetriever = passwordRetriever;
+		this.settings = settings;
+		decoders = new DecodersContainer();
+		decoders.instantiateDecodersWhenNeeded(settings.encodings);
+		state = new HandshakeState(this);
+	}
+
+	@Override
+	public void changeStateTo(ProtocolState state) {
+		this.state = state;
+	}
+
+	public void handshake() throws UnsupportedProtocolVersionException, UnsupportedSecurityTypeException,
+			AuthenticationFailedException, TransportException, FatalException {
+		while (state.next()) {
+			continue;
+		}
+		this.messageQueue = new MessageQueue();
+	}
+
+	@Override
+	public PixelFormat getPixelFormat() {
+		return pixelFormat;
+	}
+
+	@Override
+	public void setPixelFormat(PixelFormat pixelFormat) {
+		this.pixelFormat = pixelFormat;
+		if (repaintController != null) {
+			repaintController.setPixelFormat(pixelFormat);
+		}
+	}
+
+	@Override
+	public String getRemoteDesktopName() {
+		return remoteDesctopName;
+	}
+
+	@Override
+	public void setRemoteDesktopName(String name) {
+		remoteDesctopName = name;
+	}
+
+	@Override
+	public int getFbWidth() {
+		return fbWidth;
+	}
+
+	@Override
+	public void setFbWidth(int fbWidth) {
+		this.fbWidth = fbWidth;
+	}
+
+	@Override
+	public int getFbHeight() {
+		return fbHeight;
+	}
+
+	@Override
+	public void setFbHeight(int fbHeight) {
+		this.fbHeight = fbHeight;
+	}
+
+	@Override
+	public IPasswordRetriever getPasswordRetriever() {
+		return passwordRetriever;
+	}
+
+	@Override
+	public ProtocolSettings getSettings() {
+		return settings;
+	}
+
+	@Override
+	public Logger getLogger() {
+		return logger;
+	}
+
+	@Override
+	public Writer getWriter() {
+		return writer;
+	}
+
+	@Override
+	public Reader getReader() {
+		return reader;
+	}
+
+	/**
+	 * Following the server initialisation message it's up to the client to send
+	 * whichever protocol messages it wants.  Typically it will send a
+	 * SetPixelFormat message and a SetEncodings message, followed by a
+	 * FramebufferUpdateRequest.  From then on the server will send
+	 * FramebufferUpdate messages in response to the client's
+	 * FramebufferUpdateRequest messages.  The client should send
+	 * FramebufferUpdateRequest messages with incremental set to true when it has
+	 * finished processing one FramebufferUpdate and is ready to process another.
+	 * With a fast client, the rate at which FramebufferUpdateRequests are sent
+	 * should be regulated to avoid hogging the network.
+	 */
+	public void startNormalHandling(IRfbSessionListener rfbSessionListener,
+			IRepaintController repaintController, ClipboardController clipboardController) {
+		this.rfbSessionListener = rfbSessionListener;
+		this.repaintController = repaintController;
+//		if (settings.getBitsPerPixel() == 0) {
+//			settings.setBitsPerPixel(pixelFormat.bitsPerPixel); // the same the server sent when not initialized yet
+//		}
+		serverPixelFormat = pixelFormat;
+		serverPixelFormat.trueColourFlag = 1; // correct flag - we don't support color maps
+		setPixelFormat(createPixelFormat(settings));
+		sendMessage(new SetPixelFormatMessage(pixelFormat));
+		logger.fine("sent: "+pixelFormat);
+
+		sendSupportedEncodingsMessage(settings);
+		settings.addListener(this); // to support pixel format (color depth), and encodings changes
+		settings.addListener(repaintController);
+
+		sendRefreshMessage();
+		senderTask = new SenderTask(messageQueue, writer, this);
+		senderThread = new Thread(senderTask);
+		senderThread.start();
+		decoders.resetDecoders();
+		receiverTask = new ReceiverTask(
+				reader, repaintController,
+				clipboardController,
+				decoders, this);
+		receiverThread = new Thread(receiverTask);
+		receiverThread.start();
+	}
+
+	@Override
+	public void sendMessage(ClientToServerMessage message) {
+		messageQueue.put(message);
+	}
+
+	private void sendSupportedEncodingsMessage(ProtocolSettings settings) {
+		decoders.instantiateDecodersWhenNeeded(settings.encodings);
+		SetEncodingsMessage encodingsMessage = new SetEncodingsMessage(settings.encodings);
+		sendMessage(encodingsMessage);
+		logger.fine("sent: " + encodingsMessage.toString());
+	}
+
+	/**
+	 * create pixel format by bpp
+	 */
+	private PixelFormat createPixelFormat(ProtocolSettings settings) {
+		int serverBigEndianFlag = serverPixelFormat.bigEndianFlag;
+		switch (settings.getBitsPerPixel()) {
+		case ProtocolSettings.BPP_32:
+			return PixelFormat.create32bppPixelFormat(serverBigEndianFlag);
+		case ProtocolSettings.BPP_16:
+			return PixelFormat.create16bppPixelFormat(serverBigEndianFlag);
+		case ProtocolSettings.BPP_8:
+			return PixelFormat.create8bppBGRPixelFormat(serverBigEndianFlag);
+		case ProtocolSettings.BPP_6:
+			return PixelFormat.create6bppPixelFormat(serverBigEndianFlag);
+		case ProtocolSettings.BPP_3:
+			return PixelFormat.create3bppPixelFormat(serverBigEndianFlag);
+		case ProtocolSettings.BPP_SERVER_SETTINGS:
+			return serverPixelFormat;
+		default:
+			// unsupported bpp, use default
+			return PixelFormat.create32bppPixelFormat(serverBigEndianFlag);
+		}
+	}
+
+	@Override
+	public void settingsChanged(SettingsChangedEvent e) {
+		ProtocolSettings settings = (ProtocolSettings) e.getSource();
+		if (settings.isChangedEncodings()) {
+			sendSupportedEncodingsMessage(settings);
+		}
+		if (settings.changedBitsPerPixel() && receiverTask != null) {
+			receiverTask.queueUpdatePixelFormat(createPixelFormat(settings));
+		}
+	}
+
+	@Override
+	public void sendRefreshMessage() {
+		sendMessage(new FramebufferUpdateRequestMessage(0, 0, fbWidth, fbHeight, false));
+		logger.fine("sent: full FB Refresh");
+	}
+
+	@Override
+	public void cleanUpSession(String message) {
+		cleanUpSession();
+		rfbSessionListener.rfbSessionStopped(message);
+	}
+
+	public synchronized void cleanUpSession() {
+		if (senderTask != null) { senderTask.stopTask(); }
+		if (receiverTask != null) { receiverTask.stopTask(); }
+		if (senderTask != null) {
+			try {
+				senderThread.join(1000);
+			} catch (InterruptedException e) {
+				// nop
+			}
+			senderTask = null;
+		}
+		if (receiverTask != null) {
+			try {
+				receiverThread.join(1000);
+			} catch (InterruptedException e) {
+				// nop
+			}
+			receiverTask = null;
+		}
+	}
+
+}