Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

211 lines
10 KiB

//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
//--------------------------------------------------------------------------------------------------------------
// download_internal.h
//
// Header file for optional HTTP asset downloading
// Author: Matthew D. Campbell ([email protected]), 2004
//--------------------------------------------------------------------------------------------------------------
#ifndef DOWNLOAD_INTERNAL_H
#define DOWNLOAD_INTERNAL_H
#include "tier0/platform.h"
//--------------------------------------------------------------------------------------------------------------
/**
* -------------------
* Download overview:
* HTTP downloading is done outside the main thread, to increase responsiveness
* and for code clarity (the download can be a linear sequence of blocking calls).
*
* The process is as follows, from the perspective of the main thread:
* 1. Downloads are queued up when connecting to a server, if the server sends
* a download URL.
* 2. If HTTP downloads are queued up, the client disconnects from the server,
* and puts up a progress bar dialog box for the transfers.
* 3. The CL_HTTPUpdate() function is called every frame, and it does the following:
* a) Starts a download thread if none are active, and at least one is queued up.
* b) Checks on status of the current transfer and updates the progress bar.
* i. If the thread has finished, the file is written out to disk and another
* transfer is started.
* ii. If the thread has aborted/errored out, any partial data is written to
* the cache, the progress bar is removed, and an error message is
* shown, if neccessary.
* c) Checks for old transfers to clean up where the download thread has exited.
* 4. If the user hits Cancel on the progress bar, the current download is told to
* abort, and the progress bar is removed.
*
* The process is as follows, from the perspective of the download thread:
* 1. A complete URL is constructed and verified for correctness.
* 2. The connection is established with the server.
* 3. The file is requested from the server, including the file timestamp and
* byte range for partial transfers (resuming an aborted transfer). A buffer
* for the data is allocated in this thread.
* 4. while the main thread has not requested an abort, read data from the server.
* 5. Upon completion, abort, or an error, the thread does the following:
* a) close any open handles
* b) wait for the main thread to request an exit (so the main thread can read
* any data.)
* c) delete the data buffer (previously allocated in this thread)
* d) sets a flag letting the main thread know this thread is finished.
* e) exit
*
* -------------------
* Thread interaction:
* All thread interaction is handled via a shared RequestContext. Interaction is
* structured so that at all times, only one thread can be writing to any given
* variable.
*
* This is an attempt to enumerate all cases of thread interaction:
* 1. Before download thread creation
* a) main thread allocates the RequestContext, and zeroes it out.
* b) main thread fills in the baseURL and gamePath strings.
* c) main thread sets cachedTimestamp, nBytesCached, and allocates/fills
* cacheData if there is data from a previous aborted download.
* 2. During thread operation:
* a) download thread can do the following:
* i. for HTTP_CONNECTING, download thread can set nBytesTotal,
* nBytesCached, and nBytesCurrent. It can allocate data, and
* set the status to HTTP_FETCH, HTTP_ABORTED, or HTTP_ERROR.
* ii. for HTTP_FETCH, download thread can write to data, set
* nBytesCurrent, and set status to HTTP_DONE, HTTP_ABORTED,
* or HTTP_ERROR.
* iii. for HTTP_DONE, HTTP_ABORTED, and HTTP_ERROR, the download thread
* can only look at shouldStop until it is set by the main thread.
* b) main thread can look at status.
* i. for HTTP_CONNECTING, nothing is read, and only shouldStop can be set.
* ii. for HTTP_FETCH, nBytesTotal and nBytesCurrent are read, and
* shouldStop can be set.
* iii. for HTTP_DONE, nBytesTotal, nBytesCurrent, and data are read. Also,
* shouldStop can be set.
* iv. for HTTP_ABORTED, nothing is read, and only shouldStop can be set.
* v. for HTTP_ERROR, nBytesTotal, nBytesCurrent, and data are read. Also,
* shouldStop can be set.
* 3. After shouldStop is set by main thread:
* a) if the download thread is in status HTTP_FETCH, it will cease operations
* and set status to HTTP_ABORTED.
* b) download thread will delete data, if it exists.
* c) download thread will set threadDone.
* d) after the main thread set shouldStop, it will only look at threadDone.
* 4. After threadDone is set by download thread:
* a) download thread can safely exit, and will not access the RequestContext.
* b) main thread can delete the cacheData, if any exists, and delete the
* RequestContext itself. Thus ends the download.
* 5. SPECIAL CASE: if the user hits Cancel during a download, the main thread will
* look at nBytesTotal and nBytesCurrent to determine if there is any data
* present, and read from data if there is. The download thread will most likely
* be in HTTP_CONNECTING or HTTP_FETCH, but could also be in HTTP_DONE or
* HTTP_ERROR at this time. Regardless, this should be safe because of the
* following reasons:
* a) if nBytesCurrent is non-zero, this means data has been allocated, and
* nBytesTotal has been set and won't change.
* b) nBytesCurrent increases monotonically, so the contents of
* data[0..nBytesCurrent] is complete and unchanging.
*
*/
enum { BufferSize = 256 }; ///< BufferSize is used extensively within the download system to size char buffers.
#ifdef POSIX
typedef void *LPVOID;
#endif
#if defined( _X360 ) || defined( POSIX )
typedef LPVOID HINTERNET;
#endif
//--------------------------------------------------------------------------------------------------------------
/**
* Status of the download thread, as set in RequestContext::status.
*/
enum HTTPStatus
{
HTTP_CONNECTING = 0,///< This is set in the main thread before the download thread starts.
HTTP_FETCH, ///< The download thread sets this when it starts reading data.
HTTP_DONE, ///< The download thread sets this if it has read all the data successfully.
HTTP_ABORTED, ///< The download thread sets this if it aborts because it's RequestContext::shouldStop has been set.
HTTP_ERROR ///< The download thread sets this if there is an error connecting or downloading. Partial data may be present, so the main thread can check.
};
//--------------------------------------------------------------------------------------------------------------
/**
* Error encountered in the download thread, as set in RequestContext::error.
*/
enum HTTPError
{
HTTP_ERROR_NONE = 0,
HTTP_ERROR_ZERO_LENGTH_FILE,
HTTP_ERROR_CONNECTION_CLOSED,
HTTP_ERROR_INVALID_URL, ///< InternetCrackUrl failed
HTTP_ERROR_INVALID_PROTOCOL, ///< URL didn't start with http:// or https://
HTTP_ERROR_CANT_BIND_SOCKET,
HTTP_ERROR_CANT_CONNECT,
HTTP_ERROR_NO_HEADERS, ///< Cannot read HTTP headers
HTTP_ERROR_FILE_NONEXISTENT,
HTTP_ERROR_MAX
};
//--------------------------------------------------------------------------------------------------------------
typedef struct {
/**
* The main thread sets this when it wants to abort the download,
* or it is done reading data from a finished download.
*/
bool shouldStop;
/**
* The download thread sets this when it is exiting, so the main thread
* can delete the RequestContext.
*/
bool threadDone;
bool bIsBZ2; ///< true if the file is a .bz2 file that should be uncompressed at the end of the download. Set and used by main thread.
bool bAsHTTP; ///< true if downloaded via HTTP and not ingame protocol. Set and used by main thread
unsigned int nRequestID; ///< request ID for ingame download
HTTPStatus status; ///< Download thread status
DWORD fetchStatus; ///< Detailed status info for the download
HTTPError error; ///< Detailed error info
char baseURL[BufferSize]; ///< Base URL (including http://). Set by main thread.
char basePath[BufferSize]; ///< Base path for the mod in the filesystem. Set by main thread.
char gamePath[BufferSize]; ///< Game path to be appended to base URL. Set by main thread.
char serverURL[BufferSize]; ///< Server URL (IP:port, loopback, etc). Set by main thread, and used for HTTP Referer header.
/**
* The file's timestamp, as returned in the HTTP Last-Modified header.
* Saved to ensure partial download resumes match the original cached data.
*/
char cachedTimestamp[BufferSize];
DWORD nBytesTotal; ///< Total bytes in the file
DWORD nBytesCurrent; ///< Current bytes downloaded
DWORD nBytesCached; ///< Amount of data present in cacheData.
/**
* Buffer for the full file data. Allocated/deleted by the download thread
* (which idles until the data is not needed anymore)
*/
unsigned char *data;
/**
* Buffer for partial data from previous failed downloads.
* Allocated/deleted by the main thread (deleted after download thread is done)
*/
unsigned char *cacheData;
// Used purely by the download thread - internal data -------------------
HINTERNET hOpenResource; ///< Handle created by InternetOpen
HINTERNET hDataResource; ///< Handle created by InternetOpenUrl
} RequestContext;
//--------------------------------------------------------------------------------------------------------------
uintp DownloadThread( void *voidPtr );
#endif // DOWNLOAD_INTERNAL_H