VirtualBox

Ignore:
Timestamp:
Jan 27, 2021 5:11:25 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
142470
Message:

Shared Clipboard/Transfers: More code for HTTP transfers. bugref:9437

Location:
trunk/src/VBox/GuestHost/SharedClipboard
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp

    r82968 r87452  
    352352    LogRel2(("Shared Clipboard: Calculating transfer ...\n"));
    353353
    354     int rc = ShClTransferOpen(pTransfer);
     354    PSHCLROOTLIST pRootList;
     355    rc = ShClTransferRootsGet(pTransfer, &pRootList);
    355356    if (RT_SUCCESS(rc))
    356357    {
    357         PSHCLROOTLIST pRootList;
    358         rc = ShClTransferRootsGet(pTransfer, &pRootList);
    359         if (RT_SUCCESS(rc))
    360         {
    361             LogFlowFunc(("cRoots=%RU32\n\n", pRootList->Hdr.cRoots));
    362 
    363             for (uint32_t i = 0; i < pRootList->Hdr.cRoots; i++)
     358        LogFlowFunc(("cRoots=%RU32\n\n", pRootList->Hdr.cRoots));
     359
     360        for (uint32_t i = 0; i < pRootList->Hdr.cRoots; i++)
     361        {
     362            PSHCLLISTENTRY pRootEntry = &pRootList->paEntries[i];
     363            AssertPtr(pRootEntry);
     364
     365            Assert(pRootEntry->cbInfo == sizeof(SHCLFSOBJINFO));
     366            PSHCLFSOBJINFO pFsObjInfo = (PSHCLFSOBJINFO)pRootEntry->pvInfo;
     367
     368            LogFlowFunc(("pszRoot=%s, fMode=0x%x\n", pRootEntry->pszName, pFsObjInfo->Attr.fMode));
     369
     370            if (RTFS_IS_DIRECTORY(pFsObjInfo->Attr.fMode))
    364371            {
    365                 PSHCLLISTENTRY pRootEntry = &pRootList->paEntries[i];
    366                 AssertPtr(pRootEntry);
    367 
    368                 Assert(pRootEntry->cbInfo == sizeof(SHCLFSOBJINFO));
    369                 PSHCLFSOBJINFO pFsObjInfo = (PSHCLFSOBJINFO)pRootEntry->pvInfo;
    370 
    371                 LogFlowFunc(("pszRoot=%s, fMode=0x%x\n", pRootEntry->pszName, pFsObjInfo->Attr.fMode));
    372 
    373                 if (RTFS_IS_DIRECTORY(pFsObjInfo->Attr.fMode))
     372                FSOBJENTRY objEntry = { pRootEntry->pszName, *pFsObjInfo };
     373
     374                pThis->m_lstEntries.push_back(objEntry); /** @todo Can this throw? */
     375
     376                rc = pThis->readDir(pTransfer, pRootEntry->pszName);
     377            }
     378            else if (RTFS_IS_FILE(pFsObjInfo->Attr.fMode))
     379            {
     380                FSOBJENTRY objEntry = { pRootEntry->pszName, *pFsObjInfo };
     381
     382                pThis->m_lstEntries.push_back(objEntry); /** @todo Can this throw? */
     383            }
     384            else
     385                rc = VERR_NOT_SUPPORTED;
     386
     387            if (ASMAtomicReadBool(&pTransfer->Thread.fStop))
     388            {
     389                LogRel2(("Shared Clipboard: Stopping transfer calculation ...\n"));
     390                break;
     391            }
     392
     393            if (RT_FAILURE(rc))
     394                break;
     395        }
     396
     397        ShClTransferRootListFree(pRootList);
     398        pRootList = NULL;
     399
     400        if (   RT_SUCCESS(rc)
     401            && !ASMAtomicReadBool(&pTransfer->Thread.fStop))
     402        {
     403            LogRel2(("Shared Clipboard: Transfer calculation complete (%zu root entries)\n", pThis->m_lstEntries.size()));
     404
     405            /*
     406             * Signal the "list complete" event so that this data object can return (valid) data via ::GetData().
     407             * This in turn then will create IStream instances (by the OS) for each file system object to handle.
     408             */
     409            int rc2 = RTSemEventSignal(pThis->m_EventListComplete);
     410            AssertRC(rc2);
     411
     412            if (pThis->m_lstEntries.size())
     413            {
     414                LogRel2(("Shared Clipboard: Waiting for transfer to complete ...\n"));
     415
     416                LogFlowFunc(("Waiting for transfer to complete ...\n"));
     417
     418                /* Transferring stuff can take a while, so don't use any timeout here. */
     419                rc2 = RTSemEventWait(pThis->m_EventTransferComplete, RT_INDEFINITE_WAIT);
     420                AssertRC(rc2);
     421
     422                switch (pThis->m_enmStatus)
    374423                {
    375                     FSOBJENTRY objEntry = { pRootEntry->pszName, *pFsObjInfo };
    376 
    377                     pThis->m_lstEntries.push_back(objEntry); /** @todo Can this throw? */
    378 
    379                     rc = pThis->readDir(pTransfer, pRootEntry->pszName);
     424                    case Completed:
     425                        LogRel2(("Shared Clipboard: Transfer complete\n"));
     426                        break;
     427
     428                    case Canceled:
     429                        LogRel2(("Shared Clipboard: Transfer canceled\n"));
     430                        break;
     431
     432                    case Error:
     433                        LogRel2(("Shared Clipboard: Transfer error occurred\n"));
     434                        break;
     435
     436                    default:
     437                        break;
    380438                }
    381                 else if (RTFS_IS_FILE(pFsObjInfo->Attr.fMode))
    382                 {
    383                     FSOBJENTRY objEntry = { pRootEntry->pszName, *pFsObjInfo };
    384 
    385                     pThis->m_lstEntries.push_back(objEntry); /** @todo Can this throw? */
    386                 }
    387                 else
    388                     rc = VERR_NOT_SUPPORTED;
    389 
    390                 if (ASMAtomicReadBool(&pTransfer->Thread.fStop))
    391                 {
    392                     LogRel2(("Shared Clipboard: Stopping transfer calculation ...\n"));
    393                     break;
    394                 }
    395 
    396                 if (RT_FAILURE(rc))
    397                     break;
    398439            }
    399 
    400             ShClTransferRootListFree(pRootList);
    401             pRootList = NULL;
    402 
    403             if (   RT_SUCCESS(rc)
    404                 && !ASMAtomicReadBool(&pTransfer->Thread.fStop))
    405             {
    406                 LogRel2(("Shared Clipboard: Transfer calculation complete (%zu root entries)\n", pThis->m_lstEntries.size()));
    407 
    408                 /*
    409                  * Signal the "list complete" event so that this data object can return (valid) data via ::GetData().
    410                  * This in turn then will create IStream instances (by the OS) for each file system object to handle.
    411                  */
    412                 int rc2 = RTSemEventSignal(pThis->m_EventListComplete);
    413                 AssertRC(rc2);
    414 
    415                 if (pThis->m_lstEntries.size())
    416                 {
    417                     LogRel2(("Shared Clipboard: Waiting for transfer to complete ...\n"));
    418 
    419                     LogFlowFunc(("Waiting for transfer to complete ...\n"));
    420 
    421                     /* Transferring stuff can take a while, so don't use any timeout here. */
    422                     rc2 = RTSemEventWait(pThis->m_EventTransferComplete, RT_INDEFINITE_WAIT);
    423                     AssertRC(rc2);
    424 
    425                     switch (pThis->m_enmStatus)
    426                     {
    427                         case Completed:
    428                             LogRel2(("Shared Clipboard: Transfer complete\n"));
    429                             break;
    430 
    431                         case Canceled:
    432                             LogRel2(("Shared Clipboard: Transfer canceled\n"));
    433                             break;
    434 
    435                         case Error:
    436                             LogRel2(("Shared Clipboard: Transfer error occurred\n"));
    437                             break;
    438 
    439                         default:
    440                             break;
    441                     }
    442                 }
    443                 else
    444                    LogRel(("Shared Clipboard: No transfer root entries found -- should not happen, please file a bug report\n"));
    445             }
    446             else if (RT_FAILURE(rc))
    447                 LogRel(("Shared Clipboard: Transfer failed with %Rrc\n", rc));
    448         }
    449 
    450         ShClTransferClose(pTransfer);
     440            else
     441               LogRel(("Shared Clipboard: No transfer root entries found -- should not happen, please file a bug report\n"));
     442        }
     443        else if (RT_FAILURE(rc))
     444            LogRel(("Shared Clipboard: Transfer failed with %Rrc\n", rc));
    451445    }
    452446
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers-http.cpp

    r87072 r87452  
    11/* $Id$ */
    22/** @file
    3  * Shared Clipboard: HTTP server implementation for Shared Clipboard transfers on UNIX-y hosts.
     3 * Shared Clipboard: HTTP server implementation for Shared Clipboard transfers on UNIX-y guests / hosts.
    44 */
    55
     
    4848
    4949#include <VBox/HostServices/VBoxClipboardSvc.h>
     50#include <VBox/GuestHost/SharedClipboard-x11.h>
    5051#include <VBox/GuestHost/SharedClipboard-transfers.h>
    5152
     
    6162    /** Pointer to associated transfer. */
    6263    PSHCLTRANSFER       pTransfer;
     64    /** The (cached) root list of the transfer. NULL if not cached yet. */
     65    PSHCLROOTLIST       pRootList;
     66    /** Critical section for serializing access. */
     67    RTCRITSECT          CritSect;
     68    /** The handle we're going to use for this HTTP transfer. */
     69    SHCLOBJHANDLE       hObj;
    6370    /** The virtual path of the HTTP server's root directory for this transfer. */
    6471    char                szPathVirtual[RTPATH_MAX];
     
    7077*   Prototypes                                                                                                                   *
    7178*********************************************************************************************************************************/
    72 int shClTransferHttpServerDestroyInternal(PSHCLHTTPSERVER pThis);
     79static int shClTransferHttpServerDestroyInternal(PSHCLHTTPSERVER pThis);
     80static const char *shClTransferHttpServerGetHost(PSHCLHTTPSERVER pSrv);
    7381
    7482
    7583/*********************************************************************************************************************************
    76 *   Internal functions                                                                                                           *
     84*   Public Shared Clipboard HTTP transfer functions                                                                              *
    7785*********************************************************************************************************************************/
     86
     87int ShClHttpTransferCreate(PSHCLHTTPCONTEXT pCtx, PSHCLTRANSFER pTransfer)
     88{
     89    int rc = VINF_SUCCESS;
     90
     91    /* Start the built-in HTTP server to serve file(s). */
     92    if (!ShClTransferHttpServerIsRunning(&pCtx->HttpServer)) /* Only one HTTP server per transfer context. */
     93        rc = ShClTransferHttpServerCreate(&pCtx->HttpServer, NULL /* puPort */);
     94
     95    if (RT_SUCCESS(rc))
     96        rc = ShClTransferHttpServerRegisterTransfer(&pCtx->HttpServer, pTransfer);
     97
     98    return rc;
     99}
     100
     101int ShClHttpTransferDestroy(PSHCLHTTPCONTEXT pCtx, PSHCLTRANSFER pTransfer)
     102{
     103    int rc = VINF_SUCCESS;
     104
     105    if (ShClTransferHttpServerIsRunning(&pCtx->HttpServer))
     106    {
     107        /* Try unregistering transfer (if it was registered before). */
     108        rc = ShClTransferHttpServerUnregisterTransfer(&pCtx->HttpServer, pTransfer);
     109        if (RT_SUCCESS(rc))
     110        {
     111            /* No more registered transfers left? Tear down the HTTP server instance then. */
     112            if (ShClTransferHttpServerGetTransferCount(&pCtx->HttpServer) == 0)
     113                rc = ShClTransferHttpServerDestroy(&pCtx->HttpServer);
     114        }
     115        AssertRC(rc);
     116    }
     117
     118    return rc;
     119}
     120
     121
     122/*********************************************************************************************************************************
     123*   Internal Shared Clipboard HTTP transfer functions                                                                            *
     124*********************************************************************************************************************************/
     125
     126DECLINLINE(void) shClHttpTransferLock(PSHCLHTTPSERVERTRANSFER pSrvTx)
     127{
     128    int rc2 = RTCritSectEnter(&pSrvTx->CritSect);
     129    AssertRC(rc2);
     130}
     131
     132DECLINLINE(void) shClHttpTransferUnlock(PSHCLHTTPSERVERTRANSFER pSrvTx)
     133{
     134    int rc2 = RTCritSectEnter(&pSrvTx->CritSect);
     135    AssertRC(rc2);
     136}
    78137
    79138/**
     
    97156
    98157/**
    99  * Validates a given URL whether it matches a registered HTTP transfer.
    100  *
    101  * @returns VBox status code.
     158 * Returns a HTTP server transfer from a given URL.
     159 *
     160 * @returns Pointer to HTTP server transfer if found, NULL if not found.
    102161 * @param   pThis               HTTP server instance data.
    103162 * @param   pszUrl              URL to validate.
    104163 */
    105 static int shClTransferHttpPathValidate(PSHCLHTTPSERVER pThis, const char *pszUrl)
    106 {
    107     AssertPtrReturn(pszUrl, VERR_INVALID_POINTER);
    108 
    109     int rc = VERR_PATH_NOT_FOUND;
    110 
    111     PSHCLHTTPSERVERTRANSFER pSrvTx;
    112     RTListForEach(&pThis->lstTransfers, pSrvTx, SHCLHTTPSERVERTRANSFER, Node)
    113     {
    114         AssertPtr(pSrvTx->pTransfer);
    115 
    116         const char *psz = pszUrl;
     164DECLINLINE(PSHCLHTTPSERVERTRANSFER) shClTransferHttpGetTransferFromUrl(PSHCLHTTPSERVER pThis, const char *pszUrl)
     165{
     166    AssertPtrReturn(pszUrl, NULL);
     167
     168    PSHCLHTTPSERVERTRANSFER pSrvTx = NULL;
     169
     170    PSHCLHTTPSERVERTRANSFER pSrvTxCur;
     171    RTListForEach(&pThis->lstTransfers, pSrvTxCur, SHCLHTTPSERVERTRANSFER, Node)
     172    {
     173        AssertPtr(pSrvTxCur->pTransfer);
     174
     175        LogFlowFunc(("pSrvTxCur=%s\n", pSrvTxCur->szPathVirtual));
    117176
    118177        /* Be picky here, do a case sensitive comparison. */
    119         if (RTStrStartsWith(psz, pSrvTx->szPathVirtual))
     178        if (RTStrStartsWith(pszUrl, pSrvTxCur->szPathVirtual))
    120179        {
    121             /* Skip the virtual root path. */
    122             psz += RTStrNLen(pSrvTx->szPathVirtual, RTPATH_MAX);
    123 
    124 
    125 
    126             LogFlowFunc(("psz=%s\n", psz));
    127 
    128             rc = VINF_SUCCESS;
     180            pSrvTx = pSrvTxCur;
    129181            break;
    130182        }
    131183    }
    132184
    133     LogFlowFunc(("pszUrl=%s, rc=%Rrc\n", pszUrl, rc));
    134     return rc;
    135 }
     185    if (!pSrvTx)
     186        LogRel2(("Shared Clipboard: HTTP URL '%s' not valid\n", pszUrl));
     187
     188    LogFlowFunc(("pszUrl=%s, pSrvTx=%p\n", pszUrl, pSrvTx));
     189    return pSrvTx;
     190}
     191
     192/**
     193 * Returns a HTTP server transfer from an internal HTTP handle.
     194 *
     195 * @returns Pointer to HTTP server transfer if found, NULL if not found.
     196 * @param   pThis               HTTP server instance data.
     197 * @param   pvHandle            Handle to return transfer for.
     198 */
     199DECLINLINE(PSHCLHTTPSERVERTRANSFER) shClTransferHttpGetTransferFromHandle(PSHCLHTTPSERVER pThis, void *pvHandle)
     200{
     201    AssertPtrReturn(pvHandle, NULL);
     202
     203    const SHCLTRANSFERID uHandle = *(uint16_t *)pvHandle;
     204
     205    /** @ŧodo Use a handle lookup table (map) later. */
     206    PSHCLHTTPSERVERTRANSFER pSrvTxCur;
     207    RTListForEach(&pThis->lstTransfers, pSrvTxCur, SHCLHTTPSERVERTRANSFER, Node)
     208    {
     209        AssertPtr(pSrvTxCur->pTransfer);
     210
     211        if (pSrvTxCur->pTransfer->State.uID == uHandle) /** @ŧodo We're using the transfer ID as handle for now. */
     212            return pSrvTxCur;
     213    }
     214
     215    return NULL;
     216}
     217
     218static int shClTransferHttpGetTransferRoots(PSHCLHTTPSERVER pThis, PSHCLHTTPSERVERTRANSFER pSrvTx)
     219{
     220    RT_NOREF(pThis);
     221
     222    int rc = VINF_SUCCESS;
     223
     224    if (pSrvTx->pRootList == NULL)
     225    {
     226        AssertPtr(pSrvTx->pTransfer);
     227        rc = ShClTransferRootsGet(pSrvTx->pTransfer, &pSrvTx->pRootList);
     228    }
     229
     230    return rc;
     231}
     232
     233
     234/*********************************************************************************************************************************
     235*   HTTP server callback implementations                                                                                         *
     236*********************************************************************************************************************************/
    136237
    137238/** @copydoc RTHTTPSERVERCALLBACKS::pfnOpen */
     
    141242    Assert(pData->cbUser == sizeof(SHCLHTTPSERVER));
    142243
    143     int rc = shClTransferHttpPathValidate(pThis, pReq->pszUrl);
     244    int rc;
     245
     246    PSHCLHTTPSERVERTRANSFER pSrvTx = shClTransferHttpGetTransferFromUrl(pThis, pReq->pszUrl);
     247    if (pSrvTx)
     248    {
     249        shClHttpTransferLock(pSrvTx);
     250
     251        AssertPtr(pSrvTx->pTransfer);
     252
     253        SHCLOBJOPENCREATEPARMS openParms;
     254        rc = ShClTransferObjOpenParmsInit(&openParms);
     255        if (RT_SUCCESS(rc))
     256        {
     257            openParms.fCreate = SHCL_OBJ_CF_ACCESS_READ
     258                              | SHCL_OBJ_CF_ACCESS_DENYWRITE;
     259
     260            rc = RTStrCopy(openParms.pszPath, openParms.cbPath, "foo"); /** @ŧodo BUGBUG !!!! */
     261            if (RT_SUCCESS(rc))
     262            {
     263                rc = ShClTransferObjOpen(pSrvTx->pTransfer, &openParms, &pSrvTx->hObj);
     264                if (RT_SUCCESS(rc))
     265                {
     266                    *ppvHandle = &pSrvTx->hObj;
     267                    LogRel2(("Shared Clipboard: HTTP transfer (handle %RU64) started ...\n", pSrvTx->hObj));
     268                }
     269            }
     270
     271            ShClTransferObjOpenParmsDestroy(&openParms);
     272        }
     273
     274        shClHttpTransferUnlock(pSrvTx);
     275    }
     276    else
     277        rc = VERR_NOT_FOUND;
     278
    144279    if (RT_FAILURE(rc))
    145         return rc;
    146 
    147     RT_NOREF(ppvHandle);
     280        LogRel(("Shared Clipboard: Error starting HTTP transfer for '%s', rc=%Rrc\n", pReq->pszUrl, rc));
    148281
    149282    LogFlowFuncLeaveRC(rc);
     
    157290    Assert(pData->cbUser == sizeof(SHCLHTTPSERVER));
    158291
    159     RT_NOREF(pThis, pvHandle, pvBuf, cbBuf, pcbRead);
    160 
    161     int rc = 0;
     292    RT_NOREF(pvBuf, cbBuf, pcbRead);
     293
     294    int rc;
     295
     296    PSHCLHTTPSERVERTRANSFER pSrvTx = shClTransferHttpGetTransferFromHandle(pThis, pvHandle);
     297    if (pSrvTx)
     298    {
     299        Assert(pSrvTx->hObj != SHCLOBJHANDLE_INVALID);
     300//        rc = ShClTransferObjRead(pSrvTx->pTransfer, pSrvTx->hObj, );
     301rc = 0;
     302        if (RT_SUCCESS(rc))
     303        {
     304
     305        }
     306
     307        if (RT_FAILURE(rc))
     308            LogRel(("Shared Clipboard: Error reading HTTP transfer (handle %RU64), rc=%Rrc\n", pSrvTx->hObj, rc));
     309    }
     310    else
     311        rc = VERR_NOT_FOUND;
    162312
    163313    LogFlowFuncLeaveRC(rc);
     
    171321    Assert(pData->cbUser == sizeof(SHCLHTTPSERVER));
    172322
    173     RT_NOREF(pThis, pvHandle);
    174 
    175     int rc = 0;
     323    int rc;
     324
     325    PSHCLHTTPSERVERTRANSFER pSrvTx = shClTransferHttpGetTransferFromHandle(pThis, pvHandle);
     326    if (pSrvTx)
     327    {
     328        shClHttpTransferLock(pSrvTx);
     329
     330        Assert(pSrvTx->hObj != SHCLOBJHANDLE_INVALID);
     331        rc = ShClTransferObjClose(pSrvTx->pTransfer, pSrvTx->hObj);
     332        if (RT_SUCCESS(rc))
     333        {
     334            pSrvTx->hObj = SHCLOBJHANDLE_INVALID;
     335            LogRel2(("Shared Clipboard: HTTP transfer %RU16 done\n", pSrvTx->pTransfer->State.uID));
     336        }
     337
     338        if (RT_FAILURE(rc))
     339            LogRel(("Shared Clipboard: Error closing HTTP transfer (handle %RU64), rc=%Rrc\n", pSrvTx->hObj, rc));
     340
     341        shClHttpTransferUnlock(pSrvTx);
     342    }
     343    else
     344        rc = VERR_NOT_FOUND;
    176345
    177346    LogFlowFuncLeaveRC(rc);
     
    186355    Assert(pData->cbUser == sizeof(SHCLHTTPSERVER));
    187356
    188     int rc = shClTransferHttpPathValidate(pThis, pReq->pszUrl);
    189     if (RT_FAILURE(rc))
    190         return rc;
     357    int rc;
     358
     359    PSHCLHTTPSERVERTRANSFER pSrvTx = shClTransferHttpGetTransferFromUrl(pThis, pReq->pszUrl);
     360    if (pSrvTx)
     361    {
     362        shClHttpTransferLock(pSrvTx);
     363
     364        rc = shClTransferHttpGetTransferRoots(pThis, pSrvTx);
     365
     366        shClHttpTransferUnlock(pSrvTx);
     367    }
     368    else
     369        rc = VERR_NOT_FOUND;
    191370
    192371    RT_NOREF(pObjInfo, ppszMIMEHint);
     
    205384}
    206385
     386
     387/*********************************************************************************************************************************
     388*   Internal Shared Clipboard HTTP server functions                                                                              *
     389*********************************************************************************************************************************/
     390
    207391/**
    208392 * Destroys a Shared Clipboard HTTP server instance, internal version.
     
    211395 * @param   pSrv                Shared Clipboard HTTP server instance to destroy.
    212396 */
    213 int shClTransferHttpServerDestroyInternal(PSHCLHTTPSERVER pSrv)
     397static int shClTransferHttpServerDestroyInternal(PSHCLHTTPSERVER pSrv)
    214398{
    215399    PSHCLHTTPSERVERTRANSFER pSrvTx, pSrvTxNext;
     
    226410    pSrv->hHTTPServer = NIL_RTHTTPSERVER;
    227411
    228     return RTCritSectDelete(&pSrv->CritSect);
     412    int rc = VINF_SUCCESS;
     413
     414    if (RTCritSectIsInitialized(&pSrv->CritSect))
     415        rc = RTCritSectDelete(&pSrv->CritSect);
     416
     417    return rc;
    229418}
    230419
     
    268457
    269458/*********************************************************************************************************************************
    270 *   Public functions                                                                                                             *
     459*   Public Shared Clipboard HTTP server functions                                                                                *
    271460*********************************************************************************************************************************/
    272461
     
    350539        for (int i = 0; i < 32; i++)
    351540        {
     541#ifdef DEBUG_andy
     542            uPort = 8080; /* Make the port predictable, but only for me, mwahaha! :-). */
     543#else
    352544            uPort = RTRandAdvU32Ex(hRand, 1024, UINT16_MAX);
     545#endif
    353546            rc = ShClTransferHttpServerCreateEx(pSrv, (uint32_t)uPort);
    354547            if (RT_SUCCESS(rc))
     
    405598    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    406599
     600    AssertReturn(pTransfer->State.uID, VERR_INVALID_PARAMETER); /* Paranoia. */
     601
    407602    shClTransferHttpServerLock(pSrv);
    408603
     
    418613        if (RT_SUCCESS(rc))
    419614        {
    420             AssertReturn(pTransfer->State.uID, VERR_INVALID_PARAMETER); /* Paranoia. */
     615            rc = RTCritSectInit(&pSrvTx->CritSect);
     616            AssertRC(rc);
    421617
    422618            /* Create the virtual HTTP path for the transfer.
    423619             * Every transfer has a dedicated HTTP path. */
     620#ifdef DEBUG_andy
     621            ssize_t cch = RTStrPrintf2(pSrvTx->szPathVirtual, sizeof(pSrvTx->szPathVirtual), "/d1bbda60-80b7-45dc-a41c-ac4686c1d988/10664");
     622#else
    424623            ssize_t cch = RTStrPrintf2(pSrvTx->szPathVirtual, sizeof(pSrvTx->szPathVirtual), "%s/%RU16/", szUuid, pTransfer->State.uID);
     624#endif
    425625            AssertReturn(cch, VERR_BUFFER_OVERFLOW);
    426626
    427627            pSrvTx->pTransfer = pTransfer;
     628            pSrvTx->pRootList = NULL;
     629            pSrvTx->hObj      = SHCLOBJHANDLE_INVALID;
    428630
    429631            RTListAppend(&pSrv->lstTransfers, &pSrvTx->Node);
     
    473675            RTListNodeRemove(&pSrvTx->Node);
    474676
     677            Assert(pSrv->cTransfers);
     678            pSrv->cTransfers--;
     679
     680            LogFunc(("pTransfer=%p, idTransfer=%RU16, szPath=%s -> %RU32 transfers\n",
     681                     pSrvTx->pTransfer, pSrvTx->pTransfer->State.uID, pSrvTx->szPathVirtual, pSrv->cTransfers));
     682
     683            LogRel2(("Shared Clipboard: Unregistered HTTP transfer %RU16, now %RU32 HTTP transfers total\n",
     684                     pTransfer->State.uID, pSrv->cTransfers));
     685
     686            rc = RTCritSectDelete(&pSrvTx->CritSect);
     687            AssertRC(rc);
     688
    475689            RTMemFree(pSrvTx);
    476690            pSrvTx = NULL;
    477 
    478             Assert(pSrv->cTransfers);
    479             pSrv->cTransfers--;
    480 
    481             LogFunc(("pTransfer=%p, idTransfer=%RU16, szPath=%s -> %RU32 transfers\n",
    482                      pSrvTx->pTransfer, pSrvTx->pTransfer->State.uID, pSrvTx->szPathVirtual, pSrv->cTransfers));
    483 
    484             LogRel2(("Shared Clipboard: Unregistered HTTP transfer %RU16, now %RU32 HTTP transfers total\n",
    485                      pTransfer->State.uID, pSrv->cTransfers));
    486691
    487692            rc = VINF_SUCCESS;
     
    631836    return (pSrv->hHTTPServer != NIL_RTHTTPSERVER); /* Seems enough for now. */
    632837}
    633 
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp

    r87070 r87452  
    3333static int shClTransferThreadCreate(PSHCLTRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser);
    3434static int shClTransferThreadDestroy(PSHCLTRANSFER pTransfer, RTMSINTERVAL uTimeoutMs);
    35 static PSHCLTRANSFER shClTransferCtxGetTransferInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uIdx);
     35
     36static void shclTransferCtxTransferRemoveAndUnregister(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer);
     37static PSHCLTRANSFER shClTransferCtxGetTransferByIdInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uId);
     38static PSHCLTRANSFER shClTransferCtxGetTransferByIndexInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uIdx);
    3639static int shClConvertFileCreateFlags(uint32_t fShClFlags, uint64_t *pfOpen);
    3740static int shClTransferResolvePathAbs(PSHCLTRANSFER pTransfer, const char *pszPath, uint32_t fFlags, char **ppszResolved);
     
    11721175    pTransfer->pszPathRootAbs    = NULL;
    11731176
    1174     pTransfer->uTimeoutMs     = 30 * 1000; /* 30s timeout by default. */
     1177#ifdef DEBUG_andy
     1178    pTransfer->uTimeoutMs     = RT_MS_5SEC;
     1179#else
     1180    pTransfer->uTimeoutMs     = RT_MS_30SEC;
     1181#endif
    11751182    pTransfer->cbMaxChunkSize = _64K; /** @todo Make this configurable. */
    11761183
    11771184    pTransfer->pvUser = NULL;
    11781185    pTransfer->cbUser = 0;
    1179 
    1180     RT_ZERO(pTransfer->Callbacks);
    11811186
    11821187    RTListInit(&pTransfer->lstList);
     
    12371242 * @returns VBox status code.
    12381243 * @param   pTransfer           Transfer to initialize.
    1239  * @param   uID                 ID to use for the transfer. Can be set to 0 if not important.
    12401244 * @param   enmDir              Specifies the transfer direction of this transfer.
    12411245 * @param   enmSource           Specifies the data source of the transfer.
    12421246 */
    1243 int ShClTransferInit(PSHCLTRANSFER pTransfer,
    1244                      SHCLTRANSFERID uID, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource)
    1245 {
    1246     pTransfer->State.uID       = uID;
     1247int ShClTransferInit(PSHCLTRANSFER pTransfer, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource)
     1248{
     1249    pTransfer->State.uID       = 0;
    12471250    pTransfer->State.enmDir    = enmDir;
    12481251    pTransfer->State.enmSource = enmSource;
     
    12641267        pTransfer->uObjHandleNext  = 1;
    12651268
    1266         if (pTransfer->Callbacks.pfnTransferInitialize)
    1267         {
    1268             SHCLTRANSFERCALLBACKDATA Data = { pTransfer, pTransfer->Callbacks.pvUser, pTransfer->Callbacks.cbUser };
    1269             rc = pTransfer->Callbacks.pfnTransferInitialize(&Data);
    1270         }
    1271     }
    1272 
    1273     LogFlowFuncLeaveRC(rc);
    1274     return rc;
    1275 }
    1276 
    1277 int ShClTransferOpen(PSHCLTRANSFER pTransfer)
    1278 {
    1279     int rc = VINF_SUCCESS;
    1280 
    1281     if (pTransfer->ProviderIface.pfnTransferOpen)
    1282         rc = pTransfer->ProviderIface.pfnTransferOpen(&pTransfer->ProviderCtx);
    1283 
    1284     LogFlowFuncLeaveRC(rc);
    1285     return rc;
    1286 }
    1287 
    1288 int ShClTransferClose(PSHCLTRANSFER pTransfer)
    1289 {
    1290     int rc = VINF_SUCCESS;
    1291 
    1292     if (pTransfer->ProviderIface.pfnTransferClose)
    1293         rc = pTransfer->ProviderIface.pfnTransferClose(&pTransfer->ProviderCtx);
     1269        if (pTransfer->ProviderIface.pfnInitialize)
     1270            rc = pTransfer->ProviderIface.pfnInitialize(&pTransfer->ProviderCtx);
     1271    }
    12941272
    12951273    LogFlowFuncLeaveRC(rc);
     
    20442022 * @param   pCreationCtx        Provider creation context to use for provider creation.
    20452023 */
    2046 int ShClTransferSetInterface(PSHCLTRANSFER pTransfer,
    2047                              PSHCLPROVIDERCREATIONCTX pCreationCtx)
     2024int ShClTransferSetProviderIface(PSHCLTRANSFER pTransfer,
     2025                                 PSHCLTXPROVIDERCREATIONCTX pCreationCtx)
    20482026{
    20492027    AssertPtrReturn(pTransfer,    VERR_INVALID_POINTER);
     
    20552033
    20562034    pTransfer->ProviderIface         = pCreationCtx->Interface;
    2057 
    2058 #ifdef DEBUG
    2059 # define LOG_IFACE_PTR(a_Name) \
    2060     LogFlowFunc(( #a_Name "=%p\n", pTransfer->ProviderIface.a_Name));
    2061 
    2062     LOG_IFACE_PTR(pfnTransferOpen);
    2063     LOG_IFACE_PTR(pfnTransferClose);
    2064     LOG_IFACE_PTR(pfnRootsGet);
    2065     LOG_IFACE_PTR(pfnListOpen);
    2066     LOG_IFACE_PTR(pfnListClose);
    2067 
    2068 # undef LOG_IFACE_PTR
    2069 #endif
    2070 
    20712035    pTransfer->ProviderCtx.pTransfer = pTransfer;
    20722036    pTransfer->ProviderCtx.pvUser    = pCreationCtx->pvUser;
     
    25202484    int rc;
    25212485
    2522     if (pTransfer->Callbacks.pfnTransferStart)
    2523     {
    2524         SHCLTRANSFERCALLBACKDATA Data = { pTransfer, pTransfer->Callbacks.pvUser, pTransfer->Callbacks.cbUser };
    2525         rc = pTransfer->Callbacks.pfnTransferStart(&Data);
     2486    if (pTransfer->ProviderIface.pfnStart)
     2487    {
     2488        rc = pTransfer->ProviderIface.pfnStart(&pTransfer->ProviderCtx);
    25262489    }
    25272490    else
     
    25352498    LogFlowFuncLeaveRC(rc);
    25362499    return rc;
    2537 }
    2538 
    2539 /**
    2540  * Sets or unsets the callback table to be used for a Shared Clipboard transfer.
    2541  *
    2542  * @returns VBox status code.
    2543  * @param   pTransfer           Clipboard transfer to set callbacks for.
    2544  * @param   pCallbacks          Pointer to callback table to set.
    2545  */
    2546 void ShClTransferSetCallbacks(PSHCLTRANSFER pTransfer,
    2547                               PSHCLTRANSFERCALLBACKS pCallbacks)
    2548 {
    2549     AssertPtrReturnVoid(pTransfer);
    2550     AssertPtrReturnVoid(pCallbacks);
    2551 
    2552     LogFlowFunc(("pCallbacks=%p\n", pCallbacks));
    2553 
    2554 #define SET_CALLBACK(a_pfnCallback)             \
    2555     if (pCallbacks->a_pfnCallback)              \
    2556         pTransfer->Callbacks.a_pfnCallback = pCallbacks->a_pfnCallback
    2557 
    2558     SET_CALLBACK(pfnTransferInitialize);
    2559     SET_CALLBACK(pfnTransferStart);
    2560     SET_CALLBACK(pfnListHeaderComplete);
    2561     SET_CALLBACK(pfnListEntryComplete);
    2562     SET_CALLBACK(pfnTransferCanceled);
    2563     SET_CALLBACK(pfnTransferError);
    2564 
    2565 #undef SET_CALLBACK
    2566 
    2567     pTransfer->Callbacks.pvUser = pCallbacks->pvUser;
    2568     pTransfer->Callbacks.cbUser = pCallbacks->cbUser;
    25692500}
    25702501
     
    26762607void ShClTransferCtxDestroy(PSHCLTRANSFERCTX pTransferCtx)
    26772608{
    2678     AssertPtrReturnVoid(pTransferCtx);
     2609    if (!pTransferCtx)
     2610        return;
    26792611
    26802612    LogFlowFunc(("pTransferCtx=%p\n", pTransferCtx));
     
    26882620        ShClTransferDestroy(pTransfer);
    26892621
    2690         RTListNodeRemove(&pTransfer->Node);
     2622        shclTransferCtxTransferRemoveAndUnregister(pTransferCtx, pTransfer);
    26912623
    26922624        RTMemFree(pTransfer);
     
    27232655 * @returns Shared Clipboard transfer, or NULL if not found.
    27242656 * @param   pTransferCtx                Transfer context to return transfer for.
    2725  * @param   uID                 ID of the transfer to return.
    2726  */
    2727 static PSHCLTRANSFER shClTransferCtxGetTransferInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uID)
     2657 * @param   uID                         ID of the transfer to return.
     2658 */
     2659static PSHCLTRANSFER shClTransferCtxGetTransferByIdInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uID)
    27282660{
    27292661    PSHCLTRANSFER pTransfer;
     
    27382670
    27392671/**
    2740  * Returns a specific Shared Clipboard transfer.
     2672 * Returns a specific Shared Clipboard transfer by index, internal version.
    27412673 *
    27422674 * @returns Shared Clipboard transfer, or NULL if not found.
    27432675 * @param   pTransferCtx                Transfer context to return transfer for.
    2744  * @param   uID                 ID of the transfer to return.
    2745  */
    2746 PSHCLTRANSFER ShClTransferCtxGetTransfer(PSHCLTRANSFERCTX pTransferCtx, uint32_t uID)
    2747 {
    2748     return shClTransferCtxGetTransferInternal(pTransferCtx, uID);
     2676 * @param   uIdx                        Index of the transfer to return.
     2677 */
     2678static PSHCLTRANSFER shClTransferCtxGetTransferByIndexInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uIdx)
     2679{
     2680    uint32_t idx = 0;
     2681
     2682    PSHCLTRANSFER pTransfer;
     2683    RTListForEach(&pTransferCtx->List, pTransfer, SHCLTRANSFER, Node) /** @todo Slow, but works for now. */
     2684    {
     2685        if (uIdx == idx)
     2686            return pTransfer;
     2687        idx++;
     2688    }
     2689
     2690    return NULL;
     2691}
     2692
     2693/**
     2694 * Returns a Shared Clipboard transfer for a specific transfer ID.
     2695 *
     2696 * @returns Shared Clipboard transfer, or NULL if not found.
     2697 * @param   pTransferCtx                Transfer context to return transfer for.
     2698 * @param   uID                         ID of the transfer to return.
     2699 */
     2700PSHCLTRANSFER ShClTransferCtxGetTransferById(PSHCLTRANSFERCTX pTransferCtx, uint32_t uID)
     2701{
     2702    return shClTransferCtxGetTransferByIdInternal(pTransferCtx, uID);
     2703}
     2704
     2705/**
     2706 * Returns a Shared Clipboard transfer for a specific list index.
     2707 *
     2708 * @returns Shared Clipboard transfer, or NULL if not found.
     2709 * @param   pTransferCtx                Transfer context to return transfer for.
     2710 * @param   uIdx                        List index of the transfer to return.
     2711 */
     2712PSHCLTRANSFER ShClTransferCtxGetTransferByIndex(PSHCLTRANSFERCTX pTransferCtx, uint32_t uIdx)
     2713{
     2714    return shClTransferCtxGetTransferByIndexInternal(pTransferCtx, uIdx);
    27492715}
    27502716
     
    27852751int ShClTransferCtxTransferRegister(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID *pidTransfer)
    27862752{
    2787     AssertPtrReturn(pTransferCtx,      VERR_INVALID_POINTER);
     2753    AssertPtrReturn(pTransferCtx, VERR_INVALID_POINTER);
    27882754    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    27892755    /* pidTransfer is optional. */
     
    28162782    Log2Func(("pTransfer=%p, idTransfer=%RU32 (%RU16 transfers)\n", pTransfer, idTransfer, pTransferCtx->cTransfers));
    28172783
     2784    pTransfer->State.uID = idTransfer;
     2785
    28182786    RTListAppend(&pTransferCtx->List, &pTransfer->Node);
    28192787
    28202788    pTransferCtx->cTransfers++;
    28212789
    2822     int rc = VINF_SUCCESS;
    2823 
    2824 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
    2825     if (!ShClTransferHttpServerIsRunning(&pTransferCtx->HttpServer)) /* Only one HTTP server per transfer context. */
    2826         rc = ShClTransferHttpServerCreate(&pTransferCtx->HttpServer, NULL /* puPort */);
    2827 
    2828     if (RT_SUCCESS(rc))
    2829         rc = ShClTransferHttpServerRegisterTransfer(&pTransferCtx->HttpServer, pTransfer);
    2830 #endif
     2790    if (pTransfer->ProviderIface.pfnRegistered)
     2791        pTransfer->ProviderIface.pfnRegistered(&pTransfer->ProviderCtx, pTransferCtx);
    28312792
    28322793    if (pidTransfer)
    28332794        *pidTransfer = idTransfer;
    28342795
    2835     LogFlowFuncLeaveRC(rc);
    2836     return rc;
    2837 }
    2838 
    2839 /**
    2840  * Registers a Shared Clipboard transfer with a transfer contextby specifying an ID for the transfer.
     2796    LogFlowFuncLeaveRC(VINF_SUCCESS);
     2797    return VINF_SUCCESS;
     2798}
     2799
     2800/**
     2801 * Registers a Shared Clipboard transfer with a transfer context by specifying an ID for the transfer.
    28412802 *
    28422803 * @return  VBox status code.
     
    28472808 * @param   idTransfer          Transfer ID to use for registration.
    28482809 */
    2849 int ShClTransferCtxTransferRegisterByIndex(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID idTransfer)
     2810int ShClTransferCtxTransferRegisterById(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID idTransfer)
    28502811{
    28512812    LogFlowFunc(("cTransfers=%RU16, idTransfer=%RU32\n", pTransferCtx->cTransfers, idTransfer));
     
    28562817        {
    28572818            RTListAppend(&pTransferCtx->List, &pTransfer->Node);
     2819
     2820            pTransfer->State.uID = idTransfer;
     2821
     2822            if (pTransfer->ProviderIface.pfnRegistered)
     2823                pTransfer->ProviderIface.pfnRegistered(&pTransfer->ProviderCtx, pTransferCtx);
    28582824
    28592825            pTransferCtx->cTransfers++;
     
    28692835
    28702836/**
    2871  * Removes a transfer from a transfer context.
     2837 * Removes and unregisters a transfer from a transfer context.
    28722838 *
    28732839 * @param   pTransferCtx        Transfer context to remove transfer from.
    28742840 * @param   pTransfer           Transfer to remove.
    28752841 */
    2876 static void shclTransferCtxTransferRemove(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer)
     2842static void shclTransferCtxTransferRemoveAndUnregister(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer)
    28772843{
    28782844    RTListNodeRemove(&pTransfer->Node);
     
    28832849    Assert(pTransferCtx->cTransfers >= pTransferCtx->cRunning);
    28842850
     2851    if (pTransfer->ProviderIface.pfnUnregistered)
     2852        pTransfer->ProviderIface.pfnUnregistered(&pTransfer->ProviderCtx, pTransferCtx);
     2853
    28852854    LogFlowFunc(("Now %RU32 transfers left\n", pTransferCtx->cTransfers));
    2886 
    2887 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
    2888     if (ShClTransferHttpServerIsRunning(&pTransferCtx->HttpServer))
    2889     {
    2890         /* Try unregistering transfer (if it was registered before). */
    2891         int rc2 = ShClTransferHttpServerUnregisterTransfer(&pTransferCtx->HttpServer, pTransfer);
    2892         if (RT_SUCCESS(rc2))
    2893         {
    2894             /* No more registered transfers left? Tear down the HTTP server instance then. */
    2895             if (pTransferCtx->cTransfers == 0)
    2896                 rc2 = ShClTransferHttpServerDestroy(&pTransferCtx->HttpServer);
    2897         }
    2898         AssertRC(rc2);
    2899     }
    2900 #endif
    29012855}
    29022856
     
    29162870    LogFlowFunc(("idTransfer=%RU32\n", idTransfer));
    29172871
    2918     PSHCLTRANSFER pTransfer = shClTransferCtxGetTransferInternal(pTransferCtx, idTransfer);
     2872    PSHCLTRANSFER pTransfer = shClTransferCtxGetTransferByIdInternal(pTransferCtx, idTransfer);
    29192873    if (pTransfer)
    29202874    {
    2921         shclTransferCtxTransferRemove(pTransferCtx, pTransfer);
     2875        shclTransferCtxTransferRemoveAndUnregister(pTransferCtx, pTransfer);
    29222876    }
    29232877    else
     
    29502904        if (ShClTransferGetStatus(pTransfer) != SHCLTRANSFERSTATUS_STARTED)
    29512905        {
    2952             shclTransferCtxTransferRemove(pTransferCtx, pTransfer);
     2906            shclTransferCtxTransferRemoveAndUnregister(pTransferCtx, pTransfer);
    29532907
    29542908            ShClTransferDestroy(pTransfer);
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-x11.cpp

    r87084 r87452  
    11601160    pCtx->fXtBusy        = false;
    11611161    pCtx->fXtNeedsUpdate = false;
     1162#endif
     1163
     1164#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
     1165    ShClTransferHttpServerInit(&pCtx->HttpCtx.HttpServer);
    11621166#endif
    11631167
  • trunk/src/VBox/GuestHost/SharedClipboard/testcase/tstClipboardGH-X11.cpp

    r87082 r87452  
    119119}
    120120
    121 /* Return the data in the simulated VBox clipboard. */
     121/** @copydoc ShClX11RequestDataForX11Callback */
    122122DECLCALLBACK(int) ShClX11RequestDataForX11Callback(PSHCLCONTEXT pCtx, uint32_t uFmt, void **ppv, uint32_t *pcb)
    123123{
     
    244244static uint32_t g_tst_uX11Formats = 0;
    245245
     246/** @copydoc ShClX11ReportFormatsCallback */
    246247DECLCALLBACK(void) ShClX11ReportFormatsCallback(PSHCLCONTEXT pCtx, SHCLFORMATS fFormats)
    247248{
     
    399400static char g_tst_abCompletedBuf[TESTCASE_MAX_BUF_SIZE];
    400401
     402/** @copydoc ShClX11RequestFromX11CompleteCallback */
    401403void ShClX11RequestFromX11CompleteCallback(PSHCLCONTEXT pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb)
    402404{
  • trunk/src/VBox/GuestHost/SharedClipboard/testcase/tstClipboardGH-X11Smoke.cpp

    r87082 r87452  
    3030#include <VBox/GuestHost/clipboard-helper.h>
    3131
     32/** @copydoc ShClX11RequestDataForX11Callback */
    3233DECLCALLBACK(int) ShClX11RequestDataForX11Callback(PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppv, uint32_t *pcb)
    3334{
     
    3637}
    3738
     39/** @copydoc ShClX11ReportFormatsCallback */
    3840DECLCALLBACK(void) ShClX11ReportFormatsCallback(PSHCLCONTEXT pCtx, SHCLFORMATS fFormats)
    3941{
     
    4143}
    4244
     45/** @copydoc ShClX11RequestFromX11CompleteCallback */
    4346DECLCALLBACK(void) ShClX11RequestFromX11CompleteCallback(PSHCLCONTEXT pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb)
    4447{
Note: See TracChangeset for help on using the changeset viewer.

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