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.

269 lines
6.4 KiB

  1. //====== Copyright 1996-2004, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. //#include "stdafx.h"
  7. #ifdef _WIN32
  8. #include "winlite.h"
  9. // dgoodenough- skip this on PS3 as well
  10. // PS3_BUILDFIX
  11. #if !defined( _X360 ) && !defined( _PS3 ) //tmauer
  12. #include "winsock.h"
  13. #endif
  14. #elif POSIX
  15. #define INVALID_SOCKET -1
  16. #define SOCKET_ERROR -1
  17. #define SOCKET int
  18. #define LPSOCKADDR struct sockaddr *
  19. #define SOCKADDR_IN struct sockaddr_in
  20. #include <netdb.h>
  21. #include <sys/types.h>
  22. #include <sys/socket.h>
  23. #include <netinet/in.h>
  24. #include <arpa/inet.h>
  25. #define closesocket close
  26. #endif
  27. #include "tier1/strtools.h"
  28. #include "keyvalues.h"
  29. #include "utlbuffer.h"
  30. #include "tier1/checksum_crc.h"
  31. #include "tier1/convar.h"
  32. #include "cbase.h"
  33. #include "cs_gamestats.h"
  34. #include "cs_gamerules.h"
  35. #include "cs_urlretrieveprices.h"
  36. #ifdef BLACKMARKET_PRICING
  37. #if _DEBUG
  38. #define WEEKLY_PRICE_URL "http://gamestats/weeklyprices.dat"
  39. #else
  40. #define WEEKLY_PRICE_URL "http://www.steampowered.com/stats/csmarket/weeklyprices.dat"
  41. #endif
  42. //-----------------------------------------------------------------------------
  43. // Purpose: request a URL from connection
  44. //-----------------------------------------------------------------------------
  45. bool SendHTTPRequest( const char *pchRequestURL, SOCKET socketHTML )
  46. {
  47. // dgoodenough- skip this on PS3 as well
  48. // PS3_BUILDFIX
  49. #if !defined( _X360 ) && !defined( _PS3 ) //tmauer
  50. char szHeader[ MED_BUFFER_SIZE ];
  51. char szHostName[ SMALL_BUFFER_SIZE ];
  52. ::gethostname( szHostName, sizeof(szHostName) );
  53. Q_snprintf( szHeader, sizeof(szHeader), "GET %s HTTP/1.0\r\n" \
  54. "Accept: */*\r\n" \
  55. "Accept-Language: en-us\r\n" \
  56. "User-Agent: Steam/3.0\r\n" \
  57. "Host: %s\r\n" \
  58. "\r\n",
  59. pchRequestURL, szHostName );
  60. return ::send( socketHTML, szHeader, Q_strlen(szHeader) + 1, 0 ) != SOCKET_ERROR ;
  61. #else
  62. return false;
  63. #endif
  64. }
  65. //-----------------------------------------------------------------------------
  66. // Purpose: Given a previous HTTP request parse the response into a key values buffer
  67. //-----------------------------------------------------------------------------
  68. bool ParseHTTPResponse( SOCKET socketHTML, uint32 *unPageHash = NULL )
  69. {
  70. // dgoodenough- skip this on PS3 as well
  71. // PS3_BUILDFIX
  72. #if !defined( _X360 ) && !defined( _PS3 ) //tmauer
  73. char szHeaderBuf[ MED_BUFFER_SIZE ];
  74. char szBodyBuf[ MED_BUFFER_SIZE ];
  75. DWORD dwRet = 0;
  76. bool bFinishedHeaderRead = false;
  77. int iRecvPosition = 0;
  78. int cCharsInLine = 0;
  79. // scan for the end of the header
  80. while ( !bFinishedHeaderRead && iRecvPosition < sizeof(szHeaderBuf) )
  81. {
  82. dwRet = ::recv( socketHTML, &szHeaderBuf[ iRecvPosition ] , 1, 0);
  83. if ( dwRet < 0 )
  84. {
  85. bFinishedHeaderRead = true;
  86. }
  87. switch( szHeaderBuf[ iRecvPosition ] )
  88. {
  89. case '\r':
  90. break;
  91. case '\n':
  92. if ( cCharsInLine == 0 )
  93. bFinishedHeaderRead = true;
  94. cCharsInLine = 0;
  95. break;
  96. default:
  97. cCharsInLine++;
  98. break;
  99. }
  100. iRecvPosition++;
  101. }
  102. CUtlBuffer buf;
  103. buf.SetBufferType( false, false );
  104. while( 1 )
  105. {
  106. dwRet = ::recv( socketHTML, szBodyBuf, sizeof(szBodyBuf)-1, 0);
  107. if ( dwRet <= 0 )
  108. break;
  109. buf.Put( szBodyBuf, sizeof(szBodyBuf)-1 );
  110. }
  111. weeklyprice_t weeklyprice;
  112. Q_memset( &weeklyprice, 0, sizeof( weeklyprice_t) );
  113. buf.Get( &weeklyprice, sizeof( weeklyprice_t ) );
  114. if ( weeklyprice.iVersion != PRICE_BLOB_VERSION )
  115. {
  116. Msg( "Incorrect price blob version! Update your server!\n" );
  117. return false;
  118. }
  119. CSGameRules()->AddPricesToTable( weeklyprice );
  120. return true;
  121. #else
  122. return false;
  123. #endif
  124. }
  125. //-----------------------------------------------------------------------------
  126. // Purpose: Given http url crack it into an address and the request part
  127. //-----------------------------------------------------------------------------
  128. bool ProcessURL( const char *pchURL, void *pSockAddrIn, char *pchRequest, int cchRequest )
  129. {
  130. // dgoodenough- skip this on PS3 as well
  131. // PS3_BUILDFIX
  132. #if !defined( _X360 ) && !defined( _PS3 ) //tmauer
  133. char rgchHost[ MAX_DNS_NAME ];
  134. char rgchRequest[ MED_BUFFER_SIZE ];
  135. uint16 iPort;
  136. if ( Q_strnicmp( pchURL, "http://", 7 ) != 0 )
  137. {
  138. Assert( !"http protocol only supported" );
  139. return false;
  140. }
  141. const char *pchColon = strchr( pchURL + 7, ':' );
  142. if ( pchColon )
  143. {
  144. Q_strncpy( rgchHost, pchURL + 7, pchColon - ( pchURL + 7 ) + 1 );
  145. const char *pchForwardSlash = strchr( pchColon + 1, '/' );
  146. if ( !pchForwardSlash )
  147. return false;
  148. Q_strncpy( rgchRequest, pchColon + 1, pchForwardSlash - ( pchColon + 1 ) + 1 );
  149. iPort = atoi( rgchRequest );
  150. Q_strncpy( rgchRequest, pchForwardSlash, ( pchURL + Q_strlen(pchURL) ) - pchForwardSlash + 1 );
  151. }
  152. else
  153. {
  154. const char *pchForwardSlash = strchr( pchURL + 7, '/' );
  155. if ( !pchForwardSlash )
  156. return false;
  157. Q_strncpy( rgchHost, pchURL + 7, pchForwardSlash - ( pchURL + 7 ) + 1 );
  158. iPort = 80;
  159. Q_strncpy( rgchRequest, pchForwardSlash, ( pchURL + Q_strlen(pchURL) ) - pchForwardSlash + 1 );
  160. }
  161. struct hostent *hp = NULL;
  162. if ( inet_addr( rgchHost ) == INADDR_NONE )
  163. {
  164. hp = gethostbyname( rgchHost );
  165. }
  166. else
  167. {
  168. uint32 addr = inet_addr( rgchHost );
  169. hp = gethostbyaddr( ( char* )&addr, sizeof( addr ), AF_INET );
  170. }
  171. if( hp == NULL )
  172. {
  173. return false;
  174. }
  175. sockaddr_in &sockAddrIn = *((sockaddr_in *)pSockAddrIn);
  176. sockAddrIn.sin_addr.s_addr = *( ( unsigned long* )hp->h_addr );
  177. sockAddrIn.sin_family = AF_INET;
  178. sockAddrIn.sin_port = htons( iPort );
  179. Q_strncpy( pchRequest, rgchRequest, cchRequest );
  180. return true;
  181. #else
  182. return false;
  183. #endif
  184. }
  185. //networkstringtable
  186. bool BlackMarket_DownloadPrices( void )
  187. {
  188. // dgoodenough- skip this on PS3 as well
  189. // PS3_BUILDFIX
  190. #if !defined( _X360 ) && !defined( _PS3 ) //tmauer
  191. char szRequest[ MED_BUFFER_SIZE ];
  192. sockaddr_in server;
  193. bool bConnected = false;
  194. if ( ProcessURL( WEEKLY_PRICE_URL, &server, szRequest, sizeof(szRequest) ) )
  195. {
  196. SOCKET socketHTML = ::socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
  197. if ( socketHTML != INVALID_SOCKET)
  198. {
  199. int iRet = ::connect( socketHTML, (LPSOCKADDR)&server, sizeof(SOCKADDR_IN) );
  200. if ( !iRet )
  201. {
  202. bConnected = true;
  203. if ( SendHTTPRequest( szRequest, socketHTML ) )
  204. {
  205. uint32 unHash = 0;
  206. bool bRet = ParseHTTPResponse( socketHTML, &unHash );
  207. closesocket( socketHTML );
  208. return bRet;
  209. }
  210. else
  211. {
  212. return false;
  213. }
  214. }
  215. else
  216. {
  217. closesocket( socketHTML );
  218. return false;
  219. }
  220. }
  221. }
  222. else
  223. {
  224. return false;
  225. }
  226. return true;
  227. #else
  228. return false;
  229. #endif
  230. }
  231. #endif // BLACKMARKET_PRICING