mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-09 02:09:35 +00:00
1
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
//#include "stdafx.h"
|
||||
#ifdef _WIN32
|
||||
#include "winlite.h"
|
||||
#include "winsock.h"
|
||||
#elif POSIX
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#define SOCKET int
|
||||
#define LPSOCKADDR struct sockaddr *
|
||||
#define SOCKADDR_IN struct sockaddr_in
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#define closesocket close
|
||||
#endif
|
||||
#include "tier1/strtools.h"
|
||||
#include "KeyValues.h"
|
||||
#include "utlbuffer.h"
|
||||
#include "tier1/checksum_crc.h"
|
||||
#include "tier1/convar.h"
|
||||
#include "cbase.h"
|
||||
#include "cs_gamestats.h"
|
||||
#include "cs_gamerules.h"
|
||||
#include "cs_urlretrieveprices.h"
|
||||
|
||||
#if _DEBUG
|
||||
#define WEEKLY_PRICE_URL "http://gamestats/weeklyprices.dat"
|
||||
#else
|
||||
#define WEEKLY_PRICE_URL "http://www.steampowered.com/stats/csmarket/weeklyprices.dat"
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: request a URL from connection
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SendHTTPRequest( const char *pchRequestURL, SOCKET socketHTML )
|
||||
{
|
||||
char szHeader[ MED_BUFFER_SIZE ];
|
||||
char szHostName[ SMALL_BUFFER_SIZE ];
|
||||
::gethostname( szHostName, sizeof(szHostName) );
|
||||
|
||||
Q_snprintf( szHeader, sizeof(szHeader), "GET %s HTTP/1.0\r\n" \
|
||||
"Accept: */*\r\n" \
|
||||
"Accept-Language: en-us\r\n" \
|
||||
"User-Agent: Steam/3.0\r\n" \
|
||||
"Host: %s\r\n" \
|
||||
"\r\n",
|
||||
pchRequestURL, szHostName );
|
||||
|
||||
return ::send( socketHTML, szHeader, Q_strlen(szHeader) + 1, 0 ) != SOCKET_ERROR ;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Given a previous HTTP request parse the response into a key values buffer
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ParseHTTPResponse( SOCKET socketHTML, uint32 *unPageHash = NULL )
|
||||
{
|
||||
char szHeaderBuf[ MED_BUFFER_SIZE ];
|
||||
char szBodyBuf[ MED_BUFFER_SIZE ];
|
||||
|
||||
int dwRet = 0;
|
||||
bool bFinishedHeaderRead = false;
|
||||
int iRecvPosition = 0;
|
||||
int cCharsInLine = 0;
|
||||
|
||||
// scan for the end of the header
|
||||
while ( !bFinishedHeaderRead && iRecvPosition < sizeof(szHeaderBuf) )
|
||||
{
|
||||
dwRet = ::recv( socketHTML, &szHeaderBuf[ iRecvPosition ] , 1, 0);
|
||||
if ( dwRet < 0 )
|
||||
{
|
||||
bFinishedHeaderRead = true;
|
||||
}
|
||||
|
||||
switch( szHeaderBuf[ iRecvPosition ] )
|
||||
{
|
||||
case '\r':
|
||||
break;
|
||||
case '\n':
|
||||
if ( cCharsInLine == 0 )
|
||||
bFinishedHeaderRead = true;
|
||||
|
||||
cCharsInLine = 0;
|
||||
break;
|
||||
default:
|
||||
cCharsInLine++;
|
||||
break;
|
||||
}
|
||||
|
||||
iRecvPosition++;
|
||||
}
|
||||
|
||||
CUtlBuffer buf;
|
||||
buf.SetBufferType( false, false );
|
||||
while( 1 )
|
||||
{
|
||||
dwRet = ::recv( socketHTML, szBodyBuf, sizeof(szBodyBuf)-1, 0);
|
||||
if ( dwRet <= 0 )
|
||||
break;
|
||||
|
||||
buf.Put( szBodyBuf, sizeof(szBodyBuf)-1 );
|
||||
}
|
||||
|
||||
weeklyprice_t weeklyprice;
|
||||
Q_memset( &weeklyprice, 0, sizeof( weeklyprice_t) );
|
||||
|
||||
buf.Get( &weeklyprice, sizeof( weeklyprice_t ) );
|
||||
|
||||
if ( weeklyprice.iVersion != PRICE_BLOB_VERSION )
|
||||
{
|
||||
Msg( "Incorrect price blob version! Update your server!\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
CSGameRules()->AddPricesToTable( weeklyprice );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Given http url crack it into an address and the request part
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ProcessURL( const char *pchURL, void *pSockAddrIn, char *pchRequest, int cchRequest )
|
||||
{
|
||||
char rgchHost[ MAX_DNS_NAME ];
|
||||
char rgchRequest[ MED_BUFFER_SIZE ];
|
||||
uint16 iPort;
|
||||
|
||||
if ( Q_strnicmp( pchURL, "http://", 7 ) != 0 )
|
||||
{
|
||||
Assert( !"http protocol only supported" );
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *pchColon = strchr( pchURL + 7, ':' );
|
||||
if ( pchColon )
|
||||
{
|
||||
Q_strncpy( rgchHost, pchURL + 7, pchColon - ( pchURL + 7 ) + 1 );
|
||||
const char *pchForwardSlash = strchr( pchColon + 1, '/' );
|
||||
if ( !pchForwardSlash )
|
||||
return false;
|
||||
Q_strncpy( rgchRequest, pchColon + 1, pchForwardSlash - ( pchColon + 1 ) + 1 );
|
||||
iPort = atoi( rgchRequest );
|
||||
Q_strncpy( rgchRequest, pchForwardSlash, ( pchURL + Q_strlen(pchURL) ) - pchForwardSlash + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *pchForwardSlash = strchr( pchURL + 7, '/' );
|
||||
if ( !pchForwardSlash )
|
||||
return false;
|
||||
|
||||
Q_strncpy( rgchHost, pchURL + 7, pchForwardSlash - ( pchURL + 7 ) + 1 );
|
||||
iPort = 80;
|
||||
Q_strncpy( rgchRequest, pchForwardSlash, ( pchURL + Q_strlen(pchURL) ) - pchForwardSlash + 1 );
|
||||
}
|
||||
|
||||
struct hostent *hp = NULL;
|
||||
if ( inet_addr( rgchHost ) == INADDR_NONE )
|
||||
{
|
||||
hp = gethostbyname( rgchHost );
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 addr = inet_addr( rgchHost );
|
||||
hp = gethostbyaddr( ( char* )&addr, sizeof( addr ), AF_INET );
|
||||
}
|
||||
|
||||
if( hp == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sockaddr_in &sockAddrIn = *((sockaddr_in *)pSockAddrIn);
|
||||
sockAddrIn.sin_addr.s_addr = *( ( unsigned long* )hp->h_addr );
|
||||
sockAddrIn.sin_family = AF_INET;
|
||||
sockAddrIn.sin_port = htons( iPort );
|
||||
|
||||
Q_strncpy( pchRequest, rgchRequest, cchRequest );
|
||||
return true;
|
||||
}
|
||||
|
||||
//networkstringtable
|
||||
|
||||
bool BlackMarket_DownloadPrices( void )
|
||||
{
|
||||
char szRequest[ MED_BUFFER_SIZE ];
|
||||
sockaddr_in server;
|
||||
bool bConnected = false;
|
||||
|
||||
if ( ProcessURL( WEEKLY_PRICE_URL, &server, szRequest, sizeof(szRequest) ) )
|
||||
{
|
||||
SOCKET socketHTML = ::socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
|
||||
if ( socketHTML != INVALID_SOCKET)
|
||||
{
|
||||
int iRet = ::connect( socketHTML, (LPSOCKADDR)&server, sizeof(SOCKADDR_IN) );
|
||||
|
||||
if ( !iRet )
|
||||
{
|
||||
bConnected = true;
|
||||
if ( SendHTTPRequest( szRequest, socketHTML ) )
|
||||
{
|
||||
uint32 unHash = 0;
|
||||
bool bRet = ParseHTTPResponse( socketHTML, &unHash );
|
||||
|
||||
closesocket( socketHTML );
|
||||
|
||||
return bRet;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
closesocket( socketHTML );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user