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
|
|
27 import com.glavsoft.core.SettingsChangedEvent;
|
|
28 import com.glavsoft.rfb.CapabilityContainer;
|
|
29 import com.glavsoft.rfb.IChangeSettingsListener;
|
|
30 import com.glavsoft.rfb.RfbCapabilityInfo;
|
|
31 import com.glavsoft.rfb.encoding.EncodingType;
|
|
32 import com.glavsoft.rfb.protocol.auth.SecurityType;
|
|
33
|
|
34 import java.io.Serializable;
|
|
35 import java.util.Iterator;
|
|
36 import java.util.LinkedHashSet;
|
|
37 import java.util.LinkedList;
|
|
38 import java.util.List;
|
|
39
|
|
40 /**
|
|
41 * Protocol Settings class
|
|
42 */
|
|
43 public class ProtocolSettings implements Serializable {
|
|
44 private static final long serialVersionUID = 1L;
|
|
45
|
|
46 private static final EncodingType DEFAULT_PREFERRED_ENCODING = EncodingType.TIGHT;
|
|
47 public static final int DEFAULT_JPEG_QUALITY = 6;
|
|
48 private static final int DEFAULT_COMPRESSION_LEVEL = -6;
|
|
49
|
|
50 // color depth constants
|
|
51 public static final int COLOR_DEPTH_32 = 32;
|
|
52 public static final int COLOR_DEPTH_24 = 24;
|
|
53 public static final int COLOR_DEPTH_16 = 16;
|
|
54 public static final int COLOR_DEPTH_8 = 8;
|
|
55 public static final int COLOR_DEPTH_6 = 6;
|
|
56 public static final int COLOR_DEPTH_3 = 3;
|
|
57
|
|
58 public static final int COLOR_DEPTH_SERVER_SETTINGS = 0;
|
|
59
|
|
60 private static final int DEFAULT_COLOR_DEPTH = COLOR_DEPTH_24;
|
|
61
|
|
62 public static final int CHANGED_VIEW_ONLY = 1; // 1 << 0;
|
|
63 public static final int CHANGED_ENCODINGS = 1 << 1;
|
|
64 public static final int CHANGED_ALLOW_COPY_RECT = 1 << 2;
|
|
65 public static final int CHANGED_SHOW_REMOTE_CURSOR = 1 << 3;
|
|
66 public static final int CHANGED_MOUSE_CURSOR_TRACK = 1 << 4;
|
|
67 public static final int CHANGED_COMPRESSION_LEVEL = 1 << 5;
|
|
68 public static final int CHANGED_JPEG_QUALITY = 1 << 6;
|
|
69 public static final int CHANGED_ALLOW_CLIPBOARD_TRANSFER = 1 << 7;
|
|
70 public static final int CHANGED_CONVERT_TO_ASCII = 1 << 8;
|
|
71 public static final int CHANGED_COLOR_DEPTH = 1 << 9;
|
|
72 public static final int CHANGED_SHARED = 1 << 10;
|
|
73
|
|
74 private transient int changedSettingsMask;
|
|
75
|
|
76 private boolean sharedFlag;
|
|
77 private boolean viewOnly;
|
|
78 private EncodingType preferredEncoding;
|
|
79 private boolean allowCopyRect;
|
|
80 private boolean showRemoteCursor;
|
|
81 private LocalPointer mouseCursorTrack;
|
|
82 private int compressionLevel;
|
|
83 private int jpegQuality;
|
|
84 private boolean allowClipboardTransfer;
|
|
85 private boolean convertToAscii;
|
|
86 private int colorDepth;
|
|
87
|
|
88 public transient LinkedHashSet<EncodingType> encodings;
|
|
89 private transient final List<IChangeSettingsListener> listeners;
|
|
90
|
|
91 public transient CapabilityContainer
|
|
92 tunnelingCapabilities,
|
|
93 authCapabilities,
|
|
94 serverMessagesCapabilities,
|
|
95 clientMessagesCapabilities,
|
|
96 encodingTypesCapabilities;
|
|
97 private transient String remoteCharsetName;
|
|
98
|
|
99 public static ProtocolSettings getDefaultSettings() {
|
|
100 ProtocolSettings settings = new ProtocolSettings();
|
|
101 settings.initKnownAuthCapabilities(settings.authCapabilities);
|
|
102 settings.initKnownEncodingTypesCapabilities(settings.encodingTypesCapabilities);
|
|
103 return settings;
|
|
104 }
|
|
105
|
|
106 private ProtocolSettings() {
|
|
107 sharedFlag = true;
|
|
108 viewOnly = false;
|
|
109 showRemoteCursor = true;
|
|
110 mouseCursorTrack = LocalPointer.ON;
|
|
111 preferredEncoding = DEFAULT_PREFERRED_ENCODING;
|
|
112 allowCopyRect = true;
|
|
113 compressionLevel = DEFAULT_COMPRESSION_LEVEL;
|
|
114 jpegQuality = DEFAULT_JPEG_QUALITY;
|
|
115 convertToAscii = false;
|
|
116 allowClipboardTransfer = true;
|
|
117 colorDepth = COLOR_DEPTH_SERVER_SETTINGS;
|
|
118 refine();
|
|
119
|
|
120 listeners = new LinkedList<IChangeSettingsListener>();
|
|
121 tunnelingCapabilities = new CapabilityContainer();
|
|
122 authCapabilities = new CapabilityContainer();
|
|
123 serverMessagesCapabilities = new CapabilityContainer();
|
|
124 clientMessagesCapabilities = new CapabilityContainer();
|
|
125 encodingTypesCapabilities = new CapabilityContainer();
|
|
126 changedSettingsMask = 0;
|
|
127 }
|
|
128
|
|
129 public ProtocolSettings(ProtocolSettings s) {
|
|
130 this();
|
|
131 copyDataFrom(s);
|
|
132 changedSettingsMask = s.changedSettingsMask;
|
|
133 encodings = s.encodings;
|
|
134 }
|
|
135
|
|
136 public void copyDataFrom(ProtocolSettings s) {
|
|
137 copyDataFrom(s, 0);
|
|
138 }
|
|
139
|
|
140 public void copyDataFrom(ProtocolSettings s, int mask) {
|
|
141 if (null == s) return;
|
|
142 if ((mask & CHANGED_SHARED) == 0) setSharedFlag(s.sharedFlag);
|
|
143 if ((mask & CHANGED_VIEW_ONLY) == 0) setViewOnly(s.viewOnly);
|
|
144 if ((mask & CHANGED_ALLOW_COPY_RECT) == 0) setAllowCopyRect(s.allowCopyRect);
|
|
145 if ((mask & CHANGED_SHOW_REMOTE_CURSOR) == 0) setShowRemoteCursor(s.showRemoteCursor);
|
|
146 if ((mask & CHANGED_ALLOW_CLIPBOARD_TRANSFER) == 0) setAllowClipboardTransfer(s.allowClipboardTransfer);
|
|
147
|
|
148 if ((mask & CHANGED_MOUSE_CURSOR_TRACK) == 0) setMouseCursorTrack(s.mouseCursorTrack);
|
|
149 if ((mask & CHANGED_COMPRESSION_LEVEL) == 0) setCompressionLevel(s.compressionLevel);
|
|
150 if ((mask & CHANGED_JPEG_QUALITY) == 0) setJpegQuality(s.jpegQuality);
|
|
151 if ((mask & CHANGED_CONVERT_TO_ASCII) == 0) setConvertToAscii(s.convertToAscii);
|
|
152 if ((mask & CHANGED_COLOR_DEPTH) == 0) setColorDepth(s.colorDepth);
|
|
153 if ((mask & CHANGED_ENCODINGS) == 0) setPreferredEncoding(s.preferredEncoding);
|
|
154 }
|
|
155
|
|
156 private void initKnownAuthCapabilities(CapabilityContainer cc) {
|
|
157 cc.addEnabled(SecurityType.NONE_AUTHENTICATION.getId(),
|
|
158 RfbCapabilityInfo.VENDOR_STANDARD, RfbCapabilityInfo.AUTHENTICATION_NO_AUTH);
|
|
159 cc.addEnabled(SecurityType.VNC_AUTHENTICATION.getId(),
|
|
160 RfbCapabilityInfo.VENDOR_STANDARD, RfbCapabilityInfo.AUTHENTICATION_VNC_AUTH);
|
15
|
161 cc.addEnabled(SecurityType.REQUIRE_AUTHENTICATION.getId()
|
|
162 , RfbCapabilityInfo.VENDOR_STANDARD, RfbCapabilityInfo.AUTHENTICATION_REQ_AUTH);
|
0
|
163 //cc.addEnabled( 19, "VENC", "VENCRYPT");
|
|
164 //cc.addEnabled( 20, "GTKV", "SASL____");
|
|
165 //cc.addEnabled(129, RfbCapabilityInfo.TIGHT_VNC_VENDOR, "ULGNAUTH");
|
|
166 //cc.addEnabled(130, RfbCapabilityInfo.TIGHT_VNC_VENDOR, "XTRNAUTH");
|
|
167 }
|
|
168
|
|
169 private void initKnownEncodingTypesCapabilities(CapabilityContainer cc) {
|
|
170 cc.add(EncodingType.COPY_RECT.getId(),
|
|
171 RfbCapabilityInfo.VENDOR_STANDARD, RfbCapabilityInfo.ENCODING_COPYRECT);
|
|
172 cc.add(EncodingType.HEXTILE.getId(),
|
|
173 RfbCapabilityInfo.VENDOR_STANDARD, RfbCapabilityInfo.ENCODING_HEXTILE);
|
|
174 cc.add(EncodingType.ZLIB.getId(),
|
|
175 RfbCapabilityInfo.VENDOR_TRIADA, RfbCapabilityInfo.ENCODING_ZLIB);
|
|
176 cc.add(EncodingType.ZRLE.getId(),
|
|
177 RfbCapabilityInfo.VENDOR_TRIADA, RfbCapabilityInfo.ENCODING_ZRLE);
|
|
178 cc.add(EncodingType.RRE.getId(),
|
|
179 RfbCapabilityInfo.VENDOR_STANDARD, RfbCapabilityInfo.ENCODING_RRE);
|
|
180 cc.add(EncodingType.TIGHT.getId(),
|
|
181 RfbCapabilityInfo.VENDOR_TIGHT, RfbCapabilityInfo.ENCODING_TIGHT);
|
|
182
|
|
183 cc.add(EncodingType.RICH_CURSOR.getId(),
|
|
184 RfbCapabilityInfo.VENDOR_TIGHT, RfbCapabilityInfo.ENCODING_RICH_CURSOR);
|
|
185 cc.add(EncodingType.CURSOR_POS.getId(),
|
|
186 RfbCapabilityInfo.VENDOR_TIGHT, RfbCapabilityInfo.ENCODING_CURSOR_POS);
|
|
187 cc.add(EncodingType.DESKTOP_SIZE.getId(),
|
|
188 RfbCapabilityInfo.VENDOR_TIGHT, RfbCapabilityInfo.ENCODING_DESKTOP_SIZE);
|
|
189 }
|
|
190
|
|
191 public void addListener(IChangeSettingsListener listener) {
|
|
192 listeners.add(listener);
|
|
193 }
|
|
194
|
|
195 public byte getSharedFlag() {
|
|
196 return (byte) (sharedFlag ? 1 : 0);
|
|
197 }
|
|
198
|
|
199 public boolean isShared() {
|
|
200 return sharedFlag;
|
|
201 }
|
|
202
|
|
203 public void setSharedFlag(boolean sharedFlag) {
|
|
204 if (this.sharedFlag != sharedFlag) {
|
|
205 this.sharedFlag = sharedFlag;
|
|
206 changedSettingsMask |= CHANGED_SHARED;
|
|
207 }
|
|
208 }
|
|
209
|
|
210 public boolean isViewOnly() {
|
|
211 return viewOnly;
|
|
212 }
|
|
213
|
|
214 public void setViewOnly(boolean viewOnly) {
|
|
215 if (this.viewOnly != viewOnly) {
|
|
216 this.viewOnly = viewOnly;
|
|
217 changedSettingsMask |= CHANGED_VIEW_ONLY;
|
|
218 }
|
|
219 }
|
|
220
|
|
221 public void enableAllEncodingCaps() {
|
|
222 encodingTypesCapabilities.setAllEnable(true);
|
|
223
|
|
224 }
|
|
225
|
|
226 public int getColorDepth() {
|
|
227 return colorDepth;
|
|
228 }
|
|
229
|
|
230 /**
|
|
231 * Set depth only in 3, 6, 8, 16, 32. When depth is wrong, it resets to {@link #DEFAULT_COLOR_DEPTH}
|
|
232 */
|
|
233 public void setColorDepth(int depth) {
|
|
234 if (colorDepth != depth) {
|
|
235 changedSettingsMask |= CHANGED_COLOR_DEPTH;
|
|
236 switch (depth) {
|
|
237 case COLOR_DEPTH_32:
|
|
238 colorDepth = COLOR_DEPTH_24;
|
|
239 break;
|
|
240 case COLOR_DEPTH_24:
|
|
241 case COLOR_DEPTH_16:
|
|
242 case COLOR_DEPTH_8:
|
|
243 case COLOR_DEPTH_6:
|
|
244 case COLOR_DEPTH_3:
|
|
245 case COLOR_DEPTH_SERVER_SETTINGS:
|
|
246 colorDepth = depth;
|
|
247 break;
|
|
248 default:
|
|
249 colorDepth = DEFAULT_COLOR_DEPTH;
|
|
250 }
|
|
251 refine();
|
|
252 }
|
|
253 }
|
|
254
|
|
255 public void refine() {
|
|
256 LinkedHashSet<EncodingType> encodings = new LinkedHashSet<EncodingType>();
|
|
257 if (EncodingType.RAW_ENCODING == preferredEncoding) {
|
|
258 // when RAW selected send no ordinary encodings so only default RAW encoding will be enabled
|
|
259 } else {
|
|
260 encodings.add(preferredEncoding); // preferred first
|
|
261 encodings.addAll(EncodingType.ordinaryEncodings);
|
|
262 if (compressionLevel > 0 && compressionLevel < 10) {
|
|
263 encodings.add(EncodingType.byId(
|
|
264 EncodingType.COMPRESS_LEVEL_0.getId() + compressionLevel));
|
|
265 }
|
|
266 if (jpegQuality > 0 && jpegQuality < 10 &&
|
|
267 (colorDepth == COLOR_DEPTH_24 || colorDepth == COLOR_DEPTH_SERVER_SETTINGS)) {
|
|
268 encodings.add(EncodingType.byId(
|
|
269 EncodingType.JPEG_QUALITY_LEVEL_0.getId() + jpegQuality));
|
|
270 }
|
|
271 if (allowCopyRect) {
|
|
272 encodings.add(EncodingType.COPY_RECT);
|
|
273 }
|
|
274 }
|
|
275 switch(mouseCursorTrack) {
|
|
276 case OFF:
|
|
277 setShowRemoteCursor(false);
|
|
278 break;
|
|
279 case HIDE:
|
|
280 setShowRemoteCursor(false);
|
|
281 encodings.add(EncodingType.RICH_CURSOR);
|
|
282 encodings.add(EncodingType.CURSOR_POS);
|
|
283 break;
|
|
284 case ON:
|
|
285 default:
|
|
286 setShowRemoteCursor(true);
|
|
287 encodings.add(EncodingType.RICH_CURSOR);
|
|
288 encodings.add(EncodingType.CURSOR_POS);
|
|
289 }
|
|
290 encodings.add(EncodingType.DESKTOP_SIZE);
|
|
291 if ( isEncodingsChanged(this.encodings, encodings) || isChangedEncodings()) {
|
|
292 this.encodings = encodings;
|
|
293 changedSettingsMask |= CHANGED_ENCODINGS;
|
|
294 }
|
|
295 }
|
|
296
|
|
297 private boolean isEncodingsChanged(LinkedHashSet<EncodingType> encodings1, LinkedHashSet<EncodingType> encodings2) {
|
|
298 if (null == encodings1 || encodings1.size() != encodings2.size()) return true;
|
|
299 Iterator<EncodingType> it1 = encodings1.iterator();
|
|
300 Iterator<EncodingType> it2 = encodings2.iterator();
|
|
301 while (it1.hasNext()) {
|
|
302 EncodingType v1 = it1.next();
|
|
303 EncodingType v2 = it2.next();
|
|
304 if (v1 != v2) return true;
|
|
305 }
|
|
306 return false;
|
|
307 }
|
|
308
|
|
309 public void fireListeners() {
|
|
310 if (null == listeners) return;
|
|
311 final SettingsChangedEvent event = new SettingsChangedEvent(new ProtocolSettings(this));
|
|
312 changedSettingsMask = 0;
|
|
313 for (IChangeSettingsListener listener : listeners) {
|
|
314 listener.settingsChanged(event);
|
|
315 }
|
|
316 }
|
|
317
|
|
318 public static boolean isRfbSettingsChangedFired(SettingsChangedEvent event) {
|
|
319 return event.getSource() instanceof ProtocolSettings;
|
|
320 }
|
|
321
|
|
322 public void setPreferredEncoding(EncodingType preferredEncoding) {
|
|
323 if (this.preferredEncoding != preferredEncoding) {
|
|
324 this.preferredEncoding = preferredEncoding;
|
|
325 changedSettingsMask |= CHANGED_ENCODINGS;
|
|
326 refine();
|
|
327 }
|
|
328 }
|
|
329
|
|
330 public EncodingType getPreferredEncoding() {
|
|
331 return preferredEncoding;
|
|
332 }
|
|
333
|
|
334 public void setAllowCopyRect(boolean allowCopyRect) {
|
|
335 if (this.allowCopyRect != allowCopyRect) {
|
|
336 this.allowCopyRect = allowCopyRect;
|
|
337 changedSettingsMask |= CHANGED_ALLOW_COPY_RECT;
|
|
338 refine();
|
|
339 }
|
|
340 }
|
|
341
|
|
342 public boolean isAllowCopyRect() {
|
|
343 return allowCopyRect;
|
|
344 }
|
|
345
|
|
346 private void setShowRemoteCursor(boolean showRemoteCursor) {
|
|
347 if (this.showRemoteCursor != showRemoteCursor) {
|
|
348 this.showRemoteCursor = showRemoteCursor;
|
|
349 changedSettingsMask |= CHANGED_SHOW_REMOTE_CURSOR;
|
|
350 }
|
|
351 }
|
|
352
|
|
353 public boolean isShowRemoteCursor() {
|
|
354 return showRemoteCursor;
|
|
355 }
|
|
356
|
|
357 public void setMouseCursorTrack(LocalPointer mouseCursorTrack) {
|
|
358 if (this.mouseCursorTrack != mouseCursorTrack) {
|
|
359 this.mouseCursorTrack = mouseCursorTrack;
|
|
360 changedSettingsMask |= CHANGED_MOUSE_CURSOR_TRACK;
|
|
361 refine();
|
|
362 }
|
|
363 }
|
|
364
|
|
365 public LocalPointer getMouseCursorTrack() {
|
|
366 return mouseCursorTrack;
|
|
367 }
|
|
368
|
|
369 public void setCompressionLevel(int compressionLevel) {
|
|
370 if (this.compressionLevel != compressionLevel) {
|
|
371 this.compressionLevel = compressionLevel;
|
|
372 changedSettingsMask |= CHANGED_COMPRESSION_LEVEL;
|
|
373 refine();
|
|
374 }
|
|
375 }
|
|
376
|
|
377 public int getCompressionLevel() {
|
|
378 return compressionLevel;
|
|
379 }
|
|
380
|
|
381 public void setJpegQuality(int jpegQuality) {
|
|
382 if (this.jpegQuality != jpegQuality) {
|
|
383 this.jpegQuality = jpegQuality;
|
|
384 changedSettingsMask |= CHANGED_JPEG_QUALITY;
|
|
385 refine();
|
|
386 }
|
|
387 }
|
|
388
|
|
389 public int getJpegQuality() {
|
|
390 return jpegQuality;
|
|
391 }
|
|
392
|
|
393 public void setAllowClipboardTransfer(boolean enable) {
|
|
394 if (this.allowClipboardTransfer != enable) {
|
|
395 this.allowClipboardTransfer = enable;
|
|
396 changedSettingsMask |= CHANGED_ALLOW_CLIPBOARD_TRANSFER;
|
|
397 }
|
|
398 }
|
|
399
|
|
400 public boolean isAllowClipboardTransfer() {
|
|
401 return allowClipboardTransfer;
|
|
402 }
|
|
403
|
|
404 public boolean isConvertToAscii() {
|
|
405 return convertToAscii;
|
|
406 }
|
|
407
|
|
408 public void setConvertToAscii(boolean convertToAscii) {
|
|
409 if (this.convertToAscii != convertToAscii) {
|
|
410 this.convertToAscii = convertToAscii;
|
|
411 changedSettingsMask |= CHANGED_CONVERT_TO_ASCII;
|
|
412 }
|
|
413 }
|
|
414
|
|
415 public boolean isChangedEncodings() {
|
|
416 return (changedSettingsMask & CHANGED_ENCODINGS) == CHANGED_ENCODINGS;
|
|
417 }
|
|
418
|
|
419 public boolean isChangedColorDepth() {
|
|
420 return (changedSettingsMask & CHANGED_COLOR_DEPTH) == CHANGED_COLOR_DEPTH;
|
|
421 }
|
|
422
|
|
423 public void setRemoteCharsetName(String remoteCharsetName) {
|
|
424 this.remoteCharsetName = remoteCharsetName;
|
|
425 }
|
|
426
|
|
427 public String getRemoteCharsetName() {
|
|
428 return remoteCharsetName;
|
|
429 }
|
|
430
|
|
431 @Override
|
|
432 public String toString() {
|
|
433 return "ProtocolSettings{" +
|
|
434 "sharedFlag=" + sharedFlag +
|
|
435 ", viewOnly=" + viewOnly +
|
|
436 ", preferredEncoding=" + preferredEncoding +
|
|
437 ", allowCopyRect=" + allowCopyRect +
|
|
438 ", showRemoteCursor=" + showRemoteCursor +
|
|
439 ", mouseCursorTrack=" + mouseCursorTrack +
|
|
440 ", compressionLevel=" + compressionLevel +
|
|
441 ", jpegQuality=" + jpegQuality +
|
|
442 ", allowClipboardTransfer=" + allowClipboardTransfer +
|
|
443 ", convertToAscii=" + convertToAscii +
|
|
444 ", colorDepth=" + colorDepth +
|
|
445 '}';
|
|
446 }
|
|
447 }
|