Added platform libs

This commit is contained in:
Anonymous
2014-01-16 07:25:50 -07:00
parent 202d7d1de3
commit 77c2b5f6bc
92 changed files with 16139 additions and 2 deletions
+4
View File
@@ -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)
+1
View File
@@ -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
+1
View File
@@ -1,2 +1,3 @@
add_subdirectory(platform)
add_subdirectory(udplibrary)
+9
View File
@@ -0,0 +1,9 @@
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/projects
${CMAKE_CURRENT_SOURCE_DIR}/utils
)
add_subdirectory(projects)
add_subdirectory(utils)
+2
View File
@@ -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,&copy,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,&copy,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,&copy,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,&copy,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, &copy, 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
+262
View File
@@ -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
View File
@@ -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
+353
View File
@@ -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
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
#include "Base.h"
+63
View File
@@ -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
+70
View File
@@ -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
View File
@@ -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
View File
@@ -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
+22
View File
@@ -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
+71
View File
@@ -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
View File
@@ -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
View File
@@ -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
+23
View File
@@ -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
View File
@@ -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
+34
View File
@@ -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
+40
View File
@@ -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
+45
View File
@@ -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
+140
View File
@@ -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
+22
View File
@@ -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
+23
View File
@@ -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
+103
View File
@@ -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)
+74
View File
@@ -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
};
+199
View File
@@ -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)
+79
View File
@@ -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)
+146
View File
@@ -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
+42
View File
@@ -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)
+92
View File
@@ -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
+19
View File
@@ -0,0 +1,19 @@
// File.cpp: implementation of the CFile class.
//
//////////////////////////////////////////////////////////////////////
#include "File.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CFile::CFile(const char *)
{
}
CFile::~CFile()
{
}
+22
View File
@@ -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)
+73
View File
@@ -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)
+144
View File
@@ -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
+42
View File
@@ -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
+2
View File
@@ -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
)