]> source.dussan.org Git - tigervnc.git/commitdiff
Retry connection in case of an error
authorJohannes <bensky@arcor.de>
Sat, 30 Jan 2021 23:12:50 +0000 (00:12 +0100)
committerPierre Ossman <ossman@cendio.se>
Fri, 23 Jul 2021 09:53:01 +0000 (11:53 +0200)
vncviewer/CConn.cxx
vncviewer/DesktopWindow.cxx
vncviewer/Viewport.cxx
vncviewer/parameters.cxx
vncviewer/parameters.h
vncviewer/touch.cxx
vncviewer/vncviewer.cxx
vncviewer/vncviewer.h
vncviewer/vncviewer.man

index e1f5f70a277b5b981e0d0e2a2b03d43b9b1f95f7..ebdfbe87bba3e18aa862db4a355fbc474d46dd52 100644 (file)
@@ -111,8 +111,8 @@ CConn::CConn(const char* vncServerName, network::Socket* socket=NULL)
       }
     } catch (rdr::Exception& e) {
       vlog.error("%s", e.str());
-      exit_vncviewer(_("Failed to connect to \"%s\":\n\n%s"),
-                     vncServerName, e.str());
+      abort_connection(_("Failed to connect to \"%s\":\n\n%s"),
+                       vncServerName, e.str());
       return;
     }
   }
@@ -259,7 +259,7 @@ void CConn::socketEvent(FL_SOCKET fd, void *data)
        Timer::checkTimeouts();
 
        // Also check if we need to stop reading and terminate
-       if (should_exit())
+       if (should_disconnect())
          break;
     }
 
@@ -270,14 +270,14 @@ void CConn::socketEvent(FL_SOCKET fd, void *data)
     if (!cc->desktop) {
       vlog.error(_("The connection was dropped by the server before "
                    "the session could be established."));
-      exit_vncviewer(_("The connection was dropped by the server "
+      abort_connection(_("The connection was dropped by the server "
                        "before the session could be established."));
     } else {
-      exit_vncviewer();
+      disconnect();
     }
   } catch (rdr::Exception& e) {
     vlog.error("%s", e.str());
-    exit_vncviewer(_("An unexpected error occurred when communicating "
+    abort_connection(_("An unexpected error occurred when communicating "
                      "with the server:\n\n%s"), e.str());
   }
 
index 3b4589c9a62ea746226886786b45acb2748628ef..7936deb7fbc733ac577a1b1829780f6d70c9406f 100644 (file)
@@ -1393,7 +1393,7 @@ void DesktopWindow::repositionWidgets()
 
 void DesktopWindow::handleClose(Fl_Widget *wnd, void *data)
 {
-  exit_vncviewer();
+  disconnect();
 }
 
 
index 56bcc3140279425d7fa679214a7a6d2f7ace8261..2f8a92c6112f2b09b93a6d868f586d12f4fb0a7d 100644 (file)
@@ -103,7 +103,7 @@ static rfb::LogWriter vlog("Viewport");
 
 // Menu constants
 
-enum { ID_EXIT, ID_FULLSCREEN, ID_MINIMIZE, ID_RESIZE,
+enum { ID_DISCONNECT, ID_FULLSCREEN, ID_MINIMIZE, ID_RESIZE,
        ID_CTRL, ID_ALT, ID_MENUKEY, ID_CTRLALTDEL,
        ID_REFRESH, ID_OPTIONS, ID_INFO, ID_ABOUT };
 
@@ -572,8 +572,9 @@ int Viewport::handle(int event)
       cc->sendClipboardData(filtered);
     } catch (rdr::Exception& e) {
       vlog.error("%s", e.str());
-      exit_vncviewer(_("An unexpected error occurred when communicating "
-                       "with the server:\n\n%s"), e.str());
+      abort_connection(_("An unexpected error occurred when "
+                         "communicating with the server:\n\n%s"),
+                       e.str());
     }
 
     strFree(filtered);
@@ -669,8 +670,9 @@ void Viewport::sendPointerEvent(const rfb::Point& pos, int buttonMask)
       cc->writer()->writePointerEvent(pos, buttonMask);
     } catch (rdr::Exception& e) {
       vlog.error("%s", e.str());
-      exit_vncviewer(_("An unexpected error occurred when communicating "
-                       "with the server:\n\n%s"), e.str());
+      abort_connection(_("An unexpected error occurred when "
+                         "communicating with the server:\n\n%s"),
+                       e.str());
     }
   } else {
     if (!Fl::has_timeout(handlePointerTimeout, this))
@@ -771,8 +773,9 @@ void Viewport::handleClipboardChange(int source, void *data)
     self->cc->announceClipboard(true);
   } catch (rdr::Exception& e) {
     vlog.error("%s", e.str());
-    exit_vncviewer(_("An unexpected error occurred when communicating "
-                     "with the server:\n\n%s"), e.str());
+    abort_connection(_("An unexpected error occurred when "
+                       "communicating with the server:\n\n%s"),
+                     e.str());
   }
 }
 
@@ -785,8 +788,9 @@ void Viewport::flushPendingClipboard()
       cc->requestClipboard();
     } catch (rdr::Exception& e) {
       vlog.error("%s", e.str());
-      exit_vncviewer(_("An unexpected error occurred when communicating "
-                       "with the server:\n\n%s"), e.str());
+      abort_connection(_("An unexpected error occurred when "
+                         "communicating with the server:\n\n%s"),
+                       e.str());
     }
   }
   if (pendingClientClipboard) {
@@ -795,8 +799,9 @@ void Viewport::flushPendingClipboard()
       cc->announceClipboard(true);
     } catch (rdr::Exception& e) {
       vlog.error("%s", e.str());
-      exit_vncviewer(_("An unexpected error occurred when communicating "
-                       "with the server:\n\n%s"), e.str());
+      abort_connection(_("An unexpected error occurred when "
+                         "communicating with the server:\n\n%s"),
+                       e.str());
     }
   }
 
@@ -822,8 +827,9 @@ void Viewport::handlePointerTimeout(void *data)
                                           self->lastButtonMask);
   } catch (rdr::Exception& e) {
     vlog.error("%s", e.str());
-    exit_vncviewer(_("An unexpected error occurred when communicating "
-                     "with the server:\n\n%s"), e.str());
+    abort_connection(_("An unexpected error occurred when "
+                       "communicating with the server:\n\n%s"),
+                     e.str());
   }
 }
 
@@ -892,8 +898,9 @@ void Viewport::handleKeyPress(int keyCode, rdr::U32 keySym)
       cc->writer()->writeKeyEvent(keySym, keyCode, true);
   } catch (rdr::Exception& e) {
     vlog.error("%s", e.str());
-    exit_vncviewer(_("An unexpected error occurred when communicating "
-                     "with the server:\n\n%s"), e.str());
+    abort_connection(_("An unexpected error occurred when "
+                       "communicating with the server:\n\n%s"),
+                     e.str());
   }
 }
 
@@ -927,8 +934,9 @@ void Viewport::handleKeyRelease(int keyCode)
       cc->writer()->writeKeyEvent(iter->second, keyCode, false);
   } catch (rdr::Exception& e) {
     vlog.error("%s", e.str());
-    exit_vncviewer(_("An unexpected error occurred when communicating "
-                     "with the server:\n\n%s"), e.str());
+    abort_connection(_("An unexpected error occurred when "
+                       "communicating with the server:\n\n%s"),
+                     e.str());
   }
 
   downKeySym.erase(iter);
@@ -1239,8 +1247,8 @@ void Viewport::initContextMenu()
 {
   contextMenu->clear();
 
-  fltk_menu_add(contextMenu, p_("ContextMenu|", "E&xit viewer"),
-                0, NULL, (void*)ID_EXIT, FL_MENU_DIVIDER);
+  fltk_menu_add(contextMenu, p_("ContextMenu|", "Dis&connect"),
+                0, NULL, (void*)ID_DISCONNECT, FL_MENU_DIVIDER);
 
   fltk_menu_add(contextMenu, p_("ContextMenu|", "&Full screen"),
                 0, NULL, (void*)ID_FULLSCREEN,
@@ -1314,8 +1322,8 @@ void Viewport::popupContextMenu()
     return;
 
   switch (m->argument()) {
-  case ID_EXIT:
-    exit_vncviewer();
+  case ID_DISCONNECT:
+    disconnect();
     break;
   case ID_FULLSCREEN:
     if (window()->fullscreen_active())
index 46ad132f119075c3a86e8cda1edc512b22fe1bf1..c589a2f09c4d23e8a5a2a957409d17dd81cfa5fb 100644 (file)
@@ -69,6 +69,10 @@ BoolParameter alertOnFatalError("AlertOnFatalError",
                                 "Give a dialog on connection problems rather "
                                 "than exiting immediately", true);
 
+BoolParameter reconnectOnError("ReconnectOnError",
+                               "Give a dialog on connection problems rather "
+                               "than exiting immediately and ask for a reconnect.", true);
+
 StringParameter passwordFile("PasswordFile",
                              "Password file for VNC authentication", "");
 AliasParameter passwd("passwd", "Alias for PasswordFile", &passwordFile);
index 614e577f24b41dde3546b4450f4cbd73b0fd853e..1dd9aca2e3b687ffcd0da4f6692ecbe82d049dc9 100644 (file)
@@ -74,6 +74,7 @@ extern rfb::StringParameter menuKey;
 
 extern rfb::BoolParameter fullscreenSystemKeys;
 extern rfb::BoolParameter alertOnFatalError;
+extern rfb::BoolParameter reconnectOnError;
 
 #ifndef WIN32
 extern rfb::StringParameter via;
index 3d23aa58d6d0b20ec6874539cd4e2eb548a9fa34..5ba9d1086009ccc8655ccc593d6817c025647469 100644 (file)
@@ -181,7 +181,7 @@ static int handleTouchEvent(void *event, void *data)
       handlers[msg->hwnd] = new Win32TouchHandler(msg->hwnd);
     } catch (rfb::Exception& e) {
       vlog.error(_("Failed to create touch handler: %s"), e.str());
-      exit_vncviewer(_("Failed to create touch handler: %s"), e.str());
+      abort_vncviewer(_("Failed to create touch handler: %s"), e.str());
     }
     // Add a special hook-in for handling events sent directly to WndProc
     if (!SetWindowSubclass(msg->hwnd, &win32WindowProc, 1, 0)) {
@@ -248,14 +248,14 @@ void enable_touch()
   fl_open_display();
 
   if (!XQueryExtension(fl_display, "XInputExtension", &xi_major, &ev, &err)) {
-    exit_vncviewer(_("X Input extension not available."));
+    abort_vncviewer(_("X Input extension not available."));
     return; // Not reached
   }
 
   major_ver = 2;
   minor_ver = 2;
   if (XIQueryVersion(fl_display, &major_ver, &minor_ver) != Success) {
-    exit_vncviewer(_("X Input 2 (or newer) is not available."));
+    abort_vncviewer(_("X Input 2 (or newer) is not available."));
     return; // Not reached
   }
 
index c93a6f7553ee8903ff0187645111903cc9f5a592..1092f1f46ad079e039b4591525d5e13a7b132391 100644 (file)
@@ -22,6 +22,7 @@
 #include <config.h>
 #endif
 
+#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 #include <ctype.h>
@@ -87,7 +88,8 @@ static const char *argv0 = NULL;
 
 static bool inMainloop = false;
 static bool exitMainloop = false;
-static const char *exitError = NULL;
+static char *exitError = NULL;
+static bool fatalError = false;
 
 static const char *about_text()
 {
@@ -107,17 +109,19 @@ static const char *about_text()
   return buffer;
 }
 
-void exit_vncviewer(const char *error, ...)
+
+void abort_vncviewer(const char *error, ...)
 {
+  fatalError = true;
+
   // Prioritise the first error we get as that is probably the most
   // relevant one.
-  if ((error != NULL) && (exitError == NULL)) {
+  if (exitError == NULL) {
     va_list ap;
 
     va_start(ap, error);
     exitError = (char*)malloc(1024);
-    if (exitError)
-      (void) vsnprintf((char*)exitError, 1024, error, ap);
+    vsnprintf(exitError, 1024, error, ap);
     va_end(ap);
   }
 
@@ -131,7 +135,30 @@ void exit_vncviewer(const char *error, ...)
   }
 }
 
-bool should_exit()
+void abort_connection(const char *error, ...)
+{
+  assert(inMainloop);
+
+  // Prioritise the first error we get as that is probably the most
+  // relevant one.
+  if (exitError == NULL) {
+    va_list ap;
+
+    va_start(ap, error);
+    exitError = (char*)malloc(1024);
+    vsnprintf(exitError, 1024, error, ap);
+    va_end(ap);
+  }
+
+  exitMainloop = true;
+}
+
+void disconnect()
+{
+  exitMainloop = true;
+}
+
+bool should_disconnect()
 {
   return exitMainloop;
 }
@@ -142,17 +169,57 @@ void about_vncviewer()
   fl_message("%s", about_text());
 }
 
-void run_mainloop()
+static void mainloop(const char* vncserver, network::Socket* sock)
 {
-  int next_timer;
+  while (true) {
+    CConn *cc;
 
-  next_timer = Timer::checkTimeouts();
-  if (next_timer == 0)
-    next_timer = INT_MAX;
+    exitMainloop = false;
 
-  if (Fl::wait((double)next_timer / 1000.0) < 0.0) {
-    vlog.error(_("Internal FLTK error. Exiting."));
-    exit(-1);
+    cc = new CConn(vncServerName, sock);
+
+    while (!exitMainloop) {
+      int next_timer;
+
+      next_timer = Timer::checkTimeouts();
+      if (next_timer == 0)
+        next_timer = INT_MAX;
+
+      if (Fl::wait((double)next_timer / 1000.0) < 0.0) {
+        vlog.error(_("Internal FLTK error. Exiting."));
+        exit(-1);
+      }
+    }
+
+    delete cc;
+
+    if (fatalError) {
+      assert(exitError != NULL);
+      if (alertOnFatalError)
+        fl_alert("%s", exitError);
+      break;
+    }
+
+    if (exitError == NULL)
+      break;
+
+    if(reconnectOnError && (sock == NULL)) {
+      int ret;
+      ret = fl_choice(_("%s\n\n"
+                        "Attempt to reconnect?"),
+                      fl_yes, fl_no, 0, exitError);
+      free(exitError);
+      exitError = NULL;
+      if (ret == 0)
+        continue;
+      else
+        break;
+    }
+
+    if (alertOnFatalError)
+      fl_alert("%s", exitError);
+
+    break;
   }
 }
 
@@ -429,8 +496,8 @@ potentiallyLoadConfigurationFile(char *vncServerName)
       vncServerName[VNCSERVERNAMELEN-1] = '\0';
     } catch (rfb::Exception& e) {
       vlog.error("%s", e.str());
-      exit_vncviewer(_("Error reading configuration file \"%s\":\n\n%s"),
-                     vncServerName, e.str());
+      abort_vncviewer(_("Error reading configuration file \"%s\":\n\n%s"),
+                      vncServerName, e.str());
     }
   }
 }
@@ -640,7 +707,7 @@ int main(int argc, char** argv)
     // TRANSLATORS: "Parameters" are command line arguments, or settings
     // from a file or the Windows registry.
     vlog.error(_("Parameters -listen and -via are incompatible"));
-    exit_vncviewer(_("Parameters -listen and -via are incompatible"));
+    abort_vncviewer(_("Parameters -listen and -via are incompatible"));
     return 1; /* Not reached */
   }
 #endif
@@ -687,7 +754,7 @@ int main(int argc, char** argv)
       }
     } catch (rdr::Exception& e) {
       vlog.error("%s", e.str());
-      exit_vncviewer(_("Failure waiting for incoming VNC connection:\n\n%s"), e.str());
+      abort_vncviewer(_("Failure waiting for incoming VNC connection:\n\n%s"), e.str());
       return 1; /* Not reached */
     }
 
@@ -708,17 +775,9 @@ int main(int argc, char** argv)
 #endif
   }
 
-  CConn *cc = new CConn(vncServerName, sock);
-
   inMainloop = true;
-  while (!exitMainloop)
-    run_mainloop();
+  mainloop(vncServerName, sock);
   inMainloop = false;
 
-  delete cc;
-
-  if (exitError != NULL && alertOnFatalError)
-    fl_alert("%s", exitError);
-
   return 0;
 }
index 494611b7d6ccca22ab3862e6e9d3c213cfb5fcbb..57eb91fb35244c36465cd8ce569d319bc9f2d88c 100644 (file)
 #  define __printf_attr(a, b)
 #endif // __GNUC__
 
-void exit_vncviewer(const char *error = NULL, ...) __printf_attr(1, 2);
-bool should_exit();
+void abort_vncviewer(const char *error, ...) __printf_attr(1, 2);
+void abort_connection(const char *error, ...) __printf_attr(1, 2);
+void disconnect();
+bool should_disconnect();
+
 void about_vncviewer();
-void run_mainloop();
 
 #endif
index 062bba9bd1840d81f6358672275abff36a2cddfe..894787c0e25df0e809bb4685f893cd91dd73bb4c 100644 (file)
@@ -328,6 +328,12 @@ respectively.
 .TP
 .B \-AlertOnFatalError
 Display a dialog with any fatal error before exiting. Default is on.
+.
+.TP
+.B \-ReconnectOnError
+Display a dialog with any error and offer the possibility to retry
+establishing the connection. In case this is off no dialog to
+re-connect will be offered. Default is on.
 
 .SH FILES
 .TP