Mercurial > hg > Applications > TreeVNC
view src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java @ 412:372532ae5f4d
Add ErrorAnnounce
author | innparusu |
---|---|
date | Thu, 19 Nov 2015 16:53:50 +0900 |
parents | cdab1354e227 |
children | 3af5f4af2d63 |
line wrap: on
line source
// Copyright (C) 2010, 2011, 2012, 2013 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.drawing.Renderer; import com.glavsoft.exceptions.CommonException; import com.glavsoft.exceptions.ProtocolException; import com.glavsoft.exceptions.TransportException; import com.glavsoft.rfb.ClipboardController; import com.glavsoft.rfb.IRepaintController; import com.glavsoft.rfb.client.FramebufferUpdateRequestMessage; import com.glavsoft.rfb.client.SetPixelFormatMessage; import com.glavsoft.rfb.encoding.EncodingType; import com.glavsoft.rfb.encoding.PixelFormat; import com.glavsoft.rfb.encoding.decoder.*; import com.glavsoft.transport.Reader; import java.io.PrintWriter; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.util.LinkedList; import java.util.Timer; import java.util.TimerTask; import java.util.logging.Logger; import com.glavsoft.viewer.ViewerInterface; import jp.ac.u_ryukyu.treevnc.*; public class ReceiverTask implements Runnable { private static final byte FRAMEBUFFER_UPDATE = 0; private static final byte SET_COLOR_MAP_ENTRIES = 1; private static final byte BELL = 2; private static final byte SERVER_CUT_TEXT = 3; private static Logger logger = Logger.getLogger("com.glavsoft.rfb.protocol.ReceiverTask"); private Reader reader; private volatile boolean isRunning = false; private Renderer renderer; private final IRepaintController repaintController; private final ClipboardController clipboardController; protected final DecodersContainer decoders; protected FramebufferUpdateRequestMessage fullscreenFbUpdateIncrementalRequest; protected final ProtocolContext context; protected PixelFormat pixelFormat; protected boolean needSendPixelFormat; private TreeRFBProto rfb; private long checkCounter = 0; public int numberOfRectangles = 0; private Timer timer = null; public ReceiverTask(Reader reader, IRepaintController repaintController, ClipboardController clipboardController, DecodersContainer decoders, final ProtocolContext context, TreeRFBProto _rfb) { rfb = _rfb; this.reader = reader; this.repaintController = repaintController; this.clipboardController = clipboardController; this.context = context; this.decoders = decoders; Decoder decoder = new ZRLEESender(rfb); decoders.setDecoderByType(EncodingType.ZLIB, decoder); decoders.setDecoderByType(EncodingType.ZRLE, decoder); decoders.setDecoderByType(EncodingType.ZRLEE, decoder); if(!rfb.getCuiVersion()) if (rfb.filterSingleDisplay) { renderer = repaintController.createRenderer(reader, context.getFbWidth(), context.getFbHeight(), context.getPixelFormat()); fullscreenFbUpdateIncrementalRequest = new FramebufferUpdateRequestMessage(0, 0, rfb.getSingleWidth(), rfb.getSingleHeight(), false); } else { renderer = repaintController.createRenderer(reader, context.getFbWidth(), context.getFbHeight(), context.getPixelFormat()); fullscreenFbUpdateIncrementalRequest = new FramebufferUpdateRequestMessage(0, 0, context.getFbWidth(), context.getFbHeight(), false); } if(rfb.isTreeManager()) { fullscreenFbUpdateIncrementalRequest.sendFullScreenRequest(); connectionFinished(); if(rfb.checkDelay) { SendCheckDelay sendCheckDelay = new SendCheckDelay(rfb); Thread sendCheckDelayThread = new Thread(sendCheckDelay, "send-check-delay"); sendCheckDelayThread.start(); } if(rfb.fixingSize) { timer = new Timer("framebufferUpdate-request-timer", true); timer.schedule(new TimerTask() { @Override public void run() { context.setFbWidth(rfb.fixingSizeWidth); context.setFbHeight(rfb.fixingSizeHeight); context.sendMessage(new FramebufferUpdateRequestMessage(0, 0, context.getFbWidth(), context.getFbHeight(), true)); } }, 0, 100); } } } @Override public void run() { isRunning = true; while (isRunning) { try { reader.available(); if (! isRunning) { // server Change in direct mode // pass the input stream to the TreeVNC protocol reader return; } if(! rfb.isTreeManager() && rfb.isAddSerialNum()) { // client has 8byte packet sequence number // add serial number flag (4byte) reader.mark(20+8+4); getLost(reader); //check seq consistency } else { reader.mark(20); } byte messageId = reader.readByte(); switch (messageId) { case FRAMEBUFFER_UPDATE: // logger.fine("Server message: FramebufferUpdate (0)"); framebufferUpdateMessage(); break; case SET_COLOR_MAP_ENTRIES: logger.severe("Server message SetColorMapEntries is not implemented. Skip."); setColorMapEntries(); break; case BELL: logger.fine("Server message: Bell"); // System.out.print("\0007"); // System.out.flush(); break; case SERVER_CUT_TEXT: logger.fine("Server message: CutText (3)"); serverCutText(); break; default: logger.severe("Unsupported server message. Id = " + messageId); } } catch (TransportException e) { logger.severe("Close session : ReceiverTask : " + e.getMessage()); if(!rfb.isTreeManager() && !(rfb.getTerminationType())) { System.out.println("death parent node, wait connect new parent node."); // close viewer ViewerInterface viewer = rfb.getViewer(); viewer.setVisible(false); try { // clean DataInputStream reader.close(); } catch (TransportException e1) { e1.printStackTrace(); } } stopTask(); } catch (ProtocolException e) { logger.severe(e.getMessage()); if (isRunning) { context.cleanUpSession(e.getMessage() + "\nConnection closed."); } stopTask(); } catch (CommonException e) { logger.severe(e.getMessage()); if (isRunning) { context.cleanUpSession("Connection closed.."); } stopTask(); } catch (Throwable te) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); te.printStackTrace(pw); logger.severe("updateRectangle record failed : " + te.getMessage()); if (isRunning) { context.cleanUpSession(te.getMessage() + "\n" + sw.toString()); } stopTask(); } } } private void sleep(int i) { try { Thread.sleep(i); } catch (InterruptedException e) { // nothing. } } private void setColorMapEntries() throws TransportException { reader.readByte(); // padding reader.readUInt16(); // first color index int length = reader.readUInt16(); while (length-- > 0) { reader.readUInt16(); // R reader.readUInt16(); // G reader.readUInt16(); // B } } private void serverCutText() throws TransportException { reader.readByte(); // padding reader.readInt16(); // padding int length = reader.readInt32() & Integer.MAX_VALUE; clipboardController.updateSystemClipboard(reader.readBytes(length)); } public void framebufferUpdateMessage() throws Exception { try { reader.readByte(); // padding this.numberOfRectangles = reader.readUInt16(); if(numberOfRectangles != 1) System.out.println("numberofrectangle : " + numberOfRectangles); while (numberOfRectangles-- > 0) { FramebufferUpdateRectangle rect = new FramebufferUpdateRectangle(); rect.fill(reader); if(rfb.isTreeManager() && rfb.checkDelay) { long time = System.currentTimeMillis(); System.out.println(time + " : size : " + rect.width * rect.height); } Decoder decoder = decoders.getDecoderByType(rect.getEncodingType()); logger.finest(rect.toString() + (0 == numberOfRectangles ? "\n---" : "")); if (decoder != null) { try { decoder.decode(reader, renderer, rect); // TreeVNC processing here if (rfb.getCuiVersion()) continue; if (rect.x >= rfb.getSingleWidth() && rfb.getShareScreenNumber() == 1) { continue; } else if(rect.x < rfb.getSingleWidth() && rfb.getShareScreenNumber() == 2) { continue; } repaintController.repaintBitmap(rect); } catch (Exception e) { throw e; } } else if (rect.getEncodingType() == EncodingType.RICH_CURSOR) { RichCursorDecoder.getInstance().decode(reader, renderer, rect); if(repaintController!=null) repaintController.repaintCursor(); } else if (rect.getEncodingType() == EncodingType.CURSOR_POS) { renderer.decodeCursorPosition(rect); repaintController.repaintCursor(); } else if (rect.getEncodingType() == EncodingType.DESKTOP_SIZE || rect.getEncodingType() == EncodingType.INIT_DATA || rect.getEncodingType() == EncodingType.EXTENDED_DESKTOP_SIZE) { if (rect.getEncodingType() == EncodingType.EXTENDED_DESKTOP_SIZE){ int numberOfScreen = reader.readByte(); reader.readBytes(3); LinkedList<FramebufferUpdateRectangle> screens = new LinkedList<FramebufferUpdateRectangle>(); for (int i = 0; i < numberOfScreen; i++){ long id = reader.readUInt32(); int x = reader.readUInt16(); int y = reader.readUInt16(); int width = reader.readUInt16(); int height = reader.readUInt16(); long flag = reader.readUInt32(); FramebufferUpdateRectangle screen = new FramebufferUpdateRectangle(x, y, width, height); screen.port = (int) id; screen.time = flag; screens.add(screen); System.out.println("screen " + id + ":" + "x=" + x + " y=" + y + "width=" + width + "height=" + height); } return; } fullscreenFbUpdateIncrementalRequest = new FramebufferUpdateRequestMessage(0, 0, rect.width, rect.height, false); rfb.setCuiVersion(false); boolean visible = true; if (rect.getEncodingType() == EncodingType.INIT_DATA) { // VNCServer is changed, initiarize new screen. int length = reader.readInt32(); byte[] initData = new byte[length]; reader.read(initData); String name = new String(initData, 24, length - 24, "UTF-8"); context.setRemoteDesktopName(name); context.setInitData(initData); context.setFbWidth(rect.width); context.setFbHeight(rect.height); repaintController.updateRemoteDesktopName(context); reader.reset(); // All children multicastqueue should be discarded here. // rfb.clearChildrenTransmission(); rfb.readSendData(length + 20, reader, null, rect); // size of UpdateRectangleMessage with initData. short id = (short) rect.x; visible = (id != rfb.getId()); } synchronized (renderer.getLock()) { if (!(rfb.getCuiVersion())) { renderer = repaintController.createRenderer(reader, rect.width, rect.height, context.getPixelFormat()); } } if (rect.getEncodingType() == EncodingType.INIT_DATA) { repaintController.setVisible(visible); } if (rfb.hasViewer()){ rfb.getViewer().setFitScreen(); } if (rfb.isTreeManager()) { context.sendMessage(new FramebufferUpdateRequestMessage(0, 0, rect.width, rect.height, false)); } } else if (rect.getEncodingType() == EncodingType.CHECK_DELAY) { int checkDelaySize = 24; reader.reset(); rfb.readSendData(checkDelaySize, reader, null, rect); int port = rfb.acceptPort; String address = rfb.getMyAddress(); sendCheckDelayReply(rect.time, port, address); } else if (rect.getEncodingType() == EncodingType.SOUND) { // SOUNDを受信した時の処理を } else if (rect.getEncodingType() == EncodingType.ERROR_ANNOUNCE) { short id = (short) rect.x; int length = reader.readInt32(); byte[] errorMessage = new byte[length]; reader.read(errorMessage); String errorMessageStr = new String(errorMessage, "UTF-8"); if (id == rfb.getId()) { rfb.getViewer().getConnectionPresenter().showConnectionErrorDialog(errorMessageStr); rfb.getViewer().getConnectionPresenter().clearMessage(); } if (!rfb.hasParent()) { reader.reset(); rfb.readSendData(length + 20, reader, null, rect); } } else throw new CommonException("Unprocessed encoding: " + rect.toString()); } } catch (UnsupportedEncodingException e) { e.getMessage(); e.printStackTrace(); reader.close(); } if (rfb.isTreeManager()) { synchronized (this) { if (needSendPixelFormat) { needSendPixelFormat = false; context.setPixelFormat(pixelFormat); context.sendMessage(new SetPixelFormatMessage(pixelFormat)); logger.fine("sent: " + pixelFormat); context.sendRefreshMessage(); logger.fine("sent: nonincremental fb update"); } else { context.sendMessage(new FramebufferUpdateRequestMessage(0, 0, context.getFbWidth(), context.getFbHeight(), false)); } } } } private void sendCheckDelayReply(long time, int port, String address) throws UnsupportedEncodingException { context.sendMessage(new CheckDelayReply(time, port, address)); } public synchronized void queueUpdatePixelFormat(PixelFormat pf) { pixelFormat = pf; needSendPixelFormat = true; // context.sendMessage(new FramebufferUpdateRequestMessage(0, 0, 1, 1, false)); } public void stopTask() { isRunning = false; } private void connectionFinished() { rfb.vncConnected(true); } private void getLost(Reader reader) throws Exception { int addSerialNumFlag = reader.readInt32(); long num = reader.readInt64(); if (addSerialNumFlag == 1) { if(num != ++checkCounter) { System.out.println("LostData" + (num - checkCounter)); checkCounter = num; } } } }