VirtualBox

Ignore:
Timestamp:
Dec 11, 2012 5:06:02 PM (12 years ago)
Author:
vboxsync
Message:

VBoxService/VMInfo: Implemented detecting hotdesk sessions through VRDP location awareness.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp

    r44073 r44097  
    7272
    7373
     74/** Structure containing information about a location awarness
     75 *  client provided by the host. */
     76/** @todo Move this (and functions) into VbglR3. */
     77typedef struct VBOXSERVICELACLIENTINFO
     78{
     79    uint32_t    uID;
     80    char       *pszName;
     81    char       *pszLocation;
     82    char       *pszDomain;
     83    bool        fAttached;
     84    uint64_t    uAttachedTS;
     85} VBOXSERVICELACLIENTINFO, *PVBOXSERVICELACLIENTINFO;
     86
     87
    7488/*******************************************************************************
    7589*   Global Variables                                                           *
     
    87101/** The VM session ID. Changes whenever the VM is restored or reset. */
    88102static uint64_t                 g_idVMInfoSession;
     103/** The last attached locartion awareness (LA) client timestamp. */
     104static uint64_t                 g_LAClientAttachedTS = 0;
     105/** The current LA client info. */
     106static VBOXSERVICELACLIENTINFO  g_LAClientInfo;
    89107
    90108
     
    92110*   Defines                                                                    *
    93111*******************************************************************************/
     112static const char *g_pszLAActiveClient = "/VirtualBox/HostInfo/VRDP/ActiveClient";
     113
    94114#ifdef VBOX_WITH_DBUS
    95115/** ConsoleKit defines (taken from 0.4.5). */
     
    153173        g_cMsVMInfoInterval = g_DefaultInterval * 1000;
    154174    if (!g_cMsVMInfoInterval)
    155         g_cMsVMInfoInterval = 10 * 1000;
     175    {
     176        /* Set it to 5s by default for location awareness checks. */
     177        g_cMsVMInfoInterval = 5 * 1000;
     178    }
    156179
    157180    int rc = RTSemEventMultiCreate(&g_hVMInfoEvent);
     
    161184    /* The status code is ignored as this information is not available with VBox < 3.2.10. */
    162185
     186    /* Initialize the LA client object. */
     187    RT_ZERO(g_LAClientInfo);
     188
    163189    rc = VbglR3GuestPropConnect(&g_uVMInfoGuestPropSvcClientID);
    164190    if (RT_SUCCESS(rc))
    165         VBoxServiceVerbose(3, "VMInfo: Property Service Client ID: %#x\n", g_uVMInfoGuestPropSvcClientID);
     191        VBoxServiceVerbose(3, "Property Service Client ID: %#x\n", g_uVMInfoGuestPropSvcClientID);
    166192    else
    167193    {
     
    170196        if (rc == VERR_HGCM_SERVICE_NOT_FOUND) /* Host service is not available. */
    171197        {
    172             VBoxServiceVerbose(0, "VMInfo: Guest property service is not available, disabling the service\n");
     198            VBoxServiceVerbose(0, "Guest property service is not available, disabling the service\n");
    173199            rc = VERR_SERVICE_DISABLED;
    174200        }
    175201        else
    176             VBoxServiceError("VMInfo: Failed to connect to the guest property service! Error: %Rrc\n", rc);
     202            VBoxServiceError("Failed to connect to the guest property service! Error: %Rrc\n", rc);
    177203        RTSemEventMultiDestroy(g_hVMInfoEvent);
    178204        g_hVMInfoEvent = NIL_RTSEMEVENTMULTI;
     
    196222    }
    197223    return rc;
     224}
     225
     226
     227/**
     228 * Retrieves a specifiy client LA property.
     229 *
     230 * @return  IPRT status code.
     231 * @param   uClientID               LA client ID to retrieve property for.
     232 * @param   pszProperty             Property (without path) to retrieve.
     233 * @param   ppszValue               Where to store value of property.
     234 * @param   puTimestamp             Timestamp of property to retrieve. Optional.
     235 */
     236static int vboxServiceGetLAClientValue(uint32_t uClientID, const char *pszProperty,
     237                                       char **ppszValue, uint64_t *puTimestamp)
     238{
     239    AssertReturn(uClientID, VERR_INVALID_PARAMETER);
     240    AssertPtrReturn(pszProperty, VERR_INVALID_POINTER);
     241
     242    int rc;
     243
     244    char pszClientPath[255];
     245    if (RTStrPrintf(pszClientPath, sizeof(pszClientPath),
     246                    "/VirtualBox/HostInfo/VRDP/Client/%RU32/%s", uClientID, pszProperty))
     247    {
     248        rc = VBoxServiceReadHostProp(g_uVMInfoGuestPropSvcClientID, pszClientPath, true /* Read only */,
     249                                     ppszValue, NULL /* Flags */, puTimestamp);
     250    }
     251    else
     252        rc = VERR_NO_MEMORY;
     253
     254    return rc;
     255}
     256
     257
     258/**
     259 * Retrieves LA client information. On success the returned structure will have allocated
     260 * objects which need to be free'd with vboxServiceFreeLAClientInfo.
     261 *
     262 * @return  IPRT status code.
     263 * @param   uClientID               Client ID to retrieve information for.
     264 * @param   pClient                 Pointer where to store the client information.
     265 */
     266static int vboxServiceGetLAClientInfo(uint32_t uClientID, PVBOXSERVICELACLIENTINFO pClient)
     267{
     268    AssertReturn(uClientID, VERR_INVALID_PARAMETER);
     269    AssertPtrReturn(pClient, VERR_INVALID_POINTER);
     270
     271    int rc = vboxServiceGetLAClientValue(uClientID, "Name", &pClient->pszName,
     272                                         NULL /* Timestamp */);
     273    if (RT_SUCCESS(rc))
     274    {
     275        char *pszAttach;
     276        rc = vboxServiceGetLAClientValue(uClientID, "Attach", &pszAttach,
     277                                         &pClient->uAttachedTS);
     278        if (RT_SUCCESS(rc))
     279        {
     280            AssertPtr(pszAttach);
     281            pClient->fAttached = !RTStrICmp(pszAttach, "1") ? true : false;
     282
     283            RTStrFree(pszAttach);
     284        }
     285    }
     286    if (RT_SUCCESS(rc))
     287        rc = vboxServiceGetLAClientValue(uClientID, "Location", &pClient->pszLocation,
     288                                         NULL /* Timestamp */);
     289    if (RT_SUCCESS(rc))
     290        rc = vboxServiceGetLAClientValue(uClientID, "Domain", &pClient->pszDomain,
     291                                         NULL /* Timestamp */);
     292    if (RT_SUCCESS(rc))
     293        pClient->uID = uClientID;
     294
     295    return rc;
     296}
     297
     298
     299/**
     300 * Frees all allocated LA client information of a structure.
     301 *
     302 * @param   pClient                 Pointer to client information structure to free.
     303 */
     304static void vboxServiceFreeLAClientInfo(PVBOXSERVICELACLIENTINFO pClient)
     305{
     306    if (pClient)
     307    {
     308        if (pClient->pszName)
     309            RTStrFree(pClient->pszName);
     310        if (pClient->pszLocation)
     311            RTStrFree(pClient->pszLocation);
     312        if (pClient->pszDomain)
     313            RTStrFree(pClient->pszDomain);
     314
     315        pClient = NULL;
     316    }
    198317}
    199318
     
    433552                        }
    434553
    435                         VBoxServiceVerbose(4, "ConsoleKit: session '%s' is %s\n", 
     554                        VBoxServiceVerbose(4, "ConsoleKit: session '%s' is %s\n",
    436555                                           *ppszCurSession, fActive ? "active" : "not active");
    437556
     
    613732    if (RT_FAILURE(rc))
    614733    {
    615         VBoxServiceError("VMInfo: Error writing logged on users list, rc=%Rrc\n", rc);
     734        VBoxServiceError("Error writing logged on users list, rc=%Rrc\n", rc);
    616735        cUsersInList = 0; /* Reset user count on error. */
    617736    }
     
    620739    if (RT_FAILURE(rc))
    621740    {
    622         VBoxServiceError("VMInfo: Error writing logged on users count, rc=%Rrc\n", rc);
     741        VBoxServiceError("Error writing logged on users count, rc=%Rrc\n", rc);
    623742        cUsersInList = 0; /* Reset user count on error. */
    624743    }
     
    629748                                        cUsersInList == 0 ? "true" : "false");
    630749        if (RT_FAILURE(rc))
    631             VBoxServiceError("VMInfo: Error writing no logged in users beacon, rc=%Rrc\n", rc);
     750            VBoxServiceError("Error writing no logged in users beacon, rc=%Rrc\n", rc);
    632751        g_cVMInfoLoggedInUsers = cUsersInList;
    633752    }
     
    10661185            break;
    10671186
     1187        /* Whether to wait for event semaphore or not. */
     1188        bool fWait = true;
     1189
     1190        /* Check for location awareness. This most likely only
     1191         * works with VBox (latest) 4.1 and up. */
     1192
     1193        /* Check for new connection. */
     1194        char *pszLAClientID;
     1195        int rc2 = VBoxServiceReadHostProp(g_uVMInfoGuestPropSvcClientID, g_pszLAActiveClient, true /* Read only */,
     1196                                          &pszLAClientID, NULL /* Flags */, NULL /* Timestamp */);
     1197        if (RT_SUCCESS(rc2))
     1198        {
     1199            if (RTStrICmp(pszLAClientID, "0")) /* Is a client connected? */
     1200            {
     1201                uint32_t uLAClientID = RTStrToInt32(pszLAClientID);
     1202                uint64_t uLAClientAttachedTS;
     1203
     1204                /* Peek at "Attach" value to figure out if hotdesking happened. */
     1205                char *pszAttach = NULL;
     1206                rc2 = vboxServiceGetLAClientValue(uLAClientID, "Attach", &pszAttach,
     1207                                                 &uLAClientAttachedTS);
     1208
     1209                if (   RT_SUCCESS(rc2)
     1210                    && (   !g_LAClientAttachedTS
     1211                        || (g_LAClientAttachedTS != uLAClientAttachedTS)))
     1212                {
     1213                    vboxServiceFreeLAClientInfo(&g_LAClientInfo);
     1214
     1215                    /* Note: There is a race between setting the guest properties by the host and getting them by
     1216                     *       the guest. */
     1217                    rc2 = vboxServiceGetLAClientInfo(uLAClientID, &g_LAClientInfo);
     1218                    if (RT_SUCCESS(rc2))
     1219                    {
     1220                        VBoxServiceVerbose(1, "VRDP: Hotdesk client %s with ID=%RU32, Name=%s, Domain=%s\n",
     1221                                           /* If g_LAClientAttachedTS is 0 this means there already was an active
     1222                                            * hotdesk session when VBoxService started. */
     1223                                           !g_LAClientAttachedTS ? "already active" : g_LAClientInfo.fAttached ? "connected" : "disconnected",
     1224                                           uLAClientID, g_LAClientInfo.pszName, g_LAClientInfo.pszDomain);
     1225
     1226                        g_LAClientAttachedTS = g_LAClientInfo.uAttachedTS;
     1227
     1228                        /* Don't wait for event semaphore below anymore because we now know that the client
     1229                         * changed. This means we need to iterate all VM information again immediately. */
     1230                        fWait = false;
     1231                    }
     1232                    else
     1233                    {
     1234                        static int s_iBitchedAboutLAClientInfo = 0;
     1235                        if (s_iBitchedAboutLAClientInfo++ < 10)
     1236                            VBoxServiceError("Error getting active location awareness client info, rc=%Rrc\n", rc2);
     1237                    }
     1238                }
     1239                else if (RT_FAILURE(rc2))
     1240                     VBoxServiceError("Error getting attached value of location awareness client %RU32, rc=%Rrc\n",
     1241                                      uLAClientID, rc2);
     1242                if (pszAttach)
     1243                    RTStrFree(pszAttach);
     1244            }
     1245            else
     1246            {
     1247                VBoxServiceVerbose(1, "VRDP: UTTSC disconnected from VRDP server\n");
     1248                vboxServiceFreeLAClientInfo(&g_LAClientInfo);
     1249            }
     1250
     1251            RTStrFree(pszLAClientID);
     1252        }
     1253        else
     1254        {
     1255            static int s_iBitchedAboutLAClient = 0;
     1256            if (   (rc2 != VERR_NOT_FOUND) /* No location awareness installed, skip. */
     1257                && s_iBitchedAboutLAClient++ < 3)
     1258                VBoxServiceError("VRDP: Querying connected location awareness client failed with rc=%Rrc\n", rc2);
     1259        }
     1260
    10681261        /*
    10691262         * Flush all properties if we were restored.
     
    10731266        if (idNewSession != g_idVMInfoSession)
    10741267        {
    1075             VBoxServiceVerbose(3, "VMInfo: The VM session ID changed, flushing all properties\n");
     1268            VBoxServiceVerbose(3, "The VM session ID changed, flushing all properties\n");
    10761269            vboxserviceVMInfoWriteFixedProperties();
    10771270            VBoxServicePropCacheFlush(&g_VMInfoPropCache);
     
    10871280        if (*pfShutdown)
    10881281            break;
    1089         int rc2 = RTSemEventMultiWait(g_hVMInfoEvent, g_cMsVMInfoInterval);
     1282        if (fWait)
     1283            rc2 = RTSemEventMultiWait(g_hVMInfoEvent, g_cMsVMInfoInterval);
    10901284        if (*pfShutdown)
    10911285            break;
    10921286        if (rc2 != VERR_TIMEOUT && RT_FAILURE(rc2))
    10931287        {
    1094             VBoxServiceError("VMInfo: RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
     1288            VBoxServiceError("RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
    10951289            rc = rc2;
    10961290            break;
     
    11011295            rc2 = RTSemEventMultiReset(g_hVMInfoEvent);
    11021296            if (RT_FAILURE(rc2))
    1103                 rc2 = VBoxServiceError("VMInfo: RTSemEventMultiReset failed; rc2=%Rrc\n", rc2);
     1297                rc2 = VBoxServiceError("RTSemEventMultiReset failed; rc2=%Rrc\n", rc2);
    11041298        }
    11051299    }
     
    11401334        int rc = VbglR3GuestPropDelSet(g_uVMInfoGuestPropSvcClientID, &apszPat[0], RT_ELEMENTS(apszPat));
    11411335
     1336        /* Destroy LA client info. */
     1337        vboxServiceFreeLAClientInfo(&g_LAClientInfo);
     1338
    11421339        /* Destroy property cache. */
    11431340        VBoxServicePropCacheDestroy(&g_VMInfoPropCache);
     
    11461343        rc = VbglR3GuestPropDisconnect(g_uVMInfoGuestPropSvcClientID);
    11471344        if (RT_FAILURE(rc))
    1148             VBoxServiceError("VMInfo: Failed to disconnect from guest property service! Error: %Rrc\n", rc);
     1345            VBoxServiceError("Failed to disconnect from guest property service! Error: %Rrc\n", rc);
    11491346        g_uVMInfoGuestPropSvcClientID = 0;
    11501347
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette