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
+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)