Changeset 100367 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Jul 4, 2023 4:23:18 PM (21 months ago)
- svn:sync-xref-src-repo-rev:
- 158104
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/http-server.cpp
r100250 r100367 689 689 case VERR_IS_A_DIRECTORY: return RTHTTPSTATUS_FORBIDDEN; 690 690 case VERR_NOT_FOUND: return RTHTTPSTATUS_NOTFOUND; 691 case VERR_INTERNAL_ERROR: return RTHTTPSTATUS_INTERNALSERVERERROR; 691 692 default: 692 693 break; … … 713 714 LogFlowFuncEnter(); 714 715 715 int rc = VINF_SUCCESS;716 717 716 /* If a low-level GET request handler is defined, call it and return. */ 718 717 RTHTTPSERVER_HANDLE_CALLBACK_VA_RET(pfnOnGetRequest, pReq); … … 723 722 char *pszMIMEHint = NULL; 724 723 724 RTHTTPSTATUS enmStsResponse = RTHTTPSTATUS_OK; 725 726 int rc; 727 725 728 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnQueryInfo, pReq, &fsObj, &pszMIMEHint); 726 729 if (RT_FAILURE(rc)) 727 return rc;730 enmStsResponse = rtHttpServerRcToStatus(rc); 728 731 729 732 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); 742 785 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. */ 760 808 { 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; 769 811 } 770 812 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) 820 823 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnClose, pReq, pvHandle); 821 824 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; 825 827 826 828 LogFlowFuncLeaveRC(rc); … … 1224 1226 if (RT_FAILURE(rcMethod)) 1225 1227 LogFunc(("Request %s %s failed with %Rrc\n", RTHttpMethodToStr(pReq->enmMethod), pReq->pszUrl, rcMethod)); 1226 1227 enmSts = rtHttpServerRcToStatus(rcMethod);1228 1228 break; 1229 1229 } … … 1242 1242 /* Make sure to return at least *something* to the client, to prevent hangs. */ 1243 1243 if (enmSts == RTHTTPSTATUS_INTERNAL_NOT_SET) 1244 enmSts = RTHTTPSTATUS_INTERNALSERVERERROR;1244 enmSts = rtHttpServerRcToStatus(VERR_INTERNAL_ERROR); 1245 1245 1246 1246 int rc2 = rtHttpServerSendResponseSimple(pClient, enmSts); … … 1257 1257 * @returns VBox status code. 1258 1258 * @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 */ 1262 static int rtHttpServerClientMain(PRTHTTPSERVERCLIENT pClient, RTMSINTERVAL msTimeout) 1261 1263 { 1262 1264 int rc; … … 1269 1271 pClient->State.msKeepAlive = 0; 1270 1272 1271 RTMSINTERVAL cWaitMs = RT_INDEFINITE_WAIT; /* The first wait always waits indefinitely. */1273 RTMSINTERVAL cWaitMs = msTimeout; 1272 1274 uint64_t tsLastReadMs = 0; 1273 1275 1274 for (;;) 1276 for (;;) /* For keep-alive handling. */ 1275 1277 { 1276 1278 rc = RTTcpSelectOne(pClient->hSocket, cWaitMs); … … 1349 1351 rc = rtHttpServerProcessRequest(pClient, szReq, cbReadTotal); 1350 1352 } 1351 else 1352 1353 1354 break; 1353 1355 1354 1356 } /* for */ … … 1395 1397 Client.hSocket = hSocket; 1396 1398 1397 return rtHttpServerClientMain(&Client );1399 return rtHttpServerClientMain(&Client, RT_MS_30SEC /* Timeout */); 1398 1400 } 1399 1401
Note:
See TracChangeset
for help on using the changeset viewer.