- Timestamp:
- Oct 31, 2012 3:01:55 PM (12 years ago)
- Location:
- trunk/src/VBox/HostServices/HostChannel
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/HostChannel/HostChannel.cpp
r43462 r43785 22 22 #include "HostChannel.h" 23 23 24 24 25 static DECLCALLBACK(void) HostChannelCallbackEvent(void *pvCallbacks, void *pvInstance, 25 26 uint32_t u32Id, const void *pvEvent, uint32_t cbEvent); 27 static DECLCALLBACK(void) HostChannelCallbackDeleted(void *pvCallbacks, void *pvChannel); 26 28 27 29 … … 63 65 }; 64 66 67 /* The channel callbacks context. The provider passes the pointer as a callback parameter. 68 * Created for the provider and deleted when the provider says so. 69 */ 70 typedef struct VBOXHOSTCHCALLBACKCTX 71 { 72 RTLISTNODE nodeClient; /* In the client, for cleanup when a client disconnects. */ 73 74 VBOXHOSTCHCLIENT *pClient; /* The client which uses the channel, NULL when the client does not exist. */ 75 } VBOXHOSTCHCALLBACKCTX; 76 65 77 /* Only one service instance is supported. */ 66 78 static VBOXHOSTCHCTX g_ctx = { false }; … … 68 80 static VBOXHOSTCHANNELCALLBACKS g_callbacks = 69 81 { 70 HostChannelCallbackEvent 82 HostChannelCallbackEvent, 83 HostChannelCallbackDeleted 71 84 }; 72 85 … … 340 353 } 341 354 355 /* 356 * Channel callback contexts. 357 */ 358 static int vhcCallbackCtxCreate(VBOXHOSTCHCLIENT *pClient, VBOXHOSTCHCALLBACKCTX **ppCallbackCtx) 359 { 360 int rc = VINF_SUCCESS; 361 362 VBOXHOSTCHCALLBACKCTX *pCallbackCtx = (VBOXHOSTCHCALLBACKCTX *)RTMemAllocZ(sizeof(VBOXHOSTCHCALLBACKCTX)); 363 364 if (pCallbackCtx != NULL) 365 { 366 /* The callback context is accessed by the providers threads. */ 367 rc = vboxHostChannelLock(); 368 if (RT_SUCCESS(rc)) 369 { 370 RTListAppend(&pClient->listContexts, &pCallbackCtx->nodeClient); 371 pCallbackCtx->pClient = pClient; 372 373 vboxHostChannelUnlock(); 374 } 375 else 376 { 377 RTMemFree(pCallbackCtx); 378 } 379 } 380 else 381 { 382 rc = VERR_NO_MEMORY; 383 } 384 385 if (RT_SUCCESS(rc)) 386 { 387 *ppCallbackCtx = pCallbackCtx; 388 } 389 390 return rc; 391 } 392 393 static int vhcCallbackCtxDelete(VBOXHOSTCHCALLBACKCTX *pCallbackCtx) 394 { 395 int rc = vboxHostChannelLock(); 396 if (RT_SUCCESS(rc)) 397 { 398 VBOXHOSTCHCLIENT *pClient = pCallbackCtx->pClient; 399 400 if (pClient != NULL) 401 { 402 /* The callback is associated with a client. 403 * Check that the callback is in the list and remove it from the list. 404 */ 405 bool fFound = false; 406 407 VBOXHOSTCHCALLBACKCTX *pIter; 408 RTListForEach(&pClient->listContexts, pIter, VBOXHOSTCHCALLBACKCTX, nodeClient) 409 { 410 if (pIter == pCallbackCtx) 411 { 412 fFound = true; 413 break; 414 } 415 } 416 417 if (fFound) 418 { 419 RTListNodeRemove(&pCallbackCtx->nodeClient); 420 } 421 else 422 { 423 AssertFailed(); 424 rc = VERR_INVALID_PARAMETER; 425 } 426 } 427 else 428 { 429 /* It is not in the clients anymore. May be the client has been disconnected. 430 * Just free the memory. 431 */ 432 } 433 434 vboxHostChannelUnlock(); 435 } 436 437 if (RT_SUCCESS(rc)) 438 { 439 RTMemFree(pCallbackCtx); 440 } 441 442 return rc; 443 } 342 444 343 445 /* … … 383 485 RTListInit(&pClient->listChannels); 384 486 RTListInit(&pClient->listEvents); 487 RTListInit(&pClient->listContexts); 385 488 386 489 return VINF_SUCCESS; … … 389 492 void vboxHostChannelClientDisconnect(VBOXHOSTCHCLIENT *pClient) 390 493 { 494 /* Clear the list of contexts. */ 495 int rc = vboxHostChannelLock(); 496 if (RT_SUCCESS(rc)) 497 { 498 VBOXHOSTCHCALLBACKCTX *pIter; 499 RTListForEach(&pClient->listContexts, pIter, VBOXHOSTCHCALLBACKCTX, nodeClient) 500 { 501 pIter->pClient = NULL; 502 } 503 504 vboxHostChannelUnlock(); 505 } 506 391 507 /* If there are attached channels, detach them. */ 392 508 VBOXHOSTCHINSTANCE *pIter; … … 418 534 if (RT_SUCCESS(rc)) 419 535 { 420 void *pvChannel = NULL; 421 rc = pProvider->iface.HostChannelAttach(pProvider->iface.pvProvider, 422 &pvChannel, 423 u32Flags, 424 &g_callbacks, pClient); 536 VBOXHOSTCHCALLBACKCTX *pCallbackCtx = NULL; 537 rc = vhcCallbackCtxCreate(pClient, &pCallbackCtx); 538 425 539 if (RT_SUCCESS(rc)) 426 540 { 427 vhcProviderAddRef(pProvider); 428 pInstance->pProvider = pProvider; 429 430 pInstance->pClient = pClient; 431 pInstance->pvChannel = pvChannel; 432 433 vhcInstanceAddRef(pInstance); /* Referenced by the list client's channels. */ 434 RTListAppend(&pClient->listChannels, &pInstance->nodeClient); 435 436 vhcInstanceAddRef(pInstance); /* Referenced by the list of provider's channels. */ 437 RTListAppend(&pProvider->listChannels, &pInstance->nodeProvider); 438 439 *pu32Handle = pInstance->u32Handle; 440 441 HOSTCHLOG(("HostChannel: Attach: (%d) handle %d\n", pClient->u32ClientID, pInstance->u32Handle)); 541 void *pvChannel = NULL; 542 rc = pProvider->iface.HostChannelAttach(pProvider->iface.pvProvider, 543 &pvChannel, 544 u32Flags, 545 &g_callbacks, pCallbackCtx); 546 547 if (RT_SUCCESS(rc)) 548 { 549 vhcProviderAddRef(pProvider); 550 pInstance->pProvider = pProvider; 551 552 pInstance->pClient = pClient; 553 pInstance->pvChannel = pvChannel; 554 555 vhcInstanceAddRef(pInstance); /* Referenced by the list client's channels. */ 556 RTListAppend(&pClient->listChannels, &pInstance->nodeClient); 557 558 vhcInstanceAddRef(pInstance); /* Referenced by the list of provider's channels. */ 559 RTListAppend(&pProvider->listChannels, &pInstance->nodeProvider); 560 561 *pu32Handle = pInstance->u32Handle; 562 563 HOSTCHLOG(("HostChannel: Attach: (%d) handle %d\n", pClient->u32ClientID, pInstance->u32Handle)); 564 } 565 566 if (RT_FAILURE(rc)) 567 { 568 vhcCallbackCtxDelete(pCallbackCtx); 569 } 442 570 } 443 571 … … 626 754 } 627 755 756 /* @thread provider */ 628 757 static DECLCALLBACK(void) HostChannelCallbackEvent(void *pvCallbacks, void *pvChannel, 629 758 uint32_t u32Id, const void *pvEvent, uint32_t cbEvent) 630 759 { 631 VBOXHOSTCHCLIENT *pClient = (VBOXHOSTCHCLIENT *)pvCallbacks; 760 VBOXHOSTCHCALLBACKCTX *pCallbackCtx = (VBOXHOSTCHCALLBACKCTX *)pvCallbacks; 761 762 int rc = vboxHostChannelLock(); 763 if (RT_FAILURE(rc)) 764 { 765 return; 766 } 767 768 /* Check that the structure is still associated with a client. 769 * The client can disconnect and will be invalid. 770 */ 771 VBOXHOSTCHCLIENT *pClient = pCallbackCtx->pClient; 772 773 if (pClient == NULL) 774 { 775 vboxHostChannelUnlock(); 776 777 HOSTCHLOG(("HostChannel: CallbackEvent[%p]: client gone.\n")); 778 779 /* The client does not exist anymore, skip the event. */ 780 return; 781 } 782 783 bool fFound = false; 784 785 VBOXHOSTCHCALLBACKCTX *pIter; 786 RTListForEach(&pClient->listContexts, pIter, VBOXHOSTCHCALLBACKCTX, nodeClient) 787 { 788 if (pIter == pCallbackCtx) 789 { 790 fFound = true; 791 break; 792 } 793 } 794 795 if (!fFound) 796 { 797 AssertFailed(); 798 799 vboxHostChannelUnlock(); 800 801 HOSTCHLOG(("HostChannel: CallbackEvent[%p]: client does not have the context.\n")); 802 803 /* The context is not in the list of contexts. Skip the event. */ 804 return; 805 } 632 806 633 807 VBOXHOSTCHINSTANCE *pInstance = vhcInstanceFindByChannelPtr(pClient, pvChannel); 634 808 635 HOSTCHLOG(("HostChannel: CallbackEvent : (%d) instance %p\n",636 pC lient->u32ClientID, pInstance));809 HOSTCHLOG(("HostChannel: CallbackEvent[%p]: (%d) instance %p\n", 810 pCallbackCtx, pClient->u32ClientID, pInstance)); 637 811 638 812 if (!pInstance) 639 813 { 814 vboxHostChannelUnlock(); 815 640 816 #ifdef DEBUG_sunlover 641 817 AssertFailed(); … … 644 820 } 645 821 646 int rc = vboxHostChannelLock();647 if (RT_FAILURE(rc))648 {649 return;650 }651 652 822 uint32_t u32ChannelHandle = pInstance->u32Handle; 653 823 654 824 HOSTCHLOG(("HostChannel: CallbackEvent: (%d) handle %d, async %d, cbEvent %d\n", 655 825 pClient->u32ClientID, u32ChannelHandle, pClient->fAsync, cbEvent)); 656 826 657 827 /* Check whether the event is waited. */ … … 697 867 698 868 vboxHostChannelUnlock(); 869 } 870 871 static DECLCALLBACK(void) HostChannelCallbackDeleted(void *pvCallbacks, void *pvChannel) 872 { 873 vhcCallbackCtxDelete((VBOXHOSTCHCALLBACKCTX *)pvCallbacks); 699 874 } 700 875 -
trunk/src/VBox/HostServices/HostChannel/HostChannel.h
r43462 r43785 45 45 RTLISTANCHOR listChannels; 46 46 uint32_t volatile u32HandleSrc; 47 48 RTLISTANCHOR listContexts; /* Callback contexts. */ 47 49 48 50 RTLISTANCHOR listEvents;
Note:
See TracChangeset
for help on using the changeset viewer.