VirtualBox

Ignore:
Timestamp:
Nov 29, 2018 12:42:18 AM (6 years ago)
Author:
vboxsync
Message:

VBoxGuestCtrlSvc: More cleanups. bugref:9313

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/GuestControl/service.cpp

    r75799 r75800  
    447447typedef struct ClientState
    448448{
     449    PVBOXHGCMSVCHELPERS mSvcHelpers;
     450    /** The client's ID. */
     451    uint32_t mID;
     452    /** Host command list to process. */
     453    HostCmdList mHostCmdList;
     454    /** Pending client call (GUEST_MSG_PEEK_WAIT or GUEST_MSG_WAIT), zero if none pending.
     455     *
     456     * This means the client waits for a new host command to reply and won't return
     457     * from the waiting call until a new host command is available. */
     458    guestControl::eGuestFn mIsPending;
     459    /** The client's pending connection. */
     460    ClientConnection    mPendingCon;
     461    /** Set if we've got a pending wait cancel. */
     462    bool                m_fPendingCancel;
     463    /** Set if master. */
     464    bool                m_fIsMaster;
     465    /** The session ID for this client, UINT32_MAX if not set or master. */
     466    uint32_t            m_idSession;
     467
     468
    449469    ClientState(void)
    450470        : mSvcHelpers(NULL)
    451471        , mID(0)
    452472        , mIsPending((guestControl::eGuestFn)0)
     473        , m_fPendingCancel(false)
    453474        , m_fIsMaster(false)
    454475        , m_idSession(UINT32_MAX)
     
    462483        , mID(idClient)
    463484        , mIsPending((guestControl::eGuestFn)0)
     485        , m_fPendingCancel(false)
    464486        , m_fIsMaster(false)
    465487        , m_idSession(UINT32_MAX)
     
    470492
    471493    /**
     494     * Used by for Service::hostProcessCommand().
     495     */
     496    int EnqueueCommand(HostCommand *pHostCmd)
     497    {
     498        AssertPtrReturn(pHostCmd, VERR_INVALID_POINTER);
     499
     500        try
     501        {
     502            mHostCmdList.push_back(pHostCmd);
     503        }
     504        catch (std::bad_alloc &)
     505        {
     506            return VERR_NO_MEMORY;
     507        }
     508
     509        pHostCmd->Retain();
     510        return VINF_SUCCESS;
     511    }
     512
     513    /**
     514     * Used by for Service::hostProcessCommand().
     515     *
     516     * @note This wakes up both GUEST_MSG_WAIT and GUEST_MSG_PEEK_WAIT sleepers.
     517     */
     518    int Wakeup(void)
     519    {
     520        int rc = VINF_NO_CHANGE;
     521
     522        if (mIsPending != 0)
     523        {
     524            LogFlowFunc(("[Client %RU32] Waking up ...\n", mID));
     525
     526            rc = VINF_SUCCESS;
     527
     528            HostCmdListIter curCmd = mHostCmdList.begin();
     529            if (curCmd != mHostCmdList.end())
     530            {
     531                HostCommand *pHostCmd = (*curCmd);
     532                AssertPtrReturn(pHostCmd, VERR_INVALID_POINTER);
     533
     534                LogFlowThisFunc(("[Client %RU32] Current host command is %RU32 (CID=%RU32, cParms=%RU32, m_cRefs=%RU32)\n",
     535                                 mID, pHostCmd->mMsgType, pHostCmd->m_idContext, pHostCmd->mParmCount, pHostCmd->m_cRefs));
     536
     537                if (mIsPending == GUEST_MSG_PEEK_WAIT)
     538                {
     539                    HGCMSvcSetU32(&mPendingCon.mParms[0], pHostCmd->mMsgType);
     540                    HGCMSvcSetU32(&mPendingCon.mParms[1], pHostCmd->mParmCount);
     541                    for (uint32_t i = pHostCmd->mParmCount; i >= 2; i--)
     542                        switch (pHostCmd->mpParms[i - 2].type)
     543                        {
     544                            case VBOX_HGCM_SVC_PARM_32BIT: mPendingCon.mParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break;
     545                            case VBOX_HGCM_SVC_PARM_64BIT: mPendingCon.mParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break;
     546                            case VBOX_HGCM_SVC_PARM_PTR:   mPendingCon.mParms[i].u.uint32 = pHostCmd->mpParms[i - 2].u.pointer.size; break;
     547                        }
     548
     549                    rc = mSvcHelpers->pfnCallComplete(mPendingCon.mHandle, VINF_SUCCESS);
     550                    mIsPending = (guestControl::eGuestFn)0;
     551                }
     552                else if (mIsPending == GUEST_MSG_WAIT)
     553                    rc = OldRun(&mPendingCon, pHostCmd);
     554                else
     555                    AssertMsgFailed(("mIsPending=%d\n", mIsPending));
     556            }
     557            else
     558                AssertMsgFailed(("Waking up client ID=%RU32 with no host command in queue is a bad idea\n", mID));
     559
     560            return rc;
     561        }
     562
     563        return VINF_NO_CHANGE;
     564    }
     565
     566    /**
     567     * Used by Service::call() to handle GUEST_MSG_CANCEL.
     568     *
     569     * @note This cancels both GUEST_MSG_WAIT and GUEST_MSG_PEEK_WAIT sleepers.
     570     */
     571    int CancelWaiting()
     572    {
     573        LogFlowFunc(("[Client %RU32] Cancelling waiting thread, isPending=%d, pendingNumParms=%RU32, m_idSession=%x\n",
     574                     mID, mIsPending, mPendingCon.mNumParms, m_idSession));
     575
     576        /*
     577         * The PEEK call is simple: At least two parameters, all set to zero before sleeping.
     578         */
     579        int rcComplete;
     580        if (mIsPending == GUEST_MSG_PEEK_WAIT)
     581        {
     582            HGCMSvcSetU32(&mPendingCon.mParms[0], HOST_CANCEL_PENDING_WAITS);
     583            rcComplete = VINF_TRY_AGAIN;
     584        }
     585        /*
     586         * The GUEST_MSG_WAIT call is complicated, though we're generally here
     587         * to wake up someone who is peeking and have two parameters.  If there
     588         * aren't two parameters, fail the call.
     589         */
     590        else if (mIsPending != 0)
     591        {
     592            Assert(mIsPending == GUEST_MSG_WAIT);
     593            if (mPendingCon.mNumParms > 0)
     594                HGCMSvcSetU32(&mPendingCon.mParms[0], HOST_CANCEL_PENDING_WAITS);
     595            if (mPendingCon.mNumParms > 1)
     596                HGCMSvcSetU32(&mPendingCon.mParms[1], 0);
     597            rcComplete = mPendingCon.mNumParms == 2 ? VINF_SUCCESS : VERR_TRY_AGAIN;
     598        }
     599        /*
     600         * If nobody is waiting, flag the next wait call as cancelled.
     601         */
     602        else
     603        {
     604            m_fPendingCancel = true;
     605            return VINF_SUCCESS;
     606        }
     607
     608        mSvcHelpers->pfnCallComplete(mPendingCon.mHandle, rcComplete);
     609        mIsPending       = (guestControl::eGuestFn)0;
     610        m_fPendingCancel = false;
     611        return VINF_SUCCESS;
     612    }
     613
     614
     615    /** @name The GUEST_MSG_WAIT state and helpers.
     616     *
     617     * @note Don't try understand this, it is certificable!
     618     *
     619     * @{
     620     */
     621
     622    /** Last (most recent) rc after handling the host command. */
     623    int mHostCmdRc;
     624    /** How many GUEST_MSG_WAIT calls the client has issued to retrieve one command.
     625     *
     626     * This is used as a heuristic to remove a message that the client appears not
     627     * to be able to successfully retrieve.  */
     628    uint32_t mHostCmdTries;
     629    /** Number of times we've peeked at a pending message.
     630     *
     631     * This is necessary for being compatible with older Guest Additions.  In case
     632     * there are commands which only have two (2) parameters and therefore would fit
     633     * into the GUEST_MSG_WAIT reply immediately, we now can make sure that the
     634     * client first gets back the GUEST_MSG_WAIT results first.
     635     */
     636    uint32_t mPeekCount;
     637
     638    /**
    472639     * Ditches the first host command and crazy GUEST_MSG_WAIT state.
    473      */
    474     void DitchFirstHostCmd()
     640     *
     641     * @note Only used by GUEST_MSG_WAIT scenarios.
     642     */
     643    void OldDitchFirstHostCmd()
    475644    {
    476645        Assert(!mHostCmdList.empty());
     
    484653        mHostCmdTries = 0;
    485654        mPeekCount    = 0;
    486     }
    487 
    488     int EnqueueCommand(HostCommand *pHostCmd)
    489     {
    490         AssertPtrReturn(pHostCmd, VERR_INVALID_POINTER);
    491 
    492         try
    493         {
    494             mHostCmdList.push_back(pHostCmd);
    495         }
    496         catch (std::bad_alloc &)
    497         {
    498             return VERR_NO_MEMORY;
    499         }
    500 
    501         pHostCmd->Retain();
    502         return VINF_SUCCESS;
    503     }
    504 
    505     /**
    506      * Set to indicate that a client call (GUEST_MSG_WAIT) is pending.
    507      *
    508      * @note Only used by GUEST_MSG_WAIT scenarios.
    509      */
    510     int OldSetPending(const ClientConnection *pConnection)
    511     {
    512         AssertPtrReturn(pConnection, VERR_INVALID_POINTER);
    513 
    514         if (mIsPending != 0)
    515         {
    516             LogFlowFunc(("[Client %RU32] Already is in pending mode\n", mID));
    517 
    518             /*
    519              * Signal that we don't and can't return yet.
    520              */
    521             return VINF_HGCM_ASYNC_EXECUTE;
    522         }
    523 
    524         if (mHostCmdList.empty())
    525         {
    526             AssertMsg(mIsPending == 0, ("Client ID=%RU32 already is pending but tried to receive a new host command\n", mID));
    527 
    528             mPendingCon.mHandle   = pConnection->mHandle;
    529             mPendingCon.mNumParms = pConnection->mNumParms;
    530             mPendingCon.mParms    = pConnection->mParms;
    531 
    532             mIsPending = GUEST_MSG_WAIT;
    533 
    534             LogFlowFunc(("[Client %RU32] Is now in pending mode\n", mID));
    535 
    536             /*
    537              * Signal that we don't and can't return yet.
    538              */
    539             return VINF_HGCM_ASYNC_EXECUTE;
    540         }
    541 
    542         /*
    543          * Signal that there already is a connection pending.
    544          * Shouldn't happen in daily usage.
    545          */
    546         AssertMsgFailed(("Client already has a connection pending\n"));
    547         return VERR_SIGNAL_PENDING;
    548655    }
    549656
     
    605712        {
    606713            Assert(*mHostCmdList.begin() == pHostCmd);
    607             DitchFirstHostCmd();
     714            OldDitchFirstHostCmd();
    608715        }
    609716
     
    613720
    614721    /**
     722     * Set to indicate that a client call (GUEST_MSG_WAIT) is pending.
     723     *
    615724     * @note Only used by GUEST_MSG_WAIT scenarios.
    616725     */
     726    int OldSetPending(const ClientConnection *pConnection)
     727    {
     728        AssertPtrReturn(pConnection, VERR_INVALID_POINTER);
     729
     730        if (mIsPending != 0)
     731        {
     732            LogFlowFunc(("[Client %RU32] Already is in pending mode\n", mID));
     733
     734            /*
     735             * Signal that we don't and can't return yet.
     736             */
     737            return VINF_HGCM_ASYNC_EXECUTE;
     738        }
     739
     740        if (mHostCmdList.empty())
     741        {
     742            AssertMsg(mIsPending == 0, ("Client ID=%RU32 already is pending but tried to receive a new host command\n", mID));
     743
     744            mPendingCon.mHandle   = pConnection->mHandle;
     745            mPendingCon.mNumParms = pConnection->mNumParms;
     746            mPendingCon.mParms    = pConnection->mParms;
     747
     748            mIsPending = GUEST_MSG_WAIT;
     749
     750            LogFlowFunc(("[Client %RU32] Is now in pending mode\n", mID));
     751
     752            /*
     753             * Signal that we don't and can't return yet.
     754             */
     755            return VINF_HGCM_ASYNC_EXECUTE;
     756        }
     757
     758        /*
     759         * Signal that there already is a connection pending.
     760         * Shouldn't happen in daily usage.
     761         */
     762        AssertMsgFailed(("Client already has a connection pending\n"));
     763        return VERR_SIGNAL_PENDING;
     764    }
     765
     766    /**
     767     * @note Only used by GUEST_MSG_WAIT scenarios.
     768     */
    617769    int OldRunCurrent(const ClientConnection *pConnection)
    618770    {
    619771        AssertPtrReturn(pConnection, VERR_INVALID_POINTER);
    620772
    621         int rc;
     773        /*
     774         * If the host command list is empty, the request must wait for one to be posted.
     775         */
    622776        if (mHostCmdList.empty())
    623777        {
    624             rc = OldSetPending(pConnection);
    625         }
    626         else
    627         {
    628             AssertMsgReturn(mIsPending == 0,
    629                             ("Client ID=%RU32 still is in pending mode; can't use another connection\n", mID), VERR_INVALID_PARAMETER);
    630 
    631             HostCmdListIter curCmd = mHostCmdList.begin();
    632             Assert(curCmd != mHostCmdList.end());
    633             HostCommand *pHostCmd = *curCmd;
    634             AssertPtrReturn(pHostCmd, VERR_INVALID_POINTER);
    635 
    636             rc = OldRun(pConnection, pHostCmd);
    637         }
    638 
    639         return rc;
    640     }
    641 
    642     /**
    643      * Used by for Service::hostProcessCommand().
    644      *
    645      * @note This wakes up both GUEST_MSG_WAIT and GUEST_MSG_PEEK_WAIT sleepers.
    646      */
    647     int Wakeup(void)
    648     {
    649         int rc = VINF_NO_CHANGE;
    650 
    651         if (mIsPending != 0)
    652         {
    653             LogFlowFunc(("[Client %RU32] Waking up ...\n", mID));
    654 
    655             rc = VINF_SUCCESS;
    656 
    657             HostCmdListIter curCmd = mHostCmdList.begin();
    658             if (curCmd != mHostCmdList.end())
     778            if (!m_fPendingCancel)
    659779            {
    660                 HostCommand *pHostCmd = (*curCmd);
    661                 AssertPtrReturn(pHostCmd, VERR_INVALID_POINTER);
    662 
    663                 LogFlowThisFunc(("[Client %RU32] Current host command is %RU32 (CID=%RU32, cParms=%RU32, m_cRefs=%RU32)\n",
    664                                  mID, pHostCmd->mMsgType, pHostCmd->m_idContext, pHostCmd->mParmCount, pHostCmd->m_cRefs));
    665 
    666                 if (mIsPending == GUEST_MSG_PEEK_WAIT)
    667                 {
    668                     HGCMSvcSetU32(&mPendingCon.mParms[0], pHostCmd->mMsgType);
    669                     HGCMSvcSetU32(&mPendingCon.mParms[1], pHostCmd->mParmCount);
    670                     for (uint32_t i = pHostCmd->mParmCount; i >= 2; i--)
    671                         switch (pHostCmd->mpParms[i - 2].type)
    672                         {
    673                             case VBOX_HGCM_SVC_PARM_32BIT: mPendingCon.mParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break;
    674                             case VBOX_HGCM_SVC_PARM_64BIT: mPendingCon.mParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break;
    675                             case VBOX_HGCM_SVC_PARM_PTR:   mPendingCon.mParms[i].u.uint32 = pHostCmd->mpParms[i - 2].u.pointer.size; break;
    676                         }
    677 
    678                     rc = mSvcHelpers->pfnCallComplete(mPendingCon.mHandle, VINF_SUCCESS);
    679                     mIsPending = (guestControl::eGuestFn)0;
    680                 }
    681                 else if (mIsPending == GUEST_MSG_WAIT)
    682                     rc = OldRun(&mPendingCon, pHostCmd);
    683                 else
    684                     AssertMsgFailed(("mIsPending=%d\n", mIsPending));
     780                /* Go to sleep. */
     781                ASSERT_GUEST_RETURN(mIsPending == 0, VERR_WRONG_ORDER);
     782                mPendingCon = *pConnection;
     783                mIsPending  = GUEST_MSG_WAIT;
     784                LogFlowFunc(("[Client %RU32] Is now in pending mode\n", mID));
     785                return VINF_HGCM_ASYNC_EXECUTE;
    685786            }
    686             else
    687                 AssertMsgFailed(("Waking up client ID=%RU32 with no host command in queue is a bad idea\n", mID));
    688 
    689             return rc;
    690         }
    691 
    692         return VINF_NO_CHANGE;
    693     }
    694 
    695     /**
    696      * Used by Service::call() to handle GUEST_MSG_CANCEL.
    697      *
    698      * @note This cancels both GUEST_MSG_WAIT and GUEST_MSG_PEEK_WAIT sleepers.
    699      */
    700     int CancelWaiting()
    701     {
    702         LogFlowFunc(("[Client %RU32] Cancelling waiting thread, isPending=%d, pendingNumParms=%RU32, m_idSession=%x\n",
    703                      mID, mIsPending, mPendingCon.mNumParms, m_idSession));
    704 /** @todo r=bird: This must be made sticky if no pending call, i.e. next wait
    705  * call must return immediately. otherwise there will be a race and
    706  * occational long VBoxService shutdown times. */
    707 
    708         int rc;
    709         if (   mIsPending != 0
    710             && mPendingCon.mNumParms >= 2)
    711         {
    712             HGCMSvcSetU32(&mPendingCon.mParms[0], HOST_CANCEL_PENDING_WAITS); /* Message ID. */
    713             HGCMSvcSetU32(&mPendingCon.mParms[1], 0);                         /* Required parameters for message. */
    714 
    715             AssertPtr(mSvcHelpers);
    716             mSvcHelpers->pfnCallComplete(mPendingCon.mHandle, mIsPending == GUEST_MSG_WAIT ? VINF_SUCCESS : VINF_TRY_AGAIN);
    717 
    718             mIsPending = (guestControl::eGuestFn)0;
    719 
    720             rc = VINF_SUCCESS;
    721         }
    722         else if (mPendingCon.mNumParms < 2)
    723             rc = VERR_BUFFER_OVERFLOW;
    724         else /** @todo Enqueue command instead of dropping? */
    725             rc = VERR_WRONG_ORDER;
    726 
    727         return rc;
     787
     788            /* Wait was cancelled. */
     789            m_fPendingCancel = false;
     790            if (pConnection->mNumParms > 0)
     791                HGCMSvcSetU32(&pConnection->mParms[0], HOST_CANCEL_PENDING_WAITS);
     792            if (pConnection->mNumParms > 1)
     793                HGCMSvcSetU32(&pConnection->mParms[1], 0);
     794            return pConnection->mNumParms == 2 ? VINF_SUCCESS : VERR_TRY_AGAIN;
     795        }
     796
     797        /*
     798         * Return first host command.
     799         */
     800        AssertMsgReturn(mIsPending == 0,
     801                        ("Client ID=%RU32 still is in pending mode; can't use another connection\n", mID), VERR_INVALID_PARAMETER);
     802
     803        HostCmdListIter curCmd = mHostCmdList.begin();
     804        Assert(curCmd != mHostCmdList.end());
     805        HostCommand *pHostCmd = *curCmd;
     806        AssertPtrReturn(pHostCmd, VERR_INVALID_POINTER);
     807
     808        return OldRun(pConnection, pHostCmd);
    728809    }
    729810
     
    795876    }
    796877
    797     PVBOXHGCMSVCHELPERS mSvcHelpers;
    798     /** The client's ID. */
    799     uint32_t mID;
    800     /** Host command list to process. */
    801     HostCmdList mHostCmdList;
    802     /** Pending client call (GUEST_MSG_PEEK_WAIT or GUEST_MSG_WAIT), zero if none pending.
    803      *
    804      * This means the client waits for a new host command to reply and won't return
    805      * from the waiting call until a new host command is available. */
    806     guestControl::eGuestFn mIsPending;
    807     /** The client's pending connection. */
    808     ClientConnection    mPendingCon;
    809     /** Set if master. */
    810     bool                m_fIsMaster;
    811     /** The session ID for this client, UINT32_MAX if not set or master. */
    812     uint32_t            m_idSession;
    813 
    814     /** @name The GUEST_MSG_WAIT state.
    815      * @note Don't try understand this, it is certificable!
    816      * @{ */
    817     /** Last (most recent) rc after handling the host command. */
    818     int mHostCmdRc;
    819     /** How many GUEST_MSG_WAIT calls the client has issued to retrieve one command.
    820      *
    821      * This is used as a heuristic to remove a message that the client appears not
    822      * to be able to successfully retrieve.  */
    823     uint32_t mHostCmdTries;
    824     /** Number of times we've peeked at a pending message.
    825      *
    826      * This is necessary for being compatible with older Guest Additions.  In case
    827      * there are commands which only have two (2) parameters and therefore would fit
    828      * into the GUEST_MSG_WAIT reply immediately, we now can make sure that the
    829      * client first gets back the GUEST_MSG_WAIT results first.
    830      */
    831     uint32_t mPeekCount;
    832878    /** @} */
    833 
    834879} ClientState;
    835880typedef std::map< uint32_t, ClientState > ClientStateMap;
     
    895940    }
    896941
    897     /**
    898      * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnUnload}
    899      * Simply deletes the GstCtrlService object
    900      */
    901     static DECLCALLBACK(int) svcUnload(void *pvService)
    902     {
    903         AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
    904         SELF *pSelf = reinterpret_cast<SELF *>(pvService);
    905         int rc = pSelf->uninit();
    906         AssertRC(rc);
    907         if (RT_SUCCESS(rc))
    908             delete pSelf;
    909         return rc;
    910     }
    911 
    912     /**
    913      * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnConnect}
    914      * Stub implementation of pfnConnect and pfnDisconnect.
    915      */
    916     static DECLCALLBACK(int) svcConnect(void *pvService,
    917                                         uint32_t u32ClientID,
    918                                         void *pvClient,
    919                                         uint32_t fRequestor, bool fRestoring)
    920     {
    921         RT_NOREF(fRestoring);
    922         AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
    923         SELF *pSelf = reinterpret_cast<SELF *>(pvService);
    924         AssertPtrReturn(pSelf, VERR_INVALID_POINTER);
    925         return pSelf->clientConnect(u32ClientID, pvClient, fRequestor);
    926     }
    927 
    928     /**
    929      * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnConnect}
    930      * Stub implementation of pfnConnect and pfnDisconnect.
    931      */
    932     static DECLCALLBACK(int) svcDisconnect(void *pvService,
    933                                            uint32_t u32ClientID,
    934                                            void *pvClient)
    935     {
    936         AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
    937         SELF *pSelf = reinterpret_cast<SELF *>(pvService);
    938         AssertPtrReturn(pSelf, VERR_INVALID_POINTER);
    939         return pSelf->clientDisconnect(u32ClientID, pvClient);
    940     }
    941 
    942     /**
    943      * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnCall}
    944      * Wraps to the call member function
    945      */
    946     static DECLCALLBACK(void) svcCall(void * pvService,
    947                                       VBOXHGCMCALLHANDLE callHandle,
    948                                       uint32_t u32ClientID,
    949                                       void *pvClient,
    950                                       uint32_t u32Function,
    951                                       uint32_t cParms,
    952                                       VBOXHGCMSVCPARM paParms[],
    953                                       uint64_t tsArrival)
    954     {
    955         AssertLogRelReturnVoid(VALID_PTR(pvService));
    956         SELF *pSelf = reinterpret_cast<SELF *>(pvService);
    957         AssertPtrReturnVoid(pSelf);
    958         RT_NOREF_PV(tsArrival);
    959         pSelf->call(callHandle, u32ClientID, pvClient, u32Function, cParms, paParms);
    960     }
    961 
    962     /**
    963      * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnHostCall}
    964      * Wraps to the hostCall member function
    965      */
    966     static DECLCALLBACK(int) svcHostCall(void *pvService,
    967                                          uint32_t u32Function,
    968                                          uint32_t cParms,
    969                                          VBOXHGCMSVCPARM paParms[])
    970     {
    971         AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
    972         SELF *pSelf = reinterpret_cast<SELF *>(pvService);
    973         AssertPtrReturn(pSelf, VERR_INVALID_POINTER);
    974         return pSelf->hostCall(u32Function, cParms, paParms);
    975     }
    976 
    977     /**
    978      * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnRegisterExtension}
    979      * Installs a host callback for notifications of property changes.
    980      */
    981     static DECLCALLBACK(int) svcRegisterExtension(void *pvService,
    982                                                   PFNHGCMSVCEXT pfnExtension,
    983                                                   void *pvExtension)
    984     {
    985         AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
    986         SELF *pSelf = reinterpret_cast<SELF *>(pvService);
    987         AssertPtrReturn(pSelf, VERR_INVALID_POINTER);
    988         pSelf->mpfnHostCallback = pfnExtension;
    989         pSelf->mpvHostData = pvExtension;
    990         return VINF_SUCCESS;
    991     }
     942    static DECLCALLBACK(int)  svcUnload(void *pvService);
     943    static DECLCALLBACK(int)  svcConnect(void *pvService, uint32_t u32ClientID, void *pvClient,
     944                                         uint32_t fRequestor, bool fRestoring);
     945    static DECLCALLBACK(int)  svcDisconnect(void *pvService, uint32_t u32ClientID, void *pvClient);
     946    static DECLCALLBACK(void) svcCall(void *pvService, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient,
     947                                      uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[], uint64_t tsArrival);
     948    static DECLCALLBACK(int)  svcHostCall(void *pvService, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     949    static DECLCALLBACK(int)  svcRegisterExtension(void *pvService, PFNHGCMSVCEXT pfnExtension, void *pvExtension);
    992950
    993951private:
    994 
    995     int prepareExecute(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    996     int clientConnect(uint32_t u32ClientID, void *pvClient, uint32_t fRequestor);
    997     int clientDisconnect(uint32_t u32ClientID, void *pvClient);
    998 
    999952    int clientMakeMeMaster(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms);
    1000953    int clientMsgPeek(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fWait);
     
    1013966    int hostCallback(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    1014967    int hostProcessCommand(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    1015     void call(VBOXHGCMCALLHANDLE hCall, uint32_t idClient, void *pvClient, uint32_t idFunction,
    1016               uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    1017     int hostCall(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    1018     int uninit(void);
    1019968
    1020969    DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(GstCtrlService);
     
    1023972
    1024973/**
    1025  * Handles a client which just connected.
    1026  *
    1027  * @return  IPRT status code.
    1028  * @param   idClient
    1029  * @param   pvClient
    1030  * @param   fRequestor  VMMDevRequestHeader::fRequestor value, if available.
    1031  */
    1032 int GstCtrlService::clientConnect(uint32_t idClient, void *pvClient, uint32_t fRequestor)
    1033 {
    1034     RT_NOREF(pvClient);
     974 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnUnload,
     975 *  Simply deletes the GstCtrlService object}
     976 */
     977/*static*/ DECLCALLBACK(int)
     978GstCtrlService::svcUnload(void *pvService)
     979{
     980    AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
     981    SELF *pThis = reinterpret_cast<SELF *>(pvService);
     982    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     983
     984    delete pThis;
     985
     986    return VINF_SUCCESS;
     987}
     988
     989
     990
     991/**
     992 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnConnect,
     993 *  Initializes the state for a new client.}
     994 */
     995/*static*/ DECLCALLBACK(int)
     996GstCtrlService::svcConnect(void *pvService, uint32_t idClient, void *pvClient, uint32_t fRequestor, bool fRestoring)
     997{
    1035998    LogFlowFunc(("[Client %RU32] Connected\n", idClient));
    1036     AssertMsg(mClientStateMap.find(idClient) == mClientStateMap.end(),
     999
     1000    RT_NOREF(fRestoring, pvClient);
     1001    AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
     1002    SELF *pThis = reinterpret_cast<SELF *>(pvService);
     1003    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1004
     1005    AssertMsg(pThis->mClientStateMap.find(idClient) == pThis->mClientStateMap.end(),
    10371006              ("Client with ID=%RU32 already connected when it should not\n", idClient));
    10381007
     
    10421011    try
    10431012    {
    1044         mClientStateMap[idClient] = ClientState(mpHelpers, idClient);
     1013        pThis->mClientStateMap[idClient] = ClientState(pThis->mpHelpers, idClient);
    10451014    }
    10461015    catch (std::bad_alloc)
     
    10481017        return VERR_NO_MEMORY;
    10491018    }
    1050     ClientState &rClientState = mClientStateMap[idClient];
     1019    ClientState &rClientState = pThis->mClientStateMap[idClient];
    10511020
    10521021    /*
     
    10561025     */
    10571026/** @todo make picking the master more dynamic/flexible. */
    1058     if (   m_fLegacyMode
    1059         && m_idMasterClient == UINT32_MAX)
     1027    if (   pThis->m_fLegacyMode
     1028        && pThis->m_idMasterClient == UINT32_MAX)
    10601029    {
    10611030        if (   fRequestor == VMMDEV_REQUESTOR_LEGACY
     
    10631032        {
    10641033            LogFunc(("Picking %u as master for now.\n", idClient));
    1065             m_idMasterClient = idClient;
     1034            pThis->m_idMasterClient = idClient;
    10661035            rClientState.m_fIsMaster = true;
    10671036        }
     
    10731042
    10741043/**
    1075  * Handles a client which disconnected.
     1044 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnConnect,
     1045 *  Handles a client which disconnected.}
    10761046 *
    10771047 * This functiond does some internal cleanup as well as sends notifications to
    10781048 * the host so that the host can do the same (if required).
    1079  *
    1080  * @return  IPRT status code.
    1081  * @param   idClient    The client's ID of which disconnected.
    1082  * @param   pvClient    User data, not used at the moment.
    1083  */
    1084 int GstCtrlService::clientDisconnect(uint32_t idClient, void *pvClient)
     1049 */
     1050/*static*/ DECLCALLBACK(int)
     1051GstCtrlService::svcDisconnect(void *pvService, uint32_t idClient, void *pvClient)
    10851052{
    10861053    RT_NOREF(pvClient);
    1087     LogFlowFunc(("[Client %RU32] Disconnected (%zu clients total)\n", idClient, mClientStateMap.size()));
    1088 
    1089     ClientStateMapIter ItClientState = mClientStateMap.find(idClient);
    1090     AssertMsgReturn(ItClientState != mClientStateMap.end(),
     1054    AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
     1055    SELF *pThis = reinterpret_cast<SELF *>(pvService);
     1056    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1057    LogFlowFunc(("[Client %RU32] Disconnected (%zu clients total)\n", idClient, pThis->mClientStateMap.size()));
     1058
     1059    ClientStateMapIter ItClientState = pThis->mClientStateMap.find(idClient);
     1060    AssertMsgReturn(ItClientState != pThis->mClientStateMap.end(),
    10911061                    ("Client ID=%RU32 not found in client list when it should be there\n", idClient),
    10921062                    VINF_SUCCESS);
     
    11091079                VBOXHGCMSVCPARM Parm;
    11101080                HGCMSvcSetU32(&Parm, idContext);
    1111                 int rc2 = hostCallback(GUEST_DISCONNECTED, 1, &Parm);
     1081                int rc2 = pThis->hostCallback(GUEST_DISCONNECTED, 1, &Parm);
    11121082                LogFlowFunc(("Cancelled host command %u (%s) with idContext=%#x -> %Rrc\n",
    11131083                             idFunction, GstCtrlHostFnName((eHostFn)idFunction), idContext, rc2));
     
    11201090     * Delete the client state.
    11211091     */
    1122     mClientStateMap.erase(ItClientState);
     1092    pThis->mClientStateMap.erase(ItClientState);
    11231093
    11241094    /*
    11251095     * If it's the master disconnecting, we need to reset related globals.
    11261096     */
    1127     if (idClient == m_idMasterClient)
    1128     {
    1129         m_idMasterClient = UINT32_MAX;
     1097    if (idClient == pThis->m_idMasterClient)
     1098    {
     1099        pThis->m_idMasterClient = UINT32_MAX;
    11301100        GstCtrlPreparedSession *pCur, *pNext;
    1131         RTListForEachSafe(&m_PreparedSessions, pCur, pNext, GstCtrlPreparedSession, ListEntry)
     1101        RTListForEachSafe(&pThis->m_PreparedSessions, pCur, pNext, GstCtrlPreparedSession, ListEntry)
    11321102        {
    11331103            RTMemFree(pCur);
    11341104        }
    1135         m_cPreparedSessions = 0;
    1136     }
    1137 
    1138     if (mClientStateMap.empty())
    1139         m_fLegacyMode = true;
     1105        pThis->m_cPreparedSessions = 0;
     1106    }
     1107
     1108    if (pThis->mClientStateMap.empty())
     1109        pThis->m_fLegacyMode = true;
    11401110
    11411111    /*
    11421112     * Host command sanity check.
    11431113     */
    1144     Assert(RTListIsEmpty(&mHostCmdList) || !mClientStateMap.empty());
     1114    Assert(RTListIsEmpty(&pThis->mHostCmdList) || !pThis->mClientStateMap.empty());
    11451115
    11461116    return VINF_SUCCESS;
     
    12051175 * @param   hCall       The client's call handle.
    12061176 * @param   cParms      Number of parameters.
    1207  * @param   paParms     Array of parameters.
    1208  * @param   fWait       Set if we should wait for a message, clear if to return
    1209  *                      immediately.
    12101177 */
    12111178int GstCtrlService::clientMakeMeMaster(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms)
     
    18811848     */
    18821849    if (!rClientState.mHostCmdList.empty())
    1883         rClientState.DitchFirstHostCmd();
     1850        rClientState.OldDitchFirstHostCmd();
    18841851
    18851852    LogFlowFunc(("[Client %RU32] Skipped current message - leagcy function\n", idClient));
     
    18931860 *
    18941861 * @return  IPRT status code.
    1895  * @param   eFunction               Function (event) that occured.
    1896  * @param   cParms                  Number of parameters.
    1897  * @param   paParms                 Array of parameters.
    1898  */
    1899 int GstCtrlService::hostCallback(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    1900 {
    1901     LogFlowFunc(("eFunction=%ld, cParms=%ld, paParms=%p\n",
    1902                  eFunction, cParms, paParms));
     1862 * @param   idFunction      Function (event) that occured.
     1863 * @param   cParms          Number of parameters.
     1864 * @param   paParms         Array of parameters.
     1865 */
     1866int GstCtrlService::hostCallback(uint32_t idFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     1867{
     1868    LogFlowFunc(("idFunction=%u (%s), cParms=%ld, paParms=%p\n", idFunction, GstCtrlGuestFnName((eGuestFn)idFunction), cParms, paParms));
    19031869
    19041870    int rc;
     
    19151881        try
    19161882        {
    1917             rc = mpfnHostCallback(mpvHostData, eFunction, (void *)(&data), sizeof(data));
     1883            rc = mpfnHostCallback(mpvHostData, idFunction, (void *)(&data), sizeof(data));
    19181884        }
    19191885        catch (std::bad_alloc &)
     
    20231989
    20241990/**
    2025  * Worker for svcCall() that helps implement VBOXHGCMSVCFNTABLE::pfnCall.
     1991 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnHostCall,
     1992 *  Wraps to the hostProcessCommand() member function.}
     1993 */
     1994/*static*/ DECLCALLBACK(int)
     1995GstCtrlService::svcHostCall(void *pvService, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     1996{
     1997    AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
     1998    SELF *pThis = reinterpret_cast<SELF *>(pvService);
     1999    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     2000
     2001    LogFlowFunc(("fn=%RU32, cParms=%RU32, paParms=0x%p\n", u32Function, cParms, paParms));
     2002    AssertReturn(u32Function != HOST_CANCEL_PENDING_WAITS, VERR_INVALID_FUNCTION);
     2003    return pThis->hostProcessCommand(u32Function, cParms, paParms);
     2004}
     2005
     2006
     2007/**
     2008 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnCall}
    20262009 *
    20272010 * @note    All functions which do not involve an unreasonable delay will be
    20282011 *          handled synchronously.  If needed, we will add a request handler
    20292012 *          thread in future for those which do.
    2030  *
    20312013 * @thread  HGCM
    20322014 */
    2033 void GstCtrlService::call(VBOXHGCMCALLHANDLE hCall, uint32_t idClient, void * /* pvClient */, uint32_t idFunction,
    2034                           uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     2015/*static*/ DECLCALLBACK(void)
     2016GstCtrlService::svcCall(void *pvService, VBOXHGCMCALLHANDLE hCall, uint32_t idClient, void *pvClient,
     2017                        uint32_t idFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[], uint64_t tsArrival)
    20352018{
    20362019    LogFlowFunc(("[Client %RU32] idFunction=%RU32 (%s), cParms=%RU32, paParms=0x%p\n",
    20372020                 idClient, idFunction, GstCtrlHostFnName((eHostFn)idFunction), cParms, paParms));
     2021    RT_NOREF(tsArrival, pvClient);
     2022
     2023    AssertLogRelReturnVoid(VALID_PTR(pvService));
     2024    SELF *pThis= reinterpret_cast<SELF *>(pvService);
     2025    AssertPtrReturnVoid(pThis);
     2026
    20382027    int rc;
    20392028    switch (idFunction)
     
    20412030        case GUEST_MAKE_ME_MASTER:
    20422031            LogFlowFunc(("[Client %RU32] GUEST_MAKE_ME_MASTER\n", idClient));
    2043             rc = clientMakeMeMaster(idClient, hCall, cParms);
     2032            rc = pThis->clientMakeMeMaster(idClient, hCall, cParms);
    20442033            break;
    20452034        case GUEST_MSG_PEEK_NOWAIT:
    20462035            LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_NOWAIT\n", idClient));
    2047             rc = clientMsgPeek(idClient, hCall, cParms, paParms, false /*fWait*/);
     2036            rc = pThis->clientMsgPeek(idClient, hCall, cParms, paParms, false /*fWait*/);
    20482037            break;
    20492038        case GUEST_MSG_PEEK_WAIT:
    20502039            LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_WAIT\n", idClient));
    2051             rc = clientMsgPeek(idClient, hCall, cParms, paParms, true /*fWait*/);
     2040            rc = pThis->clientMsgPeek(idClient, hCall, cParms, paParms, true /*fWait*/);
    20522041            break;
    20532042        case GUEST_MSG_GET:
    20542043            LogFlowFunc(("[Client %RU32] GUEST_MSG_GET\n", idClient));
    2055             rc = clientMsgGet(idClient, hCall, cParms, paParms);
     2044            rc = pThis->clientMsgGet(idClient, hCall, cParms, paParms);
    20562045            break;
    20572046        case GUEST_MSG_CANCEL:
    20582047            LogFlowFunc(("[Client %RU32] GUEST_MSG_CANCEL\n", idClient));
    2059             rc = clientMsgCancel(idClient, cParms);
     2048            rc = pThis->clientMsgCancel(idClient, cParms);
    20602049            break;
    20612050        case GUEST_MSG_SKIP:
    20622051            LogFlowFunc(("[Client %RU32] GUEST_MSG_SKIP\n", idClient));
    2063             rc = clientMsgSkip(idClient, hCall, cParms);
     2052            rc = pThis->clientMsgSkip(idClient, hCall, cParms);
    20642053            break;
    20652054        case GUEST_SESSION_PREPARE:
    20662055            LogFlowFunc(("[Client %RU32] GUEST_SESSION_PREPARE\n", idClient));
    2067             rc = clientSessionPrepare(idClient, hCall, cParms, paParms);
     2056            rc = pThis->clientSessionPrepare(idClient, hCall, cParms, paParms);
    20682057            break;
    20692058        case GUEST_SESSION_CANCEL_PREPARED:
    20702059            LogFlowFunc(("[Client %RU32] GUEST_SESSION_CANCEL_PREPARED\n", idClient));
    2071             rc = clientSessionCancelPrepared(idClient, cParms, paParms);
     2060            rc = pThis->clientSessionCancelPrepared(idClient, cParms, paParms);
    20722061            break;
    20732062        case GUEST_SESSION_ACCEPT:
    20742063            LogFlowFunc(("[Client %RU32] GUEST_SESSION_ACCEPT\n", idClient));
    2075             rc = clientSessionAccept(idClient, hCall, cParms, paParms);
     2064            rc = pThis->clientSessionAccept(idClient, hCall, cParms, paParms);
    20762065            break;
    20772066        case GUEST_SESSION_CLOSE:
    20782067            LogFlowFunc(("[Client %RU32] GUEST_SESSION_CLOSE\n", idClient));
    2079             rc = clientSessionCloseOther(idClient, cParms, paParms);
     2068            rc = pThis->clientSessionCloseOther(idClient, cParms, paParms);
    20802069            break;
    20812070
     
    20862075         */
    20872076        default:
    2088             rc = hostCallback(idFunction, cParms, paParms);
     2077            rc = pThis->hostCallback(idFunction, cParms, paParms);
    20892078            break;
    20902079
     
    20952084        case GUEST_MSG_WAIT:
    20962085            LogFlowFunc(("[Client %RU32] GUEST_MSG_WAIT\n", idClient));
    2097             clientMsgOldGet(idClient, hCall, cParms, paParms);
     2086            pThis->clientMsgOldGet(idClient, hCall, cParms, paParms);
    20982087            rc = VINF_HGCM_ASYNC_EXECUTE;
    20992088            break;
     
    21012090        case GUEST_MSG_SKIP_OLD:
    21022091            LogFlowFunc(("[Client %RU32] GUEST_MSG_SKIP_OLD\n", idClient));
    2103             rc = clientMsgOldSkip(idClient, cParms);
     2092            rc = pThis->clientMsgOldSkip(idClient, cParms);
    21042093            break;
    21052094
    21062095        case GUEST_MSG_FILTER_SET:
    21072096            LogFlowFunc(("[Client %RU32] GUEST_MSG_FILTER_SET\n", idClient));
    2108             rc = clientMsgOldFilterSet(idClient, cParms, paParms);
     2097            rc = pThis->clientMsgOldFilterSet(idClient, cParms, paParms);
    21092098            break;
    21102099
     
    21192108        /* Tell the client that the call is complete (unblocks waiting). */
    21202109        LogFlowFunc(("[Client %RU32] Calling pfnCallComplete w/ rc=%Rrc\n", idClient, rc));
    2121         AssertPtr(mpHelpers);
    2122         mpHelpers->pfnCallComplete(hCall, rc);
     2110        AssertPtr(pThis->mpHelpers);
     2111        pThis->mpHelpers->pfnCallComplete(hCall, rc);
    21232112    }
    21242113}
     
    21262115
    21272116/**
    2128  * Service call handler for the host.
    2129  * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnHostCall}
    2130  * @thread  hgcm
    2131  */
    2132 int GstCtrlService::hostCall(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    2133 {
    2134     LogFlowFunc(("fn=%RU32, cParms=%RU32, paParms=0x%p\n", eFunction, cParms, paParms));
    2135 
    2136     switch (eFunction)
    2137     {
    2138         default:
    2139             return hostProcessCommand(eFunction, cParms, paParms);
    2140 
    2141         /** @todo r=bird: Why is this here, I cannot find anyone using this in Main.
    2142          * I thought the HOST_CANCEL_PENDING_WAITS was only for return to the _guest_
    2143          * when the root VBoxService wanted to shut down. */
    2144         case HOST_CANCEL_PENDING_WAITS:
    2145         {
    2146             LogFlowFunc(("HOST_CANCEL_PENDING_WAITS\n"));
    2147             AssertFailed(); /* want to know who uses this function! */
    2148             ClientStateMapIter itClientState = mClientStateMap.begin();
    2149             while (itClientState != mClientStateMap.end())
    2150             {
    2151                 int rc2 = itClientState->second.CancelWaiting();
    2152                 if (RT_FAILURE(rc2))
    2153                     LogFlowFunc(("Cancelling waiting for client ID=%RU32 failed with rc=%Rrc",
    2154                                  itClientState->first, rc2));
    2155                 ++itClientState;
    2156             }
    2157             return VINF_SUCCESS;
    2158         }
    2159     }
    2160 }
    2161 
    2162 
    2163 int GstCtrlService::uninit(void)
    2164 {
     2117 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnRegisterExtension,
     2118 *  Installs a host callback for notifications of property changes.}
     2119 */
     2120/*static*/ DECLCALLBACK(int) GstCtrlService::svcRegisterExtension(void *pvService, PFNHGCMSVCEXT pfnExtension, void *pvExtension)
     2121{
     2122    AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
     2123    SELF *pSelf = reinterpret_cast<SELF *>(pvService);
     2124    AssertPtrReturn(pSelf, VERR_INVALID_POINTER);
     2125    pSelf->mpfnHostCallback = pfnExtension;
     2126    pSelf->mpvHostData = pvExtension;
    21652127    return VINF_SUCCESS;
    21662128}
    2167 
    21682129
    21692130
Note: See TracChangeset for help on using the changeset viewer.

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