aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/common/Sockets.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/CascLib/src/common/Sockets.cpp')
-rw-r--r--dep/CascLib/src/common/Sockets.cpp67
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);
}