Mercurial > hg > Applications > tvnjviewer
annotate src/main/java/com/glavsoft/rfb/protocol/Protocol.java @ 31:59cdd271f79c
change compressed DSM only pixel data
author | Nozomi Teruya <e125769@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 16 Nov 2015 23:02:29 +0900 |
parents | 45176f732171 |
children |
rev | line source |
---|---|
0 | 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 | |
22
45176f732171
put protocol instance for stop SenderTask and ReceiverTask
sugi
parents:
7
diff
changeset
|
27 import alice.datasegment.DataSegment; |
45176f732171
put protocol instance for stop SenderTask and ReceiverTask
sugi
parents:
7
diff
changeset
|
28 import alice.datasegment.ReceiveData; |
45176f732171
put protocol instance for stop SenderTask and ReceiverTask
sugi
parents:
7
diff
changeset
|
29 |
0 | 30 import com.glavsoft.core.SettingsChangedEvent; |
31 import com.glavsoft.exceptions.*; | |
32 import com.glavsoft.rfb.*; | |
33 import com.glavsoft.rfb.client.ClientToServerMessage; | |
34 import com.glavsoft.rfb.client.FramebufferUpdateRequestMessage; | |
35 import com.glavsoft.rfb.client.SetEncodingsMessage; | |
36 import com.glavsoft.rfb.client.SetPixelFormatMessage; | |
37 import com.glavsoft.rfb.encoding.PixelFormat; | |
38 import com.glavsoft.rfb.encoding.decoder.DecodersContainer; | |
39 import com.glavsoft.rfb.protocol.state.HandshakeState; | |
40 import com.glavsoft.rfb.protocol.state.ProtocolState; | |
41 import com.glavsoft.transport.Reader; | |
42 import com.glavsoft.transport.Writer; | |
43 | |
44 import java.util.logging.Logger; | |
45 | |
46 public class Protocol implements ProtocolContext, IChangeSettingsListener { | |
47 private ProtocolState state; | |
48 private final Logger logger; | |
49 private final IPasswordRetriever passwordRetriever; | |
50 private final ProtocolSettings settings; | |
51 private int fbWidth; | |
52 private int fbHeight; | |
53 private PixelFormat pixelFormat; | |
54 private final Reader reader; | |
55 private final Writer writer; | |
56 private String remoteDesktopName; | |
57 private MessageQueue messageQueue; | |
58 private final DecodersContainer decoders; | |
59 private SenderTask senderTask; | |
60 private ReceiverTask receiverTask; | |
61 private IRfbSessionListener rfbSessionListener; | |
62 private IRepaintController repaintController; | |
63 private PixelFormat serverPixelFormat; | |
64 private Thread senderThread; | |
65 private Thread receiverThread; | |
66 private boolean isTight; | |
67 private String protocolVersion; | |
68 | |
69 public Protocol(Reader reader, Writer writer, | |
70 IPasswordRetriever passwordRetriever, ProtocolSettings settings) { | |
71 this.reader = reader; | |
72 this.writer = writer; | |
73 this.passwordRetriever = passwordRetriever; | |
74 this.settings = settings; | |
75 decoders = new DecodersContainer(); | |
76 decoders.instantiateDecodersWhenNeeded(settings.encodings); | |
77 state = new HandshakeState(this); | |
78 logger = Logger.getLogger(getClass().getName()); | |
79 } | |
80 | |
81 @Override | |
82 public void changeStateTo(ProtocolState state) { | |
83 this.state = state; | |
84 } | |
85 | |
86 public void handshake() throws UnsupportedProtocolVersionException, UnsupportedSecurityTypeException, | |
87 AuthenticationFailedException, TransportException, FatalException { | |
88 while (state.next()) { | |
89 // continue; | |
90 } | |
91 this.messageQueue = new MessageQueue(); | |
92 } | |
93 | |
94 @Override | |
95 public PixelFormat getPixelFormat() { | |
96 return pixelFormat; | |
97 } | |
98 | |
99 @Override | |
100 public void setPixelFormat(PixelFormat pixelFormat) { | |
101 this.pixelFormat = pixelFormat; | |
102 if (repaintController != null) { | |
103 repaintController.setPixelFormat(pixelFormat); | |
104 } | |
105 } | |
106 | |
107 @Override | |
108 public String getRemoteDesktopName() { | |
109 return remoteDesktopName; | |
110 } | |
111 | |
112 @Override | |
113 public void setRemoteDesktopName(String name) { | |
114 remoteDesktopName = name; | |
115 } | |
116 | |
117 @Override | |
118 public int getFbWidth() { | |
119 return fbWidth; | |
120 } | |
121 | |
122 @Override | |
123 public void setFbWidth(int fbWidth) { | |
124 this.fbWidth = fbWidth; | |
125 } | |
126 | |
127 @Override | |
128 public int getFbHeight() { | |
129 return fbHeight; | |
130 } | |
131 | |
132 @Override | |
133 public void setFbHeight(int fbHeight) { | |
134 this.fbHeight = fbHeight; | |
135 } | |
136 | |
137 @Override | |
138 public IPasswordRetriever getPasswordRetriever() { | |
139 return passwordRetriever; | |
140 } | |
141 | |
142 @Override | |
143 public ProtocolSettings getSettings() { | |
144 return settings; | |
145 } | |
146 | |
147 @Override | |
148 public Writer getWriter() { | |
149 return writer; | |
150 } | |
151 | |
152 @Override | |
153 public Reader getReader() { | |
154 return reader; | |
155 } | |
156 | |
157 /** | |
158 * Following the server initialisation message it's up to the client to send | |
159 * whichever protocol messages it wants. Typically it will send a | |
160 * SetPixelFormat message and a SetEncodings message, followed by a | |
161 * FramebufferUpdateRequest. From then on the server will send | |
162 * FramebufferUpdate messages in response to the client's | |
163 * FramebufferUpdateRequest messages. The client should send | |
164 * FramebufferUpdateRequest messages with incremental set to true when it has | |
165 * finished processing one FramebufferUpdate and is ready to process another. | |
166 * With a fast client, the rate at which FramebufferUpdateRequests are sent | |
167 * should be regulated to avoid hogging the network. | |
168 */ | |
169 public void startNormalHandling(IRfbSessionListener rfbSessionListener, | |
170 IRepaintController repaintController, ClipboardController clipboardController) { | |
171 this.rfbSessionListener = rfbSessionListener; | |
172 this.repaintController = repaintController; | |
173 // if (settings.getColorDepth() == 0) { | |
174 // settings.setColorDepth(pixelFormat.depth); // the same the server sent when not initialized yet | |
175 // } | |
176 serverPixelFormat = pixelFormat; | |
177 correctServerPixelFormat(); | |
178 setPixelFormat(createPixelFormat(settings)); | |
179 sendMessage(new SetPixelFormatMessage(pixelFormat)); | |
180 logger.fine("sent: " + pixelFormat); | |
181 | |
182 sendSupportedEncodingsMessage(settings); | |
183 settings.addListener(this); // to support pixel format (color depth), and encodings changes | |
184 settings.addListener(repaintController); | |
185 | |
186 sendRefreshMessage(); | |
187 senderTask = new SenderTask(messageQueue, writer, this); | |
188 senderThread = new Thread(senderTask, "RfbSenderTask"); | |
189 senderThread.start(); | |
190 decoders.resetDecoders(); | |
191 receiverTask = new ReceiverTask( | |
192 reader, repaintController, | |
193 clipboardController, | |
194 decoders, this); | |
195 receiverThread = new Thread(receiverTask, "RfbReceiverTask"); | |
196 receiverThread.start(); | |
22
45176f732171
put protocol instance for stop SenderTask and ReceiverTask
sugi
parents:
7
diff
changeset
|
197 // add |
31
59cdd271f79c
change compressed DSM only pixel data
Nozomi Teruya <e125769@ie.u-ryukyu.ac.jp>
parents:
22
diff
changeset
|
198 ReceiveData rData = new ReceiveData(this); |
59cdd271f79c
change compressed DSM only pixel data
Nozomi Teruya <e125769@ie.u-ryukyu.ac.jp>
parents:
22
diff
changeset
|
199 DataSegment.getLocal().put("protocol", rData, false); |
0 | 200 } |
201 | |
202 private void correctServerPixelFormat() { | |
203 // correct true color flag - we don't support color maps, so always set it up | |
204 serverPixelFormat.trueColourFlag = 1; | |
205 // correct .depth to use actual depth 24 instead of incorrect 32, used by ex. UltraVNC server, that cause | |
206 // protocol incompatibility in ZRLE encoding | |
207 final long significant = serverPixelFormat.redMax << serverPixelFormat.redShift | | |
208 serverPixelFormat.greenMax << serverPixelFormat.greenShift | | |
209 serverPixelFormat.blueMax << serverPixelFormat.blueShift; | |
210 if (32 == serverPixelFormat.bitsPerPixel && | |
211 ((significant & 0x00ff000000L) == 0 || (significant & 0x000000ffL) == 0) && | |
212 32 == serverPixelFormat.depth) { | |
213 serverPixelFormat.depth = 24; | |
214 } | |
215 } | |
216 | |
217 @Override | |
218 public void sendMessage(ClientToServerMessage message) { | |
219 messageQueue.put(message); | |
220 } | |
221 | |
222 private void sendSupportedEncodingsMessage(ProtocolSettings settings) { | |
223 decoders.instantiateDecodersWhenNeeded(settings.encodings); | |
224 SetEncodingsMessage encodingsMessage = new SetEncodingsMessage(settings.encodings); | |
225 sendMessage(encodingsMessage); | |
226 logger.fine("sent: " + encodingsMessage.toString()); | |
227 } | |
228 | |
229 /** | |
230 * create pixel format by bpp | |
231 */ | |
232 private PixelFormat createPixelFormat(ProtocolSettings settings) { | |
233 int serverBigEndianFlag = serverPixelFormat.bigEndianFlag; | |
234 switch (settings.getColorDepth()) { | |
235 case ProtocolSettings.COLOR_DEPTH_24: | |
236 return PixelFormat.create24bitColorDepthPixelFormat(serverBigEndianFlag); | |
237 case ProtocolSettings.COLOR_DEPTH_16: | |
238 return PixelFormat.create16bitColorDepthPixelFormat(serverBigEndianFlag); | |
239 case ProtocolSettings.COLOR_DEPTH_8: | |
240 return PixelFormat.create8bitColorDepthBGRPixelFormat(serverBigEndianFlag); | |
241 case ProtocolSettings.COLOR_DEPTH_6: | |
242 return PixelFormat.create6bitColorDepthPixelFormat(serverBigEndianFlag); | |
243 case ProtocolSettings.COLOR_DEPTH_3: | |
244 return PixelFormat.create3bppPixelFormat(serverBigEndianFlag); | |
245 case ProtocolSettings.COLOR_DEPTH_SERVER_SETTINGS: | |
246 return serverPixelFormat; | |
247 default: | |
248 // unsupported bpp, use default | |
249 return PixelFormat.create24bitColorDepthPixelFormat(serverBigEndianFlag); | |
250 } | |
251 } | |
252 | |
253 @Override | |
254 public void settingsChanged(SettingsChangedEvent e) { | |
255 ProtocolSettings settings = (ProtocolSettings) e.getSource(); | |
256 if (settings.isChangedEncodings()) { | |
257 sendSupportedEncodingsMessage(settings); | |
258 } | |
259 if (settings.isChangedColorDepth() && receiverTask != null) { | |
260 receiverTask.queueUpdatePixelFormat(createPixelFormat(settings)); | |
261 } | |
262 } | |
263 | |
264 @Override | |
265 public void sendRefreshMessage() { | |
266 sendMessage(new FramebufferUpdateRequestMessage(0, 0, fbWidth, fbHeight, false)); | |
267 logger.fine("sent: full FB Refresh"); | |
268 } | |
269 | |
270 @Override | |
271 public void cleanUpSession(String message) { | |
272 cleanUpSession(); | |
273 rfbSessionListener.rfbSessionStopped(message); | |
274 } | |
275 | |
276 public synchronized void cleanUpSession() { | |
277 if (senderTask != null) { senderTask.stopTask(); } | |
278 if (receiverTask != null) { receiverTask.stopTask(); } | |
279 if (senderTask != null) { | |
280 try { | |
281 senderThread.join(1000); | |
282 } catch (InterruptedException e) { | |
283 // nop | |
284 } | |
285 senderTask = null; | |
286 } | |
287 if (receiverTask != null) { | |
288 try { | |
289 receiverThread.join(1000); | |
290 } catch (InterruptedException e) { | |
291 // nop | |
292 } | |
293 receiverTask = null; | |
294 } | |
295 } | |
296 | |
297 @Override | |
298 public void setTight(boolean isTight) { | |
299 this.isTight = isTight; | |
300 } | |
301 | |
302 @Override | |
303 public boolean isTight() { | |
304 return isTight; | |
305 } | |
306 | |
307 @Override | |
308 public void setProtocolVersion(String protocolVersion) { | |
309 this.protocolVersion = protocolVersion; | |
310 } | |
311 | |
312 @Override | |
313 public String getProtocolVersion() { | |
314 return protocolVersion; | |
315 } | |
316 | |
7 | 317 public void setMessageQueue(MessageQueue queue) { // add |
22
45176f732171
put protocol instance for stop SenderTask and ReceiverTask
sugi
parents:
7
diff
changeset
|
318 messageQueue = queue; |
45176f732171
put protocol instance for stop SenderTask and ReceiverTask
sugi
parents:
7
diff
changeset
|
319 |
3 | 320 } |
321 | |
0 | 322 } |