diff options
author | Shauren <shauren.trinity@gmail.com> | 2022-11-03 01:15:30 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-11-03 01:15:30 +0100 |
commit | c4564566b0b308f88f3664ec124a8557bdc278f0 (patch) | |
tree | f09d604f961e5d605556bc652aea5ec5d505d025 /dep/CascLib/src/common/Sockets.cpp | |
parent | 722201e01c7809f1e85eb480499630a7d7d748b5 (diff) |
Dep/CascLib: Update to ladislav-zezula/CascLib@136c6e05537bd7123620ddb28671d1f2cf060e0b
Diffstat (limited to 'dep/CascLib/src/common/Sockets.cpp')
-rw-r--r-- | dep/CascLib/src/common/Sockets.cpp | 67 |
1 files changed, 52 insertions, 15 deletions
diff --git a/dep/CascLib/src/common/Sockets.cpp b/dep/CascLib/src/common/Sockets.cpp index dee5643d42e..cf3ffe9d0b1 100644 --- a/dep/CascLib/src/common/Sockets.cpp +++ b/dep/CascLib/src/common/Sockets.cpp @@ -16,6 +16,8 @@ //----------------------------------------------------------------------------- // Local variables +#define BUFFER_INITIAL_SIZE 0x8000 + CASC_SOCKET_CACHE SocketCache; //----------------------------------------------------------------------------- @@ -26,9 +28,12 @@ char * CASC_SOCKET::ReadResponse(const char * request, size_t request_length, si { CASC_MIME_HTTP HttpInfo; char * server_response = NULL; + size_t content_length = 0; size_t total_received = 0; - size_t block_increment = 0x8000; - size_t buffer_size = block_increment; + size_t buffer_length = BUFFER_INITIAL_SIZE; + size_t buffer_delta = BUFFER_INITIAL_SIZE; + size_t http_flags = 0; + DWORD dwErrCode = ERROR_SUCCESS; int bytes_received = 0; // Pre-set the result length @@ -54,41 +59,73 @@ char * CASC_SOCKET::ReadResponse(const char * request, size_t request_length, si } // Allocate buffer for server response. Allocate one extra byte for zero terminator - if((server_response = CASC_ALLOC<char>(buffer_size + 1)) != NULL) + if((server_response = CASC_ALLOC<char>(buffer_length + 1)) != NULL) { - for(;;) + while((http_flags & HTTP_DATA_COMPLETE) == 0) { // Reallocate the buffer size, if needed - if(total_received == buffer_size) + if(total_received == buffer_length) { - if((server_response = CASC_REALLOC(char, server_response, buffer_size + block_increment + 1)) == NULL) + // Reallocate the buffer + if((server_response = CASC_REALLOC(server_response, buffer_length + buffer_delta + 1)) == NULL) { - SetCascError(ERROR_NOT_ENOUGH_MEMORY); - CascUnlock(Lock); - return NULL; + dwErrCode = ERROR_NOT_ENOUGH_MEMORY; + break; } - buffer_size += block_increment; + buffer_length += buffer_delta; + buffer_delta = BUFFER_INITIAL_SIZE; } // Receive the next part of the response, up to buffer size // Return value 0 means "connection closed", -1 means an error - bytes_received = recv(sock, server_response + total_received, (int)(buffer_size - total_received), 0); + bytes_received = recv(sock, server_response + total_received, (int)(buffer_length - total_received), 0); if(bytes_received <= 0) break; + // Verify buffer overflow + if((total_received + bytes_received) < total_received) + { + dwErrCode = ERROR_NOT_ENOUGH_MEMORY; + break; + } + // Append the number of bytes received. Also terminate response with zero total_received += bytes_received; server_response[total_received] = 0; // On a HTTP protocol, we need to check whether we received all data - if(HttpInfo.IsDataComplete(server_response, total_received)) - break; + http_flags = HttpInfo.IsDataComplete(server_response, total_received, &content_length); + if(http_flags & HTTP_HEADER_COMPLETE) + { + // Check for maximum file size + if(content_length > CASC_MAX_ONLINE_FILE_SIZE) + { + dwErrCode = ERROR_NOT_ENOUGH_MEMORY; + break; + } + + // If we just retrieved the content length, we temporarily increment + // the buffer delta. This will make next reallocation to make buffer + // large enough to prevent abundant reallocations and memory memcpy's + if(content_length > buffer_length) + { + buffer_delta = (HttpInfo.content_offset + content_length) - buffer_length; + } + } } } // Unlock the socket CascUnlock(Lock); + // Low memory condition: Delete the server response + if(dwErrCode != ERROR_SUCCESS) + { + CASC_FREE(server_response); + SetCascError(dwErrCode); + total_received = 0; + } + // Give the result to the caller if(PtrLength != NULL) PtrLength[0] = total_received; @@ -143,7 +180,7 @@ DWORD CASC_SOCKET::GetAddrInfoWrapper(const char * hostName, unsigned portNum, P continue; } #endif - case EAI_AGAIN: // Temporary error, try again + case (DWORD)EAI_AGAIN: // Temporary error, try again continue; default: // Any other result, incl. ERROR_SUCCESS @@ -428,7 +465,7 @@ PCASC_SOCKET sockets_connect(const char * hostName, unsigned portNum) pSocket = CASC_SOCKET::Connect(hostName, portNum); // Insert it to the cache, if it's a HTTP connection - if(pSocket->portNum == CASC_PORT_HTTP) + if(pSocket != NULL && pSocket->portNum == CASC_PORT_HTTP) pSocket = SocketCache.InsertSocket(pSocket); } |