Changeset 100367 in vbox for trunk/src/VBox/Additions/x11/VBoxClient
- Timestamp:
- Jul 4, 2023 4:23:18 PM (21 months ago)
- svn:sync-xref-src-repo-rev:
- 158104
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/VBoxClient/clipboard-x11.cpp
r100286 r100367 57 57 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 58 58 /** 59 * Worker for waiting for a transfer status change. 60 */ 61 static DECLCALLBACK(int) vbclX11TransferWaitForStatusWorker(PSHCLCONTEXT pCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS enmSts, 62 RTMSINTERVAL msTimeout) 63 { 64 RT_NOREF(pCtx); 65 66 LogFlowFuncEnter(); 67 68 int rc = VERR_TIMEOUT; 69 70 ShClTransferAcquire(pTransfer); 71 72 uint64_t const tsStartMs = RTTimeMilliTS(); 73 74 while (RTTimeMilliTS() - tsStartMs <= msTimeout) 75 { 76 if (ShClTransferGetStatus(pTransfer) == enmSts) /* Currently we only have busy waiting here. */ 77 { 78 rc = VINF_SUCCESS; 79 break; 80 } 81 RTThreadSleep(100); 82 } 83 84 ShClTransferRelease(pTransfer); 85 86 return rc; 87 } 88 89 /** 90 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnRegistered 91 * 92 * This starts the HTTP server if not done yet and registers the transfer with it. 59 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnInitialized 93 60 * 94 61 * @thread Clipboard main thread. 95 62 */ 96 static DECLCALLBACK(void) vbclX11OnHttpTransferRegisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx) 97 { 98 RT_NOREF(pTransferCtx); 99 63 static DECLCALLBACK(void) vbclX11OnTransferInitializedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx) 64 { 100 65 LogFlowFuncEnter(); 101 66 … … 106 71 AssertPtr(pTransfer); 107 72 108 ShClTransferAcquire(pTransfer); 73 int rc = VINF_SUCCESS; 74 75 /* If this is a G->H transfer, we need to set the root list entries here, as the host 76 * will start reading those as soon as we report the INITIALIZED status. */ 77 switch (ShClTransferGetDir(pTransfer)) 78 { 79 case SHCLTRANSFERDIR_TO_REMOTE: /* G->H */ 80 { 81 PSHCLEVENT pEvent; 82 rc = ShClEventSourceGenerateAndRegisterEvent(&pCtx->EventSrc, &pEvent); 83 if (RT_SUCCESS(rc)) 84 { 85 rc = ShClX11ReadDataFromX11Async(&g_Ctx.X11, VBOX_SHCL_FMT_URI_LIST, UINT32_MAX, pEvent); 86 if (RT_SUCCESS(rc)) 87 { 88 PSHCLEVENTPAYLOAD pPayload; 89 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 90 if (RT_SUCCESS(rc)) 91 { 92 if (pPayload) 93 { 94 Assert(pPayload->cbData == sizeof(SHCLX11RESPONSE)); 95 PSHCLX11RESPONSE pResp = (PSHCLX11RESPONSE)pPayload->pvData; 96 97 rc = ShClTransferRootsInitFromStringList(pTransfer, (const char *)pResp->Read.pvData, pResp->Read.cbData); 98 99 RTMemFree(pResp->Read.pvData); 100 pResp->Read.cbData = 0; 101 102 ShClPayloadFree(pPayload); 103 } 104 } 105 } 106 } 107 break; 108 } 109 110 case SHCLTRANSFERDIR_FROM_REMOTE: /* H->G */ 111 { 112 /* Retrieve the root entries as a first action, so that the transfer is ready to go 113 * once it gets registered to HTTP server. */ 114 int rc2 = ShClTransferRootListRead(pTransfer); 115 if ( RT_SUCCESS(rc2) 116 /* As soon as we register the transfer with the HTTP server, the transfer needs to have its roots set. */ 117 && ShClTransferRootsCount(pTransfer)) 118 { 119 rc2 = ShClTransferHttpServerRegisterTransfer(&pCtx->X11.HttpCtx.HttpServer, pTransfer); 120 } 121 break; 122 } 123 124 default: 125 break; 126 } 127 128 LogFlowFuncLeaveRC(rc); 129 } 130 131 /** 132 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnRegistered 133 * 134 * This starts the HTTP server if not done yet and registers the transfer with it. 135 * 136 * @thread Clipboard main thread. 137 */ 138 static DECLCALLBACK(void) vbclX11OnTransferRegisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx) 139 { 140 RT_NOREF(pTransferCtx); 141 142 LogFlowFuncEnter(); 143 144 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser; 145 AssertPtr(pCtx); 146 147 PSHCLTRANSFER pTransfer = pCbCtx->pTransfer; 148 AssertPtr(pTransfer); 109 149 110 150 /* We only need to start the HTTP server when we actually receive data from the remote (host). */ 111 if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE) 112 { 113 /* Retrieve the root entries as a first action, so that the transfer is ready to go 114 * once it gets registered to HTTP server below. */ 115 int rc2 = ShClTransferRootListRead(pTransfer); 116 if (RT_SUCCESS(rc2)) 117 { 118 ShClTransferHttpServerMaybeStart(&pCtx->X11.HttpCtx); 119 rc2 = ShClTransferHttpServerRegisterTransfer(&pCtx->X11.HttpCtx.HttpServer, pTransfer); 120 } 121 151 if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE) /* H->G */ 152 { 153 int rc2 = ShClTransferHttpServerMaybeStart(&pCtx->X11.HttpCtx); 122 154 if (RT_FAILURE(rc2)) 123 155 LogRel(("Shared Clipboard: Registering HTTP transfer failed: %Rrc\n", rc2)); … … 137 169 * @thread Clipboard main thread. 138 170 */ 139 static void vbclX11 HttpTransferUnregister(PSHCLCONTEXT pCtx, PSHCLTRANSFER pTransfer)171 static void vbclX11TransferUnregister(PSHCLCONTEXT pCtx, PSHCLTRANSFER pTransfer) 140 172 { 141 173 if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE) 142 174 { 143 ShClTransferHttpServerUnregisterTransfer(&pCtx->X11.HttpCtx.HttpServer, pTransfer); 144 ShClTransferHttpServerMaybeStop(&pCtx->X11.HttpCtx); 145 } 146 147 ShClTransferRelease(pTransfer); 175 if (ShClTransferHttpServerIsInitialized(&pCtx->X11.HttpCtx.HttpServer)) 176 { 177 ShClTransferHttpServerUnregisterTransfer(&pCtx->X11.HttpCtx.HttpServer, pTransfer); 178 ShClTransferHttpServerMaybeStop(&pCtx->X11.HttpCtx); 179 } 180 } 148 181 } 149 182 … … 155 188 * @thread Clipboard main thread. 156 189 */ 157 static DECLCALLBACK(void) vbclX11On HttpTransferUnregisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx)190 static DECLCALLBACK(void) vbclX11OnTransferUnregisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx) 158 191 { 159 192 RT_NOREF(pTransferCtx); 160 vbclX11 HttpTransferUnregister((PSHCLCONTEXT)pCbCtx->pvUser, pCbCtx->pTransfer);193 vbclX11TransferUnregister((PSHCLCONTEXT)pCbCtx->pvUser, pCbCtx->pTransfer); 161 194 } 162 195 … … 168 201 * @thread Clipboard main thread. 169 202 */ 170 static DECLCALLBACK(void) vbclX11On HttpTransferCompletedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, int rc)203 static DECLCALLBACK(void) vbclX11OnTransferCompletedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, int rc) 171 204 { 172 205 RT_NOREF(rc); 173 vbclX11 HttpTransferUnregister((PSHCLCONTEXT)pCbCtx->pvUser, pCbCtx->pTransfer);206 vbclX11TransferUnregister((PSHCLCONTEXT)pCbCtx->pvUser, pCbCtx->pTransfer); 174 207 } 175 208 … … 180 213 * @thread Clipboard main thread. 181 214 */ 182 static DECLCALLBACK(void) vbclX11On HttpTransferErrorCallback(PSHCLTRANSFERCALLBACKCTX pCtx, int rc)183 { 184 return vbclX11On HttpTransferCompletedCallback(pCtx, rc);215 static DECLCALLBACK(void) vbclX11OnTransferErrorCallback(PSHCLTRANSFERCALLBACKCTX pCtx, int rc) 216 { 217 return vbclX11OnTransferCompletedCallback(pCtx, rc); 185 218 } 186 219 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */ … … 257 290 * @copydoc SHCLCALLBACKS::pfnOnRequestDataFromSource 258 291 * 259 * Requests URI data from the host. 260 * This initiates a transfer on the host. Most of the handling will be done VbglR3 then. 292 * Requests data from the host. 293 * 294 * For transfers: This requests a transfer from the host. Most of the handling will be done VbglR3 then. 261 295 * 262 296 * @thread X11 event thread. … … 274 308 if (uFmt == VBOX_SHCL_FMT_URI_LIST) 275 309 { 276 PSHCLHTTPSERVER pSrv = &pCtx->X11.HttpCtx.HttpServer;277 278 310 rc = vbclX11ReadDataWorker(pCtx, uFmt, ppv, pcb, pvUser); 279 311 if (RT_SUCCESS(rc)) 280 rc = ShClTransferHttpServerWaitForStatusChange(pSrv, SHCLHTTPSERVERSTATUS_TRANSFER_REGISTERED, 5000 /* SHCL_TIMEOUT_DEFAULT_MS */); 281 if (RT_SUCCESS(rc)) 282 { 283 PSHCLTRANSFER pTransfer = ShClTransferHttpServerGetTransferLast(pSrv); 284 if (pTransfer) 312 { 313 /* Request a new H->G transfer from the host. 314 * This is needed in order to get a transfer ID from the host we can initialize our own local transfer with. 315 * Transfer creation and set up will be done in VbglR3. */ 316 rc = VbglR3ClipboardTransferRequest(&pCtx->CmdCtx); 317 if (RT_SUCCESS(rc)) 285 318 { 286 rc = vbclX11TransferWaitForStatusWorker(pCtx, pTransfer, SHCLTRANSFERSTATUS_STARTED, SHCL_TIMEOUT_DEFAULT_MS); 319 PSHCLHTTPSERVER pSrv = &pCtx->X11.HttpCtx.HttpServer; 320 321 /* Wait until the HTTP server got the transfer registered, so that we have something to work with. */ 322 rc = ShClTransferHttpServerWaitForStatusChange(pSrv, SHCLHTTPSERVERSTATUS_TRANSFER_REGISTERED, SHCL_TIMEOUT_DEFAULT_MS); 287 323 if (RT_SUCCESS(rc)) 288 324 { 289 char *pszURL = ShClTransferHttpServerGetUrlA(pSrv, pTransfer->State.uID); 290 char *pszData = NULL; 291 RTStrAPrintf(&pszData, "copy\n%s", pszURL); 292 293 *ppv = pszData; 294 *pcb = strlen(pszData) + 1 /* Include terminator */; 295 296 LogFlowFunc(("pszURL=%s\n", pszURL)); 297 298 RTStrFree(pszURL); 299 300 rc = VINF_SUCCESS; 301 } 325 PSHCLTRANSFER pTransfer = ShClTransferHttpServerGetTransferLast(pSrv); 326 if (pTransfer) 327 { 328 rc = ShClTransferWaitForStatus(pTransfer, SHCL_TIMEOUT_DEFAULT_MS, SHCLTRANSFERSTATUS_INITIALIZED); 329 if (RT_SUCCESS(rc)) 330 { 331 char *pszURL = ShClTransferHttpServerGetUrlA(pSrv, pTransfer->State.uID); 332 if (pszURL) 333 { 334 *ppv = pszURL; 335 *pcb = strlen(pszURL) + 1 /* Include terminator */; 336 337 LogFlowFunc(("URL is '%s'\n", pszURL)); 338 339 /* ppv has ownership of pszURL. */ 340 } 341 else 342 rc = VERR_NO_MEMORY; 343 } 344 } 345 else 346 AssertMsgFailed(("No registered transfer found for HTTP server\n")); 347 } 348 else 349 LogRel(("Shared Clipboard: Could not start transfer, as no new HTTP transfer was registered in time\n")); 302 350 } 303 else 304 AssertMsgFailed(("No registered transfer found for HTTP server\n")); 305 } 306 else 307 LogRel(("Shared Clipboard: Could not start transfer, as the HTTP server is not running\n")); 351 } 308 352 } 309 353 else /* Anything else */ … … 314 358 315 359 if (RT_FAILURE(rc)) 316 LogRel((" Requesting data in format %#x from host failed with %Rrc\n", uFmt, rc));360 LogRel(("Shared Clipboard: Requesting data in format %#x from host failed with %Rrc\n", uFmt, rc)); 317 361 318 362 LogFlowFuncLeaveRC(rc); … … 418 462 pCtx->CmdCtx.Transfers.Callbacks.cbUser = sizeof(SHCLCONTEXT); 419 463 420 pCtx->CmdCtx.Transfers.Callbacks.pfnOnRegistered = vbclX11OnHttpTransferRegisteredCallback; 421 pCtx->CmdCtx.Transfers.Callbacks.pfnOnUnregistered = vbclX11OnHttpTransferUnregisteredCallback; 422 pCtx->CmdCtx.Transfers.Callbacks.pfnOnCompleted = vbclX11OnHttpTransferCompletedCallback; 423 pCtx->CmdCtx.Transfers.Callbacks.pfnOnError = vbclX11OnHttpTransferErrorCallback; 464 pCtx->CmdCtx.Transfers.Callbacks.pfnOnInitialized = vbclX11OnTransferInitializedCallback; 465 pCtx->CmdCtx.Transfers.Callbacks.pfnOnRegistered = vbclX11OnTransferRegisteredCallback; 466 pCtx->CmdCtx.Transfers.Callbacks.pfnOnUnregistered = vbclX11OnTransferUnregisteredCallback; 467 pCtx->CmdCtx.Transfers.Callbacks.pfnOnCompleted = vbclX11OnTransferCompletedCallback; 468 pCtx->CmdCtx.Transfers.Callbacks.pfnOnError = vbclX11OnTransferErrorCallback; 424 469 # endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */ 425 470 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
Note:
See TracChangeset
for help on using the changeset viewer.