52
|
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.viewer.swing;
|
|
26
|
|
27 import com.glavsoft.exceptions.*;
|
|
28 import com.glavsoft.rfb.IPasswordRetriever;
|
|
29 import com.glavsoft.rfb.IRfbSessionListener;
|
|
30 import com.glavsoft.rfb.protocol.Protocol;
|
|
31 import com.glavsoft.rfb.protocol.ProtocolSettings;
|
|
32 import com.glavsoft.transport.Reader;
|
|
33 import com.glavsoft.transport.Writer;
|
|
34 import com.glavsoft.utils.Strings;
|
|
35 import com.glavsoft.viewer.*;
|
|
36 import com.glavsoft.viewer.swing.gui.PasswordDialog;
|
|
37
|
|
38 import javax.swing.*;
|
|
39 import java.io.IOException;
|
|
40 import java.lang.reflect.InvocationTargetException;
|
|
41 import java.net.Socket;
|
|
42 import java.util.List;
|
|
43 import java.util.concurrent.CancellationException;
|
|
44 import java.util.concurrent.ExecutionException;
|
|
45 import java.util.logging.Logger;
|
|
46
|
|
47 /**
|
|
48 * @author dime at tightvnc.com
|
|
49 */
|
|
50 public class SwingRfbConnectionWorker extends SwingWorker<Void, String> implements RfbConnectionWorker, IRfbSessionListener {
|
|
51
|
|
52 private String predefinedPassword;
|
|
53 private ConnectionPresenter presenter;
|
|
54 private JFrame parentWindow;
|
|
55 private SwingViewerWindowFactory viewerWindowFactory;
|
|
56 private Logger logger;
|
|
57 private volatile boolean isStoppingProcess;
|
|
58 private SwingViewerWindow viewerWindow;
|
|
59 protected String connectionString;
|
|
60 protected Protocol workingProtocol;
|
|
61 protected Socket workingSocket;
|
|
62 protected ProtocolSettings rfbSettings;
|
|
63 protected UiSettings uiSettings;
|
|
64
|
|
65 @Override
|
|
66 public Void doInBackground() throws Exception {
|
|
67 if (null == workingSocket) throw new ConnectionErrorException("Null socket");
|
|
68 workingSocket.setTcpNoDelay(true); // disable Nagle algorithm
|
|
69 Reader reader = new Reader(workingSocket.getInputStream());
|
|
70 Writer writer = new Writer(workingSocket.getOutputStream());
|
|
71
|
|
72 workingProtocol = new Protocol(reader, writer,
|
|
73 new PasswordChooser(connectionString, parentWindow, this),
|
|
74 rfbSettings);
|
|
75 String message = "Handshaking with remote host";
|
|
76 logger.info(message);
|
|
77 publish(message);
|
|
78
|
|
79 workingProtocol.handshake();
|
|
80 // tryAgain = false;
|
|
81 return null;
|
|
82 }
|
|
83
|
|
84 public SwingRfbConnectionWorker(String predefinedPassword, ConnectionPresenter presenter, JFrame parentWindow,
|
|
85 SwingViewerWindowFactory viewerWindowFactory) {
|
|
86 this.predefinedPassword = predefinedPassword;
|
|
87 this.presenter = presenter;
|
|
88 this.parentWindow = parentWindow;
|
|
89 this.viewerWindowFactory = viewerWindowFactory;
|
|
90 logger = Logger.getLogger(getClass().getName());
|
|
91 }
|
|
92
|
|
93
|
|
94 @Override
|
|
95 protected void process(List<String> strings) { // EDT
|
|
96 String message = strings.get(strings.size() - 1); // get last
|
|
97 presenter.showMessage(message);
|
|
98 }
|
|
99
|
|
100 @Override
|
|
101 protected void done() { // EDT
|
|
102 try {
|
|
103 get();
|
|
104 presenter.showMessage("Handshake established");
|
|
105 ClipboardControllerImpl clipboardController =
|
|
106 new ClipboardControllerImpl(workingProtocol, rfbSettings.getRemoteCharsetName());
|
|
107 clipboardController.setEnabled(rfbSettings.isAllowClipboardTransfer());
|
|
108 rfbSettings.addListener(clipboardController);
|
|
109 viewerWindow = viewerWindowFactory.createViewerWindow(
|
|
110 workingProtocol, rfbSettings, uiSettings, connectionString, presenter);
|
|
111
|
|
112 workingProtocol.startNormalHandling(this, viewerWindow.getSurface(), clipboardController);
|
|
113 presenter.showMessage("Started");
|
|
114
|
|
115 presenter.successfulRfbConnection();
|
|
116 } catch (CancellationException e) {
|
|
117 logger.info("Cancelled");
|
|
118 presenter.showMessage("Cancelled");
|
|
119 presenter.connectionCancelled();
|
|
120 } catch (InterruptedException e) {
|
|
121 logger.info("Interrupted");
|
|
122 presenter.showMessage("Interrupted");
|
|
123 presenter.connectionFailed();
|
|
124 } catch (ExecutionException ee) {
|
|
125 String errorTitle;
|
|
126 String errorMessage;
|
|
127 try {
|
|
128 throw ee.getCause();
|
|
129 } catch (UnsupportedProtocolVersionException e) {
|
|
130 errorTitle = "Unsupported Protocol Version";
|
|
131 errorMessage = e.getMessage();
|
|
132 logger.severe(errorMessage);
|
|
133 } catch (UnsupportedSecurityTypeException e) {
|
|
134 errorTitle = "Unsupported Security Type";
|
|
135 errorMessage = e.getMessage();
|
|
136 logger.severe(errorMessage);
|
|
137 } catch (AuthenticationFailedException e) {
|
|
138 errorTitle = "Authentication Failed";
|
|
139 errorMessage = e.getMessage();
|
|
140 logger.severe(errorMessage);
|
|
141 presenter.clearPredefinedPassword();
|
|
142 } catch (TransportException e) {
|
|
143 // if ( ! isAppletStopped) {
|
|
144 errorTitle = "Connection Error";
|
|
145 errorMessage = "Connection Error: " + e.getMessage();
|
|
146 logger.severe(errorMessage);
|
|
147 // }
|
|
148 } catch (IOException e) {
|
|
149 errorTitle = "Connection Error";
|
|
150 errorMessage = "Connection Error: " + e.getMessage();
|
|
151 logger.severe(errorMessage);
|
|
152 } catch (FatalException e) {
|
|
153 errorTitle = "Connection Error";
|
|
154 errorMessage = "Connection Error: " + e.getMessage();
|
|
155 logger.severe(errorMessage);
|
|
156 } catch (Throwable e) {
|
|
157 errorTitle = "Error";
|
|
158 errorMessage = "Error: " + e.getMessage();
|
|
159 logger.severe(errorMessage);
|
|
160 }
|
|
161 presenter.showReconnectDialog(errorTitle, errorMessage);
|
|
162 presenter.clearMessage();
|
|
163 presenter.connectionFailed();
|
|
164 }
|
|
165 }
|
|
166
|
|
167 @Override
|
|
168 public void rfbSessionStopped(final String reason) {
|
|
169 if (workingProtocol != null) {
|
|
170 workingProtocol.cleanUpSession();
|
|
171 }
|
|
172 if (isStoppingProcess) return;
|
|
173 cleanUpUISessionAndConnection();
|
|
174 logger.info("Rfb session stopped: " + reason);
|
|
175 if (presenter.needReconnection()) {
|
|
176 SwingUtilities.invokeLater(new Runnable() {
|
|
177 @Override
|
|
178 public void run() {
|
|
179 presenter.showReconnectDialog("Connection error", reason);
|
|
180 presenter.reconnect(predefinedPassword);
|
|
181 }
|
|
182 });
|
|
183 }
|
|
184 }
|
|
185
|
|
186 @Override
|
|
187 public boolean cancel() {
|
|
188 boolean res = super.cancel(true);
|
|
189 if (res && workingProtocol != null) {
|
|
190 workingProtocol.cleanUpSession();
|
|
191 }
|
|
192 cleanUpUISessionAndConnection();
|
|
193 return res;
|
|
194 }
|
|
195
|
|
196 private synchronized void cleanUpUISessionAndConnection() {
|
|
197 isStoppingProcess = true;
|
|
198 if (workingSocket != null && workingSocket.isConnected()) {
|
|
199 try {
|
|
200 workingSocket.close();
|
|
201 } catch (IOException e) { /*nop*/ }
|
|
202 }
|
|
203 if (viewerWindow != null) {
|
|
204 viewerWindow.close();
|
|
205 }
|
|
206 isStoppingProcess = false;
|
|
207 }
|
|
208
|
|
209 @Override
|
|
210 public void setWorkingSocket(Socket workingSocket) {
|
|
211 this.workingSocket = workingSocket;
|
|
212 }
|
|
213
|
|
214 @Override
|
|
215 public void setRfbSettings(ProtocolSettings rfbSettings) {
|
|
216 this.rfbSettings = rfbSettings;
|
|
217 }
|
|
218
|
|
219 @Override
|
|
220 public void setUiSettings(UiSettings uiSettings) {
|
|
221 this.uiSettings = uiSettings;
|
|
222 }
|
|
223
|
|
224 @Override
|
|
225 public void setConnectionString(String connectionString) {
|
|
226 this.connectionString = connectionString;
|
|
227 }
|
|
228
|
|
229 /**
|
|
230 * Ask user for password if needed
|
|
231 */
|
|
232 private class PasswordChooser implements IPasswordRetriever {
|
|
233 PasswordDialog passwordDialog;
|
|
234 private String connectionString;
|
|
235 private final JFrame owner;
|
|
236 private final ConnectionWorker onCancel;
|
|
237
|
|
238 private PasswordChooser(String connectionString, JFrame parentWindow, ConnectionWorker onCancel) {
|
|
239 this.connectionString = connectionString;
|
|
240 this.owner = parentWindow;
|
|
241 this.onCancel = onCancel;
|
|
242 }
|
|
243
|
|
244 @Override
|
|
245 public String getPassword() {
|
|
246 return Strings.isTrimmedEmpty(predefinedPassword) ?
|
|
247 getPasswordFromGUI() :
|
|
248 predefinedPassword;
|
|
249 }
|
|
250
|
|
251 private String getPasswordFromGUI() {
|
|
252 try {
|
|
253 SwingUtilities.invokeAndWait(new Runnable() {
|
|
254 @Override
|
|
255 public void run() {
|
|
256 if (null == passwordDialog) {
|
|
257 passwordDialog = new PasswordDialog(owner, onCancel);
|
|
258 }
|
|
259 passwordDialog.setServerHostName(connectionString);
|
|
260 passwordDialog.toFront();
|
|
261 passwordDialog.setVisible(true);
|
|
262 }
|
|
263 });
|
|
264 } catch (InterruptedException e) {
|
|
265 //nop
|
|
266 } catch (InvocationTargetException e) {
|
|
267 //nop
|
|
268 }
|
|
269 return passwordDialog.getPassword();
|
|
270 }
|
|
271 }
|
|
272 }
|