aboutsummaryrefslogtreecommitdiffstats
path: root/vncviewer/ConnectingDialog.cxx
diff options
context:
space:
mode:
authorConstantin Kaplinsky <const@tightvnc.com>2006-05-16 08:48:31 +0000
committerConstantin Kaplinsky <const@tightvnc.com>2006-05-16 08:48:31 +0000
commitac30668d41335ff9fb606332888a6ec0df83f3ce (patch)
tree1331ebd2da8e8c091fef9270f8280f82366f5b76 /vncviewer/ConnectingDialog.cxx
parentcbfb59805d3b2317503411ef188e06408365b1b2 (diff)
downloadtigervnc-ac30668d41335ff9fb606332888a6ec0df83f3ce.tar.gz
tigervnc-ac30668d41335ff9fb606332888a6ec0df83f3ce.zip
Win32 vncviewer merged with VNC 4.1.1 code. The merge is incomplete - the code compiles but does not always work properly yet.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/branches/merge-with-vnc-4.1.1@552 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'vncviewer/ConnectingDialog.cxx')
-rw-r--r--vncviewer/ConnectingDialog.cxx160
1 files changed, 160 insertions, 0 deletions
diff --git a/vncviewer/ConnectingDialog.cxx b/vncviewer/ConnectingDialog.cxx
new file mode 100644
index 00000000..60fcb661
--- /dev/null
+++ b/vncviewer/ConnectingDialog.cxx
@@ -0,0 +1,160 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ *
+ * This 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 software 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 software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+// -=- ConnectingDialog.cxx
+
+#include <stdlib.h>
+#include <vncviewer/ConnectingDialog.h>
+#include <vncviewer/resource.h>
+#include <network/TcpSocket.h>
+#include <rfb/Threading.h>
+#include <rfb/Hostname.h>
+#include <map>
+
+using namespace rfb;
+using namespace rfb::win32;
+
+
+// ConnectingDialog callback
+static BOOL CALLBACK ConnectingDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
+ bool* activePtr = (bool*)GetWindowLong(hwnd, GWL_USERDATA);
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ SetWindowLong(hwnd, GWL_USERDATA, lParam);
+ return TRUE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ if (activePtr)
+ *activePtr = false;
+ return TRUE;
+ }
+ break;
+ case WM_DESTROY:
+ if (activePtr)
+ *activePtr = false;
+ return TRUE;
+ }
+ return 0;
+}
+
+
+// Global map, used by ConnectingDialog::Threads to call back to their owning
+// ConnectingDialogs, while coping with the fact that the owner may already have quit.
+static std::map<int, ConnectingDialog*> dialogs;
+static int nextDialogId = 0;
+static Mutex dialogsLock;
+
+
+// ConnectingDialog::Thread
+// Attempts to connect to the specified host. If the connection succeeds, the
+// socket is saved in the owning ConnectingDialog, if still available, and the
+// event is signalled. If the connection fails, the Exception text is returned
+// to the dialog. If the dialog is already gone, the Exception/socket are discarded.
+// NB: This thread class cleans itself up on exit - DO NOT join()!
+class ConnectingDialog::Thread : public rfb::Thread {
+public:
+ Thread(int dialogId_, const char* hostAndPort) : dialogId(dialogId_) {
+ setDeleteAfterRun();
+ getHostAndPort(hostAndPort, &host.buf, &port);
+ }
+ virtual void run() {
+ try {
+ returnSock(new network::TcpSocket(host.buf, port));
+ } catch (rdr::Exception& e) {
+ returnException(e);
+ }
+ }
+ void returnSock(network::Socket* s) {
+ Lock l(dialogsLock);
+ if (dialogs.count(dialogId)) {
+ dialogs[dialogId]->newSocket = s;
+ SetEvent(dialogs[dialogId]->readyEvent);
+ } else {
+ delete s;
+ }
+ }
+ void returnException(const rdr::Exception& e) {
+ Lock l(dialogsLock);
+ if (dialogs.count(dialogId)) {
+ dialogs[dialogId]->errMsg.replaceBuf(strDup(e.str()));
+ SetEvent(dialogs[dialogId]->readyEvent);
+ }
+ };
+ CharArray host;
+ int port;
+ int dialogId;
+};
+
+
+ConnectingDialog::ConnectingDialog() : dialog(0), readyEvent(CreateEvent(0, TRUE, FALSE, 0)),
+ newSocket(0), dialogId(0) {
+}
+
+network::Socket* ConnectingDialog::connect(const char* hostAndPort) {
+ Thread* connectThread = 0;
+ bool active = true;
+ errMsg.replaceBuf(0);
+ newSocket = 0;
+
+ // Get a unique dialog identifier and create the dialog window
+ {
+ Lock l(dialogsLock);
+ dialogId = ++nextDialogId;
+ dialogs[dialogId] = this;
+ dialog = CreateDialogParam(GetModuleHandle(0),
+ MAKEINTRESOURCE(IDD_CONNECTING_DLG), 0, &ConnectingDlgProc, (long)&active);
+ ShowWindow(dialog, SW_SHOW);
+ ResetEvent(readyEvent);
+ }
+
+ // Create and start the connection thread
+ try {
+ connectThread = new Thread(dialogId, hostAndPort);
+ connectThread->start();
+ } catch (rdr::Exception& e) {
+ errMsg.replaceBuf(strDup(e.str()));
+ active = false;
+ }
+
+ // Process window messages until the connection thread signals readyEvent, or the dialog is cancelled
+ while (active && (MsgWaitForMultipleObjects(1, &readyEvent.h, FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)) {
+ MSG msg;
+ while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
+ DispatchMessage(&msg);
+ }
+
+ // Remove this dialog from the table
+ // NB: If the dialog was cancelled then the thread is still running, and will only
+ // discover that we're gone when it looks up our unique Id in the dialog table.
+ {
+ Lock l(dialogsLock);
+ dialogs.erase(dialogId);
+ }
+
+ // Close the dialog window
+ DestroyWindow(dialog); dialog=0;
+
+ // Throw the exception, if there was one
+ if (errMsg.buf)
+ throw rdr::Exception(errMsg.buf);
+
+ // Otherwise, return the socket
+ // NB: The socket will be null if the dialog was cancelled
+ return newSocket;
+}