Changeset 39312 in vbox for trunk/src/VBox/HostServices/GuestControl/service.cpp
- Timestamp:
- Nov 15, 2011 2:40:49 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/GuestControl/service.cpp
r38133 r39312 27 27 * - Client: A client (e.g. VBoxService) running inside the guest OS waiting for 28 28 * new host commands to perform. There can be multiple clients connected 29 * to a service. A client is represented by itsHGCM client ID.29 * to this service. A client is represented by its unique HGCM client ID. 30 30 * - Context ID: An (almost) unique ID automatically generated on the host (Main API) 31 31 * to not only distinguish clients but individual requests. Because … … 285 285 int clientConnect(uint32_t u32ClientID, void *pvClient); 286 286 int clientDisconnect(uint32_t u32ClientID, void *pvClient); 287 int sendHostCmdToGuest(HostCmd *pCmd, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);287 int assignHostCmdToGuest(HostCmd *pCmd, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 288 288 int retrieveNextHostCmd(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 289 int cancelHostCmd(uint32_t u32ContextID); 289 290 int cancelPendingWaits(uint32_t u32ClientID); 290 291 int notifyHost(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); … … 492 493 int Service::clientDisconnect(uint32_t u32ClientID, void *pvClient) 493 494 { 494 LogFlowFunc(("Client (%ld) disconnected\n", u32ClientID)); 495 LogFlowFunc(("Client (ID=%u, %u clients total) disconnected\n", 496 u32ClientID, mNumClients)); 495 497 Assert(mNumClients > 0); 496 498 mNumClients--; 499 500 /* If this was the last connected (guest) client we need to 501 * unblock all eventually queued up (waiting) host calls. */ 502 bool fAllClientsDisconnected = mNumClients == 0; 503 if (fAllClientsDisconnected) 504 LogFlowFunc(("No connected clients left, notifying all queued up callbacks\n")); 497 505 498 506 /* … … 516 524 && RT_SUCCESS(rc)) 517 525 { 518 if (it->mClientID == u32ClientID) 526 /* 527 * Unblock/call back all queued items of the specified client 528 * or for all items in case there is no waiting client around 529 * anymore. 530 */ 531 if ( it->mClientID == u32ClientID 532 || fAllClientsDisconnected) 519 533 { 520 534 std::list< uint32_t >::iterator itContext = it->mContextList.begin(); 521 while ( itContext != it->mContextList.end() 522 && RT_SUCCESS(rc)) 535 while (itContext != it->mContextList.end()) 523 536 { 524 LogFlowFunc(("Notifying host context %u of disconnect ...\n", (*itContext)));537 uint32_t uContextID = (*itContext); 525 538 526 539 /* … … 528 541 * around and need to be cleaned up (canceling waits etc). 529 542 */ 530 if (mpfnHostCallback) 543 LogFlowFunc(("Notifying CID=%u of disconnect ...\n", uContextID)); 544 rc = cancelHostCmd(uContextID); 545 if (RT_FAILURE(rc)) 531 546 { 532 CALLBACKDATACLIENTDISCONNECTED data; 533 data.hdr.u32Magic = CALLBACKDATAMAGIC_CLIENT_DISCONNECTED; 534 data.hdr.u32ContextID = (*itContext); 535 rc = mpfnHostCallback(mpvHostData, GUEST_DISCONNECTED, (void *)(&data), sizeof(data)); 536 if (RT_FAILURE(rc)) 537 LogFlowFunc(("Notification of host context %u failed with %Rrc\n", rc)); 547 LogFlowFunc(("Cancelling of CID=%u failed with rc=%Rrc\n", 548 uContextID, rc)); 549 /* Keep going. */ 538 550 } 551 539 552 itContext++; 540 553 } … … 544 557 it++; 545 558 } 559 560 if (fAllClientsDisconnected) 561 { 562 /* 563 * If all clients disconnected we also need to make sure that all buffered 564 * host commands need to be notified, because Main is waiting a notification 565 * via a (multi stage) progress object. 566 */ 567 HostCmdListIter it; 568 for (it = mHostCmds.begin(); it != mHostCmds.end(); it++) 569 { 570 rc = cancelHostCmd(it->mContextID); 571 if (RT_FAILURE(rc)) 572 { 573 LogFlowFunc(("Cancelling of buffered CID=%u failed with rc=%Rrc\n", 574 it->mContextID, rc)); 575 /* Keep going. */ 576 } 577 578 paramBufferFree(&it->mParmBuf); 579 } 580 581 mHostCmds.clear(); 582 } 583 546 584 return rc; 547 585 } 548 586 549 587 /** 550 * Sends a specified host command to a client.588 * Assigns a specified host command to a client. 551 589 * 552 590 * @return IPRT status code. … … 556 594 * @param paParms Array of parameters. 557 595 */ 558 int Service:: sendHostCmdToGuest(HostCmd *pCmd, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[])559 { 560 AssertPtr (pCmd);596 int Service::assignHostCmdToGuest(HostCmd *pCmd, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 597 { 598 AssertPtrReturn(pCmd, VERR_INVALID_POINTER); 561 599 int rc; 562 600 563 /* Sufficient parameter space? */ 601 /* Does the current host command need more parameter space which 602 * the client does not provide yet? */ 564 603 if (pCmd->mParmBuf.uParmCount > cParms) 565 604 { … … 578 617 rc = paramBufferAssign(&pCmd->mParmBuf, cParms, paParms); 579 618 } 619 620 LogFlowFunc(("Returned with rc=%Rrc\n", rc)); 580 621 return rc; 581 622 } … … 632 673 */ 633 674 HostCmd curCmd = mHostCmds.front(); 634 rc = sendHostCmdToGuest(&curCmd, callHandle, cParms, paParms);675 rc = assignHostCmdToGuest(&curCmd, callHandle, cParms, paParms); 635 676 if (RT_SUCCESS(rc)) 636 677 { … … 658 699 else 659 700 { 660 /* Client did not understand the message or something else weird happened. Try again one661 * more time and drop it if it didn't get handled then. */701 /* Client did not understand the message or something else weird happened. Try again one 702 * more time and drop it if it didn't get handled then. */ 662 703 if (++curCmd.mTries > 1) 663 704 { … … 668 709 } 669 710 return rc; 711 } 712 713 /** 714 * Cancels a buffered host command to unblock waits on Main side 715 * (via (multi stage) progress objects. 716 * 717 * @return IPRT status code. 718 * @param u32ContextID Context ID of host command to cancel. 719 */ 720 int Service::cancelHostCmd(uint32_t u32ContextID) 721 { 722 AssertReturn(u32ContextID, VERR_INVALID_PARAMETER); 723 Assert(mpfnHostCallback); 724 725 LogFlowFunc(("Cancelling CID=%u ...\n", u32ContextID)); 726 727 CALLBACKDATACLIENTDISCONNECTED data; 728 data.hdr.u32Magic = CALLBACKDATAMAGIC_CLIENT_DISCONNECTED; 729 data.hdr.u32ContextID = u32ContextID; 730 731 AssertPtr(mpfnHostCallback); 732 AssertPtr(mpvHostData); 733 734 return mpfnHostCallback(mpvHostData, GUEST_DISCONNECTED, (void *)(&data), sizeof(data)); 670 735 } 671 736 … … 789 854 HostCmd newCmd; 790 855 int rc = paramBufferAllocate(&newCmd.mParmBuf, eFunction, cParms, paParms); 791 if (RT_SUCCESS(rc) && cParms) 856 if ( RT_SUCCESS(rc) 857 && cParms) /* Make sure we at least get one parameter (that is, the context ID). */ 792 858 { 793 859 /* … … 798 864 Assert(newCmd.mContextID > 0); 799 865 } 866 else if (!cParms) 867 rc = VERR_INVALID_PARAMETER; 800 868 801 869 if (RT_SUCCESS(rc)) 802 870 { 871 LogFlowFunc(("Handling host command CID = %u\n", 872 newCmd.mContextID)); 873 803 874 bool fProcessed = false; 804 875 … … 807 878 { 808 879 ClientWaiter guest = mClientWaiterList.front(); 809 rc = sendHostCmdToGuest(&newCmd,810 guest.mHandle, guest.mNumParms, guest.mParms);880 rc = assignHostCmdToGuest(&newCmd, 881 guest.mHandle, guest.mNumParms, guest.mParms); 811 882 812 883 /* In any case the client did something, so wake up and remove from list. */ … … 825 896 else /* If command was understood by the client, free and remove from host commands list. */ 826 897 { 898 LogFlowFunc(("Host command CID = %u processed with rc=%Rrc\n", 899 newCmd.mContextID, rc)); 900 827 901 paramBufferFree(&newCmd.mParmBuf); 828 fProcessed = true;829 902 } 830 903 } 831 904 832 /* If not processed, buffer it ... */833 905 if (!fProcessed) 834 906 { 907 LogFlowFunc(("Buffering host command CID = %u (rc=%Rrc)\n", 908 newCmd.mContextID, rc)); 909 835 910 mHostCmds.push_back(newCmd); 836 #if 0 837 /* Limit list size by deleting oldest element. */ 838 if (mHostCmds.size() > 256) /** @todo Use a define! */ 839 mHostCmds.pop_front(); 840 #endif 841 } 842 } 911 } 912 } 913 914 LogFlowFunc(("Returned with rc=%Rrc\n", rc)); 843 915 return rc; 844 916 } … … 858 930 { 859 931 int rc = VINF_SUCCESS; 860 LogFlowFunc(("u32ClientID = % d, fn = %d, cParms = %d, pparms = %d\n",932 LogFlowFunc(("u32ClientID = %u, fn = %u, cParms = %u, paParms = 0x%p\n", 861 933 u32ClientID, eFunction, cParms, paParms)); 862 934 try … … 913 985 { 914 986 int rc = VERR_NOT_SUPPORTED; 915 LogFlowFunc(("fn = % d, cParms = %d, pparms = %d\n",987 LogFlowFunc(("fn = %u, cParms = %u, paParms = 0x%p\n", 916 988 eFunction, cParms, paParms)); 917 989 try … … 930 1002 int Service::uninit() 931 1003 { 932 /* Free allocated buffered host commands. */ 933 HostCmdListIter it; 934 for (it = mHostCmds.begin(); it != mHostCmds.end(); it++) 935 paramBufferFree(&it->mParmBuf); 936 mHostCmds.clear(); 1004 Assert(mHostCmds.empty()); 937 1005 938 1006 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.