Mercurial > hg > Applications > TreeVNC
view src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java @ 617:33ee6facf4ee
remove debug message
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 22 Feb 2020 11:57:26 +0900 |
parents | 994a710100fd |
children | 120a31960494 |
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.*; import java.nio.ByteBuffer; 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; ZRLEESender zdecdoder = new ZRLEESender(rfb); Decoder decoder = zdecdoder; if (rfb.isTreeManager()) zdecdoder.setMulticast(true); if (rfb.multicastBlocking || rfb.getViewer().getUseMulticast()) zdecdoder.setBroadcast(true); decoders.setDecoderByType(EncodingType.ZLIB, decoder); decoders.setDecoderByType(EncodingType.ZRLE, decoder); ZRLEESender zdecdoder1 = new ZRLEESender(rfb); zdecdoder1.setZREEstream(true); decoders.setDecoderByType(EncodingType.ZRLEE, zdecdoder1); 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()); } else { renderer = new NullRenderer(context.getPixelFormat().bitsPerPixel/8, 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() { int failure = 0; 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(reader); switch (messageId) { case FRAMEBUFFER_UPDATE: // logger.fine("Server message: FramebufferUpdate (0)"); framebufferUpdateMessage(reader); 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.fine("Unsupported server message. Id = " + messageId); continue; } failure = 0; } catch (TransportException e) { System.out.println(e.getMessage()); System.out.println(e.getCause().getClass().getSimpleName()); if (e.getCause().getClass().getSimpleName().equals("SocketTimeoutException")) { sendFrameBufferUpdateRequest(); if (failure++ > 10) stopTask(); 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(Reader reader) 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(Reader reader) throws Exception { int numberOfRectangles; try { reader.readByte(); // padding numberOfRectangles = reader.readUInt16(); this.numberOfRectangles = numberOfRectangles; if(numberOfRectangles > 3) { // System.out.println("numberofrectangle : " + numberOfRectangles); if (rfb.getViewer().getUseMulticast()){ return; // Discard invalid packet } } 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 { // System.out.println(rect); decoder.decode(reader, renderer, rect); // TreeVNC processing here if (rfb.getCuiVersion()) continue; repaintController.repaintBitmap(rect); } catch (Exception e) { e.printStackTrace(); continue; // we have to read all rectangles } } 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(); System.out.println("INIT_DATA: "+rect); // 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(); } catch (Exception e) { System.out.println("FrameBufferUpdate: "+e); } sendFrameBufferUpdateRequest(); } public void checkFrameBufferRectanble(ByteBuffer c1, byte[] bytes, int flushOffset, int flushEnd) { FramebufferUpdateRectangle rect = new FramebufferUpdateRectangle(); Reader in = new Reader(new ByteArrayInputStream(c1.array())); try { if (getMessageId(in) != FRAMEBUFFER_UPDATE) { return; } in.readByte(); int numberOfRectangeles = in.readInt16(); if (true) { in.mark(c1.limit() - 4); ZRLEDecoder decoder = new ZRLEDecoder(); int n = numberOfRectangeles; while(n-- > 0 ) { rect.fill(in); if (rect.getEncodingType() == EncodingType.ZRLEE) { int length = rect.width * rect.height * renderer.getBytesPerPixel() + 20480; int zippedLength = (int) in.readUInt32(); if (zippedLength > in.available()) { System.out.println("overrun zippedLength=" + zippedLength + " available="+in.available()); } try { decoder.decoding = "checking offset="+Integer.toHexString(flushOffset)+ " "; ByteBuffer buf = decoder.unzip(in, zippedLength, length, rect.getEncodingType()); System.out.println("check rect No." + n + " = " + rect + " offset =" + flushOffset + " end = " + (flushOffset+buf.remaining()) + " span = " + (buf.remaining())); compareBytes(buf, bytes, flushOffset, flushOffset+buf.remaining()); flushOffset += buf.remaining(); } catch (Exception e) { e.printStackTrace(); } } } assert(flushOffset==flushEnd); in.reset(); } ZRLEDecoder zdecoder = new ZRLEDecoder(); Decoder decoder = zdecoder; while (numberOfRectangeles-- > 0) { rect.fill(in); if (rect.getEncodingType() == EncodingType.ZRLEE) { System.out.println(); zdecoder.decoding = "checking offset="+Integer.toHexString(flushOffset)+ " "; decoder.decode(in,new NullRenderer(context.getPixelFormat().bitsPerPixel/8, context.getFbWidth(), context.getFbHeight(), context.getPixelFormat()),rect); } } } catch (Exception e) { e.printStackTrace(); } } static public boolean multiasting = true; public void handleMulticastFrameBufferUpdate(ByteArrayInputStream c1) { FramebufferUpdateRectangle rect = new FramebufferUpdateRectangle(); Reader in = new Reader(c1); if (!multiasting) { System.out.println("broadcasting!"); multiasting = true; } try { if (getMessageId(in) != FRAMEBUFFER_UPDATE) { return; } in.readByte(); int numberOfRectangeles = in.readInt16(); ZRLEDecoder zdecoder = new ZRLEDecoder(); Decoder decoder = zdecoder; while (numberOfRectangeles-- > 0) { rect.fill(in); // System.out.println("broadcast rectangle "+rect); if (rect.getEncodingType() == EncodingType.ZRLEE) { decoder.decode(in,renderer,rect); if (rfb.getCuiVersion()) continue; repaintController.repaintBitmap(rect); } } } catch (Exception e) { e.printStackTrace(); } } private void compareBytes(ByteBuffer buf, byte[] bytes, int flushOffset, int flushEnd) { int span = flushEnd - flushOffset; int pos = buf.position(); if (buf.remaining() == span) { for(int i = 0;i<span;i++) { if (buf.array()[pos+i]!=bytes[flushOffset+i]) { System.out.println("Bytes is not equal at "+i); break; } } } else { System.out.println("Bytes is not equal length "+buf.remaining()+" - "+span + " = " + (buf.remaining() - span)); } dump("in ",bytes,flushOffset,8); dump("... ",bytes,flushEnd-8,8); System.out.println(); dump("out ",buf.array(),buf.position(),8); dump("... ",buf.array(),buf.limit()-8,8); System.out.println(); } public static void dump(String s, byte[] bytes, int begin, int len) { System.out.print(s); while(len > 0 && begin < bytes.length) { System.out.print(bytes[begin] + " "); begin ++ ; len--; } } 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; } }