VirtualBox

Changeset 55571 in vbox for trunk/src


Ignore:
Timestamp:
Apr 30, 2015 5:04:37 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
99943
Message:

DnD: Simplified cancellation logic.

Location:
trunk/src/VBox
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp

    r55422 r55571  
    14241424    /*
    14251425     * Note: Don't clear this->lstAllowedFormats at the moment, as this value is initialized
    1426      *       on class creation. We might later want to modify the allowed formats in runtime,
     1426     *       on class creation. We might later want to modify the allowed formats at runtime,
    14271427     *       so keep this in mind when implementing this.
    14281428     */
     
    16651665             * don't support the stuff we do on the guest side, so make sure we
    16661666             * don't process invalid messages forever. */
    1667             if (cMsgSkippedInvalid++ > 3)
     1667            if (rc == VERR_INVALID_PARAMETER)
     1668                cMsgSkippedInvalid++;
     1669            if (cMsgSkippedInvalid > 32)
    16681670            {
    16691671                LogRel(("DnD: Too many invalid/skipped messages from host, exiting ...\n"));
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp

    r55556 r55571  
    552552            }
    553553
    554 #if 0
     554#if 0 /* Not used yet. */
    555555            if (pCtx->uProtocol >= XXX)
    556556            {
  • trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp

    r55459 r55571  
    11841184     * Do we have a new window which now is under the cursor?
    11851185     */
    1186     if (   wndCursor != m_wndCur 
     1186    if (   wndCursor != m_wndCur
    11871187        && newVer    != -1)
    11881188    {
     
    13381338    if (RT_UNLIKELY(xrc == 0))
    13391339    {
    1340         logError(("Error sending SelectionNotify event to window=%#x: %s\n", 
     1340        logError(("Error sending SelectionNotify event to window=%#x: %s\n",
    13411341                  s.xselection.requestor, gX11->xErrorToString(xrc).c_str()));
    13421342    }
     
    14481448                }
    14491449
    1450                 /* 
     1450                /*
    14511451                 * Acknowledge the event by sending a status message back to the window.
    14521452                 */
     
    14661466                if (RT_UNLIKELY(xRc == 0))
    14671467                {
    1468                     logError(("Error sending enter XA_XdndStatus to current window=%#x: %s\n", 
     1468                    logError(("Error sending enter XA_XdndStatus to current window=%#x: %s\n",
    14691469                              m_wndCur, gX11->xErrorToString(xRc).c_str()));
    14701470                }
     
    14921492                if (RT_UNLIKELY(xRc == 0))
    14931493                {
    1494                     logError(("Error sending position XA_XdndStatus to current window=%#x: %s\n", 
     1494                    logError(("Error sending position XA_XdndStatus to current window=%#x: %s\n",
    14951495                              m_wndCur, gX11->xErrorToString(xRc).c_str()));
    14961496                }
     
    16911691                    if (RT_UNLIKELY(xrc == 0))
    16921692                    {
    1693                         logError(("Error sending XA_XdndFinished to proxy window=%#x: %s\n", 
     1693                        logError(("Error sending XA_XdndFinished to proxy window=%#x: %s\n",
    16941694                                  m_wndProxy, gX11->xErrorToString(xrc).c_str()));
    16951695                    }
     
    23262326            if (rc == VERR_INVALID_PARAMETER)
    23272327                cMsgSkippedInvalid++;
    2328             if (cMsgSkippedInvalid > 3)
     2328            if (cMsgSkippedInvalid > 32)
    23292329            {
    23302330                LogRel(("DnD: Too many invalid/skipped messages from host, exiting ...\n"));
  • trunk/src/VBox/Main/include/GuestDnDPrivate.h

    r55556 r55571  
    110110        lstDirs.clear();
    111111        lstFiles.clear();
     112#if 0 /* Currently the scratch buffer will be maintained elswewhere. */
    112113        if (pvScratchBuf)
    113114        {
     
    116117        }
    117118        cbScratchBuf = 0;
     119#else
     120        pvScratchBuf = NULL;
     121        cbScratchBuf = 0;
     122#endif
    118123    }
    119124
     
    549554    int getProtocolVersion(uint32_t *puVersion);
    550555
    551     int addMsg(GuestDnDMsg *pMsg)
    552     {
    553         mDataBase.mListOutgoing.push_back(pMsg);
    554         return VINF_SUCCESS;
    555     }
    556 
    557     GuestDnDMsg *nextMsg(void)
    558     {
    559         if (mDataBase.mListOutgoing.empty())
    560             return NULL;
    561         return mDataBase.mListOutgoing.front();
    562     }
    563 
    564     void removeNext(void)
    565     {
    566         if (!mDataBase.mListOutgoing.empty())
    567         {
    568             GuestDnDMsg *pMsg = mDataBase.mListOutgoing.front();
    569             if (pMsg)
    570                 delete pMsg;
    571             mDataBase.mListOutgoing.pop_front();
    572         }
    573     }
     556    /** @name Functions for handling a simple host HGCM message queue.
     557     * @{ */
     558    int msgQueueAdd(GuestDnDMsg *pMsg);
     559    GuestDnDMsg *msgQueueGetNext(void);
     560    void msgQueueRemoveNext(void);
     561    void msgQueueClear(void);
     562    /** @}  */
     563
     564    int sendCancel(void);
     565    int waitForEvent(RTMSINTERVAL msTimeout, GuestDnDCallbackEvent &Event, GuestDnDResponse *pResp);
    574566
    575567protected:
  • trunk/src/VBox/Main/include/GuestDnDTargetImpl.h

    r55549 r55571  
    7474
    7575    int i_cancelOperation(void);
    76     int i_sendData(PSENDDATACTX pCtx);
     76    int i_sendData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout);
    7777    int i_sendDirectory(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject &aDirectory);
    7878    int i_sendFile(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject &aFile);
    7979    int i_sendFileData(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject &aFile);
    80     int i_sendURIData(PSENDDATACTX pCtx);
     80    int i_sendURIData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout);
     81    int i_sendRawData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout);
    8182    int i_sendURIDataLoop(PSENDDATACTX pCtx, GuestDnDMsg *pMsg);
    8283
  • trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp

    r55556 r55571  
    831831    return rc;
    832832}
     833
     834int GuestDnDBase::msgQueueAdd(GuestDnDMsg *pMsg)
     835{
     836    mDataBase.mListOutgoing.push_back(pMsg);
     837    return VINF_SUCCESS;
     838}
     839
     840GuestDnDMsg *GuestDnDBase::msgQueueGetNext(void)
     841{
     842    if (mDataBase.mListOutgoing.empty())
     843        return NULL;
     844    return mDataBase.mListOutgoing.front();
     845}
     846
     847void GuestDnDBase::msgQueueRemoveNext(void)
     848{
     849    if (!mDataBase.mListOutgoing.empty())
     850    {
     851        GuestDnDMsg *pMsg = mDataBase.mListOutgoing.front();
     852        if (pMsg)
     853            delete pMsg;
     854        mDataBase.mListOutgoing.pop_front();
     855    }
     856}
     857
     858void GuestDnDBase::msgQueueClear(void)
     859{
     860    GuestDnDMsgList::iterator itMsg = mDataBase.mListOutgoing.begin();
     861    while (itMsg != mDataBase.mListOutgoing.end())
     862    {
     863        delete *itMsg;
     864    }
     865
     866    mDataBase.mListOutgoing.clear();
     867}
     868
     869int GuestDnDBase::sendCancel(void)
     870{
     871    LogFlowFunc(("Sending cancelation request to guest ...\n"));
     872
     873    GuestDnDMsg MsgCancel;
     874    MsgCancel.setType(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL);
     875
     876    return GuestDnDInst()->hostCall(MsgCancel.getType(), MsgCancel.getCount(), MsgCancel.getParms());
     877}
     878
     879/** @todo GuestDnDResponse *pResp needs to go. */
     880int GuestDnDBase::waitForEvent(RTMSINTERVAL msTimeout, GuestDnDCallbackEvent &Event, GuestDnDResponse *pResp)
     881{
     882    int rc;
     883
     884    uint64_t tsStart = RTTimeMilliTS();
     885    do
     886    {
     887        /*
     888         * Wait until our desired callback triggered the
     889         * wait event. As we don't want to block if the guest does not
     890         * respond, so do busy waiting here.
     891         */
     892        rc = Event.Wait(500 /* ms */);
     893        if (RT_SUCCESS(rc))
     894        {
     895            rc = Event.Result();
     896            LogFlowFunc(("Callback done, result is %Rrc\n", rc));
     897            break;
     898        }
     899        else if (rc == VERR_TIMEOUT) /* Continue waiting. */
     900            rc = VINF_SUCCESS;
     901
     902        if (   msTimeout != RT_INDEFINITE_WAIT
     903            && RTTimeMilliTS() - tsStart > msTimeout)
     904        {
     905            rc = VERR_TIMEOUT;
     906        }
     907        else if (pResp->isProgressCanceled())
     908        {
     909            pResp->setProgress(100 /* Percent */, DragAndDropSvc::DND_PROGRESS_CANCELLED);
     910            rc = VERR_CANCELLED;
     911        }
     912
     913    } while (RT_SUCCESS(rc));
     914
     915    LogFlowFuncLeaveRC(rc);
     916    return rc;
     917}
    833918#endif /* VBOX_WITH_DRAG_AND_DROP */
    834919
  • trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp

    r55556 r55571  
    781781    if (SUCCEEDED(autoCaller.rc()))
    782782    {
    783         rc = pSource->i_receiveData(pTask->getCtx(), RT_INDEFINITE_WAIT);
     783        rc = pSource->i_receiveData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */);
    784784    }
    785785    else
     
    838838        rc = pInst->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
    839839        if (RT_SUCCESS(rc))
    840         {
    841             /*
    842              * Wait until our callback i_receiveRawDataCallback triggered the
    843              * wait event.
    844              */
    845             LogFlowFunc(("Waiting for raw data callback (%RU32ms timeout) ...\n", msTimeout));
    846             rc = pCtx->mCallback.Wait(msTimeout);
    847             LogFlowFunc(("Raw callback done, rc=%Rrc\n", rc));
    848         }
     840            rc = waitForEvent(msTimeout, pCtx->mCallback, pCtx->mpResp);
    849841
    850842    } while (0);
     
    858850#undef REGISTER_CALLBACK
    859851#undef UNREGISTER_CALLBACK
     852
     853    if (rc == VERR_CANCELLED)
     854    {
     855        int rc2 = sendCancel();
     856        AssertRC(rc2);
     857    }
    860858
    861859    LogFlowFuncLeaveRC(rc);
     
    918916
    919917        /* Make the initial call to the guest by telling that we initiated the "dropped" event on
    920          * the host and therefore now waiting for the actual URI actual data. */
     918         * the host and therefore now waiting for the actual URI data. */
    921919        rc = pInst->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
    922920        if (RT_SUCCESS(rc))
    923         {
    924             /*
    925              * Wait until our callback i_receiveURIDataCallback triggered the
    926              * wait event.
    927              */
    928             LogFlowFunc(("Waiting for URI callback (%RU32ms timeout) ...\n", msTimeout));
    929             rc = pCtx->mCallback.Wait(msTimeout);
    930             LogFlowFunc(("URI callback done, rc=%Rrc\n", rc));
    931             if (RT_SUCCESS(rc))
    932             {
    933                 rc = pCtx->mCallback.Result();
    934                 LogFlowFunc(("Callback result is %Rrc\n", rc));
    935             }
    936         }
     921            rc = waitForEvent(msTimeout, pCtx->mCallback, pCtx->mpResp);
    937922
    938923    } while (0);
     
    950935#undef REGISTER_CALLBACK
    951936#undef UNREGISTER_CALLBACK
     937
     938    if (rc == VERR_CANCELLED)
     939    {
     940        int rc2 = sendCancel();
     941        AssertRC(rc2);
     942    }
    952943
    953944    if (RT_FAILURE(rc))
  • trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp

    r55556 r55571  
    491491    if (SUCCEEDED(autoCaller.rc()))
    492492    {
    493         rc = pTarget->i_sendData(pTask->getCtx());
     493        rc = pTarget->i_sendData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */);
    494494        /* Nothing to do here anymore. */
    495495    }
     
    601601}
    602602
    603 int GuestDnDTarget::i_sendData(PSENDDATACTX pCtx)
     603int GuestDnDTarget::i_sendData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout)
    604604{
    605605    AssertPtrReturn(pCtx,  VERR_INVALID_POINTER);
    606 
    607 #define DATA_IS_VALID_BREAK(x) \
    608     if (!x) \
    609     { \
    610         LogFlowFunc(("Invalid URI data value for \"" #x "\"\n")); \
    611         rc = VERR_INVALID_PARAMETER; \
    612         break; \
    613     }
    614606
    615607    GuestDnD *pInst = GuestDnDInst();
     
    624616    mDataBase.mListOutgoing.clear();
    625617
    626     do
    627     {
    628         const char *pszFormat = pCtx->mFormat.c_str();
    629         DATA_IS_VALID_BREAK(pszFormat);
    630         uint32_t cbFormat = pCtx->mFormat.length() + 1;
    631 
    632         /* Do we need to build up a file tree? */
    633         bool fHasURIList = DnDMIMEHasFileURLs(pszFormat, cbFormat);
    634         if (fHasURIList)
    635         {
    636             rc = i_sendURIData(pCtx);
    637         }
    638         else
    639         {
    640             GuestDnDMsg Msg;
    641 
    642             size_t cbDataTotal = pCtx->mData.vecData.size();
    643             DATA_IS_VALID_BREAK(cbDataTotal);
    644 
    645             /* Just copy over the raw data. */
    646             Msg.setType(DragAndDropSvc::HOST_DND_HG_SND_DATA);
    647             Msg.setNextUInt32(pCtx->mScreenID);
    648             Msg.setNextPointer((void *)pCtx->mFormat.c_str(), (uint32_t)pCtx->mFormat.length() + 1);
    649             Msg.setNextUInt32((uint32_t)pCtx->mFormat.length() + 1);
    650             Msg.setNextPointer((void*)&pCtx->mData.vecData.front(), (uint32_t)cbDataTotal);
    651             Msg.setNextUInt32(cbDataTotal);
    652 
    653             LogFlowFunc(("%zu total bytes of raw data to transfer\n", cbDataTotal));
    654 
    655             /* Make the initial call to the guest by sending the actual data. This might
    656              * be an URI list which in turn can lead to more data to send afterwards. */
    657             rc = pInst->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
    658             if (RT_FAILURE(rc))
    659                 break;
    660         }
    661 
    662     } while (0);
     618    const char *pszFormat = pCtx->mFormat.c_str();
     619    uint32_t cbFormat = pCtx->mFormat.length() + 1;
     620
     621    /* Do we need to build up a file tree? */
     622    bool fHasURIList = DnDMIMEHasFileURLs(pszFormat, cbFormat);
     623    if (fHasURIList)
     624    {
     625        rc = i_sendURIData(pCtx, msTimeout);
     626    }
     627    else
     628    {
     629        rc = i_sendRawData(pCtx, msTimeout);
     630    }
    663631
    664632    ASMAtomicWriteBool(&pCtx->mIsActive, false);
     
    857825            {
    858826                pMsg = new GuestDnDMsg();
     827
    859828                rc = pThis->i_sendURIDataLoop(pCtx, pMsg);
    860829                if (RT_SUCCESS(rc))
    861830                {
    862                     rc = pThis->addMsg(pMsg);
     831                    rc = pThis->msgQueueAdd(pMsg);
    863832                    if (RT_SUCCESS(rc)) /* Return message type & required parameter count to the guest. */
    864833                    {
     
    903872            LogFlowFunc(("pCBData->uMsg=%RU32, paParms=%p, cParms=%RU32\n", pCBData->uMsg, pCBData->paParms, pCBData->cParms));
    904873
    905             GuestDnDMsg *pMsg = pThis->nextMsg();
     874            GuestDnDMsg *pMsg = pThis->msgQueueGetNext();
    906875            if (pMsg)
    907876            {
     
    913882                    || pCBData->cParms  != pMsg->getCount())
    914883                {
     884                    /* Start over. */
     885                    pThis->msgQueueClear();
     886
    915887                    rc = VERR_INVALID_PARAMETER;
    916888                }
     
    923895                    {
    924896                        pCBData->cParms = pMsg->getCount();
    925                         pThis->removeNext();
     897                        pThis->msgQueueRemoveNext();
    926898                    }
    927899                    else
     
    971943}
    972944
    973 int GuestDnDTarget::i_sendURIData(PSENDDATACTX pCtx)
     945int GuestDnDTarget::i_sendURIData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout)
    974946{
    975947    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     
    990962    int rc;
    991963
    992 #define REGISTER_CALLBACK(x) \
     964#define REGISTER_CALLBACK(x)                                        \
    993965    rc = pCtx->mpResp->setCallback(x, i_sendURIDataCallback, pCtx); \
    994     if (RT_FAILURE(rc)) \
     966    if (RT_FAILURE(rc))                                             \
    995967        return rc;
     968
     969#define UNREGISTER_CALLBACK(x)                        \
     970    {                                                 \
     971        int rc2 = pCtx->mpResp->setCallback(x, NULL); \
     972        AssertRC(rc2);                                \
     973    }
    996974
    997975    rc = pCtx->mCallback.Reset();
    998976    if (RT_FAILURE(rc))
    999977        return rc;
    1000 
    1001 #define UNREGISTER_CALLBACK(x) \
    1002     rc = pCtx->mpResp->setCallback(x, NULL); \
    1003     AssertRC(rc);
    1004978
    1005979    /*
     
    10571031        size_t    cbData  = strData.length() + 1; /* Include terminating zero. */
    10581032
    1059         GuestDnDMsg Msg;
    1060         Msg.setType(DragAndDropSvc::HOST_DND_HG_SND_DATA);
    1061         Msg.setNextUInt32(pCtx->mScreenID);
    1062         Msg.setNextPointer((void *)pCtx->mFormat.c_str(), (uint32_t)pCtx->mFormat.length() + 1);
    1063         Msg.setNextUInt32((uint32_t)pCtx->mFormat.length() + 1);
    1064         Msg.setNextPointer((void*)strData.c_str(), (uint32_t)cbData);
    1065         Msg.setNextUInt32((uint32_t)cbData);
    1066 
    1067         rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
     1033        GuestDnDMsg MsgSndData;
     1034        MsgSndData.setType(DragAndDropSvc::HOST_DND_HG_SND_DATA);
     1035        MsgSndData.setNextUInt32(pCtx->mScreenID);
     1036        MsgSndData.setNextPointer((void *)pCtx->mFormat.c_str(), (uint32_t)pCtx->mFormat.length() + 1);
     1037        MsgSndData.setNextUInt32((uint32_t)pCtx->mFormat.length() + 1);
     1038        MsgSndData.setNextPointer((void*)strData.c_str(), (uint32_t)cbData);
     1039        MsgSndData.setNextUInt32((uint32_t)cbData);
     1040
     1041        rc = GuestDnDInst()->hostCall(MsgSndData.getType(), MsgSndData.getCount(), MsgSndData.getParms());
    10681042        if (RT_SUCCESS(rc))
    1069         {
    1070             /*
    1071              * Wait until our callback i_sendURIDataCallback triggered the
    1072              * wait event.
    1073              */
    1074             LogFlowFunc(("Waiting for URI callback ...\n"));
    1075             rc = pCtx->mCallback.Wait(RT_INDEFINITE_WAIT);
    1076             LogFlowFunc(("URI callback done, rc=%Rrc\n", rc));
    1077         }
     1043            rc = waitForEvent(msTimeout, pCtx->mCallback, pCtx->mpResp);
    10781044
    10791045    } while (0);
    10801046
    10811047    /*
    1082      * Unregister callbacksagain.
     1048     * Unregister callbacks.
    10831049     */
    10841050    /* Guest callbacks. */
     
    10941060#undef UNREGISTER_CALLBACK
    10951061
     1062    /*
     1063     * Now that we've cleaned up tell the guest side to cancel.
     1064     */
     1065    if (rc == VERR_CANCELLED)
     1066    {
     1067        int rc2 = sendCancel();
     1068        AssertRC(rc2);
     1069    }
     1070
    10961071    /* Destroy temporary scratch buffer. */
    10971072    if (pvBuf)
     
    11711146    }
    11721147
    1173     if (   pCtx->mpResp
    1174         && pCtx->mpResp->isProgressCanceled())
    1175     {
    1176         LogFlowFunc(("Cancelling ...\n"));
    1177 
    1178         rc = i_cancelOperation();
    1179         if (RT_SUCCESS(rc))
    1180             rc = VERR_CANCELLED;
    1181     }
    1182 
    11831148    LogFlowFuncLeaveRC(rc);
    11841149    return rc;
     1150}
     1151
     1152int GuestDnDTarget::i_sendRawData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout)
     1153{
     1154    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     1155    NOREF(msTimeout);
     1156
     1157    GuestDnD *pInst = GuestDnDInst();
     1158    AssertPtr(pInst);
     1159
     1160    /* At the moment we only allow up to 64K raw data. */
     1161    size_t cbDataTotal = pCtx->mData.vecData.size();
     1162    if (   !cbDataTotal
     1163        || cbDataTotal > _64K)
     1164    {
     1165        return VERR_INVALID_PARAMETER;
     1166    }
     1167
     1168    /* Just copy over the raw data. */
     1169    GuestDnDMsg Msg;
     1170    Msg.setType(DragAndDropSvc::HOST_DND_HG_SND_DATA);
     1171    Msg.setNextUInt32(pCtx->mScreenID);
     1172    Msg.setNextPointer((void *)pCtx->mFormat.c_str(), (uint32_t)pCtx->mFormat.length() + 1);
     1173    Msg.setNextUInt32((uint32_t)pCtx->mFormat.length() + 1);
     1174    Msg.setNextPointer((void*)&pCtx->mData.vecData.front(), (uint32_t)cbDataTotal);
     1175    Msg.setNextUInt32(cbDataTotal);
     1176
     1177    LogFlowFunc(("%zu total bytes of raw data to transfer\n", cbDataTotal));
     1178
     1179    return pInst->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
    11851180}
    11861181
Note: See TracChangeset for help on using the changeset viewer.

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