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

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. //--------------------------------------------------------------------------------------------------------------
  9. // download_internal.h
  10. //
  11. // Header file for optional HTTP asset downloading
  12. // Author: Matthew D. Campbell ([email protected]), 2004
  13. //--------------------------------------------------------------------------------------------------------------
  14. #ifndef DOWNLOAD_INTERNAL_H
  15. #define DOWNLOAD_INTERNAL_H
  16. #include "tier0/platform.h"
  17. //--------------------------------------------------------------------------------------------------------------
  18. /**
  19. * -------------------
  20. * Download overview:
  21. * HTTP downloading is done outside the main thread, to increase responsiveness
  22. * and for code clarity (the download can be a linear sequence of blocking calls).
  23. *
  24. * The process is as follows, from the perspective of the main thread:
  25. * 1. Downloads are queued up when connecting to a server, if the server sends
  26. * a download URL.
  27. * 2. If HTTP downloads are queued up, the client disconnects from the server,
  28. * and puts up a progress bar dialog box for the transfers.
  29. * 3. The CL_HTTPUpdate() function is called every frame, and it does the following:
  30. * a) Starts a download thread if none are active, and at least one is queued up.
  31. * b) Checks on status of the current transfer and updates the progress bar.
  32. * i. If the thread has finished, the file is written out to disk and another
  33. * transfer is started.
  34. * ii. If the thread has aborted/errored out, any partial data is written to
  35. * the cache, the progress bar is removed, and an error message is
  36. * shown, if neccessary.
  37. * c) Checks for old transfers to clean up where the download thread has exited.
  38. * 4. If the user hits Cancel on the progress bar, the current download is told to
  39. * abort, and the progress bar is removed.
  40. *
  41. * The process is as follows, from the perspective of the download thread:
  42. * 1. A complete URL is constructed and verified for correctness.
  43. * 2. The connection is established with the server.
  44. * 3. The file is requested from the server, including the file timestamp and
  45. * byte range for partial transfers (resuming an aborted transfer). A buffer
  46. * for the data is allocated in this thread.
  47. * 4. while the main thread has not requested an abort, read data from the server.
  48. * 5. Upon completion, abort, or an error, the thread does the following:
  49. * a) close any open handles
  50. * b) wait for the main thread to request an exit (so the main thread can read
  51. * any data.)
  52. * c) delete the data buffer (previously allocated in this thread)
  53. * d) sets a flag letting the main thread know this thread is finished.
  54. * e) exit
  55. *
  56. * -------------------
  57. * Thread interaction:
  58. * All thread interaction is handled via a shared RequestContext. Interaction is
  59. * structured so that at all times, only one thread can be writing to any given
  60. * variable.
  61. *
  62. * This is an attempt to enumerate all cases of thread interaction:
  63. * 1. Before download thread creation
  64. * a) main thread allocates the RequestContext, and zeroes it out.
  65. * b) main thread fills in the baseURL and gamePath strings.
  66. * c) main thread sets cachedTimestamp, nBytesCached, and allocates/fills
  67. * cacheData if there is data from a previous aborted download.
  68. * 2. During thread operation:
  69. * a) download thread can do the following:
  70. * i. for HTTP_CONNECTING, download thread can set nBytesTotal,
  71. * nBytesCached, and nBytesCurrent. It can allocate data, and
  72. * set the status to HTTP_FETCH, HTTP_ABORTED, or HTTP_ERROR.
  73. * ii. for HTTP_FETCH, download thread can write to data, set
  74. * nBytesCurrent, and set status to HTTP_DONE, HTTP_ABORTED,
  75. * or HTTP_ERROR.
  76. * iii. for HTTP_DONE, HTTP_ABORTED, and HTTP_ERROR, the download thread
  77. * can only look at shouldStop until it is set by the main thread.
  78. * b) main thread can look at status.
  79. * i. for HTTP_CONNECTING, nothing is read, and only shouldStop can be set.
  80. * ii. for HTTP_FETCH, nBytesTotal and nBytesCurrent are read, and
  81. * shouldStop can be set.
  82. * iii. for HTTP_DONE, nBytesTotal, nBytesCurrent, and data are read. Also,
  83. * shouldStop can be set.
  84. * iv. for HTTP_ABORTED, nothing is read, and only shouldStop can be set.
  85. * v. for HTTP_ERROR, nBytesTotal, nBytesCurrent, and data are read. Also,
  86. * shouldStop can be set.
  87. * 3. After shouldStop is set by main thread:
  88. * a) if the download thread is in status HTTP_FETCH, it will cease operations
  89. * and set status to HTTP_ABORTED.
  90. * b) download thread will delete data, if it exists.
  91. * c) download thread will set threadDone.
  92. * d) after the main thread set shouldStop, it will only look at threadDone.
  93. * 4. After threadDone is set by download thread:
  94. * a) download thread can safely exit, and will not access the RequestContext.
  95. * b) main thread can delete the cacheData, if any exists, and delete the
  96. * RequestContext itself. Thus ends the download.
  97. * 5. SPECIAL CASE: if the user hits Cancel during a download, the main thread will
  98. * look at nBytesTotal and nBytesCurrent to determine if there is any data
  99. * present, and read from data if there is. The download thread will most likely
  100. * be in HTTP_CONNECTING or HTTP_FETCH, but could also be in HTTP_DONE or
  101. * HTTP_ERROR at this time. Regardless, this should be safe because of the
  102. * following reasons:
  103. * a) if nBytesCurrent is non-zero, this means data has been allocated, and
  104. * nBytesTotal has been set and won't change.
  105. * b) nBytesCurrent increases monotonically, so the contents of
  106. * data[0..nBytesCurrent] is complete and unchanging.
  107. *
  108. */
  109. enum { BufferSize = 256 }; ///< BufferSize is used extensively within the download system to size char buffers.
  110. #ifdef POSIX
  111. typedef void *LPVOID;
  112. #endif
  113. #if defined( _X360 ) || defined( POSIX )
  114. typedef LPVOID HINTERNET;
  115. #endif
  116. //--------------------------------------------------------------------------------------------------------------
  117. /**
  118. * Status of the download thread, as set in RequestContext::status.
  119. */
  120. enum HTTPStatus
  121. {
  122. HTTP_CONNECTING = 0,///< This is set in the main thread before the download thread starts.
  123. HTTP_FETCH, ///< The download thread sets this when it starts reading data.
  124. HTTP_DONE, ///< The download thread sets this if it has read all the data successfully.
  125. HTTP_ABORTED, ///< The download thread sets this if it aborts because it's RequestContext::shouldStop has been set.
  126. 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.
  127. };
  128. //--------------------------------------------------------------------------------------------------------------
  129. /**
  130. * Error encountered in the download thread, as set in RequestContext::error.
  131. */
  132. enum HTTPError
  133. {
  134. HTTP_ERROR_NONE = 0,
  135. HTTP_ERROR_ZERO_LENGTH_FILE,
  136. HTTP_ERROR_CONNECTION_CLOSED,
  137. HTTP_ERROR_INVALID_URL, ///< InternetCrackUrl failed
  138. HTTP_ERROR_INVALID_PROTOCOL, ///< URL didn't start with http:// or https://
  139. HTTP_ERROR_CANT_BIND_SOCKET,
  140. HTTP_ERROR_CANT_CONNECT,
  141. HTTP_ERROR_NO_HEADERS, ///< Cannot read HTTP headers
  142. HTTP_ERROR_FILE_NONEXISTENT,
  143. HTTP_ERROR_MAX
  144. };
  145. //--------------------------------------------------------------------------------------------------------------
  146. typedef struct {
  147. /**
  148. * The main thread sets this when it wants to abort the download,
  149. * or it is done reading data from a finished download.
  150. */
  151. bool shouldStop;
  152. /**
  153. * The download thread sets this when it is exiting, so the main thread
  154. * can delete the RequestContext.
  155. */
  156. bool threadDone;
  157. 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.
  158. bool bAsHTTP; ///< true if downloaded via HTTP and not ingame protocol. Set and used by main thread
  159. unsigned int nRequestID; ///< request ID for ingame download
  160. HTTPStatus status; ///< Download thread status
  161. DWORD fetchStatus; ///< Detailed status info for the download
  162. HTTPError error; ///< Detailed error info
  163. char baseURL[BufferSize]; ///< Base URL (including http://). Set by main thread.
  164. char basePath[BufferSize]; ///< Base path for the mod in the filesystem. Set by main thread.
  165. char gamePath[BufferSize]; ///< Game path to be appended to base URL. Set by main thread.
  166. char serverURL[BufferSize]; ///< Server URL (IP:port, loopback, etc). Set by main thread, and used for HTTP Referer header.
  167. /**
  168. * The file's timestamp, as returned in the HTTP Last-Modified header.
  169. * Saved to ensure partial download resumes match the original cached data.
  170. */
  171. char cachedTimestamp[BufferSize];
  172. DWORD nBytesTotal; ///< Total bytes in the file
  173. DWORD nBytesCurrent; ///< Current bytes downloaded
  174. DWORD nBytesCached; ///< Amount of data present in cacheData.
  175. /**
  176. * Buffer for the full file data. Allocated/deleted by the download thread
  177. * (which idles until the data is not needed anymore)
  178. */
  179. unsigned char *data;
  180. /**
  181. * Buffer for partial data from previous failed downloads.
  182. * Allocated/deleted by the main thread (deleted after download thread is done)
  183. */
  184. unsigned char *cacheData;
  185. // Used purely by the download thread - internal data -------------------
  186. HINTERNET hOpenResource; ///< Handle created by InternetOpen
  187. HINTERNET hDataResource; ///< Handle created by InternetOpenUrl
  188. } RequestContext;
  189. //--------------------------------------------------------------------------------------------------------------
  190. uintp DownloadThread( void *voidPtr );
  191. #endif // DOWNLOAD_INTERNAL_H