comparison src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java @ 0:daa24f8a557b

TightVNC original
author YU
date Thu, 11 Sep 2014 07:30:03 +0900
parents
children 3c0f262384dc
comparison
equal deleted inserted replaced
-1:000000000000 0:daa24f8a557b
1 // Copyright (C) 2010, 2011, 2012, 2013 GlavSoft LLC.
2 // All rights reserved.
3 //
4 //-------------------------------------------------------------------------
5 // This file is part of the TightVNC software. Please visit our Web site:
6 //
7 // http://www.tightvnc.com/
8 //
9 // This program is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License along
20 // with this program; if not, write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 //-------------------------------------------------------------------------
23 //
24
25 package com.glavsoft.rfb.protocol;
26
27 import com.glavsoft.drawing.Renderer;
28 import com.glavsoft.exceptions.CommonException;
29 import com.glavsoft.exceptions.ProtocolException;
30 import com.glavsoft.exceptions.TransportException;
31 import com.glavsoft.rfb.ClipboardController;
32 import com.glavsoft.rfb.IRepaintController;
33 import com.glavsoft.rfb.client.FramebufferUpdateRequestMessage;
34 import com.glavsoft.rfb.client.SetPixelFormatMessage;
35 import com.glavsoft.rfb.encoding.EncodingType;
36 import com.glavsoft.rfb.encoding.PixelFormat;
37 import com.glavsoft.rfb.encoding.decoder.Decoder;
38 import com.glavsoft.rfb.encoding.decoder.DecodersContainer;
39 import com.glavsoft.rfb.encoding.decoder.FramebufferUpdateRectangle;
40 import com.glavsoft.rfb.encoding.decoder.RichCursorDecoder;
41 import com.glavsoft.transport.Reader;
42
43 import java.io.PrintWriter;
44 import java.io.StringWriter;
45 import java.util.logging.Logger;
46
47 public class ReceiverTask implements Runnable {
48 private static final byte FRAMEBUFFER_UPDATE = 0;
49 private static final byte SET_COLOR_MAP_ENTRIES = 1;
50 private static final byte BELL = 2;
51 private static final byte SERVER_CUT_TEXT = 3;
52
53
54 private static Logger logger = Logger.getLogger("com.glavsoft.rfb.protocol.ReceiverTask");
55 private final Reader reader;
56 private volatile boolean isRunning = false;
57 private Renderer renderer;
58 private final IRepaintController repaintController;
59 private final ClipboardController clipboardController;
60 private final DecodersContainer decoders;
61 private FramebufferUpdateRequestMessage fullscreenFbUpdateIncrementalRequest;
62 private final ProtocolContext context;
63 private PixelFormat pixelFormat;
64 private boolean needSendPixelFormat;
65
66 public ReceiverTask(Reader reader,
67 IRepaintController repaintController, ClipboardController clipboardController,
68 DecodersContainer decoders, ProtocolContext context) {
69 this.reader = reader;
70 this.repaintController = repaintController;
71 this.clipboardController = clipboardController;
72 this.context = context;
73 this.decoders = decoders;
74 renderer = repaintController.createRenderer(reader, context.getFbWidth(), context.getFbHeight(),
75 context.getPixelFormat());
76 fullscreenFbUpdateIncrementalRequest =
77 new FramebufferUpdateRequestMessage(0, 0, context.getFbWidth(), context.getFbHeight(), true);
78 }
79
80 @Override
81 public void run() {
82 isRunning = true;
83 while (isRunning) {
84 try {
85 byte messageId = reader.readByte();
86 switch (messageId) {
87 case FRAMEBUFFER_UPDATE:
88 // logger.fine("Server message: FramebufferUpdate (0)");
89 framebufferUpdateMessage();
90 break;
91 case SET_COLOR_MAP_ENTRIES:
92 logger.severe("Server message SetColorMapEntries is not implemented. Skip.");
93 setColorMapEntries();
94 break;
95 case BELL:
96 logger.fine("Server message: Bell");
97 System.out.print("\0007");
98 System.out.flush();
99 break;
100 case SERVER_CUT_TEXT:
101 logger.fine("Server message: CutText (3)");
102 serverCutText();
103 break;
104 default:
105 logger.severe("Unsupported server message. Id = " + messageId);
106 }
107 } catch (TransportException e) {
108 if (isRunning) {
109 logger.severe("Close session: " + e.getMessage());
110 context.cleanUpSession("Connection closed.");
111 }
112 stopTask();
113 } catch (ProtocolException e) {
114 logger.severe(e.getMessage());
115 if (isRunning) {
116 context.cleanUpSession(e.getMessage() + "\nConnection closed.");
117 }
118 stopTask();
119 } catch (CommonException e) {
120 logger.severe(e.getMessage());
121 if (isRunning) {
122 context.cleanUpSession("Connection closed..");
123 }
124 stopTask();
125 } catch (Throwable te) {
126 StringWriter sw = new StringWriter();
127 PrintWriter pw = new PrintWriter(sw);
128 te.printStackTrace(pw);
129 if (isRunning) {
130 context.cleanUpSession(te.getMessage() + "\n" + sw.toString());
131 }
132 stopTask();
133 }
134 }
135 }
136
137 private void setColorMapEntries() throws TransportException {
138 reader.readByte(); // padding
139 reader.readUInt16(); // first color index
140 int length = reader.readUInt16();
141 while (length-- > 0) {
142 reader.readUInt16(); // R
143 reader.readUInt16(); // G
144 reader.readUInt16(); // B
145 }
146 }
147
148 private void serverCutText() throws TransportException {
149 reader.readByte(); // padding
150 reader.readInt16(); // padding
151 int length = reader.readInt32() & Integer.MAX_VALUE;
152 clipboardController.updateSystemClipboard(reader.readBytes(length));
153 }
154
155 public void framebufferUpdateMessage() throws CommonException {
156 reader.readByte(); // padding
157 int numberOfRectangles = reader.readUInt16();
158 while (numberOfRectangles-- > 0) {
159 FramebufferUpdateRectangle rect = new FramebufferUpdateRectangle();
160 rect.fill(reader);
161
162 Decoder decoder = decoders.getDecoderByType(rect.getEncodingType());
163 logger.finest(rect.toString() + (0 == numberOfRectangles ? "\n---" : ""));
164 if (decoder != null) {
165 decoder.decode(reader, renderer, rect);
166 repaintController.repaintBitmap(rect);
167 } else if (rect.getEncodingType() == EncodingType.RICH_CURSOR) {
168 RichCursorDecoder.getInstance().decode(reader, renderer, rect);
169 repaintController.repaintCursor();
170 } else if (rect.getEncodingType() == EncodingType.CURSOR_POS) {
171 renderer.decodeCursorPosition(rect);
172 repaintController.repaintCursor();
173 } else if (rect.getEncodingType() == EncodingType.DESKTOP_SIZE) {
174 fullscreenFbUpdateIncrementalRequest =
175 new FramebufferUpdateRequestMessage(0, 0, rect.width, rect.height, true);
176 synchronized (renderer.getLock()) {
177 renderer = repaintController.createRenderer(reader, rect.width, rect.height,
178 context.getPixelFormat());
179 }
180 context.sendMessage(new FramebufferUpdateRequestMessage(0, 0, rect.width, rect.height, false));
181 // repaintController.repaintCursor();
182 } else
183 throw new CommonException("Unprocessed encoding: " + rect.toString());
184 }
185 synchronized (this) {
186 if (needSendPixelFormat) {
187 needSendPixelFormat = false;
188 context.setPixelFormat(pixelFormat);
189 context.sendMessage(new SetPixelFormatMessage(pixelFormat));
190 logger.fine("sent: "+pixelFormat);
191 context.sendRefreshMessage();
192 logger.fine("sent: nonincremental fb update");
193 } else {
194 context.sendMessage(fullscreenFbUpdateIncrementalRequest);
195 }
196 }
197 }
198
199 public synchronized void queueUpdatePixelFormat(PixelFormat pf) {
200 pixelFormat = pf;
201 needSendPixelFormat = true;
202 // context.sendMessage(new FramebufferUpdateRequestMessage(0, 0, 1, 1, false));
203 }
204
205 public void stopTask() {
206 isRunning = false;
207 }
208
209 }