VirtualBox

Changeset 100367 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Jul 4, 2023 4:23:18 PM (21 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
158104
Message:

Shared Clipboard: More work on making the internal APIs more fine grained and easier to follow. bugref:9437

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/http-server.cpp

    r100250 r100367  
    689689        case VERR_IS_A_DIRECTORY:       return RTHTTPSTATUS_FORBIDDEN;
    690690        case VERR_NOT_FOUND:            return RTHTTPSTATUS_NOTFOUND;
     691        case VERR_INTERNAL_ERROR:       return RTHTTPSTATUS_INTERNALSERVERERROR;
    691692        default:
    692693            break;
     
    713714    LogFlowFuncEnter();
    714715
    715     int rc = VINF_SUCCESS;
    716 
    717716    /* If a low-level GET request handler is defined, call it and return. */
    718717    RTHTTPSERVER_HANDLE_CALLBACK_VA_RET(pfnOnGetRequest, pReq);
     
    723722    char *pszMIMEHint = NULL;
    724723
     724    RTHTTPSTATUS enmStsResponse = RTHTTPSTATUS_OK;
     725
     726    int rc;
     727
    725728    RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnQueryInfo, pReq, &fsObj, &pszMIMEHint);
    726729    if (RT_FAILURE(rc))
    727         return rc;
     730         enmStsResponse = rtHttpServerRcToStatus(rc);
    728731
    729732    void *pvHandle = NULL;
    730     RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnOpen, pReq, &pvHandle);
    731 
    732     if (RT_SUCCESS(rc))
    733     {
    734         size_t cbBuf = _64K;
    735         void  *pvBuf = RTMemAlloc(cbBuf);
    736         AssertPtrReturn(pvBuf, VERR_NO_MEMORY);
    737 
    738         for (;;)
    739         {
    740             RTHTTPHEADERLIST HdrLst;
    741             rc = RTHttpHeaderListInit(&HdrLst);
     733    if (RT_SUCCESS(rc)) /* Only call open if querying information above succeeded. */
     734        RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnOpen, pReq, &pvHandle);
     735
     736    size_t cbBuf = _64K;
     737    void  *pvBuf = RTMemAlloc(cbBuf);
     738    AssertPtrReturn(pvBuf, VERR_NO_MEMORY);
     739
     740    for (;;)
     741    {
     742        RTHTTPHEADERLIST HdrLst;
     743        rc = RTHttpHeaderListInit(&HdrLst);
     744        AssertRCReturn(rc, rc);
     745
     746        char szVal[16];
     747
     748        /* Note: For directories fsObj.cbObject contains the actual size (in bytes)
     749         *       of the body data for the directory listing. */
     750
     751        ssize_t cch = RTStrPrintf2(szVal, sizeof(szVal), "%RU64", fsObj.cbObject);
     752        AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW);
     753        rc = RTHttpHeaderListAdd(HdrLst, "Content-Length", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK);
     754        AssertRCBreak(rc);
     755
     756        cch = RTStrPrintf2(szVal, sizeof(szVal), "identity");
     757        AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW);
     758        rc = RTHttpHeaderListAdd(HdrLst, "Content-Encoding", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK);
     759        AssertRCBreak(rc);
     760
     761        if (pszMIMEHint == NULL)
     762        {
     763            const char *pszMIME = rtHttpServerGuessMIMEType(RTPathSuffix(pReq->pszUrl));
     764            rc = RTHttpHeaderListAdd(HdrLst, "Content-Type", pszMIME, strlen(pszMIME), RTHTTPHEADERLISTADD_F_BACK);
     765        }
     766        else
     767        {
     768            rc = RTHttpHeaderListAdd(HdrLst, "Content-Type", pszMIMEHint, strlen(pszMIMEHint), RTHTTPHEADERLISTADD_F_BACK);
     769            RTStrFree(pszMIMEHint);
     770            pszMIMEHint = NULL;
     771        }
     772        AssertRCBreak(rc);
     773
     774        if (pClient->State.msKeepAlive)
     775        {
     776            /* If the client requested to keep alive the connection,
     777             * always override this with 30s and report this back to the client. */
     778            pClient->State.msKeepAlive = RT_MS_30SEC; /** @todo Make this configurable. */
     779#ifdef DEBUG_andy
     780            pClient->State.msKeepAlive = 5000;
     781#endif
     782            cch = RTStrPrintf2(szVal, sizeof(szVal), "timeout=%RU64", pClient->State.msKeepAlive / RT_MS_1SEC); /** @todo No pipelining support here yet. */
     783            AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW);
     784            rc = RTHttpHeaderListAdd(HdrLst, "Keep-Alive", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK);
    742785            AssertRCReturn(rc, rc);
    743 
    744             char szVal[16];
    745 
    746             /* Note: For directories fsObj.cbObject contains the actual size (in bytes)
    747              *       of the body data for the directory listing. */
    748 
    749             ssize_t cch = RTStrPrintf2(szVal, sizeof(szVal), "%RU64", fsObj.cbObject);
    750             AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW);
    751             rc = RTHttpHeaderListAdd(HdrLst, "Content-Length", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK);
    752             AssertRCBreak(rc);
    753 
    754             cch = RTStrPrintf2(szVal, sizeof(szVal), "identity");
    755             AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW);
    756             rc = RTHttpHeaderListAdd(HdrLst, "Content-Encoding", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK);
    757             AssertRCBreak(rc);
    758 
    759             if (pszMIMEHint == NULL)
     786        }
     787
     788        rc = rtHttpServerSendResponseEx(pClient, enmStsResponse, &HdrLst);
     789
     790        RTHttpHeaderListDestroy(HdrLst);
     791
     792        if (rc == VERR_BROKEN_PIPE) /* Could happen on fast reloads. */
     793            break;
     794        AssertRCReturn(rc, rc);
     795
     796        size_t cbToRead  = fsObj.cbObject;
     797        size_t cbRead    = 0; /* Shut up GCC. */
     798        size_t cbWritten = 0; /* Ditto. */
     799        while (cbToRead)
     800        {
     801            RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnRead, pReq, pvHandle, pvBuf, RT_MIN(cbBuf, cbToRead), &cbRead);
     802            if (RT_FAILURE(rc))
     803                break;
     804            rc = rtHttpServerSendResponseBody(pClient, pvBuf, cbRead, &cbWritten);
     805            AssertBreak(cbToRead >= cbWritten);
     806            cbToRead -= cbWritten;
     807            if (rc == VERR_NET_CONNECTION_RESET_BY_PEER) /* Clients often apruptly abort the connection when done. */
    760808            {
    761                 const char *pszMIME = rtHttpServerGuessMIMEType(RTPathSuffix(pReq->pszUrl));
    762                 rc = RTHttpHeaderListAdd(HdrLst, "Content-Type", pszMIME, strlen(pszMIME), RTHTTPHEADERLISTADD_F_BACK);
    763             }
    764             else
    765             {
    766                 rc = RTHttpHeaderListAdd(HdrLst, "Content-Type", pszMIMEHint, strlen(pszMIMEHint), RTHTTPHEADERLISTADD_F_BACK);
    767                 RTStrFree(pszMIMEHint);
    768                 pszMIMEHint = NULL;
     809                rc = VINF_SUCCESS;
     810                break;
    769811            }
    770812            AssertRCBreak(rc);
    771 
    772             if (pClient->State.msKeepAlive)
    773             {
    774                 /* If the client requested to keep alive the connection,
    775                  * always override this with 30s and report this back to the client. */
    776                 pClient->State.msKeepAlive = RT_MS_30SEC; /** @todo Make this configurable. */
    777 #ifdef DEBUG_andy
    778                 pClient->State.msKeepAlive = 5000;
    779 #endif
    780                 cch = RTStrPrintf2(szVal, sizeof(szVal), "timeout=%RU64", pClient->State.msKeepAlive / RT_MS_1SEC); /** @todo No pipelining support here yet. */
    781                 AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW);
    782                 rc = RTHttpHeaderListAdd(HdrLst, "Keep-Alive", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK);
    783                 AssertRCReturn(rc, rc);
    784             }
    785 
    786             rc = rtHttpServerSendResponseEx(pClient, RTHTTPSTATUS_OK, &HdrLst);
    787 
    788             RTHttpHeaderListDestroy(HdrLst);
    789 
    790             if (rc == VERR_BROKEN_PIPE) /* Could happen on fast reloads. */
    791                 break;
    792             AssertRCReturn(rc, rc);
    793 
    794             size_t cbToRead  = fsObj.cbObject;
    795             size_t cbRead    = 0; /* Shut up GCC. */
    796             size_t cbWritten = 0; /* Ditto. */
    797             while (cbToRead)
    798             {
    799                 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnRead, pReq, pvHandle, pvBuf, RT_MIN(cbBuf, cbToRead), &cbRead);
    800                 if (RT_FAILURE(rc))
    801                     break;
    802                 rc = rtHttpServerSendResponseBody(pClient, pvBuf, cbRead, &cbWritten);
    803                 AssertBreak(cbToRead >= cbWritten);
    804                 cbToRead -= cbWritten;
    805                 if (rc == VERR_NET_CONNECTION_RESET_BY_PEER) /* Clients often apruptly abort the connection when done. */
    806                 {
    807                     rc = VINF_SUCCESS;
    808                     break;
    809                 }
    810                 AssertRCBreak(rc);
    811             }
    812 
    813             break;
    814         } /* for (;;) */
    815 
    816         RTMemFree(pvBuf);
    817 
    818         int rc2 = rc; /* Save rc. */
    819 
     813        }
     814
     815        break;
     816    } /* for (;;) */
     817
     818    RTMemFree(pvBuf);
     819
     820    int rc2 = rc; /* Save rc. */
     821
     822    if (pvHandle)
    820823        RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnClose, pReq, pvHandle);
    821824
    822         if (RT_FAILURE(rc2)) /* Restore original rc on failure. */
    823             rc = rc2;
    824     }
     825    if (RT_FAILURE(rc2)) /* Restore original rc on failure. */
     826        rc = rc2;
    825827
    826828    LogFlowFuncLeaveRC(rc);
     
    12241226                if (RT_FAILURE(rcMethod))
    12251227                    LogFunc(("Request %s %s failed with %Rrc\n", RTHttpMethodToStr(pReq->enmMethod), pReq->pszUrl, rcMethod));
    1226 
    1227                 enmSts = rtHttpServerRcToStatus(rcMethod);
    12281228                break;
    12291229            }
     
    12421242    /* Make sure to return at least *something* to the client, to prevent hangs. */
    12431243    if (enmSts == RTHTTPSTATUS_INTERNAL_NOT_SET)
    1244         enmSts = RTHTTPSTATUS_INTERNALSERVERERROR;
     1244        enmSts = rtHttpServerRcToStatus(VERR_INTERNAL_ERROR);
    12451245
    12461246    int rc2 = rtHttpServerSendResponseSimple(pClient, enmSts);
     
    12571257 * @returns VBox status code.
    12581258 * @param   pClient             Client to process requests for.
    1259  */
    1260 static int rtHttpServerClientMain(PRTHTTPSERVERCLIENT pClient)
     1259 * @param   msTimeout           Timeout to wait for reading data.
     1260 *                              Gets renewed for a each reading round.
     1261 */
     1262static int rtHttpServerClientMain(PRTHTTPSERVERCLIENT pClient, RTMSINTERVAL msTimeout)
    12611263{
    12621264    int rc;
     
    12691271    pClient->State.msKeepAlive = 0;
    12701272
    1271     RTMSINTERVAL cWaitMs      = RT_INDEFINITE_WAIT; /* The first wait always waits indefinitely. */
     1273    RTMSINTERVAL cWaitMs      = msTimeout;
    12721274    uint64_t     tsLastReadMs = 0;
    12731275
    1274     for (;;)
     1276    for (;;) /* For keep-alive handling. */
    12751277    {
    12761278        rc = RTTcpSelectOne(pClient->hSocket, cWaitMs);
     
    13491351            rc = rtHttpServerProcessRequest(pClient, szReq, cbReadTotal);
    13501352        }
    1351         else
    1352             break;
     1353
     1354        break;
    13531355
    13541356    } /* for */
     
    13951397    Client.hSocket = hSocket;
    13961398
    1397     return rtHttpServerClientMain(&Client);
     1399    return rtHttpServerClientMain(&Client, RT_MS_30SEC /* Timeout */);
    13981400}
    13991401
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