Mercurial > hg > Applications > TightVNC_orginal
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; + } + } + +}