Changeset 87452 in vbox for trunk/src/VBox/GuestHost/SharedClipboard
- Timestamp:
- Jan 27, 2021 5:11:25 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 142470
- Location:
- trunk/src/VBox/GuestHost/SharedClipboard
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp
r82968 r87452 352 352 LogRel2(("Shared Clipboard: Calculating transfer ...\n")); 353 353 354 int rc = ShClTransferOpen(pTransfer); 354 PSHCLROOTLIST pRootList; 355 rc = ShClTransferRootsGet(pTransfer, &pRootList); 355 356 if (RT_SUCCESS(rc)) 356 357 { 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)) 364 371 { 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) 374 423 { 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; 380 438 } 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 else388 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;398 439 } 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)); 451 445 } 452 446 -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers-http.cpp
r87072 r87452 1 1 /* $Id$ */ 2 2 /** @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. 4 4 */ 5 5 … … 48 48 49 49 #include <VBox/HostServices/VBoxClipboardSvc.h> 50 #include <VBox/GuestHost/SharedClipboard-x11.h> 50 51 #include <VBox/GuestHost/SharedClipboard-transfers.h> 51 52 … … 61 62 /** Pointer to associated transfer. */ 62 63 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; 63 70 /** The virtual path of the HTTP server's root directory for this transfer. */ 64 71 char szPathVirtual[RTPATH_MAX]; … … 70 77 * Prototypes * 71 78 *********************************************************************************************************************************/ 72 int shClTransferHttpServerDestroyInternal(PSHCLHTTPSERVER pThis); 79 static int shClTransferHttpServerDestroyInternal(PSHCLHTTPSERVER pThis); 80 static const char *shClTransferHttpServerGetHost(PSHCLHTTPSERVER pSrv); 73 81 74 82 75 83 /********************************************************************************************************************************* 76 * Internal functions*84 * Public Shared Clipboard HTTP transfer functions * 77 85 *********************************************************************************************************************************/ 86 87 int 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 101 int 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 126 DECLINLINE(void) shClHttpTransferLock(PSHCLHTTPSERVERTRANSFER pSrvTx) 127 { 128 int rc2 = RTCritSectEnter(&pSrvTx->CritSect); 129 AssertRC(rc2); 130 } 131 132 DECLINLINE(void) shClHttpTransferUnlock(PSHCLHTTPSERVERTRANSFER pSrvTx) 133 { 134 int rc2 = RTCritSectEnter(&pSrvTx->CritSect); 135 AssertRC(rc2); 136 } 78 137 79 138 /** … … 97 156 98 157 /** 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. 102 161 * @param pThis HTTP server instance data. 103 162 * @param pszUrl URL to validate. 104 163 */ 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;164 DECLINLINE(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)); 117 176 118 177 /* Be picky here, do a case sensitive comparison. */ 119 if (RTStrStartsWith(psz , pSrvTx->szPathVirtual))178 if (RTStrStartsWith(pszUrl, pSrvTxCur->szPathVirtual)) 120 179 { 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; 129 181 break; 130 182 } 131 183 } 132 184 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 */ 199 DECLINLINE(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 218 static 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 *********************************************************************************************************************************/ 136 237 137 238 /** @copydoc RTHTTPSERVERCALLBACKS::pfnOpen */ … … 141 242 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER)); 142 243 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 144 279 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)); 148 281 149 282 LogFlowFuncLeaveRC(rc); … … 157 290 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER)); 158 291 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, ); 301 rc = 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; 162 312 163 313 LogFlowFuncLeaveRC(rc); … … 171 321 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER)); 172 322 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; 176 345 177 346 LogFlowFuncLeaveRC(rc); … … 186 355 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER)); 187 356 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; 191 370 192 371 RT_NOREF(pObjInfo, ppszMIMEHint); … … 205 384 } 206 385 386 387 /********************************************************************************************************************************* 388 * Internal Shared Clipboard HTTP server functions * 389 *********************************************************************************************************************************/ 390 207 391 /** 208 392 * Destroys a Shared Clipboard HTTP server instance, internal version. … … 211 395 * @param pSrv Shared Clipboard HTTP server instance to destroy. 212 396 */ 213 int shClTransferHttpServerDestroyInternal(PSHCLHTTPSERVER pSrv)397 static int shClTransferHttpServerDestroyInternal(PSHCLHTTPSERVER pSrv) 214 398 { 215 399 PSHCLHTTPSERVERTRANSFER pSrvTx, pSrvTxNext; … … 226 410 pSrv->hHTTPServer = NIL_RTHTTPSERVER; 227 411 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; 229 418 } 230 419 … … 268 457 269 458 /********************************************************************************************************************************* 270 * Public functions*459 * Public Shared Clipboard HTTP server functions * 271 460 *********************************************************************************************************************************/ 272 461 … … 350 539 for (int i = 0; i < 32; i++) 351 540 { 541 #ifdef DEBUG_andy 542 uPort = 8080; /* Make the port predictable, but only for me, mwahaha! :-). */ 543 #else 352 544 uPort = RTRandAdvU32Ex(hRand, 1024, UINT16_MAX); 545 #endif 353 546 rc = ShClTransferHttpServerCreateEx(pSrv, (uint32_t)uPort); 354 547 if (RT_SUCCESS(rc)) … … 405 598 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 406 599 600 AssertReturn(pTransfer->State.uID, VERR_INVALID_PARAMETER); /* Paranoia. */ 601 407 602 shClTransferHttpServerLock(pSrv); 408 603 … … 418 613 if (RT_SUCCESS(rc)) 419 614 { 420 AssertReturn(pTransfer->State.uID, VERR_INVALID_PARAMETER); /* Paranoia. */ 615 rc = RTCritSectInit(&pSrvTx->CritSect); 616 AssertRC(rc); 421 617 422 618 /* Create the virtual HTTP path for the transfer. 423 619 * 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 424 623 ssize_t cch = RTStrPrintf2(pSrvTx->szPathVirtual, sizeof(pSrvTx->szPathVirtual), "%s/%RU16/", szUuid, pTransfer->State.uID); 624 #endif 425 625 AssertReturn(cch, VERR_BUFFER_OVERFLOW); 426 626 427 627 pSrvTx->pTransfer = pTransfer; 628 pSrvTx->pRootList = NULL; 629 pSrvTx->hObj = SHCLOBJHANDLE_INVALID; 428 630 429 631 RTListAppend(&pSrv->lstTransfers, &pSrvTx->Node); … … 473 675 RTListNodeRemove(&pSrvTx->Node); 474 676 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 475 689 RTMemFree(pSrvTx); 476 690 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));486 691 487 692 rc = VINF_SUCCESS; … … 631 836 return (pSrv->hHTTPServer != NIL_RTHTTPSERVER); /* Seems enough for now. */ 632 837 } 633 -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp
r87070 r87452 33 33 static int shClTransferThreadCreate(PSHCLTRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser); 34 34 static int shClTransferThreadDestroy(PSHCLTRANSFER pTransfer, RTMSINTERVAL uTimeoutMs); 35 static PSHCLTRANSFER shClTransferCtxGetTransferInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uIdx); 35 36 static void shclTransferCtxTransferRemoveAndUnregister(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer); 37 static PSHCLTRANSFER shClTransferCtxGetTransferByIdInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uId); 38 static PSHCLTRANSFER shClTransferCtxGetTransferByIndexInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uIdx); 36 39 static int shClConvertFileCreateFlags(uint32_t fShClFlags, uint64_t *pfOpen); 37 40 static int shClTransferResolvePathAbs(PSHCLTRANSFER pTransfer, const char *pszPath, uint32_t fFlags, char **ppszResolved); … … 1172 1175 pTransfer->pszPathRootAbs = NULL; 1173 1176 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 1175 1182 pTransfer->cbMaxChunkSize = _64K; /** @todo Make this configurable. */ 1176 1183 1177 1184 pTransfer->pvUser = NULL; 1178 1185 pTransfer->cbUser = 0; 1179 1180 RT_ZERO(pTransfer->Callbacks);1181 1186 1182 1187 RTListInit(&pTransfer->lstList); … … 1237 1242 * @returns VBox status code. 1238 1243 * @param pTransfer Transfer to initialize. 1239 * @param uID ID to use for the transfer. Can be set to 0 if not important.1240 1244 * @param enmDir Specifies the transfer direction of this transfer. 1241 1245 * @param enmSource Specifies the data source of the transfer. 1242 1246 */ 1243 int ShClTransferInit(PSHCLTRANSFER pTransfer, 1244 SHCLTRANSFERID uID, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource) 1245 { 1246 pTransfer->State.uID = uID; 1247 int ShClTransferInit(PSHCLTRANSFER pTransfer, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource) 1248 { 1249 pTransfer->State.uID = 0; 1247 1250 pTransfer->State.enmDir = enmDir; 1248 1251 pTransfer->State.enmSource = enmSource; … … 1264 1267 pTransfer->uObjHandleNext = 1; 1265 1268 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 } 1294 1272 1295 1273 LogFlowFuncLeaveRC(rc); … … 2044 2022 * @param pCreationCtx Provider creation context to use for provider creation. 2045 2023 */ 2046 int ShClTransferSet Interface(PSHCLTRANSFER pTransfer,2047 PSHCLPROVIDERCREATIONCTX pCreationCtx)2024 int ShClTransferSetProviderIface(PSHCLTRANSFER pTransfer, 2025 PSHCLTXPROVIDERCREATIONCTX pCreationCtx) 2048 2026 { 2049 2027 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); … … 2055 2033 2056 2034 pTransfer->ProviderIface = pCreationCtx->Interface; 2057 2058 #ifdef DEBUG2059 # 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_PTR2069 #endif2070 2071 2035 pTransfer->ProviderCtx.pTransfer = pTransfer; 2072 2036 pTransfer->ProviderCtx.pvUser = pCreationCtx->pvUser; … … 2520 2484 int rc; 2521 2485 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); 2526 2489 } 2527 2490 else … … 2535 2498 LogFlowFuncLeaveRC(rc); 2536 2499 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_pfnCallback2557 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_CALLBACK2566 2567 pTransfer->Callbacks.pvUser = pCallbacks->pvUser;2568 pTransfer->Callbacks.cbUser = pCallbacks->cbUser;2569 2500 } 2570 2501 … … 2676 2607 void ShClTransferCtxDestroy(PSHCLTRANSFERCTX pTransferCtx) 2677 2608 { 2678 AssertPtrReturnVoid(pTransferCtx); 2609 if (!pTransferCtx) 2610 return; 2679 2611 2680 2612 LogFlowFunc(("pTransferCtx=%p\n", pTransferCtx)); … … 2688 2620 ShClTransferDestroy(pTransfer); 2689 2621 2690 RTListNodeRemove(&pTransfer->Node);2622 shclTransferCtxTransferRemoveAndUnregister(pTransferCtx, pTransfer); 2691 2623 2692 2624 RTMemFree(pTransfer); … … 2723 2655 * @returns Shared Clipboard transfer, or NULL if not found. 2724 2656 * @param pTransferCtx Transfer context to return transfer for. 2725 * @param uID ID of the transfer to return.2726 */ 2727 static PSHCLTRANSFER shClTransferCtxGetTransfer Internal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uID)2657 * @param uID ID of the transfer to return. 2658 */ 2659 static PSHCLTRANSFER shClTransferCtxGetTransferByIdInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uID) 2728 2660 { 2729 2661 PSHCLTRANSFER pTransfer; … … 2738 2670 2739 2671 /** 2740 * Returns a specific Shared Clipboard transfer .2672 * Returns a specific Shared Clipboard transfer by index, internal version. 2741 2673 * 2742 2674 * @returns Shared Clipboard transfer, or NULL if not found. 2743 2675 * @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 */ 2678 static 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 */ 2700 PSHCLTRANSFER 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 */ 2712 PSHCLTRANSFER ShClTransferCtxGetTransferByIndex(PSHCLTRANSFERCTX pTransferCtx, uint32_t uIdx) 2713 { 2714 return shClTransferCtxGetTransferByIndexInternal(pTransferCtx, uIdx); 2749 2715 } 2750 2716 … … 2785 2751 int ShClTransferCtxTransferRegister(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID *pidTransfer) 2786 2752 { 2787 AssertPtrReturn(pTransferCtx, 2753 AssertPtrReturn(pTransferCtx, VERR_INVALID_POINTER); 2788 2754 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 2789 2755 /* pidTransfer is optional. */ … … 2816 2782 Log2Func(("pTransfer=%p, idTransfer=%RU32 (%RU16 transfers)\n", pTransfer, idTransfer, pTransferCtx->cTransfers)); 2817 2783 2784 pTransfer->State.uID = idTransfer; 2785 2818 2786 RTListAppend(&pTransferCtx->List, &pTransfer->Node); 2819 2787 2820 2788 pTransferCtx->cTransfers++; 2821 2789 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); 2831 2792 2832 2793 if (pidTransfer) 2833 2794 *pidTransfer = idTransfer; 2834 2795 2835 LogFlowFuncLeaveRC( rc);2836 return rc;2837 } 2838 2839 /** 2840 * Registers a Shared Clipboard transfer with a transfer context by 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. 2841 2802 * 2842 2803 * @return VBox status code. … … 2847 2808 * @param idTransfer Transfer ID to use for registration. 2848 2809 */ 2849 int ShClTransferCtxTransferRegisterByI ndex(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID idTransfer)2810 int ShClTransferCtxTransferRegisterById(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID idTransfer) 2850 2811 { 2851 2812 LogFlowFunc(("cTransfers=%RU16, idTransfer=%RU32\n", pTransferCtx->cTransfers, idTransfer)); … … 2856 2817 { 2857 2818 RTListAppend(&pTransferCtx->List, &pTransfer->Node); 2819 2820 pTransfer->State.uID = idTransfer; 2821 2822 if (pTransfer->ProviderIface.pfnRegistered) 2823 pTransfer->ProviderIface.pfnRegistered(&pTransfer->ProviderCtx, pTransferCtx); 2858 2824 2859 2825 pTransferCtx->cTransfers++; … … 2869 2835 2870 2836 /** 2871 * Removes a transfer from a transfer context.2837 * Removes and unregisters a transfer from a transfer context. 2872 2838 * 2873 2839 * @param pTransferCtx Transfer context to remove transfer from. 2874 2840 * @param pTransfer Transfer to remove. 2875 2841 */ 2876 static void shclTransferCtxTransferRemove (PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer)2842 static void shclTransferCtxTransferRemoveAndUnregister(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer) 2877 2843 { 2878 2844 RTListNodeRemove(&pTransfer->Node); … … 2883 2849 Assert(pTransferCtx->cTransfers >= pTransferCtx->cRunning); 2884 2850 2851 if (pTransfer->ProviderIface.pfnUnregistered) 2852 pTransfer->ProviderIface.pfnUnregistered(&pTransfer->ProviderCtx, pTransferCtx); 2853 2885 2854 LogFlowFunc(("Now %RU32 transfers left\n", pTransferCtx->cTransfers)); 2886 2887 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP2888 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 #endif2901 2855 } 2902 2856 … … 2916 2870 LogFlowFunc(("idTransfer=%RU32\n", idTransfer)); 2917 2871 2918 PSHCLTRANSFER pTransfer = shClTransferCtxGetTransfer Internal(pTransferCtx, idTransfer);2872 PSHCLTRANSFER pTransfer = shClTransferCtxGetTransferByIdInternal(pTransferCtx, idTransfer); 2919 2873 if (pTransfer) 2920 2874 { 2921 shclTransferCtxTransferRemove (pTransferCtx, pTransfer);2875 shclTransferCtxTransferRemoveAndUnregister(pTransferCtx, pTransfer); 2922 2876 } 2923 2877 else … … 2950 2904 if (ShClTransferGetStatus(pTransfer) != SHCLTRANSFERSTATUS_STARTED) 2951 2905 { 2952 shclTransferCtxTransferRemove (pTransferCtx, pTransfer);2906 shclTransferCtxTransferRemoveAndUnregister(pTransferCtx, pTransfer); 2953 2907 2954 2908 ShClTransferDestroy(pTransfer); -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-x11.cpp
r87084 r87452 1160 1160 pCtx->fXtBusy = false; 1161 1161 pCtx->fXtNeedsUpdate = false; 1162 #endif 1163 1164 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 1165 ShClTransferHttpServerInit(&pCtx->HttpCtx.HttpServer); 1162 1166 #endif 1163 1167 -
trunk/src/VBox/GuestHost/SharedClipboard/testcase/tstClipboardGH-X11.cpp
r87082 r87452 119 119 } 120 120 121 /* Return the data in the simulated VBox clipboard.*/121 /** @copydoc ShClX11RequestDataForX11Callback */ 122 122 DECLCALLBACK(int) ShClX11RequestDataForX11Callback(PSHCLCONTEXT pCtx, uint32_t uFmt, void **ppv, uint32_t *pcb) 123 123 { … … 244 244 static uint32_t g_tst_uX11Formats = 0; 245 245 246 /** @copydoc ShClX11ReportFormatsCallback */ 246 247 DECLCALLBACK(void) ShClX11ReportFormatsCallback(PSHCLCONTEXT pCtx, SHCLFORMATS fFormats) 247 248 { … … 399 400 static char g_tst_abCompletedBuf[TESTCASE_MAX_BUF_SIZE]; 400 401 402 /** @copydoc ShClX11RequestFromX11CompleteCallback */ 401 403 void ShClX11RequestFromX11CompleteCallback(PSHCLCONTEXT pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb) 402 404 { -
trunk/src/VBox/GuestHost/SharedClipboard/testcase/tstClipboardGH-X11Smoke.cpp
r87082 r87452 30 30 #include <VBox/GuestHost/clipboard-helper.h> 31 31 32 /** @copydoc ShClX11RequestDataForX11Callback */ 32 33 DECLCALLBACK(int) ShClX11RequestDataForX11Callback(PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppv, uint32_t *pcb) 33 34 { … … 36 37 } 37 38 39 /** @copydoc ShClX11ReportFormatsCallback */ 38 40 DECLCALLBACK(void) ShClX11ReportFormatsCallback(PSHCLCONTEXT pCtx, SHCLFORMATS fFormats) 39 41 { … … 41 43 } 42 44 45 /** @copydoc ShClX11RequestFromX11CompleteCallback */ 43 46 DECLCALLBACK(void) ShClX11RequestFromX11CompleteCallback(PSHCLCONTEXT pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb) 44 47 {
Note:
See TracChangeset
for help on using the changeset viewer.