Mercurial > hg > Applications > TreeVNC
view src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java @ 505:af958194248b
change replyToRootSearchMulticast
author | oshiro |
---|---|
date | Mon, 18 Feb 2019 18:46:23 +0900 |
parents | 8d95d64c33bf |
children | c4d1a275b7d5 |
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 com.glavsoft.viewer.ConnectionPresenter; import com.glavsoft.viewer.ViewerInterface; import jp.ac.u_ryukyu.treevnc.CheckDelayReply; import jp.ac.u_ryukyu.treevnc.TreeRFBProto; import java.io.PrintWriter; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.util.LinkedList; import java.util.Timer; import java.util.logging.Logger; public class ReceiverTask implements Runnable { public 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.fixingSize) { context.setFbWidth(rfb.fixingSizeWidth); context.setFbHeight(rfb.fixingSizeHeight); } ConnectionPresenter cp = rfb.getViewer().getConnectionPresenter(); if(!rfb.getCuiVersion()) { if (cp.getSingleWidth()==0) { // request full screen for the first time cp.setSingleWidth(context.getFbWidth()); cp.setSingleHeight(context.getFbHeight()); } renderer = repaintController.createRenderer(reader, context.getFbWidth(), context.getFbHeight(), context.getPixelFormat()); } if(rfb.isTreeManager()) { fullscreenFbUpdateIncrementalRequest = new FramebufferUpdateRequestMessage(cp.getX(), cp.getY(), cp.getSingleWidth(), cp.getSingleHeight(), false); connectionFinished(); } } @Override public void run() { isRunning = true; if (fullscreenFbUpdateIncrementalRequest != null) { fullscreenFbUpdateIncrementalRequest.sendFullScreenRequest(context); } while (isRunning) { try { reader.available(); if (! isRunning) { // server Change in direct mode // pass the input stream to the TreeVNC protocol reader return; } byte messageId = getMessageId(); 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) { System.out.println(e.getMessage()); System.out.println(e.getCause().getClass().getSimpleName()); if (e.getCause().getClass().getSimpleName().equals("SocketTimeoutException")) { sendFrameBufferUpdateRequest(); continue; } 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(); } //} else { // rfb.sendDesktopSizeChange((short) -1); } 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); te.printStackTrace(); if (isRunning) { context.cleanUpSession(te.getMessage() + "\n" + sw.toString()); } stopTask(); } } } public byte getMessageId() throws Exception { 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+4); } return reader.readByte(); } public void sendFrameBufferUpdateRequest() { if (rfb.isTreeManager()) { sendFrameBufferUpdateRequest0(); } } 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); 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; 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.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; } else if (rect.getEncodingType() == EncodingType.DESKTOP_SIZE) { System.out.println("DESKTOP_SIZE"); fullscreenFbUpdateIncrementalRequest = new FramebufferUpdateRequestMessage(rect.x, rect.y, rect.width, rect.height, false); renderer = repaintController.createRenderer(reader, rect.width, rect.height, context.getPixelFormat()); if (rfb.hasViewer()){ setScreenParameter(rect,rect.width,rect.height); } } else if (rect.getEncodingType() == EncodingType.INIT_DATA) { // VNCServer is changed, initiarize new screen. int length = reader.readInt32() - 6; short id = reader.readInt16(); int singleWidth = reader.readUInt16(); int singleHeight = reader.readUInt16(); 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(); // request one screen fullscreenFbUpdateIncrementalRequest = new FramebufferUpdateRequestMessage(rect.x, rect.y, singleWidth, singleHeight, false); // All children multicastqueue should be discarded here. // rfb.clearChildrenTransmission(); rfb.readSendData(length + 16 + 10, reader, null, rect); // size of UpdateRectangleMessage with initData. if (!(rfb.getCuiVersion())) { // keep full frame buffer for multi screen renderer = repaintController.createRenderer(reader, rect.width, rect.height, context.getPixelFormat()); } rfb.setSharingId(id); if (rfb.hasViewer()){ System.out.println("setscreenparameter"); setScreenParameter(rect,singleWidth,singleHeight); } } else if (rect.getEncodingType() == EncodingType.CHECK_DELAY) { int checkDelaySize = 24; int port = rfb.acceptPort; String address = rfb.getMyAddress(); int dataLen = reader.readInt32(); sendCheckDelayReply(rect.time, port, address, dataLen); reader.reset(); reader.readBytes(24); decoder = decoders.getDecoderByType(EncodingType.ZRLEE); decoder.decode(reader, renderer, rect); // TreeVNC processing here repaintController.repaintBitmap(rect); } 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().showPortErrorDialog(errorMessageStr); rfb.getViewer().getConnectionPresenter().clearMessage(); } else { 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(); } sendFrameBufferUpdateRequest(); } private void setScreenParameter(FramebufferUpdateRectangle rect,int singleWidth ,int singleHeight) { ViewerInterface v = rfb.getViewer(); ConnectionPresenter cp = v.getConnectionPresenter(); cp.setX(rect.x); cp.setY(rect.y); cp.setFrameSizeWidth(rect.width); cp.setFrameSizeHeight(rect.height); cp.setSingleWidth(singleWidth); cp.setSingleHeight(singleHeight); rfb.setConnectionPresenter(cp); v.setFitScreen(); System.out.println("got INIT_DATA: myID = " + rfb.getId() + " sharingID = " + rfb.getSharingId()); if (rfb.isTreeManager()) { repaintController.setVisible(-1 != rfb.getSharingId() && rfb.getId() != rfb.getSharingId()); } else { if (rfb.getSharingId() != -1) repaintController.setVisible(rfb.getId() != rfb.getSharingId()); } } private void sendFrameBufferUpdateRequest0() { if (needSendPixelFormat) { needSendPixelFormat = false; context.setPixelFormat(pixelFormat); context.sendMessage(new SetPixelFormatMessage(pixelFormat)); logger.fine("sent: " + pixelFormat); context.sendMessage(fullscreenFbUpdateIncrementalRequest); logger.fine("sent: nonincremental fb update"); } else { context.sendMessage(fullscreenFbUpdateIncrementalRequest); } } private void sendCheckDelayReply(long time, int port, String address, int dataLen) throws UnsupportedEncodingException { context.sendMessage(new CheckDelayReply(time, port, address, dataLen)); } 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; } } } public void setReader(Reader reader) { this.reader = reader; } }