mirror of
https://github.com/SWG-Source/src.git
synced 2026-07-28 22:15:49 -04:00
Added platform libs
This commit is contained in:
@@ -20,6 +20,10 @@ find_package(Perl REQUIRED)
|
||||
find_package(STLPort REQUIRED)
|
||||
find_package(ZLib REQUIRED)
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
include_directories(${STLPORT_INCLUDE_DIR})
|
||||
|
||||
add_subdirectory(external)
|
||||
|
||||
@@ -79,6 +79,7 @@ FIND_LIBRARY(STLPORT_LIBRARY_RELEASE
|
||||
$ENV{STLPORT_ROOT}
|
||||
)
|
||||
|
||||
GET_FILENAME_COMPONENT(STLPORT_LIBDIR "${STLPORT_LIBRARY_DEBUG}" PATH)
|
||||
|
||||
IF(STLPORT_INCLUDE_DIR)
|
||||
IF(STLPORT_LIBRARY_RELEASE)
|
||||
|
||||
@@ -731,6 +731,7 @@ include_directories(
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedObject/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedPathfinding/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRandom/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRegex/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedSkillSystem/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedTerrain/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public
|
||||
@@ -739,6 +740,9 @@ include_directories(
|
||||
${SWG_ENGINE_SOURCE_DIR}/server/library/serverPathfinding/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/server/library/serverScript/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/server/library/serverUtility/include/public
|
||||
${SWG_GAME_SOURCE_DIR}/server/application/SwgGameServer/include/public
|
||||
${SWG_GAME_SOURCE_DIR}/server/library/swgServerNetworkMessages/include/public
|
||||
${SWG_GAME_SOURCE_DIR}/shared/library/swgSharedNetworkMessages/include/public
|
||||
${SWG_GAME_SOURCE_DIR}/shared/library/swgSharedUtility/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public
|
||||
@@ -749,6 +753,7 @@ include_directories(
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public
|
||||
${Boost_INCLUDE_DIR}
|
||||
${JNI_INCLUDE_DIRS}
|
||||
${PCRE_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "StringId.h"
|
||||
#include "Unicode.h"
|
||||
#include "UnicodeUtils.h"
|
||||
#include "pcre/pcre.h"
|
||||
#include "pcre.h"
|
||||
#include "sharedFoundation/PointerDeleter.h"
|
||||
#include "sharedRegex/RegexServices.h"
|
||||
#include "sharedUtility/DataTable.h"
|
||||
|
||||
@@ -508,6 +508,7 @@ include_directories(
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/singleton/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public
|
||||
${Boost_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
add_library(serverNetworkMessages STATIC
|
||||
|
||||
@@ -128,6 +128,8 @@ include_directories(
|
||||
${SWG_ENGINE_SOURCE_DIR}/server/library/serverNetworkMessages/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/server/library/serverPathfinding/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/server/library/serverUtility/include/public
|
||||
${SWG_GAME_SOURCE_DIR}/server/application/SwgGameServer/include/public
|
||||
${SWG_GAME_SOURCE_DIR}/shared/library/swgSharedNetworkMessages/include/public
|
||||
${SWG_GAME_SOURCE_DIR}/shared/library/swgSharedUtility/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public
|
||||
|
||||
@@ -58,7 +58,7 @@ include_directories(
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetwork/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetworkMessages/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/serverNetworkMessages/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/server/library/serverNetworkMessages/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localization/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localizationArchive/include/public
|
||||
|
||||
Vendored
+1
@@ -1,2 +1,3 @@
|
||||
|
||||
add_subdirectory(platform)
|
||||
add_subdirectory(udplibrary)
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/projects
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils
|
||||
)
|
||||
|
||||
add_subdirectory(projects)
|
||||
add_subdirectory(utils)
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
add_subdirectory(Session)
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
add_subdirectory(CommonAPI)
|
||||
add_subdirectory(LoginAPI)
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
include_directories(
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/3rd/library/udplibrary
|
||||
)
|
||||
|
||||
add_library(CommonAPI
|
||||
CommonAPI.cpp
|
||||
CommonAPI.h
|
||||
CommonAPIStrings.h
|
||||
CommonClient.cpp
|
||||
CommonClient.h
|
||||
CommonMessages.cpp
|
||||
CommonMessages.h
|
||||
)
|
||||
@@ -0,0 +1,455 @@
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include "CommonAPI.h"
|
||||
|
||||
|
||||
const unsigned MAX_ACCOUNT_NAME_LENGTH = 15;
|
||||
const unsigned MAX_PASSWORD_LENGTH = 15;
|
||||
const unsigned MAX_NAMESPACE_LENGTH = 64;
|
||||
const unsigned SESSION_TICKET_LENGTH = 16;
|
||||
const unsigned SESSION_SERVER_NAME_LENGTH = 40;
|
||||
const unsigned SESSION_CHARACTER_NAME_LENGTH = 128;
|
||||
const unsigned MAX_CLIENT_IP_LENGTH = 16;
|
||||
const unsigned MAX_PLAN_DURATION_LENGTH = 64;
|
||||
const unsigned MAX_GAME_CODE_LENGTH = 64;
|
||||
|
||||
const char * _defaultNamespace = "STATION";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
apiAccount::apiAccount() :
|
||||
mName(),
|
||||
mId(0),
|
||||
mStatus(ACCOUNT_STATUS_NULL)
|
||||
{
|
||||
mName[0] = 0;
|
||||
}
|
||||
|
||||
apiAccount::apiAccount(const apiAccount & copy) :
|
||||
mName(),
|
||||
mId(copy.mId),
|
||||
mStatus(copy.mStatus)
|
||||
{
|
||||
memcpy(mName, copy.mName, apiAccountNameWidth);
|
||||
mName[apiAccountNameWidth-1] = 0;
|
||||
}
|
||||
|
||||
apiAccount::apiAccount(const apiAccount_v1 & copy) :
|
||||
mName(),
|
||||
mId(copy.id),
|
||||
mStatus(copy.status)
|
||||
{
|
||||
strncpy(mName, copy.name, apiAccountNameWidth);
|
||||
mName[apiAccountNameWidth-1] = 0;
|
||||
}
|
||||
|
||||
apiAccount::~apiAccount()
|
||||
{
|
||||
}
|
||||
|
||||
apiAccount & apiAccount::operator=(const apiAccount & rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
memcpy(mName, rhs.mName, apiAccountNameWidth);
|
||||
mName[apiAccountNameWidth-1] = 0;
|
||||
mId = rhs.mId;
|
||||
mStatus = rhs.mStatus;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void apiAccount::SetName(const char * name)
|
||||
{
|
||||
strncpy(mName, name, apiAccountNameWidth-1);
|
||||
mName[apiAccountNameWidth-1] = 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
apiSubscription::apiSubscription() :
|
||||
mGamecode(GAMECODE_NULL),
|
||||
mProviderId(PROVIDER_NULL),
|
||||
mStatus(SUBSCRIPTION_STATUS_NULL),
|
||||
mSubscriptionFeatures(0),
|
||||
mGameFeatures(0),
|
||||
mDurationSeconds(0),
|
||||
mParentalLimitSeconds(0)
|
||||
{
|
||||
}
|
||||
|
||||
apiSubscription::apiSubscription(const apiSubscription & copy) :
|
||||
mGamecode(copy.mGamecode),
|
||||
mProviderId(copy.mProviderId),
|
||||
mStatus(copy.mStatus),
|
||||
mSubscriptionFeatures(copy.mSubscriptionFeatures),
|
||||
mGameFeatures(copy.mGameFeatures),
|
||||
mDurationSeconds(copy.mDurationSeconds),
|
||||
mParentalLimitSeconds(copy.mParentalLimitSeconds)
|
||||
{
|
||||
}
|
||||
|
||||
apiSubscription::apiSubscription(const apiSubscription_v1 & copy) :
|
||||
mGamecode(copy.gamecode),
|
||||
mProviderId(PROVIDER_SOE),
|
||||
mStatus(copy.status),
|
||||
mSubscriptionFeatures(copy.subscriptionFeatures),
|
||||
mGameFeatures(copy.gameFeatures),
|
||||
mDurationSeconds(copy.durationSeconds),
|
||||
mParentalLimitSeconds(copy.parentalLimitSeconds)
|
||||
{
|
||||
}
|
||||
|
||||
apiSubscription::~apiSubscription()
|
||||
{
|
||||
}
|
||||
|
||||
apiSubscription & apiSubscription::operator=(const apiSubscription & rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
mGamecode = rhs.mGamecode;
|
||||
mProviderId = rhs.mProviderId;
|
||||
mStatus = rhs.mStatus;
|
||||
mSubscriptionFeatures = rhs.mSubscriptionFeatures;
|
||||
mGameFeatures = rhs.mGameFeatures;
|
||||
mDurationSeconds = rhs.mDurationSeconds;
|
||||
mParentalLimitSeconds = rhs.mParentalLimitSeconds;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
apiSession::apiSession() :
|
||||
mType(SESSION_TYPE_NULL),
|
||||
mProviderId(PROVIDER_NULL),
|
||||
mId(),
|
||||
mClientIP(0),
|
||||
mDurationSeconds(0),
|
||||
mParentalLimitSeconds(0),
|
||||
mTimeoutMinutes(0),
|
||||
mIsSecure(false)
|
||||
{
|
||||
mId[0] = 0;
|
||||
}
|
||||
|
||||
apiSession::apiSession(const apiSession & copy) :
|
||||
mType(copy.mType),
|
||||
mProviderId(copy.mProviderId),
|
||||
mId(),
|
||||
mClientIP(copy.mClientIP),
|
||||
mDurationSeconds(copy.mDurationSeconds),
|
||||
mParentalLimitSeconds(copy.mParentalLimitSeconds),
|
||||
mTimeoutMinutes(copy.mTimeoutMinutes),
|
||||
mIsSecure(copy.mIsSecure)
|
||||
{
|
||||
memcpy(mId, copy.mId, apiSessionIdWidth);
|
||||
mId[apiSessionIdWidth-1] = 0;
|
||||
}
|
||||
|
||||
apiSession::apiSession(const apiSession_v1 & copy) :
|
||||
mType(copy.type),
|
||||
mProviderId(PROVIDER_SOE),
|
||||
mId(),
|
||||
mClientIP(copy.clientIP),
|
||||
mDurationSeconds(copy.durationSeconds),
|
||||
mParentalLimitSeconds(copy.parentalLimitSeconds),
|
||||
mTimeoutMinutes(copy.timeoutMinutes),
|
||||
mIsSecure(copy.isSecure)
|
||||
{
|
||||
strncpy(mId, copy.id, apiSessionIdWidth);
|
||||
mId[apiSessionIdWidth-1] = 0;
|
||||
}
|
||||
|
||||
apiSession::~apiSession()
|
||||
{
|
||||
}
|
||||
|
||||
apiSession & apiSession::operator=(const apiSession & rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
mType = rhs.mType;
|
||||
mProviderId = rhs.mProviderId;
|
||||
mClientIP = rhs.mClientIP;
|
||||
mDurationSeconds = rhs.mDurationSeconds;
|
||||
mParentalLimitSeconds = rhs.mParentalLimitSeconds;
|
||||
mTimeoutMinutes = rhs.mTimeoutMinutes;
|
||||
mIsSecure = rhs.mIsSecure;
|
||||
|
||||
memcpy(mId, rhs.mId, apiSessionIdWidth);
|
||||
mId[apiSessionIdWidth-1] = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void apiSession::SetId(const char * id)
|
||||
{
|
||||
strncpy(mId, id, apiSessionIdWidth-1);
|
||||
mId[apiSessionIdWidth-1] = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
apiAccount_v1::apiAccount_v1()
|
||||
{
|
||||
memset(this,0,sizeof(apiAccount_v1));
|
||||
}
|
||||
|
||||
apiAccount_v1::apiAccount_v1(const apiAccount_v1 & copy)
|
||||
{
|
||||
memcpy(this,©,sizeof(apiAccount_v1));
|
||||
}
|
||||
|
||||
apiAccount_v1::apiAccount_v1(const apiAccount & copy) :
|
||||
name(),
|
||||
id(copy.GetId()),
|
||||
status(copy.GetStatus())
|
||||
{
|
||||
strncpy(name, copy.GetName(), apiAccountNameWidth_v1-1);
|
||||
name[apiAccountNameWidth_v1-1] = 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
apiSubscription_v1::apiSubscription_v1()
|
||||
{
|
||||
memset(this,0,sizeof(apiSubscription_v1));
|
||||
}
|
||||
|
||||
apiSubscription_v1::apiSubscription_v1(const apiSubscription_v1 & copy)
|
||||
{
|
||||
memcpy(this,©,sizeof(apiSubscription_v1));
|
||||
}
|
||||
|
||||
apiSubscription_v1::apiSubscription_v1(const apiSubscription & copy) :
|
||||
gamecode(copy.GetGamecode()),
|
||||
status(copy.GetStatus()),
|
||||
subscriptionFeatures(copy.GetSubscriptionFeatures()),
|
||||
gameFeatures(copy.GetGameFeatures()),
|
||||
durationSeconds(copy.GetDurationSeconds()),
|
||||
parentalLimitSeconds(copy.GetParentalLimitSeconds())
|
||||
{
|
||||
}
|
||||
|
||||
/********************* Plan *********************************/
|
||||
apiPlan::apiPlan():
|
||||
m_planID(0),
|
||||
m_paymentType(0),
|
||||
m_attributes(0),
|
||||
m_defaultStatus(0),
|
||||
m_reqGameFeatures(0),
|
||||
m_grantedGameFeatures(0),
|
||||
m_reqSubFeatures(0),
|
||||
m_grantedSubFeatures(0)
|
||||
{
|
||||
|
||||
m_description[0] = 0;
|
||||
m_sku[0] = 0;
|
||||
m_duration[0] = 0;
|
||||
m_gameCode[0] = 0;
|
||||
m_billFeatureSkuExt[0] = 0;
|
||||
}
|
||||
|
||||
apiPlan::apiPlan(const apiPlan & copy):
|
||||
m_planID(copy.m_planID),
|
||||
m_paymentType(copy.m_paymentType),
|
||||
m_attributes(copy.m_attributes),
|
||||
m_defaultStatus(copy.m_defaultStatus),
|
||||
m_reqGameFeatures(copy.m_reqGameFeatures),
|
||||
m_grantedGameFeatures(copy.m_grantedGameFeatures),
|
||||
m_reqSubFeatures(copy.m_reqSubFeatures),
|
||||
m_grantedSubFeatures(copy.m_grantedSubFeatures)
|
||||
{
|
||||
memcpy(m_description, copy.m_description, planDescWidth);
|
||||
m_description[planDescWidth-1] = 0;
|
||||
|
||||
memcpy(m_sku, copy.m_sku, planSkuWidth);
|
||||
m_sku[planSkuWidth-1] = 0;
|
||||
|
||||
memcpy(m_duration, copy.m_duration, planDurationWidth);
|
||||
m_duration[planDurationWidth-1] = 0;
|
||||
|
||||
memcpy(m_gameCode, copy.m_gameCode, gameCodeWidth);
|
||||
m_gameCode[gameCodeWidth-1] = 0;
|
||||
|
||||
memcpy(m_billFeatureSkuExt, copy.m_billFeatureSkuExt, billFeatureSkuExtWidth);
|
||||
m_billFeatureSkuExt[billFeatureSkuExtWidth-1] = 0;
|
||||
}
|
||||
|
||||
apiPlan::apiPlan(const apiPlan_v1 & copy):
|
||||
m_planID(copy.planID),
|
||||
m_paymentType(copy.paymentType),
|
||||
m_attributes(copy.attributes),
|
||||
m_defaultStatus(copy.defaultStatus),
|
||||
m_reqGameFeatures(copy.reqGameFeatures),
|
||||
m_grantedGameFeatures(copy.grantedGameFeatures),
|
||||
m_reqSubFeatures(copy.reqSubFeatures),
|
||||
m_grantedSubFeatures(copy.grantedSubFeatures)
|
||||
{
|
||||
strncpy(m_description, copy.description, planDescWidth);
|
||||
m_description[planDescWidth-1] = 0;
|
||||
|
||||
strncpy(m_sku, copy.sku, planSkuWidth);
|
||||
m_sku[planSkuWidth-1] = 0;
|
||||
|
||||
strncpy(m_duration, copy.duration, planDurationWidth);
|
||||
m_duration[planDurationWidth-1] = 0;
|
||||
|
||||
strncpy(m_gameCode, copy.gameCode, gameCodeWidth);
|
||||
m_gameCode[gameCodeWidth-1] = 0;
|
||||
|
||||
strncpy(m_billFeatureSkuExt, copy.billFeatureSkuExt, billFeatureSkuExtWidth);
|
||||
m_billFeatureSkuExt[billFeatureSkuExtWidth-1] = 0;
|
||||
}
|
||||
|
||||
apiPlan::~apiPlan()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
apiPlan & apiPlan::operator=(const apiPlan & rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
m_planID = rhs.m_planID;
|
||||
m_paymentType = rhs.m_paymentType;
|
||||
m_attributes = rhs.m_attributes;
|
||||
m_defaultStatus = rhs.m_defaultStatus;
|
||||
m_reqGameFeatures = rhs.m_reqGameFeatures;
|
||||
m_grantedGameFeatures = rhs.m_grantedGameFeatures;
|
||||
m_reqSubFeatures = rhs.m_reqSubFeatures;
|
||||
m_grantedSubFeatures = rhs.m_grantedSubFeatures;
|
||||
|
||||
memcpy(m_description, rhs.m_description, planDescWidth);
|
||||
m_description[planDescWidth-1] = 0;
|
||||
|
||||
memcpy(m_sku, rhs.m_sku, planSkuWidth);
|
||||
m_sku[planSkuWidth-1] = 0;
|
||||
|
||||
memcpy(m_duration, rhs.m_duration, planDurationWidth);
|
||||
m_duration[planDurationWidth-1] = 0;
|
||||
|
||||
memcpy(m_gameCode, rhs.m_gameCode, gameCodeWidth);
|
||||
m_gameCode[gameCodeWidth-1] = 0;
|
||||
|
||||
memcpy(m_billFeatureSkuExt, rhs.m_billFeatureSkuExt, billFeatureSkuExtWidth);
|
||||
m_billFeatureSkuExt[billFeatureSkuExtWidth-1] = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void apiPlan::SetDescription(const char * description)
|
||||
{
|
||||
memcpy(m_description, description, planDescWidth);
|
||||
m_description[planDescWidth-1] = 0;
|
||||
}
|
||||
|
||||
void apiPlan::SetSku(const char * sku)
|
||||
{
|
||||
memcpy(m_sku, sku, planSkuWidth);
|
||||
m_sku[planSkuWidth-1] = 0;
|
||||
}
|
||||
|
||||
void apiPlan::SetDuration(const char * duration)
|
||||
{
|
||||
memcpy(m_duration, duration, planDurationWidth);
|
||||
m_duration[planDurationWidth-1] = 0;
|
||||
}
|
||||
|
||||
void apiPlan::SetGameCode(const char * gameCode)
|
||||
{
|
||||
memcpy(m_gameCode, gameCode, gameCodeWidth);
|
||||
m_gameCode[gameCodeWidth-1] = 0;
|
||||
}
|
||||
|
||||
void apiPlan::SetBillFeatureSkuExt(const char * billFeatureSkuExt)
|
||||
{
|
||||
memcpy(m_billFeatureSkuExt, billFeatureSkuExt, billFeatureSkuExtWidth);
|
||||
m_billFeatureSkuExt[billFeatureSkuExtWidth-1] = 0;
|
||||
}
|
||||
|
||||
|
||||
///////////////// V1 ////////////////
|
||||
|
||||
apiPlan_v1::apiPlan_v1()
|
||||
{
|
||||
memset(this,0,sizeof(apiPlan_v1));
|
||||
}
|
||||
|
||||
apiPlan_v1::apiPlan_v1(const apiPlan_v1 & copy)
|
||||
{
|
||||
memcpy(this,©,sizeof(apiPlan_v1));
|
||||
}
|
||||
|
||||
apiPlan_v1::apiPlan_v1(const apiPlan & copy):
|
||||
planID(copy.GetPlanID()),
|
||||
paymentType(copy.GetPaymentType()),
|
||||
attributes(copy.GetAttributes()),
|
||||
defaultStatus(copy.GetDefaultStatus()),
|
||||
reqGameFeatures(copy.GetReqGameFeatures()),
|
||||
grantedGameFeatures(copy.GetGrantedGameFeatures()),
|
||||
reqSubFeatures(copy.GetReqSubFeatures()),
|
||||
grantedSubFeatures(copy.GetGrantedSubFeatures())
|
||||
{
|
||||
strncpy(description, copy.GetDescription(), planDescWidth);
|
||||
description[planDescWidth-1] = 0;
|
||||
|
||||
strncpy(sku, copy.GetSku(), planSkuWidth);
|
||||
sku[planSkuWidth-1] = 0;
|
||||
|
||||
strncpy(duration, copy.GetDuration(), planDurationWidth);
|
||||
duration[planDurationWidth-1] = 0;
|
||||
|
||||
strncpy(gameCode, copy.GetGameCode(), gameCodeWidth);
|
||||
gameCode[gameCodeWidth-1] = 0;
|
||||
|
||||
strncpy(billFeatureSkuExt, copy.GetBillFeatureSkuExt(), billFeatureSkuExtWidth);
|
||||
billFeatureSkuExt[billFeatureSkuExtWidth-1] = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
apiSession_v1::apiSession_v1()
|
||||
{
|
||||
memset(this,0,sizeof(apiSession_v1));
|
||||
}
|
||||
|
||||
apiSession_v1::apiSession_v1(const apiSession_v1 & copy)
|
||||
{
|
||||
memcpy(this,©,sizeof(apiSession_v1));
|
||||
}
|
||||
|
||||
apiSession_v1::apiSession_v1(const apiSession & copy) :
|
||||
type(copy.GetType()),
|
||||
id(),
|
||||
clientIP(copy.GetClientIP()),
|
||||
durationSeconds(copy.GetDurationSeconds()),
|
||||
parentalLimitSeconds(copy.GetParentalLimitSeconds()),
|
||||
timeoutMinutes(copy.GetTimeoutMinutes()),
|
||||
isSecure(copy.GetIsSecure())
|
||||
{
|
||||
strncpy(id, copy.GetId(), apiSessionIdWidth_v1-1);
|
||||
id[apiSessionIdWidth_v1-1] = 0;
|
||||
}
|
||||
SessionTypeDesc::SessionTypeDesc(const SessionTypeDesc & copy)
|
||||
{
|
||||
memcpy( this, ©, sizeof(SessionTypeDesc));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,502 @@
|
||||
#ifndef COMMON_API_H
|
||||
#define COMMON_API_H
|
||||
|
||||
|
||||
class apiCore;
|
||||
class apiClient
|
||||
{
|
||||
public:
|
||||
apiClient();
|
||||
virtual ~apiClient();
|
||||
|
||||
void Connect(const char * address);
|
||||
virtual void Process();
|
||||
|
||||
////////////////////////////////////////
|
||||
// State Callbacks
|
||||
virtual void OnConnectionOpened(const char * address, unsigned connectionCount);
|
||||
virtual void OnConnectionClosed(const char * address, unsigned connectionCount);
|
||||
virtual void OnConnectionFailed(const char * address, unsigned connectionCount);
|
||||
|
||||
protected:
|
||||
apiCore * mClientCore;
|
||||
};
|
||||
|
||||
#define apiSessionType unsigned
|
||||
#define apiGamecode unsigned
|
||||
|
||||
typedef unsigned apiAccountId;
|
||||
typedef unsigned apiTrackingNumber;
|
||||
typedef unsigned apiProductFeatures;
|
||||
typedef unsigned apiIP;
|
||||
typedef unsigned apiResult;
|
||||
typedef unsigned apiAccountStatus;
|
||||
typedef unsigned apiSubscriptionStatus;
|
||||
typedef unsigned apiProviderId;
|
||||
typedef unsigned apiKickReason;
|
||||
typedef unsigned apiKickReply;
|
||||
|
||||
#ifdef API_NAMESPACE
|
||||
namespace API_NAMESPACE
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
RESULT_SUCCESS = 0, // operation successful
|
||||
RESULT_CANCELLED, // operation cancelled by user
|
||||
RESULT_TIMEOUT, // operation could not be serviced
|
||||
RESULT_FUNCTION_DEPRICATED, // operation is not supported anymore
|
||||
RESULT_FUNCTION_NOT_SUPPORTED, // operation is not supported yet
|
||||
|
||||
// Login related result codes
|
||||
RESULT_INVALID_NAME_OR_PASSWORD = 1000,
|
||||
RESULT_INVALID_ACCOUNT_ID,
|
||||
RESULT_INVALID_SESSION,
|
||||
RESULT_INVALID_PARENT_SESSION,
|
||||
RESULT_INVALID_SESSION_TYPE,
|
||||
RESULT_INVALID_GAMECODE,
|
||||
RESULT_REQUIRES_VALID_SUBSCRIPTION,
|
||||
RESULT_REQUIRES_ACTIVE_ACCOUNT,
|
||||
RESULT_REQUIRES_CLIENT_LOGOUT,
|
||||
RESULT_SESSION_ALREADY_CONSUMED,
|
||||
RESULT_REQUIRES_SECURE_ID_NEXT_CODE,
|
||||
RESULT_REQUIRES_SECURE_ID_NEW_PIN,
|
||||
RESULT_SECURE_ID_PIN_ACCEPTED,
|
||||
RESULT_SECURE_ID_PIN_REJECTED,
|
||||
RESULT_USAGE_LIMIT_DENIED_LOGIN,
|
||||
RESULT_INVALID_FEATURE,
|
||||
RESULT_INVALID_SERVER_NAME,
|
||||
RESULT_INVALID_CHARACTER_NAME,
|
||||
RESULT_INVALID_NAMESPACE,
|
||||
RESULT_INVALID_CLIENT_IP,
|
||||
RESULT_USER_LOCKOUT,
|
||||
RESULT_INVALID_KICK_REASON,
|
||||
|
||||
// Chat related result codes
|
||||
RESULT_INVALID_AVATAR = 1032,
|
||||
RESULT_INVALID_CHATROOM,
|
||||
RESULT_INVALID_MESSAGE,
|
||||
RESULT_INVALID_FANCLUB,
|
||||
RESULT_INVALID_ROOM_BANNER,
|
||||
RESULT_REQUIRES_FANCLUB_MEMBERSHIP,
|
||||
RESULT_REQUIRES_ONLINE_AVATAR,
|
||||
RESULT_REQUIRES_MODERATOR_PRIVILEGES,
|
||||
RESULT_REQUIRES_VALID_MODERATION_STATE,
|
||||
RESULT_BANNED_FROM_ROOM,
|
||||
RESULT_FULL_ROOM,
|
||||
RESULT_INVALID_ROOM_PATH,
|
||||
RESULT_INVALID_ROOM_ATTRIBUTES,
|
||||
RESULT_INVALID_MAX_ROOM_SIZE,
|
||||
RESULT_INVALID_SUBJECT_SIZE,
|
||||
|
||||
RESULT_INVALID_PLAN_DURATION_SIZE = 2000,
|
||||
RESULT_INVALID_GAME_CODE_SIZE,
|
||||
RESULT_INVALID_PLAN_ID,
|
||||
RESULT_INVALID_FEATURE_MATCH,
|
||||
RESULT_INVALID_SUBSCRIPTION
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ACCOUNT_STATUS_NULL, // Invalid account status
|
||||
ACCOUNT_STATUS_ACTIVE,
|
||||
ACCOUNT_STATUS_CLOSED,
|
||||
// Add new account status codes here
|
||||
ACCOUNT_STATUS_END
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SESSION_TYPE_NULL, // Invalid session type
|
||||
SESSION_TYPE_LAUNCH_PAD,
|
||||
SESSION_TYPE_STATION_UNSECURE,
|
||||
SESSION_TYPE_STATION_SECURE,
|
||||
SESSION_TYPE_TANARUS,
|
||||
SESSION_TYPE_INFANTRY,
|
||||
SESSION_TYPE_COSMIC_RIFT,
|
||||
SESSION_TYPE_EVERQUEST,
|
||||
SESSION_TYPE_EVERQUEST_2,
|
||||
SESSION_TYPE_STARWARS,
|
||||
SESSION_TYPE_PLANETSIDE,
|
||||
SESSION_TYPE_EVERQUEST_ONLINE_ADVENTURES_BETA,
|
||||
SESSION_TYPE_EVERQUEST_ONLINE_ADVENTURES,
|
||||
SESSION_TYPE_EVERQUEST_INSTANT_MESSENGER,
|
||||
SESSION_TYPE_REALM_SERVER,
|
||||
SESSION_TYPE_EVERQUEST_MACINTOSH,
|
||||
SESSION_TYPE_MATRIX_ONLINE,
|
||||
SESSION_TYPE_HARRY_POTTER,
|
||||
SESSION_TYPE_NEO_PETS,
|
||||
SESSION_TYPE_GOODLIFE,
|
||||
SESSION_TYPE_EQ2_GUILDS,
|
||||
SESSION_TYPE_SWG_JP_BETA,
|
||||
SESSION_TYPE_MARVEL,
|
||||
SESSION_TYPE_EQ2_JAPAN,
|
||||
SESSION_TYPE_EQ2_TAIWAN,
|
||||
SESSION_TYPE_EQ2_CHINA,
|
||||
SESSION_TYPE_EQ2_KOREA,
|
||||
SESSION_TYPE_VGD,
|
||||
SESSION_TYPE_PIRATE,
|
||||
SESSION_TYPE_STAR_CHAMBER,
|
||||
SESSION_TYPE_STARGATE,
|
||||
SESSION_TYPE_DCU_ONLINE,
|
||||
SESSION_TYPE_NORRATH_CSG,
|
||||
// Add new session type codes here
|
||||
SESSION_TYPE_END
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GAMECODE_NULL, // Invalid gamecode
|
||||
GAMECODE_STATION_PASS,
|
||||
GAMECODE_EVERQUEST,
|
||||
GAMECODE_EVERQUEST_2,
|
||||
GAMECODE_STARWARS,
|
||||
GAMECODE_PLANETSIDE,
|
||||
GAMECODE_EVERQUEST_ONLINE_ADVENTURES_BETA,
|
||||
GAMECODE_EVERQUEST_ONLINE_ADVENTURES,
|
||||
GAMECODE_EVERQUEST_INSTANT_MESSENGER,
|
||||
GAMECODE_EVERQUEST_MACINTOSH,
|
||||
GAMECODE_MATRIX_ONLINE,
|
||||
GAMECODE_HARRY_POTTER,
|
||||
GAMECODE_NEO_PETS,
|
||||
GAMECODE_GOODLIFE,
|
||||
GAMECODE_SWG_JP_BETA,
|
||||
GAMECODE_MARVEL,
|
||||
GAMECODE_EQ2_JAPAN,
|
||||
GAMECODE_EQ2_TAIWAN,
|
||||
GAMECODE_EQ2_CHINA,
|
||||
GAMECODE_EQ2_KOREA,
|
||||
GAMECODE_VGD,
|
||||
GAMECODE_PIRATE,
|
||||
GAMECODE_STAR_CHAMBER,
|
||||
GAMECODE_STARGATE,
|
||||
GAMECODE_DCU_ONLINE,
|
||||
GAMECODE_NORRATH_CSG,
|
||||
// Add new gamecodes here
|
||||
GAMECODE_END
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SUBSCRIPTION_STATUS_NULL, // Invalid subscription status
|
||||
SUBSCRIPTION_STATUS_NO_ACCOUNT,
|
||||
SUBSCRIPTION_STATUS_ACTIVE,
|
||||
SUBSCRIPTION_STATUS_PENDING,
|
||||
SUBSCRIPTION_STATUS_CLOSED,
|
||||
SUBSCRIPTION_STATUS_TRIAL_ACTIVE,
|
||||
SUBSCRIPTION_STATUS_TRIAL_EXPIRED,
|
||||
SUBSCRIPTION_STATUS_SUSPENDED,
|
||||
SUBSCRIPTION_STATUS_BANNED,
|
||||
SUBSCRIPTION_STATUS_RENTAL_ACTIVE,
|
||||
SUBSCRIPTION_STATUS_RENTAL_CLOSED,
|
||||
SUBSCRIPTION_STATUS_ACTIVE_COMBO,
|
||||
SUBSCRIPTION_STATUS_BANNED_CHARGEBACK,
|
||||
// Add new subscription status codes here
|
||||
SUBSCRIPTION_STATUS_END
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
KICK_REASON_NULL, // Invalid kick reason
|
||||
KICK_REASON_USER_REQUEST,
|
||||
KICK_REASON_ADMIN_REQUEST,
|
||||
// Add new kick reason codes here
|
||||
KICK_REASON_END
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
KICK_REPLY_NULL,
|
||||
KICK_REPLY_ALLOW,
|
||||
KICK_REPLY_DENY,
|
||||
KICK_REPLY_UNKNOWN_SESSION,
|
||||
// Add new kick reply codes here
|
||||
KICK_REPLY_END
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROVIDER_NULL,
|
||||
PROVIDER_SOE,
|
||||
PROVIDER_UBISOFT,
|
||||
// Add new provider id codes here
|
||||
PROVIDER_END
|
||||
};
|
||||
|
||||
|
||||
#ifdef API_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
extern const unsigned MAX_ACCOUNT_NAME_LENGTH; // 15: ASCII characters (alpha-numeric only)
|
||||
extern const unsigned MAX_PASSWORD_LENGTH; // 15: ASCII characters (alpha-numeric only)
|
||||
extern const unsigned MAX_NAMESPACE_LENGTH; // 64: ASCII characters (alpha-numeric only)
|
||||
extern const unsigned SESSION_TICKET_LENGTH; // 16: ASCII characters (alpha numeric + '.' + '?')
|
||||
extern const unsigned SESSION_SERVER_NAME_LENGTH;
|
||||
extern const unsigned SESSION_CHARACTER_NAME_LENGTH;
|
||||
extern const unsigned MAX_CLIENT_IP_LENGTH;
|
||||
extern const unsigned MAX_PLAN_DURATION_LENGTH;
|
||||
extern const unsigned MAX_GAME_CODE_LENGTH;
|
||||
|
||||
extern const char * _defaultNamespace;
|
||||
|
||||
static const int apiAccountNameWidth = 16;
|
||||
struct apiAccount_v1;
|
||||
class apiAccount
|
||||
{
|
||||
public:
|
||||
apiAccount();
|
||||
apiAccount(const apiAccount & copy);
|
||||
apiAccount(const apiAccount_v1 & copy);
|
||||
~apiAccount();
|
||||
|
||||
apiAccount & operator=(const apiAccount & rhs);
|
||||
|
||||
const char * GetName() const { return mName; }
|
||||
apiAccountId GetId() const { return mId; }
|
||||
apiAccountStatus GetStatus() const { return mStatus; }
|
||||
|
||||
void SetName(const char * name);
|
||||
void SetId(apiAccountId id) { mId = id; }
|
||||
void SetStatus(apiAccountStatus status) { mStatus = status; }
|
||||
|
||||
private:
|
||||
char mName[apiAccountNameWidth];
|
||||
apiAccountId mId;
|
||||
apiAccountStatus mStatus;
|
||||
};
|
||||
|
||||
struct apiSubscription_v1;
|
||||
class apiSubscription
|
||||
{
|
||||
public:
|
||||
apiSubscription();
|
||||
apiSubscription(const apiSubscription & copy);
|
||||
apiSubscription(const apiSubscription_v1 & copy);
|
||||
~apiSubscription();
|
||||
|
||||
apiSubscription & operator=(const apiSubscription & rhs);
|
||||
|
||||
apiGamecode GetGamecode() const { return mGamecode; }
|
||||
apiProviderId GetProviderId() const { return mProviderId; }
|
||||
apiSubscriptionStatus GetStatus() const { return mStatus; }
|
||||
apiProductFeatures GetSubscriptionFeatures() const { return mSubscriptionFeatures; }
|
||||
apiProductFeatures GetGameFeatures() const { return mGameFeatures; }
|
||||
unsigned GetDurationSeconds() const { return mDurationSeconds; }
|
||||
unsigned GetParentalLimitSeconds() const { return mParentalLimitSeconds; }
|
||||
|
||||
void SetGamecode(apiGamecode gamecode) { mGamecode = gamecode; }
|
||||
void SetProviderId(apiProviderId provider) { mProviderId = provider; }
|
||||
void SetStatus(apiSubscriptionStatus status) { mStatus = status; }
|
||||
void SetSubscriptionFeatures(apiProductFeatures features) { mSubscriptionFeatures = features; }
|
||||
void SetGameFeatures(apiProductFeatures features) { mGameFeatures = features; }
|
||||
void SetDurationSeconds(unsigned duration) { mDurationSeconds = duration; }
|
||||
void SetParentalLimitSeconds(unsigned parentalLimit) { mParentalLimitSeconds = parentalLimit; }
|
||||
|
||||
private:
|
||||
apiGamecode mGamecode;
|
||||
apiProviderId mProviderId;
|
||||
apiSubscriptionStatus mStatus;
|
||||
apiProductFeatures mSubscriptionFeatures;
|
||||
apiProductFeatures mGameFeatures;
|
||||
unsigned mDurationSeconds;
|
||||
unsigned mParentalLimitSeconds;
|
||||
};
|
||||
|
||||
static const int apiSessionIdWidth = 17;
|
||||
struct apiSession_v1;
|
||||
class apiSession
|
||||
{
|
||||
public:
|
||||
apiSession();
|
||||
apiSession(const apiSession & copy);
|
||||
apiSession(const apiSession_v1 & copy);
|
||||
~apiSession();
|
||||
|
||||
apiSession & operator=(const apiSession & rhs);
|
||||
|
||||
apiSessionType GetType() const { return mType; }
|
||||
apiProviderId GetProviderId() const { return mProviderId; }
|
||||
const char * GetId() const { return mId; }
|
||||
apiIP GetClientIP() const { return mClientIP; }
|
||||
unsigned GetDurationSeconds() const { return mDurationSeconds; }
|
||||
unsigned GetParentalLimitSeconds() const { return mParentalLimitSeconds; }
|
||||
unsigned char GetTimeoutMinutes() const { return mTimeoutMinutes; }
|
||||
bool GetIsSecure() const { return mIsSecure; }
|
||||
|
||||
void SetType(apiSessionType type) { mType = type; }
|
||||
void SetProviderId(apiProviderId provider) { mProviderId = provider; }
|
||||
void SetId(const char * id);
|
||||
void SetClientIP(apiIP clientIP) { mClientIP = clientIP; }
|
||||
void SetDurationSeconds(unsigned duration) { mDurationSeconds = duration; }
|
||||
void SetParentalLimitSeconds(unsigned parentalLimit) { mParentalLimitSeconds = parentalLimit; }
|
||||
void SetTimeoutMinutes(unsigned char timeout) { mTimeoutMinutes = timeout; }
|
||||
void SetIsSecure(bool isSecure) { mIsSecure = isSecure; }
|
||||
|
||||
private:
|
||||
apiSessionType mType;
|
||||
apiProviderId mProviderId;
|
||||
char mId[apiSessionIdWidth];
|
||||
apiIP mClientIP;
|
||||
unsigned mDurationSeconds;
|
||||
unsigned mParentalLimitSeconds;
|
||||
unsigned char mTimeoutMinutes;
|
||||
bool mIsSecure;
|
||||
};
|
||||
|
||||
|
||||
static const int apiAccountNameWidth_v1 = 32;
|
||||
struct apiAccount_v1
|
||||
{
|
||||
apiAccount_v1();
|
||||
apiAccount_v1(const apiAccount_v1 & copy);
|
||||
apiAccount_v1(const apiAccount & copy);
|
||||
|
||||
char name[apiAccountNameWidth_v1];
|
||||
apiAccountId id;
|
||||
apiAccountStatus status;
|
||||
};
|
||||
|
||||
struct apiSubscription_v1
|
||||
{
|
||||
apiSubscription_v1();
|
||||
apiSubscription_v1(const apiSubscription_v1 & copy);
|
||||
apiSubscription_v1(const apiSubscription & copy);
|
||||
|
||||
apiGamecode gamecode;
|
||||
apiSubscriptionStatus status;
|
||||
apiProductFeatures subscriptionFeatures;
|
||||
apiProductFeatures gameFeatures;
|
||||
unsigned durationSeconds;
|
||||
unsigned parentalLimitSeconds;
|
||||
};
|
||||
|
||||
static const int apiSessionIdWidth_v1 = 32;
|
||||
struct apiSession_v1
|
||||
{
|
||||
apiSession_v1();
|
||||
apiSession_v1(const apiSession_v1 & copy);
|
||||
apiSession_v1(const apiSession & copy);
|
||||
|
||||
apiSessionType type;
|
||||
char id[apiSessionIdWidth_v1];
|
||||
apiIP clientIP;
|
||||
unsigned durationSeconds;
|
||||
unsigned parentalLimitSeconds;
|
||||
unsigned char timeoutMinutes;
|
||||
bool isSecure;
|
||||
};
|
||||
|
||||
static const int gameCodeWidth = 26;
|
||||
static const int sessionTypeDescriptionWidth = 257;
|
||||
struct SessionTypeDesc
|
||||
{
|
||||
SessionTypeDesc() : type(0), gameCodeID(0), independent(false), exclusive(false) {gameCode[0]= 0; description[0] = 0;}
|
||||
SessionTypeDesc(const SessionTypeDesc & copy);
|
||||
apiSessionType type;
|
||||
char gameCode[gameCodeWidth];
|
||||
apiGamecode gameCodeID;
|
||||
char description[sessionTypeDescriptionWidth];
|
||||
bool independent;
|
||||
bool exclusive;
|
||||
};
|
||||
|
||||
static const int gameCodeDescriptionWidth = 256;
|
||||
struct GameCodeDescription
|
||||
{
|
||||
GameCodeDescription() : gameID(0), createDynamic(false) { code[0] = 0; description[0] = 0;}
|
||||
|
||||
apiGamecode gameID;
|
||||
char code[gameCodeWidth];
|
||||
char description[gameCodeDescriptionWidth];
|
||||
bool createDynamic;
|
||||
};
|
||||
|
||||
/*************** Plan **************************************/
|
||||
struct apiPlan_v1;
|
||||
static const int planDescWidth = 256;
|
||||
static const int planSkuWidth = 256;
|
||||
static const int planDurationWidth = 11;
|
||||
static const int billFeatureSkuExtWidth = 101;
|
||||
|
||||
class apiPlan
|
||||
{
|
||||
public:
|
||||
apiPlan();
|
||||
apiPlan(const apiPlan & copy);
|
||||
apiPlan(const apiPlan_v1 & copy);
|
||||
~apiPlan();
|
||||
|
||||
apiPlan & operator=(const apiPlan & rhs);
|
||||
|
||||
unsigned GetPlanID() const { return m_planID; }
|
||||
const char * GetDescription() const { return m_description; }
|
||||
const char * GetSku() const { return m_sku; }
|
||||
unsigned GetPaymentType() const { return m_paymentType; }
|
||||
const char * GetDuration() const { return m_duration; }
|
||||
unsigned GetAttributes() const { return m_attributes; }
|
||||
unsigned GetDefaultStatus() const { return m_defaultStatus; }
|
||||
const char * GetGameCode() const { return m_gameCode; }
|
||||
unsigned GetReqGameFeatures() const { return m_reqGameFeatures; }
|
||||
unsigned GetGrantedGameFeatures() const { return m_grantedGameFeatures; }
|
||||
unsigned GetReqSubFeatures() const { return m_reqSubFeatures; }
|
||||
unsigned GetGrantedSubFeatures() const { return m_grantedSubFeatures; }
|
||||
const char * GetBillFeatureSkuExt() const { return m_billFeatureSkuExt; }
|
||||
|
||||
void SetPlanID(unsigned planID) { m_planID = planID; }
|
||||
void SetDescription(const char * description);
|
||||
void SetSku(const char * sku);
|
||||
void SetPaymentType(unsigned paymentType) { m_paymentType = paymentType; }
|
||||
void SetDuration(const char * duration);
|
||||
void SetAttributes(unsigned attributes) { m_attributes = attributes; }
|
||||
void SetDefaultStatus(unsigned defaultStatus) { m_defaultStatus = defaultStatus; }
|
||||
void SetGameCode(const char * gameCode);
|
||||
void SetReqGameFeatures(unsigned reqGameFeatures) { m_reqGameFeatures = reqGameFeatures; }
|
||||
void SetGrantedGameFeatures(unsigned grantedGameFeatures) { m_grantedGameFeatures = grantedGameFeatures; }
|
||||
void SetReqSubFeatures(unsigned reqSubFeatures) { m_reqSubFeatures = reqSubFeatures; }
|
||||
void SetGrantedSubFeatures(unsigned grantedSubFeatures) { m_grantedSubFeatures = grantedSubFeatures; }
|
||||
void SetBillFeatureSkuExt(const char * billFeatureSkuExt);
|
||||
|
||||
private:
|
||||
|
||||
unsigned m_planID;
|
||||
char m_description[planDescWidth];
|
||||
char m_sku[planSkuWidth];
|
||||
unsigned m_paymentType;
|
||||
char m_duration[planDurationWidth];
|
||||
unsigned m_attributes;
|
||||
unsigned m_defaultStatus;
|
||||
char m_gameCode[gameCodeWidth];
|
||||
unsigned m_reqGameFeatures;
|
||||
unsigned m_grantedGameFeatures;
|
||||
unsigned m_reqSubFeatures;
|
||||
unsigned m_grantedSubFeatures;
|
||||
char m_billFeatureSkuExt[billFeatureSkuExtWidth];
|
||||
};
|
||||
|
||||
struct apiPlan_v1
|
||||
{
|
||||
apiPlan_v1();
|
||||
apiPlan_v1(const apiPlan_v1 & copy);
|
||||
apiPlan_v1(const apiPlan & copy);
|
||||
|
||||
unsigned planID;
|
||||
char description[planDescWidth];
|
||||
char sku[planSkuWidth];
|
||||
unsigned paymentType;
|
||||
char duration[planDurationWidth];
|
||||
unsigned attributes;
|
||||
unsigned defaultStatus;
|
||||
char gameCode[gameCodeWidth];
|
||||
unsigned reqGameFeatures;
|
||||
unsigned grantedGameFeatures;
|
||||
unsigned reqSubFeatures;
|
||||
unsigned grantedSubFeatures;
|
||||
char billFeatureSkuExt[billFeatureSkuExtWidth];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
#ifndef COMMON_API_STRINGS_H
|
||||
#define COMMON_API_STRINGS_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "CommonAPI.h"
|
||||
|
||||
#define result_text std::pair<apiResult,const char *>
|
||||
#define gamecode_text std::pair<apiGamecode,const char *>
|
||||
#define text_gamecode std::pair<std::string, apiGamecode>
|
||||
|
||||
static const int _ResultCount = 38;
|
||||
static const result_text _resultString[_ResultCount] =
|
||||
{
|
||||
result_text(RESULT_SUCCESS, "RESULT_SUCCESS"),
|
||||
result_text(RESULT_CANCELLED, "RESULT_CANCELLED"),
|
||||
result_text(RESULT_TIMEOUT, "RESULT_TIMEOUT"),
|
||||
result_text(RESULT_FUNCTION_DEPRICATED, "RESULT_FUNCTION_DEPRICATED"),
|
||||
result_text(RESULT_FUNCTION_NOT_SUPPORTED, "RESULT_FUNCTION_NOT_SUPPORTED"),
|
||||
result_text(RESULT_INVALID_NAME_OR_PASSWORD, "RESULT_INVALID_NAME_OR_PASSWORD"),
|
||||
result_text(RESULT_INVALID_ACCOUNT_ID, "RESULT_INVALID_USER_ID"),
|
||||
result_text(RESULT_INVALID_SESSION, "RESULT_INVALID_SESSION"),
|
||||
result_text(RESULT_INVALID_PARENT_SESSION, "RESULT_INVALID_PARENT_SESSION"),
|
||||
result_text(RESULT_INVALID_SESSION_TYPE, "RESULT_INVALID_SESSION_TYPE"),
|
||||
result_text(RESULT_INVALID_GAMECODE, "RESULT_INVALID_GAMECODE"),
|
||||
result_text(RESULT_REQUIRES_VALID_SUBSCRIPTION, "RESULT_REQUIRES_VALID_SUBSCRIPTION"),
|
||||
result_text(RESULT_REQUIRES_ACTIVE_ACCOUNT, "RESULT_REQUIRES_ACTIVE_ACCOUNT"),
|
||||
result_text(RESULT_REQUIRES_CLIENT_LOGOUT, "RESULT_REQUIRES_CLIENT_LOGOUT"),
|
||||
result_text(RESULT_SESSION_ALREADY_CONSUMED, "RESULT_SESSION_ALREADY_CONSUMED"),
|
||||
result_text(RESULT_REQUIRES_SECURE_ID_NEXT_CODE, "RESULT_REQUIRES_SECURE_ID_NEXT_CODE"),
|
||||
result_text(RESULT_REQUIRES_SECURE_ID_NEW_PIN, "RESULT_REQUIRES_SECURE_ID_NEW_PIN"),
|
||||
result_text(RESULT_SECURE_ID_PIN_ACCEPTED, "RESULT_SECURE_ID_PIN_ACCEPTED"),
|
||||
result_text(RESULT_SECURE_ID_PIN_REJECTED, "RESULT_SECURE_ID_PIN_REJECTED"),
|
||||
result_text(RESULT_USAGE_LIMIT_DENIED_LOGIN, "RESULT_USAGE_LIMIT_DENIED_LOGIN"),
|
||||
result_text(RESULT_INVALID_FEATURE, "RESULT_INVALID_FEATURE"),
|
||||
result_text(RESULT_INVALID_AVATAR, "RESULT_INVALID_AVATAR"),
|
||||
result_text(RESULT_INVALID_CHATROOM, "RESULT_INVALID_CHATROOM"),
|
||||
result_text(RESULT_INVALID_MESSAGE, "RESULT_INVALID_MESSAGE"),
|
||||
result_text(RESULT_INVALID_FANCLUB, "RESULT_INVALID_FANCLUB"),
|
||||
result_text(RESULT_INVALID_ROOM_BANNER, "RESULT_INVALID_ROOM_BANNER"),
|
||||
result_text(RESULT_REQUIRES_FANCLUB_MEMBERSHIP, "RESULT_REQUIRES_FANCLUB_MEMBERSHIP"),
|
||||
result_text(RESULT_REQUIRES_ONLINE_AVATAR, "RESULT_REQUIRES_ONLINE_AVATAR"),
|
||||
result_text(RESULT_REQUIRES_MODERATOR_PRIVILEGES, "RESULT_REQUIRES_MODERATOR_PRIVILEGES"),
|
||||
result_text(RESULT_REQUIRES_VALID_MODERATION_STATE, "RESULT_REQUIRES_VALID_MODERATION_STATE"),
|
||||
result_text(RESULT_BANNED_FROM_ROOM, "RESULT_BANNED_FROM_ROOM"),
|
||||
result_text(RESULT_INVALID_NAMESPACE, "RESULT_INVALID_NAMESPACE"),
|
||||
result_text(RESULT_INVALID_CLIENT_IP, "RESULT_INVALID_CLIENT_IP"),
|
||||
result_text(RESULT_USER_LOCKOUT, "RESULT_USER_LOCKOUT"),
|
||||
result_text(RESULT_INVALID_KICK_REASON, "RESULT_INVALID_KICK_REASON"),
|
||||
result_text(RESULT_INVALID_PLAN_ID, "RESULT_INVALID_PLAN_ID"),
|
||||
result_text(RESULT_INVALID_FEATURE_MATCH, "RESULT_INVALID_FEATURE_MATCH"),
|
||||
result_text(RESULT_INVALID_SUBSCRIPTION, "RESULT_INVALID_SUBSCRIPTION"),
|
||||
|
||||
};
|
||||
static std::map<apiResult,const char *> ResultString((const std::map<apiResult,const char *>::value_type *)&_resultString[0],(const std::map<apiResult,const char *>::value_type *)&_resultString[_ResultCount]);
|
||||
|
||||
static const result_text _resultText[_ResultCount] =
|
||||
{
|
||||
result_text(RESULT_SUCCESS, "The operation completed successfully."),
|
||||
result_text(RESULT_CANCELLED, "The operation was cancelled by the requestor."),
|
||||
result_text(RESULT_TIMEOUT, "The operation could not be processed within a reasonable time. Please try again."),
|
||||
result_text(RESULT_FUNCTION_DEPRICATED, "This operation is no longer supported."),
|
||||
result_text(RESULT_FUNCTION_NOT_SUPPORTED, "This operation is not supported yet."),
|
||||
result_text(RESULT_INVALID_NAME_OR_PASSWORD, "The sepecifed user name or password is invalid."),
|
||||
result_text(RESULT_INVALID_ACCOUNT_ID, "The sepecifed account identifier is invalid."),
|
||||
result_text(RESULT_INVALID_SESSION, "The sepecifed session identifier is invalid."),
|
||||
result_text(RESULT_INVALID_PARENT_SESSION, "The sepecifed parent session identifier is invalid."),
|
||||
result_text(RESULT_INVALID_SESSION_TYPE, "The sepecifed session type is invalid."),
|
||||
result_text(RESULT_INVALID_GAMECODE, "The specified gamecode is invalid."),
|
||||
result_text(RESULT_REQUIRES_VALID_SUBSCRIPTION, "This operation requires a valid subscription to complete."),
|
||||
result_text(RESULT_REQUIRES_ACTIVE_ACCOUNT, "RESULT_REQUIRES_ACTIVE_ACCOUNT"),
|
||||
result_text(RESULT_REQUIRES_CLIENT_LOGOUT, "RESULT_REQUIRES_CLIENT_LOGOUT"),
|
||||
result_text(RESULT_SESSION_ALREADY_CONSUMED, "RESULT_SESSION_ALREADY_CONSUMED"),
|
||||
result_text(RESULT_REQUIRES_SECURE_ID_NEXT_CODE,"RESULT_REQUIRES_SECURE_ID_NEXT_CODE"),
|
||||
result_text(RESULT_REQUIRES_SECURE_ID_NEW_PIN, "RESULT_REQUIRES_SECURE_ID_NEW_PIN"),
|
||||
result_text(RESULT_SECURE_ID_PIN_ACCEPTED, "RESULT_SECURE_ID_PIN_ACCEPTED"),
|
||||
result_text(RESULT_SECURE_ID_PIN_REJECTED, "RESULT_SECURE_ID_PIN_REJECTED"),
|
||||
result_text(RESULT_USAGE_LIMIT_DENIED_LOGIN, "RESULT_USAGE_LIMIT_DENIED_LOGIN"),
|
||||
result_text(RESULT_INVALID_FEATURE, "RESULT_INVALID_FEATURE"),
|
||||
result_text(RESULT_INVALID_AVATAR, "The specified chat avatar name is invalid."),
|
||||
result_text(RESULT_INVALID_CHATROOM, "The specified chat room name is invalid."),
|
||||
result_text(RESULT_INVALID_MESSAGE, "The specified chat message is invalid."),
|
||||
result_text(RESULT_INVALID_FANCLUB, "The specified fan club is invalid."),
|
||||
result_text(RESULT_INVALID_ROOM_BANNER, "RESULT_INVALID_ROOM_BANNER"),
|
||||
result_text(RESULT_REQUIRES_FANCLUB_MEMBERSHIP, "This operation requires membership inb the specified fan club."),
|
||||
result_text(RESULT_REQUIRES_ONLINE_AVATAR, "RESULT_REQUIRES_ONLINE_AVATAR"),
|
||||
result_text(RESULT_REQUIRES_MODERATOR_PRIVILEGES, "RESULT_REQUIRES_MODERATOR_PRIVILEGES"),
|
||||
result_text(RESULT_REQUIRES_VALID_MODERATION_STATE, "RESULT_REQUIRES_VALID_MODERATION_STATE"),
|
||||
result_text(RESULT_BANNED_FROM_ROOM, "RESULT_BANNED_FROM_ROOM"),
|
||||
result_text(RESULT_INVALID_NAMESPACE, "RESULT_INVALID_NAMESPACE"),
|
||||
result_text(RESULT_INVALID_PLAN_ID, "RESULT_INVALID_PLAN_ID"),
|
||||
result_text(RESULT_INVALID_FEATURE_MATCH, "RESULT_INVALID_FEATURE_MATCH"),
|
||||
result_text(RESULT_INVALID_SUBSCRIPTION, "RESULT_INVALID_SUBSCRIPTION"),
|
||||
};
|
||||
static std::map<apiResult,const char *> ResultText((const std::map<apiResult,const char *>::value_type *)&_resultText[0],(const std::map<apiResult,const char *>::value_type *)&_resultText[_ResultCount]);
|
||||
|
||||
static const char * AccountStatusString[ACCOUNT_STATUS_END] =
|
||||
{
|
||||
"ACCOUNT_STATUS_NULL",
|
||||
"ACCOUNT_STATUS_ACTIVE",
|
||||
"ACCOUNT_STATUS_CLOSED"
|
||||
};
|
||||
|
||||
static const char * SessionTypeString[SESSION_TYPE_END] =
|
||||
{
|
||||
"SESSION_TYPE_NULL",
|
||||
"SESSION_TYPE_LAUNCH_PAD",
|
||||
"SESSION_TYPE_STATION_UNSECURE",
|
||||
"SESSION_TYPE_STATION_SECURE",
|
||||
"SESSION_TYPE_TANARUS",
|
||||
"SESSION_TYPE_INFANTRY",
|
||||
"SESSION_TYPE_COSMIC_RIFT",
|
||||
"SESSION_TYPE_EVERQUEST",
|
||||
"SESSION_TYPE_EVERQUEST_2",
|
||||
"SESSION_TYPE_STARWARS",
|
||||
"SESSION_TYPE_PLANETSIDE",
|
||||
"SESSION_TYPE_EVERQUEST_ONLINE_ADVENTURES_BETA",
|
||||
"SESSION_TYPE_EVERQUEST_ONLINE_ADVENTURES",
|
||||
"SESSION_TYPE_EVERQUEST_INSTANT_MESSENGER",
|
||||
"SESSION_TYPE_REALM_SERVER",
|
||||
"SESSION_TYPE_EVERQUEST_MACINTOSH",
|
||||
"SESSION_TYPE_MATRIX_ONLINE",
|
||||
"SESSION_TYPE_HARRY_POTTER",
|
||||
"SESSION_TYPE_NEO_PETS",
|
||||
"SESSION_TYPE_GOODLIFE",
|
||||
"SESSION_TYPE_EQ2_GUILDS",
|
||||
"SESSION_TYPE_SWG_JP_BETA",
|
||||
"SESSION_TYPE_MARVEL",
|
||||
"SESSION_TYPE_EQ2_JAPAN",
|
||||
"SESSION_TYPE_EQ2_TAIWAN",
|
||||
"SESSION_TYPE_EQ2_CHINA",
|
||||
"SESSION_TYPE_EQ2_KOREA",
|
||||
"SESSION_TYPE_VGD",
|
||||
"SESSION_TYPE_PIRATE",
|
||||
"SESSION_TYPE_STAR_CHAMBER",
|
||||
"SESSION_TYPE_STARGATE",
|
||||
"SESSION_TYPE_DCU_ONLINE",
|
||||
"SESSION_TYPE_NORRATH_CSG",
|
||||
};
|
||||
|
||||
static const char * GamecodeString[GAMECODE_END] =
|
||||
{
|
||||
"GAMECODE_NULL",
|
||||
"GAMECODE_STATION_PASS",
|
||||
"GAMECODE_EVERQUEST",
|
||||
"GAMECODE_EVERQUEST_2",
|
||||
"GAMECODE_STARWARS",
|
||||
"GAMECODE_PLANETSIDE",
|
||||
"GAMECODE_EVERQUEST_ONLINE_ADVENTURES_BETA",
|
||||
"GAMECODE_EVERQUEST_ONLINE_ADVENTURES",
|
||||
"GAMECODE_EVERQUEST_INSTANT_MESSENGER",
|
||||
"GAMECODE_EVERQUEST_MACINTOSH",
|
||||
"GAMECODE_MATRIX_ONLINE",
|
||||
"GAMECODE_HARRY_POTTER",
|
||||
"GAMECODE_NEO_PETS",
|
||||
"GAMECODE_GOODLIFE",
|
||||
"GAMECODE_SWG_JP_BETA",
|
||||
"GAMECODE_MARVEL",
|
||||
"GAMECODE_EQ2_JAPAN",
|
||||
"GAMECODE_EQ2_TAIWAN",
|
||||
"GAMECODE_EQ2_CHINA",
|
||||
"GAMECODE_EQ2_KOREA",
|
||||
"GAMECODE_VGD",
|
||||
"GAMECODE_PIRATE",
|
||||
"GAMECODE_STAR_CHAMBER",
|
||||
"GAMECODE_STARGATE",
|
||||
"GAMECODE_DCU_ONLINE",
|
||||
"GAMECODE_NORRATH_CSG"
|
||||
};
|
||||
|
||||
static const char * SubscriptionStatusString[SUBSCRIPTION_STATUS_END] =
|
||||
{
|
||||
"SUBSCRIPTION_STATUS_NULL",
|
||||
"SUBSCRIPTION_STATUS_NO_ACCOUNT",
|
||||
"SUBSCRIPTION_STATUS_ACTIVE",
|
||||
"SUBSCRIPTION_STATUS_PENDING",
|
||||
"SUBSCRIPTION_STATUS_CANCEL",
|
||||
"SUBSCRIPTION_STATUS_TRIAL_ACTIVE",
|
||||
"SUBSCRIPTION_STATUS_TRIAL_EXPIRED",
|
||||
"SUBSCRIPTION_STATUS_SUSPENDED",
|
||||
"SUBSCRIPTION_STATUS_BANNED",
|
||||
"SUBSCRIPTION_STATUS_RENTAL_ACTIVE",
|
||||
"SUBSCRIPTION_STATUS_RENTAL_CLOSED"
|
||||
"SUBSCRIPTION_STATUS_ACTIVE_COMBO",
|
||||
"SUBSCRIPTION_STATUS_BANNED_CHARGEBACK",
|
||||
};
|
||||
|
||||
const std::pair<std::string, apiGamecode> _gamecodeID[GAMECODE_END] =
|
||||
{
|
||||
text_gamecode(std::string("SP"), GAMECODE_STATION_PASS),
|
||||
text_gamecode(std::string("EQ"), GAMECODE_EVERQUEST),
|
||||
text_gamecode(std::string("EQ2"), GAMECODE_EVERQUEST_2),
|
||||
text_gamecode(std::string("SWG"), GAMECODE_STARWARS),
|
||||
text_gamecode(std::string("PS"), GAMECODE_PLANETSIDE),
|
||||
text_gamecode(std::string("EQOA-beta"), GAMECODE_EVERQUEST_ONLINE_ADVENTURES_BETA),
|
||||
text_gamecode(std::string("EQOA"), GAMECODE_EVERQUEST_ONLINE_ADVENTURES),
|
||||
text_gamecode(std::string("EQIM"), GAMECODE_EVERQUEST_INSTANT_MESSENGER),
|
||||
text_gamecode(std::string("EQM"), GAMECODE_EVERQUEST_MACINTOSH),
|
||||
text_gamecode(std::string("MXO"), GAMECODE_MATRIX_ONLINE),
|
||||
text_gamecode(std::string("HPO"), GAMECODE_HARRY_POTTER),
|
||||
text_gamecode(std::string("NP"), GAMECODE_NEO_PETS),
|
||||
text_gamecode(std::string("GL"), GAMECODE_GOODLIFE),
|
||||
text_gamecode(std::string("SWG-JP"), GAMECODE_SWG_JP_BETA),
|
||||
text_gamecode(std::string("MRVL"), GAMECODE_MARVEL),
|
||||
text_gamecode(std::string("EQ2-JP"), GAMECODE_EQ2_JAPAN),
|
||||
text_gamecode(std::string("EQ2-TW"), GAMECODE_EQ2_TAIWAN),
|
||||
text_gamecode(std::string("EQ2-CN"), GAMECODE_EQ2_CHINA),
|
||||
text_gamecode(std::string("EQ2-KR"), GAMECODE_EQ2_KOREA),
|
||||
text_gamecode(std::string("VGD"), GAMECODE_VGD),
|
||||
text_gamecode(std::string("POCSG"), GAMECODE_PIRATE),
|
||||
text_gamecode(std::string("StarChamber"), GAMECODE_STAR_CHAMBER),
|
||||
text_gamecode(std::string("Stargate"), GAMECODE_STARGATE),
|
||||
text_gamecode(std::string("DCO"), GAMECODE_DCU_ONLINE),
|
||||
text_gamecode(std::string("NCSG"), GAMECODE_NORRATH_CSG)
|
||||
};
|
||||
static std::map<std::string,apiGamecode> GamecodeID((const std::map<std::string,apiGamecode>::value_type *)&_gamecodeID[0],(const std::map<std::string,apiGamecode>::value_type *)&_gamecodeID[GAMECODE_END]);
|
||||
|
||||
const gamecode_text _gamecodeName[GAMECODE_END] =
|
||||
{
|
||||
gamecode_text(GAMECODE_NULL, ""),
|
||||
gamecode_text(GAMECODE_STATION_PASS, "SP"),
|
||||
gamecode_text(GAMECODE_EVERQUEST, "EQ"),
|
||||
gamecode_text(GAMECODE_EVERQUEST_2, "EQ2"),
|
||||
gamecode_text(GAMECODE_STARWARS, "SWG"),
|
||||
gamecode_text(GAMECODE_PLANETSIDE, "PS"),
|
||||
gamecode_text(GAMECODE_EVERQUEST_ONLINE_ADVENTURES_BETA, "EQOA-beta"),
|
||||
gamecode_text(GAMECODE_EVERQUEST_ONLINE_ADVENTURES, "EQOA"),
|
||||
gamecode_text(GAMECODE_EVERQUEST_INSTANT_MESSENGER, "EQIM"),
|
||||
gamecode_text(GAMECODE_EVERQUEST_MACINTOSH, "EQM"),
|
||||
gamecode_text(GAMECODE_MATRIX_ONLINE, "MXO"),
|
||||
gamecode_text(GAMECODE_HARRY_POTTER, "HPO"),
|
||||
gamecode_text(GAMECODE_NEO_PETS, "NP"),
|
||||
gamecode_text(GAMECODE_GOODLIFE, "GL"),
|
||||
gamecode_text(GAMECODE_SWG_JP_BETA, "SWG-JP"),
|
||||
gamecode_text(GAMECODE_MARVEL, "MRVL"),
|
||||
gamecode_text(GAMECODE_EQ2_JAPAN, "EQ2-JP"),
|
||||
gamecode_text(GAMECODE_EQ2_TAIWAN, "EQ2-TW"),
|
||||
gamecode_text(GAMECODE_EQ2_CHINA, "EQ2-CN"),
|
||||
gamecode_text(GAMECODE_EQ2_KOREA, "EQ2-KR"),
|
||||
gamecode_text(GAMECODE_VGD, "VGD"),
|
||||
gamecode_text(GAMECODE_PIRATE, "POCSG"),
|
||||
gamecode_text(GAMECODE_STAR_CHAMBER, "StarChamber"),
|
||||
gamecode_text(GAMECODE_STARGATE, "Stargate"),
|
||||
gamecode_text(GAMECODE_DCU_ONLINE, "DCO"),
|
||||
gamecode_text(GAMECODE_NORRATH_CSG, "NCSG")
|
||||
};
|
||||
static std::map<apiGamecode,const char *> GamecodeName((const std::map<apiGamecode,const char *>::value_type *)&_gamecodeName[0],(const std::map<apiGamecode,const char *>::value_type *)&_gamecodeName[GAMECODE_END]);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,764 @@
|
||||
#pragma warning (disable : 4786)
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include "CommonClient.h"
|
||||
#include "CommonMessages.h"
|
||||
#include "Base/Platform.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace Base;
|
||||
|
||||
|
||||
const int CONNECTION_ATTEMPT_TIMEOUT = 4; // connection timeout in seconds
|
||||
const int CONNECTION_DELAY = 5; // pause between connection attempts in seconds
|
||||
const int KEEP_ALIVE_DELAY = 15; // connection keep-alive timeout in seconds
|
||||
const int PORT_ALIVE_DELAY = 0; // port-alive delay in milliseconds
|
||||
const int NO_DATA_TIMEOUT = 0; // no-data timeout in seconds
|
||||
const int UNACKNOWLEDGED_DATA_TIMEOUT = 15; // unacknowledged-data timeout in seconds
|
||||
|
||||
struct RandFunction : std::unary_function<int,int>
|
||||
{
|
||||
int operator()(int n) { return rand()%n; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CConnectionHandler::CConnectionHandler(CConnectionManager & parent, UdpConnection * connection, unsigned index) :
|
||||
mParent(parent),
|
||||
mConnection(connection),
|
||||
mIndex(index)
|
||||
{
|
||||
if (mConnection)
|
||||
mConnection->SetHandler(this);
|
||||
}
|
||||
|
||||
CConnectionHandler::~CConnectionHandler()
|
||||
{
|
||||
if (mConnection)
|
||||
{
|
||||
mConnection->SetHandler(NULL);
|
||||
mConnection->Disconnect();
|
||||
mConnection->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void CConnectionHandler::Send(const Base::ByteStream & stream)
|
||||
{
|
||||
if (mConnection && mConnection->GetStatus() == UdpConnection::cStatusConnected)
|
||||
{
|
||||
mConnection->Send(cUdpChannelReliable1, stream.getBuffer(), stream.getSize());
|
||||
}
|
||||
}
|
||||
|
||||
void CConnectionHandler::OnConnectComplete(UdpConnection *)
|
||||
{
|
||||
if (mConnection->GetStatus() == UdpConnection::cStatusConnected)
|
||||
{
|
||||
Message::Connect message;
|
||||
message.SetVersion(mParent.GetCore().GetVersion());
|
||||
message.SetDescription(mParent.GetCore().GetDescription());
|
||||
Base::ByteStream stream;
|
||||
message.pack(stream);
|
||||
Send(stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnTerminated(mConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void CConnectionHandler::OnTerminated(UdpConnection *)
|
||||
{
|
||||
mParent.OnConnectionClosed(mIndex);
|
||||
|
||||
if (mConnection)
|
||||
{
|
||||
mConnection->SetHandler(NULL);
|
||||
mConnection->Release();
|
||||
mConnection = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CConnectionHandler::OnRoutePacket(UdpConnection *, const uchar *data, int dataLen)
|
||||
{
|
||||
unsigned short itemCount;
|
||||
unsigned short messageId = 0;
|
||||
unsigned trackingNumber = 0;
|
||||
|
||||
if (dataLen < 8)
|
||||
return;
|
||||
|
||||
Base::ByteStream stream(data,dataLen);
|
||||
Base::ByteStream::ReadIterator streamIterator = stream.begin();
|
||||
|
||||
Base::get(streamIterator, itemCount);
|
||||
Base::get(streamIterator, messageId);
|
||||
Base::get(streamIterator, trackingNumber);
|
||||
|
||||
if (messageId == Message::MESSAGE_CONNECT_REPLY)
|
||||
{
|
||||
streamIterator = stream.begin();
|
||||
Message::ConnectReply message(streamIterator);
|
||||
if (message.GetResult() == RESULT_SUCCESS)
|
||||
mParent.OnConnectionOpened(mIndex);
|
||||
else
|
||||
OnTerminated(mConnection);
|
||||
}
|
||||
|
||||
mParent.GetCore().QueueTrackedCallback(stream);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CConnectionManager::CConnectionManager(apiCore & parent, std::vector<std::string> & serverList, unsigned maxConnections) :
|
||||
mParent(parent),
|
||||
mServerArray(),
|
||||
mServerCount(0),
|
||||
mMaxConnections(maxConnections),
|
||||
mParams(),
|
||||
mUdpManager(0),
|
||||
mConnectionArray(),
|
||||
mConnectedSet(),
|
||||
mPendingSet(),
|
||||
mDisconnectedQueue(),
|
||||
mSendQueue(),
|
||||
mConnectionCount(0),
|
||||
mActiveCount(0),
|
||||
mConnectionDelay(0)
|
||||
{
|
||||
for (unsigned serverIndex = 0; serverIndex < serverList.size(); serverIndex++)
|
||||
{
|
||||
std::string address = serverList[serverIndex];
|
||||
unsigned portIndex = address.find(':');
|
||||
if (portIndex != string::npos)
|
||||
{
|
||||
std::string host = address.substr(0, portIndex);
|
||||
std::string port = address.substr(portIndex+1);
|
||||
|
||||
if (!host.length() || !port.length())
|
||||
continue;
|
||||
|
||||
portIndex = port.find('-');
|
||||
if (portIndex == string::npos)
|
||||
{
|
||||
if (atoi(port.c_str()) == 0)
|
||||
continue;
|
||||
mServerArray.push_back(address);
|
||||
mServerCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int first = atoi(port.substr(0,portIndex).c_str());
|
||||
int last = atoi(port.substr(portIndex+1).c_str());
|
||||
|
||||
if (!first || !last)
|
||||
continue;
|
||||
|
||||
char buffer[64];
|
||||
for (int rangeIndex=first; rangeIndex<=last; rangeIndex++)
|
||||
{
|
||||
sprintf(buffer,"%s:%d",host.c_str(),rangeIndex);
|
||||
mServerArray.push_back(std::string(buffer));
|
||||
mServerCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mMaxConnections > mServerCount)
|
||||
mMaxConnections = mServerCount;
|
||||
if (mMaxConnections == 0)
|
||||
mMaxConnections = 1;
|
||||
|
||||
//mParams.handler = this;
|
||||
mParams.keepAliveDelay = parent.GetKeepAliveDelay() * 1000;
|
||||
mParams.portAliveDelay = parent.GetPortAliveDelay();
|
||||
mParams.incomingBufferSize = 256 * 1024;
|
||||
mParams.outgoingBufferSize = 256 * 1024;
|
||||
mParams.maxConnections = mMaxConnections;
|
||||
mParams.hashTableSize = mMaxConnections*10;
|
||||
mParams.port = 0;
|
||||
|
||||
mUdpManager = new UdpManager(&mParams);
|
||||
|
||||
srand((int)Base::getTimer()+(int)time(0));
|
||||
RandFunction myRand;
|
||||
random_shuffle(mServerArray.begin(), mServerArray.end(), myRand);
|
||||
mConnectionArray.resize(mServerCount,0);
|
||||
for (unsigned i=0; i<mServerCount; i++)
|
||||
{
|
||||
mDisconnectedQueue.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
CConnectionManager::~CConnectionManager()
|
||||
{
|
||||
for (unsigned i=0; i<mConnectionArray.size(); i++)
|
||||
{
|
||||
if (mConnectionArray[i] != 0)
|
||||
{
|
||||
delete mConnectionArray[i];
|
||||
mConnectionArray[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
mUdpManager->Release();
|
||||
}
|
||||
|
||||
void CConnectionManager::Process()
|
||||
{
|
||||
mUdpManager->GiveTime();
|
||||
|
||||
////////////////////////////////////////
|
||||
// try a new connection if:
|
||||
// 1. active connection count (pending + connected) < max connections
|
||||
// 2. (and) the set of disconnect servers is not empty
|
||||
// 3. (and) connection delay has expired or there are no active connections
|
||||
if (mActiveCount < mMaxConnections && !mDisconnectedQueue.empty())
|
||||
{
|
||||
if (!mConnectionCount || mConnectionDelay < (unsigned)time(0))
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i=0; i<mServerCount; i++)
|
||||
{
|
||||
CConnectionHandler * handler = mConnectionArray[i];
|
||||
if (!handler)
|
||||
continue;
|
||||
|
||||
if (!handler->mConnection)
|
||||
{
|
||||
std::set<unsigned>::iterator iterator;
|
||||
|
||||
// remove from connected set
|
||||
if ((iterator = mConnectedSet.find(i)) != mConnectedSet.end())
|
||||
{
|
||||
mConnectedSet.erase(iterator);
|
||||
mActiveCount--;
|
||||
mConnectionCount--;
|
||||
}
|
||||
|
||||
// remove from pending set
|
||||
if ((iterator = mPendingSet.find(i)) != mPendingSet.end())
|
||||
{
|
||||
mPendingSet.erase(iterator);
|
||||
mActiveCount--;
|
||||
}
|
||||
|
||||
// add to disconnected set
|
||||
mDisconnectedQueue.push_back(i);
|
||||
|
||||
delete handler;
|
||||
mConnectionArray[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
UdpConnection::ChannelStatus cs;
|
||||
handler->mConnection->GetChannelStatus(cUdpChannelReliable1,&cs);
|
||||
if (handler->mConnection->GetStatus() == UdpConnection::cStatusDisconnected || cs.oldestUnacknowledgedAge > mParent.GetUnacknowledgedDataTimeout()*1000) // 30 seconds, fairly liberal, odds are the connection is dead after 10 seconds
|
||||
{
|
||||
handler->OnTerminated(handler->mConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CConnectionManager::Connect()
|
||||
{
|
||||
unsigned index = mDisconnectedQueue.front();
|
||||
mDisconnectedQueue.pop_front();
|
||||
|
||||
std::string address;
|
||||
int port;
|
||||
|
||||
if (!ParseAddress(mServerArray[index],address,port))
|
||||
{
|
||||
mDisconnectedQueue.push_back(index);
|
||||
return;
|
||||
}
|
||||
|
||||
UdpConnection * connection = mUdpManager->EstablishConnection(address.c_str(), port, CONNECTION_ATTEMPT_TIMEOUT*1000);
|
||||
if (connection)
|
||||
{
|
||||
mConnectionArray[index] = new CConnectionHandler(*this, connection, index);
|
||||
|
||||
mPendingSet.insert(index);
|
||||
mActiveCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDisconnectedQueue.push_back(index);
|
||||
mParent.OnConnectionFailed(mServerArray[index],mConnectionCount);
|
||||
}
|
||||
}
|
||||
|
||||
void CConnectionManager::Send(const Base::ByteStream & stream)
|
||||
{
|
||||
if (CanSend())
|
||||
{
|
||||
unsigned index;
|
||||
CConnectionHandler * handler = 0;
|
||||
while (!handler && !mSendQueue.empty())
|
||||
{
|
||||
index = mSendQueue.front();
|
||||
mSendQueue.pop_front();
|
||||
|
||||
handler = mConnectionArray[index];
|
||||
}
|
||||
|
||||
if (handler)
|
||||
{
|
||||
mSendQueue.push_back(index);
|
||||
handler->Send(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CConnectionManager::CanSend()
|
||||
{
|
||||
return (mConnectionCount > 0);
|
||||
}
|
||||
|
||||
void CConnectionManager::SetConnectionDelay()
|
||||
{
|
||||
mConnectionDelay = (int)time(0) + CONNECTION_DELAY;
|
||||
}
|
||||
|
||||
void CConnectionManager::OnConnectionOpened(unsigned index)
|
||||
{
|
||||
mPendingSet.erase(index);
|
||||
mConnectedSet.insert(index);
|
||||
mSendQueue.push_back(index);
|
||||
mConnectionCount++;
|
||||
|
||||
mParent.OnConnectionOpened(mServerArray[index],mConnectionCount);
|
||||
}
|
||||
|
||||
void CConnectionManager::OnConnectionClosed(unsigned index)
|
||||
{
|
||||
if (mPendingSet.find(index) != mPendingSet.end())
|
||||
{
|
||||
mParent.OnConnectionFailed(mServerArray[index],mConnectionCount ? mConnectionCount-1 : mConnectionCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
mSendQueue.remove(index);
|
||||
mParent.OnConnectionClosed(mServerArray[index],mConnectionCount);
|
||||
}
|
||||
}
|
||||
|
||||
bool CConnectionManager::ParseAddress(const std::string & full, std::string & address, int & port)
|
||||
{
|
||||
unsigned index = full.find(':');
|
||||
if (full.length() == 0 || index == string::npos)
|
||||
return false;
|
||||
|
||||
address = full.substr(0,index);
|
||||
port = atoi(full.substr(index+1).c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
apiClient::apiClient() :
|
||||
mClientCore(0)
|
||||
{
|
||||
}
|
||||
|
||||
apiClient::~apiClient()
|
||||
{
|
||||
}
|
||||
|
||||
void apiClient::Process()
|
||||
{
|
||||
if (mClientCore)
|
||||
static_cast<apiCore *>(mClientCore)->Process();
|
||||
}
|
||||
|
||||
void apiClient::OnConnectionOpened(const char *, unsigned)
|
||||
{
|
||||
}
|
||||
|
||||
void apiClient::OnConnectionClosed(const char *, unsigned)
|
||||
{
|
||||
}
|
||||
|
||||
void apiClient::OnConnectionFailed(const char *, unsigned)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
apiCore::apiCore(apiClient * parent, const char * version, const char * serverList, const char * description, unsigned maxConnections) :
|
||||
mParent(parent),
|
||||
mVersion(version),
|
||||
mDescription(description),
|
||||
mServerArray(),
|
||||
mMaxConnections(maxConnections),
|
||||
mConnectionManager(0),
|
||||
mTrackingIndex(1),
|
||||
mTrackedMessages(),
|
||||
mRequestMap(),
|
||||
mCallbackQueue(),
|
||||
mTrackedCallbackQueue(),
|
||||
mTimeoutQueue(),
|
||||
mRequestQueueSize(0),
|
||||
mExpirationTimeout(0),
|
||||
mInCallback(false)
|
||||
{
|
||||
std::string list = serverList;
|
||||
unsigned offset=0;
|
||||
unsigned index=0;
|
||||
|
||||
while ((index = list.find(' ',offset)) != std::string::npos)
|
||||
{
|
||||
mServerArray.push_back(list.substr(offset, index-offset));
|
||||
offset = index + 1;
|
||||
}
|
||||
|
||||
mServerArray.push_back(list.substr(offset));
|
||||
|
||||
if (mDescription.length() > 64)
|
||||
mDescription = mDescription.substr(0,64);
|
||||
}
|
||||
|
||||
apiCore::apiCore(apiClient * parent, const char * version, const char ** serverList, unsigned serverCount, const char * description, unsigned maxConnections) :
|
||||
mParent(parent),
|
||||
mVersion(version),
|
||||
mDescription(description),
|
||||
mServerArray(),
|
||||
mMaxConnections(maxConnections),
|
||||
mConnectionManager(0),
|
||||
mTrackingIndex(1),
|
||||
mTrackedMessages(),
|
||||
mRequestMap(),
|
||||
mCallbackQueue(),
|
||||
mTrackedCallbackQueue(),
|
||||
mTimeoutQueue(),
|
||||
mRequestQueueSize(0),
|
||||
mExpirationTimeout(0),
|
||||
mInCallback(false)
|
||||
{
|
||||
for (unsigned i=0; i<serverCount; i++)
|
||||
{
|
||||
mServerArray.push_back(serverList[i]);
|
||||
}
|
||||
|
||||
if (mDescription.length() > 64)
|
||||
mDescription = mDescription.substr(0,64);
|
||||
}
|
||||
|
||||
apiCore::~apiCore()
|
||||
{
|
||||
delete mConnectionManager;
|
||||
}
|
||||
|
||||
int apiCore::GetKeepAliveDelay()
|
||||
{
|
||||
return KEEP_ALIVE_DELAY;
|
||||
}
|
||||
|
||||
int apiCore::GetPortAliveDelay()
|
||||
{
|
||||
return PORT_ALIVE_DELAY;
|
||||
}
|
||||
|
||||
int apiCore::GetNoDataTimeout()
|
||||
{
|
||||
return NO_DATA_TIMEOUT;
|
||||
}
|
||||
|
||||
int apiCore::GetUnacknowledgedDataTimeout()
|
||||
{
|
||||
return UNACKNOWLEDGED_DATA_TIMEOUT;
|
||||
}
|
||||
|
||||
void apiCore::NotifyConnectionOpened(const char *address, unsigned connectionCount)
|
||||
{
|
||||
}
|
||||
|
||||
void apiCore::NotifyConnectionClosed(const char *address, unsigned connectionCount)
|
||||
{
|
||||
}
|
||||
|
||||
void apiCore::NotifyConnectionFailed(const char *address, unsigned connectionCount)
|
||||
{
|
||||
}
|
||||
|
||||
void apiCore::OnConnectionOpened(const std::string & address, unsigned connectionCount)
|
||||
{
|
||||
NotifyConnectionOpened(address.c_str(),connectionCount);
|
||||
mParent->OnConnectionOpened(address.c_str(),connectionCount);
|
||||
}
|
||||
|
||||
void apiCore::OnConnectionClosed(const std::string & address, unsigned connectionCount)
|
||||
{
|
||||
NotifyConnectionClosed(address.c_str(),connectionCount);
|
||||
mParent->OnConnectionClosed(address.c_str(),connectionCount);
|
||||
}
|
||||
|
||||
void apiCore::OnConnectionFailed(const std::string & address, unsigned connectionCount)
|
||||
{
|
||||
NotifyConnectionFailed(address.c_str(),connectionCount);
|
||||
mParent->OnConnectionFailed(address.c_str(),connectionCount);
|
||||
}
|
||||
|
||||
bool apiCore::IsTrackedMessage(const unsigned short messageId)
|
||||
{
|
||||
return mTrackedMessages.find(messageId) != mTrackedMessages.end();
|
||||
}
|
||||
|
||||
void apiCore::RegisterTrackedMessage(const unsigned short messageId)
|
||||
{
|
||||
mTrackedMessages.insert(messageId);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// This function submits a request that expects no reply
|
||||
void apiCore::SubmitRequest(Message::Basic & input)
|
||||
{
|
||||
Base::ByteStream stream;
|
||||
input.pack(stream);
|
||||
|
||||
if (mConnectionManager && mConnectionManager->CanSend())
|
||||
mConnectionManager->Send(stream);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// This function submits a request that expects a reply
|
||||
apiTrackingNumber apiCore::SubmitRequest(Message::Tracked & input, Message::TrackedReply & output, const void * userData, unsigned timeout)
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// Set tracking number
|
||||
apiTrackingNumber trackingNumber = mTrackingIndex++;
|
||||
|
||||
input.SetTrackingNumber(trackingNumber);
|
||||
output.SetTrackingNumber(trackingNumber);
|
||||
|
||||
mRequestMap.insert(pair<apiTrackingNumber,apiTrackedRequest>(trackingNumber, apiTrackedRequest(trackingNumber, output.GetMessageID(), userData, timeout)));
|
||||
|
||||
////////////////////////////////////////
|
||||
// Verify that the request needs to be sent.
|
||||
// If the default result is not RESULT_TIMEOUT,
|
||||
// trigger callback using the output
|
||||
if (!mConnectionManager || !mConnectionManager->CanSend() || output.GetResult() != RESULT_TIMEOUT)
|
||||
{
|
||||
QueueTrackedCallback(output);
|
||||
}
|
||||
else
|
||||
{
|
||||
Base::ByteStream stream;
|
||||
input.pack(stream);
|
||||
|
||||
mConnectionManager->Send(stream);
|
||||
}
|
||||
|
||||
return input.GetTrackingNumber();
|
||||
}
|
||||
|
||||
void apiCore::QueueCallback(const Base::ByteStream & stream)
|
||||
{
|
||||
mCallbackQueue.push_back(stream);
|
||||
}
|
||||
|
||||
void apiCore::QueueCallback(const Message::Basic & message)
|
||||
{
|
||||
Base::ByteStream stream;
|
||||
message.pack(stream);
|
||||
|
||||
mCallbackQueue.push_back(stream);
|
||||
}
|
||||
|
||||
void apiCore::QueueTrackedCallback(const Base::ByteStream & stream)
|
||||
{
|
||||
mTrackedCallbackQueue.push_back(stream);
|
||||
}
|
||||
|
||||
void apiCore::QueueTrackedCallback(const Message::Basic & message)
|
||||
{
|
||||
Base::ByteStream stream;
|
||||
message.pack(stream);
|
||||
|
||||
mTrackedCallbackQueue.push_back(stream);
|
||||
}
|
||||
|
||||
std::string & apiCore::GetVersion()
|
||||
{
|
||||
return mVersion;
|
||||
}
|
||||
|
||||
std::string & apiCore::GetDescription()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
void apiCore::Process()
|
||||
{
|
||||
if (mInCallback)
|
||||
return;
|
||||
mInCallback = true;
|
||||
|
||||
unsigned currentTime = (unsigned)time(0);
|
||||
|
||||
////////////////////////////////////////
|
||||
// Process connection manager
|
||||
if (mConnectionManager)
|
||||
mConnectionManager->Process();
|
||||
else
|
||||
{
|
||||
mConnectionManager = new CConnectionManager(*this, mServerArray, mMaxConnections);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Check timeout in Request Map
|
||||
if (mExpirationTimeout <= currentTime)
|
||||
{
|
||||
map<unsigned,apiTrackedRequest>::iterator mapIterator = mRequestMap.begin();
|
||||
while (mapIterator != mRequestMap.end())
|
||||
{
|
||||
apiTrackedRequest & request = (*mapIterator).second;
|
||||
mapIterator++;
|
||||
|
||||
if (request.Expired())
|
||||
{
|
||||
mTimeoutQueue.push_back(request.GetTrackingNumber());
|
||||
}
|
||||
}
|
||||
mExpirationTimeout = currentTime + 3;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Process Timeout Queue
|
||||
while (!mTimeoutQueue.empty())
|
||||
{
|
||||
apiTrackingNumber trackingNumber = mTimeoutQueue.front();
|
||||
|
||||
map<unsigned,apiTrackedRequest>::iterator mapIterator;
|
||||
mapIterator = mRequestMap.find(trackingNumber);
|
||||
if (mapIterator != mRequestMap.end())
|
||||
{
|
||||
apiTrackedRequest & request = mapIterator->second;
|
||||
Timeout(request.GetMessageId(), trackingNumber, (void *)request.GetUserData());
|
||||
mRequestMap.erase(mapIterator);
|
||||
}
|
||||
mTimeoutQueue.pop_front();
|
||||
}
|
||||
|
||||
/*
|
||||
////////////////////////////////////////
|
||||
// Process Callback Queue
|
||||
while (!mCallbackQueue.empty())
|
||||
{
|
||||
Base::ByteStream & stream = mCallbackQueue.front();
|
||||
Callback(stream,0);
|
||||
mCallbackQueue.pop_front();
|
||||
}
|
||||
*/
|
||||
|
||||
////////////////////////////////////////
|
||||
// Process Tracked Callback Queue
|
||||
while (!mTrackedCallbackQueue.empty())
|
||||
{
|
||||
unsigned short itemCount;
|
||||
unsigned short messageId = 0;
|
||||
|
||||
Base::ByteStream & stream = mTrackedCallbackQueue.front();
|
||||
Base::ByteStream::ReadIterator streamIterator = stream.begin();
|
||||
Base::get(streamIterator, itemCount);
|
||||
Base::get(streamIterator, messageId);
|
||||
|
||||
if (!IsTrackedMessage(messageId))
|
||||
{
|
||||
Callback(stream,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
streamIterator = stream.begin();
|
||||
Message::Tracked message(streamIterator);
|
||||
|
||||
map<apiTrackingNumber,apiTrackedRequest>::iterator mapIterator = mRequestMap.find(message.GetTrackingNumber());
|
||||
if (mapIterator != mRequestMap.end())
|
||||
{
|
||||
apiTrackedRequest & request = (*mapIterator).second;
|
||||
Callback(stream,(void *)request.GetUserData());
|
||||
mRequestMap.erase(mapIterator);
|
||||
}
|
||||
}
|
||||
mTrackedCallbackQueue.pop_front();
|
||||
}
|
||||
|
||||
mInCallback = false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
const int DEFAULT_TIMEOUT = 20;
|
||||
|
||||
|
||||
apiTrackedRequest::apiTrackedRequest(apiTrackingNumber trackingNumber, const unsigned short messageId, const void * userData, unsigned duration) :
|
||||
mTrackingNumber(trackingNumber),
|
||||
mMessageId(messageId),
|
||||
mUserData(userData),
|
||||
mTimeout(0),
|
||||
mDuration(duration)
|
||||
{
|
||||
if (mDuration == 0)
|
||||
mDuration = DEFAULT_TIMEOUT;
|
||||
|
||||
mTimeout = (int)time(0) + mDuration;
|
||||
}
|
||||
|
||||
apiTrackedRequest::apiTrackedRequest(const apiTrackedRequest & copy) :
|
||||
mTrackingNumber(copy.mTrackingNumber),
|
||||
mMessageId(copy.mMessageId),
|
||||
mUserData(copy.mUserData),
|
||||
mTimeout(copy.mTimeout),
|
||||
mDuration(copy.mDuration)
|
||||
{
|
||||
}
|
||||
|
||||
apiTrackedRequest::~apiTrackedRequest()
|
||||
{
|
||||
}
|
||||
|
||||
apiTrackingNumber apiTrackedRequest::GetTrackingNumber()
|
||||
{
|
||||
return mTrackingNumber;
|
||||
}
|
||||
|
||||
unsigned short apiTrackedRequest::GetMessageId()
|
||||
{
|
||||
return mMessageId;
|
||||
}
|
||||
|
||||
const void * apiTrackedRequest::GetUserData()
|
||||
{
|
||||
return mUserData;
|
||||
}
|
||||
|
||||
bool apiTrackedRequest::Expired()
|
||||
{
|
||||
return mTimeout < (unsigned)time(0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
#ifndef COMMON_API__COMMON_CLIENT_H
|
||||
#define COMMON_API__COMMON_CLIENT_H
|
||||
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include "Base/Archive.h"
|
||||
#include "UdpLibrary.hpp"
|
||||
#include "CommonAPI.h"
|
||||
#include "CommonMessages.h"
|
||||
|
||||
#ifdef COMMON__UDPLIBRARY_HPP
|
||||
using CommonAPI::UdpManager;
|
||||
using CommonAPI::UdpConnectionHandler;
|
||||
using CommonAPI::UdpConnection;
|
||||
using CommonAPI::uchar;
|
||||
using CommonAPI::cUdpChannelReliable1;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class apiTrackedRequest;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CConnectionManager;
|
||||
class CConnectionHandler : public UdpConnectionHandler
|
||||
{
|
||||
public:
|
||||
CConnectionHandler(CConnectionManager & parent, UdpConnection * connection, unsigned index);
|
||||
virtual ~CConnectionHandler();
|
||||
|
||||
void Send(const Base::ByteStream & stream);
|
||||
|
||||
virtual void OnRoutePacket(UdpConnection *con, const uchar *data, int dataLen);
|
||||
virtual void OnConnectComplete(UdpConnection *con);
|
||||
virtual void OnTerminated(UdpConnection *con);
|
||||
|
||||
public:
|
||||
CConnectionManager & mParent;
|
||||
UdpConnection * mConnection;
|
||||
unsigned mIndex;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class CConnectionManager
|
||||
{
|
||||
public:
|
||||
CConnectionManager(apiCore & parent, std::vector<std::string> & serverList, unsigned maxConnections);
|
||||
virtual ~CConnectionManager();
|
||||
|
||||
void Process();
|
||||
void Connect();
|
||||
void Send(const Base::ByteStream & stream);
|
||||
bool CanSend();
|
||||
void SetConnectionDelay();
|
||||
|
||||
apiCore & GetCore() { return mParent; }
|
||||
|
||||
void OnConnectionOpened(unsigned index);
|
||||
void OnConnectionClosed(unsigned index);
|
||||
|
||||
bool ParseAddress(const std::string & full, std::string & address, int & port);
|
||||
|
||||
protected:
|
||||
apiCore & mParent;
|
||||
std::vector<std::string> mServerArray;
|
||||
unsigned mServerCount;
|
||||
unsigned mMaxConnections;
|
||||
|
||||
UdpManager::Params mParams;
|
||||
UdpManager * mUdpManager;
|
||||
|
||||
std::vector<CConnectionHandler *> mConnectionArray;
|
||||
std::set<unsigned> mConnectedSet;
|
||||
std::set<unsigned> mPendingSet;
|
||||
std::list<unsigned> mDisconnectedQueue;
|
||||
std::list<unsigned> mSendQueue;
|
||||
unsigned mConnectionCount;
|
||||
unsigned mActiveCount;
|
||||
|
||||
unsigned mConnectionDelay;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class apiTrackedRequest
|
||||
{
|
||||
public:
|
||||
apiTrackedRequest(apiTrackingNumber trackingNumber, const unsigned short messageId, const void * userData, unsigned duration = 20);
|
||||
apiTrackedRequest(const apiTrackedRequest & copy);
|
||||
~apiTrackedRequest();
|
||||
|
||||
apiTrackingNumber GetTrackingNumber();
|
||||
unsigned short GetMessageId();
|
||||
const void * GetUserData();
|
||||
|
||||
bool Expired();
|
||||
|
||||
private:
|
||||
apiTrackingNumber mTrackingNumber;
|
||||
unsigned short mMessageId;
|
||||
const void * mUserData;
|
||||
unsigned mTimeout;
|
||||
unsigned mDuration;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class apiCore
|
||||
{
|
||||
friend class CConnectionHandler;
|
||||
friend class CConnectionManager;
|
||||
|
||||
public:
|
||||
apiCore(apiClient * parent, const char * version, const char * serverList, const char * description, unsigned maxConnections);
|
||||
apiCore(apiClient * parent, const char * version, const char ** serverList, unsigned serverCount, const char * description, unsigned maxConnections);
|
||||
virtual ~apiCore();
|
||||
|
||||
apiClient * GetParent() { return mParent; }
|
||||
|
||||
void Process();
|
||||
|
||||
void RegisterTrackedMessage(const unsigned short messageId);
|
||||
bool IsTrackedMessage(const unsigned short messageId);
|
||||
|
||||
virtual int GetKeepAliveDelay();
|
||||
virtual int GetPortAliveDelay();
|
||||
virtual int GetNoDataTimeout();
|
||||
virtual int GetUnacknowledgedDataTimeout();
|
||||
virtual void NotifyConnectionOpened(const char *address, unsigned connectionCount);
|
||||
virtual void NotifyConnectionClosed(const char *address, unsigned connectionCount);
|
||||
virtual void NotifyConnectionFailed(const char *address, unsigned connectionCount);
|
||||
|
||||
protected:
|
||||
void SubmitRequest(Message::Basic & input);
|
||||
apiTrackingNumber SubmitRequest(Message::Tracked & input, Message::TrackedReply & output, const void * userData, unsigned timeout=0);
|
||||
|
||||
virtual bool Callback(Base::ByteStream & stream, void * userData) = 0;
|
||||
virtual void Timeout(unsigned short messageId, apiTrackingNumber trackingNumber, void * userData) = 0;
|
||||
|
||||
private:
|
||||
void OnConnectionOpened(const std::string & address, unsigned connectionCount);
|
||||
void OnConnectionClosed(const std::string & address, unsigned connectionCount);
|
||||
void OnConnectionFailed(const std::string & address, unsigned connectionCount);
|
||||
|
||||
void QueueRequest(Message::Basic & input);
|
||||
void QueueTrackedRequest(Message::Tracked & input, apiTrackedRequest & request);
|
||||
|
||||
void QueueCallback(const Base::ByteStream & stream);
|
||||
void QueueCallback(const Message::Basic & input);
|
||||
void QueueTrackedCallback(const Base::ByteStream & stream);
|
||||
void QueueTrackedCallback(const Message::Basic & input);
|
||||
|
||||
std::string & GetVersion();
|
||||
std::string & GetDescription();
|
||||
|
||||
void Update();
|
||||
|
||||
private:
|
||||
apiClient * mParent;
|
||||
std::string mVersion;
|
||||
std::string mDescription;
|
||||
std::vector<std::string> mServerArray;
|
||||
unsigned mMaxConnections;
|
||||
|
||||
CConnectionManager * mConnectionManager;
|
||||
|
||||
apiTrackingNumber mTrackingIndex;
|
||||
|
||||
std::set<unsigned short> mTrackedMessages;
|
||||
std::map<unsigned,apiTrackedRequest> mRequestMap;
|
||||
|
||||
std::list<Base::ByteStream> mCallbackQueue;
|
||||
std::list<Base::ByteStream> mTrackedCallbackQueue;
|
||||
std::list<apiTrackingNumber> mTimeoutQueue;
|
||||
|
||||
unsigned mRequestQueueSize;
|
||||
unsigned mExpirationTimeout;
|
||||
bool mInCallback;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
#include "CommonMessages.h"
|
||||
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
void get(ByteStream::ReadIterator & source, apiAccount & target)
|
||||
{
|
||||
char name[apiAccountNameWidth];
|
||||
apiAccountId id;
|
||||
apiAccountStatus status;
|
||||
|
||||
get(source, (unsigned char *)name, apiAccountNameWidth);
|
||||
get(source, id);
|
||||
get(source, status);
|
||||
|
||||
target.SetName(name);
|
||||
target.SetId(id);
|
||||
target.SetStatus(status);
|
||||
}
|
||||
|
||||
void get(ByteStream::ReadIterator & source, apiSubscription & target)
|
||||
{
|
||||
apiGamecode gamecode;
|
||||
apiProviderId provider;
|
||||
apiSubscriptionStatus status;
|
||||
apiProductFeatures subscriptionFeatures;
|
||||
apiProductFeatures gameFeatures;
|
||||
unsigned durationSeconds;
|
||||
unsigned parentalLimitSeconds;
|
||||
|
||||
get(source, gamecode);
|
||||
get(source, provider);
|
||||
get(source, status);
|
||||
get(source, subscriptionFeatures);
|
||||
get(source, gameFeatures);
|
||||
get(source, durationSeconds);
|
||||
get(source, parentalLimitSeconds);
|
||||
|
||||
target.SetGamecode(gamecode);
|
||||
target.SetProviderId(provider);
|
||||
target.SetStatus(status);
|
||||
target.SetSubscriptionFeatures(subscriptionFeatures);
|
||||
target.SetGameFeatures(gameFeatures);
|
||||
target.SetDurationSeconds(durationSeconds);
|
||||
target.SetParentalLimitSeconds(parentalLimitSeconds);
|
||||
|
||||
}
|
||||
|
||||
void get(ByteStream::ReadIterator & source, apiSession & target)
|
||||
{
|
||||
apiSessionType type;
|
||||
apiProviderId provider;
|
||||
char id[apiSessionIdWidth];
|
||||
apiIP clientIP;
|
||||
unsigned durationSeconds;
|
||||
unsigned parentalLimitSeconds;
|
||||
unsigned char timeoutMinutes;
|
||||
bool isSecure;
|
||||
|
||||
get(source, type);
|
||||
get(source, provider);
|
||||
get(source, (unsigned char *)id, apiSessionIdWidth);
|
||||
get(source, clientIP);
|
||||
get(source, durationSeconds);
|
||||
get(source, parentalLimitSeconds);
|
||||
get(source, timeoutMinutes);
|
||||
get(source, isSecure);
|
||||
|
||||
target.SetType(type);
|
||||
target.SetProviderId(provider);
|
||||
target.SetId(id);
|
||||
target.SetClientIP(clientIP);
|
||||
target.SetDurationSeconds(durationSeconds);
|
||||
target.SetParentalLimitSeconds(parentalLimitSeconds);
|
||||
target.SetTimeoutMinutes(timeoutMinutes);
|
||||
target.SetIsSecure(isSecure);
|
||||
}
|
||||
|
||||
void get(ByteStream::ReadIterator & source, apiAccount_v1 & target)
|
||||
{
|
||||
get(source, (unsigned char *)target.name, apiAccountNameWidth_v1);
|
||||
get(source, target.id);
|
||||
get(source, target.status);
|
||||
}
|
||||
|
||||
void get(ByteStream::ReadIterator & source, apiSubscription_v1 & target)
|
||||
{
|
||||
get(source, target.gamecode);
|
||||
get(source, target.status);
|
||||
get(source, target.subscriptionFeatures);
|
||||
get(source, target.gameFeatures);
|
||||
get(source, target.durationSeconds);
|
||||
get(source, target.parentalLimitSeconds);
|
||||
}
|
||||
|
||||
void get(ByteStream::ReadIterator & source, apiSession_v1 & target)
|
||||
{
|
||||
get(source, target.type);
|
||||
get(source, (unsigned char *)target.id, apiSessionIdWidth_v1);
|
||||
get(source, target.clientIP);
|
||||
get(source, target.durationSeconds);
|
||||
get(source, target.parentalLimitSeconds);
|
||||
get(source, target.timeoutMinutes);
|
||||
get(source, target.isSecure);
|
||||
}
|
||||
|
||||
void get(ByteStream::ReadIterator & source, SessionTypeDesc & target)
|
||||
{
|
||||
unsigned tmp = 0;
|
||||
get(source, target.type);
|
||||
get(source, (unsigned char *)target.gameCode, gameCodeWidth);
|
||||
get(source, target.gameCodeID);
|
||||
get(source, (unsigned char *)target.description, sessionTypeDescriptionWidth);
|
||||
get(source, tmp);
|
||||
target.independent = (tmp == 1);
|
||||
get(source, tmp);
|
||||
target.exclusive = (tmp == 1);
|
||||
}
|
||||
|
||||
void get(ByteStream::ReadIterator & source, GameCodeDescription & target)
|
||||
{
|
||||
unsigned tmp = 0;
|
||||
get(source, target.gameID);
|
||||
get(source, (unsigned char *)target.code, gameCodeWidth);
|
||||
get(source, (unsigned char *)target.description, sessionTypeDescriptionWidth);
|
||||
get(source, tmp);
|
||||
target.createDynamic = (tmp == 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void put(ByteStream & target, const apiAccount & source)
|
||||
{
|
||||
put(target, (const unsigned char *)source.GetName(), apiAccountNameWidth);
|
||||
put(target, source.GetId());
|
||||
put(target, source.GetStatus());
|
||||
}
|
||||
|
||||
void put(ByteStream & target, const apiSubscription & source)
|
||||
{
|
||||
put(target, source.GetGamecode());
|
||||
put(target, source.GetProviderId());
|
||||
put(target, source.GetStatus());
|
||||
put(target, source.GetSubscriptionFeatures());
|
||||
put(target, source.GetGameFeatures());
|
||||
put(target, source.GetDurationSeconds());
|
||||
put(target, source.GetParentalLimitSeconds());
|
||||
}
|
||||
|
||||
void put(ByteStream & target, const apiSession & source)
|
||||
{
|
||||
put(target, source.GetType());
|
||||
put(target, source.GetProviderId());
|
||||
put(target, (const unsigned char *)source.GetId(), apiSessionIdWidth);
|
||||
put(target, source.GetClientIP());
|
||||
put(target, source.GetDurationSeconds());
|
||||
put(target, source.GetParentalLimitSeconds());
|
||||
put(target, source.GetTimeoutMinutes());
|
||||
put(target, source.GetIsSecure());
|
||||
}
|
||||
|
||||
void put(ByteStream & target, const apiAccount_v1 & source)
|
||||
{
|
||||
put(target, (unsigned char *)source.name, apiAccountNameWidth_v1);
|
||||
put(target, source.id);
|
||||
put(target, source.status);
|
||||
}
|
||||
|
||||
void put(ByteStream & target, const apiSubscription_v1 & source)
|
||||
{
|
||||
put(target, source.gamecode);
|
||||
put(target, source.status);
|
||||
put(target, source.subscriptionFeatures);
|
||||
put(target, source.gameFeatures);
|
||||
put(target, source.durationSeconds);
|
||||
put(target, source.parentalLimitSeconds);
|
||||
}
|
||||
|
||||
void put(ByteStream & target, const apiSession_v1 & source)
|
||||
{
|
||||
put(target, source.type);
|
||||
put(target, (unsigned char *)source.id, apiSessionIdWidth_v1);
|
||||
put(target, source.clientIP);
|
||||
put(target, source.durationSeconds);
|
||||
put(target, source.parentalLimitSeconds);
|
||||
put(target, source.timeoutMinutes);
|
||||
put(target, source.isSecure);
|
||||
}
|
||||
|
||||
void put (ByteStream & target, const SessionTypeDesc & source)
|
||||
{
|
||||
put(target, source.type);
|
||||
put(target, (unsigned char *)source.gameCode, gameCodeWidth);
|
||||
put(target, source.gameCodeID);
|
||||
put(target, (unsigned char *)source.description, sessionTypeDescriptionWidth);
|
||||
put(target, (unsigned)source.independent);
|
||||
put(target, (unsigned)source.exclusive);
|
||||
}
|
||||
|
||||
void put (ByteStream & target, const GameCodeDescription & source)
|
||||
{
|
||||
put(target, source.gameID);
|
||||
put(target, (unsigned char *)source.code, gameCodeWidth);
|
||||
put(target, (unsigned char *)source.description, sessionTypeDescriptionWidth);
|
||||
put(target, (unsigned)source.createDynamic);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
namespace Message
|
||||
{
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/*
|
||||
Basic::Basic() :
|
||||
AutoByteStream(),
|
||||
mMessageID(0)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
Basic::Basic(const unsigned short newMessageId) :
|
||||
AutoByteStream(),
|
||||
mMessageID(newMessageId)
|
||||
{
|
||||
addVariable(mMessageID);
|
||||
}
|
||||
|
||||
Basic::Basic(Base::ByteStream::ReadIterator & source) :
|
||||
AutoByteStream(),
|
||||
mMessageID(0)
|
||||
{
|
||||
addVariable(mMessageID);
|
||||
AutoByteStream::unpack(source);
|
||||
}
|
||||
|
||||
/*
|
||||
Basic::Basic(const Basic & source) :
|
||||
AutoByteStream(source),
|
||||
mMessageID(source.GetMessageID())
|
||||
{
|
||||
}
|
||||
|
||||
Basic & Basic::operator=(const Basic & rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Basic::~Basic()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Null
|
||||
BeginImplementMessage(Null, Basic)
|
||||
EndImplementMessage
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Connect_v1
|
||||
BeginImplementMessage(Connect_v1, Basic)
|
||||
ImplementMessageMember(Version, "unknown")
|
||||
EndImplementMessage
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Connect
|
||||
BeginImplementMessage(Connect, Basic)
|
||||
ImplementMessageMember(Version, "unknown")
|
||||
ImplementMessageMember(Description, "unknown")
|
||||
EndImplementMessage
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// ConnectReply
|
||||
BeginImplementMessage(ConnectReply, Basic)
|
||||
ImplementMessageMember(Result, RESULT_SUCCESS)
|
||||
ImplementMessageMember(Version, "unknown")
|
||||
EndImplementMessage
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Unknown
|
||||
BeginImplementMessage(Unknown, Basic)
|
||||
ImplementMessageMember(UnknownMessageID,0)
|
||||
EndImplementMessage
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Tracked
|
||||
BeginImplementMessage(Tracked, Basic)
|
||||
ImplementMessageMember(TrackingNumber, 0)
|
||||
EndImplementMessage
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// TrackedReply
|
||||
BeginImplementMessage(TrackedReply, Tracked)
|
||||
ImplementMessageMember(Result, RESULT_TIMEOUT)
|
||||
EndImplementMessage
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
#ifndef COMMON_API__COMMON_MESSAGES_H
|
||||
#define COMMON_API__COMMON_MESSAGES_H
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include "Base/Archive.h"
|
||||
#include "CommonAPI.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
/*
|
||||
void get(ByteStream::ReadIterator & source, apiAccountStatus & target);
|
||||
void get(ByteStream::ReadIterator & source, apiSessionType & target);
|
||||
void get(ByteStream::ReadIterator & source, apiGamecode & target);
|
||||
void get(ByteStream::ReadIterator & source, apiSubscriptionStatus & target);
|
||||
void get(ByteStream::ReadIterator & source, apiKickReason & target);
|
||||
void get(ByteStream::ReadIterator & source, apiKickResult & target);
|
||||
*/
|
||||
void get(ByteStream::ReadIterator & source, apiAccount_v1 & target);
|
||||
void get(ByteStream::ReadIterator & source, apiSubscription_v1 & target);
|
||||
void get(ByteStream::ReadIterator & source, apiSession_v1 & target);
|
||||
void get(ByteStream::ReadIterator & source, apiAccount & target);
|
||||
void get(ByteStream::ReadIterator & source, apiSubscription & target);
|
||||
void get(ByteStream::ReadIterator & source, apiSession & target);
|
||||
|
||||
/*
|
||||
void put(ByteStream & target, const apiAccountStatus & source);
|
||||
void put(ByteStream & target, const apiSessionType & source);
|
||||
void put(ByteStream & target, const apiGamecode & source);
|
||||
void put(ByteStream & target, const apiSubscriptionStatus & source);
|
||||
void put(ByteStream & target, const apiKickReason & source);
|
||||
void put(ByteStream & target, const apiKickResult & source);
|
||||
*/
|
||||
void put(ByteStream & target, const apiAccount_v1 & source);
|
||||
void put(ByteStream & target, const apiSubscription_v1 & source);
|
||||
void put(ByteStream & target, const apiSession_v1 & source);
|
||||
void put(ByteStream & target, const apiAccount & source);
|
||||
void put(ByteStream & target, const apiSubscription & source);
|
||||
void put(ByteStream & target, const apiSession & source);
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
namespace Message
|
||||
{
|
||||
|
||||
|
||||
class Basic : public Base::AutoByteStream
|
||||
{
|
||||
public:
|
||||
Basic();
|
||||
|
||||
Basic(const unsigned char * const buffer, const unsigned int bufferSize);
|
||||
explicit Basic(const unsigned short messageId);
|
||||
explicit Basic(Base::ByteStream::ReadIterator & source);
|
||||
|
||||
Basic(const Basic & source);
|
||||
Basic & operator=(const Basic & rhs);
|
||||
|
||||
virtual ~Basic();
|
||||
const unsigned short GetMessageID() const;
|
||||
private:
|
||||
Base::AutoVariable<unsigned short> mMessageID;
|
||||
};
|
||||
|
||||
inline const unsigned short Basic::GetMessageID() const
|
||||
{
|
||||
return mMessageID.get(); //lint !e1037 choosing a const or non const conversion is NOT ambiguous
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// These macros are used to define VNL messages. These marcos make the message
|
||||
// objects easier to read and easier to define. There are three macros used
|
||||
// to define message objects and three macros used to implement the message
|
||||
// objects.
|
||||
|
||||
#define BeginDefineMessage(ClassName,BaseClass,MessageID) \
|
||||
class ClassName : public BaseClass \
|
||||
{ \
|
||||
enum { MESSAGE_ID = MessageID }; \
|
||||
private: \
|
||||
void InitializeMembers(); \
|
||||
public: \
|
||||
ClassName(const unsigned short messageId = MESSAGE_ID); \
|
||||
ClassName(Base::ByteStream::ReadIterator & source);
|
||||
|
||||
#define DefineMessageMember(MemberName,Type) \
|
||||
private: \
|
||||
Base::AutoVariable<Type> m##MemberName; \
|
||||
public: \
|
||||
const Type & Get##MemberName() const \
|
||||
{ return (const Type &)m##MemberName.get(); } \
|
||||
void Set##MemberName(const Type & value) \
|
||||
{ m##MemberName.set((const Type &)value); }
|
||||
|
||||
/*
|
||||
#define DefineMessageMemberEnum(MemberName,Type,Internal) \
|
||||
private: \
|
||||
Base::AutoVariable<Internal> m##MemberName; \
|
||||
public: \
|
||||
const Type & Get##MemberName() const \
|
||||
{ return (const Type &)m##MemberName.get(); } \
|
||||
void Set##MemberName(const Type & value) \
|
||||
{ m##MemberName.set((const Internal &)value); }
|
||||
*/
|
||||
|
||||
#define DefineMessageMemberArray(MemberName, MemberType) \
|
||||
private: \
|
||||
Base::AutoArray<MemberType> m##MemberName; \
|
||||
public: \
|
||||
const std::vector<MemberType> & Get##MemberName() const { return m##MemberName.get(); } \
|
||||
void Set##MemberName(const std::vector<MemberType> & value) { m##MemberName.set(value); }
|
||||
|
||||
#define EndDefineMessage \
|
||||
};
|
||||
|
||||
#define BeginImplementMessage(ClassName,BaseClass) \
|
||||
ClassName::ClassName(const unsigned short messageId) : BaseClass(messageId) \
|
||||
{ \
|
||||
InitializeMembers(); \
|
||||
} \
|
||||
ClassName::ClassName(Base::ByteStream::ReadIterator & source) : BaseClass(MESSAGE_ID) \
|
||||
{ \
|
||||
InitializeMembers(); \
|
||||
unpack(source); \
|
||||
} \
|
||||
void ClassName::InitializeMembers() \
|
||||
{
|
||||
|
||||
#define ImplementMessageMember(MemberName,DefaultValue) \
|
||||
m##MemberName.set(DefaultValue); \
|
||||
addVariable(m##MemberName);
|
||||
|
||||
#define EndImplementMessage \
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
namespace Message
|
||||
{
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
MESSAGE_NULL = 0x0000,
|
||||
|
||||
// Client Messages
|
||||
MESSAGE_CONNECT_v1 = 0x0ff0,
|
||||
MESSAGE_CANCEL_REQUEST = 0x0ff1,
|
||||
MESSAGE_CONNECT = 0x0ff2,
|
||||
|
||||
// Server Messages
|
||||
MESSAGE_CONNECT_REPLY = 0x7ff0,
|
||||
MESSAGE_RECONNECT = 0x7ffd,
|
||||
MESSAGE_CONNECTION_CLOSED = 0x7ffe,
|
||||
MESSAGE_CONNECTION_FAILED = 0x7fff,
|
||||
|
||||
MESSAGE_UNKNOWN = 0xffff
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Null
|
||||
BeginDefineMessage(Null, Basic, MESSAGE_NULL)
|
||||
EndDefineMessage
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Connect_v1
|
||||
BeginDefineMessage(Connect_v1, Basic, MESSAGE_CONNECT_v1)
|
||||
DefineMessageMember(Version, std::string)
|
||||
EndDefineMessage
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Connect
|
||||
BeginDefineMessage(Connect, Basic, MESSAGE_CONNECT)
|
||||
DefineMessageMember(Version, std::string)
|
||||
DefineMessageMember(Description, std::string)
|
||||
EndDefineMessage
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// ConnectReply
|
||||
BeginDefineMessage(ConnectReply, Basic, MESSAGE_CONNECT_REPLY)
|
||||
DefineMessageMember(Result, apiResult)
|
||||
DefineMessageMember(Version, std::string)
|
||||
EndDefineMessage
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Unknown
|
||||
BeginDefineMessage(Unknown, Basic, MESSAGE_UNKNOWN)
|
||||
DefineMessageMember(UnknownMessageID, unsigned short)
|
||||
EndDefineMessage
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Tracked
|
||||
BeginDefineMessage(Tracked, Basic, MESSAGE_NULL)
|
||||
DefineMessageMember(TrackingNumber, apiTrackingNumber)
|
||||
EndDefineMessage
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// TrackedReply
|
||||
BeginDefineMessage(TrackedReply, Tracked, MESSAGE_NULL)
|
||||
DefineMessageMember(Result, apiResult)
|
||||
EndDefineMessage
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // LAUNCHPAD_API_COMMON_H
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
include_directories(
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/3rd/library/udplibrary
|
||||
)
|
||||
|
||||
add_library(LoginAPI
|
||||
Client.cpp
|
||||
Client.h
|
||||
ClientCore.cpp
|
||||
ClientCore.h
|
||||
Messages.cpp
|
||||
Messages.h
|
||||
)
|
||||
@@ -0,0 +1,419 @@
|
||||
#pragma warning (disable : 4786 )
|
||||
|
||||
|
||||
#include "Client.h"
|
||||
#include "ClientCore.h"
|
||||
|
||||
|
||||
namespace LoginAPI
|
||||
{
|
||||
|
||||
Entitlement::Entitlement() :
|
||||
mTotalTime(0),
|
||||
mEntitledTime(0),
|
||||
mTotalTimeSinceLastLogin(0),
|
||||
mEntitledTimeSinceLastLogin(0),
|
||||
mReasonUnentitled(0)
|
||||
{
|
||||
}
|
||||
|
||||
Feature::Feature() :
|
||||
mID(0),
|
||||
mData()
|
||||
{
|
||||
}
|
||||
|
||||
bool Feature::SetParameter(const std::string & key, int value)
|
||||
{
|
||||
if (key.size() > 32)
|
||||
return false;
|
||||
|
||||
std::string keyToken = key + "[";
|
||||
unsigned offset = mData.find(keyToken);
|
||||
if (offset == std::string::npos)
|
||||
{
|
||||
char token[256];
|
||||
sprintf(token, "%s[%d]", key.c_str(), value);
|
||||
if (!mData.empty())
|
||||
mData += ", ";
|
||||
mData += token;
|
||||
}
|
||||
else
|
||||
{
|
||||
char token[256];
|
||||
unsigned delimiter = mData.find("]", offset);
|
||||
sprintf(token, "%d", value);
|
||||
std::string newData = mData.substr(0,offset+keyToken.size()) + token + mData.substr(delimiter);
|
||||
mData = newData;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Feature::SetParameter(const std::string & key, const std::string & value)
|
||||
{
|
||||
if (key.size() > 32 || value.size() > 32)
|
||||
return false;
|
||||
|
||||
std::string keyToken = key + "[";
|
||||
unsigned offset = mData.find(keyToken);
|
||||
if (offset == std::string::npos)
|
||||
{
|
||||
char token[256];
|
||||
sprintf(token, "%s[%s]", key.c_str(), value.c_str());
|
||||
if (!mData.empty())
|
||||
mData += ", ";
|
||||
mData += token;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned delimiter = mData.find("]", offset);
|
||||
offset += keyToken.size();
|
||||
std::string newData = mData.substr(0,offset) + value + mData.substr(delimiter);
|
||||
mData = newData;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int Feature::GetParameter(const std::string & key) const
|
||||
{
|
||||
std::string keyToken = key + "[";
|
||||
unsigned offset = mData.find(keyToken);
|
||||
if (offset != std::string::npos)
|
||||
{
|
||||
offset += keyToken.size();
|
||||
return atoi(mData.c_str() + offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string & Feature::GetParameter(const std::string & key, std::string & value) const
|
||||
{
|
||||
std::string keyToken = key + "[";
|
||||
unsigned offset = mData.find(keyToken);
|
||||
if (offset != std::string::npos)
|
||||
{
|
||||
unsigned delimiter = mData.find("]", offset);
|
||||
offset += keyToken.size();
|
||||
value = mData.substr(offset,delimiter-offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// For consumable promotions
|
||||
bool Feature::Consume()
|
||||
{
|
||||
int consumeCount = GetParameter("count");
|
||||
if (consumeCount == 0)
|
||||
return false;
|
||||
SetParameter("count", consumeCount-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
int Feature::GetConsumeCount() const
|
||||
{
|
||||
return GetParameter("count");
|
||||
}
|
||||
|
||||
bool Feature::IsActive() const
|
||||
{
|
||||
return GetParameter("active") ? true : false;
|
||||
}
|
||||
|
||||
void Feature::SetActive(bool isActive)
|
||||
{
|
||||
SetParameter("active", (int)isActive);
|
||||
}
|
||||
|
||||
|
||||
FeatureDescription::FeatureDescription() :
|
||||
mID(0),
|
||||
mDescription(),
|
||||
mDefaultData()
|
||||
{
|
||||
}
|
||||
|
||||
UsageLimit::UsageLimit() :
|
||||
mType(0),
|
||||
mAllowance(0),
|
||||
mNextAllowance(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const char * apiVersion = "2004.07.20";
|
||||
|
||||
Client::Client(const char * serverList, const char * description, unsigned maxConnections)
|
||||
: apiClient()
|
||||
{
|
||||
mClientCore = new ClientCore(this, apiVersion, serverList, description, maxConnections);
|
||||
}
|
||||
|
||||
Client::Client(const char ** serverList, unsigned serverCount, const char * description, unsigned maxConnections)
|
||||
: apiClient()
|
||||
{
|
||||
mClientCore = new ClientCore(this, apiVersion, serverList, serverCount, description, maxConnections);
|
||||
}
|
||||
|
||||
Client::~Client()
|
||||
{
|
||||
delete mClientCore;
|
||||
}
|
||||
|
||||
void Client::Process()
|
||||
{
|
||||
this->apiClient::Process();
|
||||
}
|
||||
|
||||
void Client::OnConnectionOpened(const char * address, unsigned connectionCount)
|
||||
{
|
||||
}
|
||||
|
||||
void Client::OnConnectionClosed(const char * address, unsigned connectionCount)
|
||||
{
|
||||
}
|
||||
|
||||
void Client::OnConnectionFailed(const char * address, unsigned connectionCount)
|
||||
{
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionLogin(const char * name, const char * password, const apiSessionType sessionType, const apiIP clientIP, unsigned flags, const char * sessionNamespace, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionLogin(name, password, sessionType, clientIP, flags, sessionNamespace, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionLogin(const char * parentSession, const apiSessionType sessionType, const apiIP clientIP, unsigned flags, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionLogin(parentSession, sessionType, clientIP, flags, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionLoginInternal(const apiAccountId accountId, const apiSessionType sessionType, const apiIP clientIP, unsigned flags, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionLoginInternal(accountId, sessionType, clientIP, flags, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionConsume(const char * sessionID, const apiSessionType sessionType, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionConsume(sessionID, sessionType, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionValidate(const char * sessionID, const apiSessionType sessionType, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionValidate(sessionID, sessionType, userData) : 0;
|
||||
}
|
||||
|
||||
void Client::SessionLogout(const char * sessionID)
|
||||
{
|
||||
if (mClientCore)
|
||||
static_cast<ClientCore *>(mClientCore)->SessionLogout(sessionID);
|
||||
}
|
||||
|
||||
void Client::SessionTouch(const char * sessionID)
|
||||
{
|
||||
if (mClientCore)
|
||||
static_cast<ClientCore *>(mClientCore)->SessionTouch(sessionID);
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GetSessions(const apiAccountId accountId, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetSessions(accountId, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GetFeatures(const char * sessionID, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetFeatures(sessionID, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GetFeatures(const apiAccountId accountId, const apiGamecode gamecode, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetFeatures(accountId, gamecode, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GrantFeature(const char * sessionID, unsigned featureType, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GrantFeature(sessionID, featureType, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::ModifyFeature(const char * sessionID, const Feature & feature, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->ModifyFeature(sessionID, feature, userData) : 0;
|
||||
}
|
||||
apiTrackingNumber Client::RevokeFeature(const char * sessionID, unsigned featureType, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->RevokeFeature(sessionID, featureType, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::EnumerateFeatures(apiGamecode gamecode, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->EnumerateFeatures(gamecode, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionStartPlay(const char * sessionID, const char * serverName, const char * characterName, const char * gameData, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionStartPlay(sessionID, serverName, characterName, gameData, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionStopPlay(const char * sessionID, const char * serverName, const char * characterName, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionStopPlay(sessionID, serverName, characterName, userData) : 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// OLD CALLS
|
||||
apiTrackingNumber Client::GetAccountStatus(const char * name, const char * password, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetAccountStatus(name, password, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GetAccountStatus(const apiAccountId accountId, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetAccountStatus(accountId, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GetAccountSubscriptions(const char * name, const char * password, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetAccountSubscriptions(name, password, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GetAccountSubscriptions(const char * sessionID, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetAccountSubscriptions(sessionID, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GetAccountSubscriptions(const apiAccountId accountId, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetAccountSubscriptions(accountId, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GetAccountSubscription(const char * name, const char * password, const apiGamecode gamecode, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetAccountSubscription(name, password, gamecode, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GetAccountSubscription(const char * sessionID, const apiGamecode gamecode, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetAccountSubscription(sessionID, gamecode, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GetAccountSubscription(const apiAccountId accountId, const apiGamecode gamecode, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetAccountSubscription(accountId, gamecode, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionLogin_v3(const char * name, const char * password, const apiSessionType sessionType, const apiIP clientIP, const bool forceLogin, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionLogin_v3(name, password, sessionType, clientIP, forceLogin, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionLogin_v3(const char * parentSession, const apiSessionType sessionType, const apiIP clientIP, const bool forceLogin, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionLogin_v3(parentSession, sessionType, clientIP, forceLogin, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionLogin_v4(const char * name, const char * password, const apiSessionType sessionType, const apiIP clientIP, const bool forceLogin, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionLogin_v4(name, password, sessionType, clientIP, forceLogin, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionLogin_v4(const char * parentSession, const apiSessionType sessionType, const apiIP clientIP, const bool forceLogin, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionLogin_v4(parentSession, sessionType, clientIP, forceLogin, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionLogin_v5(const char * name, const char * password, const apiSessionType sessionType, const apiIP clientIP, unsigned flags, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionLogin_v5(name, password, sessionType, clientIP, flags, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionLogin_v5(const char * parentSession, const apiSessionType sessionType, const apiIP clientIP, unsigned flags, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionLogin_v5(parentSession, sessionType, clientIP, flags, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionConsume_v2(const char * sessionID, const apiSessionType sessionType, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionConsume_v2(sessionID, sessionType, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionConsume_v3(const char * sessionID, const apiSessionType sessionType, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionConsume_v3(sessionID, sessionType, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionValidate_v2(const char * sessionID, const apiSessionType sessionType, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionValidate_v2(sessionID, sessionType, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionValidate_v3(const char * sessionID, const apiSessionType sessionType, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionValidate_v3(sessionID, sessionType, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionValidateEx(const char * sessionID, const apiSessionType sessionType, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionValidateEx(sessionID, sessionType, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SubscriptionValidate(const char * sessionID, const apiGamecode gamecode, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SubscriptionValidate(sessionID, gamecode, userData) : 0;
|
||||
}
|
||||
|
||||
void Client::SessionLogout(const char ** sessionList, const unsigned sessionCount)
|
||||
{
|
||||
if (mClientCore)
|
||||
static_cast<ClientCore *>(mClientCore)->SessionLogout(sessionList, sessionCount);
|
||||
}
|
||||
|
||||
void Client::SessionTouch(const char ** sessionList, const unsigned sessionCount)
|
||||
{
|
||||
if (mClientCore)
|
||||
static_cast<ClientCore *>(mClientCore)->SessionTouch(sessionList, sessionCount);
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::SessionKick(const char * sessionID, apiKickReason reason, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->SessionKick(sessionID, reason, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GetMemberInformation(const apiAccountId accountId, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetMemberInformation(accountId, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GetMemberInformation_v2(const apiAccountId accountId, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GetMemberInformation_v2(accountId, userData) : 0;
|
||||
}
|
||||
|
||||
void Client::SessionKickReply(const char * sessionID, apiKickReply reply)
|
||||
{
|
||||
if (mClientCore)
|
||||
static_cast<ClientCore *>(mClientCore)->SessionKickReply(sessionID, reply);
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::GrantFeature_v2(const char * sessionID, unsigned featureType, const char * gameCode, unsigned providerID, unsigned promoID, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GrantFeature_v2(sessionID, featureType, gameCode, providerID, promoID, userData) : 0;
|
||||
}
|
||||
|
||||
apiTrackingNumber Client::ModifyFeature_v2(unsigned accountID, const char * gameCode, const Feature & origFeature, const Feature & newFeature, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->ModifyFeature_v2(accountID, gameCode, origFeature, newFeature, userData) : 0;
|
||||
}
|
||||
|
||||
|
||||
apiTrackingNumber Client::GrantFeatureByStationID(unsigned accountID, unsigned featureType, const char * gameCode, unsigned providerID, unsigned promoID, const void * userData)
|
||||
{
|
||||
return mClientCore ? static_cast<ClientCore *>(mClientCore)->GrantFeatureByStationID(accountID, featureType, gameCode, providerID, promoID, userData) : 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,504 @@
|
||||
#ifndef SESSION_LOGIN_API__CLIENT_H
|
||||
#define SESSION_LOGIN_API__CLIENT_H
|
||||
|
||||
|
||||
#include <string>
|
||||
#include "Session/CommonAPI/CommonAPI.h"
|
||||
|
||||
|
||||
namespace LoginAPI
|
||||
{
|
||||
|
||||
|
||||
class UsageLimit;
|
||||
class Feature;
|
||||
class FeatureDescription;
|
||||
class Entitlement;
|
||||
class Client : public apiClient
|
||||
{
|
||||
public:
|
||||
// server list is space delimited
|
||||
Client(const char * serverList, const char * description, unsigned maxConnections = 2);
|
||||
// server list is c-style string array
|
||||
Client(const char ** serverList, unsigned serverCount, const char * description, unsigned maxConnections = 2);
|
||||
virtual ~Client();
|
||||
|
||||
virtual void Process();
|
||||
|
||||
////////////////////////////////////////
|
||||
// State Callbacks
|
||||
virtual void OnConnectionOpened(const char * address, unsigned connectionCount);
|
||||
virtual void OnConnectionClosed(const char * address, unsigned connectionCount);
|
||||
virtual void OnConnectionFailed(const char * address, unsigned connectionCount);
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Requests
|
||||
apiTrackingNumber SessionLogin(const char * name,
|
||||
const char * password,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const unsigned flags,
|
||||
const char * sessionNamespace = _defaultNamespace,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin(const char * parentSessionID,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const unsigned flags,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLoginInternal(const apiAccountId accountId,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const unsigned flags,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionConsume(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionValidate(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
void SessionLogout(const char * sessionID);
|
||||
void SessionTouch(const char * sessionID);
|
||||
|
||||
apiTrackingNumber SessionStartPlay(const char * sessionID,
|
||||
const char * serverName,
|
||||
const char * characterName,
|
||||
const char * gameData,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionStopPlay(const char * sessionID,
|
||||
const char * serverName,
|
||||
const char * characterName,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionKick(const char * sessionID,
|
||||
apiKickReason reason,
|
||||
const void * userData = 0);
|
||||
|
||||
apiTrackingNumber GetSessions(const apiAccountId accountId,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetFeatures(const char * sessionID,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetFeatures(const apiAccountId accountId,
|
||||
const apiGamecode gamecode,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GrantFeature(const char * sessionID,
|
||||
unsigned featureType,
|
||||
const void * userData = 0);
|
||||
|
||||
apiTrackingNumber ModifyFeature(const char * sessionID,
|
||||
const Feature & feature,
|
||||
const void * userData = 0);
|
||||
|
||||
|
||||
|
||||
apiTrackingNumber RevokeFeature(const char * sessionID,
|
||||
unsigned featureType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber EnumerateFeatures(apiGamecode,
|
||||
const void * userData = 0);
|
||||
|
||||
apiTrackingNumber GrantFeature_v2(const char * sessionID,
|
||||
unsigned featureType,
|
||||
const char * gameCode,
|
||||
unsigned providerID = 0,
|
||||
unsigned promoID = 0,
|
||||
const void * userData = 0);
|
||||
|
||||
apiTrackingNumber ModifyFeature_v2( unsigned accountID,
|
||||
const char * gameCode,
|
||||
const Feature & origFeature,
|
||||
const Feature & newFeature,
|
||||
const void * userData = 0);
|
||||
|
||||
apiTrackingNumber GrantFeatureByStationID(unsigned accountID,
|
||||
unsigned featureType,
|
||||
const char * gameCode,
|
||||
unsigned providerID = 0,
|
||||
unsigned promoID = 0,
|
||||
const void * userData = 0);
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Result Callbacks
|
||||
virtual void OnSessionLogin(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
const apiSession & session,
|
||||
const UsageLimit & usageLimit,
|
||||
const Entitlement & entitlement,
|
||||
void * userData) = 0;
|
||||
virtual void OnSessionLoginInternal(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
const apiSession & session,
|
||||
const UsageLimit & usageLimit,
|
||||
const Entitlement & entitlement,
|
||||
void * userData) = 0;
|
||||
virtual void OnSessionValidate(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
const apiSession & session,
|
||||
const UsageLimit & usageLimit,
|
||||
const Entitlement & entitlement,
|
||||
void * userData) = 0;
|
||||
virtual void OnSessionConsume(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
const apiSession & session,
|
||||
const UsageLimit & usageLimit,
|
||||
const Entitlement & entitlement,
|
||||
void * userData) = 0;
|
||||
virtual void OnSessionStartPlay(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
void * userData) = 0;
|
||||
virtual void OnSessionStopPlay(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
void * userData) = 0;
|
||||
virtual void OnSessionKick(const unsigned trackingNumber,
|
||||
const apiResult result,
|
||||
void * userData) = 0;
|
||||
virtual void OnGetSessions(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const unsigned count,
|
||||
const apiSession session[],
|
||||
const apiSubscription subscription[],
|
||||
const UsageLimit usageLimit[],
|
||||
const unsigned timeCreated[],
|
||||
const unsigned timeTouched[],
|
||||
void * userData) = 0;
|
||||
virtual void OnGetFeatures(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const unsigned featureCount,
|
||||
const Feature featureArray[],
|
||||
const void * userData = 0) = 0;
|
||||
virtual void OnGrantFeature(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
void * userData) = 0;
|
||||
virtual void OnModifyFeature(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
void * userData) = 0;
|
||||
virtual void OnRevokeFeature(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
void * userData) = 0;
|
||||
virtual void OnEnumerateFeatures(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const unsigned featureCount,
|
||||
const FeatureDescription featureArray[],
|
||||
const void * userData = 0) = 0;
|
||||
virtual void NotifySessionKick(const char ** sessionList,
|
||||
const unsigned sessionCount) = 0;
|
||||
|
||||
////////////////////////////////////////
|
||||
// Call support for backwards compatability
|
||||
apiTrackingNumber GetAccountStatus(const char * name,
|
||||
const char * password,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountStatus(const apiAccountId accountId,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountSubscriptions(const char * name,
|
||||
const char * password,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountSubscriptions(const char * sessionID,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountSubscriptions(const apiAccountId accountId,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountSubscription(const char * name,
|
||||
const char * password,
|
||||
const apiGamecode gamecode,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountSubscription(const char * sessionID,
|
||||
const apiGamecode gamecode,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountSubscription(const apiAccountId accountId,
|
||||
const apiGamecode gamecode,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin_v3(const char * name,
|
||||
const char * password,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const bool forceLogin,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin_v3(const char * parentSessionID,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const bool forceLogin,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin_v4(const char * name,
|
||||
const char * password,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const bool forceLogin,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin_v4(const char * parentSessionID,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const bool forceLogin,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin_v5(const char * name,
|
||||
const char * password,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const unsigned flags,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin_v5(const char * parentSessionID,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const unsigned flags,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionConsume_v2(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionConsume_v3(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionValidate_v2(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionValidate_v3(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionValidateEx(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SubscriptionValidate(const char * sessionID,
|
||||
const apiGamecode gamecode,
|
||||
const void * userData = 0);
|
||||
void SessionLogout(const char ** sessionList,
|
||||
const unsigned sessionCount);
|
||||
void SessionTouch(const char ** sessionList,
|
||||
const unsigned sessionCount);
|
||||
apiTrackingNumber GetMemberInformation(const apiAccountId accountId,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetMemberInformation_v2(const apiAccountId accountId,
|
||||
const void * userData = 0);
|
||||
|
||||
void SessionKickReply(const char * sessionID,
|
||||
apiKickReply reply);
|
||||
|
||||
virtual void NotifySessionKickRequest(const apiAccount & account,
|
||||
const apiSession & session,
|
||||
const apiKickReason reason) {}
|
||||
virtual void OnGetAccountStatus(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
void * userData) {}
|
||||
virtual void OnGetAccountSubscriptions(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription * subscriptionArray,
|
||||
unsigned subscriptionCount,
|
||||
void * userData) {}
|
||||
virtual void OnGetAccountSubscription(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
void * userData) {}
|
||||
virtual void OnSessionLogin_v3(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
const apiSession & session,
|
||||
void * userData) {}
|
||||
virtual void OnSessionLogin_v4(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
const apiSession & session,
|
||||
const UsageLimit & usageLimit,
|
||||
void * userData) {}
|
||||
virtual void OnSessionLogin_v5(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
const apiSession & session,
|
||||
const UsageLimit & usageLimit,
|
||||
const Entitlement & entitlement,
|
||||
void * userData) {};
|
||||
virtual void OnSessionValidate_v2(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
const apiSession & session,
|
||||
void * userData) {}
|
||||
virtual void OnSessionValidate_v3(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
const apiSession & session,
|
||||
const UsageLimit & usageLimit,
|
||||
void * userData) {}
|
||||
virtual void OnSessionValidateEx(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
const apiSession & session,
|
||||
const char * password,
|
||||
void * userData) {}
|
||||
virtual void OnSessionConsume_v2(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
const apiSession & session,
|
||||
void * userData) {}
|
||||
virtual void OnSessionConsume_v3(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const apiSubscription & subscription,
|
||||
const apiSession & session,
|
||||
const UsageLimit & usageLimit,
|
||||
void * userData) {}
|
||||
virtual void OnSubscriptionValidate(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiSubscription & subscription,
|
||||
void * userData) {}
|
||||
virtual void OnGetMemberInformation(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const char * firstName,
|
||||
const char * lastName,
|
||||
const char * gender,
|
||||
const char * email,
|
||||
void * userData) {}
|
||||
virtual void OnGetMemberInformation_v2(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const apiAccount & account,
|
||||
const char * firstName,
|
||||
const char * lastName,
|
||||
const char * gender,
|
||||
const char * email,
|
||||
const char * defaultCurrency,
|
||||
const char * defaultCountry,
|
||||
const char * stationHandle,
|
||||
void * userData) {}
|
||||
|
||||
virtual void OnGrantFeatureV2(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
void * userData) {}
|
||||
|
||||
virtual void OnModifyFeature_v2(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
const Feature & currentFeature,
|
||||
void * userData) {}
|
||||
|
||||
virtual void OnGrantFeatureByStationID(const apiTrackingNumber trackingNumber,
|
||||
const apiResult result,
|
||||
void * userData) {}
|
||||
|
||||
|
||||
};
|
||||
|
||||
class Entitlement
|
||||
{
|
||||
public:
|
||||
typedef unsigned char UnentitledCode;
|
||||
enum
|
||||
{
|
||||
UNENTITLED_REASON_NULL,
|
||||
UNENTITLED_REASON_USER_CLOSED,
|
||||
UNENTITLED_REASON_ADMIN_CLOSED,
|
||||
UNENTITLED_REASON_BILL_DECLINED,
|
||||
UNENTITLED_REASON_END
|
||||
};
|
||||
|
||||
public:
|
||||
Entitlement();
|
||||
|
||||
unsigned GetTotalTime() const { return mTotalTime; }
|
||||
unsigned GetEntitledTime() const { return mEntitledTime; }
|
||||
unsigned GetTotalTimeSinceLastLogin() const { return mTotalTimeSinceLastLogin; }
|
||||
unsigned GetEntitledTimeSinceLastLogin() const { return mEntitledTimeSinceLastLogin; }
|
||||
UnentitledCode GetReasonUnentitled() const { return mReasonUnentitled; }
|
||||
|
||||
void SetTotalTime(unsigned value) { mTotalTime = value; }
|
||||
void SetEntitledTime(unsigned value) { mEntitledTime = value; }
|
||||
void SetTotalTimeSinceLastLogin(unsigned value) { mTotalTimeSinceLastLogin = value; }
|
||||
void SetEntitledTimeSinceLastLogin(unsigned value) { mEntitledTimeSinceLastLogin = value; }
|
||||
void SetReasonUnentitled(UnentitledCode value) { mReasonUnentitled = value; }
|
||||
|
||||
private:
|
||||
unsigned mTotalTime;
|
||||
unsigned mEntitledTime;
|
||||
unsigned mTotalTimeSinceLastLogin;
|
||||
unsigned mEntitledTimeSinceLastLogin;
|
||||
UnentitledCode mReasonUnentitled;
|
||||
};
|
||||
|
||||
class Feature
|
||||
{
|
||||
public:
|
||||
Feature();
|
||||
|
||||
unsigned GetID() const { return mID; }
|
||||
const std::string & GetData() const { return mData; }
|
||||
|
||||
void SetID(unsigned value) { mID = value; }
|
||||
void SetData(const std::string & value) { mData = value; }
|
||||
|
||||
bool SetParameter(const std::string & key, int value);
|
||||
bool SetParameter(const std::string & key, const std::string & value);
|
||||
int GetParameter(const std::string & key) const;
|
||||
std::string & GetParameter(const std::string & key, std::string & value) const;
|
||||
|
||||
// For consumable promotions
|
||||
bool Consume();
|
||||
int GetConsumeCount() const;
|
||||
bool IsActive() const;
|
||||
void SetActive(bool isActive);
|
||||
|
||||
private:
|
||||
unsigned mID;
|
||||
std::string mData;
|
||||
};
|
||||
|
||||
class FeatureDescription
|
||||
{
|
||||
public:
|
||||
FeatureDescription();
|
||||
unsigned GetID() const { return mID; }
|
||||
const std::string & GetDescription() const { return mDescription; }
|
||||
const std::string & GetDefaultData() const { return mDefaultData; }
|
||||
void SetID(unsigned value) { mID = value; }
|
||||
void SetDescription(const std::string & value) { mDescription = value; }
|
||||
void SetDefaultData(const std::string & value) { mDefaultData = value; }
|
||||
private:
|
||||
unsigned mID;
|
||||
std::string mDescription;
|
||||
std::string mDefaultData;
|
||||
};
|
||||
|
||||
class UsageLimit
|
||||
{
|
||||
public:
|
||||
typedef unsigned char TypeCode;
|
||||
enum
|
||||
{
|
||||
TYPE_NONE,
|
||||
TYPE_COMPULSORY,
|
||||
TYPE_ADVISORY
|
||||
};
|
||||
|
||||
public:
|
||||
UsageLimit();
|
||||
|
||||
TypeCode GetType() const { return mType; }
|
||||
unsigned GetAllowance() const { return mAllowance; }
|
||||
time_t GetNextAllowance() const { return mNextAllowance; }
|
||||
|
||||
void SetType(unsigned char value) { mType = value; }
|
||||
void SetAllowance(unsigned value) { mAllowance = value; }
|
||||
void SetNextAllowance(time_t value) { mNextAllowance = value; }
|
||||
|
||||
private:
|
||||
TypeCode mType;
|
||||
unsigned mAllowance;
|
||||
time_t mNextAllowance;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,240 @@
|
||||
#ifndef SESSION_LOGIN_API__CLIENT_CORE_H
|
||||
#define SESSION_LOGIN_API__CLIENT_CORE_H
|
||||
|
||||
|
||||
#include "Session/CommonAPI/CommonClient.h"
|
||||
#include "Client.h"
|
||||
|
||||
|
||||
namespace LoginAPI
|
||||
{
|
||||
|
||||
|
||||
class ClientCore : public apiCore
|
||||
{
|
||||
public:
|
||||
ClientCore(apiClient * parent, const char * version, const char * serverList, const char * description, unsigned maxConnections);
|
||||
ClientCore(apiClient * parent, const char * version, const char ** serverList, unsigned serverCount, const char * description, unsigned maxConnections);
|
||||
virtual ~ClientCore();
|
||||
|
||||
Client * GetClient() { return static_cast<Client *>(GetParent()); }
|
||||
|
||||
virtual int GetKeepAliveDelay();
|
||||
|
||||
////////////////////////////////////////
|
||||
// Requests
|
||||
public:
|
||||
apiTrackingNumber GetAccountStatus(const char * name,
|
||||
const char * password,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountStatus(const apiAccountId accountId,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountSubscriptions(const char * name,
|
||||
const char * password,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountSubscriptions(const char * sessionID,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountSubscriptions(const apiAccountId accountId,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountSubscription(const char * name,
|
||||
const char * password,
|
||||
const apiGamecode gamecode,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountSubscription(const char * sessionID,
|
||||
const apiGamecode gamecode,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetAccountSubscription(const apiAccountId accountId,
|
||||
const apiGamecode gamecode,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin_v3(const char * name,
|
||||
const char * password,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const bool forceLogin,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin_v3(const char * parentSessionID,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const bool forceLogin,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin_v4(const char * name,
|
||||
const char * password,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const bool forceLogin,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin_v4(const char * parentSessionID,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const bool forceLogin,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin_v5(const char * name,
|
||||
const char * password,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const unsigned flags,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin_v5(const char * parentSessionID,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const unsigned flags,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin(const char * name,
|
||||
const char * password,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const unsigned flags,
|
||||
const char * sessionNamespace = _defaultNamespace,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLogin(const char * parentSessionID,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const unsigned flags,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionLoginInternal(const apiAccountId accountId,
|
||||
const apiSessionType sessionType,
|
||||
const apiIP clientIP,
|
||||
const unsigned flags,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionConsume_v2(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionConsume_v3(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionConsume(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionValidate_v2(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionValidate_v3(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionValidate(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionValidateEx(const char * sessionID,
|
||||
const apiSessionType sessionType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SubscriptionValidate(const char * sessionID,
|
||||
const apiGamecode gamecode,
|
||||
const void * userData = 0);
|
||||
|
||||
void SessionLogout(const char * sessionID);
|
||||
void SessionLogout(const char ** sessionList,
|
||||
const unsigned sessionCount);
|
||||
void SessionTouch(const char * sessionID);
|
||||
void SessionTouch(const char ** sessionList,
|
||||
const unsigned sessionCount);
|
||||
|
||||
apiTrackingNumber GetMemberInformation(const apiAccountId accountId,
|
||||
const void * userData = 0);
|
||||
|
||||
apiTrackingNumber GetMemberInformation_v2(const apiAccountId accountId,
|
||||
const void * userData = 0);
|
||||
|
||||
void SessionKickReply(const char * sessionID,
|
||||
apiKickReply reply);
|
||||
|
||||
apiTrackingNumber GetSessions(const apiAccountId accountId,
|
||||
const void * userData = 0);
|
||||
|
||||
apiTrackingNumber GetFeatures(const char * sessionID,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GetFeatures(const apiAccountId accountId,
|
||||
const apiGamecode gamecode,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber GrantFeature(const char * sessionID,
|
||||
unsigned featureType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber ModifyFeature(const char * sessionID,
|
||||
const Feature & feature,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber RevokeFeature(const char * sessionID,
|
||||
unsigned featureType,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber EnumerateFeatures(apiGamecode,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionStartPlay(const char * sessionId,
|
||||
const char * serverName,
|
||||
const char * characterName,
|
||||
const char * gameData,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionStopPlay(const char * sessionId,
|
||||
const char * serverName,
|
||||
const char * characterName,
|
||||
const void * userData = 0);
|
||||
apiTrackingNumber SessionKick(const char * sessionID,
|
||||
apiKickReason reason,
|
||||
const void * userData = 0);
|
||||
|
||||
apiTrackingNumber GrantFeature_v2(const char * sessionID,
|
||||
unsigned featureType,
|
||||
const char * gameCode,
|
||||
unsigned providerID,
|
||||
unsigned promoID,
|
||||
const void * userData = 0);
|
||||
|
||||
apiTrackingNumber ModifyFeature_v2( unsigned accountID,
|
||||
const char * gameCode,
|
||||
const Feature & origFeature,
|
||||
const Feature & newFeature,
|
||||
const void * userData = 0);
|
||||
|
||||
apiTrackingNumber GrantFeatureByStationID(unsigned accountID,
|
||||
unsigned featureType,
|
||||
const char * gameCode,
|
||||
unsigned providerID,
|
||||
unsigned promoID,
|
||||
const void * userData = 0);
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Result Callbacks
|
||||
public:
|
||||
void OnGetAccountStatus(const Base::ByteStream & stream, void * userData);
|
||||
void OnGetAccountSubscriptions(const Base::ByteStream & stream, void * userData);
|
||||
void OnGetAccountSubscription(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionLogin_v3(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionLogin_v4(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionLogin_v5(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionLogin(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionLoginInternal(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionValidate_v2(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionValidate_v3(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionValidate(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionValidateEx(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionConsume_v2(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionConsume_v3(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionConsume(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionKick(const Base::ByteStream & stream);
|
||||
void OnSubscriptionValidate(const Base::ByteStream & stream, void * userData);
|
||||
void OnGetMemberInformation(const Base::ByteStream & stream, void * userData);
|
||||
void OnGetMemberInformation_v2(const Base::ByteStream & stream, void * userData);
|
||||
void OnGetSessions(const Base::ByteStream & stream, void * userData);
|
||||
void OnGetFeatures(const Base::ByteStream & stream, void * userData);
|
||||
void OnGrantFeature(const Base::ByteStream & stream, void * userData);
|
||||
void OnModifyFeature(const Base::ByteStream & stream, void * userData);
|
||||
void OnRevokeFeature(const Base::ByteStream & stream, void * userData);
|
||||
void OnEnumerateFeatures(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionStartPlay(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionStopPlay(const Base::ByteStream & stream, void * userData);
|
||||
void OnSessionKick(const Base::ByteStream & stream, void * userData);
|
||||
void OnGrantFeatureV2(const Base::ByteStream & stream, void * userData);
|
||||
void NotifySessionKickRequest(const Base::ByteStream & stream, void * userData);
|
||||
void NotifySessionKick(const Base::ByteStream & stream, void * userData);
|
||||
void OnModifyFeature_v2(const Base::ByteStream & stream, void * userData);
|
||||
void OnGrantFeatureByStationID(const Base::ByteStream & stream, void * userData);
|
||||
|
||||
|
||||
virtual bool Callback(Base::ByteStream & stream, void * userData);
|
||||
virtual void Timeout(unsigned short messageId, apiTrackingNumber trackingNumber, void * userData);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,262 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The author of this code is Justin Randall
|
||||
//
|
||||
// I have made modifications to the ByteStream
|
||||
// and AutoByteStream classes in order to make them suitable
|
||||
// for use in messaging systems which require objects that
|
||||
// are copyable and assignable. It is also desirable for
|
||||
// the ByteStream object to use a flexible allocator system
|
||||
// that may support multi-threaded programming models.
|
||||
|
||||
|
||||
#include "Archive.h"
|
||||
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
CMutex ByteStreamMutex;
|
||||
#endif
|
||||
|
||||
#if defined (PASCAL_STRING)
|
||||
#pragma message ("--- Packing pascal style strings ---")
|
||||
void get(Base::ByteStream::ReadIterator& source, std::string& target)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
Base::get (source, size);
|
||||
|
||||
const unsigned char *buf = source.getBuffer();
|
||||
|
||||
target.assign((const char *)buf, (unsigned int)(buf + size));
|
||||
|
||||
const unsigned int readSize = size * sizeof(char);
|
||||
source.advance(readSize);
|
||||
}
|
||||
|
||||
void put(ByteStream& target, const std::string& source)
|
||||
{
|
||||
const unsigned int size = source.size();
|
||||
put(target, size);
|
||||
target.put(source.data(), size * sizeof (char));
|
||||
}
|
||||
|
||||
#else
|
||||
#pragma message ("--- Packing c style strings ---")
|
||||
void get(ByteStream::ReadIterator & source, std::string & target)
|
||||
{
|
||||
target = reinterpret_cast<const char *>(source.getBuffer());
|
||||
source.advance(target.length() + 1);
|
||||
}
|
||||
|
||||
|
||||
void put(ByteStream & target, const std::string & source)
|
||||
{
|
||||
target.put(source.c_str(), source.size()+1);
|
||||
}
|
||||
#endif
|
||||
|
||||
Base::ReadIterator::ReadIterator() :
|
||||
readPtr(0),
|
||||
stream(0)
|
||||
{
|
||||
}
|
||||
|
||||
Base::ReadIterator::ReadIterator(const ReadIterator & source) :
|
||||
readPtr(source.readPtr),
|
||||
stream(source.stream)
|
||||
{
|
||||
}
|
||||
|
||||
Base::ReadIterator::ReadIterator(const ByteStream & source) :
|
||||
readPtr(0),
|
||||
stream(&source)
|
||||
{
|
||||
}
|
||||
|
||||
ByteStream::ReadIterator::~ReadIterator()
|
||||
{
|
||||
stream = 0;
|
||||
}
|
||||
|
||||
ByteStream::ByteStream() :
|
||||
allocatedSize(0),
|
||||
beginReadIterator(),
|
||||
data(NULL),
|
||||
size(0)
|
||||
{
|
||||
data = Data::getNewData();
|
||||
beginReadIterator = ReadIterator(*this);
|
||||
}
|
||||
|
||||
ByteStream::ByteStream(const unsigned char * const newBuffer, const unsigned int bufferSize) :
|
||||
allocatedSize(bufferSize),
|
||||
data(0),
|
||||
size(bufferSize)
|
||||
{
|
||||
data = Data::getNewData();
|
||||
if(data->size < size)
|
||||
{
|
||||
delete[] data->buffer;
|
||||
data->buffer = new unsigned char[size];
|
||||
data->size = size;
|
||||
}
|
||||
memcpy(data->buffer, newBuffer, size);
|
||||
beginReadIterator = ReadIterator(*this);
|
||||
}
|
||||
|
||||
ByteStream::ByteStream(const ByteStream & source):
|
||||
allocatedSize(source.getSize()), // only allocate what is really there, be opportinistic when grow()'ing
|
||||
data(source.data),
|
||||
size(source.getSize())
|
||||
{
|
||||
source.data->ref();
|
||||
beginReadIterator = ReadIterator(*this);
|
||||
}
|
||||
|
||||
ByteStream::ByteStream(ReadIterator & source) :
|
||||
allocatedSize(0),
|
||||
size(0)
|
||||
{
|
||||
data = Data::getNewData();
|
||||
put(source.getBuffer(), source.getSize());
|
||||
source.advance(source.getSize());
|
||||
beginReadIterator = ReadIterator(*this);
|
||||
}
|
||||
|
||||
ByteStream::~ByteStream()
|
||||
{
|
||||
data->deref();
|
||||
allocatedSize = 0;
|
||||
data = 0; //lint !e672 (data deref insures the data is deleted if no one references it)
|
||||
size = 0;
|
||||
}
|
||||
|
||||
ByteStream & ByteStream::operator=(const ByteStream & rhs)
|
||||
{
|
||||
if(this != &rhs)
|
||||
{
|
||||
data->deref(); // deref local data
|
||||
rhs.data->ref();
|
||||
allocatedSize = rhs.allocatedSize;
|
||||
size = rhs.size;
|
||||
data = rhs.data; //lint !e672 (data is ref counted)
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ByteStream::get(void * target, ReadIterator & readIterator, const unsigned long int targetSize) const
|
||||
{
|
||||
assert(readIterator.getReadPosition() + targetSize <= allocatedSize);
|
||||
memcpy(target, &data->buffer[readIterator.getReadPosition()], targetSize);
|
||||
}
|
||||
|
||||
void ByteStream::put(const void * const source, const unsigned int sourceSize)
|
||||
{
|
||||
if(data->getRef() > 1)
|
||||
{
|
||||
const unsigned char * const tmp = data->buffer;
|
||||
data->deref();
|
||||
data = Data::getNewData();
|
||||
if(data->size < sourceSize)
|
||||
{
|
||||
delete[] data->buffer;
|
||||
data->buffer = new unsigned char[size];
|
||||
data->size = size;
|
||||
}
|
||||
memcpy(data->buffer, tmp, size);
|
||||
allocatedSize = size;
|
||||
}
|
||||
growToAtLeast(size + sourceSize);
|
||||
memcpy(&data->buffer[size], source, sourceSize);
|
||||
size += sourceSize;
|
||||
}
|
||||
|
||||
void ByteStream::reAllocate(const unsigned int newSize)
|
||||
{
|
||||
allocatedSize = newSize;
|
||||
if(data->size < allocatedSize)
|
||||
{
|
||||
unsigned char * tmp = new unsigned char[newSize];
|
||||
if(data->buffer != NULL)
|
||||
memcpy(tmp, data->buffer, size);
|
||||
delete[] data->buffer;
|
||||
data->buffer = tmp;
|
||||
data->size = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
AutoByteStream::AutoByteStream() :
|
||||
members()
|
||||
{
|
||||
}
|
||||
|
||||
AutoByteStream::~AutoByteStream()
|
||||
{
|
||||
}
|
||||
|
||||
void AutoByteStream::addVariable(AutoVariableBase & newVariable)
|
||||
{
|
||||
members.push_back(&newVariable);
|
||||
}
|
||||
|
||||
const unsigned int AutoByteStream::getItemCount() const
|
||||
{
|
||||
return members.size();
|
||||
}
|
||||
|
||||
void AutoByteStream::pack(ByteStream & target) const
|
||||
{
|
||||
std::vector<AutoVariableBase *>::const_iterator i;
|
||||
unsigned short packedSize=static_cast<unsigned short>(members.size());
|
||||
put(target,packedSize);
|
||||
for(i = members.begin(); i != members.end(); ++i)
|
||||
{
|
||||
(*i)->pack(target);
|
||||
}
|
||||
}
|
||||
|
||||
void AutoByteStream::unpack(ByteStream::ReadIterator & source)
|
||||
{
|
||||
std::vector<AutoVariableBase *>::iterator i;
|
||||
unsigned short packedSize;
|
||||
get(source,packedSize);
|
||||
for(i = members.begin(); i != members.end(); ++i)
|
||||
{
|
||||
(*i)->unpack(source);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
AutoVariableBase::AutoVariableBase()
|
||||
{
|
||||
}
|
||||
|
||||
AutoVariableBase::~AutoVariableBase()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
+673
@@ -0,0 +1,673 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The author of this code is Justin Randall
|
||||
//
|
||||
// I have made modifications to the ByteStream
|
||||
// and AutoByteStream classes in order to make them suitable
|
||||
// for use in messaging systems which require objects that
|
||||
// are copyable and assignable. It is also desirable for
|
||||
// the ByteStream object to use a flexible allocator system
|
||||
// that may support multi-threaded programming models.
|
||||
|
||||
|
||||
#ifndef BASE_ARCHIVE_H
|
||||
#define BASE_ARCHIVE_H
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Platform.h"
|
||||
#include "Mutex.h"
|
||||
|
||||
|
||||
#if defined _MT || defined _REENTRANT
|
||||
# define USE_ARCHIVE_MUTEX
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# include "win32/Archive.h"
|
||||
#elif linux
|
||||
# include "linux/Archive.h"
|
||||
#elif sparc
|
||||
# include "solaris/Archive.h"
|
||||
#else
|
||||
#error /Base/Archive.h: Undefine platform type
|
||||
#endif
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
const unsigned MAX_ARRAY_SIZE = 1024;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
extern CMutex ByteStreamMutex;
|
||||
#endif
|
||||
|
||||
class ByteStream;
|
||||
|
||||
class ReadIterator
|
||||
{
|
||||
public:
|
||||
ReadIterator();
|
||||
ReadIterator(const ReadIterator & source);
|
||||
explicit ReadIterator(const ByteStream & source);
|
||||
~ReadIterator();
|
||||
|
||||
ReadIterator & operator = (const ReadIterator & source);
|
||||
void advance (const unsigned int distance);
|
||||
void get (void * target, const unsigned long int readSize);
|
||||
const unsigned int getSize () const;
|
||||
const unsigned char * const getBuffer () const;
|
||||
const unsigned int getReadPosition () const;
|
||||
|
||||
private:
|
||||
unsigned int readPtr;
|
||||
const ByteStream * stream;
|
||||
};
|
||||
class ByteStream
|
||||
{
|
||||
public:
|
||||
typedef Base::ReadIterator ReadIterator;
|
||||
|
||||
private:
|
||||
class Data
|
||||
{
|
||||
friend class ByteStream;
|
||||
friend class Base::ReadIterator;
|
||||
public:
|
||||
~Data();
|
||||
|
||||
static Data * getNewData();
|
||||
|
||||
const int getRef () const;
|
||||
void deref ();
|
||||
void ref ();
|
||||
protected:
|
||||
unsigned char * buffer;
|
||||
unsigned long size;
|
||||
private:
|
||||
struct DataFreeList
|
||||
{
|
||||
~DataFreeList()
|
||||
{
|
||||
std::vector<ByteStream::Data *>::iterator i;
|
||||
for(i = freeList.begin(); i != freeList.end(); ++i)
|
||||
{
|
||||
delete (*i);
|
||||
}
|
||||
};
|
||||
std::vector<Data *> freeList;
|
||||
};
|
||||
Data();
|
||||
//explicit Data(unsigned char * buffer);
|
||||
static std::vector<Data *> & getDataFreeList();
|
||||
static void releaseOldData(Data * oldData);
|
||||
private:
|
||||
int refCount;
|
||||
};
|
||||
|
||||
friend class Base::ReadIterator;
|
||||
public:
|
||||
ByteStream();
|
||||
ByteStream(const unsigned char * const buffer, const unsigned int bufferSize);
|
||||
ByteStream(const ByteStream & source);
|
||||
virtual ~ByteStream();
|
||||
|
||||
public:
|
||||
ByteStream(ReadIterator & source);
|
||||
ByteStream & operator = (const ByteStream & source);
|
||||
ByteStream & operator = (ReadIterator & source);
|
||||
const ReadIterator & begin() const;
|
||||
void clear();
|
||||
const unsigned char * const getBuffer() const;
|
||||
const unsigned int getSize() const;
|
||||
void put(const void * const source, const unsigned int sourceSize);
|
||||
|
||||
private:
|
||||
void get(void * target, ReadIterator & readIterator, const unsigned long int readSize) const;
|
||||
void growToAtLeast(const unsigned int targetSize);
|
||||
void reAllocate(const unsigned int newSize);
|
||||
|
||||
private:
|
||||
unsigned int allocatedSize;
|
||||
ReadIterator beginReadIterator;
|
||||
Data * data;
|
||||
unsigned int size;
|
||||
|
||||
|
||||
};
|
||||
|
||||
inline ByteStream::Data::Data() :
|
||||
buffer(0),
|
||||
size(0),
|
||||
refCount(1)
|
||||
{
|
||||
}
|
||||
|
||||
inline ByteStream::Data::~Data()
|
||||
{
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Lock();
|
||||
#endif
|
||||
|
||||
refCount = 0;
|
||||
delete[] buffer;
|
||||
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void ByteStream::Data::deref()
|
||||
{
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Lock();
|
||||
#endif
|
||||
|
||||
refCount--;
|
||||
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Unlock();
|
||||
#endif
|
||||
|
||||
if(refCount < 1)
|
||||
releaseOldData(this);
|
||||
}
|
||||
|
||||
inline std::vector<ByteStream::Data *> & ByteStream::Data::getDataFreeList()
|
||||
{
|
||||
static DataFreeList freeList;
|
||||
return freeList.freeList;
|
||||
}
|
||||
|
||||
inline ByteStream::Data * ByteStream::Data::getNewData()
|
||||
{
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Lock();
|
||||
#endif
|
||||
|
||||
Data * result = 0;
|
||||
if(getDataFreeList().empty())
|
||||
{
|
||||
result = new Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = getDataFreeList().back();
|
||||
getDataFreeList().pop_back();
|
||||
}
|
||||
result->refCount = 1;
|
||||
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Unlock();
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline const int ByteStream::Data::getRef() const
|
||||
{
|
||||
return refCount;
|
||||
}
|
||||
|
||||
inline void ByteStream::Data::ref()
|
||||
{
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Lock();
|
||||
#endif
|
||||
|
||||
refCount++;
|
||||
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void ByteStream::Data::releaseOldData(ByteStream::Data * oldData)
|
||||
{
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Lock();
|
||||
#endif
|
||||
|
||||
getDataFreeList().push_back(oldData);
|
||||
oldData->refCount = 0;
|
||||
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline ByteStream::ReadIterator & ByteStream::ReadIterator::operator = (const ByteStream::ReadIterator & rhs)
|
||||
{
|
||||
if(&rhs != this)
|
||||
{
|
||||
readPtr = rhs.readPtr;
|
||||
stream = rhs.stream;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void ByteStream::ReadIterator::get(void * target, const unsigned long int readSize)
|
||||
{
|
||||
assert(stream);
|
||||
stream->get(target, *this, readSize);
|
||||
readPtr += readSize;
|
||||
}
|
||||
|
||||
inline const unsigned int ByteStream::ReadIterator::getSize() const
|
||||
{
|
||||
assert(stream);
|
||||
return stream->getSize() - readPtr;
|
||||
}
|
||||
|
||||
inline const ByteStream::ReadIterator & ByteStream::begin() const
|
||||
{
|
||||
return beginReadIterator;
|
||||
}
|
||||
|
||||
inline void ByteStream::ReadIterator::advance(const unsigned int distance)
|
||||
{
|
||||
readPtr += distance;
|
||||
}
|
||||
|
||||
inline const unsigned int ByteStream::ReadIterator::getReadPosition() const
|
||||
{
|
||||
return readPtr;
|
||||
}
|
||||
|
||||
inline const unsigned char * const ByteStream::ReadIterator::getBuffer() const
|
||||
{
|
||||
if(stream)
|
||||
return &stream->data->buffer[readPtr];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void ByteStream::clear()
|
||||
{
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Lock();
|
||||
#endif
|
||||
|
||||
size = 0;
|
||||
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline const unsigned char * const ByteStream::getBuffer() const
|
||||
{
|
||||
return data->buffer;
|
||||
}
|
||||
|
||||
inline const unsigned int ByteStream::getSize() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
inline void ByteStream::growToAtLeast(const unsigned int targetSize)
|
||||
{
|
||||
if(allocatedSize < targetSize)
|
||||
{
|
||||
reAllocate(allocatedSize + allocatedSize + targetSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, ByteStream & target)
|
||||
{
|
||||
target.put(source.getBuffer(), source.getSize());
|
||||
source.advance(source.getSize());
|
||||
}
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, double & target)
|
||||
{
|
||||
source.get(&target, 8);
|
||||
target = byteSwap(target);
|
||||
}
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, float & target)
|
||||
{
|
||||
source.get(&target, 4);
|
||||
target = byteSwap(target);
|
||||
}
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, uint64 & target)
|
||||
{
|
||||
source.get(&target, 8);
|
||||
target = byteSwap(target);
|
||||
}
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, int64 & target)
|
||||
{
|
||||
source.get(&target, 8);
|
||||
target = byteSwap(target);
|
||||
}
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, uint32 & target)
|
||||
{
|
||||
source.get(&target, 4);
|
||||
target = byteSwap(target);
|
||||
}
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, int32 & target)
|
||||
{
|
||||
source.get(&target, 4);
|
||||
target = byteSwap(target);
|
||||
}
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, uint16 & target)
|
||||
{
|
||||
source.get(&target, 2);
|
||||
target = byteSwap(target);
|
||||
}
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, int16 & target)
|
||||
{
|
||||
source.get(&target, 2);
|
||||
target = byteSwap(target);
|
||||
}
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, uint8 & target)
|
||||
{
|
||||
source.get(&target, 1);
|
||||
}
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, int8 & target)
|
||||
{
|
||||
source.get(&target, 1);
|
||||
}
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, unsigned char * const target, const unsigned int targetSize)
|
||||
{
|
||||
source.get(target, targetSize);
|
||||
}
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, bool & target)
|
||||
{
|
||||
source.get(&target, 1);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
inline void put(ByteStream & target, ByteStream::ReadIterator & source)
|
||||
{
|
||||
target.put(source.getBuffer(), source.getSize());
|
||||
source.advance(source.getSize());
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const double value)
|
||||
{
|
||||
double temp = byteSwap(value);
|
||||
target.put(&temp, 8);
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const float value)
|
||||
{
|
||||
float temp = byteSwap(value);
|
||||
target.put(&temp, 4);
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const uint64 value)
|
||||
{
|
||||
uint64 temp = byteSwap(value);
|
||||
target.put(&temp, 8);
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const int64 value)
|
||||
{
|
||||
int64 temp = byteSwap(value);
|
||||
target.put(&temp, 8);
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const uint32 value)
|
||||
{
|
||||
uint32 temp = byteSwap(value);
|
||||
target.put(&temp, 4);
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const int32 value)
|
||||
{
|
||||
int32 temp = byteSwap(value);
|
||||
target.put(&temp, 4);
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const uint16 value)
|
||||
{
|
||||
uint16 temp = byteSwap(value);
|
||||
target.put(&temp, 2);
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const int16 value)
|
||||
{
|
||||
int16 temp = byteSwap(value);
|
||||
target.put(&temp, 2);
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const uint8 value)
|
||||
{
|
||||
target.put(&value, 1);
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const int8 value)
|
||||
{
|
||||
target.put(&value, 1);
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const bool & source)
|
||||
{
|
||||
target.put(&source, 1);
|
||||
}
|
||||
|
||||
|
||||
inline void put(ByteStream & target, const unsigned char * const source, const unsigned int sourceSize)
|
||||
{
|
||||
target.put(source, sourceSize);
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const ByteStream & source)
|
||||
{
|
||||
target.put(source.begin().getBuffer(), source.begin().getSize());
|
||||
}
|
||||
|
||||
void get(ByteStream::ReadIterator & source, std::string & target);
|
||||
void put(ByteStream & target, const std::string & source);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class AutoVariableBase
|
||||
{
|
||||
public:
|
||||
AutoVariableBase();
|
||||
virtual ~AutoVariableBase();
|
||||
|
||||
virtual void pack(ByteStream & target) const = 0;
|
||||
virtual void unpack(ByteStream::ReadIterator & source) = 0;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class AutoByteStream
|
||||
{
|
||||
public:
|
||||
AutoByteStream();
|
||||
virtual ~AutoByteStream();
|
||||
void addVariable(AutoVariableBase & newVariable);
|
||||
virtual const unsigned int getItemCount() const;
|
||||
virtual void pack(ByteStream & target) const;
|
||||
virtual void unpack(ByteStream::ReadIterator & source);
|
||||
protected:
|
||||
std::vector<AutoVariableBase *> members;
|
||||
private:
|
||||
AutoByteStream(const AutoByteStream & source);
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
class AutoVariable : public AutoVariableBase
|
||||
{
|
||||
public:
|
||||
AutoVariable();
|
||||
explicit AutoVariable(const ValueType & source);
|
||||
virtual ~AutoVariable();
|
||||
|
||||
const ValueType & get() const;
|
||||
virtual void pack(ByteStream & target) const;
|
||||
void set(const ValueType & rhs);
|
||||
virtual void unpack(ByteStream::ReadIterator & source);
|
||||
|
||||
private:
|
||||
ValueType value;
|
||||
};
|
||||
|
||||
template<class ValueType>
|
||||
AutoVariable<ValueType>::AutoVariable() :
|
||||
AutoVariableBase(),
|
||||
value()
|
||||
{
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
AutoVariable<ValueType>::AutoVariable(const ValueType & source) :
|
||||
AutoVariableBase(),
|
||||
value(source)
|
||||
{
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
AutoVariable<ValueType>::~AutoVariable()
|
||||
{
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
const ValueType & AutoVariable<ValueType>::get() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
void AutoVariable<ValueType>::pack(ByteStream & target) const
|
||||
{
|
||||
Base::put(target, value);
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
void AutoVariable<ValueType>::set(const ValueType & rhs)
|
||||
{
|
||||
value = rhs;
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
void AutoVariable<ValueType>::unpack(ByteStream::ReadIterator & source)
|
||||
{
|
||||
Base::get(source, value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
class AutoArray : public AutoVariableBase
|
||||
{
|
||||
public:
|
||||
AutoArray();
|
||||
AutoArray(const AutoArray & source);
|
||||
~AutoArray();
|
||||
|
||||
const std::vector<ValueType> & get() const;
|
||||
void set(const std::vector<ValueType> & source);
|
||||
|
||||
virtual void pack(ByteStream & target) const;
|
||||
virtual void unpack(ByteStream::ReadIterator & source);
|
||||
|
||||
private:
|
||||
std::vector<ValueType> array;
|
||||
};
|
||||
|
||||
template<class ValueType>
|
||||
inline AutoArray<ValueType>::AutoArray()
|
||||
{
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
inline AutoArray<ValueType>::AutoArray(const AutoArray & source) :
|
||||
array(source.array)
|
||||
{
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
inline AutoArray<ValueType>::~AutoArray()
|
||||
{
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
inline const std::vector<ValueType> & AutoArray<ValueType>::get() const
|
||||
{
|
||||
return array;
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
inline void AutoArray<ValueType>::set(const std::vector<ValueType> & source)
|
||||
{
|
||||
array = source;
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
inline void AutoArray<ValueType>::pack(ByteStream & target) const
|
||||
{
|
||||
unsigned int arraySize = array.size();
|
||||
Base::put(target, arraySize);
|
||||
|
||||
typename std::vector<ValueType>::const_iterator i;
|
||||
for(i = array.begin(); i != array.end(); ++i)
|
||||
{
|
||||
ValueType v = (*i);
|
||||
Base::put(target, v);
|
||||
}
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
inline void AutoArray<ValueType>::unpack(ByteStream::ReadIterator & source)
|
||||
{
|
||||
unsigned int arraySize;
|
||||
Base::get(source, arraySize);
|
||||
ValueType v;
|
||||
|
||||
if (arraySize > MAX_ARRAY_SIZE)
|
||||
arraySize = 0;
|
||||
|
||||
for(unsigned int i = 0; i < arraySize; ++i)
|
||||
{
|
||||
Base::get(source, v);
|
||||
array.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,353 @@
|
||||
#include "AutoLog.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
#ifdef WIN32
|
||||
#include <direct.h> // for NT directory commands
|
||||
#define SLASHCHAR "\\"
|
||||
#define WRONGSLASH '/'
|
||||
#else
|
||||
#define SLASHCHAR "/"
|
||||
#define WRONGSLASH '\\'
|
||||
#endif
|
||||
|
||||
// set default values for global masks
|
||||
CAutoLog::eLogLevel CAutoLog::nLogMask = eLOG_NORMAL; // what is logged in log files
|
||||
CAutoLog::eLogLevel CAutoLog::nPrintMask = eLOG_ERROR; // what is printed on the screen
|
||||
CAutoLog::eLogLevel CAutoLog::nFlushMask = eLOG_ERROR; // when is file flushed on every entry?
|
||||
|
||||
// class info
|
||||
|
||||
//-------------------------------------
|
||||
bool CAutoLog::Open(const char * filename)
|
||||
//-------------------------------------
|
||||
{
|
||||
|
||||
if( NULL == filename)
|
||||
return false;
|
||||
|
||||
if (pFilename)
|
||||
return false;
|
||||
|
||||
#ifdef WIN32
|
||||
pFilename = _strdup(filename);
|
||||
#else
|
||||
pFilename = strdup(filename);
|
||||
#endif
|
||||
|
||||
// Sanitize slashes
|
||||
char *ptr;
|
||||
while ((ptr = strchr(pFilename,WRONGSLASH)) != NULL)
|
||||
*ptr = SLASHCHAR[0];
|
||||
|
||||
char strPath[1024];
|
||||
strcpy(strPath,pFilename);
|
||||
ptr = strrchr(strPath, SLASHCHAR[0]);
|
||||
if (ptr != NULL)
|
||||
{
|
||||
*ptr = 0;
|
||||
|
||||
#ifdef WIN32
|
||||
char curdir[128];
|
||||
|
||||
// remember current directory
|
||||
if( _getcwd(curdir,sizeof(curdir)) == NULL )
|
||||
{
|
||||
fprintf(stderr,"CAutoLog::Archive failed to get current directory!\n");
|
||||
free(pFilename);
|
||||
pFilename = NULL;
|
||||
return false; // error, can't proceed
|
||||
}
|
||||
|
||||
if (_chdir(strPath))
|
||||
{
|
||||
// failed to find the directory, so we must create it
|
||||
if (_mkdir(strPath))
|
||||
{
|
||||
fprintf(stderr,"CAutoLog::Archive failed to make directory: %s\n", strPath);
|
||||
free(pFilename);
|
||||
pFilename = NULL;
|
||||
return false; // error, can't proceed
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// found the directory, but we don't want to be there, so go back
|
||||
_chdir(curdir);
|
||||
}
|
||||
#else
|
||||
struct stat SS;
|
||||
|
||||
// see if directory exists
|
||||
if (stat(strPath,&SS))
|
||||
{
|
||||
// create directory
|
||||
if (mkdir(strPath,0777))
|
||||
{
|
||||
fprintf(stderr,"CAutoLog::Archive failed to make directory: %s\n", strPath);
|
||||
free(pFilename);
|
||||
pFilename = NULL;
|
||||
return false; // error, can't proceed
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
pFile = fopen(pFilename,"a+");
|
||||
if( pFile == NULL || pFile == (FILE *)-1)
|
||||
{
|
||||
//fprintf(stderr,"CAutoLog::Open failed to open log file: %s\n",pFilename);
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
time_t t;
|
||||
time(&t);
|
||||
struct tm *ptm = localtime(&t);
|
||||
nTodaysDayOfYear = ptm->tm_yday;
|
||||
|
||||
//printf("Open log file: %s\n",pFilename);
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
void CAutoLog::Close(void)
|
||||
//-------------------------------------
|
||||
{
|
||||
if( pFile != (FILE *)-1 && pFile != NULL)
|
||||
{
|
||||
fclose(pFile);
|
||||
}
|
||||
pFile = (FILE *)-1;
|
||||
|
||||
if (pFilename)
|
||||
{
|
||||
free(pFilename);
|
||||
}
|
||||
pFilename = NULL;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
void CAutoLog::LogError(char * format, ...)
|
||||
{
|
||||
char strInput[1024];
|
||||
|
||||
// parse format and input arguments
|
||||
va_list varg;
|
||||
va_start(varg, format);
|
||||
vsprintf(strInput, format, varg);
|
||||
va_end(varg);
|
||||
|
||||
Log(eLOG_ERROR, strInput);
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
void CAutoLog::LogAlert(char * format, ...)
|
||||
{
|
||||
char strInput[1024];
|
||||
|
||||
// parse format and input arguments
|
||||
va_list varg;
|
||||
va_start(varg, format);
|
||||
vsprintf(strInput, format, varg);
|
||||
va_end(varg);
|
||||
|
||||
Log(eLOG_ALERT, strInput);
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
void CAutoLog::Log(char * format, ...)
|
||||
{
|
||||
char strInput[1024];
|
||||
|
||||
// parse format and input arguments
|
||||
va_list varg;
|
||||
va_start(varg, format);
|
||||
vsprintf(strInput, format, varg);
|
||||
va_end(varg);
|
||||
|
||||
Log(eLOG_NORMAL, strInput);
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
void CAutoLog::LogDebug(char * format, ...)
|
||||
{
|
||||
char strInput[1024];
|
||||
|
||||
// parse format and input arguments
|
||||
va_list varg;
|
||||
va_start(varg, format);
|
||||
vsprintf(strInput, format, varg);
|
||||
va_end(varg);
|
||||
|
||||
Log(eLOG_DEBUG, strInput);
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
void CAutoLog::Log(eLogLevel severity, char *fmt, ...)
|
||||
//-------------------------------------
|
||||
{
|
||||
if (pFile == (FILE *)-1 || pFile == NULL)
|
||||
{
|
||||
//fprintf(stderr,"CAutoLog::Log called with no file open!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nLogMask == eLOG_NONE || nLogMask < severity)
|
||||
{
|
||||
if (nPrintMask == eLOG_NONE || nPrintMask < severity)
|
||||
{ // no point in parsing, we're doing nothing.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char strTime[128];
|
||||
char strInput[1024];
|
||||
char strOutput[1024+128];
|
||||
time_t t;
|
||||
|
||||
// parse format and input arguments
|
||||
va_list varg;
|
||||
va_start(varg, fmt);
|
||||
vsprintf(strInput, fmt, varg);
|
||||
va_end(varg);
|
||||
|
||||
// make timestamp
|
||||
time(&t);
|
||||
strftime(strTime, sizeof(strTime), "[%m/%d/%Y %H:%M:%S]", localtime(&t) );
|
||||
|
||||
// construct output string
|
||||
sprintf(strOutput, "%s %s\n", strTime, strInput);
|
||||
|
||||
// check to see if current file needs to be archived
|
||||
Archive();
|
||||
|
||||
// log to file
|
||||
if (!(nLogMask == eLOG_NONE || nLogMask < severity))
|
||||
{
|
||||
fwrite(strOutput,strlen(strOutput),1,pFile);
|
||||
}
|
||||
|
||||
// print as standard output
|
||||
if (!(nPrintMask == eLOG_NONE || nPrintMask < severity))
|
||||
{
|
||||
printf("%s", strOutput);
|
||||
}
|
||||
|
||||
// flush file buffer if error is high severity
|
||||
if (severity <= nFlushMask)
|
||||
fflush(pFile);
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
void CAutoLog::Archive(void)
|
||||
//-------------------------------------
|
||||
{
|
||||
if( pFile == (FILE *)-1 || pFile == NULL)
|
||||
{
|
||||
//fprintf(stderr,"CAutoLog::Archive called with no file open!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// check to see if it's time to archive
|
||||
time_t t;
|
||||
time(&t);
|
||||
struct tm *ptm = localtime(&t);
|
||||
if (ptm->tm_yday == nTodaysDayOfYear)
|
||||
{
|
||||
return; // nope, not time to archive
|
||||
}
|
||||
nTodaysDayOfYear = ptm->tm_yday;
|
||||
|
||||
char strPath[1024];
|
||||
char strCurrent[1024];
|
||||
char strTime[128];
|
||||
char * pCurrent;
|
||||
|
||||
#ifdef WIN32
|
||||
char curdir[128];
|
||||
#else
|
||||
struct stat SS;
|
||||
#endif
|
||||
|
||||
strftime(strTime, sizeof(strTime), "%m%d%Y", localtime(&t) ); // numerical time e.g. 041698
|
||||
|
||||
strcpy(strCurrent,pFilename);
|
||||
pCurrent = strrchr(strCurrent, SLASHCHAR[0]);
|
||||
if (pCurrent != NULL)
|
||||
*pCurrent = 0;
|
||||
else
|
||||
sprintf(strCurrent,".");
|
||||
|
||||
sprintf(strPath,"%s"SLASHCHAR"%s", strCurrent, strTime); // logs/041698
|
||||
|
||||
#ifdef WIN32
|
||||
// remember current directory
|
||||
if( _getcwd(curdir,sizeof(curdir)) == NULL )
|
||||
{
|
||||
fprintf(stderr,"CAutoLog::Archive failed to get current directory!\n");
|
||||
return; // error, can't proceed
|
||||
}
|
||||
|
||||
if (_chdir(strPath))
|
||||
{
|
||||
// failed to find the directory, so we must create it
|
||||
if (_mkdir(strPath))
|
||||
{
|
||||
fprintf(stderr,"CAutoLog::Archive failed to make directory: %s\n", strPath);
|
||||
return; // error, can't proceed
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// found the directory, but we don't want to be there, so go back
|
||||
_chdir(curdir);
|
||||
}
|
||||
#else
|
||||
// see if directory exists
|
||||
if (stat(strPath,&SS))
|
||||
{
|
||||
// create directory
|
||||
if (mkdir(strPath,0777))
|
||||
{
|
||||
fprintf(stderr,"CAutoLog::Archive failed to make directory: %s\n", strPath);
|
||||
return; // error, can't proceed
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pCurrent = strrchr(pFilename, SLASHCHAR[0]);
|
||||
if (pCurrent == NULL)
|
||||
pCurrent = pFilename;
|
||||
else
|
||||
pCurrent++;
|
||||
|
||||
sprintf(strCurrent,"%s"SLASHCHAR"%s",strPath,pCurrent);
|
||||
|
||||
fflush(pFile);
|
||||
fclose(pFile);
|
||||
|
||||
rename(pFilename,strCurrent);
|
||||
|
||||
pFile = fopen(pFilename,"w+");
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
#ifndef _AUTOLOG_H
|
||||
#define _AUTOLOG_H
|
||||
|
||||
#pragma warning (disable : 4786)
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
class CAutoLog
|
||||
{
|
||||
public:
|
||||
enum eLogLevel {
|
||||
eLOG_NONE = 0, // log entries are discarded
|
||||
eLOG_ERROR = 1, // log errors only
|
||||
eLOG_ALERT = 2, // log alerts and errors only
|
||||
eLOG_NORMAL = 3, // log all normal events, no debug
|
||||
eLOG_DEBUG = 4 // log everything
|
||||
};
|
||||
|
||||
// Global setting for all AutoLog instances for this application. Can be set on the fly. Default is eLOG_NORMAL.
|
||||
void SetLogLevel(eLogLevel loglevel);
|
||||
|
||||
// Global setting for all AutoLog instances for this application. Can be set on the fly. Default is eLOG_ERROR.
|
||||
void SetPrintLevel(eLogLevel printlevel);
|
||||
|
||||
// Global setting for all AutoLog instances for this application. Can be set on the fly. Default is eLOG_ERROR.
|
||||
void SetFlushLevel(eLogLevel flushlevel);
|
||||
|
||||
// constructor, no file loaded
|
||||
CAutoLog();
|
||||
|
||||
// version of constructor that calls Open(file)
|
||||
CAutoLog(const char * file);
|
||||
|
||||
// destructor, will close file if opened
|
||||
~CAutoLog();
|
||||
|
||||
// Open log file. If a file is already open, function will fail.
|
||||
// returns true if no error
|
||||
bool Open(const char * file);
|
||||
|
||||
// Close log file if opened.
|
||||
void Close(void);
|
||||
|
||||
// Make an entry in the log. Format and variable arguments are identical to printf.
|
||||
// severity will be compared to master log level to determine if the log entry will be made
|
||||
// severity will be compared to master print level to determine if the log entry will be printed to stdout
|
||||
void Log(eLogLevel severity, char * format, ...);
|
||||
|
||||
// Equivalent to the above with the approriate severity argument
|
||||
void LogError(char * format, ...);
|
||||
void LogAlert(char * format, ...);
|
||||
void Log(char * format, ...);
|
||||
void LogDebug(char * format, ...);
|
||||
|
||||
private:
|
||||
FILE * pFile; // current log file opened
|
||||
char * pFilename; // current log file opened
|
||||
int nTodaysDayOfYear; // remember the current day to detect change of day
|
||||
void Archive(void); // archives current log
|
||||
|
||||
static eLogLevel nLogMask; // master severity level
|
||||
static eLogLevel nPrintMask; // master severity level
|
||||
static eLogLevel nFlushMask; // master severity level
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
inline void CAutoLog::SetLogLevel(eLogLevel loglevel)
|
||||
{
|
||||
nLogMask = loglevel;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
inline void CAutoLog::SetPrintLevel(eLogLevel printlevel)
|
||||
{
|
||||
nPrintMask = printlevel;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
inline void CAutoLog::SetFlushLevel(eLogLevel flushlevel)
|
||||
{
|
||||
nFlushMask = flushlevel;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
inline CAutoLog::CAutoLog()
|
||||
{
|
||||
pFilename = NULL;
|
||||
pFile = (FILE *)-1;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
inline CAutoLog::CAutoLog(const char * file)
|
||||
{
|
||||
pFilename = NULL;
|
||||
pFile = (FILE *)-1;
|
||||
Open(file);
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
inline CAutoLog::~CAutoLog()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
#include "Base.h"
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
////////////////////////////////////////
|
||||
// Base.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Provide a single header file that may be used to include all
|
||||
// Base library header files.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef _BASEPCH_H
|
||||
#define _BASEPCH_H
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32/Platform.h"
|
||||
#include "win32/Types.h"
|
||||
#include "win32/Mutex.h"
|
||||
#include "win32/Event.h"
|
||||
#include "win32/Thread.h"
|
||||
#include "Logger.h"
|
||||
#include "Config.h"
|
||||
#include "ScopeLock.h"
|
||||
#include "Statistics.h"
|
||||
#include "TemplateObjectAllocator.h"
|
||||
#include "BlockAllocator.h"
|
||||
|
||||
#elif linux
|
||||
|
||||
#include "linux/Platform.h"
|
||||
#include "linux/Types.h"
|
||||
#include "linux/Mutex.h"
|
||||
#include "linux/Event.h"
|
||||
#include "linux/Thread.h"
|
||||
#include "Logger.h"
|
||||
#include "Config.h"
|
||||
#include "ScopeLock.h"
|
||||
#include "Statistics.h"
|
||||
#include "TemplateObjectAllocator.h"
|
||||
#include "BlockAllocator.h"
|
||||
|
||||
#elif sparc
|
||||
|
||||
#include "solaris/Platform.h"
|
||||
#include "solaris/Types.h"
|
||||
#include "solaris/Mutex.h"
|
||||
#include "solaris/Event.h"
|
||||
#include "solaris/Thread.h"
|
||||
#include "Logger.h"
|
||||
#include "Config.h"
|
||||
#include "ScopeLock.h"
|
||||
#include "Statistics.h"
|
||||
#include "TemplateObjectAllocator.h"
|
||||
#include "BlockAllocator.h"
|
||||
|
||||
#else
|
||||
|
||||
#error Base.h: Undefine platform type
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _BASEPCH_H
|
||||
@@ -0,0 +1,30 @@
|
||||
#if !defined (BLOCKALLOCATOR_H_)
|
||||
#define BLOCKALLOCATOR_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
class BlockAllocator
|
||||
{
|
||||
public:
|
||||
BlockAllocator();
|
||||
~BlockAllocator();
|
||||
void *getBlock(unsigned accum);
|
||||
void returnBlock(unsigned *handle);
|
||||
|
||||
private:
|
||||
unsigned *m_blocks[31];
|
||||
};
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
|
||||
|
||||
set(SHARED_SOURCES
|
||||
Archive.cpp
|
||||
Archive.h
|
||||
AutoLog.cpp
|
||||
AutoLog.h
|
||||
Base.cpp
|
||||
Base.h
|
||||
BlockAllocator.h
|
||||
Config.cpp
|
||||
Config.h
|
||||
Event.h
|
||||
Logger.h
|
||||
MD5.cpp
|
||||
MD5.h
|
||||
Mutex.h
|
||||
Platform.h
|
||||
ScopeLock.cpp
|
||||
ScopeLock.h
|
||||
Statistics.cpp
|
||||
Statistics.h
|
||||
TemplateBlockAllocator.h
|
||||
TemplateObjectAllocator.h
|
||||
Thread.h
|
||||
Types.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(PLATFORM_SOURCES
|
||||
win32/Archive.h
|
||||
win32/BlockAllocator.cpp
|
||||
win32/Event.cpp
|
||||
win32/Event.h
|
||||
win32/File.cpp
|
||||
win32/File.h
|
||||
win32/Logger.cpp
|
||||
win32/Mutex.cpp
|
||||
win32/Mutex.h
|
||||
win32/Platform.cpp
|
||||
win32/Platform.h
|
||||
win32/Thread.cpp
|
||||
win32/Thread.h
|
||||
win32/Types.h
|
||||
)
|
||||
|
||||
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32)
|
||||
else()
|
||||
set(PLATFORM_SOURCES
|
||||
linux/Archive.h
|
||||
linux/BlockAllocator.h
|
||||
linux/Event.cpp
|
||||
linux/Event.h
|
||||
linux/Logger.cpp
|
||||
linux/Mutex.cpp
|
||||
linux/Mutex.h
|
||||
linux/Platform.cpp
|
||||
linux/Platform.h
|
||||
linux/Thread.cpp
|
||||
linux/Thread.h
|
||||
linux/Types.h
|
||||
)
|
||||
|
||||
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/linux)
|
||||
endif()
|
||||
|
||||
add_library(Base STATIC
|
||||
${SHARED_SOURCES}
|
||||
${PLATFORM_SOURCES}
|
||||
)
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
#include "Config.h"
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include <stdio.h>
|
||||
//#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
//-----------------------------------
|
||||
/// Read the config file into memory
|
||||
/// Returns true for success
|
||||
bool CConfig::LoadFile(char * file)
|
||||
//-----------------------------------
|
||||
{
|
||||
char ch;
|
||||
FILE * fp;
|
||||
|
||||
UnloadFile();
|
||||
|
||||
// open file
|
||||
fp = fopen(file, "r");
|
||||
if (fp == NULL || fp == (FILE *)-1)
|
||||
{
|
||||
//fprintf(stderr,"Failed to open config file %s!",file);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get length of file
|
||||
fseek(fp,0,SEEK_END);
|
||||
long length = ftell(fp);
|
||||
rewind(fp);
|
||||
|
||||
// allocate buffer
|
||||
pConfig = new char[length + 1];
|
||||
|
||||
if (pConfig == NULL)
|
||||
{
|
||||
fclose(fp);
|
||||
fprintf(stderr,"Failed to alloc config buffer length %d",(int32)length);
|
||||
return false;
|
||||
}
|
||||
memset(pConfig,0,length);
|
||||
|
||||
// read data, stripping comments
|
||||
int i = 0;
|
||||
while (i < length)
|
||||
{
|
||||
ch = fgetc(fp);
|
||||
if (feof(fp))
|
||||
break;
|
||||
if (ch == '#')
|
||||
{
|
||||
while (ch != 10 && !feof (fp))
|
||||
{
|
||||
ch = fgetc(fp);
|
||||
}
|
||||
}
|
||||
pConfig[i++] = ch;
|
||||
}
|
||||
pConfig[i] = 0; // mark end of file buffer
|
||||
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
/// remove the config file from memory
|
||||
void CConfig::UnloadFile(void)
|
||||
//-----------------------------------
|
||||
{
|
||||
if (pConfig)
|
||||
delete[] pConfig;
|
||||
pConfig = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
/// finds a key of the config in memory
|
||||
// key argument is case-insensitive, but must be upper case in config file
|
||||
// Returns true for success (passing NULL is a special case returned as success)
|
||||
bool CConfig::FindKey(char *key)
|
||||
//-----------------------------------
|
||||
{
|
||||
if (pConfig == NULL)
|
||||
return false;
|
||||
|
||||
// special case...continue with existing key
|
||||
if (key == NULL)
|
||||
return true;
|
||||
|
||||
// form the search key
|
||||
strcpy(strBuffer, "[");
|
||||
strcat(strBuffer, key);
|
||||
strcat(strBuffer,"]");
|
||||
_strupr(strBuffer); // keywords must be upper case
|
||||
|
||||
// find the key heading
|
||||
pCursor = strstr(pConfig,strBuffer);
|
||||
if (pCursor==NULL)
|
||||
return false;
|
||||
|
||||
// find the closing bracket of key heading
|
||||
pCursor = strchr(pCursor,']');
|
||||
if (pCursor==NULL)
|
||||
return false;
|
||||
pCursor++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
/// extract a number from the config string
|
||||
// pass the key to find the first number in the list, else NULL to find the next number in the list
|
||||
// returns 0 if no number is found, else returns the number
|
||||
long CConfig::GetLong(char *key)
|
||||
//-----------------------------------
|
||||
{
|
||||
if (!FindKey(key))
|
||||
return 0;
|
||||
|
||||
|
||||
// look for start of number or end of key
|
||||
while (*pCursor && !isdigit(*pCursor) && *pCursor != '[')
|
||||
pCursor++;
|
||||
|
||||
int c = 0;
|
||||
while (*pCursor && isdigit(*pCursor) && c < (int)sizeof(strBuffer))
|
||||
strBuffer[c++] = *(pCursor++);
|
||||
strBuffer[c] = '\0';
|
||||
|
||||
return atol(strBuffer);
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
/// extract string (in double-quotes) from the list.
|
||||
// pass the key to find the first string in the list, else NULL to find the next string in the list
|
||||
// returns NULL if no string found, else returns a temporary copy of the string (without quotes)
|
||||
char * CConfig::GetString(char *key)
|
||||
//-----------------------------------
|
||||
{
|
||||
if (!FindKey(key))
|
||||
return NULL;
|
||||
|
||||
|
||||
// look for start of string or end of key
|
||||
while (*pCursor && *pCursor != '"' && *pCursor != '[')
|
||||
pCursor++;
|
||||
if (*(pCursor++) != '"')
|
||||
return NULL;
|
||||
|
||||
// until closing quote
|
||||
int c = 0;
|
||||
while (*pCursor && c < (int)sizeof(strBuffer))
|
||||
{
|
||||
strBuffer[c++] = *pCursor; // extract string
|
||||
if (*pCursor++ == '"')
|
||||
{
|
||||
strBuffer[--c] = '\0';
|
||||
return strBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
; Example syntax of a config file.
|
||||
# This is a comment to end of line.
|
||||
; This is a comment too....both comments are to end of line
|
||||
[KEYWORD] ; all keywords must be upper case to be recognized
|
||||
|
||||
; single number, with code example
|
||||
# long number = config.GetLong("PORT");
|
||||
[PORT] 5999 ; common single-value case
|
||||
|
||||
; list of strings, with code example
|
||||
# config.FindKey("NUMBERS");
|
||||
# while (number = config.GetLong(NULL))
|
||||
# YourHandleNumber(number);
|
||||
[NUMBERS] 100
|
||||
200, 300 ; formatting is very flexible as long as numbers are delimited by non-numbers
|
||||
400 500
|
||||
600 ; This is badly formatted for example purposes only
|
||||
|
||||
; single string, with code example
|
||||
# strcpy(mystring, config.GetString("STRING"));
|
||||
[STRING] "This is a string"
|
||||
|
||||
; list of strings, with code example
|
||||
# config.FindKey("HOSTS");
|
||||
# while (string = config.GetString(NULL))
|
||||
# YourHandleString(string);
|
||||
[HOSTS]
|
||||
"206.19.151.173:5999"
|
||||
"206.19.151.173:5998"
|
||||
"206.19.151.173:2000"
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
class CConfig
|
||||
{
|
||||
public:
|
||||
// constructor, no file loaded
|
||||
CConfig();
|
||||
|
||||
// version of constructor that calls LoadFile(file)
|
||||
CConfig(char * file);
|
||||
|
||||
// destructor, will delete all buffers
|
||||
~CConfig();
|
||||
|
||||
// copy text config file into memory. Required to use extraction methods.
|
||||
// if called with a different filename, existing file will be discarded.
|
||||
bool LoadFile(char * file);
|
||||
|
||||
// delete memory buffer of file
|
||||
void UnloadFile();
|
||||
|
||||
// set cursor in file based on key name. Alternate way to select first key when extracting lists.
|
||||
// returns TRUE if key is found.
|
||||
bool FindKey(char *key);
|
||||
|
||||
// extract string from config. If key is NULL, extract next string in list, else extract first string.
|
||||
// if key was not found, returns NULL
|
||||
char * GetString(char *key = NULL);
|
||||
|
||||
// extract number from config. If key is NULL, extract next number in list, else extract first number.
|
||||
// if key was not found, returns 0
|
||||
long GetLong(char *key = NULL); // extract number from config.
|
||||
|
||||
// indicate if config file has been loaded
|
||||
inline bool FileLoaded() { return pConfig == NULL ? false : true; }
|
||||
|
||||
private:
|
||||
char * pConfig; // pointer to file memory
|
||||
char * pCursor; // current cursor into file memory
|
||||
char strBuffer[8196]; // buffer for GetString return pointer -- reused
|
||||
};
|
||||
|
||||
inline CConfig::CConfig()
|
||||
{
|
||||
pConfig = NULL;
|
||||
pCursor = NULL;
|
||||
}
|
||||
|
||||
inline CConfig::CConfig(char * file)
|
||||
{
|
||||
pConfig = NULL;
|
||||
pCursor = NULL;
|
||||
LoadFile(file);
|
||||
}
|
||||
|
||||
inline CConfig::~CConfig()
|
||||
{
|
||||
UnloadFile();
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef BASE_EVENT_H
|
||||
#define BASE_EVENT_H
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32/Event.h"
|
||||
|
||||
#elif linux
|
||||
|
||||
#include "linux/Event.h"
|
||||
|
||||
#elif sparc
|
||||
|
||||
#include "solaris/Event.h"
|
||||
|
||||
#else
|
||||
|
||||
#error /Base/Event.h: Undefine platform type
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BASE_EVENT_H
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef __LOGGER_H__
|
||||
#define __LOGGER_H__
|
||||
|
||||
// make the compiler shut up
|
||||
#pragma warning (disable : 4786)
|
||||
|
||||
#include "Platform.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "Mutex.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
#define LOG_ALWAYS -1
|
||||
#define LOG_FILEONLY -2
|
||||
|
||||
struct LogInfo
|
||||
{
|
||||
FILE *file;
|
||||
unsigned used;
|
||||
tm ts;
|
||||
time_t last;
|
||||
unsigned max;
|
||||
int level;
|
||||
std::string filename;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
Logger(const char *prefix = "logs", int level = 10, unsigned size = 0, bool rollDate = true);
|
||||
~Logger();
|
||||
void addLog(const char *id, unsigned logenum, int level, unsigned size);
|
||||
void addLog(const char *id, unsigned logenum);
|
||||
void removeLog(unsigned logenum);
|
||||
void updateLog(unsigned logenum, int level, unsigned size);
|
||||
void logSimple(unsigned logenum, int level, const char *message);
|
||||
void log(unsigned logenum, int level, const char *message, ...);
|
||||
void flushAll();
|
||||
void flush(unsigned logenum);
|
||||
private:
|
||||
void rollDate(time_t now);
|
||||
void cmkdir(const char *dir, int mode);
|
||||
unsigned m_defaultLevel;
|
||||
unsigned m_defaultSize;
|
||||
std::string m_lastDateText;
|
||||
tm m_lastDateTime;
|
||||
std::map<unsigned, LogInfo *> m_logTable;
|
||||
std::string m_logPrefix;
|
||||
std::string m_dirPrefix;
|
||||
#if defined (_REENTRANT) || defined (_MT)
|
||||
Base::CMutex rLock;
|
||||
#endif
|
||||
bool m_rollDate;
|
||||
};
|
||||
|
||||
extern const char file_sep;
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+325
@@ -0,0 +1,325 @@
|
||||
// MD5.cpp: implementation of the MD5 class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "MD5.h"
|
||||
#include "Types.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
MD5::State::State() :
|
||||
state(4,0),
|
||||
count(2,0),
|
||||
buffer(64,0)
|
||||
{
|
||||
state[0] = 0x67452301;
|
||||
state[1] = 0xefcdab89;
|
||||
state[2] = 0x98badcfe;
|
||||
state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
static char const init[64] =
|
||||
{
|
||||
-128, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
vector<char> MD5::padding(init,init+sizeof(init)/sizeof(init[0]));
|
||||
|
||||
MD5::MD5()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
MD5::MD5(const string & input)
|
||||
{
|
||||
Init();
|
||||
Update(input);
|
||||
}
|
||||
|
||||
vector<int> MD5::Decode(vector<char> achar0, int i, int j)
|
||||
{
|
||||
vector<int> ai(16,0);
|
||||
int l;
|
||||
int k = l = 0;
|
||||
for(; l < i; l += 4)
|
||||
{
|
||||
ai[k] = achar0[l + j] & 0xff | (achar0[l + 1 + j] & 0xff) << 8 | (achar0[l + 2 + j] & 0xff) << 16 | (achar0[l + 3 + j] & 0xff) << 24;
|
||||
k++;
|
||||
}
|
||||
|
||||
return ai;
|
||||
}
|
||||
|
||||
vector<char> MD5::Encode(vector<int> ai, int i)
|
||||
{
|
||||
vector<char> achar0(i,0);
|
||||
int k;
|
||||
int j = k = 0;
|
||||
for(; k < i; k += 4){
|
||||
achar0[k] = (char)(ai[j] & 0xff);
|
||||
achar0[k + 1] = (char)(ai[j] >> 8 & 0xff);
|
||||
achar0[k + 2] = (char)(ai[j] >> 16 & 0xff);
|
||||
achar0[k + 3] = (char)(ai[j] >> 24 & 0xff);
|
||||
j++;
|
||||
}
|
||||
|
||||
return achar0;
|
||||
}
|
||||
|
||||
int MD5::FF(int i, int j, int k, int l, int i1, int j1, int k1)
|
||||
{
|
||||
i = uadd(i, j & k | ~j & l, i1, k1);
|
||||
return uadd(rotate_left(i, j1), j);
|
||||
}
|
||||
|
||||
vector<char> MD5::Final()
|
||||
{
|
||||
if (finalsNull)
|
||||
{
|
||||
State &state1 = state;
|
||||
vector<char> achar0 = Encode(state1.count, 8);
|
||||
int i = state1.count[0] >> 3 & 0x3f;
|
||||
int j = i >= 56 ? 120 - i : 56 - i;
|
||||
Update(state1, padding, 0, j);
|
||||
Update(state1, achar0, 0, 8);
|
||||
finals = state1;
|
||||
finalsNull = false;
|
||||
}
|
||||
return Encode(finals.state, 16);
|
||||
}
|
||||
|
||||
int MD5::GG(int i, int j, int k, int l, int i1, int j1, int k1)
|
||||
{
|
||||
i = uadd(i, j & l | k & ~l, i1, k1);
|
||||
return uadd(rotate_left(i, j1), j);
|
||||
}
|
||||
|
||||
int MD5::HH(int i, int j, int k, int l, int i1, int j1, int k1)
|
||||
{
|
||||
i = uadd(i, j ^ k ^ l, i1, k1);
|
||||
return uadd(rotate_left(i, j1), j);
|
||||
}
|
||||
|
||||
int MD5::II(int i, int j, int k, int l, int i1, int j1, int k1)
|
||||
{
|
||||
i = uadd(i, k ^ (j | ~l), i1, k1);
|
||||
return uadd(rotate_left(i, j1), j);
|
||||
}
|
||||
|
||||
void MD5::Init()
|
||||
{
|
||||
if (padding.size() == 0)
|
||||
{
|
||||
padding.resize(64,0);
|
||||
padding[0] = -128;
|
||||
}
|
||||
finalsNull = true;
|
||||
}
|
||||
|
||||
void MD5::Transform(State & state1, vector<char> achar0, int i)
|
||||
{
|
||||
int j = state1.state[0];
|
||||
int k = state1.state[1];
|
||||
int l = state1.state[2];
|
||||
int i1 = state1.state[3];
|
||||
vector<int> ai = Decode(achar0, 64, i);
|
||||
j = FF(j, k, l, i1, ai[0], 7, 0xd76aa478);
|
||||
i1 = FF(i1, j, k, l, ai[1], 12, 0xe8c7b756);
|
||||
l = FF(l, i1, j, k, ai[2], 17, 0x242070db);
|
||||
k = FF(k, l, i1, j, ai[3], 22, 0xc1bdceee);
|
||||
j = FF(j, k, l, i1, ai[4], 7, 0xf57c0faf);
|
||||
i1 = FF(i1, j, k, l, ai[5], 12, 0x4787c62a);
|
||||
l = FF(l, i1, j, k, ai[6], 17, 0xa8304613);
|
||||
k = FF(k, l, i1, j, ai[7], 22, 0xfd469501);
|
||||
j = FF(j, k, l, i1, ai[8], 7, 0x698098d8);
|
||||
i1 = FF(i1, j, k, l, ai[9], 12, 0x8b44f7af);
|
||||
l = FF(l, i1, j, k, ai[10], 17, -42063);
|
||||
k = FF(k, l, i1, j, ai[11], 22, 0x895cd7be);
|
||||
j = FF(j, k, l, i1, ai[12], 7, 0x6b901122);
|
||||
i1 = FF(i1, j, k, l, ai[13], 12, 0xfd987193);
|
||||
l = FF(l, i1, j, k, ai[14], 17, 0xa679438e);
|
||||
k = FF(k, l, i1, j, ai[15], 22, 0x49b40821);
|
||||
j = GG(j, k, l, i1, ai[1], 5, 0xf61e2562);
|
||||
i1 = GG(i1, j, k, l, ai[6], 9, 0xc040b340);
|
||||
l = GG(l, i1, j, k, ai[11], 14, 0x265e5a51);
|
||||
k = GG(k, l, i1, j, ai[0], 20, 0xe9b6c7aa);
|
||||
j = GG(j, k, l, i1, ai[5], 5, 0xd62f105d);
|
||||
i1 = GG(i1, j, k, l, ai[10], 9, 0x2441453);
|
||||
l = GG(l, i1, j, k, ai[15], 14, 0xd8a1e681);
|
||||
k = GG(k, l, i1, j, ai[4], 20, 0xe7d3fbc8);
|
||||
j = GG(j, k, l, i1, ai[9], 5, 0x21e1cde6);
|
||||
i1 = GG(i1, j, k, l, ai[14], 9, 0xc33707d6);
|
||||
l = GG(l, i1, j, k, ai[3], 14, 0xf4d50d87);
|
||||
k = GG(k, l, i1, j, ai[8], 20, 0x455a14ed);
|
||||
j = GG(j, k, l, i1, ai[13], 5, 0xa9e3e905);
|
||||
i1 = GG(i1, j, k, l, ai[2], 9, 0xfcefa3f8);
|
||||
l = GG(l, i1, j, k, ai[7], 14, 0x676f02d9);
|
||||
k = GG(k, l, i1, j, ai[12], 20, 0x8d2a4c8a);
|
||||
j = HH(j, k, l, i1, ai[5], 4, 0xfffa3942);
|
||||
i1 = HH(i1, j, k, l, ai[8], 11, 0x8771f681);
|
||||
l = HH(l, i1, j, k, ai[11], 16, 0x6d9d6122);
|
||||
k = HH(k, l, i1, j, ai[14], 23, 0xfde5380c);
|
||||
j = HH(j, k, l, i1, ai[1], 4, 0xa4beea44);
|
||||
i1 = HH(i1, j, k, l, ai[4], 11, 0x4bdecfa9);
|
||||
l = HH(l, i1, j, k, ai[7], 16, 0xf6bb4b60);
|
||||
k = HH(k, l, i1, j, ai[10], 23, 0xbebfbc70);
|
||||
j = HH(j, k, l, i1, ai[13], 4, 0x289b7ec6);
|
||||
i1 = HH(i1, j, k, l, ai[0], 11, 0xeaa127fa);
|
||||
l = HH(l, i1, j, k, ai[3], 16, 0xd4ef3085);
|
||||
k = HH(k, l, i1, j, ai[6], 23, 0x4881d05);
|
||||
j = HH(j, k, l, i1, ai[9], 4, 0xd9d4d039);
|
||||
i1 = HH(i1, j, k, l, ai[12], 11, 0xe6db99e5);
|
||||
l = HH(l, i1, j, k, ai[15], 16, 0x1fa27cf8);
|
||||
k = HH(k, l, i1, j, ai[2], 23, 0xc4ac5665);
|
||||
j = II(j, k, l, i1, ai[0], 6, 0xf4292244);
|
||||
i1 = II(i1, j, k, l, ai[7], 10, 0x432aff97);
|
||||
l = II(l, i1, j, k, ai[14], 15, 0xab9423a7);
|
||||
k = II(k, l, i1, j, ai[5], 21, 0xfc93a039);
|
||||
j = II(j, k, l, i1, ai[12], 6, 0x655b59c3);
|
||||
i1 = II(i1, j, k, l, ai[3], 10, 0x8f0ccc92);
|
||||
l = II(l, i1, j, k, ai[10], 15, 0xffeff47d);
|
||||
k = II(k, l, i1, j, ai[1], 21, 0x85845dd1);
|
||||
j = II(j, k, l, i1, ai[8], 6, 0x6fa87e4f);
|
||||
i1 = II(i1, j, k, l, ai[15], 10, 0xfe2ce6e0);
|
||||
l = II(l, i1, j, k, ai[6], 15, 0xa3014314);
|
||||
k = II(k, l, i1, j, ai[13], 21, 0x4e0811a1);
|
||||
j = II(j, k, l, i1, ai[4], 6, 0xf7537e82);
|
||||
i1 = II(i1, j, k, l, ai[11], 10, 0xbd3af235);
|
||||
l = II(l, i1, j, k, ai[2], 15, 0x2ad7d2bb);
|
||||
k = II(k, l, i1, j, ai[9], 21, 0xeb86d391);
|
||||
state1.state[0] += j;
|
||||
state1.state[1] += k;
|
||||
state1.state[2] += l;
|
||||
state1.state[3] += i1;
|
||||
}
|
||||
|
||||
void MD5::Update(char char0)
|
||||
{
|
||||
vector<char> achar0(1,0);
|
||||
achar0[0] = char0;
|
||||
Update(achar0, 1);
|
||||
}
|
||||
|
||||
void MD5::Update(State & state1, vector<char> achar0, int i, int j)
|
||||
{
|
||||
finalsNull = true;
|
||||
if (j - i > (int)achar0.size())
|
||||
j = achar0.size() - i;
|
||||
int k = state1.count[0] >> 3 & 0x3f;
|
||||
if ((state1.count[0] += j << 3) < j << 3)
|
||||
state1.count[1]++;
|
||||
state1.count[1] += j >> 29;
|
||||
int l = 64 - k;
|
||||
int j1;
|
||||
if(j >= l)
|
||||
{
|
||||
for(int i1 = 0; i1 < l; i1++)
|
||||
state1.buffer[i1 + k] = achar0[i1 + i];
|
||||
|
||||
Transform(state1, state1.buffer, 0);
|
||||
for(j1 = l; j1 + 63 < j; j1 += 64)
|
||||
Transform(state1, achar0, j1);
|
||||
|
||||
k = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
j1 = 0;
|
||||
}
|
||||
if (j1 < j)
|
||||
{
|
||||
int k1 = j1;
|
||||
for(; j1 < j; j1++)
|
||||
state1.buffer[(k + j1) - k1] = achar0[j1 + i];
|
||||
}
|
||||
}
|
||||
|
||||
void MD5::Update(string s)
|
||||
{
|
||||
vector<char> achar(s.size(),0);
|
||||
for (int i=0; i<(int)s.size(); i++)
|
||||
achar[i] = s[i];
|
||||
Update( achar, achar.size() );
|
||||
}
|
||||
|
||||
void MD5::Update(vector<char> achar0)
|
||||
{
|
||||
Update(achar0, 0, achar0.size());
|
||||
}
|
||||
|
||||
void MD5::Update(vector<char> achar0, int i)
|
||||
{
|
||||
Update(state, achar0, 0, i);
|
||||
}
|
||||
|
||||
void MD5::Update(vector<char> achar0, int i, int j)
|
||||
{
|
||||
Update(state, achar0, i, j);
|
||||
}
|
||||
|
||||
string MD5::asHex()
|
||||
{
|
||||
return asHex(Final());
|
||||
}
|
||||
|
||||
string MD5::asHex(vector<char> achar0)
|
||||
{
|
||||
const string hex = "0123456789abcdef";
|
||||
|
||||
string stringbuffer;
|
||||
for (int i = 0; i < (int)achar0.size(); i++)
|
||||
{
|
||||
stringbuffer += hex.substr((achar0[i] >> 4) & 0x0f,1);
|
||||
stringbuffer += hex.substr(achar0[i] & 0x0f,1);
|
||||
}
|
||||
|
||||
return stringbuffer;
|
||||
}
|
||||
|
||||
int MD5::rotate_left(int i, int j)
|
||||
{
|
||||
unsigned i1 = i;
|
||||
unsigned j1 = j;
|
||||
return i1 << j1 | i1 >> (32 - j1);
|
||||
}
|
||||
|
||||
int MD5::uadd(int i, int j)
|
||||
{
|
||||
int64 l = (int64)i & 0x0ffffffffL;
|
||||
int64 l1 = (int64)j & 0x0ffffffffL;
|
||||
l += l1;
|
||||
return (int)(l & 0x0ffffffffL);
|
||||
}
|
||||
|
||||
int MD5::uadd(int i, int j, int k)
|
||||
{
|
||||
return uadd(uadd(i, j), k);
|
||||
}
|
||||
|
||||
int MD5::uadd(int i, int j, int k, int l)
|
||||
{
|
||||
return uadd(uadd(i, j, k), l);
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
// MD5.h: interface for the MD5 class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MD5_H
|
||||
#define MD5_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
class MD5
|
||||
{
|
||||
struct State
|
||||
{
|
||||
State();
|
||||
|
||||
std::vector<int> state;
|
||||
std::vector<int> count;
|
||||
std::vector<char> buffer;
|
||||
};
|
||||
|
||||
public:
|
||||
MD5::MD5();
|
||||
MD5(const std::string &input);
|
||||
|
||||
void Init();
|
||||
std::vector<char> Final();
|
||||
void Update(char char0);
|
||||
void Update(State & state1, std::vector<char> achar0, int i, int j);
|
||||
void Update(std::string s);
|
||||
void Update(std::vector<char> achar0);
|
||||
void Update(std::vector<char> achar0, int i);
|
||||
void Update(std::vector<char> achar0, int i, int j);
|
||||
std::string asHex();
|
||||
static std::string asHex(std::vector<char> achar0);
|
||||
|
||||
private:
|
||||
std::vector<int> Decode(std::vector<char> achar0, int i, int j);
|
||||
std::vector<char> Encode(std::vector<int> ai, int i);
|
||||
int FF(int i, int j, int k, int l, int i1, int j1, int k1);
|
||||
int GG(int i, int j, int k, int l, int i1, int j1, int k1);
|
||||
int HH(int i, int j, int k, int l, int i1, int j1, int k1);
|
||||
int II(int i, int j, int k, int l, int i1, int j1, int k1);
|
||||
void Transform(State & state1, std::vector<char> achar0, int i);
|
||||
int rotate_left(int i, int j);
|
||||
int uadd(int i, int j);
|
||||
int uadd(int i, int j, int k);
|
||||
int uadd(int i, int j, int k, int l);
|
||||
|
||||
private:
|
||||
State state;
|
||||
State finals;
|
||||
bool finalsNull;
|
||||
static std::vector<char> padding;
|
||||
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // MD5_H
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef BASE_MUTEX_H
|
||||
#define BASE_MUTEX_H
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32/Mutex.h"
|
||||
|
||||
#elif linux
|
||||
|
||||
#include "linux/Mutex.h"
|
||||
|
||||
#elif sparc
|
||||
|
||||
#include "solaris/Mutex.h"
|
||||
|
||||
#else
|
||||
|
||||
#error /Base/Mutex.h: Undefine platform type
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BASE_MUTEX_H
|
||||
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
#ifndef BASE_PLATFORM_H
|
||||
#define BASE_PLATFORM_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include "win32/Platform.h"
|
||||
#elif linux
|
||||
#include "linux/Platform.h"
|
||||
#elif sparc
|
||||
#include "solaris/Platform.h"
|
||||
#else
|
||||
#error /Base/Platform.h: Undefine platform type
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
template <class T> inline T rotlFixed(T x, unsigned int y)
|
||||
{
|
||||
assert(y < sizeof(T)*8);
|
||||
return (T)((x<<y) | (x>>(sizeof(T)*8-y)));
|
||||
}
|
||||
|
||||
template <class T> inline T rotrFixed(T x, unsigned int y)
|
||||
{
|
||||
assert(y < sizeof(T)*8);
|
||||
return (x>>y) | (x<<(sizeof(T)*8-y));
|
||||
}
|
||||
|
||||
template <class T> inline T rotlMod(T x, unsigned int y)
|
||||
{
|
||||
y %= sizeof(T)*8;
|
||||
return (x<<y) | (x>>(sizeof(T)*8-y));
|
||||
}
|
||||
|
||||
template <class T> inline T rotrMod(T x, unsigned int y)
|
||||
{
|
||||
y %= sizeof(T)*8;
|
||||
return (x>>y) | (x<<(sizeof(T)*8-y));
|
||||
}
|
||||
|
||||
inline uint16 byteReverse16(void * data)
|
||||
{
|
||||
uint16 value = *static_cast<uint16 *>(data);
|
||||
return *static_cast<uint16 *>(data) = rotlFixed(value, 8U);
|
||||
// return rotlFixed(value, 8U);
|
||||
}
|
||||
|
||||
inline uint32 byteReverse32(void * data)
|
||||
{
|
||||
uint32 value = *static_cast<uint32 *>(data);
|
||||
return *static_cast<uint32 *>(data) = (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
|
||||
// return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
|
||||
}
|
||||
inline uint64 byteReverse64(void * data)
|
||||
{
|
||||
uint64 value = *static_cast<uint64 *>(data);
|
||||
return *static_cast<uint64 *>(data) = (
|
||||
uint64((rotrFixed(uint32(value), 8U) & 0xff00ff00) | (rotlFixed(uint32(value), 8U) & 0x00ff00ff)) << 32) |
|
||||
(rotrFixed(uint32(value>>32), 8U) & 0xff00ff00) | (rotlFixed(uint32(value>>32), 8U) & 0x00ff00ff);
|
||||
// return (uint64(byteReverse(uint32(value))) << 32) | byteReverse(uint32(value>>32));
|
||||
}
|
||||
|
||||
inline uint32 strlen(const unsigned short * string)
|
||||
{
|
||||
if (string == 0)
|
||||
return 0;
|
||||
|
||||
uint32 length=0;
|
||||
while (*(string+length++) != 0);
|
||||
|
||||
return length-1;
|
||||
}
|
||||
|
||||
inline double getTimerLatency(Base::uint64 startTime, Base::uint64 finishTime=0)
|
||||
{
|
||||
Base::uint64 requestAge;
|
||||
Base::uint64 finish = (finishTime ? finishTime : Base::getTimer());
|
||||
if (finish < startTime)
|
||||
requestAge = (0 - 1) - startTime - finish;
|
||||
else
|
||||
requestAge = finish - startTime;
|
||||
|
||||
return (double)((unsigned)(requestAge)) / (double)((unsigned)Base::getTimerFrequency());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // BASE_PLATFORM_H
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "ScopeLock.h"
|
||||
|
||||
#ifdef INCLUDE_SCOPELOCK
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CScopeLock::CScopeLock(CMutex& mutex) :
|
||||
mMutex(&mutex)
|
||||
{
|
||||
mMutex->Lock();
|
||||
}
|
||||
|
||||
CScopeLock::CScopeLock(CScopeLock& lock) :
|
||||
mMutex(lock.mMutex)
|
||||
{
|
||||
mMutex->Lock();
|
||||
}
|
||||
|
||||
CScopeLock::~CScopeLock()
|
||||
{
|
||||
mMutex->Unlock();
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_SCOPELOCK
|
||||
@@ -0,0 +1,40 @@
|
||||
// ScopeLock.h: interface for the CScopeLock class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SCOPELOCK_H
|
||||
#define SCOPELOCK_H
|
||||
|
||||
#if defined _MT || defined _REENTRANT
|
||||
# define INCLUDE_SCOPELOCK
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_SCOPELOCK
|
||||
|
||||
#include "Mutex.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
class CScopeLock
|
||||
{
|
||||
public:
|
||||
CScopeLock(CMutex& mutex);
|
||||
CScopeLock(CScopeLock& lock);
|
||||
virtual ~CScopeLock();
|
||||
|
||||
private:
|
||||
CMutex *mMutex;
|
||||
};
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_SCOPELOCK
|
||||
|
||||
#endif // SCOPELOCK_H
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "Statistics.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CStatisticTimer::CStatisticTimer(bool running) :
|
||||
mTotal(0),
|
||||
mStart(getTimer()),
|
||||
mRunning(running)
|
||||
{
|
||||
}
|
||||
|
||||
double CStatisticTimer::GetTime()
|
||||
{
|
||||
uint64 total = mTotal;
|
||||
|
||||
if (mRunning)
|
||||
total += getTimer()-mStart;
|
||||
|
||||
return (double)((int64)(total/getTimerFrequency()));
|
||||
}
|
||||
|
||||
uint64 CStatisticTimer::GetFraction(uint32 fraction)
|
||||
{
|
||||
uint64 total = mTotal;
|
||||
|
||||
if (mRunning)
|
||||
total += getTimer()-mStart;
|
||||
|
||||
if (fraction == 0)
|
||||
return total;
|
||||
else
|
||||
return total/(getTimerFrequency()/fraction);
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
#ifndef STATISTICS_H
|
||||
#define STATISTICS_H
|
||||
|
||||
#include <time.h>
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
template <class TYPE, uint32 COUNT>
|
||||
class CStatistic
|
||||
{
|
||||
public:
|
||||
CStatistic(uint32 freq=0) :
|
||||
mSampleFrequency(freq),
|
||||
mLastSampleTime(0),
|
||||
mSample(0),
|
||||
mSampleTotal(0),
|
||||
mAggregateTotal(0),
|
||||
mAggregateMaximum(0),
|
||||
mAggregateMinimum(0),
|
||||
mAverageTotal(0),
|
||||
mAverageIndex(0),
|
||||
mAverageCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool Sample(TYPE value)
|
||||
{
|
||||
bool commit = false;
|
||||
|
||||
if (!mLastSampleTime)
|
||||
mLastSampleTime = time(NULL);
|
||||
|
||||
if (!mSampleFrequency || mLastSampleTime + mSampleFrequency < (unsigned)time(NULL))
|
||||
{
|
||||
mSampleTotal++;
|
||||
mAggregateTotal += value;
|
||||
if (value > mAggregateMaximum)
|
||||
mAggregateMaximum = value;
|
||||
if (value < mAggregateMinimum)
|
||||
mAggregateMinimum = value;
|
||||
|
||||
if (mAverageIndex == COUNT)
|
||||
mAverageIndex = 0;
|
||||
if (mAverageCount > COUNT)
|
||||
mAverageTotal -= mAverageData[mAverageIndex];
|
||||
|
||||
mAverageData[mAverageIndex++] = value;
|
||||
mAverageTotal += value;
|
||||
|
||||
if (mAverageCount < COUNT)
|
||||
mAverageCount++;
|
||||
|
||||
commit = true;
|
||||
mSample = 0;
|
||||
}
|
||||
|
||||
mSample += value;
|
||||
|
||||
return commit;
|
||||
}
|
||||
|
||||
TYPE GetSample(uint32 age = 0)
|
||||
{
|
||||
if (age > mAverageCount)
|
||||
return 0;
|
||||
|
||||
uint32 index = mAverageIndex;
|
||||
if (age > index)
|
||||
index = COUNT - (age - index);
|
||||
else
|
||||
index -= age;
|
||||
|
||||
return mAverageData[index];
|
||||
}
|
||||
|
||||
double GetAverage()
|
||||
{
|
||||
return (double)mAverageTotal/mAverageCount;
|
||||
}
|
||||
|
||||
double GetAggregateAverage()
|
||||
{
|
||||
return (double)mAggregateTotal/mSampleTotal;
|
||||
}
|
||||
|
||||
TYPE GetMaximum()
|
||||
{
|
||||
return mAggregateMaximum;
|
||||
}
|
||||
|
||||
TYPE GetMinimum()
|
||||
{
|
||||
return mAggregateMinimum;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 mSampleFrequency;
|
||||
time_t mLastSampleTime;
|
||||
TYPE mSample;
|
||||
uint32 mSampleTotal;
|
||||
TYPE mAggregateTotal;
|
||||
TYPE mAggregateMaximum;
|
||||
TYPE mAggregateMinimum;
|
||||
|
||||
TYPE mAverageData[COUNT];
|
||||
TYPE mAverageTotal;
|
||||
uint32 mAverageIndex;
|
||||
uint32 mAverageCount;
|
||||
};
|
||||
|
||||
class CStatisticTimer
|
||||
{
|
||||
public:
|
||||
CStatisticTimer(bool running = true);
|
||||
|
||||
void Start() { if (mRunning) return; mStart = getTimer(); mRunning = true; }
|
||||
void Stop() { if (!mRunning) return; mTotal += getTimer()-mStart; mRunning = false; }
|
||||
void Reset() { mTotal = 0; mStart = getTimer(); }
|
||||
|
||||
double GetTime();
|
||||
uint64 GetFraction(uint32 fraction=1000);
|
||||
|
||||
private:
|
||||
uint64 mTotal;
|
||||
uint64 mStart;
|
||||
bool mRunning;
|
||||
};
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // STATISTICS_H
|
||||
@@ -0,0 +1,238 @@
|
||||
#ifndef BLOCK_ALLOCATOR_H
|
||||
#define BLOCK_ALLOCATOR_H
|
||||
|
||||
#if defined _MT || defined _REENTRANT
|
||||
# define USE_ALLOCATOR_MUTEX
|
||||
#endif
|
||||
|
||||
|
||||
#include <new>
|
||||
#include "Mutex.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
template<int BLOCK_SIZE>
|
||||
class CBlockAllocator
|
||||
{
|
||||
|
||||
private:
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
Node * mNext;
|
||||
unsigned mBuffer[(BLOCK_SIZE-1)/sizeof(unsigned)+1];
|
||||
};
|
||||
|
||||
public:
|
||||
CBlockAllocator() :
|
||||
mMemoryBlockCount(0),
|
||||
mNodesAllocated(0),
|
||||
mNodesUsed(0),
|
||||
mUnusedList(0)
|
||||
{
|
||||
for (int block=0; block<MAX_BLOCK_COUNT; block++)
|
||||
mMemoryBlock[block] = 0;
|
||||
Allocate();
|
||||
}
|
||||
|
||||
~CBlockAllocator()
|
||||
{
|
||||
for (int block=0; block<MAX_BLOCK_COUNT; block++)
|
||||
delete[] mMemoryBlock[block];
|
||||
}
|
||||
|
||||
void * Allocate()
|
||||
{
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Lock();
|
||||
#endif
|
||||
void * data;
|
||||
|
||||
Node * node = mUnusedList;
|
||||
mUnusedList = node->mNext;
|
||||
node->mNext = (Node *)1;
|
||||
|
||||
data = node->mBuffer;
|
||||
|
||||
mNodesUsed++;
|
||||
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Unlock();
|
||||
#endif
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void Deallocate(void * data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
char * memoryPtr = reinterpret_cast<char *>(data) - sizeof(Node *);
|
||||
Node * node = reinterpret_cast<Node *>(memoryPtr);
|
||||
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Lock();
|
||||
#endif
|
||||
|
||||
node->mNext = mUnusedList;
|
||||
mUnusedList = node;
|
||||
mNodesUsed--;
|
||||
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T> T * Construct(const T & object)
|
||||
{
|
||||
T * objectPtr;
|
||||
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Lock();
|
||||
#endif
|
||||
if (sizeof(T) > BLOCK_SIZE || (!mUnusedList && !Allocate()))
|
||||
{
|
||||
char * memoryPtr = reinterpret_cast<char *>(new unsigned[(sizeof(Node *)+sizeof(T)-1)/sizeof(unsigned)+1]);
|
||||
objectPtr = reinterpret_cast<T *>(memoryPtr+sizeof(Node *));
|
||||
|
||||
*reinterpret_cast<unsigned *>(memoryPtr) = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Node * node = mUnusedList;
|
||||
mUnusedList = node->mNext;
|
||||
node->mNext = (Node *)1;
|
||||
|
||||
objectPtr = reinterpret_cast<T *>(node->mBuffer);
|
||||
|
||||
mNodesUsed++;
|
||||
}
|
||||
|
||||
new (objectPtr) T(object);
|
||||
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Unlock();
|
||||
#endif
|
||||
return objectPtr;
|
||||
}
|
||||
|
||||
template<class T> void Destroy(T * object)
|
||||
{
|
||||
if (!object)
|
||||
return;
|
||||
|
||||
char * memoryPtr = reinterpret_cast<char *>(object) - sizeof(Node *);
|
||||
Node * node = reinterpret_cast<Node *>(memoryPtr);
|
||||
|
||||
object->~T();
|
||||
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Lock();
|
||||
#endif
|
||||
if (node->mNext == 0)
|
||||
delete []memoryPtr;
|
||||
else
|
||||
{
|
||||
node->mNext = mUnusedList;
|
||||
mUnusedList = node;
|
||||
mNodesUsed--;
|
||||
}
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T> T * FastConstruct(const T & object)
|
||||
{
|
||||
T * objectPtr;
|
||||
|
||||
if (sizeof(T) > BLOCK_SIZE || (!mUnusedList && !Allocate()))
|
||||
{
|
||||
char * memoryPtr = reinterpret_cast<char *>(new unsigned[(sizeof(Node *)+sizeof(T)-1)/sizeof(unsigned)+1]);
|
||||
objectPtr = reinterpret_cast<T *>(memoryPtr+sizeof(Node *));
|
||||
|
||||
*reinterpret_cast<unsigned *>(memoryPtr) = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Node * node = mUnusedList;
|
||||
mUnusedList = node->mNext;
|
||||
node->mNext = (Node *)1;
|
||||
|
||||
objectPtr = reinterpret_cast<T *>(node->mBuffer);
|
||||
|
||||
mNodesUsed++;
|
||||
}
|
||||
|
||||
new (objectPtr) T(object);
|
||||
|
||||
return objectPtr;
|
||||
}
|
||||
|
||||
template<class T> void FastDestroy(T * object)
|
||||
{
|
||||
if (!object)
|
||||
return;
|
||||
|
||||
char * memoryPtr = reinterpret_cast<char *>(object) - sizeof(Node *);
|
||||
Node * node = reinterpret_cast<Node *>(memoryPtr);
|
||||
|
||||
object->~T();
|
||||
|
||||
if (node->mNext == 0)
|
||||
delete []memoryPtr;
|
||||
else
|
||||
{
|
||||
node->mNext = mUnusedList;
|
||||
mUnusedList = node;
|
||||
mNodesUsed--;
|
||||
}
|
||||
}
|
||||
|
||||
bool Allocate()
|
||||
{
|
||||
if (mMemoryBlockCount == MAX_BLOCK_COUNT)
|
||||
return false;
|
||||
|
||||
unsigned count = (mNodesAllocated ? mNodesAllocated : 32);
|
||||
|
||||
Node* newMemoryBlock = new Node[count];
|
||||
for (unsigned i=0; i<count-1; i++)
|
||||
newMemoryBlock[i].mNext = &newMemoryBlock[i+1];
|
||||
newMemoryBlock[count-1].mNext = mUnusedList;
|
||||
|
||||
mUnusedList = newMemoryBlock;
|
||||
mMemoryBlock[mMemoryBlockCount++] = newMemoryBlock;
|
||||
mNodesAllocated += count;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
private:
|
||||
enum { MAX_BLOCK_COUNT = 32 };
|
||||
|
||||
void * mMemoryBlock[MAX_BLOCK_COUNT];
|
||||
unsigned mMemoryBlockCount;
|
||||
unsigned mNodesAllocated;
|
||||
unsigned mNodesUsed;
|
||||
Node * mUnusedList;
|
||||
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
Base::CMutex mMutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // BLOCK_ALLOCATOR_H
|
||||
@@ -0,0 +1,200 @@
|
||||
// TemplateCBlockAlloc.h: interface for the CBlockAlloc class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _TEMPLATE_COBJECTALLOCATOR_H
|
||||
#define _TEMPLATE_COBJECTALLOCATOR_H
|
||||
|
||||
#if defined _MT || defined _REENTRANT
|
||||
# define USE_ALLOCATOR_MUTEX
|
||||
#endif
|
||||
|
||||
|
||||
#include <new>
|
||||
#include "Types.h"
|
||||
#include "Mutex.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
const uint32 MAX_BLOCK_COUNT = 32;
|
||||
|
||||
template <class TYPE>
|
||||
class CObjectAllocator
|
||||
{
|
||||
public:
|
||||
CObjectAllocator(uint32 size=32)
|
||||
{
|
||||
if (size < 32)
|
||||
size = 32;
|
||||
|
||||
for (uint32 index=0; index<MAX_BLOCK_COUNT; index++)
|
||||
mMemoryBlock[index] = 0;
|
||||
|
||||
mMemoryBlockCount = 0;
|
||||
mObjectsAllocated = 0;
|
||||
mObjectCount = 0;
|
||||
mUnusedList = 0;
|
||||
|
||||
mBytesAllocated = 0;
|
||||
|
||||
Allocate(size);
|
||||
}
|
||||
|
||||
~CObjectAllocator()
|
||||
{
|
||||
for (uint32 index=0; index<MAX_BLOCK_COUNT; index++)
|
||||
delete[] mMemoryBlock[index];
|
||||
}
|
||||
|
||||
TYPE *Construct()
|
||||
{
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Lock();
|
||||
#endif
|
||||
if (!mUnusedList)
|
||||
Allocate(mObjectCount);
|
||||
|
||||
Node *node = mUnusedList;
|
||||
mUnusedList = mUnusedList->next;
|
||||
|
||||
new (node) TYPE;
|
||||
|
||||
mObjectCount++;
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Unlock();
|
||||
#endif
|
||||
return (TYPE *)node;
|
||||
}
|
||||
|
||||
TYPE *Construct(const TYPE& object)
|
||||
{
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Lock();
|
||||
#endif
|
||||
if (!mUnusedList)
|
||||
Allocate(mObjectCount);
|
||||
|
||||
Node *node = mUnusedList;
|
||||
mUnusedList = mUnusedList->next;
|
||||
|
||||
new (node) TYPE(object);
|
||||
|
||||
mObjectCount++;
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Unlock();
|
||||
#endif
|
||||
return (TYPE *)node;
|
||||
}
|
||||
|
||||
void Destroy(TYPE *object)
|
||||
{
|
||||
if (object == NULL)
|
||||
return;
|
||||
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Lock();
|
||||
#endif
|
||||
object->~TYPE();
|
||||
|
||||
Node *node = reinterpret_cast<Node *>(object);
|
||||
|
||||
node->next = mUnusedList;
|
||||
mUnusedList = node;
|
||||
|
||||
mObjectCount--;
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
TYPE *FastConstruct()
|
||||
{
|
||||
if (!mUnusedList)
|
||||
Allocate(mObjectCount);
|
||||
|
||||
Node *node = mUnusedList;
|
||||
mUnusedList = mUnusedList->next;
|
||||
|
||||
new (node) TYPE;
|
||||
|
||||
mObjectCount++;
|
||||
return (TYPE *)node;
|
||||
}
|
||||
|
||||
TYPE *FastConstruct(const TYPE& object)
|
||||
{
|
||||
if (!mUnusedList)
|
||||
Allocate(mObjectCount);
|
||||
|
||||
Node *node = mUnusedList;
|
||||
mUnusedList = mUnusedList->next;
|
||||
|
||||
new (node) TYPE(object);
|
||||
|
||||
mObjectCount++;
|
||||
return (TYPE *)node;
|
||||
}
|
||||
|
||||
void FastDestroy(TYPE *object)
|
||||
{
|
||||
if (object == NULL)
|
||||
return;
|
||||
|
||||
object->~TYPE();
|
||||
|
||||
Node *node = reinterpret_cast<Node *>(object);
|
||||
|
||||
node->next = mUnusedList;
|
||||
mUnusedList = node;
|
||||
|
||||
mObjectCount--;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Node
|
||||
{
|
||||
char buffer[sizeof(TYPE)];
|
||||
Node* next;
|
||||
};
|
||||
|
||||
bool Allocate(uint32 size)
|
||||
{
|
||||
if (mMemoryBlockCount == MAX_BLOCK_COUNT)
|
||||
return false;
|
||||
|
||||
Node* newMemoryBlock = new Node[size];
|
||||
mBytesAllocated += size * sizeof(Node);
|
||||
|
||||
for (uint32 i=0; i<size-1; i++)
|
||||
newMemoryBlock[i].next = &newMemoryBlock[i+1];
|
||||
newMemoryBlock[size-1].next = mUnusedList;
|
||||
|
||||
mUnusedList = newMemoryBlock;
|
||||
mMemoryBlock[mMemoryBlockCount++] = newMemoryBlock;
|
||||
mObjectsAllocated += size;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Node* mMemoryBlock[MAX_BLOCK_COUNT];
|
||||
uint32 mMemoryBlockCount;
|
||||
uint32 mObjectsAllocated;
|
||||
uint32 mObjectCount;
|
||||
Node* mUnusedList;
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
CMutex mMutex;
|
||||
#endif
|
||||
|
||||
uint64 mBytesAllocated;
|
||||
};
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // _TEMPLATE_CBLOCKALLOC_H
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef BASE_THREAD_H
|
||||
#define BASE_THREAD_H
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32/Thread.h"
|
||||
|
||||
#elif linux
|
||||
|
||||
#include "linux/Thread.h"
|
||||
|
||||
#elif sparc
|
||||
|
||||
#include "solaris/Thread.h"
|
||||
|
||||
#else
|
||||
|
||||
#error /Base/Thread.h: Undefine platform type
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BASE_THREAD_H
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef BASE_TYPES_H
|
||||
#define BASE_TYPES_H
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32/Types.h"
|
||||
|
||||
#elif linux
|
||||
|
||||
#include "linux/Types.h"
|
||||
|
||||
#elif sparc
|
||||
|
||||
#include "solaris/Types.h"
|
||||
|
||||
#else
|
||||
|
||||
#error /Base/Types.h: Undefine platform type
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef BASE_LINUX_ARCHIVE_H
|
||||
#define BASE_LINUX_ARCHIVE_H
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
#ifdef PACK_BIG_ENDIAN
|
||||
|
||||
inline double byteSwap(double value) { byteReverse(&value); return value; }
|
||||
inline float byteSwap(float value) { byteReverse(&value); return value; }
|
||||
inline uint64 byteSwap(uint64 value) { byteReverse(&value); return value; }
|
||||
inline int64 byteSwap(int64 value) { byteReverse(&value); return value; }
|
||||
inline uint32 byteSwap(uint32 value) { byteReverse(&value); return value; }
|
||||
inline int32 byteSwap(int32 value) { byteReverse(&value); return value; }
|
||||
inline uint16 byteSwap(uint16 value) { byteReverse(&value); return value; }
|
||||
inline int16 byteSwap(int16 value) { byteReverse(&value); return value; }
|
||||
|
||||
#else
|
||||
|
||||
inline double byteSwap(double value) { return value; }
|
||||
inline float byteSwap(float value) { return value; }
|
||||
inline uint64 byteSwap(uint64 value) { return value; }
|
||||
inline int64 byteSwap(int64 value) { return value; }
|
||||
inline uint32 byteSwap(uint32 value) { return value; }
|
||||
inline int32 byteSwap(int32 value) { return value; }
|
||||
inline uint16 byteSwap(uint16 value) { return value; }
|
||||
inline int16 byteSwap(int16 value) { return value; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,110 @@
|
||||
#include "../BlockAllocator.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
BlockAllocator::BlockAllocator()
|
||||
{
|
||||
for(unsigned i = 0; i < 31; i++)
|
||||
{
|
||||
m_blocks[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BlockAllocator::~BlockAllocator()
|
||||
{
|
||||
// free all allocated memory blocks
|
||||
for(unsigned i = 0; i < 31; i++)
|
||||
{
|
||||
while(m_blocks[i] != NULL)
|
||||
{
|
||||
unsigned *tmp = m_blocks[i];
|
||||
m_blocks[i] = (unsigned *)*m_blocks[i];
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate a block that is the next power of two greater than the # of bytes passed.
|
||||
// 33 bytes yields a 64 byte block of memory and so forth.
|
||||
|
||||
void *BlockAllocator::getBlock(unsigned bytes)
|
||||
{
|
||||
unsigned accum = 16, bits = 16;
|
||||
unsigned *handle = NULL;
|
||||
|
||||
// Perform a binary search looking for the highest bit.
|
||||
|
||||
while(bits != 0)
|
||||
{
|
||||
// If bytes is less than the bit we're testing for, subtract half
|
||||
// from the bit value and repeat
|
||||
if(bytes < (unsigned)(1 << accum))
|
||||
{
|
||||
bits /= 2;
|
||||
accum -= bits;
|
||||
}
|
||||
// If bytes is greater than the bit we're testing for, add half
|
||||
// from the but value and repeat
|
||||
else if(bytes > (unsigned)(1 << accum))
|
||||
{
|
||||
bits /= 2;
|
||||
accum += bits;
|
||||
}
|
||||
// Got lucky and hit the value dead on
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// At this point accum contains the most significant bit index, increment
|
||||
accum++;
|
||||
if(accum < 2)
|
||||
{
|
||||
accum = 2;
|
||||
}
|
||||
|
||||
// Note that when memory is actually allocated, 8 extra bytes will be allocated.at the front
|
||||
// The first integer is the address of the next block of memory when the block is in the allocator
|
||||
// The second integer is the bit length of the block
|
||||
// Memory is allocated on 4 byte boundaries to sidestep byte alignment problems
|
||||
|
||||
|
||||
// Check if the allocator already has a block of that size
|
||||
if(m_blocks[accum] == 0)
|
||||
{
|
||||
// remove the pre allocated block from the linked list
|
||||
handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned));
|
||||
handle[1] = accum;
|
||||
handle[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate a new block
|
||||
handle = m_blocks[accum];
|
||||
m_blocks[accum] = (unsigned *)handle[0];
|
||||
handle[0] = 0;
|
||||
}
|
||||
// return a pointer that skips over the header used for the allocator's purposes
|
||||
return(handle + 2);
|
||||
}
|
||||
|
||||
void BlockAllocator::returnBlock(unsigned *handle)
|
||||
{
|
||||
// C++ allows for safe deletion of a NULL pointer
|
||||
if(handle)
|
||||
{
|
||||
// Update the allocator linked list, insert this entry at the head
|
||||
*(handle - 2) = (unsigned)m_blocks[*(handle - 1)];
|
||||
// Add this entry to the proper linked list node
|
||||
m_blocks[*(handle - 1)] = (handle - 2);
|
||||
}
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
////////////////////////////////////////
|
||||
// Event.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CEvent class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#if defined(_REENTRANT)
|
||||
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CEvent::CEvent() :
|
||||
mMutex(),
|
||||
mCond(),
|
||||
mThreadCount(0)
|
||||
{
|
||||
pthread_mutex_init(&mMutex, NULL);
|
||||
pthread_cond_init(&mCond, NULL);
|
||||
}
|
||||
|
||||
CEvent::~CEvent()
|
||||
{
|
||||
pthread_cond_destroy(&mCond);
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
}
|
||||
|
||||
bool CEvent::Signal()
|
||||
{
|
||||
pthread_mutex_lock(&mMutex);
|
||||
if (mThreadCount == 0)
|
||||
mThreadCount = SIGNALED;
|
||||
pthread_cond_signal(&mCond);
|
||||
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 CEvent::Wait(uint32 timeout)
|
||||
{
|
||||
int result;
|
||||
|
||||
pthread_mutex_lock(&mMutex);
|
||||
if (mThreadCount == SIGNALED)
|
||||
{
|
||||
mThreadCount = 0;
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
|
||||
return eWAIT_SIGNAL;
|
||||
}
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
mThreadCount++;
|
||||
result = pthread_cond_wait(&mCond, &mMutex);
|
||||
mThreadCount--;
|
||||
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct timeval now;
|
||||
struct timespec abs_timeout;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
abs_timeout.tv_sec = now.tv_sec + timeout/1000;
|
||||
abs_timeout.tv_nsec = now.tv_usec * 1000 + (timeout%1000)*1000000;
|
||||
abs_timeout.tv_sec += abs_timeout.tv_nsec / 1000000000;
|
||||
abs_timeout.tv_nsec %= 1000000000;
|
||||
|
||||
mThreadCount++;
|
||||
result = pthread_cond_timedwait(&mCond, &mMutex, &abs_timeout);
|
||||
mThreadCount--;
|
||||
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
|
||||
if (result == 0 || result == EINTR)
|
||||
return eWAIT_SIGNAL;
|
||||
else if (result == ETIMEDOUT)
|
||||
return eWAIT_TIMEOUT;
|
||||
else
|
||||
return eWAIT_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_REENTRANT)
|
||||
@@ -0,0 +1,74 @@
|
||||
////////////////////////////////////////
|
||||
// Event.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CEvent class that encapsulates the functionality of a
|
||||
// single-locking semaphore.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_EVENT_H
|
||||
#define BASE_LINUX_EVENT_H
|
||||
|
||||
#if !defined(_REENTRANT)
|
||||
# pragma message( "Excluding Base::CEvent - requires multi-threaded compile. (_REENTRANT)" )
|
||||
#else
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CEvent
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates the functionality of a singal-locking semaphore.
|
||||
// This class is valuable for thread syncronization when a thead's
|
||||
// execution needs to be dependent upon another thread.
|
||||
//
|
||||
// Public Methods:
|
||||
// Signal() : Signals a thread that has called Wait() so that it can
|
||||
// continue execution. This function returns true if the waiting
|
||||
// thread was signalled successfully, otherwise false is returned.
|
||||
// Wait() : Halts the calling thread's execution indefinately until
|
||||
// a Singal() call is made by an external thread. If the thread is
|
||||
// successfully signalled, the function returns eWAIT_SIGNAL. If
|
||||
// timeout period expires without a signal, eWAIT_TIMEOUT is returned.
|
||||
// If the function fails, eWAIT_ERROR is returned.
|
||||
//
|
||||
class CEvent
|
||||
{
|
||||
public:
|
||||
CEvent();
|
||||
virtual ~CEvent();
|
||||
|
||||
bool Signal();
|
||||
int32 Wait(uint32 timeout = 0);
|
||||
|
||||
public:
|
||||
enum { eWAIT_ERROR, eWAIT_SIGNAL, eWAIT_TIMEOUT };
|
||||
enum { SIGNALED = -1 };
|
||||
private:
|
||||
pthread_mutex_t mMutex;
|
||||
pthread_cond_t mCond;
|
||||
int mThreadCount;
|
||||
};
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_LINUX_EVENT_H
|
||||
@@ -0,0 +1,390 @@
|
||||
#include "../Logger.h"
|
||||
#include "Mutex.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
const char file_sep = '/';
|
||||
|
||||
Logger::Logger(const char *prefix, int level, unsigned size, bool rollDate)
|
||||
: m_defaultLevel(level), m_defaultSize(size), m_dirPrefix(prefix), m_rollDate(rollDate)
|
||||
{
|
||||
char buf[1024];
|
||||
FILE *logDir = NULL;
|
||||
|
||||
logDir = fopen(m_dirPrefix.c_str(), "r+");
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(m_dirPrefix.c_str(), 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
|
||||
tm now;
|
||||
time_t t = time(NULL);
|
||||
localtime_r(&t, &now);
|
||||
|
||||
memcpy(&m_lastDateTime, &now, sizeof(tm));
|
||||
if(m_rollDate)
|
||||
{
|
||||
sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buf, "%s", m_dirPrefix.c_str());
|
||||
}
|
||||
logDir = fopen(buf, "r+");
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(buf, 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
m_logPrefix = buf;
|
||||
}
|
||||
|
||||
Logger::~Logger()
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
log((*iter).first, LOG_FILEONLY, "---=== Log Stopped ===---");
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
delete((*iter).second);
|
||||
|
||||
}
|
||||
m_logTable.clear();
|
||||
}
|
||||
|
||||
void Logger::flush(unsigned logenum)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
LogInfo *info = (*iter).second;
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::flushAll()
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
LogInfo *info = (*iter).second;
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::addLog(const char *id, unsigned logenum, int level, unsigned size)
|
||||
{
|
||||
LogInfo *newLog = new LogInfo;
|
||||
newLog->filename = m_logPrefix + file_sep + id + ".log";
|
||||
newLog->name = id;
|
||||
newLog->used = 0;
|
||||
newLog->max = size;
|
||||
newLog->last = 0;
|
||||
newLog->level = level;
|
||||
|
||||
m_logTable.insert(pair<unsigned, LogInfo *>(logenum, newLog));
|
||||
|
||||
if(strcmp("stdout", id) == 0)
|
||||
{
|
||||
newLog->file = stdout;
|
||||
}
|
||||
else if(strcmp("stderr", id) == 0)
|
||||
{
|
||||
newLog->file = stderr;
|
||||
}
|
||||
else
|
||||
{
|
||||
newLog->file = fopen(newLog->filename.c_str(), "a+");
|
||||
}
|
||||
log(logenum, LOG_FILEONLY, "---=== Log Started ===---");
|
||||
}
|
||||
|
||||
void Logger::addLog(const char *id, unsigned logenum)
|
||||
{
|
||||
LogInfo *newLog = new LogInfo;
|
||||
newLog->filename = m_logPrefix + file_sep + id + ".log";
|
||||
newLog->name = id;
|
||||
newLog->used = 0;
|
||||
newLog->max = m_defaultSize;
|
||||
newLog->last = 0;
|
||||
newLog->level = m_defaultLevel;
|
||||
|
||||
m_logTable.insert(pair<unsigned, LogInfo *>(logenum, newLog));
|
||||
|
||||
if(strcmp("stdout", id) == 0)
|
||||
{
|
||||
newLog->file = stdout;
|
||||
}
|
||||
else if(strcmp("stderr", id) == 0)
|
||||
{
|
||||
newLog->file = stderr;
|
||||
}
|
||||
else
|
||||
{
|
||||
newLog->file = fopen(newLog->filename.c_str(), "a+");
|
||||
}
|
||||
log(logenum, LOG_FILEONLY, "---===Log Started ===---");
|
||||
}
|
||||
|
||||
void Logger::updateLog(unsigned logenum, int level, unsigned size)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
(*iter).second->level = level;
|
||||
(*iter).second->max = size;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::removeLog(unsigned logenum)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
log((*iter).first, LOG_ALWAYS, "---=== Log Stopped ===---");
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
delete((*iter).second);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::logSimple(unsigned logenum, int level, const char *message)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
if(iter == m_logTable.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
LogInfo *info = (*iter).second;
|
||||
if(level >= info->level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(level == LOG_FILEONLY && ((info->file == stderr) || (info->file == stdout)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(info->last != t)
|
||||
{
|
||||
memcpy(&info->ts, localtime(&t), sizeof(tm));
|
||||
info->last = t;
|
||||
}
|
||||
|
||||
if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
#if defined(_REENTRANT)
|
||||
rLock.Lock();
|
||||
#endif
|
||||
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
|
||||
rollDate(t);
|
||||
}
|
||||
#if defined(_REENTRANT)
|
||||
rLock.Unlock();
|
||||
#endif
|
||||
}
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
if(info->max > 0)
|
||||
{
|
||||
int tmp = fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, message);
|
||||
info->used += tmp;
|
||||
if(info->used > info->max)
|
||||
{
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, message);
|
||||
fflush(info->file);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Logger::log(unsigned logenum, int level, const char *message, ...)
|
||||
{
|
||||
char buf[2048];
|
||||
va_list varg;
|
||||
va_start(varg, message);
|
||||
vsnprintf(buf, 2047, message, varg);
|
||||
buf[2047] = 0;
|
||||
va_end(varg);
|
||||
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
if(iter == m_logTable.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
LogInfo *info = (*iter).second;
|
||||
if(level >= info->level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(level == LOG_FILEONLY && ((info->file == stderr) || (info->file == stdout)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(info->last != t)
|
||||
{
|
||||
localtime_r(&t, &info->ts);
|
||||
info->last = t;
|
||||
}
|
||||
if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
#if defined(_REENTRANT)
|
||||
rLock.Lock();
|
||||
#endif
|
||||
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
|
||||
rollDate(t);
|
||||
}
|
||||
#if defined(_REENTRANT)
|
||||
rLock.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
if(info->max > 0)
|
||||
{
|
||||
int tmp = fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, buf);
|
||||
info->used += tmp;
|
||||
if(info->used > info->max)
|
||||
{
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, buf);
|
||||
fflush(info->file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::rollDate(time_t t)
|
||||
{
|
||||
char buf[80];
|
||||
FILE *logDir = NULL;
|
||||
|
||||
logDir = fopen(m_dirPrefix.c_str(), "r+");
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(m_dirPrefix.c_str(), 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
|
||||
tm now;
|
||||
localtime_r(&t, &now);
|
||||
|
||||
sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100));
|
||||
logDir = fopen(buf, "r+");
|
||||
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(buf, 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
m_logPrefix = buf;
|
||||
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
(*iter).second->filename = m_logPrefix + file_sep + (*iter).second->name.c_str() + ".log";
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
(*iter).second->file = fopen((*iter).second->filename.c_str(), "a+");
|
||||
memcpy(&((*iter).second->ts), &now, sizeof(tm));
|
||||
}
|
||||
}
|
||||
|
||||
// mkdir function that creates intermediate directories
|
||||
void Logger::cmkdir(const char *dir, int mode)
|
||||
{
|
||||
char dirbuf[128];
|
||||
strncpy(dirbuf, dir, 127);
|
||||
dirbuf[127] = 0;
|
||||
char *j = dirbuf, *i = dirbuf;
|
||||
int handle;
|
||||
|
||||
while(*i)
|
||||
{
|
||||
if(*i == file_sep)
|
||||
{
|
||||
(*i) = 0;
|
||||
// handle = open(j, O_EXCL); // Ben's original code
|
||||
// if((handle > 0) || (errno != EISDIR && errno != ENOENT))
|
||||
// {
|
||||
// perror("Logger::cmkdir():");
|
||||
// abort();
|
||||
// }
|
||||
|
||||
// This doesnt work under Linux, it returns a valid handle
|
||||
// Instead: see if file exists. If it doesnt, create directory ok
|
||||
// If it exists, do stat to see if it is a dir.
|
||||
// If it is a dir, then ok, create the directory.
|
||||
// If it is a file, error
|
||||
// ging 9-16-2002
|
||||
|
||||
handle = open(j, O_RDONLY);
|
||||
if (handle > 0)
|
||||
{
|
||||
struct stat stat_buffer;
|
||||
int ret = fstat(handle,&stat_buffer);
|
||||
if ((ret == -1) || ((stat_buffer.st_mode | S_IFDIR) == 0))
|
||||
{
|
||||
perror("Logger::cmkdir():");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
mkdir(j, mode);
|
||||
close(handle);
|
||||
(*i) = file_sep;
|
||||
}
|
||||
else if(*(i + 1) == 0)
|
||||
{
|
||||
mkdir(j, mode);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,199 @@
|
||||
# environment variables:
|
||||
# $INCLUDE_PATH is a colon-delimited list of include directories
|
||||
|
||||
EMPTY_CHAR=
|
||||
SPACE_CHAR=$(empty) $(empty)
|
||||
COLON_CHAR=:
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
OUTPUT_FILE_ST=libBase.a
|
||||
OUTPUT_FILE_MT=libBase_MT.a
|
||||
OUTPUT_DIR=../../../lib
|
||||
OBJECT_DIR_ST=./obj_st
|
||||
OBJECT_DIR_MT=./obj_mt
|
||||
|
||||
STL_HOME=../../../../stlport453
|
||||
|
||||
INCLUDE_DIRS=.. ../ $(STL_HOME)/stlport
|
||||
|
||||
SOURCE_DIRS=. ..
|
||||
SOURCE_FILES=
|
||||
|
||||
LIBRARY_DIRS=
|
||||
LIBRARY_FILES=
|
||||
|
||||
CFLAGS_USER=
|
||||
LFLAGS_USER=
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
INCLUDE_DIR_LIST=$(subst $(COLON_CHAR),$(SPACE_CHAR),$(INCLUDE_PATH)) $(INCLUDE_DIRS)
|
||||
INCLUDE_FLAGS=$(addprefix -I,$(INCLUDE_DIR_LIST))
|
||||
CFLAGS_ST=$(INCLUDE_FLAGS) $(CFLAGS_USER) -D_GNU_SOURCE -Wall -Wno-unknown-pragmas
|
||||
CFLAGS_MT=$(INCLUDE_FLAGS) $(CFLAGS_USER) -D_GNU_SOURCE -D_REENTRANT -Wall -Wno-unknown-pragmas
|
||||
CFLAGS_DEBUG_ST=$(CFLAGS_ST) -D_DEBUG -g
|
||||
CFLAGS_RELEASE_ST=$(CFLAGS_ST) -DNDEBUG -O2
|
||||
CFLAGS_DEBUG_MT=$(CFLAGS_MT) -D_DEBUG -g
|
||||
CFLAGS_RELEASE_MT=$(CFLAGS_MT) -DNDEBUG -O2
|
||||
|
||||
LIBRARY_FLAGS=$(addprefix -l,$(LIBRARIES))
|
||||
LFLAGS=$(LIBRARY_FLAGS) $(LFLAGS_USER) -r
|
||||
LFLAGS_DEBUG=$(LFLAGS)
|
||||
LFLAGS_RELEASE=$(LFLAGS)
|
||||
|
||||
CPP=g++
|
||||
LINK=ld
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
DEBUG_OBJ_DIR_ST=$(OBJECT_DIR_ST)/debug
|
||||
RELEASE_OBJ_DIR_ST=$(OBJECT_DIR_ST)/release
|
||||
DEBUG_OBJ_DIR_MT=$(OBJECT_DIR_MT)/debug
|
||||
RELEASE_OBJ_DIR_MT=$(OBJECT_DIR_MT)/release
|
||||
|
||||
DEBUG_DIR=$(OUTPUT_DIR)/debug
|
||||
RELEASE_DIR=$(OUTPUT_DIR)/release
|
||||
|
||||
FIND=$(shell ls $(x)/*.cpp)
|
||||
SOURCE_LIST = $(SOURCE_FILES) $(foreach x, $(SOURCE_DIRS), $(FIND))
|
||||
|
||||
DEBUG_OBJ_LIST_ST=$(addprefix $(DEBUG_OBJ_DIR_ST)/, $(notdir $(SOURCE_LIST:.cpp=.o)))
|
||||
RELEASE_OBJ_LIST_ST=$(addprefix $(RELEASE_OBJ_DIR_ST)/, $(notdir $(SOURCE_LIST:.cpp=.o)))
|
||||
DEBUG_OBJ_LIST_MT=$(addprefix $(DEBUG_OBJ_DIR_MT)/, $(notdir $(SOURCE_LIST:.cpp=.o)))
|
||||
RELEASE_OBJ_LIST_MT=$(addprefix $(RELEASE_OBJ_DIR_MT)/, $(notdir $(SOURCE_LIST:.cpp=.o)))
|
||||
|
||||
|
||||
DEPENDENCY_LIST = $(SOURCE_LIST:.cpp=.d)
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
release_st: echoRelease_st releaseDirs_st $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo Successfully built $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo
|
||||
|
||||
debug_st: debugDirs_st $(DEBUG_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo Successfully built $(DEBUG_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo
|
||||
|
||||
release_mt: echoRelease_mt releaseDirs_mt $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo Successfully built $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo
|
||||
|
||||
debug_mt: debugDirs_mt $(DEBUG_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo Successfully built $(DEBUG_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo
|
||||
|
||||
all: clean debug_st release_st debug_mt release_mt
|
||||
|
||||
all_st: clean debug_st release_st
|
||||
|
||||
all_mt: clean debug_mt release_mt
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
debugDirs_st :
|
||||
@mkdir -p $(DEBUG_OBJ_DIR_ST)
|
||||
@mkdir -p $(DEBUG_DIR)
|
||||
|
||||
$(DEBUG_OBJ_DIR_ST)/%.o : $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
$(CPP) $(CFLAGS_DEBUG_ST) -o $@ -c $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
|
||||
$(DEBUG_DIR)/$(OUTPUT_FILE_ST): $(DEBUG_OBJ_LIST_ST)
|
||||
$(LINK) $(LFLAGS_DEBUG) -o $@ $(DEBUG_OBJ_LIST_ST)
|
||||
|
||||
|
||||
debugDirs_mt :
|
||||
@mkdir -p $(DEBUG_OBJ_DIR_MT)
|
||||
@mkdir -p $(DEBUG_DIR)
|
||||
|
||||
$(DEBUG_OBJ_DIR_MT)/%.o : $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
$(CPP) $(CFLAGS_DEBUG_MT) -o $@ -c $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
|
||||
$(DEBUG_DIR)/$(OUTPUT_FILE_MT): $(DEBUG_OBJ_LIST_MT)
|
||||
$(LINK) $(LFLAGS_DEBUG) -o $@ $(DEBUG_OBJ_LIST_MT)
|
||||
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
echoRelease_st :
|
||||
@echo Building $(OUTPUT_FILE_ST)
|
||||
@echo compiler: $(CPP) $(CFLAGS_RELEASE_ST)
|
||||
@echo linker: $(LINK) $(LFLAGS_RELEASE)
|
||||
@echo
|
||||
|
||||
echoRelease_mt :
|
||||
@echo Building $(OUTPUT_FILE_MT)
|
||||
@echo compiler: $(CPP) $(CFLAGS_RELEASE_MT)
|
||||
@echo linker: $(LINK) $(LFLAGS_RELEASE)
|
||||
@echo
|
||||
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
releaseDirs_st :
|
||||
@mkdir -p $(RELEASE_OBJ_DIR_ST)
|
||||
@mkdir -p $(RELEASE_DIR)
|
||||
|
||||
$(RELEASE_OBJ_DIR_ST)/%.o : $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
@echo compiling $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
@$(CPP) $(CFLAGS_RELEASE_ST) -o $@ -c $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
|
||||
$(RELEASE_DIR)/$(OUTPUT_FILE_ST): $(RELEASE_OBJ_LIST_ST)
|
||||
@echo linking $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@$(LINK) $(LFLAGS_RELEASE) -o $@ $(RELEASE_OBJ_LIST_ST)
|
||||
|
||||
releaseDirs_mt :
|
||||
@mkdir -p $(RELEASE_OBJ_DIR_MT)
|
||||
@mkdir -p $(RELEASE_DIR)
|
||||
|
||||
$(RELEASE_OBJ_DIR_MT)/%.o : $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
@echo compiling $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
@$(CPP) $(CFLAGS_RELEASE_MT) -o $@ -c $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
|
||||
$(RELEASE_DIR)/$(OUTPUT_FILE_MT): $(RELEASE_OBJ_LIST_MT)
|
||||
@echo linking $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@$(LINK) $(LFLAGS_RELEASE) -o $@ $(RELEASE_OBJ_LIST_MT)
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
include .depend
|
||||
|
||||
.PHONY : $(DEPENDENCY_LIST)
|
||||
|
||||
depend: .depend $(DEPENDENCY_LIST)
|
||||
|
||||
.depend:
|
||||
touch .depend
|
||||
make depend
|
||||
|
||||
$(DEPENDENCY_LIST):
|
||||
@echo Generating dependencies for $(notdir $(@:.d=.cpp))
|
||||
@echo -n $(DEBUG_OBJ_DIR_ST)/ >> .depend
|
||||
@$(CPP) -MM $(addprefix -I,$(INCLUDE_DIRS)) $(@:.d=.cpp)>> .depend
|
||||
@echo -n $(DEBUG_OBJ_DIR_MT)/ >> .depend
|
||||
@$(CPP) -MM $(addprefix -I,$(INCLUDE_DIRS)) $(@:.d=.cpp) >> .depend
|
||||
@echo -n $(RELEASE_OBJ_DIR_ST)/ >> .depend
|
||||
@$(CPP) -MM $(addprefix -I,$(INCLUDE_DIRS)) $(@:.d=.cpp)>> .depend
|
||||
@echo -n $(RELEASE_OBJ_DIR_MT)/ >> .depend
|
||||
@$(CPP) -MM $(addprefix -I,$(INCLUDE_DIRS)) $(@:.d=.cpp) >> .depend
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
clean:
|
||||
@echo removing "$(OBJECT_DIR_ST)/*.o"
|
||||
@rm -rf $(OBJECT_DIR_ST)
|
||||
@echo removing "$(OBJECT_DIR_MT)/*.o"
|
||||
@rm -rf $(OBJECT_DIR_MT)
|
||||
@echo removing $(DEBUG_DIR)/$(OUTPUT_FILE_ST)
|
||||
@rm -f $(DEBUG_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo removing $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@rm -f $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo removing $(DEBUG_DIR)/$(OUTPUT_FILE_MT)
|
||||
@rm -f $(DEBUG_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo removing $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@rm -f $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@rm -f .depend
|
||||
@echo
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
////////////////////////////////////////
|
||||
// Mutex.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CMutex class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#if defined(_REENTRANT)
|
||||
|
||||
|
||||
#include "Mutex.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CMutex::CMutex()
|
||||
{
|
||||
mInitialized = (pthread_mutex_init(&mMutex, 0) == 0);
|
||||
}
|
||||
|
||||
CMutex::~CMutex()
|
||||
{
|
||||
if (mInitialized)
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // #if defined(_REENTRANT)
|
||||
@@ -0,0 +1,79 @@
|
||||
////////////////////////////////////////
|
||||
// Mutex.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CMutex class that encapsulates the functionality of a
|
||||
// mutually-exclusive device.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_MUTEX_H
|
||||
#define BASE_LINUX_MUTEX_H
|
||||
|
||||
#if !defined(_REENTRANT)
|
||||
# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_REENTRANT)" )
|
||||
#else
|
||||
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CMutex
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates the functionality of a mutually-exclusive device.
|
||||
// This class is valuable for protecting against race conditions
|
||||
// within threaded applications. The CMutex class can be used to
|
||||
// only allow a single thread to run within a specified code
|
||||
// segment at a time.
|
||||
//
|
||||
// Public Methods:
|
||||
// Lock() : Locks the mutex. If the mutex is already locked, the
|
||||
// operating system will block the calling thread until another
|
||||
// thread has unlocked the mutex.
|
||||
// Unlock() : Unlocks the mutex.
|
||||
//
|
||||
class CMutex
|
||||
{
|
||||
public:
|
||||
CMutex();
|
||||
~CMutex();
|
||||
|
||||
void Lock();
|
||||
void Unlock();
|
||||
private:
|
||||
pthread_mutex_t mMutex;
|
||||
bool mInitialized;
|
||||
};
|
||||
|
||||
inline void CMutex::Lock(void)
|
||||
{
|
||||
if (mInitialized)
|
||||
pthread_mutex_lock(&mMutex);
|
||||
}
|
||||
|
||||
inline void CMutex::Unlock(void)
|
||||
{
|
||||
if (mInitialized)
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_LINUX_MUTEX_H
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
////////////////////////////////////////
|
||||
// Platform.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the global functionality declaired in Platform.h.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#include <ctype.h>
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
// Implementation of microsoft strlwr extension
|
||||
// This non-ANSI function is not supported under UNIX
|
||||
void _strlwr(char * s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
*s = tolower(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of microsoft strlwr extension
|
||||
// This non-ANSI function is not supported under UNIX
|
||||
void _strupr(char * s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CTimer::CTimer() :
|
||||
mTimer(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
////////////////////////////////////////
|
||||
// Platform.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Include relevent system headers that are platform specific.
|
||||
// 2. Declair global platform specific functionality.
|
||||
// 3. Include primative type definitions
|
||||
//
|
||||
// Global Functions:
|
||||
// getTimer() : Return the current high resolution clock count.
|
||||
// getTimerFrequency() : Return the frequency of the high resolution clock.
|
||||
// sleep() : Voluntarily relinquish timeslice of the calling thread for a
|
||||
// specified number of milliseconds.
|
||||
// strlwr() : Alters the contents of a string, making it all lower-case.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_PLATFORM_H
|
||||
#define BASE_LINUX_PLATFORM_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <sys/errno.h>
|
||||
#include <pthread.h>
|
||||
#include <resolv.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
uint64 getTimer(void);
|
||||
uint64 getTimerFrequency(void);
|
||||
void sleep(uint32 ms);
|
||||
|
||||
inline uint64 getTimer(void)
|
||||
{
|
||||
uint64 t;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, 0);
|
||||
t = tv.tv_sec;
|
||||
t = t * 1000000;
|
||||
t += tv.tv_usec;
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint64 getTimerFrequency(void)
|
||||
{
|
||||
uint64 f = 1000000;
|
||||
return f;
|
||||
}
|
||||
|
||||
inline void sleep(uint32 ms)
|
||||
{
|
||||
usleep(static_cast<unsigned long>(ms * 1000));
|
||||
}
|
||||
|
||||
void _strlwr(char * s);
|
||||
void _strupr(char * s);
|
||||
|
||||
|
||||
class CTimer
|
||||
{
|
||||
public:
|
||||
CTimer();
|
||||
|
||||
void Set(uint32 seconds);
|
||||
void Signal();
|
||||
bool Expired();
|
||||
|
||||
private:
|
||||
uint32 mTimer;
|
||||
};
|
||||
|
||||
inline void CTimer::Set(uint32 interval)
|
||||
{
|
||||
mTimer = (uint32)time(0) + interval;
|
||||
}
|
||||
|
||||
inline void CTimer::Signal()
|
||||
{
|
||||
mTimer = 0;
|
||||
}
|
||||
|
||||
inline bool CTimer::Expired()
|
||||
{
|
||||
return (mTimer <= (uint32)time(0));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // BASE_LINUX_PLATFORM_H
|
||||
@@ -0,0 +1,274 @@
|
||||
////////////////////////////////////////
|
||||
// Thread.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CThread class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#if defined(_REENTRANT)
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include "Thread.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
void *threadProc(void *threadPtr)
|
||||
{
|
||||
CThread &thread = *((CThread*)threadPtr);
|
||||
thread.mThreadActive = true;
|
||||
thread.ThreadProc();
|
||||
thread.mThreadActive = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CThread::CThread()
|
||||
{
|
||||
mThreadID = 0;
|
||||
mThreadActive = false;
|
||||
mThreadContinue = false;
|
||||
}
|
||||
|
||||
CThread::~CThread()
|
||||
{
|
||||
StopThread();
|
||||
}
|
||||
|
||||
void CThread::StartThread()
|
||||
{
|
||||
mThreadContinue = true;
|
||||
pthread_create(&mThreadID,0,threadProc,this);
|
||||
while (!IsThreadActive())
|
||||
Base::sleep(1);
|
||||
}
|
||||
|
||||
int32 CThread::StopThread(int timeout)
|
||||
{
|
||||
timeout += time(0);
|
||||
|
||||
mThreadContinue = false;
|
||||
while (mThreadActive && time(0)<timeout)
|
||||
sleep(1);
|
||||
if (mThreadActive)
|
||||
{
|
||||
mThreadActive = false;
|
||||
return eSTOP_TIMEOUT;
|
||||
}
|
||||
return eSTOP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CThreadPool::CMember::CMember(CThreadPool * parent) :
|
||||
mParent(parent),
|
||||
mFunction(NULL),
|
||||
mArgument(NULL),
|
||||
mSemaphore()
|
||||
{
|
||||
StartThread();
|
||||
}
|
||||
|
||||
CThreadPool::CMember::~CMember()
|
||||
{
|
||||
}
|
||||
|
||||
void CThreadPool::CMember::Destroy()
|
||||
{
|
||||
mThreadContinue = false;
|
||||
mSemaphore.Signal();
|
||||
}
|
||||
|
||||
bool CThreadPool::CMember::Execute(void( *function )( void * ), void * arg)
|
||||
{
|
||||
if (mFunction)
|
||||
return false;
|
||||
|
||||
mArgument = arg;
|
||||
mFunction = function;
|
||||
mSemaphore.Signal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CThreadPool::CMember::ThreadProc()
|
||||
{
|
||||
mParent->OnStartup(this);
|
||||
while (mThreadContinue)
|
||||
{
|
||||
mParent->OnIdle(this);
|
||||
mSemaphore.Wait(mParent->GetTimeOut()*1000);
|
||||
|
||||
if (mFunction)
|
||||
{
|
||||
mFunction(mArgument);
|
||||
mArgument = NULL;
|
||||
mFunction = NULL;
|
||||
}
|
||||
else if (mParent->OnDestory(this))
|
||||
mThreadContinue = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CThreadPool::CThreadPool(uint32 maxThreads, uint32 minThreads, uint32 timeout) :
|
||||
mMutex(),
|
||||
mIdleMember(),
|
||||
mBusyMember(),
|
||||
mNullMember(),
|
||||
mThreadCount(0),
|
||||
mMaxThreads(maxThreads),
|
||||
mMinThreads(minThreads),
|
||||
mTimeOut(timeout)
|
||||
{
|
||||
if (mMaxThreads == 0) mMaxThreads = 1;
|
||||
if (mMinThreads == 0) mMinThreads = 1;
|
||||
if (mMinThreads > mMaxThreads) mMinThreads = mMaxThreads;
|
||||
|
||||
for (uint32 i=0; i<mMinThreads; i++)
|
||||
new CMember(this);
|
||||
}
|
||||
|
||||
CThreadPool::~CThreadPool()
|
||||
{
|
||||
set<CMember *>::iterator setIterator;
|
||||
|
||||
////////////////////////////////////////
|
||||
// (1) Destory all busy member threads
|
||||
mMutex.Lock();
|
||||
setIterator = mBusyMember.begin();
|
||||
while (setIterator != mBusyMember.end())
|
||||
(*setIterator++)->Destroy();
|
||||
mMutex.Unlock();
|
||||
|
||||
////////////////////////////////////////
|
||||
// (2) Destory all idle member threads
|
||||
while (mThreadCount)
|
||||
{
|
||||
mMutex.Lock();
|
||||
setIterator = mIdleMember.begin();
|
||||
while (setIterator != mIdleMember.end())
|
||||
(*setIterator++)->Destroy();
|
||||
mMutex.Unlock();
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (3) Delete the null member threads
|
||||
mMutex.Lock();
|
||||
while (!mNullMember.empty())
|
||||
{
|
||||
delete mNullMember.front();
|
||||
mNullMember.pop_front();
|
||||
}
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
bool CThreadPool::Execute(void( *function )( void * ), void * arg)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
////////////////////////////////////////
|
||||
// (1) If no idle members, return false to indicate that no threads
|
||||
// were available. If the thread count is below the max, create
|
||||
// a new thread.
|
||||
if (mIdleMember.empty())
|
||||
{
|
||||
if (mThreadCount < mMaxThreads)
|
||||
new CMember(this);
|
||||
mMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (2) Delete any null member threads.
|
||||
while (!mNullMember.empty())
|
||||
{
|
||||
delete mNullMember.front();
|
||||
mNullMember.pop_front();
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (3) Move the first idle thread to the busy set and signal the
|
||||
// thread to execute the specified function.
|
||||
CMember * member = *(mIdleMember.begin());
|
||||
mIdleMember.erase(member);
|
||||
mBusyMember.insert(member);
|
||||
member->Execute(function,arg);
|
||||
|
||||
mMutex.Unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 CThreadPool::GetTimeOut()
|
||||
{
|
||||
return mTimeOut;
|
||||
}
|
||||
|
||||
void CThreadPool::OnStartup(CMember * member)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
mThreadCount++;
|
||||
mIdleMember.insert(member);
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
void CThreadPool::OnIdle(CMember * member)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
mBusyMember.erase(member);
|
||||
mIdleMember.insert(member);
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
bool CThreadPool::OnDestory(CMember * member)
|
||||
{
|
||||
set<CMember *>::iterator setIterator;
|
||||
|
||||
mMutex.Lock();
|
||||
|
||||
bool result = (setIterator = mIdleMember.find(member)) != mIdleMember.end();
|
||||
if (result)
|
||||
{
|
||||
mNullMember.push_back(member);
|
||||
mIdleMember.erase(setIterator);
|
||||
mThreadCount--;
|
||||
}
|
||||
|
||||
mMutex.Unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_REENTRANT)
|
||||
@@ -0,0 +1,146 @@
|
||||
////////////////////////////////////////
|
||||
// Thread.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CThread class that encapsulates threading functionality.
|
||||
// This abstract base class in intended to be used to encapsulate
|
||||
// individual tasks that require threading in derived classes.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_THREAD_H
|
||||
#define BASE_LINUX_THREAD_H
|
||||
|
||||
#if !defined(_REENTRANT)
|
||||
# pragma message( "Excluding Base::CThread - requires multi-threaded compile. (_REENTRANT)" )
|
||||
#else
|
||||
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include "Platform.h"
|
||||
#include "Mutex.h"
|
||||
#include "Event.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CThread
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates threading functionality. Creating classes derived
|
||||
// from CThread provides an easy way to encapsulate tasks that require
|
||||
// their own thread.
|
||||
//
|
||||
// Public Methods:
|
||||
// StartThread() : Creates the low-level thread handle and begins executing
|
||||
// the CThread::ThreadProc() function within the new thread.
|
||||
// StopThread() : Signals the ThreadProc() function to stop executing using
|
||||
// the mThreadContinue member variable, and waits for the ThreadProc()
|
||||
// function to exit. By default, the function will block for a maximum
|
||||
// of 5 seconds before exiting without the thread halting.
|
||||
// IsThreadActive() : Returns true if the physical thread is still executing
|
||||
// within the ThreadProc() function, otherwise it returns false.
|
||||
// ThreadProc() : Pure-virtual function that will be executed when the StartThread()
|
||||
// function is called. Derived classes must implement this function. The
|
||||
// mThreadContinue member variable should be used internal the the ThreadProc()
|
||||
// function to indicate whether it should continue executing or exit.
|
||||
// Protected Attributes:
|
||||
// mThreadContinue : Boolean value indicating to the ThreadProc() function
|
||||
// whether to continue executing or to exit. If mThreadContinue is true,
|
||||
// ThreadProc() should continue, otherwise ThreadProc() should exit. It
|
||||
// left up to the derived class to implement a ThreadProc() function that
|
||||
// uses the mThreadContinue member.
|
||||
//
|
||||
//
|
||||
class CThread
|
||||
{
|
||||
friend void * threadProc(void *);
|
||||
|
||||
public:
|
||||
enum { eSTOP_SUCCESS, eSTOP_TIMEOUT };
|
||||
public:
|
||||
CThread();
|
||||
virtual ~CThread();
|
||||
|
||||
void StartThread();
|
||||
int32 StopThread(int timeout=5);
|
||||
bool IsThreadActive() { return mThreadActive; }
|
||||
|
||||
protected:
|
||||
virtual void ThreadProc() {}
|
||||
|
||||
protected:
|
||||
bool mThreadContinue;
|
||||
private:
|
||||
pthread_t mThreadID;
|
||||
bool mThreadActive;
|
||||
};
|
||||
|
||||
|
||||
class CThreadPool
|
||||
{
|
||||
private:
|
||||
class CMember : public CThread
|
||||
{
|
||||
public:
|
||||
CMember(CThreadPool * parent);
|
||||
virtual ~CMember();
|
||||
|
||||
bool Execute(void( *function )( void * ), void * arg);
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
virtual void ThreadProc();
|
||||
|
||||
private:
|
||||
CThreadPool * mParent;
|
||||
void( * mFunction )( void * );
|
||||
void * mArgument;
|
||||
CEvent mSemaphore;
|
||||
};
|
||||
friend class CMember;
|
||||
|
||||
public:
|
||||
CThreadPool(uint32 maxThreads, uint32 minThreads=1, uint32 timeout=15*60);
|
||||
~CThreadPool();
|
||||
|
||||
bool Execute(void( *function )( void * ), void * arg);
|
||||
|
||||
private:
|
||||
uint32 GetTimeOut();
|
||||
void OnStartup(CMember * member);
|
||||
void OnIdle(CMember * member);
|
||||
bool OnDestory(CMember * member);
|
||||
|
||||
private:
|
||||
CMutex mMutex;
|
||||
std::set<CMember *> mIdleMember;
|
||||
std::set<CMember *> mBusyMember;
|
||||
std::list<CMember *> mNullMember;
|
||||
uint32 mThreadCount;
|
||||
|
||||
uint32 mMaxThreads;
|
||||
uint32 mMinThreads;
|
||||
uint32 mTimeOut;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_REENTRANT)
|
||||
|
||||
#endif // BASE_LINUX_THREAD_H
|
||||
@@ -0,0 +1,42 @@
|
||||
////////////////////////////////////////
|
||||
// Types.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Define integer types that are unambiguous with respect to size
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_TYPES_H
|
||||
#define BASE_LINUX_TYPES_H
|
||||
|
||||
#include <sys/bitypes.h>
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
|
||||
namespace Base
|
||||
{
|
||||
#define INT32_MAX 0x7FFFFFFF
|
||||
#define INT32_MIN 0x80000000
|
||||
#define UINT32_MAX 0xFFFFFFFF
|
||||
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
|
||||
typedef int32_t int32;
|
||||
typedef u_int32_t uint32;
|
||||
typedef int64_t int64;
|
||||
typedef u_int64_t uint64;
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // BASE_LINUX_TYPES_H
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef BASE_SOLARIS_ARCHIVE_H
|
||||
#define BASE_SOLARIS_ARCHIVE_H
|
||||
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
#ifdef PACK_BIG_ENDIAN
|
||||
|
||||
inline double byteSwap(double value) { return value; }
|
||||
inline float byteSwap(float value) { return value; }
|
||||
inline uint64 byteSwap(uint64 value) { return value; }
|
||||
inline int64 byteSwap(int64 value) { return value; }
|
||||
inline uint32 byteSwap(uint32 value) { return value; }
|
||||
inline int32 byteSwap(int32 value) { return value; }
|
||||
inline uint16 byteSwap(uint16 value) { return value; }
|
||||
inline int16 byteSwap(int16 value) { return value; }
|
||||
|
||||
#else
|
||||
|
||||
inline double byteSwap(double value) { byteReverse64(&value); return value; }
|
||||
inline float byteSwap(float value) { byteReverse32(&value); return value; }
|
||||
inline uint64 byteSwap(uint64 value) { byteReverse64(&value); return value; }
|
||||
inline int64 byteSwap(int64 value) { byteReverse64(&value); return value; }
|
||||
inline uint32 byteSwap(uint32 value) { byteReverse32(&value); return value; }
|
||||
inline int32 byteSwap(int32 value) { byteReverse32(&value); return value; }
|
||||
inline uint16 byteSwap(uint16 value) { byteReverse16(&value); return value; }
|
||||
inline int16 byteSwap(int16 value) { byteReverse16(&value); return value; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
#include "../BlockAllocator.h"
|
||||
|
||||
namespace Base
|
||||
{
|
||||
BlockAllocator::BlockAllocator()
|
||||
{
|
||||
for(unsigned i = 0; i < 31; i++)
|
||||
{
|
||||
m_blocks[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BlockAllocator::~BlockAllocator()
|
||||
{
|
||||
// free all allocated memory blocks
|
||||
for(unsigned i = 0; i < 31; i++)
|
||||
{
|
||||
while(m_blocks[i] != NULL)
|
||||
{
|
||||
unsigned *tmp = m_blocks[i];
|
||||
m_blocks[i] = (unsigned *)*m_blocks[i];
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate a block that is the next power of two greater than the # of bytes passed.
|
||||
// 33 bytes yields a 64 byte block of memory and so forth.
|
||||
|
||||
void *BlockAllocator::getBlock(unsigned bytes)
|
||||
{
|
||||
unsigned accum = 16, bits = 16;
|
||||
unsigned *handle = NULL;
|
||||
|
||||
// Perform a binary search looking for the highest bit.
|
||||
|
||||
while(bits != 0)
|
||||
{
|
||||
// If bytes is less than the bit we're testing for, subtract half
|
||||
// from the bit value and repeat
|
||||
if(bytes < (unsigned)(1 << accum))
|
||||
{
|
||||
bits /= 2;
|
||||
accum -= bits;
|
||||
}
|
||||
// If bytes is greater than the bit we're testing for, add half
|
||||
// from the but value and repeat
|
||||
else if(bytes > (unsigned)(1 << accum))
|
||||
{
|
||||
bits /= 2;
|
||||
accum += bits;
|
||||
}
|
||||
// Got lucky and hit the value dead on
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// At this point accum contains the most significant bit index, increment
|
||||
accum++;
|
||||
if(accum < 2)
|
||||
{
|
||||
accum = 2;
|
||||
}
|
||||
|
||||
// Note that when memory is actually allocated, 8 extra bytes will be allocated.at the front
|
||||
// The first integer is the address of the next block of memory when the block is in the allocator
|
||||
// The second integer is the bit length of the block
|
||||
// Memory is allocated on 4 byte boundaries to sidestep byte alignment problems
|
||||
|
||||
|
||||
// Check if the allocator already has a block of that size
|
||||
if(m_blocks[accum] == 0)
|
||||
{
|
||||
// remove the pre allocated block from the linked list
|
||||
handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned));
|
||||
handle[1] = accum;
|
||||
handle[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate a new block
|
||||
handle = m_blocks[accum];
|
||||
m_blocks[accum] = (unsigned *)handle[0];
|
||||
handle[0] = 0;
|
||||
}
|
||||
// return a pointer that skips over the header used for the allocator's purposes
|
||||
return(handle + 2);
|
||||
}
|
||||
|
||||
void BlockAllocator::returnBlock(unsigned *handle)
|
||||
{
|
||||
// C++ allows for safe deletion of a NULL pointer
|
||||
if(handle)
|
||||
{
|
||||
// Update the allocator linked list, insert this entry at the head
|
||||
*(handle - 2) = (unsigned)m_blocks[*(handle - 1)];
|
||||
// Add this entry to the proper linked list node
|
||||
m_blocks[*(handle - 1)] = (handle - 2);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,93 @@
|
||||
////////////////////////////////////////
|
||||
// Event.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CEvent class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#if defined(_REENTRANT)
|
||||
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CEvent::CEvent()
|
||||
{
|
||||
mWaiting = 0;
|
||||
mSignaled = false;
|
||||
mInitialized = false;
|
||||
if (pthread_cond_init( &mCond, NULL ) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init( &mMutex, NULL ) != 0)
|
||||
{
|
||||
pthread_cond_destroy( &mCond );
|
||||
return;
|
||||
}
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
CEvent::~CEvent()
|
||||
{
|
||||
if (mInitialized)
|
||||
{
|
||||
pthread_cond_destroy(&mCond);
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
}
|
||||
}
|
||||
|
||||
int32 CEvent::Wait(uint32 timeout)
|
||||
{
|
||||
if (!mInitialized)
|
||||
return CEvent::eWAIT_ERROR;
|
||||
|
||||
int result;
|
||||
pthread_mutex_lock(&mMutex);
|
||||
|
||||
if (mSignaled)
|
||||
{
|
||||
mSignaled = false;
|
||||
}
|
||||
else if (!timeout)
|
||||
{
|
||||
mWaiting++;
|
||||
result = pthread_cond_wait(&mCond, &mMutex);
|
||||
mWaiting--;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct timespec wake_time;
|
||||
|
||||
clock_gettime( CLOCK_REALTIME, &wake_time );
|
||||
wake_time.tv_sec += timeout/1000;
|
||||
wake_time.tv_nsec += (timeout%1000)*1000000;
|
||||
|
||||
// normalize new time
|
||||
wake_time.tv_sec += wake_time.tv_nsec / 1000000000;
|
||||
wake_time.tv_nsec %= 1000000000;
|
||||
|
||||
mWaiting++;
|
||||
result = pthread_cond_timedwait( &mCond, &mMutex, &wake_time );
|
||||
mWaiting--;
|
||||
}
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
|
||||
if (result == 0)
|
||||
return CEvent::eWAIT_SIGNAL;
|
||||
else if (result == ETIMEDOUT)
|
||||
return CEvent::eWAIT_TIMEOUT;
|
||||
else
|
||||
return CEvent::eWAIT_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // #if defined(_REENTRANT)
|
||||
@@ -0,0 +1,83 @@
|
||||
////////////////////////////////////////
|
||||
// Event.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CEvent class that encapsulates the functionality of a
|
||||
// single-locking semaphore.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_SOLARIS_EVENT_H
|
||||
#define BASE_SOLARIS_EVENT_H
|
||||
|
||||
#if !defined(_REENTRANT)
|
||||
# pragma message( "Excluding Base::CEvent - requires multi-threaded compile. (_REENTRANT)" )
|
||||
#else
|
||||
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CEvent
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates the functionality of a singal-locking semaphore.
|
||||
// This class is valuable for thread syncronization when a thead's
|
||||
// execution needs to be dependent upon another thread.
|
||||
//
|
||||
// Public Methods:
|
||||
// Signal() : Signals a thread that has called Wait() so that it can
|
||||
// continue execution. This function returns true if the waiting
|
||||
// thread was signalled successfully, otherwise false is returned.
|
||||
// Wait() : Halts the calling thread's execution indefinately until
|
||||
// a Singal() call is made by an external thread. If the thread is
|
||||
// successfully signalled, the function returns eWAIT_SIGNAL. If
|
||||
// timeout period expires without a signal, eWAIT_TIMEOUT is returned.
|
||||
// If the function fails, eWAIT_ERROR is returned.
|
||||
//
|
||||
class CEvent
|
||||
{
|
||||
public:
|
||||
CEvent();
|
||||
virtual ~CEvent();
|
||||
|
||||
bool Signal();
|
||||
int32 Wait(uint32 timeout = 0);
|
||||
public:
|
||||
enum { eWAIT_ERROR, eWAIT_SIGNAL, eWAIT_TIMEOUT };
|
||||
private:
|
||||
pthread_mutex_t mMutex;
|
||||
pthread_cond_t mCond;
|
||||
bool mInitialized;
|
||||
bool mSignaled;
|
||||
int32 mWaiting;
|
||||
};
|
||||
|
||||
inline bool CEvent::Signal()
|
||||
{
|
||||
if (!mInitialized)
|
||||
return false;
|
||||
pthread_mutex_lock(&mMutex);
|
||||
if(mWaiting > 0)
|
||||
{
|
||||
pthread_cond_signal(&mCond);
|
||||
}
|
||||
else
|
||||
{
|
||||
mWaiting = true;
|
||||
}
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_SOLARIS_EVENT_H
|
||||
@@ -0,0 +1,374 @@
|
||||
#include "../Logger.h"
|
||||
#include "Mutex.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Base
|
||||
{
|
||||
const char file_sep = '/';
|
||||
|
||||
Logger::Logger(const char *prefix, int level, unsigned size, bool rollDate)
|
||||
: m_defaultLevel(level), m_defaultSize(size), m_dirPrefix(prefix), m_rollDate(rollDate)
|
||||
{
|
||||
char buf[1024];
|
||||
FILE *logDir = NULL;
|
||||
|
||||
logDir = fopen(m_dirPrefix.c_str(), "r+");
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(m_dirPrefix.c_str(), 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
|
||||
tm now;
|
||||
time_t t = time(NULL);
|
||||
localtime_r(&t, &now);
|
||||
|
||||
memcpy(&m_lastDateTime, &now, sizeof(tm));
|
||||
if(m_rollDate)
|
||||
{
|
||||
sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buf, "%s", m_dirPrefix.c_str());
|
||||
}
|
||||
logDir = fopen(buf, "r+");
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(buf, 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
m_logPrefix = buf;
|
||||
}
|
||||
|
||||
Logger::~Logger()
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
log((*iter).first, LOG_FILEONLY, "---=== Log Stopped ===---");
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
delete((*iter).second);
|
||||
|
||||
}
|
||||
m_logTable.clear();
|
||||
}
|
||||
|
||||
void Logger::flush(unsigned logenum)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
LogInfo *info = (*iter).second;
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::flushAll()
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
LogInfo *info = (*iter).second;
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::addLog(const char *id, unsigned logenum, int level, unsigned size)
|
||||
{
|
||||
LogInfo *newLog = new LogInfo;
|
||||
newLog->filename = m_logPrefix + file_sep + id + ".log";
|
||||
newLog->name = id;
|
||||
newLog->used = 0;
|
||||
newLog->max = size;
|
||||
newLog->last = 0;
|
||||
newLog->level = level;
|
||||
|
||||
m_logTable.insert(pair<unsigned, LogInfo *>(logenum, newLog));
|
||||
|
||||
if(strcmp("stdout", id) == 0)
|
||||
{
|
||||
newLog->file = stdout;
|
||||
}
|
||||
else if(strcmp("stderr", id) == 0)
|
||||
{
|
||||
newLog->file = stderr;
|
||||
}
|
||||
else
|
||||
{
|
||||
newLog->file = fopen(newLog->filename.c_str(), "a+");
|
||||
}
|
||||
log(logenum, LOG_FILEONLY, "---=== Log Started ===---");
|
||||
}
|
||||
|
||||
void Logger::addLog(const char *id, unsigned logenum)
|
||||
{
|
||||
LogInfo *newLog = new LogInfo;
|
||||
newLog->filename = m_logPrefix + file_sep + id + ".log";
|
||||
newLog->name = id;
|
||||
newLog->used = 0;
|
||||
newLog->max = m_defaultSize;
|
||||
newLog->last = 0;
|
||||
newLog->level = m_defaultLevel;
|
||||
|
||||
m_logTable.insert(pair<unsigned, LogInfo *>(logenum, newLog));
|
||||
|
||||
if(strcmp("stdout", id) == 0)
|
||||
{
|
||||
newLog->file = stdout;
|
||||
}
|
||||
else if(strcmp("stderr", id) == 0)
|
||||
{
|
||||
newLog->file = stderr;
|
||||
}
|
||||
else
|
||||
{
|
||||
newLog->file = fopen(newLog->filename.c_str(), "a+");
|
||||
}
|
||||
log(logenum, LOG_FILEONLY, "---===Log Started ===---");
|
||||
}
|
||||
|
||||
void Logger::updateLog(unsigned logenum, int level, unsigned size)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
(*iter).second->level = level;
|
||||
(*iter).second->max = size;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::removeLog(unsigned logenum)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
log((*iter).first, LOG_ALWAYS, "---=== Log Stopped ===---");
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
delete((*iter).second);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::logSimple(unsigned logenum, int level, const char *message)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
if(iter == m_logTable.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
LogInfo *info = (*iter).second;
|
||||
if(level >= info->level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(info->last != t)
|
||||
{
|
||||
memcpy(&info->ts, localtime(&t), sizeof(tm));
|
||||
info->last = t;
|
||||
}
|
||||
|
||||
if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
#if defined(_REENTRANT)
|
||||
rLock.Lock();
|
||||
#endif
|
||||
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
|
||||
rollDate(t);
|
||||
}
|
||||
#if defined(_REENTRANT)
|
||||
rLock.Unlock();
|
||||
#endif
|
||||
}
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
if(info->max > 0)
|
||||
{
|
||||
int tmp = fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, message);
|
||||
info->used += tmp;
|
||||
if(info->used > info->max)
|
||||
{
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, message);
|
||||
fflush(info->file);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Logger::log(unsigned logenum, int level, const char *message, ...)
|
||||
{
|
||||
char buf[2048];
|
||||
va_list varg;
|
||||
va_start(varg, message);
|
||||
vsnprintf(buf, 2047, message, varg);
|
||||
buf[2047] = 0;
|
||||
va_end(varg);
|
||||
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
if(iter == m_logTable.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
LogInfo *info = (*iter).second;
|
||||
if(level >= info->level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(info->last != t)
|
||||
{
|
||||
localtime_r(&t, &info->ts);
|
||||
info->last = t;
|
||||
}
|
||||
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
#if defined(_REENTRANT)
|
||||
rLock.Lock();
|
||||
#endif
|
||||
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
|
||||
rollDate(t);
|
||||
}
|
||||
#if defined(_REENTRANT)
|
||||
rLock.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
if(info->max > 0)
|
||||
{
|
||||
int tmp = fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, buf);
|
||||
info->used += tmp;
|
||||
if(info->used > info->max)
|
||||
{
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, buf);
|
||||
fflush(info->file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::rollDate(time_t t)
|
||||
{
|
||||
char buf[80];
|
||||
FILE *logDir = NULL;
|
||||
|
||||
logDir = fopen(m_dirPrefix.c_str(), "r+");
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(m_dirPrefix.c_str(), 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
|
||||
tm now;
|
||||
localtime_r(&t, &now);
|
||||
|
||||
sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100));
|
||||
logDir = fopen(buf, "r+");
|
||||
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(buf, 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
m_logPrefix = buf;
|
||||
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
(*iter).second->filename = m_logPrefix + file_sep + (*iter).second->name.c_str() + ".log";
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
(*iter).second->file = fopen((*iter).second->filename.c_str(), "a+");
|
||||
memcpy(&((*iter).second->ts), &now, sizeof(tm));
|
||||
}
|
||||
}
|
||||
|
||||
// mkdir function that creates intermediate directories
|
||||
void Logger::cmkdir(const char *dir, int mode)
|
||||
{
|
||||
char dirbuf[128];
|
||||
strncpy(dirbuf, dir, 127);
|
||||
dirbuf[127] = 0;
|
||||
char *j = dirbuf, *i = dirbuf;
|
||||
int handle;
|
||||
|
||||
while(*i)
|
||||
{
|
||||
if(*i == file_sep)
|
||||
{
|
||||
(*i) = 0;
|
||||
// handle = open(j, O_EXCL); // Ben's original code
|
||||
// if((handle > 0) || (errno != EISDIR && errno != ENOENT))
|
||||
// {
|
||||
// perror("Logger::cmkdir():");
|
||||
// abort();
|
||||
// }
|
||||
|
||||
// This doesnt work under Linux, it returns a valid handle
|
||||
// Instead: see if file exists. If it doesnt, create directory ok
|
||||
// If it exists, do stat to see if it is a dir.
|
||||
// If it is a dir, then ok, create the directory.
|
||||
// If it is a file, error
|
||||
// ging 9-16-2002
|
||||
|
||||
handle = open(j, O_RDONLY);
|
||||
if (handle > 0)
|
||||
{
|
||||
struct stat stat_buffer;
|
||||
int ret = fstat(handle,&stat_buffer);
|
||||
if ((ret == -1) || ((stat_buffer.st_mode | S_IFDIR) == 0))
|
||||
{
|
||||
perror("Logger::cmkdir():");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
mkdir(j, mode);
|
||||
close(handle);
|
||||
(*i) = file_sep;
|
||||
}
|
||||
else if(*(i + 1) == 0)
|
||||
{
|
||||
mkdir(j, mode);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,171 @@
|
||||
# environment variables:
|
||||
# $INCLUDE_PATH is a colon-delimited list of include directories
|
||||
|
||||
EMPTY_CHAR=
|
||||
SPACE_CHAR=$(empty) $(empty)
|
||||
COLON_CHAR=:
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
OUTPUT_FILE_ST=libBase.a
|
||||
OUTPUT_FILE_MT=libBase_MT.a
|
||||
OUTPUT_DIR=../../../lib
|
||||
OBJECT_DIR_ST=./obj_st
|
||||
OBJECT_DIR_MT=./obj_mt
|
||||
|
||||
INCLUDE_DIRS=.. ../
|
||||
|
||||
SOURCE_DIRS=. ..
|
||||
SOURCE_FILES=
|
||||
|
||||
LIBRARY_DIRS=
|
||||
LIBRARY_FILES=
|
||||
|
||||
CFLAGS_USER=
|
||||
LFLAGS_USER=
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
INCLUDE_DIR_LIST=$(subst $(COLON_CHAR),$(SPACE_CHAR),$(INCLUDE_PATH)) $(INCLUDE_DIRS)
|
||||
INCLUDE_FLAGS=$(addprefix -I,$(INCLUDE_DIR_LIST))
|
||||
CFLAGS_ST=$(INCLUDE_FLAGS) $(CFLAGS_USER) -D_GNU_SOURCE -Wall -Wno-unknown-pragmas
|
||||
CFLAGS_MT=$(INCLUDE_FLAGS) $(CFLAGS_USER) -D_GNU_SOURCE -D_REENTRANT -Wall -Wno-unknown-pragmas
|
||||
CFLAGS_DEBUG_ST=$(CFLAGS_ST) -D_DEBUG -g
|
||||
CFLAGS_RELEASE_ST=$(CFLAGS_ST) -DNDEBUG -O2
|
||||
CFLAGS_DEBUG_MT=$(CFLAGS_MT) -D_DEBUG -g
|
||||
CFLAGS_RELEASE_MT=$(CFLAGS_MT) -DNDEBUG -O2
|
||||
|
||||
LIBRARY_FLAGS=$(addprefix -l,$(LIBRARIES))
|
||||
LFLAGS=$(LIBRARY_FLAGS) $(LFLAGS_USER) -r
|
||||
LFLAGS_DEBUG=$(LFLAGS)
|
||||
LFLAGS_RELEASE=$(LFLAGS)
|
||||
|
||||
CPP=g++
|
||||
LINK=ld
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
DEBUG_OBJ_DIR_ST=$(OBJECT_DIR_ST)/debug
|
||||
RELEASE_OBJ_DIR_ST=$(OBJECT_DIR_ST)/release
|
||||
DEBUG_OBJ_DIR_MT=$(OBJECT_DIR_MT)/debug
|
||||
RELEASE_OBJ_DIR_MT=$(OBJECT_DIR_MT)/release
|
||||
|
||||
DEBUG_DIR=$(OUTPUT_DIR)/debug
|
||||
RELEASE_DIR=$(OUTPUT_DIR)/release
|
||||
|
||||
FIND=$(shell ls $(x)/*.cpp)
|
||||
SOURCE_LIST = $(SOURCE_FILES) $(foreach x, $(SOURCE_DIRS), $(FIND))
|
||||
|
||||
DEBUG_OBJ_LIST_ST=$(addprefix $(DEBUG_OBJ_DIR_ST)/, $(notdir $(SOURCE_LIST:.cpp=.o)))
|
||||
RELEASE_OBJ_LIST_ST=$(addprefix $(RELEASE_OBJ_DIR_ST)/, $(notdir $(SOURCE_LIST:.cpp=.o)))
|
||||
DEBUG_OBJ_LIST_MT=$(addprefix $(DEBUG_OBJ_DIR_MT)/, $(notdir $(SOURCE_LIST:.cpp=.o)))
|
||||
RELEASE_OBJ_LIST_MT=$(addprefix $(RELEASE_OBJ_DIR_MT)/, $(notdir $(SOURCE_LIST:.cpp=.o)))
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
release_st: echoRelease_st releaseDirs_st $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo Successfully built $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo
|
||||
|
||||
debug_st: debugDirs_st $(DEBUG_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo Successfully built $(DEBUG_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo
|
||||
|
||||
release_mt: echoRelease_mt releaseDirs_mt $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo Successfully built $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo
|
||||
|
||||
debug_mt: debugDirs_mt $(DEBUG_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo Successfully built $(DEBUG_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo
|
||||
|
||||
all: clean debug_st release_st debug_mt release_mt
|
||||
|
||||
all_st: clean debug_st release_st
|
||||
|
||||
all_mt: clean debug_mt release_mt
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
debugDirs_st :
|
||||
@mkdir -p $(DEBUG_OBJ_DIR_ST)
|
||||
@mkdir -p $(DEBUG_DIR)
|
||||
|
||||
$(DEBUG_OBJ_DIR_ST)/%.o : $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
$(CPP) $(CFLAGS_DEBUG_ST) -o $@ -c $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
|
||||
$(DEBUG_DIR)/$(OUTPUT_FILE_ST): $(DEBUG_OBJ_LIST_ST)
|
||||
$(LINK) $(LFLAGS_DEBUG) -o $@ $(DEBUG_OBJ_LIST_ST)
|
||||
|
||||
|
||||
debugDirs_mt :
|
||||
@mkdir -p $(DEBUG_OBJ_DIR_MT)
|
||||
@mkdir -p $(DEBUG_DIR)
|
||||
|
||||
$(DEBUG_OBJ_DIR_MT)/%.o : $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
$(CPP) $(CFLAGS_DEBUG_MT) -o $@ -c $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
|
||||
$(DEBUG_DIR)/$(OUTPUT_FILE_MT): $(DEBUG_OBJ_LIST_MT)
|
||||
$(LINK) $(LFLAGS_DEBUG) -o $@ $(DEBUG_OBJ_LIST_MT)
|
||||
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
echoRelease_st :
|
||||
@echo Building $(OUTPUT_FILE_ST)
|
||||
@echo compiler: $(CPP) $(CFLAGS_RELEASE_ST)
|
||||
@echo linker: $(LINK) $(LFLAGS_RELEASE)
|
||||
@echo
|
||||
|
||||
echoRelease_mt :
|
||||
@echo Building $(OUTPUT_FILE_MT)
|
||||
@echo compiler: $(CPP) $(CFLAGS_RELEASE_MT)
|
||||
@echo linker: $(LINK) $(LFLAGS_RELEASE)
|
||||
@echo
|
||||
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
releaseDirs_st :
|
||||
@mkdir -p $(RELEASE_OBJ_DIR_ST)
|
||||
@mkdir -p $(RELEASE_DIR)
|
||||
|
||||
$(RELEASE_OBJ_DIR_ST)/%.o : $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
@echo compiling $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
@$(CPP) $(CFLAGS_RELEASE_ST) -o $@ -c $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
|
||||
$(RELEASE_DIR)/$(OUTPUT_FILE_ST): $(RELEASE_OBJ_LIST_ST)
|
||||
@echo linking $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@$(LINK) $(LFLAGS_RELEASE) -o $@ $(RELEASE_OBJ_LIST_ST)
|
||||
|
||||
releaseDirs_mt :
|
||||
@mkdir -p $(RELEASE_OBJ_DIR_MT)
|
||||
@mkdir -p $(RELEASE_DIR)
|
||||
|
||||
$(RELEASE_OBJ_DIR_MT)/%.o : $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
@echo compiling $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
@$(CPP) $(CFLAGS_RELEASE_MT) -o $@ -c $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
|
||||
$(RELEASE_DIR)/$(OUTPUT_FILE_MT): $(RELEASE_OBJ_LIST_MT)
|
||||
@echo linking $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@$(LINK) $(LFLAGS_RELEASE) -o $@ $(RELEASE_OBJ_LIST_MT)
|
||||
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
clean:
|
||||
@echo removing "$(OBJECT_DIR_ST)/*.o"
|
||||
@rm -rf $(OBJECT_DIR_ST)
|
||||
@echo removing "$(OBJECT_DIR_MT)/*.o"
|
||||
@rm -rf $(OBJECT_DIR_MT)
|
||||
@echo removing $(DEBUG_DIR)/$(OUTPUT_FILE_ST)
|
||||
@rm -f $(DEBUG_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo removing $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@rm -f $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo removing $(DEBUG_DIR)/$(OUTPUT_FILE_MT)
|
||||
@rm -f $(DEBUG_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo removing $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@rm -f $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
////////////////////////////////////////
|
||||
// Mutex.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CMutex class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#if defined(_REENTRANT)
|
||||
|
||||
|
||||
#include "Mutex.h"
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CMutex::CMutex()
|
||||
{
|
||||
mInitialized = (pthread_mutex_init(&mMutex, 0) == 0);
|
||||
}
|
||||
|
||||
CMutex::~CMutex()
|
||||
{
|
||||
if (mInitialized)
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // #if defined(_REENTRANT)
|
||||
@@ -0,0 +1,71 @@
|
||||
////////////////////////////////////////
|
||||
// Mutex.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CMutex class that encapsulates the functionality of a
|
||||
// mutually-exclusive device.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_SOLARIS_MUTEX_H
|
||||
#define BASE_SOLARIS_MUTEX_H
|
||||
|
||||
#if !defined(_REENTRANT)
|
||||
# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_REENTRANT)" )
|
||||
#else
|
||||
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CMutex
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates the functionality of a mutually-exclusive device.
|
||||
// This class is valuable for protecting against race conditions
|
||||
// within threaded applications. The CMutex class can be used to
|
||||
// only allow a single thread to run within a specified code
|
||||
// segment at a time.
|
||||
//
|
||||
// Public Methods:
|
||||
// Lock() : Locks the mutex. If the mutex is already locked, the
|
||||
// operating system will block the calling thread until another
|
||||
// thread has unlocked the mutex.
|
||||
// Unlock() : Unlocks the mutex.
|
||||
//
|
||||
class CMutex
|
||||
{
|
||||
public:
|
||||
CMutex();
|
||||
~CMutex();
|
||||
|
||||
void Lock();
|
||||
void Unlock();
|
||||
private:
|
||||
pthread_mutex_t mMutex;
|
||||
bool mInitialized;
|
||||
};
|
||||
|
||||
inline void CMutex::Lock(void)
|
||||
{
|
||||
if (mInitialized)
|
||||
pthread_mutex_lock(&mMutex);
|
||||
}
|
||||
|
||||
inline void CMutex::Unlock(void)
|
||||
{
|
||||
if (mInitialized)
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_SOLARIS_MUTEX_H
|
||||
@@ -0,0 +1,46 @@
|
||||
////////////////////////////////////////
|
||||
// Platform.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the global functionality declaired in Platform.h.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#include <ctype.h>
|
||||
#include "Platform.h"
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
// Implementation of microsoft strlwr extension
|
||||
// This non-ANSI function is not supported under UNIX
|
||||
void _strlwr(char * s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
*s = tolower(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of microsoft strupr extension
|
||||
// This non-ANSI function is not supported under UNIX
|
||||
void _strupr(char * s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CTimer::CTimer() :
|
||||
mTimer(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
////////////////////////////////////////
|
||||
// Platform.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Include relevent system headers that are platform specific.
|
||||
// 2. Declair global platform specific functionality.
|
||||
// 3. Include primative type definitions
|
||||
//
|
||||
// Global Functions:
|
||||
// getTimer() : Return the current high resolution clock count.
|
||||
// getTimerFrequency() : Return the frequency of the high resolution clock.
|
||||
// sleep() : Voluntarily relinquish timeslice of the calling thread for a
|
||||
// specified number of milliseconds.
|
||||
// strlwr() : Alters the contents of a string, making it all lower-case.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_SOLARIS_PLATFORM_H
|
||||
#define BASE_SOLARIS_PLATFORM_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
namespace Base
|
||||
{
|
||||
uint64 getTimer(void);
|
||||
uint64 getTimerFrequency(void);
|
||||
void Sleep(uint32 ms);
|
||||
|
||||
inline uint64 getTimer(void)
|
||||
{
|
||||
uint64 t;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, 0);
|
||||
t = tv.tv_sec;
|
||||
t = t * 1000000;
|
||||
t += tv.tv_usec;
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint64 getTimerFrequency(void)
|
||||
{
|
||||
uint64 f = 1000000;
|
||||
return f;
|
||||
}
|
||||
|
||||
inline void sleep(uint32 ms)
|
||||
{
|
||||
//usleep(static_cast<unsigned long>(ms * 1000));
|
||||
struct timeval sleep_tv;
|
||||
sleep_tv.tv_sec = ms / 1000;
|
||||
sleep_tv.tv_usec = (ms % 1000) * 1000;
|
||||
select(1, NULL, NULL, NULL, &sleep_tv);
|
||||
}
|
||||
|
||||
void _strlwr(char * s);
|
||||
void _strupr(char * s);
|
||||
|
||||
|
||||
class CTimer
|
||||
{
|
||||
public:
|
||||
CTimer();
|
||||
|
||||
void Set(uint32 seconds);
|
||||
void Signal();
|
||||
bool Expired();
|
||||
|
||||
private:
|
||||
uint32 mTimer;
|
||||
};
|
||||
|
||||
inline void CTimer::Set(uint32 interval)
|
||||
{
|
||||
mTimer = (uint32)time(0) + interval;
|
||||
}
|
||||
|
||||
inline void CTimer::Signal()
|
||||
{
|
||||
mTimer = 0;
|
||||
}
|
||||
|
||||
inline bool CTimer::Expired()
|
||||
{
|
||||
return (mTimer <= (uint32)time(0));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif BASE_SOLARIS_PLATFORM_H
|
||||
@@ -0,0 +1,258 @@
|
||||
////////////////////////////////////////
|
||||
// Thread.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CThread class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#if defined(_REENTRANT)
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include "Thread.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
void *threadProc(void *threadPtr)
|
||||
{
|
||||
CThread &thread = *((CThread*)threadPtr);
|
||||
thread.mThreadActive = true;
|
||||
thread.ThreadProc();
|
||||
thread.mThreadActive = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CThread::CThread()
|
||||
{
|
||||
mThreadID = 0;
|
||||
mThreadActive = false;
|
||||
mThreadContinue = false;
|
||||
}
|
||||
|
||||
CThread::~CThread()
|
||||
{
|
||||
StopThread();
|
||||
}
|
||||
|
||||
void CThread::StartThread()
|
||||
{
|
||||
mThreadContinue = true;
|
||||
pthread_create(&mThreadID,0,threadProc,this);
|
||||
while (!IsThreadActive())
|
||||
Base::sleep(1);
|
||||
}
|
||||
|
||||
int32 CThread::StopThread(int timeout)
|
||||
{
|
||||
timeout += time(0);
|
||||
|
||||
mThreadContinue = false;
|
||||
while (mThreadActive && time(0)<timeout)
|
||||
sleep(1);
|
||||
if (mThreadActive)
|
||||
{
|
||||
mThreadActive = false;
|
||||
return eSTOP_TIMEOUT;
|
||||
}
|
||||
return eSTOP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CThreadPool::CMember::CMember(CThreadPool * parent) :
|
||||
mParent(parent),
|
||||
mFunction(NULL),
|
||||
mArgument(NULL),
|
||||
mSemaphore()
|
||||
{
|
||||
StartThread();
|
||||
}
|
||||
|
||||
CThreadPool::CMember::~CMember()
|
||||
{
|
||||
}
|
||||
|
||||
void CThreadPool::CMember::Destroy()
|
||||
{
|
||||
mThreadContinue = false;
|
||||
mSemaphore.Signal();
|
||||
}
|
||||
|
||||
bool CThreadPool::CMember::Execute(void( *function )( void * ), void * arg)
|
||||
{
|
||||
if (mFunction)
|
||||
return false;
|
||||
|
||||
mArgument = arg;
|
||||
mFunction = function;
|
||||
mSemaphore.Signal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CThreadPool::CMember::ThreadProc()
|
||||
{
|
||||
while (mThreadContinue)
|
||||
{
|
||||
mParent->OnIdle(this);
|
||||
mSemaphore.Wait(mParent->GetTimeOut()*1000);
|
||||
mParent->OnBusy(this);
|
||||
|
||||
if (mFunction)
|
||||
{
|
||||
mFunction(mArgument);
|
||||
mArgument = NULL;
|
||||
mFunction = NULL;
|
||||
}
|
||||
else
|
||||
mThreadContinue = false;
|
||||
}
|
||||
|
||||
mParent->OnDestory(this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CThreadPool::CThreadPool(uint32 maxThreads, uint32 minThreads, uint32 timeout) :
|
||||
mMutex(),
|
||||
mIdleMember(),
|
||||
mBusyMember(),
|
||||
mNullMember(),
|
||||
mThreadCount(0),
|
||||
mMaxThreads(maxThreads),
|
||||
mMinThreads(minThreads),
|
||||
mTimeOut(timeout)
|
||||
{
|
||||
if (mMaxThreads == 0) mMaxThreads = 1;
|
||||
if (mMinThreads == 0) mMinThreads = 1;
|
||||
if (mMinThreads > mMaxThreads) mMinThreads = mMaxThreads;
|
||||
|
||||
if (mTimeOut < 60)
|
||||
mTimeOut = 60;
|
||||
|
||||
for (uint32 i=0; i<mMinThreads; i++)
|
||||
new CMember(this);
|
||||
}
|
||||
|
||||
CThreadPool::~CThreadPool()
|
||||
{
|
||||
set<CMember *>::iterator setIterator;
|
||||
|
||||
mMutex.Lock();
|
||||
setIterator = mBusyMember.begin();
|
||||
while (setIterator != mBusyMember.end())
|
||||
(*setIterator++)->Destroy();
|
||||
mMutex.Unlock();
|
||||
|
||||
while (mThreadCount)
|
||||
{
|
||||
mMutex.Lock();
|
||||
setIterator = mIdleMember.begin();
|
||||
while (setIterator != mIdleMember.end())
|
||||
(*setIterator++)->Destroy();
|
||||
mMutex.Unlock();
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
mMutex.Lock();
|
||||
while (!mNullMember.empty())
|
||||
{
|
||||
delete mNullMember.front();
|
||||
mNullMember.pop_front();
|
||||
}
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
bool CThreadPool::Execute(void( *function )( void * ), void * arg)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
if (mIdleMember.empty())
|
||||
{
|
||||
if (mThreadCount < mMaxThreads)
|
||||
new CMember(this);
|
||||
mMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!mNullMember.empty())
|
||||
{
|
||||
delete mNullMember.front();
|
||||
mNullMember.pop_front();
|
||||
}
|
||||
|
||||
CMember * member = *(mIdleMember.begin());
|
||||
mIdleMember.erase(member);
|
||||
member->Execute(function,arg);
|
||||
|
||||
mMutex.Unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 CThreadPool::GetTimeOut()
|
||||
{
|
||||
return mTimeOut;
|
||||
}
|
||||
|
||||
void CThreadPool::OnIdle(CMember * member)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
set<CMember *>::iterator setIterator = mBusyMember.find(member);
|
||||
if (setIterator != mBusyMember.end())
|
||||
mBusyMember.erase(member);
|
||||
else
|
||||
mThreadCount++;
|
||||
mIdleMember.insert(member);
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
void CThreadPool::OnBusy(CMember * member)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
mBusyMember.insert(member);
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
void CThreadPool::OnDestory(CMember * member)
|
||||
{
|
||||
set<CMember *>::iterator setIterator;
|
||||
|
||||
mMutex.Lock();
|
||||
|
||||
setIterator = mBusyMember.find(member);
|
||||
if (setIterator != mBusyMember.end())
|
||||
{
|
||||
mNullMember.push_back(member);
|
||||
mBusyMember.erase(member);
|
||||
mThreadCount--;
|
||||
}
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // #if defined(_REENTRANT)
|
||||
@@ -0,0 +1,139 @@
|
||||
////////////////////////////////////////
|
||||
// Thread.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CThread class that encapsulates threading functionality.
|
||||
// This abstract base class in intended to be used to encapsulate
|
||||
// individual tasks that require threading in derived classes.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_SOLARIS_THREAD_H
|
||||
#define BASE_SOLARIS_THREAD_H
|
||||
|
||||
#if !defined(_REENTRANT)
|
||||
# pragma message( "Excluding Base::CThread - requires multi-threaded compile. (_REENTRANT)" )
|
||||
#else
|
||||
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include "Platform.h"
|
||||
#include "Mutex.h"
|
||||
#include "Event.h"
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CThread
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates threading functionality. Creating classes derived
|
||||
// from CThread provides an easy way to encapsulate tasks that require
|
||||
// their own thread.
|
||||
//
|
||||
// Public Methods:
|
||||
// StartThread() : Creates the low-level thread handle and begins executing
|
||||
// the CThread::ThreadProc() function within the new thread.
|
||||
// StopThread() : Signals the ThreadProc() function to stop executing using
|
||||
// the mThreadContinue member variable, and waits for the ThreadProc()
|
||||
// function to exit. By default, the function will block for a maximum
|
||||
// of 5 seconds before exiting without the thread halting.
|
||||
// IsThreadActive() : Returns true if the physical thread is still executing
|
||||
// within the ThreadProc() function, otherwise it returns false.
|
||||
// ThreadProc() : Pure-virtual function that will be executed when the StartThread()
|
||||
// function is called. Derived classes must implement this function. The
|
||||
// mThreadContinue member variable should be used internal the the ThreadProc()
|
||||
// function to indicate whether it should continue executing or exit.
|
||||
// Protected Attributes:
|
||||
// mThreadContinue : Boolean value indicating to the ThreadProc() function
|
||||
// whether to continue executing or to exit. If mThreadContinue is true,
|
||||
// ThreadProc() should continue, otherwise ThreadProc() should exit. It
|
||||
// left up to the derived class to implement a ThreadProc() function that
|
||||
// uses the mThreadContinue member.
|
||||
//
|
||||
//
|
||||
class CThread
|
||||
{
|
||||
friend void * threadProc(void *);
|
||||
|
||||
public:
|
||||
enum { eSTOP_SUCCESS, eSTOP_TIMEOUT };
|
||||
public:
|
||||
CThread();
|
||||
virtual ~CThread();
|
||||
|
||||
void StartThread();
|
||||
int32 StopThread(int timeout=5);
|
||||
bool IsThreadActive() { return mThreadActive; }
|
||||
|
||||
protected:
|
||||
virtual void ThreadProc() = 0;
|
||||
|
||||
protected:
|
||||
bool mThreadContinue;
|
||||
private:
|
||||
bool mThreadActive;
|
||||
pthread_t mThreadID;
|
||||
};
|
||||
|
||||
|
||||
class CThreadPool
|
||||
{
|
||||
private:
|
||||
class CMember : public CThread
|
||||
{
|
||||
public:
|
||||
CMember(CThreadPool * parent);
|
||||
virtual ~CMember();
|
||||
|
||||
bool Execute(void( *function )( void * ), void * arg);
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
virtual void ThreadProc();
|
||||
|
||||
private:
|
||||
CThreadPool * mParent;
|
||||
void( * mFunction )( void * );
|
||||
void * mArgument;
|
||||
CEvent mSemaphore;
|
||||
};
|
||||
friend class CMember;
|
||||
|
||||
public:
|
||||
CThreadPool(uint32 maxThreads, uint32 minThreads=1, uint32 timeout=15*60);
|
||||
~CThreadPool();
|
||||
|
||||
bool Execute(void( *function )( void * ), void * arg);
|
||||
|
||||
private:
|
||||
uint32 GetTimeOut();
|
||||
void OnIdle(CMember * member);
|
||||
void OnBusy(CMember * member);
|
||||
void OnDestory(CMember * member);
|
||||
|
||||
private:
|
||||
CMutex mMutex;
|
||||
std::set<CMember *> mIdleMember;
|
||||
std::set<CMember *> mBusyMember;
|
||||
std::list<CMember *> mNullMember;
|
||||
uint32 mThreadCount;
|
||||
|
||||
uint32 mMaxThreads;
|
||||
uint32 mMinThreads;
|
||||
uint32 mTimeOut;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_SOLARIS_THREAD_H
|
||||
@@ -0,0 +1,28 @@
|
||||
////////////////////////////////////////
|
||||
// Types.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Define integer types that are unambiguous with respect to size
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_SOLARIS_TYPES_H
|
||||
#define BASE_SOLARIS_TYPES_H
|
||||
|
||||
namespace Base
|
||||
{
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
|
||||
typedef signed int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
}
|
||||
|
||||
#endif // BASE_SOLARIS_TYPES_H
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef BASE_WIN32_ARCHIVE_H
|
||||
#define BASE_WIN32_ARCHIVE_H
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
#ifdef PACK_BIG_ENDIAN
|
||||
|
||||
inline double byteSwap(double value) { byteReverse64(&value); return value; }
|
||||
inline float byteSwap(float value) { byteReverse32(&value); return value; }
|
||||
inline uint64 byteSwap(uint64 value) { byteReverse64(&value); return value; }
|
||||
inline int64 byteSwap(int64 value) { byteReverse64(&value); return value; }
|
||||
inline uint32 byteSwap(uint32 value) { byteReverse32(&value); return value; }
|
||||
inline int32 byteSwap(int32 value) { byteReverse32(&value); return value; }
|
||||
inline uint16 byteSwap(uint16 value) { byteReverse16(&value); return value; }
|
||||
inline int16 byteSwap(int16 value) { byteReverse16(&value); return value; }
|
||||
|
||||
#else
|
||||
|
||||
inline double byteSwap(double value) { return value; }
|
||||
inline float byteSwap(float value) { return value; }
|
||||
inline uint64 byteSwap(uint64 value) { return value; }
|
||||
inline int64 byteSwap(int64 value) { return value; }
|
||||
inline uint32 byteSwap(uint32 value) { return value; }
|
||||
inline int32 byteSwap(int32 value) { return value; }
|
||||
inline uint16 byteSwap(uint16 value) { return value; }
|
||||
inline int16 byteSwap(int16 value) { return value; }
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,112 @@
|
||||
#include "../BlockAllocator.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
BlockAllocator::BlockAllocator()
|
||||
{
|
||||
for(unsigned i = 0; i < 31; i++)
|
||||
{
|
||||
m_blocks[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BlockAllocator::~BlockAllocator()
|
||||
{
|
||||
// free all allocated memory blocks
|
||||
for(unsigned i = 0; i < 31; i++)
|
||||
{
|
||||
while(m_blocks[i] != NULL)
|
||||
{
|
||||
unsigned *tmp = m_blocks[i];
|
||||
m_blocks[i] = (unsigned *)*m_blocks[i];
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate a block that is the next power of two greater than the # of bytes passed.
|
||||
// 33 bytes yields a 64 byte block of memory and so forth.
|
||||
|
||||
void *BlockAllocator::getBlock(unsigned bytes)
|
||||
{
|
||||
unsigned accum = 16, bits = 16;
|
||||
unsigned *handle = NULL;
|
||||
|
||||
// Perform a binary search looking for the highest bit.
|
||||
|
||||
while(bits != 0)
|
||||
{
|
||||
// If bytes is less than the bit we're testing for, subtract half
|
||||
// from the bit value and repeat
|
||||
if(bytes < (unsigned)(1 << accum))
|
||||
{
|
||||
bits /= 2;
|
||||
accum -= bits;
|
||||
}
|
||||
// If bytes is greater than the bit we're testing for, add half
|
||||
// from the but value and repeat
|
||||
else if(bytes > (unsigned)(1 << accum))
|
||||
{
|
||||
bits /= 2;
|
||||
accum += bits;
|
||||
}
|
||||
// Got lucky and hit the value dead on
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// At this point accum contains the most significant bit index, increment
|
||||
accum++;
|
||||
if(accum < 2)
|
||||
{
|
||||
accum = 2;
|
||||
}
|
||||
|
||||
// Note that when memory is actually allocated, 8 extra bytes will be allocated.at the front
|
||||
// The first integer is the address of the next block of memory when the block is in the allocator
|
||||
// The second integer is the bit length of the block
|
||||
// Memory is allocated on 4 byte boundaries to sidestep byte alignment problems
|
||||
|
||||
|
||||
// Check if the allocator already has a block of that size
|
||||
if(m_blocks[accum] == 0)
|
||||
{
|
||||
// remove the pre allocated block from the linked list
|
||||
handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned));
|
||||
handle[1] = accum;
|
||||
handle[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate a new block
|
||||
handle = m_blocks[accum];
|
||||
m_blocks[accum] = (unsigned *)handle[0];
|
||||
handle[0] = 0;
|
||||
}
|
||||
// return a pointer that skips over the header used for the allocator's purposes
|
||||
return(handle + 2);
|
||||
}
|
||||
|
||||
void BlockAllocator::returnBlock(unsigned *handle)
|
||||
{
|
||||
// C++ allows for safe deletion of a NULL pointer
|
||||
if(handle)
|
||||
{
|
||||
// Update the allocator linked list, insert this entry at the head
|
||||
*(handle - 2) = (unsigned)m_blocks[*(handle - 1)];
|
||||
// Add this entry to the proper linked list node
|
||||
m_blocks[*(handle - 1)] = (handle - 2);
|
||||
}
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
////////////////////////////////////////
|
||||
// Event.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CEvent class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
|
||||
#if !defined(_MT)
|
||||
# pragma message( "Excluding Base::CEvent - requires multi-threaded compile. (_MT)" )
|
||||
#else
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CEvent::CEvent()
|
||||
{
|
||||
mEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
|
||||
}
|
||||
|
||||
CEvent::~CEvent()
|
||||
{
|
||||
if (mEvent)
|
||||
CloseHandle(mEvent);
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
////////////////////////////////////////
|
||||
// Event.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CEvent class that encapsulates the functionality of a
|
||||
// single-locking semaphore.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_WIN32_EVENT_H
|
||||
#define BASE_WIN32_EVENT_H
|
||||
|
||||
#if defined(_MT)
|
||||
|
||||
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CEvent
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates the functionality of a singal-locking semaphore.
|
||||
// This class is valuable for thread syncronization when a thead's
|
||||
// execution needs to be dependent upon another thread.
|
||||
//
|
||||
// Public Methods:
|
||||
// Signal() : Signals a thread that has called Wait() so that it can
|
||||
// continue execution. This function returns true if the waiting
|
||||
// thread was signalled successfully, otherwise false is returned.
|
||||
// Wait() : Halts the calling thread's execution indefinately until
|
||||
// a Singal() call is made by an external thread. If the thread is
|
||||
// successfully signalled, the function returns eWAIT_SIGNAL. If
|
||||
// timeout period expires without a signal, eWAIT_TIMEOUT is returned.
|
||||
// If the function fails, eWAIT_ERROR is returned.
|
||||
//
|
||||
class CEvent
|
||||
{
|
||||
public:
|
||||
CEvent();
|
||||
virtual ~CEvent();
|
||||
|
||||
bool Signal();
|
||||
int32 Wait(uint32 timeout = 0);
|
||||
|
||||
public:
|
||||
enum { eWAIT_ERROR, eWAIT_SIGNAL, eWAIT_TIMEOUT };
|
||||
private:
|
||||
HANDLE mEvent;
|
||||
};
|
||||
|
||||
inline bool CEvent::Signal()
|
||||
{
|
||||
if (mEvent)
|
||||
return SetEvent(mEvent)!=0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline int32 CEvent::Wait(uint32 timeout)
|
||||
{
|
||||
if (!mEvent)
|
||||
return CEvent::eWAIT_ERROR;
|
||||
|
||||
DWORD result = WaitForSingleObjectEx(mEvent, timeout ? timeout : INFINITE, FALSE);
|
||||
if (result == WAIT_OBJECT_0)
|
||||
return CEvent::eWAIT_SIGNAL;
|
||||
else if (result == WAIT_TIMEOUT)
|
||||
return CEvent::eWAIT_TIMEOUT;
|
||||
else
|
||||
return CEvent::eWAIT_ERROR;
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
|
||||
#endif // BASE_WIN32_EVENT_H
|
||||
@@ -0,0 +1,19 @@
|
||||
// File.cpp: implementation of the CFile class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "File.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CFile::CFile(const char *)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CFile::~CFile()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// File.h: interface for the CFile class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BASE_FILE_H
|
||||
#define BASE_FILE_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class CFile
|
||||
{
|
||||
public:
|
||||
CFile(const char *);
|
||||
virtual ~CFile();
|
||||
|
||||
bool IsOpen();
|
||||
|
||||
private:
|
||||
FILE* mFileHandle;
|
||||
};
|
||||
|
||||
#endif // BASE_FILE_H
|
||||
@@ -0,0 +1,385 @@
|
||||
#include "../Logger.h"
|
||||
#include "Mutex.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
const char file_sep = '\\';
|
||||
|
||||
Logger::Logger(const char *prefix, int level, unsigned size, bool rollDate)
|
||||
: m_defaultLevel(level), m_defaultSize(size), m_dirPrefix(prefix), m_rollDate(rollDate)
|
||||
{
|
||||
char buf[1024];
|
||||
FILE *logDir = NULL;
|
||||
|
||||
logDir = fopen(m_dirPrefix.c_str(), "r+");
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(m_dirPrefix.c_str(), 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
|
||||
tm now;
|
||||
time_t t = time(NULL);
|
||||
memcpy(&now, localtime(&t), sizeof(tm));
|
||||
memcpy(&m_lastDateTime, &now, sizeof(tm));
|
||||
if(m_rollDate)
|
||||
{
|
||||
sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buf, "%s", m_dirPrefix.c_str());
|
||||
}
|
||||
|
||||
logDir = fopen(buf, "r+");
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(buf, 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
m_logPrefix = buf;
|
||||
}
|
||||
|
||||
Logger::~Logger()
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
log((*iter).first, LOG_FILEONLY, "---=== Log Stopped ===---");
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
delete((*iter).second);
|
||||
|
||||
}
|
||||
m_logTable.clear();
|
||||
}
|
||||
|
||||
void Logger::flush(unsigned logenum)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
LogInfo *info = (*iter).second;
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::flushAll()
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
LogInfo *info = (*iter).second;
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::addLog(const char *id, unsigned logenum, int level, unsigned size)
|
||||
{
|
||||
LogInfo *newLog = new LogInfo;
|
||||
newLog->filename = m_logPrefix + file_sep + id + ".log";
|
||||
newLog->name = id;
|
||||
newLog->used = 0;
|
||||
newLog->max = size;
|
||||
newLog->last = 0;
|
||||
newLog->level = level;
|
||||
|
||||
m_logTable.insert(pair<unsigned, LogInfo *>(logenum, newLog));
|
||||
|
||||
if(strcmp("stdout", id) == 0)
|
||||
{
|
||||
newLog->file = stdout;
|
||||
}
|
||||
else if(strcmp("stderr", id) == 0)
|
||||
{
|
||||
newLog->file = stderr;
|
||||
}
|
||||
else
|
||||
{
|
||||
newLog->file = fopen(newLog->filename.c_str(), "a+");
|
||||
}
|
||||
log(logenum, LOG_FILEONLY, "---=== Log Started ===---");
|
||||
}
|
||||
|
||||
void Logger::addLog(const char *id, unsigned logenum)
|
||||
{
|
||||
LogInfo *newLog = new LogInfo;
|
||||
newLog->filename = m_logPrefix + file_sep + id + ".log";
|
||||
newLog->name = id;
|
||||
newLog->used = 0;
|
||||
newLog->max = m_defaultSize;
|
||||
newLog->last = 0;
|
||||
newLog->level = m_defaultLevel;
|
||||
m_logTable.insert(pair<unsigned, LogInfo *>(logenum, newLog));
|
||||
|
||||
if(strcmp("stdout", id) == 0)
|
||||
{
|
||||
newLog->file = stdout;
|
||||
}
|
||||
else if(strcmp("stderr", id) == 0)
|
||||
{
|
||||
newLog->file = stderr;
|
||||
}
|
||||
else
|
||||
{
|
||||
newLog->file = fopen(newLog->filename.c_str(), "a+");
|
||||
}
|
||||
log(logenum, LOG_FILEONLY, "---=== Log Started ===---");
|
||||
|
||||
}
|
||||
|
||||
void Logger::updateLog(unsigned logenum, int level, unsigned size)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
(*iter).second->level = level;
|
||||
(*iter).second->max = size;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::removeLog(unsigned logenum)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
log((*iter).first, LOG_FILEONLY, "---=== Log Stopped ===---");
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
delete((*iter).second);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::logSimple(unsigned logenum, int level, const char *message)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
char dateBuffer[256];
|
||||
|
||||
if(iter == m_logTable.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
LogInfo *info = (*iter).second;
|
||||
if(level >= info->level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(info->last != t)
|
||||
{
|
||||
memcpy(&info->ts, localtime(&t), sizeof(tm));
|
||||
info->last = t;
|
||||
}
|
||||
|
||||
if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
#if defined(_MT)
|
||||
rLock.Lock();
|
||||
#endif
|
||||
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
|
||||
rollDate(t);
|
||||
}
|
||||
#if defined(_MT)
|
||||
rLock.Unlock();
|
||||
#endif
|
||||
}
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
if(info->max > 0)
|
||||
{
|
||||
sprintf(dateBuffer, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] " , (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec);
|
||||
info->used += fputs(dateBuffer, info->file);
|
||||
info->used += fputs(message, info->file);
|
||||
fputc('\n', info->file);
|
||||
if(info->used > info->max)
|
||||
{
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(dateBuffer, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] " , (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec);
|
||||
fputs(dateBuffer, info->file);
|
||||
fputs(message, info->file);
|
||||
fputc('\n', info->file);
|
||||
fflush(info->file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::log(unsigned logenum, int level, const char *message, ...)
|
||||
{
|
||||
char buf[2048];
|
||||
char dateBuffer[256];
|
||||
va_list varg;
|
||||
va_start(varg, message);
|
||||
_vsnprintf(buf, 2047, message, varg);
|
||||
buf[2047] = 0;
|
||||
va_end(varg);
|
||||
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
if(iter == m_logTable.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
LogInfo *info = (*iter).second;
|
||||
|
||||
if(level >= info->level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(level == LOG_FILEONLY && ((info->file == stderr) || (info->file == stdout)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(info->last != t)
|
||||
{
|
||||
memcpy(&info->ts, localtime(&t), sizeof(tm));
|
||||
info->last = t;
|
||||
}
|
||||
if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
#if defined(_MT)
|
||||
rLock.Lock();
|
||||
#endif
|
||||
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
|
||||
rollDate(t);
|
||||
}
|
||||
#if defined(_MT)
|
||||
rLock.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
if(info->max > 0)
|
||||
{
|
||||
sprintf(dateBuffer, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] " , (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec);
|
||||
info->used += fputs(dateBuffer, info->file);
|
||||
info->used += fputs(buf, info->file);
|
||||
fputc('\n', info->file);
|
||||
if(info->used > info->max)
|
||||
{
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(dateBuffer, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] " , (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec);
|
||||
info->used += fputs(dateBuffer, info->file);
|
||||
info->used += fputs(buf, info->file);
|
||||
fputc('\n', info->file);
|
||||
fflush(info->file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::rollDate(time_t t)
|
||||
{
|
||||
char buf[80];
|
||||
FILE *logDir = NULL;
|
||||
|
||||
logDir = fopen(m_dirPrefix.c_str(), "r+");
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(m_dirPrefix.c_str(), 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
|
||||
tm now;
|
||||
memcpy(&now, localtime(&t), sizeof(tm));
|
||||
|
||||
sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100));
|
||||
logDir = fopen(buf, "r+");
|
||||
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(buf, 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
m_logPrefix = buf;
|
||||
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
(*iter).second->filename = m_logPrefix + file_sep + (*iter).second->name.c_str() + ".log";
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
(*iter).second->file = fopen((*iter).second->filename.c_str(), "a+");
|
||||
memcpy(&((*iter).second->ts), &now, sizeof(tm));
|
||||
}
|
||||
}
|
||||
|
||||
// mkdir function that creates intermediate directories
|
||||
void Logger::cmkdir(const char *dir, int mode)
|
||||
{
|
||||
char dirbuf[128];
|
||||
strncpy(dirbuf, dir, 127);
|
||||
dirbuf[127] = 0;
|
||||
char *j = dirbuf, *i = dirbuf;
|
||||
int handle;
|
||||
|
||||
while(*i)
|
||||
{
|
||||
if(*i == file_sep)
|
||||
{
|
||||
(*i) = 0;
|
||||
handle = _open(j, O_EXCL);
|
||||
|
||||
if((handle > 0) || (errno != EISDIR && errno != ENOENT && errno != EACCES))
|
||||
{
|
||||
perror("Logger::cmkdir():");
|
||||
abort();
|
||||
}
|
||||
_mkdir(j);
|
||||
_close(handle);
|
||||
(*i) = file_sep;
|
||||
}
|
||||
else if(*(i + 1) == 0)
|
||||
{
|
||||
_mkdir(j);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
////////////////////////////////////////
|
||||
// Mutex.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CMutex class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
#if !defined(_MT)
|
||||
# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_MT)" )
|
||||
#else
|
||||
|
||||
#include "Mutex.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CMutex::CMutex()
|
||||
{
|
||||
InitializeCriticalSection(&mCriticalSection);
|
||||
}
|
||||
|
||||
CMutex::~CMutex()
|
||||
{
|
||||
DeleteCriticalSection(&mCriticalSection);
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
////////////////////////////////////////
|
||||
// Mutex.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CMutex class that encapsulates the functionality of a
|
||||
// mutually-exclusive device.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_WIN32_MUTEX_H
|
||||
#define BASE_WIN32_MUTEX_H
|
||||
|
||||
#if defined (_MT)
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CMutex
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates the functionality of a mutually-exclusive device.
|
||||
// This class is valuable for protecting against race conditions
|
||||
// within threaded applications. The CMutex class can be used to
|
||||
// only allow a single thread to run within a specified code
|
||||
// segment at a time.
|
||||
//
|
||||
// Public Methods:
|
||||
// Lock() : Locks the mutex. If the mutex is already locked, the
|
||||
// operating system will block the calling thread until another
|
||||
// thread has unlocked the mutex.
|
||||
// Unlock() : Unlocks the mutex.
|
||||
//
|
||||
class CMutex
|
||||
{
|
||||
public:
|
||||
CMutex();
|
||||
~CMutex();
|
||||
|
||||
void Lock();
|
||||
void Unlock();
|
||||
private:
|
||||
CRITICAL_SECTION mCriticalSection;
|
||||
};
|
||||
|
||||
inline void CMutex::Lock()
|
||||
{
|
||||
EnterCriticalSection(&mCriticalSection);
|
||||
}
|
||||
|
||||
inline void CMutex::Unlock()
|
||||
{
|
||||
LeaveCriticalSection(&mCriticalSection);
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_WIN32_MUTEX_H
|
||||
@@ -0,0 +1,31 @@
|
||||
////////////////////////////////////////
|
||||
// Platform.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the global functionality declaired in Platform.h.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
CTimer::CTimer() :
|
||||
mTimer(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
////////////////////////////////////////
|
||||
// Platform.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Include relevent system headers that are platform specific.
|
||||
// 2. Declair global platform specific functionality.
|
||||
// 3. Include primative type definitions
|
||||
//
|
||||
// Global Functions:
|
||||
// getTimer() : Return the current high resolution clock count.
|
||||
// getTimerFrequency() : Return the frequency of the high resolution clock.
|
||||
// sleep() : Voluntarily relinquish timeslice of the calling thread for a
|
||||
// specified number of milliseconds.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_WIN32_PLATFORM_H
|
||||
#define BASE_WIN32_PLATFORM_H
|
||||
|
||||
#include <memory.h>
|
||||
#include <winsock2.h>
|
||||
#include <time.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <direct.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
uint64 getTimer(void);
|
||||
uint64 getTimerFrequency(void);
|
||||
|
||||
inline uint64 getTimer(void)
|
||||
{
|
||||
uint64 result;
|
||||
if (!QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&result)))
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline uint64 getTimerFrequency(void)
|
||||
{
|
||||
uint64 result;
|
||||
if (!QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER *>(&result)))
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void sleep(uint32 ms)
|
||||
{
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
|
||||
class CTimer
|
||||
{
|
||||
public:
|
||||
CTimer();
|
||||
|
||||
void Set(uint32 seconds);
|
||||
void Signal();
|
||||
bool Expired();
|
||||
|
||||
private:
|
||||
uint32 mTimer;
|
||||
};
|
||||
|
||||
inline void CTimer::Set(uint32 interval)
|
||||
{
|
||||
mTimer = (uint32)time(0) + interval;
|
||||
}
|
||||
|
||||
inline void CTimer::Signal()
|
||||
{
|
||||
mTimer = 0;
|
||||
}
|
||||
|
||||
inline bool CTimer::Expired()
|
||||
{
|
||||
return (mTimer <= (uint32)time(0));
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif BASE_WIN32_PLATFORM_H
|
||||
@@ -0,0 +1,279 @@
|
||||
////////////////////////////////////////
|
||||
// Thread.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CThread class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
|
||||
#pragma warning ( disable: 4786 )
|
||||
|
||||
|
||||
#if !defined(_MT)
|
||||
# pragma message( "Excluding Base::CThread - requires multi-threaded compile. (_MT)" )
|
||||
#else
|
||||
|
||||
#include <process.h>
|
||||
#include <time.h>
|
||||
#include "Thread.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
void threadProc(void *threadPtr)
|
||||
{
|
||||
CThread &thread = *((CThread*)threadPtr);
|
||||
thread.mThreadActive = true;
|
||||
thread.ThreadProc();
|
||||
thread.mThreadActive = false;
|
||||
}
|
||||
|
||||
CThread::CThread()
|
||||
{
|
||||
mThreadID = 0;
|
||||
mThreadActive = false;
|
||||
mThreadContinue = false;
|
||||
}
|
||||
|
||||
CThread::~CThread()
|
||||
{
|
||||
StopThread();
|
||||
}
|
||||
|
||||
void CThread::StartThread()
|
||||
{
|
||||
mThreadContinue = true;
|
||||
mThreadID = _beginthread(threadProc,0,this);
|
||||
while (!IsThreadActive())
|
||||
Base::sleep(1);
|
||||
}
|
||||
|
||||
int32 CThread::StopThread(int32 timeout)
|
||||
{
|
||||
timeout += int(time(0));
|
||||
|
||||
mThreadContinue = false;
|
||||
while (mThreadActive && time(0)<timeout)
|
||||
sleep(1);
|
||||
if (mThreadActive)
|
||||
{
|
||||
mThreadActive = false;
|
||||
return eSTOP_TIMEOUT;
|
||||
}
|
||||
return eSTOP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CThreadPool::CMember::CMember(CThreadPool * parent) :
|
||||
mParent(parent),
|
||||
mFunction(NULL),
|
||||
mArgument(NULL),
|
||||
mSemaphore()
|
||||
{
|
||||
StartThread();
|
||||
}
|
||||
|
||||
CThreadPool::CMember::~CMember()
|
||||
{
|
||||
}
|
||||
|
||||
void CThreadPool::CMember::Destroy()
|
||||
{
|
||||
mThreadContinue = false;
|
||||
mSemaphore.Signal();
|
||||
}
|
||||
|
||||
bool CThreadPool::CMember::Execute(void( __cdecl *function )( void * ), void * arg)
|
||||
{
|
||||
if (mFunction)
|
||||
return false;
|
||||
|
||||
mArgument = arg;
|
||||
mFunction = function;
|
||||
mSemaphore.Signal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CThreadPool::CMember::ThreadProc()
|
||||
{
|
||||
mParent->OnStartup(this);
|
||||
while (mThreadContinue)
|
||||
{
|
||||
mParent->OnIdle(this);
|
||||
mSemaphore.Wait(mParent->GetTimeOut()*1000);
|
||||
|
||||
if (mFunction)
|
||||
{
|
||||
mFunction(mArgument);
|
||||
mArgument = NULL;
|
||||
mFunction = NULL;
|
||||
}
|
||||
else if (mParent->OnDestory(this))
|
||||
mThreadContinue = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CThreadPool::CThreadPool(uint32 maxThreads, uint32 minThreads, uint32 timeout) :
|
||||
mMutex(),
|
||||
mIdleMember(),
|
||||
mBusyMember(),
|
||||
mNullMember(),
|
||||
mThreadCount(0),
|
||||
mMaxThreads(maxThreads),
|
||||
mMinThreads(minThreads),
|
||||
mTimeOut(timeout)
|
||||
{
|
||||
if (mMaxThreads == 0) mMaxThreads = 1;
|
||||
if (mMinThreads == 0) mMinThreads = 1;
|
||||
if (mMinThreads > mMaxThreads) mMinThreads = mMaxThreads;
|
||||
|
||||
for (uint32 i=0; i<mMinThreads; i++)
|
||||
new CMember(this);
|
||||
}
|
||||
|
||||
CThreadPool::~CThreadPool()
|
||||
{
|
||||
set<CMember *>::iterator setIterator;
|
||||
|
||||
////////////////////////////////////////
|
||||
// (1) Destory all busy member threads
|
||||
mMutex.Lock();
|
||||
setIterator = mBusyMember.begin();
|
||||
while (setIterator != mBusyMember.end())
|
||||
(*setIterator++)->Destroy();
|
||||
mMutex.Unlock();
|
||||
|
||||
////////////////////////////////////////
|
||||
// (2) Destory all idle member threads
|
||||
while (mThreadCount)
|
||||
{
|
||||
mMutex.Lock();
|
||||
setIterator = mIdleMember.begin();
|
||||
while (setIterator != mIdleMember.end())
|
||||
(*setIterator++)->Destroy();
|
||||
mMutex.Unlock();
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (3) Delete the null member threads
|
||||
mMutex.Lock();
|
||||
while (!mNullMember.empty())
|
||||
{
|
||||
delete mNullMember.front();
|
||||
mNullMember.pop_front();
|
||||
}
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
bool CThreadPool::Execute(void( __cdecl *function )( void * ), void * arg)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
////////////////////////////////////////
|
||||
// (1) If no idle members, return false to indicate that no threads
|
||||
// were available. If the thread count is below the max, create
|
||||
// a new thread.
|
||||
if (mIdleMember.empty())
|
||||
{
|
||||
if (mThreadCount < mMaxThreads)
|
||||
new CMember(this);
|
||||
mMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (2) Delete any null member threads.
|
||||
while (!mNullMember.empty())
|
||||
{
|
||||
delete mNullMember.front();
|
||||
mNullMember.pop_front();
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (3) Move the first idle thread to the busy set and signal the
|
||||
// thread to execute the specified function.
|
||||
CMember * member = *(mIdleMember.begin());
|
||||
mIdleMember.erase(member);
|
||||
mBusyMember.insert(member);
|
||||
member->Execute(function,arg);
|
||||
|
||||
mMutex.Unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 CThreadPool::GetTimeOut()
|
||||
{
|
||||
return mTimeOut;
|
||||
}
|
||||
|
||||
void CThreadPool::OnStartup(CMember * member)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
mThreadCount++;
|
||||
mIdleMember.insert(member);
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
void CThreadPool::OnIdle(CMember * member)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
mBusyMember.erase(member);
|
||||
mIdleMember.insert(member);
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
bool CThreadPool::OnDestory(CMember * member)
|
||||
{
|
||||
set<CMember *>::iterator setIterator;
|
||||
|
||||
mMutex.Lock();
|
||||
|
||||
bool result = (setIterator = mIdleMember.find(member)) != mIdleMember.end();
|
||||
if (result)
|
||||
{
|
||||
mNullMember.push_back(member);
|
||||
mIdleMember.erase(setIterator);
|
||||
mThreadCount--;
|
||||
}
|
||||
|
||||
mMutex.Unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
////////////////////////////////////////
|
||||
// Thread.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CThread class that encapsulates threading functionality.
|
||||
// This abstract base class in intended to be used to encapsulate
|
||||
// individual tasks that require threading in derived classes.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_WIN32_THREAD_H
|
||||
#define BASE_WIN32_THREAD_H
|
||||
|
||||
#if defined(_MT)
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include "Platform.h"
|
||||
#include "Mutex.h"
|
||||
#include "Event.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CThread
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates threading functionality. Creating classes derived
|
||||
// from CThread provides an easy way to encapsulate tasks that require
|
||||
// their own thread.
|
||||
//
|
||||
// Public Methods:
|
||||
// StartThread() : Creates the low-level thread handle and begins executing
|
||||
// the CThread::ThreadProc() function within the new thread.
|
||||
// StopThread() : Signals the ThreadProc() function to stop executing using
|
||||
// the mThreadContinue member variable, and waits for the ThreadProc()
|
||||
// function to exit. By default, the function will block for a maximum
|
||||
// of 5 seconds before exiting without the thread halting.
|
||||
// IsThreadActive() : Returns true if the physical thread is still executing
|
||||
// within the ThreadProc() function, otherwise it returns false.
|
||||
// ThreadProc() : Pure-virtual function that will be executed when the StartThread()
|
||||
// function is called. Derived classes must implement this function. The
|
||||
// mThreadContinue member variable should be used internal the the ThreadProc()
|
||||
// function to indicate whether it should continue executing or exit.
|
||||
// Protected Attributes:
|
||||
// mThreadContinue : Boolean value indicating to the ThreadProc() function
|
||||
// whether to continue executing or to exit. If mThreadContinue is true,
|
||||
// ThreadProc() should continue, otherwise ThreadProc() should exit. It
|
||||
// left up to the derived class to implement a ThreadProc() function that
|
||||
// uses the mThreadContinue member.
|
||||
//
|
||||
//
|
||||
class CThread
|
||||
{
|
||||
friend void threadProc(void *);
|
||||
|
||||
public:
|
||||
enum { eSTOP_SUCCESS, eSTOP_TIMEOUT };
|
||||
public:
|
||||
CThread();
|
||||
virtual ~CThread();
|
||||
|
||||
void StartThread();
|
||||
int32 StopThread(int32 timeout=5);
|
||||
bool IsThreadActive() { return mThreadActive; }
|
||||
|
||||
protected:
|
||||
virtual void ThreadProc() = 0;
|
||||
|
||||
protected:
|
||||
bool mThreadContinue;
|
||||
private:
|
||||
uint32 mThreadID;
|
||||
bool mThreadActive;
|
||||
};
|
||||
|
||||
|
||||
class CThreadPool
|
||||
{
|
||||
private:
|
||||
class CMember : public CThread
|
||||
{
|
||||
public:
|
||||
CMember(CThreadPool * parent);
|
||||
virtual ~CMember();
|
||||
|
||||
bool Execute(void( __cdecl *function )( void * ), void * arg);
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
virtual void ThreadProc();
|
||||
|
||||
private:
|
||||
CThreadPool * mParent;
|
||||
void( __cdecl * mFunction )( void * );
|
||||
void * mArgument;
|
||||
CEvent mSemaphore;
|
||||
};
|
||||
friend class CMember;
|
||||
|
||||
public:
|
||||
CThreadPool(uint32 maxThreads, uint32 minThreads=1, uint32 timeout=15*60);
|
||||
~CThreadPool();
|
||||
|
||||
bool Execute(void( __cdecl *function )( void * ), void * arg);
|
||||
|
||||
private:
|
||||
uint32 GetTimeOut();
|
||||
void OnStartup(CMember * member);
|
||||
void OnIdle(CMember * member);
|
||||
bool OnDestory(CMember * member);
|
||||
|
||||
private:
|
||||
CMutex mMutex;
|
||||
std::set<CMember *> mIdleMember;
|
||||
std::set<CMember *> mBusyMember;
|
||||
std::list<CMember *> mNullMember;
|
||||
uint32 mThreadCount;
|
||||
|
||||
uint32 mMaxThreads;
|
||||
uint32 mMinThreads;
|
||||
uint32 mTimeOut;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_WIN32_THREAD_H
|
||||
@@ -0,0 +1,42 @@
|
||||
////////////////////////////////////////
|
||||
// Types.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Define integer types that are unambiguous with respect to size
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_WIN32_TYPES_H
|
||||
#define BASE_WIN32_TYPES_H
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
#define INT32_MAX 0x7FFFFFFF
|
||||
#define INT32_MIN 0x80000000
|
||||
#define UINT32_MAX 0xFFFFFFFF
|
||||
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
typedef short int16;
|
||||
typedef unsigned short uint16;
|
||||
|
||||
typedef int int32;
|
||||
typedef unsigned uint32;
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // BASE_WIN32_TYPES_H
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
add_subdirectory(Base)
|
||||
@@ -82,8 +82,10 @@ include_directories(
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedPathfinding/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRandom/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRegex/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRemoteDebugServer/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedSkillSystem/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedTerrain/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedThread/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/server/library/serverGame/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/server/library/serverNetworkMessages/include/public
|
||||
@@ -104,7 +106,50 @@ include_directories(
|
||||
${JNI_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
link_directories(${STLPORT_LIBDIR})
|
||||
|
||||
add_executable(SwgGameServer
|
||||
${SHARED_SOURCES}
|
||||
${PLATFORM_SOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(SwgGameServer
|
||||
sharedCollision
|
||||
sharedCommandParser
|
||||
sharedDebug
|
||||
sharedFile
|
||||
sharedFoundation
|
||||
sharedGame
|
||||
sharedImage
|
||||
sharedLog
|
||||
sharedMath
|
||||
sharedMathArchive
|
||||
sharedMemoryManager
|
||||
sharedMessageDispatch
|
||||
sharedNetwork
|
||||
sharedNetworkMessages
|
||||
sharedObject
|
||||
sharedPathfinding
|
||||
sharedRandom
|
||||
sharedRegex
|
||||
sharedRemoteDebugServer
|
||||
sharedSkillSystem
|
||||
sharedTerrain
|
||||
sharedThread
|
||||
sharedUtility
|
||||
serverGame
|
||||
serverNetworkMessages
|
||||
serverPathfinding
|
||||
serverScript
|
||||
serverUtility
|
||||
swgSharedNetworkMessages
|
||||
swgSharedUtility
|
||||
swgServerNetworkMessages
|
||||
archive
|
||||
fileInterface
|
||||
localization
|
||||
localizationArchive
|
||||
singleton
|
||||
unicode
|
||||
unicodeArchive
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user