Uploaded image for project: 'Guacamole'
  1. Guacamole
  2. GUACAMOLE-484

UPSTREAM_UNAVAILABLE incorrectly reported for sessions closed by RDP server

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Minor
    • Resolution: Fixed
    • 0.9.13-incubating
    • 1.0.0
    • RDP
    • None

    Description

      I originally posted about this at http://apache-guacamole-general-user-mailing-list.2363388.n4.nabble.com/Need-guidance-with-suspected-auto-reconnect-bug-td2118.html and then replied later to another thread at http://apache-guacamole-general-user-mailing-list.2363388.n4.nabble.com/Error-message-when-disconnecting-a-Windows-Server-2012-td1835.html#a2129 stating that Frode Langelo's patch fixed my issue as well. Opening bug report per Nick Couchman's request and copy/pasting from these referenced threads below.

      I have a single connection to an RDP server. The server is set up to only allow one connection per user, so when I leave one guacamole session connected, and start up another one (e.g., open A in chrome and B in an incognito window), the session detaches from A and attaches to B.

      This (erroneously) triggers the 15 second auto-reconnect countdown in A. Once it reconnects, B is disconnected and starts the 15 second countdown. It ping-pongs back and forth.

      Running "guacd -L debug -f" I see this:

      ERRINFO_DISCONNECTED_BY_OTHER_CONNECTION (0x00000005):
      Another user connected to the server, forcing the disconnection of the current connection.
      guacd[9344]: ERROR:     Error handling RDP file descriptors
      

      Lines 1 and 2 actually come from libfreerdp, and indicate that the error code coming from RDP is 0x5. Looking at guacd: src/protocols/rdp/error.c
       

              /* Another user logged on, disconnecting this user */
              case 0x5: /* ERRINFO_DISCONNECTED_BY_OTHER_CONNECTION */
                  status = GUAC_PROTOCOL_STATUS_SESSION_CONFLICT;
                  message = "Disconnected by other connection.";
                  break;
      

      So a 0x5 return from RDP should translate to  GUAC_PROTOCOL_STATUS_SESSION_CONFLICT (0x209) being sent to the client.

      Looking at the client, in guacamole/target/guacamole-0.9.13-incubating/guacamole.js:

          /**
           * All error codes for which automatic reconnection is appropriate when a
           * client error occurs.
           */
          var CLIENT_AUTO_RECONNECT = {
              0x0200: true,
              0x0202: true,
              0x0203: true,
              0x0207: true,
              0x0208: true,
              0x0301: true,
              0x0308: true
          };
      

      0x0209 isn't in the list that should auto-reconnect. So I added this in guacamole.js:

      console.log('status = ' + status.toString(16).toUpperCase());
      

      In the session B console in Chrome, when the reconnect in session A, for example, disconnects session B, I see this:

      status = 208
      

      That's not 209, but it IS in the auto-reconnect list.

      So I started tracking down why libfreerdp sends 0x5 to guacd, which should send 0x209 to the client, but instead is sending 0x208. Here's what I found (the clue was line 3 above in the guacd debug output:

        
      guacd[9344]: ERROR:     Error handling RDP file descriptors
      

      In function guac_rdp_handle_connection:

                      /* Check the libfreerdp fds */
                      if (!freerdp_check_fds(rdp_inst)) {
                          guac_client_abort(client,
                                  GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE,
                                  "Error handling RDP file descriptors");
                          pthread_mutex_unlock(&(rdp_client->rdp_lock));
                          return 1;
                      }
      

      and lower down:

                      /* Handle RDP disconnect */
                      if (freerdp_shall_disconnect(rdp_inst)) {
                          guac_rdp_client_abort(client);
                          pthread_mutex_unlock(&(rdp_client->rdp_lock));
                          return 1;
                      }
      

      The first bit is returning GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE, which is 0x208, to the client and returning. This means guac_rdp_client_abort, which maps the RDP error codes to GUAC_PROTOCOL_STATUS*, is never reached. I poked it a bit and realized I was in over my head. I'd need to understand more about freerdp_check_fds and freerdp_shall_disconnect before I could decide how to rework it.

      I am not sure what all error conditions from RDP will trigger the first bit and return before guac_rdp_client_abort is called, but I am guessing that more than 0x5 is getting short circuited and arriving at the client as a 0x208.

      Excerpt from mailing list with Frode's patch:

      I am seeing the same behavior as Kevin; Windows 2008 does not give this error, while both 2012 and 2016 do. I found the easiest way to reproduce this is to connect to the box but not do anything in the Windows logon screen. The RDP server will disconnect the session and the referenced error is produced. The freerdp version I am using is 1.1.0~git20140921.

      Kevin; try adding this to src/protocols/rdp/rdp.c for remedy:

      diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c
      index 0b15d055..d35c663c 100644
      --- a/src/protocols/rdp/rdp.c
      +++ b/src/protocols/rdp/rdp.c
      @@ -764,9 +764,16 @@ static int
      guac_rdp_handle_connection(guac_client* client) {
      
                       /* Check the libfreerdp fds */
                       if (!freerdp_check_fds(rdp_inst)) {
      -                    guac_client_abort(client,
      -                            GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE,
      -                            "Error handling RDP file descriptors");
      +                    /* Handle RDP disconnect */
      +                    if (freerdp_shall_disconnect(rdp_inst)) {
      +                        guac_rdp_client_abort(client);
      +                    }
      +                    /* Handle FD error */
      +                    else {
      +                        guac_client_abort(client,
      +                                GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE,
      +                                "Error handling RDP file descriptors");
      +                    }
                           pthread_mutex_unlock(&(rdp_client->rdp_lock));
                           return 1;
                       }
      

      Kind regards,
      Frode

      Attachments

        Issue Links

          Activity

            People

              mjumper Mike Jumper
              jhankins Jonathan Hankins
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: