diff options
Diffstat (limited to 'public/gcsdk/gcjob.h')
| -rw-r--r-- | public/gcsdk/gcjob.h | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/public/gcsdk/gcjob.h b/public/gcsdk/gcjob.h new file mode 100644 index 0000000..b404531 --- /dev/null +++ b/public/gcsdk/gcjob.h @@ -0,0 +1,241 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef GCJOB_H +#define GCJOB_H +#ifdef _WIN32 +#pragma once +#endif + +#include "gcwebapikey.h" + +namespace GCSDK +{ + +//a free standing utility function that takes in a newly allocated job, and tells the job to start executing. An example of this would be pStore = StartNewJobDelayed( new CFooJob( Params ) ); +template < typename T > +inline typename T* StartNewJobDelayed( T* pNewJob ) +{ + if ( pNewJob ) + pNewJob->StartJobDelayed( NULL ); + return pNewJob; +} + +//----------------------------------------------------------------------------- +// Purpose: Control access to web api accounts so that they can be rate limited/blocked/exempt, etc +//----------------------------------------------------------------------------- + +enum EWebAPIAccountLevel +{ + eWebAPIAccountLevel_RateLimited = 0, //default, rate limit + eWebAPIAccountLevel_Blocked = 1, //block all requests + eWebAPIAccountLevel_Unlimited = 2, //do not rate limit + eWebAPIAccountLevel_Elevated = 3, //like rate limiting, but at a higher threshold +}; + +//resets all accounts to the default permission +void WebAPIAccount_ResetAllPermissions(); +//called to associate a permission level with an account +void WebAPIAccount_SetPermission( AccountID_t nID, EWebAPIAccountLevel eLevel ); +//external calling interface in case we want to use this from a non-WebAPI job +bool WebAPIAccount_BTrackUserAndValidate( AccountID_t nID, uint32 unIP ); + +//----------------------------------------------------------------------------- +// Purpose: handles a network message job from the client +//----------------------------------------------------------------------------- +class CGCJob : public CJob +{ +public: + // Constructor: when overriding job name a static string pointer must be used + CGCJob( CGCBase *pGC, const char *pchJobName = NULL ) : CJob( pGC->GetJobMgr(), pchJobName ), m_pGC( pGC ), m_cHeartbeatsBeforeTimeout( k_cJobHeartbeatsBeforeTimeoutDefault ) {} + + // all GC jobs must implement one of these + virtual bool BYieldingRunGCJob( IMsgNetPacket *pNetPacket ) { return false; } + virtual bool BYieldingRunGCJob() { return false; } + + virtual EServerType GetServerType() { return k_EServerTypeGC; } + + bool BYldSendMessageAndGetReply( CSteamID &steamIDTarget, CGCMsgBase &msgOut, uint nTimeoutSec, CGCMsgBase *pMsgIn, MsgType_t eMsg ); + bool BYldSendMessageAndGetReply( CSteamID &steamIDTarget, CGCMsgBase &msgOut, uint nTimeoutSec, IMsgNetPacket **ppNetPacket ); + bool BYldSendMessageAndGetReply( CSteamID &steamIDTarget, CProtoBufMsgBase &msgOut, uint nTimeoutSec, CProtoBufMsgBase *pMsgIn, MsgType_t eMsg ); + bool BYldSendMessageAndGetReply( CSteamID &steamIDTarget, CProtoBufMsgBase &msgOut, uint nTimeoutSec, IMsgNetPacket **ppNetPacket ); + + virtual uint32 CHeartbeatsBeforeTimeout() { return m_cHeartbeatsBeforeTimeout; } + void SetJobTimeout( uint nTimeoutSec ) { m_cHeartbeatsBeforeTimeout = 1 + ( ( nTimeoutSec * k_nMillion - 1 ) / k_cMicroSecJobHeartbeat ); } + +protected: + CGCBase *m_pGC; + +private: + virtual bool BYieldingRunJobFromMsg( IMsgNetPacket *pNetPacket ) + { + return BYieldingRunGCJob( pNetPacket ); + } + + virtual bool BYieldingRunJob( void *pvStartParam ) + { + return BYieldingRunGCJob(); + } + + uint32 m_cHeartbeatsBeforeTimeout; +}; + + +//This template class is designed to be derived from various job types and provides an adapter for the run from message hook, and handles +//converting it over to an appropriate protobuf message for the caller as well as validating that it parsed properly. It will bail on processing +//the message if the protobuf does not parse. +template < typename TGCJobClass, typename TGCType, typename TProtoMsgClass > +class TProtoMsgJob : + public TGCJobClass +{ +public: + typedef CProtoBufMsg< TProtoMsgClass > TProtoMsg; + + TProtoMsgJob( TGCType* pGC ) : TGCJobClass( pGC ) {} + + virtual bool BYieldingRunJobFromMsg( IMsgNetPacket *pNetPacket ) OVERRIDE + { + TProtoMsg msg( pNetPacket ); + if ( !msg.Body().IsInitialized() ) + return false; + + return BYieldingRunJobFromProtoMsg( msg ); + } + + virtual bool BYieldingRunJobFromProtoMsg( const TProtoMsg& ProtoMsg ) = 0; +}; + +//a partial specialization of the proto message job to make it easier to use with GCJob +template < typename TProtoMsgClass > +class CGCProtoJob : public TProtoMsgJob < CGCJob, CGCBase, TProtoMsgClass > +{ +public: + CGCProtoJob( CGCBase* pGC ) : TProtoMsgJob( pGC ) {} + //clients need to implement BYieldingRunJobFromProtoMsg +}; + +//----------------------------------------------------------------------------- +// CGCWGJob - A job invoked from forwarded WG messages +//----------------------------------------------------------------------------- +class CGCWGJob : public CGCJob +{ +public: + CGCWGJob( CGCBase *pGCBase ); + ~CGCWGJob(); + bool BYieldingRunGCJob( IMsgNetPacket * pNetPacket ); // invokes BYieldingRunJobFromRequest + virtual bool BYieldingRunJobFromRequest( KeyValues *pkvRequest, KeyValues *pkvResponse ) = 0; + virtual bool BVerifyParams( const CGCMsg<MsgGCWGRequest_t> & msg, KeyValues *pkvRequest, const WebApiFunc_t * pWebApiFunc ); + void SetWebApiFunc( const WebApiFunc_t * pWebApiFunc ) { m_pWebApiFunc = pWebApiFunc; } + + void SetErrorMessage( KeyValues *pkvErr, const char *pchErrorMsg, int32 nResult ); + +protected: + KeyValues *m_pkvResponse; + CUtlBuffer m_bufRequest; // packed binary form of the request + const WebApiFunc_t * m_pWebApiFunc; + + // requester auth info, like WGRequestContext + CSteamID m_steamID; +}; + + +//----------------------------------------------------------------------------- +// CGCJobVerifySession - A job that asks steam if a given user is still connected +// and cleans up the session if the user is gone +//----------------------------------------------------------------------------- +class CGCJobVerifySession : public CGCJob +{ +public: + CGCJobVerifySession( CGCBase *pGC, const CSteamID &steamID ) : CGCJob( pGC ), m_steamID( steamID ) { } + virtual bool BYieldingRunGCJob(); + +private: + CSteamID m_steamID; +}; + + + +//----------------------------------------------------------------------------- +// CWebAPIJob - A job invoked from a forwarded WebAPI request +//----------------------------------------------------------------------------- +class CWebAPIJob : public CGCJob +{ +public: + CWebAPIJob( CGCBase *pGC, EWebAPIOutputFormat eDefaultOutputFormat = k_EWebAPIOutputFormat_JSON ); + ~CWebAPIJob(); + + // Called by jobmgr, and then invokes appropriate run function for specific API version requested + bool BYieldingRunJobFromMsg( IMsgNetPacket * pNetPacket ); + + // Implemented by each individual WebAPI job, should be declared using BEGIN_WEBAPI_JOB_VERSION_ADAPTERS and related macros. + virtual bool BYieldingRunJobFromAPIRequest( const char *pchInterface, const char *pchMethod, uint32 unVersion, CHTTPRequest *pRequest, CHTTPResponse *pResponse, CWebAPIResponse *pWebAPIResponse ) = 0; + +protected: + static void AddLocalizedString( CWebAPIValues *pOutDefn, const char *pchFieldName, const char *pchKeyName, ELanguage eLang, bool bReturnTokenIfNotFound = true ); + static void ThreadedEmitFormattedOutputWrapper( CWebAPIResponse *pResponse, EWebAPIOutputFormat eFormat, CUtlBuffer *poutputBuffer, size_t unMaxResultSize, bool *pbResult ); + + CWebAPIKey m_webAPIKey; + EWebAPIOutputFormat m_eDefaultOutputFormat; +}; + + +#define BEGIN_WEBAPI_JOB_VERSION_ADAPTERS( interface, method ) \ + bool BYieldingRunJobFromAPIRequest( const char *pchInterface, const char *pchMethod, uint32 unVersion, CHTTPRequest *pRequest, CHTTPResponse *pResponse, CWebAPIResponse *pWebAPIResponse ) \ +{ \ + if ( Q_strnicmp( pchInterface, interface, Q_strlen( interface ) ) != 0 ) \ +{ \ + AssertMsg2( false, "WebAPIJob recieved request for unexpected interface (got %s, expected %s)!", pchInterface, interface ); \ + pResponse->SetStatusCode( k_EHTTPStatusCode500InternalServerError ); \ + return false; \ +} \ + \ + if ( Q_stricmp( pchMethod, method ) != 0 ) \ +{ \ + AssertMsg2( false, "WebAPIJob received request fo unexpected method (got %s, expected %s)!", pchMethod, method ); \ + pResponse->SetStatusCode( k_EHTTPStatusCode500InternalServerError ); \ + return false; \ +} \ + \ + \ + bool bFoundVersion = false; \ + bool bResult = false; \ + switch( unVersion ) \ +{ + +#define WEBAPI_JOB_VERSION_ADAPTER( version, funcname ) \ + case version: \ + bFoundVersion = true; \ + { \ + VPROF_BUDGET( #funcname, VPROF_BUDGETGROUP_JOBS_COROUTINES ); \ + bResult = this->##funcname( pRequest, pWebAPIResponse ); \ + } \ + break; + +#define WEBAPI_JOB_VERSION_ADAPTER_EXTENDED_ARRAYS( version, funcname ) \ + case version: \ + bFoundVersion = true; \ + pWebAPIResponse->SetExtendedArrays( true ); \ + { \ + VPROF_BUDGET( #funcname, VPROF_BUDGETGROUP_JOBS_COROUTINES ); \ + bResult = this->##funcname( pRequest, pWebAPIResponse ); \ + } \ + break; + +#define END_WEBAPI_JOB_VERSION_ADAPTERS() \ + default: \ + break; \ +} \ + AssertMsg3( bFoundVersion, "WebAPIJob for %s/%s received unhandled version %d", pchInterface, pchMethod, unVersion ); \ + return bResult; \ +} + + + + +} // namespace GCSDK + + +#endif // GCJOB_H |