Changeset 99937 in vbox
- Timestamp:
- May 23, 2023 3:38:52 PM (17 months ago)
- Location:
- trunk
- Files:
-
- 1 added
- 10 edited
-
include/VBox/GuestHost/SharedClipboard-transfers.h (modified) (16 diffs)
-
include/iprt/http-server.h (modified) (6 diffs)
-
src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp (modified) (3 diffs)
-
src/VBox/GuestHost/SharedClipboard/clipboard-transfers-http.cpp (modified) (9 diffs)
-
src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp (modified) (22 diffs)
-
src/VBox/GuestHost/SharedClipboard/testcase/Makefile.kmk (modified) (1 diff)
-
src/VBox/GuestHost/SharedClipboard/testcase/tstClipboardHttpServer.cpp (added)
-
src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp (modified) (2 diffs)
-
src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp (modified) (2 diffs)
-
src/VBox/Runtime/r3/http-server.cpp (modified) (12 diffs)
-
src/VBox/Runtime/tools/RTHttpServer.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/GuestHost/SharedClipboard-transfers.h
r99405 r99937 117 117 /** Pointer to a Shared Clipboard list handle. */ 118 118 typedef SHCLLISTHANDLE *PSHCLLISTHANDLE; 119 /** Specifies an invalid Shared Clipboard list handle. 120 * @todo r=bird: The convention is NIL_SHCLLISTHANDLE. */ 121 #define SHCLLISTHANDLE_INVALID ((SHCLLISTHANDLE)UINT64_MAX) 119 /** Specifies an invalid Shared Clipboard list handle. */ 120 #define NIL_SHCLLISTHANDLE ((SHCLLISTHANDLE)UINT64_MAX) 122 121 123 122 /** A Shared Clipboard object handle. */ … … 125 124 /** Pointer to a Shared Clipboard object handle. */ 126 125 typedef SHCLOBJHANDLE *PSHCLOBJHANDLE; 127 /** Specifies an invalid Shared Clipboard object handle. 128 * @todo r=bird: The convention is NIL_SHCLOBJHANDLE. */ 129 #define SHCLOBJHANDLE_INVALID ((SHCLOBJHANDLE)UINT64_MAX) 126 /** Specifies an invalid Shared Clipboard object handle. */ 127 #define NIL_SHCLOBJHANDLE ((SHCLOBJHANDLE)UINT64_MAX) 130 128 131 129 /** @} */ … … 473 471 /** Entry name. */ 474 472 char *pszName; 475 /** Size (in bytes) of entry name. */ 473 /** Size (in bytes) of entry name. 474 * Includes terminator. */ 476 475 uint32_t cbName; 477 476 /** Information flag(s). */ … … 485 484 typedef SHCLLISTENTRY *PSHCLLISTENTRY; 486 485 487 /** Maximum length (in UTF-8 characters) of a list entry name. */486 /** Maximum length (in UTF-8 characters) of a list entry name. Includes terminator. */ 488 487 #define SHCLLISTENTRY_MAX_NAME RTPATH_MAX /** @todo Improve this to be more dynamic. */ 489 488 … … 827 826 /** The node member for using this struct in a RTList. */ 828 827 RTLISTNODE Node; 828 /** Number of references to this transfer. */ 829 uint32_t cRefs; 829 830 /** The transfer's state (for SSM, later). */ 830 831 SHCLTRANSFERSTATE State; … … 893 894 894 895 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 896 /** 897 * Structure for keeping a Shared Clipboard HTTP server instance. 898 */ 895 899 typedef struct _SHCLHTTPSERVER 896 900 { … … 905 909 /** Number of registered HTTP transfers. */ 906 910 uint32_t cTransfers; 911 /** Number of files served (via GET) so far. 912 * Only complete downloads count (i.e. no aborted). */ 913 uint32_t cDownloaded; 907 914 /** Cached response data. */ 908 915 RTHTTPSERVERRESP Resp; … … 911 918 typedef SHCLHTTPSERVER *PSHCLHTTPSERVER; 912 919 920 /** 921 * Structure for keeping a Shared Clipboard HTTP context around. 922 * 923 * This contains the HTTP server instance, among other things. 924 */ 913 925 typedef struct _SHCLHTTPCONTEXT 914 926 { … … 923 935 /** 924 936 * Structure for keeping Shared Clipboard transfer context around. 937 * 938 * A transfer context contains a list of (grouped) transfers for book keeping. 925 939 */ 926 940 struct SHCLTRANSFERCTX … … 938 952 /** Number of total transfers (in list). */ 939 953 uint16_t cTransfers; 940 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP941 /** HTTP server instance for this transfer context. */942 SHCLHTTPSERVER HttpServer;943 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */944 954 }; 945 955 956 /** @name Shared Clipboard transfer object API. 957 * @{ 958 */ 946 959 int ShClTransferObjCtxInit(PSHCLCLIENTTRANSFEROBJCTX pObjCtx); 947 960 void ShClTransferObjCtxDestroy(PSHCLCLIENTTRANSFEROBJCTX pObjCtx); … … 957 970 int ShClTransferObjOpen(PSHCLTRANSFER pTransfer, PSHCLOBJOPENCREATEPARMS pOpenCreateParms, PSHCLOBJHANDLE phObj); 958 971 int ShClTransferObjClose(PSHCLTRANSFER pTransfer, SHCLOBJHANDLE hObj); 972 bool ShClTransferObjIsComplete(PSHCLTRANSFER pTransfer, SHCLOBJHANDLE hObj); 959 973 int ShClTransferObjRead(PSHCLTRANSFER pTransfer, SHCLOBJHANDLE hObj, void *pvBuf, uint32_t cbBuf, uint32_t fFlags, uint32_t *pcbRead); 960 974 int ShClTransferObjWrite(PSHCLTRANSFER pTransfer, SHCLOBJHANDLE hObj, void *pvBuf, uint32_t cbBuf, uint32_t fFlags, uint32_t *pcbWritten); … … 963 977 void ShClTransferObjDataChunkDestroy(PSHCLOBJDATACHUNK pDataChunk); 964 978 void ShClTransferObjDataChunkFree(PSHCLOBJDATACHUNK pDataChunk); 965 979 /** @} */ 980 981 /** @name Shared Clipboard transfer API. 982 * @{ 983 */ 966 984 int ShClTransferCreateEx(uint32_t cbMaxChunkSize, uint32_t cMaxListHandles, uint32_t cMaxObjHandles, PSHCLTRANSFER *ppTransfer); 967 985 int ShClTransferCreate(PSHCLTRANSFER *ppTransfer); 968 986 int ShClTransferInit(PSHCLTRANSFER pTransfer, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource); 969 987 int ShClTransferDestroy(PSHCLTRANSFER pTransfer); 988 989 int ShClTransferRun(PSHCLTRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser); 990 int ShClTransferStart(PSHCLTRANSFER pTransfer); 991 992 uint32_t ShClTransferAcquire(PSHCLTRANSFER pTransfer); 993 uint32_t ShClTransferRelease(PSHCLTRANSFER pTransfer); 994 995 SHCLTRANSFERID ShClTransferGetID(PSHCLTRANSFER pTransfer); 996 SHCLTRANSFERDIR ShClTransferGetDir(PSHCLTRANSFER pTransfer); 997 int ShClTransferGetRootPathAbs(PSHCLTRANSFER pTransfer, char *pszPath, size_t cbPath); 998 SHCLSOURCE ShClTransferGetSource(PSHCLTRANSFER pTransfer); 999 SHCLTRANSFERSTATUS ShClTransferGetStatus(PSHCLTRANSFER pTransfer); 970 1000 971 1001 int ShClTransferListOpen(PSHCLTRANSFER pTransfer, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList); … … 1020 1050 int ShClTransferSetProviderIface(PSHCLTRANSFER pTransfer, PSHCLTXPROVIDERCREATIONCTX pCreationCtx); 1021 1051 int ShClTransferRootsSet(PSHCLTRANSFER pTransfer, const char *pszRoots, size_t cbRoots); 1052 int ShClTransferRootsSetAsFile(PSHCLTRANSFER pTransfer, const char *pszFile); 1022 1053 void ShClTransferReset(PSHCLTRANSFER pTransfer); 1023 1054 … … 1025 1056 int ShClTransferRootsEntry(PSHCLTRANSFER pTransfer, uint64_t uIndex, PSHCLROOTLISTENTRY pEntry); 1026 1057 int ShClTransferRootsGet(PSHCLTRANSFER pTransfer, PSHCLROOTLIST *ppRootList); 1027 1028 SHCLTRANSFERID ShClTransferGetID(PSHCLTRANSFER pTransfer); 1029 SHCLTRANSFERDIR ShClTransferGetDir(PSHCLTRANSFER pTransfer); 1030 SHCLSOURCE ShClTransferGetSource(PSHCLTRANSFER pTransfer); 1031 SHCLTRANSFERSTATUS ShClTransferGetStatus(PSHCLTRANSFER pTransfer); 1032 int ShClTransferRun(PSHCLTRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser); 1033 int ShClTransferStart(PSHCLTRANSFER pTransfer); 1034 1058 /** @} */ 1059 1060 /** @name Shared Clipboard transfer context API. 1061 * @{ 1062 */ 1035 1063 int ShClTransferCtxInit(PSHCLTRANSFERCTX pTransferCtx); 1036 1064 void ShClTransferCtxDestroy(PSHCLTRANSFERCTX pTransferCtx); … … 1045 1073 int ShClTransferCtxTransferRegisterById(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID idTransfer); 1046 1074 int ShClTransferCtxTransferUnregister(PSHCLTRANSFERCTX pTransferCtx, SHCLTRANSFERID idTransfer); 1075 /** @} */ 1047 1076 1048 1077 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 1049 int ShClHttpTransferRegister(PSHCLHTTPCONTEXT pCtx, PSHCLTRANSFER pTransfer); 1050 int ShClHttpTransferUnregister(PSHCLHTTPCONTEXT pCtx, PSHCLTRANSFER pTransfer); 1051 1052 int ShClTransferHttpServerCreate(PSHCLHTTPSERVER pSrv, uint16_t *puPort); 1078 /** Namespace used as a prefix for HTTP(S) transfer URLs. */ 1079 #define SHCL_HTTPT_URL_NAMESPACE "vbcl" 1080 1081 /** @name Shared Clipboard HTTP context API. 1082 * @{ 1083 */ 1084 int ShClHttpTransferRegisterAndMaybeStart(PSHCLHTTPCONTEXT pCtx, PSHCLTRANSFER pTransfer); 1085 int ShClHttpTransferUnregisterAndMaybeStop(PSHCLHTTPCONTEXT pCtx, PSHCLTRANSFER pTransfer); 1086 /** @} */ 1087 1088 /** @name Shared Clipboard HTTP server API. 1089 * @{ 1090 */ 1091 int ShClTransferHttpServerCreate(PSHCLHTTPSERVER pSrv, unsigned cMaxAttempts, uint16_t *puPort); 1053 1092 int ShClTransferHttpServerCreateEx(PSHCLHTTPSERVER pSrv, uint16_t uPort); 1054 1093 int ShClTransferHttpServerDestroy(PSHCLHTTPSERVER pSrv); … … 1062 1101 char *ShClTransferHttpServerGetUrlA(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer); 1063 1102 bool ShClTransferHttpServerIsRunning(PSHCLHTTPSERVER pSrv); 1103 /** @} */ 1064 1104 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */ 1065 1105 1066 1106 void ShClFsObjFromIPRT(PSHCLFSOBJINFO pDst, PCRTFSOBJINFO pSrc); 1067 1107 1108 /** @name Shared Clipboard MIME functions. 1109 * @{ 1110 */ 1068 1111 bool ShClMIMEHasFileURLs(const char *pcszFormat, size_t cchFormatMax); 1069 1112 bool ShClMIMENeedsCache(const char *pcszFormat, size_t cchFormatMax); 1113 /** @} */ 1070 1114 1071 1115 const char *ShClTransferStatusToStr(SHCLTRANSFERSTATUS enmStatus); -
trunk/include/iprt/http-server.h
r98103 r99937 73 73 /** Request body data. */ 74 74 RTHTTPBODY Body; 75 /** User-supplied (opaque) pointer. 76 * Can be used for faster lookups between callbacks. */ 77 void *pvUser; 75 78 } RTHTTPSERVERREQ; 76 79 /** Pointer to a HTTP client request. */ … … 134 137 { 135 138 /** 136 * Called before a given URL will be retrieved by the GET method. 139 * Called before beginning to process a request. Guaranteed. 140 * 141 * @returns VBox status code. 142 * @param pData Pointer to HTTP callback data. 143 * @param pReq Pointer to request to handle. 144 */ 145 DECLCALLBACKMEMBER(int, pfnRequestBegin,(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq)); 146 /** 147 * Called after processing a request. Guaranteed. 148 * 149 * @returns VBox status code. 150 * @param pData Pointer to HTTP callback data. 151 * @param pReq Pointer to request to handle. 152 */ 153 DECLCALLBACKMEMBER(int, pfnRequestEnd,(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq)); 154 /** 155 * Opens a resource for a GET request. 156 * 157 * Will be called as as a second function for a GET request. 137 158 * 138 159 * Note: High level function, not being called when pfnOnGetRequest is implemented. … … 145 166 DECLCALLBACKMEMBER(int, pfnOpen,(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, void **ppvHandle)); 146 167 /** 147 * Called when a given URL will be retrieved by the GET method.168 * Reads a resource for a GET request. 148 169 * 149 170 * Note: High level function, not being called when pfnOnGetRequest is implemented. … … 152 173 * @returns VBox status code. 153 174 * @param pData Pointer to HTTP callback data. 175 * @param pReq Pointer to request to handle. 154 176 * @param pvHandle Opaque handle for object identification. 155 177 * @param pvBuf Pointer to buffer where to store the read data. … … 157 179 * @param pcbRead Where to return the amount (in bytes) of read data. Optional and can be NULL. 158 180 */ 159 DECLCALLBACKMEMBER(int, pfnRead,(PRTHTTPCALLBACKDATA pData, void *pvHandle, void *pvBuf, size_t cbBuf, size_t *pcbRead));160 /** 161 * C alled when a given URL is done retrieving by the GET method.181 DECLCALLBACKMEMBER(int, pfnRead,(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, void *pvHandle, void *pvBuf, size_t cbBuf, size_t *pcbRead)); 182 /** 183 * Closes a resouce for a GET a request. 162 184 * 163 185 * Note: High level function, not being called when pfnOnGetRequest is implemented. … … 165 187 * @returns VBox status code. 166 188 * @param pData Pointer to HTTP callback data. 167 * @param p szUrl URLto handle.189 * @param pReq Pointer to request to handle. 168 190 * @param pvHandle Opaque handle for object identification. 169 191 */ 170 DECLCALLBACKMEMBER(int, pfnClose,(PRTHTTPCALLBACKDATA pData, void *pvHandle));192 DECLCALLBACKMEMBER(int, pfnClose,(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, void *pvHandle)); 171 193 /** 172 194 * Queries information about a given URL. 173 195 * 174 * Will be called with GET or HEAD request. 196 * Will be called as first function for a GET or HEAD request. 197 * 198 * Note: High level function, not being called when pfnOnGetRequest is implemented.* 175 199 * 176 200 * @returns VBox status code. -
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp
r98218 r99937 718 718 if (pRootList) 719 719 { 720 SHCLROOTLISTHDR srcRootListHdr; 721 rc = vbglR3ClipboardRootListHdrRead(pCtx, &srcRootListHdr); 722 if (RT_SUCCESS(rc)) 723 { 724 pRootList->Hdr.cRoots = srcRootListHdr.cRoots; 725 pRootList->Hdr.fRoots = 0; /** @todo Implement this. */ 726 727 if (srcRootListHdr.cRoots) 720 rc = vbglR3ClipboardRootListHdrRead(pCtx, &pRootList->Hdr); 721 if (RT_SUCCESS(rc)) 722 { 723 if (pRootList->Hdr.cRoots) 728 724 { 729 725 pRootList->paEntries = 730 (PSHCLROOTLISTENTRY)RTMemAllocZ( srcRootListHdr.cRoots * sizeof(SHCLROOTLISTENTRY));726 (PSHCLROOTLISTENTRY)RTMemAllocZ(pRootList->Hdr.cRoots * sizeof(SHCLROOTLISTENTRY)); 731 727 if (pRootList->paEntries) 732 728 { 733 for (uint32_t i = 0; i < srcRootListHdr.cRoots; i++)729 for (uint32_t i = 0; i < pRootList->Hdr.cRoots; i++) 734 730 { 735 731 SHCLROOTLISTENTRY *pEntry = &pRootList->paEntries[i]; … … 2116 2112 LogFlowFunc(("pszPath=%s\n", openParmsList.pszPath)); 2117 2113 2118 SHCLLISTHANDLE hList = SHCLLISTHANDLE_INVALID;2114 SHCLLISTHANDLE hList = NIL_SHCLLISTHANDLE; 2119 2115 rc = ShClTransferListOpen(pTransfer, &openParmsList, &hList); 2120 2116 … … 2154 2150 /** @todo Handle filter + list features. */ 2155 2151 2156 SHCLLISTHANDLE hList = SHCLLISTHANDLE_INVALID;2152 SHCLLISTHANDLE hList = NIL_SHCLLISTHANDLE; 2157 2153 uint32_t fFlags = 0; 2158 2154 rc = VbglR3ClipboardListHdrReadRecvReq(pCmdCtx, &hList, &fFlags); -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers-http.cpp
r98103 r99937 45 45 #include <iprt/initterm.h> 46 46 #include <iprt/list.h> 47 #define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD48 #include <iprt/log.h>49 47 #include <iprt/mem.h> 50 48 #include <iprt/message.h> … … 56 54 #include <iprt/uuid.h> 57 55 #include <iprt/vfs.h> 56 57 #define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD 58 #include <iprt/log.h> 58 59 59 60 #include <VBox/HostServices/VBoxClipboardSvc.h> … … 78 79 /** The handle we're going to use for this HTTP transfer. */ 79 80 SHCLOBJHANDLE hObj; 80 /** The virtual path of the HTTP server's root directory for this transfer. */ 81 /** The virtual path of the HTTP server's root directory for this transfer. 82 * Always has to start with a "/". */ 81 83 char szPathVirtual[RTPATH_MAX]; 82 84 } SHCLHTTPSERVERTRANSFER; … … 89 91 static int shClTransferHttpServerDestroyInternal(PSHCLHTTPSERVER pThis); 90 92 static const char *shClTransferHttpServerGetHost(PSHCLHTTPSERVER pSrv); 93 static int shClTransferHttpServerDestroyTransfer(PSHCLHTTPSERVER pSrv, PSHCLHTTPSERVERTRANSFER pSrvTx); 91 94 92 95 93 96 /********************************************************************************************************************************* 94 * Public Shared Clipboard HTTP transfer functions*97 * Internal Shared Clipboard HTTP transfer functions * 95 98 *********************************************************************************************************************************/ 96 99 97 /** 98 * Registers a Shared Clipboard transfer to a HTTP context. 100 DECLINLINE(void) shClHttpTransferLock(PSHCLHTTPSERVERTRANSFER pSrvTx) 101 { 102 int rc2 = RTCritSectEnter(&pSrvTx->CritSect); 103 AssertRC(rc2); 104 } 105 106 DECLINLINE(void) shClHttpTransferUnlock(PSHCLHTTPSERVERTRANSFER pSrvTx) 107 { 108 int rc2 = RTCritSectLeave(&pSrvTx->CritSect); 109 AssertRC(rc2); 110 } 111 112 /** 113 * Return the HTTP server transfer for a specific transfer ID. 114 * 115 * @returns Pointer to HTTP server transfer if found, NULL if not found. 116 * @param pSrv HTTP server instance. 117 * @param idTransfer Transfer ID to return HTTP server transfer for. 118 */ 119 static PSHCLHTTPSERVERTRANSFER shClTransferHttpServerGetTransferById(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer) 120 { 121 PSHCLHTTPSERVERTRANSFER pSrvTx; 122 RTListForEach(&pSrv->lstTransfers, pSrvTx, SHCLHTTPSERVERTRANSFER, Node) /** @todo Slow O(n) lookup, but does it for now. */ 123 { 124 if (pSrvTx->pTransfer->State.uID == idTransfer) 125 return pSrvTx; 126 } 127 128 return NULL; 129 } 130 131 /** 132 * Returns a HTTP server transfer from a given URL. 133 * 134 * @returns Pointer to HTTP server transfer if found, NULL if not found. 135 * @param pThis HTTP server instance data. 136 * @param pszUrl URL to validate. 137 */ 138 DECLINLINE(PSHCLHTTPSERVERTRANSFER) shClTransferHttpGetTransferFromUrl(PSHCLHTTPSERVER pThis, const char *pszUrl) 139 { 140 AssertPtrReturn(pszUrl, NULL); 141 142 PSHCLHTTPSERVERTRANSFER pSrvTx = NULL; 143 144 PSHCLHTTPSERVERTRANSFER pSrvTxCur; 145 RTListForEach(&pThis->lstTransfers, pSrvTxCur, SHCLHTTPSERVERTRANSFER, Node) 146 { 147 AssertPtr(pSrvTxCur->pTransfer); 148 149 LogFlowFunc(("pSrvTxCur=%s\n", pSrvTxCur->szPathVirtual)); 150 151 /* Be picky here, do a case sensitive comparison. */ 152 if (RTStrStartsWith(pszUrl, pSrvTxCur->szPathVirtual)) 153 { 154 pSrvTx = pSrvTxCur; 155 break; 156 } 157 } 158 159 if (!pSrvTx) 160 LogRel2(("Shared Clipboard: HTTP URL '%s' not valid\n", pszUrl)); 161 162 LogFlowFunc(("pszUrl=%s, pSrvTx=%p\n", pszUrl, pSrvTx)); 163 return pSrvTx; 164 } 165 166 /** 167 * Returns a HTTP server transfer from an internal HTTP handle. 168 * 169 * @returns Pointer to HTTP server transfer if found, NULL if not found. 170 * @param pThis HTTP server instance data. 171 * @param pvHandle Handle to return transfer for. 172 */ 173 DECLINLINE(PSHCLHTTPSERVERTRANSFER) shClTransferHttpGetTransferFromHandle(PSHCLHTTPSERVER pThis, void *pvHandle) 174 { 175 AssertPtrReturn(pvHandle, NULL); 176 177 const SHCLTRANSFERID uHandle = *(uint16_t *)pvHandle; 178 179 /** @ŧodo Use a handle lookup table (map) later. */ 180 PSHCLHTTPSERVERTRANSFER pSrvTxCur; 181 RTListForEach(&pThis->lstTransfers, pSrvTxCur, SHCLHTTPSERVERTRANSFER, Node) 182 { 183 AssertPtr(pSrvTxCur->pTransfer); 184 185 if (pSrvTxCur->pTransfer->State.uID == uHandle) /** @ŧodo We're using the transfer ID as handle for now. */ 186 return pSrvTxCur; 187 } 188 189 return NULL; 190 } 191 192 static int shClTransferHttpGetTransferRoots(PSHCLHTTPSERVER pThis, PSHCLHTTPSERVERTRANSFER pSrvTx) 193 { 194 RT_NOREF(pThis); 195 196 int rc = VINF_SUCCESS; 197 198 if (pSrvTx->pRootList == NULL) 199 { 200 AssertMsgReturn(ShClTransferRootsCount(pSrvTx->pTransfer) == 1, 201 ("At the moment only single files are supported!\n"), VERR_NOT_SUPPORTED); 202 203 rc = ShClTransferRootsGet(pSrvTx->pTransfer, &pSrvTx->pRootList); 204 } 205 206 return rc; 207 } 208 209 210 /********************************************************************************************************************************* 211 * HTTP server callback implementations * 212 *********************************************************************************************************************************/ 213 214 /** @copydoc RTHTTPSERVERCALLBACKS::pfnRequestBegin */ 215 static DECLCALLBACK(int) shClTransferHttpBegin(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq) 216 { 217 PSHCLHTTPSERVER pThis = (PSHCLHTTPSERVER)pData->pvUser; RT_NOREF(pThis); 218 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER)); 219 220 LogRel2(("Shared Clipboard: HTTP request begin\n")); 221 222 PSHCLHTTPSERVERTRANSFER pSrvTx = shClTransferHttpGetTransferFromUrl(pThis, pReq->pszUrl); 223 if (pSrvTx) 224 { 225 shClHttpTransferLock(pSrvTx); 226 pReq->pvUser = pSrvTx; 227 } 228 229 return VINF_SUCCESS; 230 } 231 232 /** @copydoc RTHTTPSERVERCALLBACKS::pfnRequestEnd */ 233 static DECLCALLBACK(int) shClTransferHttpEnd(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq) 234 { 235 PSHCLHTTPSERVER pThis = (PSHCLHTTPSERVER)pData->pvUser; RT_NOREF(pThis); 236 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER)); 237 238 LogRel2(("Shared Clipboard: HTTP request end\n")); 239 240 PSHCLHTTPSERVERTRANSFER pSrvTx = (PSHCLHTTPSERVERTRANSFER)pReq->pvUser; 241 if (pSrvTx) 242 { 243 shClHttpTransferUnlock(pSrvTx); 244 pReq->pvUser = NULL; 245 } 246 247 return VINF_SUCCESS; 248 249 } 250 251 /** @copydoc RTHTTPSERVERCALLBACKS::pfnOpen */ 252 static DECLCALLBACK(int) shClTransferHttpOpen(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, void **ppvHandle) 253 { 254 PSHCLHTTPSERVER pThis = (PSHCLHTTPSERVER)pData->pvUser; RT_NOREF(pThis); 255 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER)); 256 257 int rc; 258 259 AssertPtr(pReq->pvUser); 260 PSHCLHTTPSERVERTRANSFER pSrvTx = (PSHCLHTTPSERVERTRANSFER)pReq->pvUser; 261 if (pSrvTx) 262 { 263 LogRel2(("Shared Clipboard: HTTP transfer (handle %RU64) started ...\n", pSrvTx->hObj)); 264 265 Assert(pSrvTx->hObj != NIL_SHCLOBJHANDLE); 266 *ppvHandle = &pSrvTx->hObj; 267 } 268 else 269 rc = VERR_NOT_FOUND; 270 271 if (RT_FAILURE(rc)) 272 LogRel(("Shared Clipboard: Error starting HTTP transfer for '%s', rc=%Rrc\n", pReq->pszUrl, rc)); 273 274 LogFlowFuncLeaveRC(rc); 275 return rc; 276 } 277 278 /** @copydoc RTHTTPSERVERCALLBACKS::pfnRead */ 279 static DECLCALLBACK(int) shClTransferHttpRead(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, 280 void *pvHandle, void *pvBuf, size_t cbBuf, size_t *pcbRead) 281 { 282 RT_NOREF(pData); 283 284 int rc; 285 286 LogRel3(("Shared Clipboard: Reading %RU32 bytes from HTTP ...\n", cbBuf)); 287 288 AssertPtr(pReq->pvUser); 289 PSHCLHTTPSERVERTRANSFER pSrvTx = (PSHCLHTTPSERVERTRANSFER)pReq->pvUser; 290 if (pSrvTx) 291 { 292 PSHCLOBJHANDLE phObj = (PSHCLOBJHANDLE)pvHandle; 293 if (phObj) 294 { 295 uint32_t cbRead; 296 rc = ShClTransferObjRead(pSrvTx->pTransfer, *phObj, pvBuf, cbBuf, 0 /* fFlags */, &cbRead); 297 if (RT_SUCCESS(rc)) 298 *pcbRead = (uint32_t)cbRead; 299 300 if (RT_FAILURE(rc)) 301 LogRel(("Shared Clipboard: Error reading HTTP transfer (handle %RU64), rc=%Rrc\n", *phObj, rc)); 302 } 303 else 304 rc = VERR_NOT_FOUND; 305 } 306 else 307 rc = VERR_NOT_FOUND; 308 309 LogFlowFuncLeaveRC(rc); 310 return rc; 311 } 312 313 /** @copydoc RTHTTPSERVERCALLBACKS::pfnClose */ 314 static DECLCALLBACK(int) shClTransferHttpClose(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, void *pvHandle) 315 { 316 RT_NOREF(pData); 317 318 int rc; 319 320 AssertPtr(pReq->pvUser); 321 PSHCLHTTPSERVERTRANSFER pSrvTx = (PSHCLHTTPSERVERTRANSFER)pReq->pvUser; 322 if (pSrvTx) 323 { 324 PSHCLOBJHANDLE phObj = (PSHCLOBJHANDLE)pvHandle; 325 if (phObj) 326 { 327 Assert(*phObj != NIL_SHCLOBJHANDLE); 328 rc = ShClTransferObjClose(pSrvTx->pTransfer, *phObj); 329 if (RT_SUCCESS(rc)) 330 { 331 pSrvTx->hObj = NIL_SHCLOBJHANDLE; 332 LogRel2(("Shared Clipboard: HTTP transfer %RU16 done\n", pSrvTx->pTransfer->State.uID)); 333 } 334 335 if (RT_FAILURE(rc)) 336 LogRel(("Shared Clipboard: Error closing HTTP transfer (handle %RU64), rc=%Rrc\n", *phObj, rc)); 337 } 338 else 339 rc = VERR_NOT_FOUND; 340 } 341 else 342 rc = VERR_NOT_FOUND; 343 344 LogFlowFuncLeaveRC(rc); 345 return rc; 346 } 347 348 /** @copydoc RTHTTPSERVERCALLBACKS::pfnQueryInfo */ 349 static DECLCALLBACK(int) shClTransferHttpQueryInfo(PRTHTTPCALLBACKDATA pData, 350 PRTHTTPSERVERREQ pReq, PRTFSOBJINFO pObjInfo, char **ppszMIMEHint) 351 { 352 RT_NOREF(ppszMIMEHint); 353 354 PSHCLHTTPSERVER pThis = (PSHCLHTTPSERVER)pData->pvUser; 355 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER)); 356 357 int rc; 358 359 PSHCLHTTPSERVERTRANSFER pSrvTx = (PSHCLHTTPSERVERTRANSFER)pReq->pvUser; 360 if (pSrvTx) 361 { 362 rc = shClTransferHttpGetTransferRoots(pThis, pSrvTx); 363 if (RT_SUCCESS(rc)) 364 { 365 SHCLOBJOPENCREATEPARMS openParms; 366 rc = ShClTransferObjOpenParmsInit(&openParms); 367 if (RT_SUCCESS(rc)) 368 { 369 openParms.fCreate = SHCL_OBJ_CF_ACCESS_READ 370 | SHCL_OBJ_CF_ACCESS_DENYWRITE; 371 372 PSHCLTRANSFER pTx = pSrvTx->pTransfer; 373 AssertPtr(pTx); 374 375 /* For now we only serve single files, hence index 0 below. */ 376 SHCLROOTLISTENTRY ListEntry; 377 rc = ShClTransferRootsEntry(pTx, 0 /* First file */, &ListEntry); 378 if (RT_SUCCESS(rc)) 379 { 380 rc = RTStrCopy(openParms.pszPath, openParms.cbPath, ListEntry.pszName); 381 if (RT_SUCCESS(rc)) 382 { 383 rc = ShClTransferObjOpen(pTx, &openParms, &pSrvTx->hObj); 384 if (RT_SUCCESS(rc)) 385 { 386 char szPath[RTPATH_MAX]; 387 rc = ShClTransferGetRootPathAbs(pTx, szPath, sizeof(szPath)); 388 if (RT_SUCCESS(rc)) 389 { 390 rc = RTPathAppend(szPath, sizeof(szPath), openParms.pszPath); 391 if (RT_SUCCESS(rc)) 392 { 393 /* Now that the object is locked, query information that we can return. */ 394 rc = RTPathQueryInfo(szPath, pObjInfo, RTFSOBJATTRADD_NOTHING); 395 } 396 } 397 } 398 } 399 } 400 401 ShClTransferObjOpenParmsDestroy(&openParms); 402 } 403 } 404 } 405 else 406 rc = VERR_NOT_FOUND; 407 408 LogFlowFuncLeaveRC(rc); 409 return rc; 410 } 411 412 /** @copydoc RTHTTPSERVERCALLBACKS::pfnDestroy */ 413 static DECLCALLBACK(int) shClTransferHttpDestroy(PRTHTTPCALLBACKDATA pData) 414 { 415 PSHCLHTTPSERVER pThis = (PSHCLHTTPSERVER)pData->pvUser; 416 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER)); 417 418 return shClTransferHttpServerDestroyInternal(pThis); 419 } 420 421 422 /********************************************************************************************************************************* 423 * Internal Shared Clipboard HTTP server functions * 424 *********************************************************************************************************************************/ 425 426 /** 427 * Destroys a Shared Clipboard HTTP server instance, internal version. 428 * 429 * @returns VBox status code. 430 * @param pSrv Shared Clipboard HTTP server instance to destroy. 431 */ 432 static int shClTransferHttpServerDestroyInternal(PSHCLHTTPSERVER pSrv) 433 { 434 int rc = VINF_SUCCESS; 435 436 PSHCLHTTPSERVERTRANSFER pSrvTx, pSrvTxNext; 437 RTListForEachSafe(&pSrv->lstTransfers, pSrvTx, pSrvTxNext, SHCLHTTPSERVERTRANSFER, Node) 438 { 439 int rc2 = shClTransferHttpServerDestroyTransfer(pSrv, pSrvTx); 440 if (RT_SUCCESS(rc)) 441 rc = rc2; 442 } 443 444 RTHttpServerResponseDestroy(&pSrv->Resp); 445 446 pSrv->hHTTPServer = NIL_RTHTTPSERVER; 447 448 if (RTCritSectIsInitialized(&pSrv->CritSect)) 449 { 450 int rc2 = RTCritSectDelete(&pSrv->CritSect); 451 if (RT_SUCCESS(rc)) 452 rc = rc2; 453 } 454 455 return rc; 456 } 457 458 /** 459 * Locks the critical section of a Shared Clipboard HTTP server instance. 460 * 461 * @param pSrv Shared Clipboard HTTP server instance to lock. 462 */ 463 DECLINLINE(void) shClTransferHttpServerLock(PSHCLHTTPSERVER pSrv) 464 { 465 int rc2 = RTCritSectEnter(&pSrv->CritSect); 466 AssertRC(rc2); 467 } 468 469 /** 470 * Unlocks the critical section of a Shared Clipboard HTTP server instance. 471 * 472 * @param pSrv Shared Clipboard HTTP server instance to unlock. 473 */ 474 DECLINLINE(void) shClTransferHttpServerUnlock(PSHCLHTTPSERVER pSrv) 475 { 476 int rc2 = RTCritSectLeave(&pSrv->CritSect); 477 AssertRC(rc2); 478 } 479 480 /** 481 * Initializes a new Shared Clipboard HTTP server instance. 482 * 483 * @param pSrv HTTP server instance to initialize. 484 */ 485 static void shClTransferHttpServerInitInternal(PSHCLHTTPSERVER pSrv) 486 { 487 pSrv->hHTTPServer = NIL_RTHTTPSERVER; 488 pSrv->uPort = 0; 489 RTListInit(&pSrv->lstTransfers); 490 pSrv->cTransfers = 0; 491 int rc2 = RTHttpServerResponseInit(&pSrv->Resp); 492 AssertRC(rc2); 493 } 494 495 496 /********************************************************************************************************************************* 497 * Public Shared Clipboard HTTP server functions * 498 *********************************************************************************************************************************/ 499 500 /** 501 * Initializes a new Shared Clipboard HTTP server instance. 502 * 503 * @param pSrv HTTP server instance to initialize. 504 */ 505 void ShClTransferHttpServerInit(PSHCLHTTPSERVER pSrv) 506 { 507 AssertPtrReturnVoid(pSrv); 508 509 shClTransferHttpServerInitInternal(pSrv); 510 } 511 512 /** 513 * Returns whether a given TCP port is known to be buggy or not. 514 * 515 * @returns \c true if the given port is known to be buggy, or \c false if not. 516 * @param uPort TCP port to check. 517 */ 518 static bool shClTransferHttpServerPortIsBuggy(uint16_t uPort) 519 { 520 uint16_t const aBuggyPorts[] = { 521 #if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) 522 /* GNOME Nautilus ("Files") v43 is unable download HTTP files from this port. */ 523 8080 524 #else /* Prevents zero-sized arrays. */ 525 0 526 #endif 527 }; 528 529 for (size_t i = 0; i < RT_ELEMENTS(aBuggyPorts); i++) 530 if (uPort == aBuggyPorts[i]) 531 return true; 532 return false; 533 } 534 535 /** 536 * Creates a new Shared Clipboard HTTP server instance, extended version. 537 * 538 * @returns VBox status code. 539 * @return VERR_ADDRESS_CONFLICT if the port is already taken or the port is known to be buggy. 540 * @param pSrv HTTP server instance to create. 541 * @param uPort TCP port number to use. 542 */ 543 int ShClTransferHttpServerCreateEx(PSHCLHTTPSERVER pSrv, uint16_t uPort) 544 { 545 AssertPtrReturn(pSrv, VERR_INVALID_POINTER); 546 AssertReturn(uPort, VERR_INVALID_PARAMETER); 547 548 AssertReturn(!shClTransferHttpServerPortIsBuggy(uPort), VERR_ADDRESS_CONFLICT); 549 550 RTHTTPSERVERCALLBACKS Callbacks; 551 RT_ZERO(Callbacks); 552 553 Callbacks.pfnRequestBegin = shClTransferHttpBegin; 554 Callbacks.pfnRequestEnd = shClTransferHttpEnd; 555 Callbacks.pfnOpen = shClTransferHttpOpen; 556 Callbacks.pfnRead = shClTransferHttpRead; 557 Callbacks.pfnClose = shClTransferHttpClose; 558 Callbacks.pfnQueryInfo = shClTransferHttpQueryInfo; 559 Callbacks.pfnDestroy = shClTransferHttpDestroy; 560 561 /* Note: The server always and *only* runs against the localhost interface. */ 562 int rc = RTHttpServerCreate(&pSrv->hHTTPServer, "localhost", uPort, &Callbacks, 563 pSrv, sizeof(SHCLHTTPSERVER)); 564 if (RT_SUCCESS(rc)) 565 { 566 rc = RTCritSectInit(&pSrv->CritSect); 567 AssertRCReturn(rc, rc); 568 569 pSrv->uPort = uPort; 570 571 LogRel2(("Shared Clipboard: HTTP server running at port %RU16\n", pSrv->uPort)); 572 } 573 else 574 { 575 int rc2 = shClTransferHttpServerDestroyInternal(pSrv); 576 AssertRC(rc2); 577 } 578 579 if (RT_FAILURE(rc)) 580 LogRel(("Shared Clipboard: HTTP server failed to run, rc=%Rrc\n", rc)); 581 582 return rc; 583 } 584 585 /** 586 * Creates a new Shared Clipboard HTTP server instance using a random port (>= 1024). 587 * 588 * This does automatic probing of TCP ports if a port already is being used. 589 * 590 * @returns VBox status code. 591 * @param pSrv HTTP server instance to create. 592 * @param cMaxAttempts Maximum number of attempts to create a HTTP server. 593 * @param puPort Where to return the TCP port number being used on success. Optional. 594 */ 595 int ShClTransferHttpServerCreate(PSHCLHTTPSERVER pSrv, unsigned cMaxAttempts, uint16_t *puPort) 596 { 597 AssertPtrReturn(pSrv, VERR_INVALID_POINTER); 598 AssertReturn(cMaxAttempts, VERR_INVALID_PARAMETER); 599 /* puPort is optional. */ 600 601 RTRAND hRand; 602 int rc = RTRandAdvCreateSystemFaster(&hRand); /* Should be good enough for this task. */ 603 if (RT_SUCCESS(rc)) 604 { 605 uint16_t uPort; 606 unsigned i = 0; 607 for (i; i < cMaxAttempts; i++) 608 { 609 /* Try some random ports above 1024 (i.e. "unprivileged ports") -- required, as VBoxClient runs as a user process 610 * on the guest. */ 611 uPort = RTRandAdvU32Ex(hRand, 1024, UINT16_MAX); 612 613 /* If the port selected turns is known to be buggy for whatever reason, skip it and try another one. */ 614 if (shClTransferHttpServerPortIsBuggy(uPort)) 615 continue; 616 617 rc = ShClTransferHttpServerCreateEx(pSrv, (uint32_t)uPort); 618 if (RT_SUCCESS(rc)) 619 { 620 if (puPort) 621 *puPort = uPort; 622 break; 623 } 624 } 625 626 if ( RT_FAILURE(rc) 627 && i == cMaxAttempts) 628 LogRel(("Shared Clipboard: Maximum attempts to create HTTP server reached (%u), giving up\n", cMaxAttempts)); 629 630 RTRandAdvDestroy(hRand); 631 } 632 633 return rc; 634 } 635 636 /** 637 * Destroys a Shared Clipboard HTTP server instance. 638 * 639 * @returns VBox status code. 640 * @param pSrv HTTP server instance to destroy. 641 */ 642 int ShClTransferHttpServerDestroy(PSHCLHTTPSERVER pSrv) 643 { 644 AssertPtrReturn(pSrv, VERR_INVALID_POINTER); 645 646 if (pSrv->hHTTPServer == NIL_RTHTTPSERVER) 647 return VINF_SUCCESS; 648 649 int rc = RTHttpServerDestroy(pSrv->hHTTPServer); 650 if (RT_SUCCESS(rc)) 651 rc = shClTransferHttpServerDestroyInternal(pSrv); 652 653 if (RT_SUCCESS(rc)) 654 LogRel2(("Shared Clipboard: HTTP server stopped\n")); 655 else 656 LogRel(("Shared Clipboard: HTTP server failed to stop, rc=%Rrc\n", rc)); 657 658 return rc; 659 } 660 661 /** 662 * Returns the host name (scheme) of a HTTP server instance. 663 * 664 * @returns Host name (scheme). 665 * @param pSrv HTTP server instance to return host name (scheme) for. 666 * 667 * @note This is hardcoded to "localhost" for now. 668 */ 669 static const char *shClTransferHttpServerGetHost(PSHCLHTTPSERVER pSrv) 670 { 671 RT_NOREF(pSrv); 672 return "http://localhost"; /* Hardcoded for now. */ 673 } 674 675 /** 676 * Destroys a server transfer, internal version. 677 * 678 * @returns VBox status code. 679 * @param pSrv HTTP server instance to unregister transfer from. 680 * @param pTransfer Server transfer to destroy 681 * The pointer will be invalid on success. 682 */ 683 static int shClTransferHttpServerDestroyTransfer(PSHCLHTTPSERVER pSrv, PSHCLHTTPSERVERTRANSFER pSrvTx) 684 { 685 RTListNodeRemove(&pSrvTx->Node); 686 687 Assert(pSrv->cTransfers); 688 pSrv->cTransfers--; 689 690 LogFunc(("pTransfer=%p, idTransfer=%RU16, szPath=%s -> %RU32 transfers\n", 691 pSrvTx->pTransfer, pSrvTx->pTransfer->State.uID, pSrvTx->szPathVirtual, pSrv->cTransfers)); 692 693 LogRel2(("Shared Clipboard: Destroyed HTTP transfer %RU16, now %RU32 HTTP transfers total\n", 694 pSrvTx->pTransfer->State.uID, pSrv->cTransfers)); 695 696 int rc = RTCritSectDelete(&pSrvTx->CritSect); 697 AssertRCReturn(rc, rc); 698 699 RTMemFree(pSrvTx); 700 pSrvTx = NULL; 701 702 return rc; 703 } 704 705 706 /********************************************************************************************************************************* 707 * Public Shared Clipboard HTTP server functions * 708 *********************************************************************************************************************************/ 709 710 /** 711 * Registers a Shared Clipboard transfer to a HTTP server instance. 712 * 713 * @returns VBox status code. 714 * @param pSrv HTTP server instance to register transfer for. 715 * @param pTransfer Transfer to register. Needs to be on the heap. 716 */ 717 int ShClTransferHttpServerRegisterTransfer(PSHCLHTTPSERVER pSrv, PSHCLTRANSFER pTransfer) 718 { 719 AssertPtrReturn(pSrv, VERR_INVALID_POINTER); 720 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 721 722 AssertMsgReturn(pTransfer->State.uID, ("Transfer needs to be registered with a transfer context first\n"), 723 VERR_INVALID_PARAMETER); 724 725 uint32_t const cRoots = ShClTransferRootsCount(pTransfer); 726 AssertMsgReturn(cRoots > 0, ("Transfer has no root entries\n"), VERR_INVALID_PARAMETER); 727 AssertMsgReturn(cRoots == 1, ("Only single files are supported for now\n"), VERR_NOT_SUPPORTED); 728 /** @todo Check for directories? */ 729 730 shClTransferHttpServerLock(pSrv); 731 732 PSHCLHTTPSERVERTRANSFER pSrvTx = (PSHCLHTTPSERVERTRANSFER)RTMemAllocZ(sizeof(SHCLHTTPSERVERTRANSFER)); 733 AssertPtrReturn(pSrvTx, VERR_NO_MEMORY); 734 735 RTUUID Uuid; 736 int rc = RTUuidCreate(&Uuid); 737 if (RT_SUCCESS(rc)) 738 { 739 char szUuid[64]; 740 rc = RTUuidToStr(&Uuid, szUuid, sizeof(szUuid)); 741 if (RT_SUCCESS(rc)) 742 { 743 rc = RTCritSectInit(&pSrvTx->CritSect); 744 AssertRC(rc); 745 746 SHCLROOTLISTENTRY ListEntry; 747 rc = ShClTransferRootsEntry(pTransfer, 0 /* First file */, &ListEntry); 748 if (RT_SUCCESS(rc)) 749 { 750 #ifdef DEBUG_andy 751 /* Create the virtual HTTP path for the transfer. 752 * Every transfer has a dedicated HTTP path (but live in the same URL namespace). */ 753 ssize_t cch = RTStrPrintf2(pSrvTx->szPathVirtual, sizeof(pSrvTx->szPathVirtual), "/%s/uuid/%RU32/%s", 754 SHCL_HTTPT_URL_NAMESPACE, pSrv->cTransfers, ListEntry.pszName); 755 #else 756 /* Create the virtual HTTP path for the transfer. 757 * Every transfer has a dedicated HTTP path (but live in the same URL namespace). */ 758 ssize_t cch = RTStrPrintf2(pSrvTx->szPathVirtual, sizeof(pSrvTx->szPathVirtual), "/%s/%s/%RU16/%s", 759 SHCL_HTTPT_URL_NAMESPACE, szUuid, pTransfer->State.uID, ListEntry.pszName); 760 #endif 761 AssertReturn(cch, VERR_BUFFER_OVERFLOW); 762 763 pSrvTx->pTransfer = pTransfer; 764 pSrvTx->pRootList = NULL; 765 pSrvTx->hObj = NIL_SHCLOBJHANDLE; 766 767 RTListAppend(&pSrv->lstTransfers, &pSrvTx->Node); 768 pSrv->cTransfers++; 769 770 LogFunc(("pTransfer=%p, idTransfer=%RU16, szPath=%s -> %RU32 transfers\n", 771 pSrvTx->pTransfer, pSrvTx->pTransfer->State.uID, pSrvTx->szPathVirtual, pSrv->cTransfers)); 772 773 LogRel2(("Shared Clipboard: Registered HTTP transfer %RU16, now %RU32 HTTP transfers total\n", 774 pTransfer->State.uID, pSrv->cTransfers)); 775 } 776 } 777 } 778 779 if (RT_FAILURE(rc)) 780 RTMemFree(pSrvTx); 781 782 shClTransferHttpServerUnlock(pSrv); 783 784 LogFlowFuncLeaveRC(rc); 785 return rc; 786 } 787 788 /** 789 * Unregisters a formerly registered Shared Clipboard transfer. 790 * 791 * @returns VBox status code. 792 * @param pSrv HTTP server instance to unregister transfer from. 793 * @param pTransfer Transfer to unregister. 794 */ 795 int ShClTransferHttpServerUnregisterTransfer(PSHCLHTTPSERVER pSrv, PSHCLTRANSFER pTransfer) 796 { 797 AssertPtrReturn(pSrv, VERR_INVALID_POINTER); 798 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 799 800 shClTransferHttpServerLock(pSrv); 801 802 AssertReturn(pSrv->cTransfers, VERR_WRONG_ORDER); 803 804 int rc = VINF_SUCCESS; 805 806 PSHCLHTTPSERVERTRANSFER pSrvTx; 807 RTListForEach(&pSrv->lstTransfers, pSrvTx, SHCLHTTPSERVERTRANSFER, Node) 808 { 809 AssertPtr(pSrvTx->pTransfer); 810 if (pSrvTx->pTransfer->State.uID == pTransfer->State.uID) 811 { 812 rc = shClTransferHttpServerDestroyTransfer(pSrv, pSrvTx); 813 break; 814 } 815 } 816 817 shClTransferHttpServerUnlock(pSrv); 818 819 LogFlowFuncLeaveRC(rc); 820 return rc; 821 } 822 823 /** 824 * Returns whether a specific transfer ID is registered with a HTTP server instance or not. 825 * 826 * @returns \c true if the transfer ID is registered, \c false if not. 827 * @param pSrv HTTP server instance. 828 * @param idTransfer Transfer ID to check for. 829 */ 830 bool ShClTransferHttpServerHasTransfer(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer) 831 { 832 AssertPtrReturn(pSrv, false); 833 834 shClTransferHttpServerLock(pSrv); 835 836 const bool fRc = shClTransferHttpServerGetTransferById(pSrv, idTransfer) != NULL; 837 838 shClTransferHttpServerUnlock(pSrv); 839 840 return fRc; 841 } 842 843 /** 844 * Returns the used TCP port number of a HTTP server instance. 845 * 846 * @returns TCP port number. 0 if not specified yet. 847 * @param pSrv HTTP server instance to return port for. 848 */ 849 uint16_t ShClTransferHttpServerGetPort(PSHCLHTTPSERVER pSrv) 850 { 851 AssertPtrReturn(pSrv, 0); 852 853 shClTransferHttpServerLock(pSrv); 854 855 const uint16_t uPort = pSrv->uPort; 856 857 shClTransferHttpServerUnlock(pSrv); 858 859 return uPort; 860 } 861 862 /** 863 * Returns the number of registered HTTP server transfers of a HTTP server instance. 864 * 865 * @returns Number of registered transfers. 866 * @param pSrv HTTP server instance to return registered transfers for. 867 */ 868 uint32_t ShClTransferHttpServerGetTransferCount(PSHCLHTTPSERVER pSrv) 869 { 870 AssertPtrReturn(pSrv, 0); 871 872 shClTransferHttpServerLock(pSrv); 873 874 const uint32_t cTransfers = pSrv->cTransfers; 875 876 shClTransferHttpServerUnlock(pSrv); 877 878 return cTransfers; 879 } 880 881 /** 882 * Returns an allocated string with a HTTP server instance's address. 883 * 884 * @returns Allocated string with a HTTP server instance's address, or NULL on OOM. 885 * Needs to be free'd by the caller using RTStrFree(). 886 * @param pSrv HTTP server instance to return address for. 887 */ 888 char *ShClTransferHttpServerGetAddressA(PSHCLHTTPSERVER pSrv) 889 { 890 AssertPtrReturn(pSrv, NULL); 891 892 shClTransferHttpServerLock(pSrv); 893 894 char *pszAddress = RTStrAPrintf2("%s:%RU16", shClTransferHttpServerGetHost(pSrv), pSrv->uPort); 895 AssertPtr(pszAddress); 896 897 shClTransferHttpServerUnlock(pSrv); 898 899 return pszAddress; 900 } 901 902 /** 903 * Returns an allocated string with the URL of a given Shared Clipboard transfer ID. 904 * 905 * @returns Allocated string with the URL of a given Shared Clipboard transfer ID, or NULL if not found. 906 * Needs to be free'd by the caller using RTStrFree(). 907 * @param pSrv HTTP server instance to return URL for. 908 * @param idTransfer Transfer ID to return the URL for. 909 */ 910 char *ShClTransferHttpServerGetUrlA(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer) 911 { 912 AssertPtrReturn(pSrv, NULL); 913 AssertReturn(idTransfer != NIL_SHCLTRANSFERID, NULL); 914 915 shClTransferHttpServerLock(pSrv); 916 917 PSHCLHTTPSERVERTRANSFER pSrvTx = shClTransferHttpServerGetTransferById(pSrv, idTransfer); 918 if (!pSrvTx) 919 { 920 AssertFailed(); 921 shClTransferHttpServerUnlock(pSrv); 922 return NULL; 923 } 924 925 AssertReturn(RTStrNLen(pSrvTx->szPathVirtual, RTPATH_MAX), NULL); 926 char *pszUrl = RTStrAPrintf2("%s:%RU16%s", shClTransferHttpServerGetHost(pSrv), pSrv->uPort, pSrvTx->szPathVirtual); 927 AssertPtr(pszUrl); 928 929 shClTransferHttpServerUnlock(pSrv); 930 931 return pszUrl; 932 } 933 934 /** 935 * Returns whether a given HTTP server instance is running or not. 936 * 937 * @returns \c true if running, or \c false if not. 938 * @param pSrv HTTP server instance to check running state for. 939 */ 940 bool ShClTransferHttpServerIsRunning(PSHCLHTTPSERVER pSrv) 941 { 942 AssertPtrReturn(pSrv, false); 943 944 return (pSrv->hHTTPServer != NIL_RTHTTPSERVER); /* Seems enough for now. */ 945 } 946 947 948 /********************************************************************************************************************************* 949 * Public Shared Clipboard HTTP context functions * 950 *********************************************************************************************************************************/ 951 952 /** 953 * Registers a Shared Clipboard transfer to a HTTP context and starts the HTTP server, if not started already. 99 954 * 100 955 * @returns VBox status code. … … 102 957 * @param pTransfer Transfer to register. 103 958 */ 104 int ShClHttpTransferRegister (PSHCLHTTPCONTEXT pCtx, PSHCLTRANSFER pTransfer)959 int ShClHttpTransferRegisterAndMaybeStart(PSHCLHTTPCONTEXT pCtx, PSHCLTRANSFER pTransfer) 105 960 { 106 961 int rc = VINF_SUCCESS; … … 108 963 /* Start the built-in HTTP server to serve file(s). */ 109 964 if (!ShClTransferHttpServerIsRunning(&pCtx->HttpServer)) /* Only one HTTP server per transfer context. */ 110 rc = ShClTransferHttpServerCreate(&pCtx->HttpServer, NULL /* puPort */);965 rc = ShClTransferHttpServerCreate(&pCtx->HttpServer, 32 /* cMaxAttempts */, NULL /* puPort */); 111 966 112 967 if (RT_SUCCESS(rc)) … … 117 972 118 973 /** 119 * Unregisters a formerly registered Shared Clipboard transfer .974 * Unregisters a formerly registered Shared Clipboard transfer and stops the HTTP server, if no transfers are left. 120 975 * 121 976 * @returns VBox status code. … … 123 978 * @param pTransfer Transfer to unregister. 124 979 */ 125 int ShClHttpTransferUnregister (PSHCLHTTPCONTEXT pCtx, PSHCLTRANSFER pTransfer)980 int ShClHttpTransferUnregisterAndMaybeStop(PSHCLHTTPCONTEXT pCtx, PSHCLTRANSFER pTransfer) 126 981 { 127 982 int rc = VINF_SUCCESS; … … 143 998 } 144 999 145 146 /*********************************************************************************************************************************147 * Internal Shared Clipboard HTTP transfer functions *148 *********************************************************************************************************************************/149 150 DECLINLINE(void) shClHttpTransferLock(PSHCLHTTPSERVERTRANSFER pSrvTx)151 {152 int rc2 = RTCritSectEnter(&pSrvTx->CritSect);153 AssertRC(rc2);154 }155 156 DECLINLINE(void) shClHttpTransferUnlock(PSHCLHTTPSERVERTRANSFER pSrvTx)157 {158 int rc2 = RTCritSectEnter(&pSrvTx->CritSect);159 AssertRC(rc2);160 }161 162 /**163 * Return the HTTP server transfer for a specific transfer ID.164 *165 * @returns Pointer to HTTP server transfer if found, NULL if not found.166 * @param pSrv HTTP server instance.167 * @param idTransfer Transfer ID to return HTTP server transfer for.168 */169 static PSHCLHTTPSERVERTRANSFER shClTransferHttpServerGetTransferById(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer)170 {171 PSHCLHTTPSERVERTRANSFER pSrvTx;172 RTListForEach(&pSrv->lstTransfers, pSrvTx, SHCLHTTPSERVERTRANSFER, Node) /** @todo Slow O(n) lookup, but does it for now. */173 {174 if (pSrvTx->pTransfer->State.uID == idTransfer)175 return pSrvTx;176 }177 178 return NULL;179 }180 181 /**182 * Returns a HTTP server transfer from a given URL.183 *184 * @returns Pointer to HTTP server transfer if found, NULL if not found.185 * @param pThis HTTP server instance data.186 * @param pszUrl URL to validate.187 */188 DECLINLINE(PSHCLHTTPSERVERTRANSFER) shClTransferHttpGetTransferFromUrl(PSHCLHTTPSERVER pThis, const char *pszUrl)189 {190 AssertPtrReturn(pszUrl, NULL);191 192 PSHCLHTTPSERVERTRANSFER pSrvTx = NULL;193 194 PSHCLHTTPSERVERTRANSFER pSrvTxCur;195 RTListForEach(&pThis->lstTransfers, pSrvTxCur, SHCLHTTPSERVERTRANSFER, Node)196 {197 AssertPtr(pSrvTxCur->pTransfer);198 199 LogFlowFunc(("pSrvTxCur=%s\n", pSrvTxCur->szPathVirtual));200 201 /* Be picky here, do a case sensitive comparison. */202 if (RTStrStartsWith(pszUrl, pSrvTxCur->szPathVirtual))203 {204 pSrvTx = pSrvTxCur;205 break;206 }207 }208 209 if (!pSrvTx)210 LogRel2(("Shared Clipboard: HTTP URL '%s' not valid\n", pszUrl));211 212 LogFlowFunc(("pszUrl=%s, pSrvTx=%p\n", pszUrl, pSrvTx));213 return pSrvTx;214 }215 216 /**217 * Returns a HTTP server transfer from an internal HTTP handle.218 *219 * @returns Pointer to HTTP server transfer if found, NULL if not found.220 * @param pThis HTTP server instance data.221 * @param pvHandle Handle to return transfer for.222 */223 DECLINLINE(PSHCLHTTPSERVERTRANSFER) shClTransferHttpGetTransferFromHandle(PSHCLHTTPSERVER pThis, void *pvHandle)224 {225 AssertPtrReturn(pvHandle, NULL);226 227 const SHCLTRANSFERID uHandle = *(uint16_t *)pvHandle;228 229 /** @ŧodo Use a handle lookup table (map) later. */230 PSHCLHTTPSERVERTRANSFER pSrvTxCur;231 RTListForEach(&pThis->lstTransfers, pSrvTxCur, SHCLHTTPSERVERTRANSFER, Node)232 {233 AssertPtr(pSrvTxCur->pTransfer);234 235 if (pSrvTxCur->pTransfer->State.uID == uHandle) /** @ŧodo We're using the transfer ID as handle for now. */236 return pSrvTxCur;237 }238 239 return NULL;240 }241 242 static int shClTransferHttpGetTransferRoots(PSHCLHTTPSERVER pThis, PSHCLHTTPSERVERTRANSFER pSrvTx)243 {244 RT_NOREF(pThis);245 246 int rc = VINF_SUCCESS;247 248 if (pSrvTx->pRootList == NULL)249 {250 AssertPtr(pSrvTx->pTransfer);251 rc = ShClTransferRootsGet(pSrvTx->pTransfer, &pSrvTx->pRootList);252 }253 254 return rc;255 }256 257 258 /*********************************************************************************************************************************259 * HTTP server callback implementations *260 *********************************************************************************************************************************/261 262 /** @copydoc RTHTTPSERVERCALLBACKS::pfnOpen */263 static DECLCALLBACK(int) shClTransferHttpOpen(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, void **ppvHandle)264 {265 PSHCLHTTPSERVER pThis = (PSHCLHTTPSERVER)pData->pvUser;266 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER));267 268 int rc;269 270 PSHCLHTTPSERVERTRANSFER pSrvTx = shClTransferHttpGetTransferFromUrl(pThis, pReq->pszUrl);271 if (pSrvTx)272 {273 shClHttpTransferLock(pSrvTx);274 275 AssertPtr(pSrvTx->pTransfer);276 277 SHCLOBJOPENCREATEPARMS openParms;278 rc = ShClTransferObjOpenParmsInit(&openParms);279 if (RT_SUCCESS(rc))280 {281 openParms.fCreate = SHCL_OBJ_CF_ACCESS_READ282 | SHCL_OBJ_CF_ACCESS_DENYWRITE;283 284 rc = RTStrCopy(openParms.pszPath, openParms.cbPath, "foo"); /** @ŧodo BUGBUG !!!! */285 if (RT_SUCCESS(rc))286 {287 rc = ShClTransferObjOpen(pSrvTx->pTransfer, &openParms, &pSrvTx->hObj);288 if (RT_SUCCESS(rc))289 {290 *ppvHandle = &pSrvTx->hObj;291 LogRel2(("Shared Clipboard: HTTP transfer (handle %RU64) started ...\n", pSrvTx->hObj));292 }293 }294 295 ShClTransferObjOpenParmsDestroy(&openParms);296 }297 298 shClHttpTransferUnlock(pSrvTx);299 }300 else301 rc = VERR_NOT_FOUND;302 303 if (RT_FAILURE(rc))304 LogRel(("Shared Clipboard: Error starting HTTP transfer for '%s', rc=%Rrc\n", pReq->pszUrl, rc));305 306 LogFlowFuncLeaveRC(rc);307 return rc;308 }309 310 /** @copydoc RTHTTPSERVERCALLBACKS::pfnRead */311 static DECLCALLBACK(int) shClTransferHttpRead(PRTHTTPCALLBACKDATA pData, void *pvHandle, void *pvBuf, size_t cbBuf, size_t *pcbRead)312 {313 PSHCLHTTPSERVER pThis = (PSHCLHTTPSERVER)pData->pvUser;314 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER));315 316 RT_NOREF(pvBuf, cbBuf, pcbRead);317 318 int rc;319 320 PSHCLHTTPSERVERTRANSFER pSrvTx = shClTransferHttpGetTransferFromHandle(pThis, pvHandle);321 if (pSrvTx)322 {323 Assert(pSrvTx->hObj != SHCLOBJHANDLE_INVALID);324 325 uint32_t cbRead;326 rc = ShClTransferObjRead(pSrvTx->pTransfer, pSrvTx->hObj, pvBuf, cbBuf, 0 /* fFlags */, &cbRead);327 if (RT_SUCCESS(rc))328 {329 *pcbRead = (uint32_t)cbRead;330 }331 332 if (RT_FAILURE(rc))333 LogRel(("Shared Clipboard: Error reading HTTP transfer (handle %RU64), rc=%Rrc\n", pSrvTx->hObj, rc));334 }335 else336 rc = VERR_NOT_FOUND;337 338 LogFlowFuncLeaveRC(rc);339 return rc;340 }341 342 /** @copydoc RTHTTPSERVERCALLBACKS::pfnClose */343 static DECLCALLBACK(int) shClTransferHttpClose(PRTHTTPCALLBACKDATA pData, void *pvHandle)344 {345 PSHCLHTTPSERVER pThis = (PSHCLHTTPSERVER)pData->pvUser;346 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER));347 348 int rc;349 350 PSHCLHTTPSERVERTRANSFER pSrvTx = shClTransferHttpGetTransferFromHandle(pThis, pvHandle);351 if (pSrvTx)352 {353 shClHttpTransferLock(pSrvTx);354 355 Assert(pSrvTx->hObj != SHCLOBJHANDLE_INVALID);356 rc = ShClTransferObjClose(pSrvTx->pTransfer, pSrvTx->hObj);357 if (RT_SUCCESS(rc))358 {359 pSrvTx->hObj = SHCLOBJHANDLE_INVALID;360 LogRel2(("Shared Clipboard: HTTP transfer %RU16 done\n", pSrvTx->pTransfer->State.uID));361 }362 363 if (RT_FAILURE(rc))364 LogRel(("Shared Clipboard: Error closing HTTP transfer (handle %RU64), rc=%Rrc\n", pSrvTx->hObj, rc));365 366 shClHttpTransferUnlock(pSrvTx);367 }368 else369 rc = VERR_NOT_FOUND;370 371 LogFlowFuncLeaveRC(rc);372 return rc;373 }374 375 /** @copydoc RTHTTPSERVERCALLBACKS::pfnQueryInfo */376 static DECLCALLBACK(int) shClTransferHttpQueryInfo(PRTHTTPCALLBACKDATA pData,377 PRTHTTPSERVERREQ pReq, PRTFSOBJINFO pObjInfo, char **ppszMIMEHint)378 {379 PSHCLHTTPSERVER pThis = (PSHCLHTTPSERVER)pData->pvUser;380 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER));381 382 int rc;383 384 PSHCLHTTPSERVERTRANSFER pSrvTx = shClTransferHttpGetTransferFromUrl(pThis, pReq->pszUrl);385 if (pSrvTx)386 {387 shClHttpTransferLock(pSrvTx);388 389 rc = shClTransferHttpGetTransferRoots(pThis, pSrvTx);390 391 shClHttpTransferUnlock(pSrvTx);392 }393 else394 rc = VERR_NOT_FOUND;395 396 RT_NOREF(pObjInfo, ppszMIMEHint);397 398 LogFlowFuncLeaveRC(rc);399 return rc;400 }401 402 /** @copydoc RTHTTPSERVERCALLBACKS::pfnDestroy */403 static DECLCALLBACK(int) shClTransferHttpDestroy(PRTHTTPCALLBACKDATA pData)404 {405 PSHCLHTTPSERVER pThis = (PSHCLHTTPSERVER)pData->pvUser;406 Assert(pData->cbUser == sizeof(SHCLHTTPSERVER));407 408 return shClTransferHttpServerDestroyInternal(pThis);409 }410 411 412 /*********************************************************************************************************************************413 * Internal Shared Clipboard HTTP server functions *414 *********************************************************************************************************************************/415 416 /**417 * Destroys a Shared Clipboard HTTP server instance, internal version.418 *419 * @returns VBox status code.420 * @param pSrv Shared Clipboard HTTP server instance to destroy.421 */422 static int shClTransferHttpServerDestroyInternal(PSHCLHTTPSERVER pSrv)423 {424 PSHCLHTTPSERVERTRANSFER pSrvTx, pSrvTxNext;425 RTListForEachSafe(&pSrv->lstTransfers, pSrvTx, pSrvTxNext, SHCLHTTPSERVERTRANSFER, Node)426 {427 RTListNodeRemove(&pSrvTx->Node);428 429 RTMemFree(pSrvTx);430 pSrvTx = NULL;431 }432 433 RTHttpServerResponseDestroy(&pSrv->Resp);434 435 pSrv->hHTTPServer = NIL_RTHTTPSERVER;436 437 int rc = VINF_SUCCESS;438 439 if (RTCritSectIsInitialized(&pSrv->CritSect))440 rc = RTCritSectDelete(&pSrv->CritSect);441 442 return rc;443 }444 445 /**446 * Locks the critical section of a Shared Clipboard HTTP server instance.447 *448 * @param pSrv Shared Clipboard HTTP server instance to lock.449 */450 DECLINLINE(void) shClTransferHttpServerLock(PSHCLHTTPSERVER pSrv)451 {452 int rc2 = RTCritSectEnter(&pSrv->CritSect);453 AssertRC(rc2);454 }455 456 /**457 * Unlocks the critical section of a Shared Clipboard HTTP server instance.458 *459 * @param pSrv Shared Clipboard HTTP server instance to unlock.460 */461 DECLINLINE(void) shClTransferHttpServerUnlock(PSHCLHTTPSERVER pSrv)462 {463 int rc2 = RTCritSectLeave(&pSrv->CritSect);464 AssertRC(rc2);465 }466 467 /**468 * Initializes a new Shared Clipboard HTTP server instance.469 *470 * @param pSrv HTTP server instance to initialize.471 */472 static void shClTransferHttpServerInitInternal(PSHCLHTTPSERVER pSrv)473 {474 pSrv->hHTTPServer = NIL_RTHTTPSERVER;475 pSrv->uPort = 0;476 RTListInit(&pSrv->lstTransfers);477 pSrv->cTransfers = 0;478 int rc2 = RTHttpServerResponseInit(&pSrv->Resp);479 AssertRC(rc2);480 }481 482 483 /*********************************************************************************************************************************484 * Public Shared Clipboard HTTP server functions *485 *********************************************************************************************************************************/486 487 /**488 * Initializes a new Shared Clipboard HTTP server instance.489 *490 * @param pSrv HTTP server instance to initialize.491 */492 void ShClTransferHttpServerInit(PSHCLHTTPSERVER pSrv)493 {494 AssertPtrReturnVoid(pSrv);495 496 shClTransferHttpServerInitInternal(pSrv);497 }498 499 /**500 * Creates a new Shared Clipboard HTTP server instance, extended version.501 *502 * @returns VBox status code.503 * @param pSrv HTTP server instance to create.504 * @param uPort TCP port number to use.505 */506 int ShClTransferHttpServerCreateEx(PSHCLHTTPSERVER pSrv, uint16_t uPort)507 {508 AssertPtrReturn(pSrv, VERR_INVALID_POINTER);509 510 RTHTTPSERVERCALLBACKS Callbacks;511 RT_ZERO(Callbacks);512 513 Callbacks.pfnOpen = shClTransferHttpOpen;514 Callbacks.pfnRead = shClTransferHttpRead;515 Callbacks.pfnClose = shClTransferHttpClose;516 Callbacks.pfnQueryInfo = shClTransferHttpQueryInfo;517 Callbacks.pfnDestroy = shClTransferHttpDestroy;518 519 /* Note: The server always and *only* runs against the localhost interface. */520 int rc = RTHttpServerCreate(&pSrv->hHTTPServer, "localhost", uPort, &Callbacks,521 pSrv, sizeof(SHCLHTTPSERVER));522 if (RT_SUCCESS(rc))523 {524 rc = RTCritSectInit(&pSrv->CritSect);525 AssertRCReturn(rc, rc);526 527 pSrv->uPort = uPort;528 529 LogRel2(("Shared Clipboard: HTTP server running at port %RU16\n", pSrv->uPort));530 }531 else532 {533 int rc2 = shClTransferHttpServerDestroyInternal(pSrv);534 AssertRC(rc2);535 }536 537 if (RT_FAILURE(rc))538 LogRel(("Shared Clipboard: HTTP server failed to run, rc=%Rrc\n", rc));539 540 return rc;541 }542 543 /**544 * Creates a new Shared Clipboard HTTP server instance.545 *546 * This does automatic probing of TCP ports if one already is being used.547 *548 * @returns VBox status code.549 * @param pSrv HTTP server instance to create.550 * @param puPort Where to return the TCP port number being used on success. Optional.551 */552 int ShClTransferHttpServerCreate(PSHCLHTTPSERVER pSrv, uint16_t *puPort)553 {554 AssertPtrReturn(pSrv, VERR_INVALID_POINTER);555 /* puPort is optional. */556 557 /** @todo Try favorite ports first (e.g. 8080, 8000, ...)? */558 559 RTRAND hRand;560 int rc = RTRandAdvCreateSystemFaster(&hRand); /* Should be good enough for this task. */561 if (RT_SUCCESS(rc))562 {563 uint16_t uPort;564 for (int i = 0; i < 32; i++)565 {566 #ifdef DEBUG_andy567 uPort = 8080; /* Make the port predictable, but only for me, mwahaha! :-). */568 #else569 uPort = RTRandAdvU32Ex(hRand, 1024, UINT16_MAX);570 #endif571 rc = ShClTransferHttpServerCreateEx(pSrv, (uint32_t)uPort);572 if (RT_SUCCESS(rc))573 {574 if (puPort)575 *puPort = uPort;576 break;577 }578 }579 580 RTRandAdvDestroy(hRand);581 }582 583 return rc;584 }585 586 /**587 * Destroys a Shared Clipboard HTTP server instance.588 *589 * @returns VBox status code.590 * @param pSrv HTTP server instance to destroy.591 */592 int ShClTransferHttpServerDestroy(PSHCLHTTPSERVER pSrv)593 {594 AssertPtrReturn(pSrv, VERR_INVALID_POINTER);595 596 if (pSrv->hHTTPServer == NIL_RTHTTPSERVER)597 return VINF_SUCCESS;598 599 Assert(pSrv->cTransfers == 0); /* Sanity. */600 601 int rc = RTHttpServerDestroy(pSrv->hHTTPServer);602 if (RT_SUCCESS(rc))603 rc = shClTransferHttpServerDestroyInternal(pSrv);604 605 if (RT_SUCCESS(rc))606 LogRel2(("Shared Clipboard: HTTP server stopped\n"));607 else608 LogRel(("Shared Clipboard: HTTP server failed to stop, rc=%Rrc\n", rc));609 610 return rc;611 }612 613 /**614 * Registers a Shared Clipboard transfer to a HTTP server instance.615 *616 * @returns VBox status code.617 * @param pSrv HTTP server instance to register transfer for.618 * @param pTransfer Transfer to register.619 */620 int ShClTransferHttpServerRegisterTransfer(PSHCLHTTPSERVER pSrv, PSHCLTRANSFER pTransfer)621 {622 AssertPtrReturn(pSrv, VERR_INVALID_POINTER);623 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);624 625 AssertReturn(pTransfer->State.uID, VERR_INVALID_PARAMETER); /* Paranoia. */626 627 shClTransferHttpServerLock(pSrv);628 629 PSHCLHTTPSERVERTRANSFER pSrvTx = (PSHCLHTTPSERVERTRANSFER)RTMemAllocZ(sizeof(SHCLHTTPSERVERTRANSFER));630 AssertPtrReturn(pSrvTx, VERR_NO_MEMORY);631 632 RTUUID Uuid;633 int rc = RTUuidCreate(&Uuid);634 if (RT_SUCCESS(rc))635 {636 char szUuid[64];637 rc = RTUuidToStr(&Uuid, szUuid, sizeof(szUuid));638 if (RT_SUCCESS(rc))639 {640 rc = RTCritSectInit(&pSrvTx->CritSect);641 AssertRC(rc);642 643 /* Create the virtual HTTP path for the transfer.644 * Every transfer has a dedicated HTTP path. */645 #ifdef DEBUG_andy646 ssize_t cch = RTStrPrintf2(pSrvTx->szPathVirtual, sizeof(pSrvTx->szPathVirtual), "/d1bbda60-80b7-45dc-a41c-ac4686c1d988/10664");647 #else648 ssize_t cch = RTStrPrintf2(pSrvTx->szPathVirtual, sizeof(pSrvTx->szPathVirtual), "%s/%RU16/", szUuid, pTransfer->State.uID);649 #endif650 AssertReturn(cch, VERR_BUFFER_OVERFLOW);651 652 pSrvTx->pTransfer = pTransfer;653 pSrvTx->pRootList = NULL;654 pSrvTx->hObj = SHCLOBJHANDLE_INVALID;655 656 RTListAppend(&pSrv->lstTransfers, &pSrvTx->Node);657 pSrv->cTransfers++;658 659 LogFunc(("pTransfer=%p, idTransfer=%RU16, szPath=%s -> %RU32 transfers\n",660 pSrvTx->pTransfer, pSrvTx->pTransfer->State.uID, pSrvTx->szPathVirtual, pSrv->cTransfers));661 662 LogRel2(("Shared Clipboard: Registered HTTP transfer %RU16, now %RU32 HTTP transfers total\n",663 pTransfer->State.uID, pSrv->cTransfers));664 }665 }666 667 if (RT_FAILURE(rc))668 RTMemFree(pSrvTx);669 670 shClTransferHttpServerUnlock(pSrv);671 672 LogFlowFuncLeaveRC(rc);673 return rc;674 }675 676 /**677 * Unregisters a formerly registered Shared Clipboard transfer.678 *679 * @returns VBox status code.680 * @param pSrv HTTP server instance to unregister transfer from.681 * @param pTransfer Transfer to unregister.682 */683 int ShClTransferHttpServerUnregisterTransfer(PSHCLHTTPSERVER pSrv, PSHCLTRANSFER pTransfer)684 {685 AssertPtrReturn(pSrv, VERR_INVALID_POINTER);686 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);687 688 shClTransferHttpServerLock(pSrv);689 690 AssertReturn(pSrv->cTransfers, VERR_WRONG_ORDER);691 692 int rc = VINF_SUCCESS;693 694 PSHCLHTTPSERVERTRANSFER pSrvTx;695 RTListForEach(&pSrv->lstTransfers, pSrvTx, SHCLHTTPSERVERTRANSFER, Node)696 {697 AssertPtr(pSrvTx->pTransfer);698 if (pSrvTx->pTransfer->State.uID == pTransfer->State.uID)699 {700 RTListNodeRemove(&pSrvTx->Node);701 702 Assert(pSrv->cTransfers);703 pSrv->cTransfers--;704 705 LogFunc(("pTransfer=%p, idTransfer=%RU16, szPath=%s -> %RU32 transfers\n",706 pSrvTx->pTransfer, pSrvTx->pTransfer->State.uID, pSrvTx->szPathVirtual, pSrv->cTransfers));707 708 LogRel2(("Shared Clipboard: Unregistered HTTP transfer %RU16, now %RU32 HTTP transfers total\n",709 pTransfer->State.uID, pSrv->cTransfers));710 711 rc = RTCritSectDelete(&pSrvTx->CritSect);712 AssertRC(rc);713 714 RTMemFree(pSrvTx);715 pSrvTx = NULL;716 717 rc = VINF_SUCCESS;718 break;719 }720 }721 722 shClTransferHttpServerUnlock(pSrv);723 724 LogFlowFuncLeaveRC(rc);725 return rc;726 }727 728 /**729 * Returns whether a specific transfer ID is registered with a HTTP server instance or not.730 *731 * @returns \c true if the transfer ID is registered, \c false if not.732 * @param pSrv HTTP server instance.733 * @param idTransfer Transfer ID to check for.734 */735 bool ShClTransferHttpServerHasTransfer(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer)736 {737 AssertPtrReturn(pSrv, false);738 739 shClTransferHttpServerLock(pSrv);740 741 const bool fRc = shClTransferHttpServerGetTransferById(pSrv, idTransfer) != NULL;742 743 shClTransferHttpServerUnlock(pSrv);744 745 return fRc;746 }747 748 /**749 * Returns the used TCP port number of a HTTP server instance.750 *751 * @returns TCP port number. 0 if not specified yet.752 * @param pSrv HTTP server instance to return port for.753 */754 uint16_t ShClTransferHttpServerGetPort(PSHCLHTTPSERVER pSrv)755 {756 AssertPtrReturn(pSrv, 0);757 758 shClTransferHttpServerLock(pSrv);759 760 const uint16_t uPort = pSrv->uPort;761 762 shClTransferHttpServerUnlock(pSrv);763 764 return uPort;765 }766 767 /**768 * Returns the number of registered HTTP server transfers of a HTTP server instance.769 *770 * @returns Number of registered transfers.771 * @param pSrv HTTP server instance to return registered transfers for.772 */773 uint32_t ShClTransferHttpServerGetTransferCount(PSHCLHTTPSERVER pSrv)774 {775 AssertPtrReturn(pSrv, 0);776 777 shClTransferHttpServerLock(pSrv);778 779 const uint32_t cTransfers = pSrv->cTransfers;780 781 shClTransferHttpServerUnlock(pSrv);782 783 return cTransfers;784 }785 786 /**787 * Returns the host name (scheme) of a HTTP server instance.788 *789 * @param pSrv HTTP server instance to return host name (scheme) for.790 *791 * @returns Host name (scheme).792 */793 static const char *shClTransferHttpServerGetHost(PSHCLHTTPSERVER pSrv)794 {795 RT_NOREF(pSrv);796 return "http://localhost"; /* Hardcoded for now. */797 }798 799 /**800 * Returns an allocated string with a HTTP server instance's address.801 *802 * @returns Allocated string with a HTTP server instance's address, or NULL on OOM.803 * Needs to be free'd by the caller using RTStrFree().804 * @param pSrv HTTP server instance to return address for.805 */806 char *ShClTransferHttpServerGetAddressA(PSHCLHTTPSERVER pSrv)807 {808 AssertPtrReturn(pSrv, NULL);809 810 shClTransferHttpServerLock(pSrv);811 812 char *pszAddress = RTStrAPrintf2("%s:%RU16", shClTransferHttpServerGetHost(pSrv), pSrv->uPort);813 AssertPtr(pszAddress);814 815 shClTransferHttpServerUnlock(pSrv);816 817 return pszAddress;818 }819 820 /**821 * Returns an allocated string with the URL of a given Shared Clipboard transfer ID.822 *823 * @returns Allocated string with the URL of a given Shared Clipboard transfer ID, or NULL if not found.824 * Needs to be free'd by the caller using RTStrFree().825 * @param pSrv HTTP server instance to return URL for.826 */827 char *ShClTransferHttpServerGetUrlA(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer)828 {829 AssertPtrReturn(pSrv, NULL);830 AssertReturn(idTransfer != NIL_SHCLTRANSFERID, NULL);831 832 shClTransferHttpServerLock(pSrv);833 834 PSHCLHTTPSERVERTRANSFER pSrvTx = shClTransferHttpServerGetTransferById(pSrv, idTransfer);835 if (!pSrvTx)836 {837 AssertFailed();838 shClTransferHttpServerUnlock(pSrv);839 return NULL;840 }841 842 AssertReturn(RTStrNLen(pSrvTx->szPathVirtual, RTPATH_MAX), NULL);843 char *pszUrl = RTStrAPrintf2("%s:%RU16/%s", shClTransferHttpServerGetHost(pSrv), pSrv->uPort, pSrvTx->szPathVirtual);844 AssertPtr(pszUrl);845 846 shClTransferHttpServerUnlock(pSrv);847 848 return pszUrl;849 }850 851 /**852 * Returns whether a given HTTP server instance is running or not.853 *854 * @returns \c true if running, or \c false if not.855 * @param pSrv HTTP server instance to check running state for.856 */857 bool ShClTransferHttpServerIsRunning(PSHCLHTTPSERVER pSrv)858 {859 AssertPtrReturn(pSrv, false);860 861 return (pSrv->hHTTPServer != NIL_RTHTTPSERVER); /* Seems enough for now. */862 } -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp
r99405 r99937 49 49 static int shClConvertFileCreateFlags(uint32_t fShClFlags, uint64_t *pfOpen); 50 50 static int shClTransferResolvePathAbs(PSHCLTRANSFER pTransfer, const char *pszPath, uint32_t fFlags, char **ppszResolved); 51 static int shClTransferValidatePath(const char *pcszPath, bool fMustExist); 51 52 52 53 /** @todo Split this file up in different modules. */ … … 76 77 77 78 for (uint32_t i = 0; i < pRootList->Hdr.cRoots; i++) 78 ShClTransferListEntry Init(&pRootList->paEntries[i]);79 ShClTransferListEntryDestroy(&pRootList->paEntries[i]); 79 80 80 81 RTMemFree(pRootList); … … 107 108 return; 108 109 109 pRootLstHdr->fRoots = 0;110 110 pRootLstHdr->cRoots = 0; 111 111 } … … 193 193 AssertPtrReturn(pInfo, VERR_INVALID_POINTER); 194 194 195 pInfo->hList = SHCLLISTHANDLE_INVALID;195 pInfo->hList = NIL_SHCLLISTHANDLE; 196 196 pInfo->enmType = SHCLOBJTYPE_INVALID; 197 197 … … 556 556 557 557 /** 558 * Initializes a clipboard list entry structure. 558 * Returns whether a given list entry name is valid or not. 559 * 560 * @returns \c true if valid, or \c false if not. 561 * @param pszName Name to check. 562 * @param cbName Size (in bytes) of \a pszName to check. 563 * Includes terminator. 564 */ 565 static bool shclTransferListEntryNameIsValid(const char *pszName, size_t cbName) 566 { 567 if (!pszName) 568 return false; 569 570 size_t const cchLen = strlen(pszName); 571 572 if ( !cbName 573 || cchLen == 0 574 || cchLen > cbName /* Includes zero termination */ - 1 575 || cchLen > SHCLLISTENTRY_MAX_NAME /* Ditto */ - 1) 576 { 577 return false; 578 } 579 580 int rc = shClTransferValidatePath(pszName, false /* fMustExist */); 581 if (RT_FAILURE(rc)) 582 return false; 583 584 return true; 585 } 586 587 /** 588 * Initializes a clipboard list entry structure, extended version. 559 589 * 560 590 * @returns VBox status code. 561 591 * @param pListEntry Clipboard list entry structure to initialize. 562 */ 563 int ShClTransferListEntryInit(PSHCLLISTENTRY pListEntry) 592 * @param pszName Name (e.g. filename) to use. Can be NULL if not being used. 593 * Up to SHCLLISTENTRY_MAX_NAME characters. 594 */ 595 int ShClTransferListEntryInitEx(PSHCLLISTENTRY pListEntry, const char *pszName) 564 596 { 565 597 AssertPtrReturn(pListEntry, VERR_INVALID_POINTER); 598 AssertReturn ( pszName == NULL 599 || shclTransferListEntryNameIsValid(pszName, strlen(pszName) + 1), VERR_INVALID_PARAMETER); 566 600 567 601 RT_BZERO(pListEntry, sizeof(SHCLLISTENTRY)); 568 602 569 pListEntry->pszName = RTStrAlloc(SHCLLISTENTRY_MAX_NAME); 570 if (!pListEntry->pszName) 571 return VERR_NO_MEMORY; 572 573 pListEntry->cbName = SHCLLISTENTRY_MAX_NAME; 603 if (pszName) 604 { 605 pListEntry->pszName = RTStrDup(pszName); 606 if (!pListEntry->pszName) 607 return VERR_NO_MEMORY; 608 pListEntry->cbName = strlen(pszName) + 1 /* Include terminator */; 609 } 574 610 575 611 pListEntry->pvInfo = (PSHCLFSOBJINFO)RTMemAlloc(sizeof(SHCLFSOBJINFO)); … … 583 619 584 620 return VERR_NO_MEMORY; 621 } 622 623 /** 624 * Initializes a clipboard list entry structure (as empty / invalid). 625 * 626 * @returns VBox status code. 627 * @param pListEntry Clipboard list entry structure to initialize. 628 */ 629 int ShClTransferListEntryInit(PSHCLLISTENTRY pListEntry) 630 { 631 return ShClTransferListEntryInitEx(pListEntry, NULL); 585 632 } 586 633 … … 621 668 AssertPtrReturn(pListEntry, false); 622 669 623 if ( !pListEntry->pszName 624 || !pListEntry->cbName 625 || strlen(pListEntry->pszName) == 0 626 || strlen(pListEntry->pszName) > pListEntry->cbName /* Includes zero termination */ - 1) 627 { 670 if (!shclTransferListEntryNameIsValid(pListEntry->pszName, pListEntry->cbName)) 628 671 return false; 629 }630 672 631 673 if (pListEntry->cbInfo) /* cbInfo / pvInfo is optional. */ … … 650 692 LogFlowFuncEnter(); 651 693 652 pObjCtx->uHandle = SHCLOBJHANDLE_INVALID;694 pObjCtx->uHandle = NIL_SHCLOBJHANDLE; 653 695 654 696 return VINF_SUCCESS; … … 676 718 { 677 719 return ( pObjCtx 678 && pObjCtx->uHandle != SHCLOBJHANDLE_INVALID);720 && pObjCtx->uHandle != NIL_SHCLOBJHANDLE); 679 721 } 680 722 … … 689 731 AssertPtrReturn(pInfo, VERR_INVALID_POINTER); 690 732 691 pInfo->hObj = SHCLOBJHANDLE_INVALID;733 pInfo->hObj = NIL_SHCLOBJHANDLE; 692 734 pInfo->enmType = SHCLOBJTYPE_INVALID; 693 735 … … 1260 1302 return VINF_SUCCESS; 1261 1303 1304 AssertMsgReturn(pTransfer->cRefs == 0, ("Number of references > 0 (%RU32)\n", pTransfer->cRefs), VERR_WRONG_ORDER); 1305 1262 1306 LogFlowFuncEnter(); 1263 1307 … … 1284 1328 int ShClTransferInit(PSHCLTRANSFER pTransfer, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource) 1285 1329 { 1330 pTransfer->cRefs = 0; 1331 1286 1332 pTransfer->State.enmDir = enmDir; 1287 1333 pTransfer->State.enmSource = enmSource; … … 1305 1351 LogFlowFuncLeaveRC(rc); 1306 1352 return rc; 1353 } 1354 1355 /** 1356 * Acquires a reference to this transfer. 1357 * 1358 * @returns New reference count. 1359 * @param pTransfer Transfer to acquire reference for. 1360 */ 1361 uint32_t ShClTransferAcquire(PSHCLTRANSFER pTransfer) 1362 { 1363 return ASMAtomicIncU32(&pTransfer->cRefs); 1364 } 1365 1366 /** 1367 * Releases a reference to this transfer. 1368 * 1369 * @returns New reference count. 1370 * @param pTransfer Transfer to release reference for. 1371 */ 1372 uint32_t ShClTransferRelease(PSHCLTRANSFER pTransfer) 1373 { 1374 return ASMAtomicDecU32(&pTransfer->cRefs); 1307 1375 } 1308 1376 … … 1592 1660 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 1593 1661 1594 if (hList == SHCLLISTHANDLE_INVALID)1662 if (hList == NIL_SHCLLISTHANDLE) 1595 1663 return VINF_SUCCESS; 1596 1664 … … 2241 2309 AssertPtrReturn(pRoot, VERR_INVALID_PARAMETER); 2242 2310 2311 const char *pcszSrcPathAbs = pRoot->pszPathAbs; 2312 2243 2313 /* Make sure that we only advertise relative source paths, not absolute ones. */ 2244 const char *pcszSrcPath = pRoot->pszPathAbs; 2245 2246 char *pszFileName = RTPathFilename(pcszSrcPath); 2314 char *pszFileName = RTPathFilename(pcszSrcPathAbs); 2247 2315 if (pszFileName) 2248 2316 { 2249 Assert(pszFileName >= pcszSrcPath );2250 size_t cchDstBase = pszFileName - pcszSrcPath ;2251 const char *pszDstPath = &pcszSrcPath [cchDstBase];2252 2253 LogFlowFunc(("pcszSrcPath =%s, pszDstPath=%s\n", pcszSrcPath, pszDstPath));2254 2255 rc = ShClTransferListEntryInit (pEntry);2317 Assert(pszFileName >= pcszSrcPathAbs); 2318 size_t cchDstBase = pszFileName - pcszSrcPathAbs; 2319 const char *pszDstPath = &pcszSrcPathAbs[cchDstBase]; 2320 2321 LogFlowFunc(("pcszSrcPathAbs=%s, pszDstPath=%s\n", pcszSrcPathAbs, pszDstPath)); 2322 2323 rc = ShClTransferListEntryInitEx(pEntry, pszFileName); 2256 2324 if (RT_SUCCESS(rc)) 2257 2325 { … … 2264 2332 { 2265 2333 RTFSOBJINFO fsObjInfo; 2266 rc = RTPathQueryInfo(pcszSrcPath , &fsObjInfo, RTFSOBJATTRADD_NOTHING);2334 rc = RTPathQueryInfo(pcszSrcPathAbs, &fsObjInfo, RTFSOBJATTRADD_NOTHING); 2267 2335 if (RT_SUCCESS(rc)) 2268 2336 { … … 2335 2403 { 2336 2404 pRootList->Hdr.cRoots = cRoots; 2337 pRootList->Hdr.fRoots = 0; /** @todo Implement this. */2338 2405 2339 2406 *ppRootList = pRootList; … … 2470 2537 2471 2538 /** 2539 * Sets a single file as a transfer root. 2540 * 2541 * @returns VBox status code. 2542 * @param pTransfer Transfer to set transfer list entries for. 2543 * @param pszFile File to use as transfer root. 2544 * 2545 * @note Convenience function, uses ShClTransferRootsSet() internally. 2546 */ 2547 int ShClTransferRootsSetAsFile(PSHCLTRANSFER pTransfer, const char *pszFile) 2548 { 2549 char *pszRoots = NULL; 2550 2551 int rc = RTStrAAppend(&pszRoots, pszFile); 2552 AssertRCReturn(rc, rc); 2553 rc = RTStrAAppend(&pszRoots, "\r\n"); 2554 AssertRCReturn(rc, rc); 2555 rc = ShClTransferRootsSet(pTransfer, pszRoots, strlen(pszRoots) + 1); 2556 RTStrFree(pszRoots); 2557 return rc; 2558 } 2559 2560 /** 2472 2561 * Returns the clipboard transfer's ID. 2473 2562 * … … 2494 2583 LogFlowFunc(("[Transfer %RU32] enmDir=%RU32\n", pTransfer->State.uID, pTransfer->State.enmDir)); 2495 2584 return pTransfer->State.enmDir; 2585 } 2586 2587 /** 2588 * Returns the absolute root path of a transfer. 2589 * 2590 * @returns VBox status code. 2591 * @param pTransfer Clipboard transfer to return absolute root path for. 2592 * @param pszPath Where to store the returned path. 2593 * @param cbPath Size (in bytes) of \a pszPath. 2594 */ 2595 int ShClTransferGetRootPathAbs(PSHCLTRANSFER pTransfer, char *pszPath, size_t cbPath) 2596 { 2597 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 2598 2599 return RTStrCopy(pszPath, cbPath, pTransfer->pszPathRootAbs); 2496 2600 } 2497 2601 … … 2674 2778 RT_ZERO(pTransferCtx->bmTransferIds); 2675 2779 2676 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP2677 ShClTransferHttpServerInit(&pTransferCtx->HttpServer);2678 #endif2679 2780 ShClTransferCtxReset(pTransferCtx); 2680 2781 } … … 2829 2930 * is reached. 2830 2931 * @param pTransferCtx Transfer context to register transfer to. 2831 * @param pTransfer Transfer to register. 2932 * @param pTransfer Transfer to register. The context takes ownership of the transfer on success. 2832 2933 * @param pidTransfer Where to return the transfer ID on success. Optional. 2833 2934 */ … … 2939 3040 2940 3041 /** 2941 * Unregisters a transfer from an Transfer context.3042 * Unregisters a transfer from an transfer context. 2942 3043 * 2943 3044 * @retval VINF_SUCCESS on success. -
trunk/src/VBox/GuestHost/SharedClipboard/testcase/Makefile.kmk
r98413 r99937 69 69 endif 70 70 71 endif 71 72 73 ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 74 ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 75 PROGRAMS += tstClipboardHttpServer 76 tstClipboardHttpServer_TEMPLATE = VBoxR3TstExe 77 tstClipboardHttpServer_SOURCES = \ 78 tstClipboardHttpServer.cpp \ 79 ../clipboard-common.cpp \ 80 ../clipboard-transfers.cpp \ 81 ../clipboard-transfers-http.cpp 82 tstClipboardHttpServer_DEFS += VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 83 endif 72 84 endif 85 73 86 endif 74 87 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp
r98103 r99937 1868 1868 RT_ZERO(creationCtx); 1869 1869 1870 if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) 1870 if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) /* Guest -> Host. */ 1871 1871 { 1872 1872 creationCtx.Interface.pfnRootsGet = shClSvcTransferIfaceGetRoots; … … 1881 1881 creationCtx.Interface.pfnObjRead = shClSvcTransferIfaceObjRead; 1882 1882 } 1883 else if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) 1883 else if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) /* Host -> Guest. */ 1884 1884 { 1885 1885 creationCtx.Interface.pfnListHdrWrite = shClSvcTransferIfaceListHdrWrite; -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp
r98103 r99937 505 505 RT_NOREF(pBackend); 506 506 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 507 return ShClHttpTransferRegister (&pClient->State.pCtx->X11.HttpCtx, pTransfer);507 return ShClHttpTransferRegisterAndMaybeStart(&pClient->State.pCtx->X11.HttpCtx, pTransfer); 508 508 #else 509 509 RT_NOREF(pClient, pTransfer); … … 516 516 RT_NOREF(pBackend); 517 517 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 518 return ShClHttpTransferUnregister (&pClient->State.pCtx->X11.HttpCtx, pTransfer);518 return ShClHttpTransferUnregisterAndMaybeStop(&pClient->State.pCtx->X11.HttpCtx, pTransfer); 519 519 #else 520 520 RT_NOREF(pClient, pTransfer); -
trunk/src/VBox/Runtime/r3/http-server.cpp
r98103 r99937 794 794 while (cbToRead) 795 795 { 796 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnRead, p vHandle, pvBuf, RT_MIN(cbBuf, cbToRead), &cbRead);796 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnRead, pReq, pvHandle, pvBuf, RT_MIN(cbBuf, cbToRead), &cbRead); 797 797 if (RT_FAILURE(rc)) 798 798 break; … … 815 815 int rc2 = rc; /* Save rc. */ 816 816 817 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnClose, p vHandle);817 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnClose, pReq, pvHandle); 818 818 819 819 if (RT_FAILURE(rc2)) /* Restore original rc on failure. */ … … 963 963 while (cbToRead) 964 964 { 965 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnRead, p vHandle, pvBuf, RT_MIN(cbBuf, cbToRead), &cbRead);965 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnRead, pReq, pvHandle, pvBuf, RT_MIN(cbBuf, cbToRead), &cbRead); 966 966 if (RT_FAILURE(rc)) 967 967 break; … … 985 985 int rc2 = rc; /* Save rc. */ 986 986 987 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnClose, p vHandle);987 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnClose, pReq, pvHandle); 988 988 989 989 if (RT_FAILURE(rc2)) /* Restore original rc on failure. */ … … 1021 1021 || RTFS_IS_FILE(objInfo.Attr.fMode); 1022 1022 1023 /* No symlinks and other stuff notallowed. */1023 /* No symlinks and other stuff allowed. */ 1024 1024 } 1025 1025 else … … 1142 1142 /* 1143 1143 * Parse HTTP version to use. 1144 * We're picky here e: Only HTTP 1.1 is supported by now.1144 * We're picky here: Only HTTP 1.1 is supported by now. 1145 1145 */ 1146 1146 const char *pszVer = ppapszFirstLine[2]; … … 1209 1209 LogFlowFunc(("Request %s %s\n", RTHttpMethodToStr(pReq->enmMethod), pReq->pszUrl)); 1210 1210 1211 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnRequestBegin, pReq); 1212 1211 1213 unsigned i = 0; 1212 1214 for (; i < RT_ELEMENTS(g_aMethodMap); i++) … … 1225 1227 } 1226 1228 1229 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnRequestEnd, pReq); 1230 1227 1231 if (i == RT_ELEMENTS(g_aMethodMap)) 1228 1232 enmSts = RTHTTPSTATUS_NOTIMPLEMENTED; … … 1233 1237 enmSts = RTHTTPSTATUS_BADREQUEST; 1234 1238 1235 if (enmSts != RTHTTPSTATUS_INTERNAL_NOT_SET) 1236 { 1237 int rc2 = rtHttpServerSendResponseSimple(pClient, enmSts); 1238 if (RT_SUCCESS(rc)) 1239 rc = rc2; 1240 } 1239 /* Make sure to return at least *something* to the client, to prevent hangs. */ 1240 if (enmSts == RTHTTPSTATUS_INTERNAL_NOT_SET) 1241 enmSts = RTHTTPSTATUS_INTERNALSERVERERROR; 1242 1243 int rc2 = rtHttpServerSendResponseSimple(pClient, enmSts); 1244 if (RT_SUCCESS(rc)) 1245 rc = rc2; 1241 1246 1242 1247 LogFlowFuncLeaveRC(rc); … … 1269 1274 if (RT_FAILURE(rc)) 1270 1275 { 1271 Log FlowFunc(("RTTcpSelectOne=%Rrc (cWaitMs=%RU64)\n", rc, cWaitMs));1276 Log2Func(("RTTcpSelectOne=%Rrc (cWaitMs=%RU64)\n", rc, cWaitMs)); 1272 1277 if (rc == VERR_TIMEOUT) 1273 1278 { … … 1277 1282 tsLastReadMs = RTTimeMilliTS(); 1278 1283 const uint64_t tsDeltaMs = pClient->State.msKeepAlive - (RTTimeMilliTS() - tsLastReadMs); 1279 Log FlowFunc(("tsLastReadMs=%RU64, tsDeltaMs=%RU64\n", tsLastReadMs, tsDeltaMs));1280 Log 3Func(("Keep alive active (%RU32ms): %RU64ms remaining\n", pClient->State.msKeepAlive, tsDeltaMs));1284 Log2Func(("tsLastReadMs=%RU64, tsDeltaMs=%RU64\n", tsLastReadMs, tsDeltaMs)); 1285 Log2Func(("Keep alive active (%RU32ms): %RU64ms remaining\n", pClient->State.msKeepAlive, tsDeltaMs)); 1281 1286 if ( tsDeltaMs > cWaitMs 1282 1287 && tsDeltaMs < pClient->State.msKeepAlive) … … 1332 1337 } while (cbToRead); 1333 1338 1339 Log2Func(("Read client request done (%zu bytes) -> rc=%Rrc\n", cbReadTotal, rc)); 1340 1334 1341 if ( RT_SUCCESS(rc) 1335 1342 && cbReadTotal) 1336 1343 { 1337 LogFlowFunc(("Received client request (%zu bytes)\n", cbReadTotal));1338 1339 1344 rtHttpServerLogProto(pClient, false /* fWrite */, szReq); 1340 1345 -
trunk/src/VBox/Runtime/tools/RTHttpServer.cpp
r98103 r99937 521 521 } 522 522 523 static DECLCALLBACK(int) onRead(PRTHTTPCALLBACKDATA pData, void *pvHandle, void *pvBuf, size_t cbBuf, size_t *pcbRead) 524 { 523 static DECLCALLBACK(int) onRead(PRTHTTPCALLBACKDATA pData, 524 PRTHTTPSERVERREQ pReq, void *pvHandle, void *pvBuf, size_t cbBuf, size_t *pcbRead) 525 { 526 RT_NOREF(pReq); 527 525 528 PHTTPSERVERDATA pThis = (PHTTPSERVERDATA)pData->pvUser; 526 529 Assert(pData->cbUser == sizeof(HTTPSERVERDATA)); … … 554 557 } 555 558 556 static DECLCALLBACK(int) onClose(PRTHTTPCALLBACKDATA pData, void *pvHandle) 557 { 559 static DECLCALLBACK(int) onClose(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, void *pvHandle) 560 { 561 RT_NOREF(pReq); 562 558 563 PHTTPSERVERDATA pThis = (PHTTPSERVERDATA)pData->pvUser; 559 564 Assert(pData->cbUser == sizeof(HTTPSERVERDATA));
Note:
See TracChangeset
for help on using the changeset viewer.

