mirror of
https://github.com/SWG-Source/src.git
synced 2026-07-31 00:15:55 -04:00
Added CSAssist library
This commit is contained in:
+2
-1
@@ -1,4 +1,5 @@
|
||||
|
||||
add_subdirectory(ChatAPI)
|
||||
add_subdirectory(CSAssist)
|
||||
add_subdirectory(CTServiceGameAPI)
|
||||
add_subdirectory(ChatAPI)
|
||||
add_subdirectory(VChatAPI)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/utils)
|
||||
|
||||
add_subdirectory(projects)
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
add_subdirectory(CSAssist)
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
add_subdirectory(CSAssistgameapi)
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
|
||||
set(SHARED_SOURCES
|
||||
CSAssistgameapi.cpp
|
||||
CSAssistgameapi.h
|
||||
CSAssistgameapicore.cpp
|
||||
CSAssistgameapicore.h
|
||||
CSAssistgameobjects.cpp
|
||||
CSAssistgameobjects.h
|
||||
CSAssistreceiver.cpp
|
||||
CSAssistreceiver.h
|
||||
packdata.cpp
|
||||
packdata.h
|
||||
request.cpp
|
||||
request.h
|
||||
response.cpp
|
||||
response.h
|
||||
|
||||
../../../utils/Base/Archive.cpp
|
||||
../../../utils/Base/Archive.h
|
||||
../../../utils/Base/AutoLog.cpp
|
||||
../../../utils/Base/AutoLog.h
|
||||
../../../utils/Base/Base.cpp
|
||||
../../../utils/Base/Base.h
|
||||
../../../utils/Base/BlockAllocator.h
|
||||
../../../utils/Base/Config.cpp
|
||||
../../../utils/Base/Config.h
|
||||
../../../utils/Base/Event.h
|
||||
../../../utils/Base/Logger.cpp
|
||||
../../../utils/Base/Logger.h
|
||||
../../../utils/Base/MD5.cpp
|
||||
../../../utils/Base/MD5.h
|
||||
../../../utils/Base/Mutex.h
|
||||
../../../utils/Base/Platform.h
|
||||
../../../utils/Base/ScopeLock.cpp
|
||||
../../../utils/Base/ScopeLock.h
|
||||
../../../utils/Base/Statistics.cpp
|
||||
../../../utils/Base/Statistics.h
|
||||
../../../utils/Base/TemplateBlockAllocator.h
|
||||
../../../utils/Base/TemplateObjectAllocator.h
|
||||
../../../utils/Base/Thread.h
|
||||
../../../utils/Base/Types.h
|
||||
../../../utils/Base/WideString.h
|
||||
../../../utils/Base/serialize.h
|
||||
|
||||
../../../utils/TcpLibrary/Clock.cpp
|
||||
../../../utils/TcpLibrary/Clock.h
|
||||
../../../utils/TcpLibrary/IPAddress.cpp
|
||||
../../../utils/TcpLibrary/IPAddress.h
|
||||
../../../utils/TcpLibrary/TcpBlockAllocator.cpp
|
||||
../../../utils/TcpLibrary/TcpBlockAllocator.h
|
||||
../../../utils/TcpLibrary/TcpConnection.cpp
|
||||
../../../utils/TcpLibrary/TcpConnection.h
|
||||
../../../utils/TcpLibrary/TcpHandlers.h
|
||||
../../../utils/TcpLibrary/TcpManager.cpp
|
||||
../../../utils/TcpLibrary/TcpManager.h
|
||||
|
||||
../../../utils/Unicode/FirstUnicode.cpp
|
||||
../../../utils/Unicode/FirstUnicode.h
|
||||
../../../utils/Unicode/Unicode.cpp
|
||||
../../../utils/Unicode/Unicode.h
|
||||
../../../utils/Unicode/UnicodeBlocks.cpp
|
||||
../../../utils/Unicode/UnicodeBlocks.h
|
||||
../../../utils/Unicode/UnicodeCharacterData.cpp
|
||||
../../../utils/Unicode/UnicodeCharacterData.h
|
||||
../../../utils/Unicode/UnicodeCharacterDataMap.cpp
|
||||
../../../utils/Unicode/UnicodeCharacterDataMap.h
|
||||
../../../utils/Unicode/UnicodeUtils.cpp
|
||||
../../../utils/Unicode/UnicodeUtils.h
|
||||
../../../utils/Unicode/utf8.cpp
|
||||
../../../utils/Unicode/utf8.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(PLATFORM_SOURCES
|
||||
../../../utils/Base/win32/Archive.h
|
||||
../../../utils/Base/win32/BlockAllocator.cpp
|
||||
../../../utils/Base/win32/Event.cpp
|
||||
../../../utils/Base/win32/Event.h
|
||||
../../../utils/Base/win32/File.cpp
|
||||
../../../utils/Base/win32/File.h
|
||||
../../../utils/Base/win32/Mutex.cpp
|
||||
../../../utils/Base/win32/Mutex.h
|
||||
../../../utils/Base/win32/Platform.cpp
|
||||
../../../utils/Base/win32/Thread.cpp
|
||||
../../../utils/Base/win32/Thread.h
|
||||
../../../utils/Base/win32/Types.h
|
||||
)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../utils/Base/win32)
|
||||
else()
|
||||
set(PLATFORM_SOURCES
|
||||
../../../utils/Base/linux/Archive.h
|
||||
../../../utils/Base/linux/BlockAllocator.cpp
|
||||
../../../utils/Base/linux/Event.cpp
|
||||
../../../utils/Base/linux/Event.h
|
||||
../../../utils/Base/linux/Mutex.cpp
|
||||
../../../utils/Base/linux/Mutex.h
|
||||
../../../utils/Base/linux/Platform.cpp
|
||||
../../../utils/Base/linux/Thread.cpp
|
||||
../../../utils/Base/linux/Thread.h
|
||||
../../../utils/Base/linux/Types.h
|
||||
)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../utils/Base/linux)
|
||||
endif()
|
||||
|
||||
add_definitions(-DEXTERNAL_DISTRO -DNAMESPACE=CSAssist)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_library(CSAssist
|
||||
${SHARED_SOURCES}
|
||||
${PLATFORM_SOURCES}
|
||||
)
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// CSAssistGameAPIDll.cpp : Defines the entry point for the DLL application.
|
||||
//
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#include <windows.h>
|
||||
#include <cstdio>
|
||||
|
||||
//#include "stdafx.h"
|
||||
#include "CSAssistGameAPIDll.h"
|
||||
|
||||
BOOL APIENTRY DllMain( HANDLE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// This is an example of an exported variable
|
||||
//CSASSISTGAMEAPIDLL_API int nCSAssistGameAPIDll=0;
|
||||
|
||||
// This is an example of an exported function.
|
||||
//CSASSISTGAMEAPIDLL_API int fnCSAssistGameAPIDll(void)
|
||||
//{
|
||||
// return 42;
|
||||
//}
|
||||
|
||||
// This is the constructor of a class that has been exported.
|
||||
// see CSAssistGameAPIDll.h for the class definition
|
||||
//CCSAssistGameAPIDll::CCSAssistGameAPIDll()
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
|
||||
// The following ifdef block is the standard way of creating macros which make exporting
|
||||
// from a DLL simpler. All files within this DLL are compiled with the CSASSISTGAMEAPIDLL_EXPORTS
|
||||
// symbol defined on the command line. this symbol should not be defined on any project
|
||||
// that uses this DLL. This way any other project whose source files include this file see
|
||||
// CSASSISTGAMEAPIDLL_API functions as being imported from a DLL, wheras this DLL sees symbols
|
||||
// defined with this macro as being exported.
|
||||
/*
|
||||
#ifdef USE_CSADLL
|
||||
#ifdef CSASSISTGAMEAPIDLL_EXPORTS
|
||||
#define CSASSISTGAMEAPIDLL_API __declspec(dllexport)
|
||||
#else
|
||||
#define CSASSISTGAMEAPIDLL_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define CSASSISTGAMEAPIDLL_API
|
||||
#endif
|
||||
*/
|
||||
#define CSASSISTGAMEAPIDLL_API __declspec(dllexport)
|
||||
|
||||
// This class is exported from the CSAssistGameAPIDll.dll
|
||||
//class CSASSISTGAMEAPIDLL_API CCSAssistGameAPIDll {
|
||||
//public:
|
||||
// CCSAssistGameAPIDll(void);
|
||||
// TODO: add your methods here.
|
||||
//};
|
||||
|
||||
//extern CSASSISTGAMEAPIDLL_API int nCSAssistGameAPIDll;
|
||||
|
||||
//CSASSISTGAMEAPIDLL_API int fnCSAssistGameAPIDll(void);
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+735
@@ -0,0 +1,735 @@
|
||||
#include "test.h"
|
||||
#include "Base/Base.h"
|
||||
#include "Unicode/UnicodeUtils.h"
|
||||
#include "request.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#ifdef WIN32
|
||||
#include <conio.h>
|
||||
#endif
|
||||
#include <queue>
|
||||
|
||||
//#define WARP_SPEED true // set this for BRIEF std::cout printing
|
||||
#define AUTO_RUN true
|
||||
|
||||
using namespace std;
|
||||
using namespace CSAssist;
|
||||
using namespace Plat_Unicode;
|
||||
|
||||
apiTest *api;
|
||||
int received = 0;
|
||||
int submitted = 0;
|
||||
unsigned packetsRx = 0;
|
||||
bool ready = false;
|
||||
bool createdTicket = false;
|
||||
bool loginFailed = true;
|
||||
unsigned firstTicketID = 0;
|
||||
unsigned lastTicketID = 0;
|
||||
unsigned uid = 0;
|
||||
unsigned testUID = 623259672;//99709401;
|
||||
unsigned track(0);
|
||||
int numberFunctionsToRun(0);
|
||||
bool doBug(false);
|
||||
|
||||
std::queue<unsigned> register_list;
|
||||
Plat_Unicode::String game;
|
||||
Plat_Unicode::String server;
|
||||
Plat_Unicode::String character;
|
||||
Plat_Unicode::String lang;
|
||||
Plat_Unicode::String comment;
|
||||
Plat_Unicode::String id;
|
||||
Plat_Unicode::String search;
|
||||
Plat_Unicode::String hierarchy = narrowToWide("test");
|
||||
|
||||
unsigned numberFunctions = 16;
|
||||
unsigned functionCount[16];
|
||||
unsigned functionID[] =
|
||||
{
|
||||
CSASSIST_CALL_NEWTICKETACTIVITY, // 2
|
||||
CSASSIST_CALL_REGISTERCHARACTER, // 3
|
||||
CSASSIST_CALL_GETISSUEHIERARCHY, // 6
|
||||
CSASSIST_CALL_CREATETICKET, // 7
|
||||
CSASSIST_CALL_APPENDCOMMENT, // 8
|
||||
CSASSIST_CALL_GETTICKETBYID, // 9
|
||||
CSASSIST_CALL_GETTICKETCOMMENTS, // 10
|
||||
CSASSIST_CALL_GETTICKET, // 11
|
||||
CSASSIST_CALL_MARKREAD, // 12
|
||||
CSASSIST_CALL_CANCELTICKET, // 13
|
||||
CSASSIST_CALL_COMMENTCOUNT, // 14
|
||||
CSASSIST_CALL_GETDOCUMENTLIST, // 16
|
||||
CSASSIST_CALL_GETDOCUMENT, // 17
|
||||
CSASSIST_CALL_GETTICKETXMLBLOCK, // 18
|
||||
CSASSIST_CALL_GETKBARTICLE, // 19
|
||||
CSASSIST_CALL_SEARCHKB // 20
|
||||
};
|
||||
char *functionName[] =
|
||||
{
|
||||
"CSASSIST_CALL_NEWTICKETACTIVITY", // 2
|
||||
"CSASSIST_CALL_REGISTERCHARACTER", // 3
|
||||
"CSASSIST_CALL_GETISSUEHIERARCHY", // 6
|
||||
"CSASSIST_CALL_CREATETICKET", // 7
|
||||
"CSASSIST_CALL_APPENDCOMMENT", // 8
|
||||
"CSASSIST_CALL_GETTICKETBYID", // 9
|
||||
"CSASSIST_CALL_GETTICKETCOMMENTS", // 10
|
||||
"CSASSIST_CALL_GETTICKET", // 11
|
||||
"CSASSIST_CALL_MARKREAD", // 12
|
||||
"CSASSIST_CALL_CANCELTICKET", // 13
|
||||
"CSASSIST_CALL_COMMENTCOUNT", // 14
|
||||
"CSASSIST_CALL_GETDOCUMENTLIST", // 16
|
||||
"CSASSIST_CALL_GETDOCUMENT", // 17
|
||||
"CSASSIST_CALL_GETTICKETXMLBLOCK", // 18
|
||||
"CSASSIST_CALL_GETKBARTICLE", // 19
|
||||
"CSASSIST_CALL_SEARCHKB" // 20
|
||||
};
|
||||
|
||||
void ResetGlobals()
|
||||
{
|
||||
received = 0;
|
||||
submitted = 0;
|
||||
packetsRx = 0;
|
||||
ready = false;
|
||||
createdTicket = false;
|
||||
loginFailed = true;
|
||||
firstTicketID = 0;
|
||||
lastTicketID = 0;
|
||||
uid = 0;
|
||||
|
||||
float max = 500.0;
|
||||
//srand(time(0));
|
||||
//numberFunctionsToRun = 2+(int) (max*rand()/(RAND_MAX+1.0));
|
||||
numberFunctionsToRun = 2000;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
apiTest::apiTest(const char *host, const unsigned port, const unsigned timeout = 0, const unsigned flags = 0)
|
||||
: CSAssistGameAPI(host, port, timeout, flags)
|
||||
//---------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
apiTest::~apiTest()
|
||||
//---------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnConnectCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nConnect: " << result;
|
||||
#endif
|
||||
if (result == CSASSIST_RESULT_SUCCESS)
|
||||
ready = true;
|
||||
else
|
||||
loginFailed = true;
|
||||
packetsRx++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnDisconnectCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nDisConnect: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnRegisterCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nRegister: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnUnRegisterCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nUnRegister: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnMarkTicketRead(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nMark Read: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
//---------------------------------------------
|
||||
void apiTest::OnCancelTicket(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nUCancel: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetTicketCommentsCount(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket, const unsigned count)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nComment Count: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
//---------------------------------------------
|
||||
void apiTest::OnRequestGameLocation(const CSAssistGameAPITrack sourceTrack, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const CSAssistGameAPIUID CSRUID)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nGame Location: " << uid;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetDocumentList(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIDocumentHeader *docList, const unsigned numberRead)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nDoc List: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetDocument(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistUnicodeChar *documentBody)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nDocument: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetTicketXMLBlock(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML XMLBody)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nGet XML Block: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
//---------------------------------------------
|
||||
void apiTest::OnSearchKB(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPISearchResult *results, const unsigned numberRead)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nSearch KB: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetKBArticle(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML articleBody)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nGet KB Article: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
//---------------------------------------------
|
||||
void apiTest::OnIssueHierarchyChanged(const CSAssistUnicodeChar *version, const CSAssistUnicodeChar *language)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nHierarchy Changed";
|
||||
#endif
|
||||
packetsRx++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnNewTicketActivity(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const unsigned NewActivityFlag, const unsigned HasTickets)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nNewActivity: " << result << " " << HasTickets;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetIssueHierarchy(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML hierarchyBody, const unsigned modifyDate)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nHierarchy: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnCreateTicket(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nCreate Ticket: " << result << " "<<flush;
|
||||
#endif
|
||||
if (firstTicketID == 0)
|
||||
firstTicketID = ticket;
|
||||
if (ticket > lastTicketID)
|
||||
lastTicketID = ticket;
|
||||
received++;
|
||||
packetsRx++;
|
||||
createdTicket = true;
|
||||
}
|
||||
//---------------------------------------------
|
||||
void apiTest::OnAppendTicketComment(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nAppend Comment: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetTicketByID(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicket *ticketBody)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nGet Ticket: " << result;
|
||||
#endif
|
||||
received++;
|
||||
packetsRx++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetTicketComments(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketComment *comments, const unsigned numberRead)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nGet Ticket Comments: " << result;
|
||||
if (comments == 0)
|
||||
std::cout << "\nNo Comment data";
|
||||
#endif
|
||||
received++;
|
||||
packetsRx += numberRead;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetTicketByCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const unsigned NumberReturned, const unsigned TotalNumber, const CSAssistGameAPITicket *tickets)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nGet Ticket: " << result;
|
||||
if (tickets == 0)
|
||||
std::cout << "\nNo Ticket data";
|
||||
#endif
|
||||
received++;
|
||||
packetsRx += NumberReturned;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnTicketChange(const CSAssistGameAPITicketID ticketID, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character)
|
||||
//---------------------------------------------
|
||||
{
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << "\nTicket Change: " << ticketID;
|
||||
#endif
|
||||
packetsRx++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void createTicket()
|
||||
//---------------------------------------------
|
||||
{
|
||||
CSAssistGameAPITicket t;
|
||||
t.setUID(testUID);
|
||||
t.setGame(game.c_str());
|
||||
t.setServer(server.c_str());
|
||||
t.setCharacter(character.c_str());
|
||||
t.setCategory(0,4000);
|
||||
t.setCategory(1,4001);
|
||||
t.setCategory(2,2);
|
||||
t.setCategory(3,1);
|
||||
if (doBug) t.setBug();
|
||||
Plat_Unicode::String details = narrowToWide("Stress Test Ticket details here.");
|
||||
Plat_Unicode::String location = narrowToWide("Stress Test Location");
|
||||
Plat_Unicode::String xml = narrowToWide("Stress Test XML here");
|
||||
t.setDetails(details.c_str());
|
||||
t.setLocation(location.c_str());
|
||||
track = api->requestCreateTicket(NULL, &t, NULL, t.uid);
|
||||
//track = api->requestCreateTicket(NULL, &t, xml.c_str(), t.uid);
|
||||
submitted++;
|
||||
|
||||
printf("creating ticket\n");
|
||||
createdTicket = false;
|
||||
if (firstTicketID ==0) // if no tickets created yet, wait for one
|
||||
{
|
||||
while (!createdTicket) // wait for create ticket to return, so we know ticket number we created
|
||||
{
|
||||
Base::sleep(50);
|
||||
api->Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
unsigned randomTicketID()
|
||||
//---------------------------------------------
|
||||
{
|
||||
if (firstTicketID == 0)
|
||||
createTicket(); // create at least one ticket first
|
||||
|
||||
unsigned r = firstTicketID;
|
||||
if (r != lastTicketID)
|
||||
r += rand() % (lastTicketID - firstTicketID);
|
||||
#ifndef WARP_SPEED
|
||||
printf(" (%d) ", r);
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
std::string GetHostName(unsigned port)
|
||||
//-----------------------------------------------
|
||||
{
|
||||
const short hostLen(512);
|
||||
char hostName[hostLen] = {0};
|
||||
char hostAndPort[hostLen+10] = {0};
|
||||
std::string serverID;
|
||||
#ifdef WIN32
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(1,1), &wsaData);
|
||||
#endif
|
||||
if (gethostname(hostName, hostLen) < 0)
|
||||
{
|
||||
// Bad error - the serverID must be unique between CSA servers.
|
||||
// Attempt to use IP Address ?. // TODO:rlsmith
|
||||
sprintf(hostName,"localhost-%u", port);
|
||||
}
|
||||
//#endif
|
||||
std::string shortName = hostName;
|
||||
unsigned dot = shortName.find_first_of(".");
|
||||
if (dot != std::string::npos)
|
||||
{
|
||||
shortName = shortName.substr(0,dot);
|
||||
}
|
||||
#ifdef WIN32
|
||||
_snprintf(hostAndPort, hostLen+10, "%s", shortName.c_str());
|
||||
#else
|
||||
snprintf(hostAndPort, hostLen+10, "%s", shortName.c_str());
|
||||
#endif
|
||||
return (std::string)hostAndPort;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
int main(int argc, char **argv)
|
||||
//---------------------------------------------
|
||||
{
|
||||
unsigned i = 0;
|
||||
unsigned tid = 0;
|
||||
|
||||
// ----- validate and strip command line parameters -----
|
||||
|
||||
char *serverhost;
|
||||
int serverport;
|
||||
char *gamep;
|
||||
char *gameserver;
|
||||
|
||||
#ifdef AUTO_RUN
|
||||
ResetGlobals();
|
||||
serverhost = "sdplatdev2.station.sony.com";
|
||||
//serverhost = "64.37.152.161";
|
||||
//serverport = 3018;
|
||||
//serverhost = "64.37.153.15";
|
||||
serverport = 3009;
|
||||
if (argc > 1)
|
||||
gamep = argv[1];
|
||||
else
|
||||
gamep = "PS";
|
||||
if (argc> 2 && !strcmp(argv[2],"bug")) doBug=true;
|
||||
std::string gs = GetHostName(numberFunctionsToRun);
|
||||
gameserver = (char*)gs.c_str();
|
||||
#else
|
||||
if (argc < 6)
|
||||
{
|
||||
std::cout << "CSAssistStressTest Game Version: Syntax:\nCSAssistStressTest <hostname> <port> <number_funcs_to_run> <game> <gameserver>\n";
|
||||
return 0;
|
||||
}
|
||||
serverhost = argv[1];
|
||||
serverport = atoi(argv[2]);
|
||||
numberFunctionsToRun = atoi(argv[3]);
|
||||
gamep = argv[4];
|
||||
gameserver = argv[5];
|
||||
|
||||
if (serverhost == NULL || strlen(serverhost) == 0)
|
||||
{
|
||||
std::cout << "Missing hostname!\n";
|
||||
return 0;
|
||||
}
|
||||
if (serverport < 3000 || serverport > 3020)
|
||||
{
|
||||
std::cout << "Missing or invalid serverport!\n";
|
||||
return 0;
|
||||
}
|
||||
if (numberFunctionsToRun <= 0)
|
||||
{
|
||||
std::cout << "Missing or invalid number of functions to run!\n";
|
||||
return 0;
|
||||
}
|
||||
if (gamep == NULL || strlen(gamep) == 0)
|
||||
{
|
||||
std::cout << "Missing game name!\n";
|
||||
return 0;
|
||||
}
|
||||
if (gameserver == NULL || strlen(gameserver) == 0)
|
||||
{
|
||||
std::cout << "Missing game server name!\n";
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
game = narrowToWide(gamep);
|
||||
server = narrowToWide(gameserver);
|
||||
character = narrowToWide("Sabinia");
|
||||
|
||||
// ----- connect to API -----
|
||||
while(1)
|
||||
{
|
||||
ResetGlobals();
|
||||
unsigned updateDelay(100);
|
||||
unsigned loginWait(500);
|
||||
unsigned loginAttempts(0);
|
||||
//api = new apiTest(serverhost, serverport, 60, CSASSIST_APIFLAG_ASSUME_RECONNECT); //, 0, CSASSIST_APIFLAG_ASSUME_RECONNECT);
|
||||
//api->connectCSAssist(NULL, game.c_str(), server.c_str());
|
||||
//while (!ready)
|
||||
// api->Update();
|
||||
|
||||
cerr<<"numberFunctionsToRun="<< numberFunctionsToRun <<endl;
|
||||
while (!ready)
|
||||
{
|
||||
if (loginFailed)
|
||||
{
|
||||
// Here we try a different set of credintials...if we have a set.
|
||||
if (api) delete api;
|
||||
//api = new apiTest(serverhost, serverport, 60, CSASSIST_APIFLAG_ASSUME_RECONNECT);
|
||||
api = new apiTest(serverhost, serverport, 60, CSASSIST_APIFLAG_ASSUME_RECONNECT|CSASSIST_APIFLAG_NO_REDIRECT);
|
||||
track = api->connectCSAssist(NULL, game.c_str(), server.c_str());
|
||||
loginFailed = false;
|
||||
std::cout <<"Trying to connect..."<<endl;
|
||||
Base::sleep(loginWait+=500);
|
||||
if (loginWait > 5000) loginWait=500;
|
||||
}
|
||||
if (loginAttempts++ > 30)
|
||||
{
|
||||
loginAttempts = 0;
|
||||
loginFailed = true;
|
||||
delete api;
|
||||
api = NULL;
|
||||
continue;
|
||||
}
|
||||
std::cout <<"Waiting for login: track:" << track<<" ..."<<endl;
|
||||
Base::sleep(updateDelay);
|
||||
api->Update();
|
||||
}
|
||||
|
||||
for (i=0; i < numberFunctions; i++)
|
||||
functionCount[i] = 0;
|
||||
|
||||
createTicket(); // works better if we do this before timing starts
|
||||
|
||||
time_t now = time(0);
|
||||
srand(now);
|
||||
|
||||
// ----- submit random packets -----
|
||||
|
||||
for (i=0; i < (unsigned)numberFunctionsToRun; i++)
|
||||
{
|
||||
//unsigned randomFunction = 3; // to generate dummy tickets use this line
|
||||
unsigned randomFunction = 3;//rand() % numberFunctions;
|
||||
functionCount[randomFunction]++;
|
||||
#ifndef WARP_SPEED
|
||||
std::cout << " " << i << " ";
|
||||
#endif
|
||||
std::cout << " calling: "<<functionName[randomFunction] << ": " << functionCount[randomFunction] << endl;
|
||||
track = 0;
|
||||
switch (functionID[randomFunction])
|
||||
{
|
||||
case CSASSIST_CALL_NEWTICKETACTIVITY:
|
||||
character = narrowToWide("Fippy");
|
||||
if ((rand() % 10) < 5)
|
||||
track = api->requestNewTicketActivity(NULL, testUID, 0);
|
||||
else
|
||||
track = api->requestNewTicketActivity(NULL, testUID, character.c_str());
|
||||
submitted++;
|
||||
|
||||
break;
|
||||
case CSASSIST_CALL_REGISTERCHARACTER:
|
||||
uid = rand();
|
||||
track = api->requestRegisterCharacter(NULL, uid, 0, 0);
|
||||
register_list.push(uid);
|
||||
submitted++;
|
||||
break;
|
||||
case CSASSIST_CALL_GETISSUEHIERARCHY:
|
||||
lang = narrowToWide("en");
|
||||
track = api->requestGetIssueHierarchy(NULL, hierarchy.c_str(), lang.c_str());
|
||||
submitted++;
|
||||
break;
|
||||
case CSASSIST_CALL_CREATETICKET:
|
||||
createTicket();
|
||||
break;
|
||||
case CSASSIST_CALL_APPENDCOMMENT:
|
||||
comment = narrowToWide("Unicode comment by player.");
|
||||
tid = randomTicketID();
|
||||
track = api->requestAppendTicketComment(NULL, tid, testUID, character.c_str(), comment.c_str());
|
||||
submitted++;
|
||||
break;
|
||||
case CSASSIST_CALL_GETTICKETBYID:
|
||||
tid = randomTicketID();
|
||||
track = api->requestGetTicketByID(NULL, tid, 1);
|
||||
submitted++;
|
||||
break;
|
||||
case CSASSIST_CALL_GETTICKETCOMMENTS:
|
||||
tid = randomTicketID();
|
||||
track = api->requestGetTicketComments(NULL, tid, 0, (rand() % 100)+1, CSASSIST_OFFSET_START);
|
||||
submitted++;
|
||||
break;
|
||||
case CSASSIST_CALL_GETTICKET:
|
||||
track = api->requestGetTicketByCharacter(NULL, testUID, character.c_str(), 0, (rand() % 100)+1, 1);
|
||||
submitted++;
|
||||
break;
|
||||
case CSASSIST_CALL_MARKREAD:
|
||||
tid = randomTicketID();
|
||||
track = api->requestMarkTicketRead(NULL, tid);
|
||||
submitted++;
|
||||
break;
|
||||
case CSASSIST_CALL_CANCELTICKET:
|
||||
if (firstTicketID != 0)
|
||||
{
|
||||
comment = narrowToWide("Ticket closed by player");
|
||||
track = api->requestCancelTicket(NULL, firstTicketID, testUID, comment.c_str());
|
||||
if (++firstTicketID > lastTicketID)
|
||||
{
|
||||
firstTicketID = 0;
|
||||
lastTicketID = 0;
|
||||
}
|
||||
submitted++;
|
||||
}
|
||||
break;
|
||||
case CSASSIST_CALL_COMMENTCOUNT:
|
||||
tid = randomTicketID();
|
||||
track = api->requestGetTicketCommentsCount(NULL, tid);
|
||||
submitted++;
|
||||
break;
|
||||
case CSASSIST_CALL_GETDOCUMENTLIST:
|
||||
// lang = narrowToWide("en");
|
||||
// track = api->requestGetDocumentList(NULL, hierarchy.c_str(), lang.c_str());
|
||||
// submitted++;
|
||||
break;
|
||||
case CSASSIST_CALL_GETDOCUMENT:
|
||||
// track = api->requestGetDocument(NULL, 1);
|
||||
// submitted++;
|
||||
break;
|
||||
case CSASSIST_CALL_GETTICKETXMLBLOCK:
|
||||
tid = randomTicketID();
|
||||
track = api->requestGetTicketXMLBlock(NULL, tid);
|
||||
submitted++;
|
||||
break;
|
||||
case CSASSIST_CALL_GETKBARTICLE:
|
||||
/*id = narrowToWide("soe1401");
|
||||
lang = narrowToWide("en");
|
||||
track = api->requestGetKBArticle(NULL, id.c_str(), lang.c_str());
|
||||
submitted++;
|
||||
*/break;
|
||||
case CSASSIST_CALL_SEARCHKB:
|
||||
/*Plat_Unicode::String searchStr = narrowToWide("video drivers");
|
||||
lang = narrowToWide("en");
|
||||
track = api->requestSearchKB(NULL, searchStr.c_str(), lang.c_str());
|
||||
submitted++;
|
||||
*/break;
|
||||
}
|
||||
Base::sleep(5);
|
||||
//api->Update();
|
||||
if (track)
|
||||
std::cout << "called: "<< functionName[randomFunction] << ": " << functionCount[randomFunction] << " track:" <<track<< endl;
|
||||
if (submitted - received > 50)
|
||||
{
|
||||
while (submitted > received)
|
||||
{
|
||||
Base::sleep(50);
|
||||
api->Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----- Wait for final packet -----
|
||||
cout<<"Waiting for last packet..."<<endl;
|
||||
while (submitted > received) // make sure everything is complete before disconnecting
|
||||
{
|
||||
Base::sleep(50);
|
||||
api->Update();
|
||||
}
|
||||
|
||||
// ----- unregister any registered characters ----
|
||||
|
||||
while (register_list.size())
|
||||
{
|
||||
uid = register_list.front();
|
||||
register_list.pop();
|
||||
api->requestUnRegisterCharacter(NULL, uid, 0);
|
||||
submitted++;
|
||||
}
|
||||
cout<<"Waiting for unregisters..."<<endl;
|
||||
while (submitted > received) // make sure everything is complete before disconnecting
|
||||
{
|
||||
Base::sleep(50);
|
||||
api->Update();
|
||||
}
|
||||
|
||||
// ----- and clean up -----
|
||||
|
||||
time_t elapsed = time(0) - now;
|
||||
if (elapsed == 0)
|
||||
elapsed = 1;
|
||||
cout<<"Going to disconnect now."<<endl;
|
||||
api->disconnectCSAssist(NULL);
|
||||
submitted++;
|
||||
|
||||
while (submitted > received)
|
||||
{
|
||||
api->Update();
|
||||
}
|
||||
|
||||
cout<<"Going to delete API now."<<endl;
|
||||
delete api;
|
||||
api = NULL;
|
||||
// ----- report findings -----
|
||||
|
||||
for (i=0; i < numberFunctions; i++)
|
||||
std::cout << "\n" << functionName[i] << ": " << functionCount[i];
|
||||
|
||||
std::cout << "\n\nSubmitted: " << submitted << "\nReceived: " << received << "\nData Packets Rx: " << packetsRx;
|
||||
std::cout << "\nElapsed time = " << elapsed << " seconds.\n" << (received / elapsed) << " req/sec.\n" << (packetsRx / elapsed) << " pkts/sec.\n";
|
||||
// getchar();
|
||||
} //while(1)
|
||||
return(0);
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
#ifndef TEST_H
|
||||
#define TEST_H
|
||||
|
||||
#include "CSAssistgameapi.h"
|
||||
#include "CSAssistgameobjects.h"
|
||||
|
||||
extern "C" {
|
||||
#include <stdio.h>
|
||||
};
|
||||
|
||||
using namespace CSAssist;
|
||||
|
||||
//---------------------------------------------
|
||||
class apiTest : public CSAssistGameAPI
|
||||
//---------------------------------------------
|
||||
{
|
||||
public:
|
||||
apiTest(const char *, const unsigned, const unsigned, const unsigned);
|
||||
virtual ~apiTest();
|
||||
|
||||
void OnConnectCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
void OnDisconnectCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
void OnNewTicketActivity(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const unsigned NewActivityFlag, const unsigned HasTickets);
|
||||
void OnRegisterCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
void OnUnRegisterCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
void OnGetIssueHierarchy(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML hierarchyBody, const unsigned modifyDate);
|
||||
void OnCreateTicket(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
void OnAppendTicketComment(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
void OnGetTicketByID(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicket *ticketBody);
|
||||
void OnGetTicketComments(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketComment *comments, const unsigned numberRead);
|
||||
void OnGetTicketByCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const unsigned NumberReturned, const unsigned TotalNumber, const CSAssistGameAPITicket *ticketBody);
|
||||
void OnTicketChange(const CSAssistGameAPITicketID ticketID, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character);
|
||||
void OnMarkTicketRead(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
void OnCancelTicket(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
void OnGetTicketCommentsCount(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket, const unsigned count);
|
||||
void OnRequestGameLocation(const CSAssistGameAPITrack sourceTrack, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const CSAssistGameAPIUID CSRUID);
|
||||
void OnGetDocumentList(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIDocumentHeader *docList, const unsigned numberRead);
|
||||
void OnGetDocument(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistUnicodeChar *documentBody);
|
||||
void OnGetTicketXMLBlock(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML XMLBody);
|
||||
void OnSearchKB(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPISearchResult *results, const unsigned numberRead);
|
||||
void OnGetKBArticle(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML articleBody);
|
||||
void OnIssueHierarchyChanged(const CSAssistUnicodeChar *version, const CSAssistUnicodeChar *language);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
Vendored
+396
@@ -0,0 +1,396 @@
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// CSAssistgameapi.cpp
|
||||
//
|
||||
// Author: Graeme Ing ([email protected])
|
||||
// Module: CSAssist API
|
||||
//
|
||||
// copyright 2002 (c) Sony Online Entertainment Inc.
|
||||
//
|
||||
// Users layer for API
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
#pragma warning (disable: 4786)
|
||||
|
||||
|
||||
#include "CSAssistgameapi.h"
|
||||
#include "CSAssistgameapicore.h"
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPI::CSAssistGameAPI(const char *host, const unsigned port, const unsigned timeout, const unsigned flags)
|
||||
//---------------------------
|
||||
{
|
||||
core = new CSAssistGameAPIcore(this, host, port, timeout, flags);
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPI::CSAssistGameAPI(const char *serverList, const unsigned timeout, const unsigned flags)
|
||||
//---------------------------
|
||||
{
|
||||
core = new CSAssistGameAPIcore(this, serverList, timeout, flags);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPI::~CSAssistGameAPI()
|
||||
//---------------------------
|
||||
{
|
||||
delete core;
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::Update()
|
||||
//---------------------------
|
||||
{
|
||||
core->Update();
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
const char *CSAssistGameAPI::getErrorString(const CSAssistGameAPIResult result)
|
||||
//---------------------------
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case CSASSIST_RESULT_SUCCESS: return "CSASSIST_RESULT_SUCCESS";
|
||||
case CSASSIST_RESULT_TIMEOUT: return "CSASSIST_RESULT_TIMEOUT";
|
||||
case CSASSIST_RESULT_FAIL: return "CSASSIST_RESULT_FAIL";
|
||||
case CSASSIST_RESULT_BADPARAMS: return "CSASSIST_RESULT_BADPARAMS";
|
||||
case CSASSIST_RESULT_OUTOFMEMORY: return "CSASSIST_RESULT_OUTOFMEMORY";
|
||||
case CSASSIST_RESULT_NOTICKET: return "CSASSIST_RESULT_NOTICKET";
|
||||
case CSASSIST_RESULT_NOCREATE_TICKET: return "CSASSIST_RESULT_NOCREATE_TICKET";
|
||||
case CSASSIST_RESULT_UNKNOWN_USER: return "CSASSIST_RESULT_UNKNOWN_USER";
|
||||
case CSASSIST_RESULT_NOCREATE_COMMENT: return "CSASSIST_RESULT_NOCREATE_COMMENT";
|
||||
case CSASSIST_RESULT_TICKETLOCKED: return "CSASSIST_RESULT_TICKETLOCKED";
|
||||
case CSASSIST_RESULT_DBERROR: return "CSASSIST_RESULT_DBERROR";
|
||||
case CSASSIST_RESULT_TOOMANYOBJECTS: return "CSASSIST_RESULT_TOOMANYOBJECTS";
|
||||
case CSASSIST_RESULT_INVALID_ACCOUNT: return "CSASSIST_RESULT_INVALID_ACCOUNT";
|
||||
case CSASSIST_RESULT_ACCOUNT_CLOSED: return "CSASSIST_RESULT_ACCOUNT_CLOSED";
|
||||
case CSASSIST_RESULT_INVALID_DOCUMENTID:return "CSASSIST_RESULT_INVALID_DOCUMENTID";
|
||||
case CSASSIST_RESULT_TICKET_XMLFAILED: return "CSASSIST_RESULT_TICKET_XMLFAILED";
|
||||
case CSASSIST_RESULT_ALREADY_REGISTERED:return "CSASSIST_RESULT_ALREADY_REGISTERED";
|
||||
case CSASSIST_RESULT_PRIMUS_ERROR: return "CSASSIST_RESULT_PRIMUS_ERROR";
|
||||
case CSASSIST_RESULT_TOOMANY_FILTERS: return "CSASSIST_RESULT_TOOMANY_FILTERS";
|
||||
case CSASSIST_RESULT_ALREADY_LOGGEDIN: return "CSASSIST_RESULT_ALREADY_LOGGEDIN";
|
||||
case CSASSIST_RESULT_UNKNOWN_FILTER: return "CSASSIST_RESULT_UNKNWON_FILTER";
|
||||
case CSASSIST_RESULT_BAD_VERSION: return "CSASSIST_RESULT_BAD_VERSION";
|
||||
case CSASSIST_RESULT_SERVER_DISCONNECT: return "CSASSIST_RESULT_SERVER_DISCONNECT";
|
||||
}
|
||||
return "CSASSIST_RESULT_UNKNOWN";
|
||||
}
|
||||
|
||||
//----------------------------------------------------
|
||||
//
|
||||
// Override API calls here! **** ADD CODE HERE ****
|
||||
//
|
||||
//----------------------------------------------------
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::setMaxPacketsPerSecond(const unsigned n)
|
||||
//---------------------------
|
||||
{
|
||||
core->setMaxPacketsPerSecond(n);
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
const char *CSAssistGameAPI::GetConnectedHost()
|
||||
//------------------------------------------------------
|
||||
{
|
||||
return core->GetConnectedHost();
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
int CSAssistGameAPI::GetConnectedPort()
|
||||
//------------------------------------------------------
|
||||
{
|
||||
return core->GetConnectedPort();
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::connectCSAssist(const void *userData, const CSAssistUnicodeChar *GameName, const CSAssistUnicodeChar *ServerName)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->connectCSAssist(userData, GameName, ServerName));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::disconnectCSAssist(const void *userData)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->disconnectCSAssist(userData));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestNewTicketActivity(const void *userData, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestNewTicketActivity(userData, uid, character));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestRegisterCharacter(const void *userData, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const unsigned avaconID)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestRegisterCharacter(userData, uid, character, avaconID));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestUnRegisterCharacter(const void *userData, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestUnRegisterCharacter(userData, uid, character));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestGetIssueHierarchy(const void *userData, const CSAssistUnicodeChar *version, const CSAssistUnicodeChar *language)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestGetIssueHierarchy(userData, version, language));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestCreateTicket(const void *userData, const CSAssistGameAPITicket *ticketBody, const CSAssistUnicodeChar *XMLBody, const CSAssistGameAPIUID uid)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestCreateTicket(userData, ticketBody, XMLBody, uid));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestAppendTicketComment(const void *userData, const CSAssistGameAPITicketID ticket, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const CSAssistUnicodeChar *comment)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestAppendTicketComment(userData, ticket, uid, character, comment));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestGetTicketByID(const void *userData, const CSAssistGameAPITicketID ticket, const unsigned FlagAsRead)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestGetTicketByID(userData, ticket, FlagAsRead));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestGetTicketComments(const void *userData, const CSAssistGameAPITicketID ticket, const unsigned Start, const unsigned Count, const CSAssistGameAPIOffset offset)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestGetTicketComments(userData, ticket, Start, Count, offset));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestGetTicketByCharacter(const void *userData, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar * character, const unsigned Start, const unsigned Count, const unsigned FlagAsRead)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestGetTicketByCharacter(userData, uid, character, Start, Count, FlagAsRead));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestMarkTicketRead(const void *userData, const CSAssistGameAPITicketID ticket)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestMarkTicketRead(userData, ticket));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestCancelTicket(const void *userData, const CSAssistGameAPITicketID ticket, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *comment)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestCancelTicket(userData, ticket, uid, comment));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestGetTicketCommentsCount(const void *userData, const CSAssistGameAPITicketID ticket)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestGetTicketCommentsCount(userData, ticket));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::replyGameLocation(const void *userData, const CSAssistGameAPITrack sourceTrack, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const CSAssistGameAPIUID csruid, const CSAssistUnicodeChar *locationString)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->replyGameLocation(userData, sourceTrack, uid, character, csruid, locationString));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestGetDocumentList(const void *userData, const CSAssistUnicodeChar *version, const CSAssistUnicodeChar *language)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestGetDocumentList(userData, version, language));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestGetDocument(const void *userData, const unsigned id)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestGetDocument(userData, id));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestGetTicketXMLBlock(const void *userData, const CSAssistGameAPITicketID id)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestGetTicketXMLBlock(userData, id));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestGetKBArticle(const void *userData, const CSAssistUnicodeChar *id, const CSAssistUnicodeChar *language, const CSAssistGameAPIUID uid)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestGetKBArticle(userData, id, language, uid));
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
CSAssistGameAPITrack CSAssistGameAPI::requestSearchKB(const void *userData, const CSAssistUnicodeChar *searchstring, const CSAssistUnicodeChar *language, const CSAssistGameAPIUID uid)
|
||||
//---------------------------
|
||||
{
|
||||
return(core->requestSearchKB(userData, searchstring, language, uid));
|
||||
}
|
||||
|
||||
//----------------------------------------------------
|
||||
//
|
||||
// Override API callbacks here! **** ADD CODE HERE ****
|
||||
//
|
||||
//----------------------------------------------------
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnConnectCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnConnectRejectedCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnDisconnectCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnNewTicketActivity(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const unsigned NewActivityFlag, const unsigned HasTickets)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnRegisterCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnUnRegisterCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnGetIssueHierarchy(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML hierarchyBody, const unsigned modifyDate)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnCreateTicket(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnAppendTicketComment(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnGetTicketByID(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicket *ticketBody)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnGetTicketComments(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketComment *comments, const unsigned numberRead)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnGetTicketByCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const unsigned NumberReturned, const unsigned TotalNumber, const CSAssistGameAPITicket *ticketBody)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnTicketChange(const CSAssistGameAPITicketID ticketID, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnMarkTicketRead(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnCancelTicket(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnGetTicketCommentsCount(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket, const unsigned count)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnRequestGameLocation(const CSAssistGameAPITrack sourceTrack, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const CSAssistGameAPIUID CSRUID)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnGetDocumentList(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIDocumentHeader *docList, const unsigned numberRead)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnGetDocument(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistUnicodeChar *documentBody)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnGetTicketXMLBlock(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML XMLBody)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnGetKBArticle(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML articleBody, const CSAssistUnicodeChar *articleTitle)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnSearchKB(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPISearchResult *results, const unsigned numberRead)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
void CSAssistGameAPI::OnIssueHierarchyChanged(const CSAssistUnicodeChar *version, const CSAssistUnicodeChar *language, const CSAssistGameAPIHierarchyChangeType type)
|
||||
//---------------------------
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace CSAssist
|
||||
|
||||
Vendored
+239
@@ -0,0 +1,239 @@
|
||||
#ifndef __CSASSISTGAMEAPI_H
|
||||
#define __CSASSISTGAMEAPI_H
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// CSAssistgameapi.h
|
||||
//
|
||||
// Author: Graeme Ing ([email protected])
|
||||
// Module: CSAssist API
|
||||
//
|
||||
// copyright 2002 (c) Sony Online Entertainment Inc.
|
||||
//
|
||||
// Main Header file for use by the API client
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
#if defined(BUILD_CSADLL)
|
||||
#define CSADLL_EXPORT __declspec(dllexport)
|
||||
#elif defined(USE_CSADLL)
|
||||
#define CSADLL_EXPORT __declspec(dllimport)
|
||||
#else
|
||||
#define CSADLL_EXPORT
|
||||
#endif
|
||||
|
||||
|
||||
#include "time.h"
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Define some API types here to identify CSAssist variables
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
typedef unsigned CSAssistGameAPITrack; // An API tracking number
|
||||
typedef unsigned CSAssistGameAPIUID; // A station UID
|
||||
typedef unsigned CSAssistGameAPITicketID; // A ticket ID
|
||||
typedef unsigned short CSAssistUnicodeChar; // base type for unicode strings (uint16)
|
||||
typedef CSAssistUnicodeChar *CSAssistGameAPIXML;// A pointer to an XML block
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Most API callbacks will return one of these result codes
|
||||
// be sure to check for CSASSIST_RESULT_SUCCESS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
CSADLL_EXPORT enum CSAssistGameAPIResult // Result codes from all API calls
|
||||
{
|
||||
CSASSIST_RESULT_SUCCESS = 0, // 0 operation was successful
|
||||
CSASSIST_RESULT_TIMEOUT, // 1 operation resulted in an API side timeout
|
||||
CSASSIST_RESULT_FAIL, // 2 general failure
|
||||
CSASSIST_RESULT_BADPARAMS, // 3 Client passed in bad parameters (strings too long etc)
|
||||
CSASSIST_RESULT_OUTOFMEMORY, // 4 failed to allocate some memory somehow
|
||||
CSASSIST_RESULT_NOTICKET, // 5 ticket not found, probably illegal ticket ID
|
||||
CSASSIST_RESULT_NOCREATE_TICKET, // 6 failed to create ticket
|
||||
CSASSIST_RESULT_UNKNOWN_USER, // 7 request cannot be made by an anonymous user (user connectCSAssist)
|
||||
CSASSIST_RESULT_NOCREATE_COMMENT, // 8 failed to create ticket comment
|
||||
CSASSIST_RESULT_TICKETLOCKED, // 9 ticked locked by another CSR
|
||||
CSASSIST_RESULT_DBERROR, // 10 operation failed due to a database problem
|
||||
CSASSIST_RESULT_TOOMANYOBJECTS, // 11 trying to obtain too many tickets/comments!
|
||||
CSASSIST_RESULT_INVALID_ACCOUNT, // 12 unvalidated user, probably wrong login name and/or password
|
||||
CSASSIST_RESULT_ACCOUNT_CLOSED, // 13 validated account but marked closed/banned
|
||||
CSASSIST_RESULT_INVALID_DOCUMENTID, // 14 document ID requested does not exist
|
||||
CSASSIST_RESULT_TICKET_XMLFAILED, // 15 failed to write XML block when creating a ticket.
|
||||
// main ticket was still created, so this error *could* be ignored
|
||||
CSASSIST_RESULT_ALREADY_REGISTERED, // 16 player character/UID was already registered for this game/server
|
||||
// he will remain registered, but this indicates a potential application bug
|
||||
CSASSIST_RESULT_PRIMUS_ERROR, // 17 Primus Knowledge Base returned an error, or malformed XML returned
|
||||
CSASSIST_RESULT_TOOMANY_FILTERS, // 18 CSR cannot have any more filters
|
||||
CSASSIST_RESULT_ALREADY_LOGGEDIN, // 19 CSR or game server is already connected and cannot have multiple connections
|
||||
CSASSIST_RESULT_UNKNOWN_FILTER, // 20 Tried to manipulate or remove a filter that does not exist
|
||||
CSASSIST_RESULT_BAD_VERSION, // 21 Incorrect API for this server, probably an old API!
|
||||
CSASSIST_RESULT_SERVER_DISCONNECT // 22 The API was disconnected from the backend. Not a user requested disconnect.
|
||||
};
|
||||
|
||||
CSADLL_EXPORT enum CSAssistGameAPIOffset // offset for First/Last type commands
|
||||
{
|
||||
CSASSIST_OFFSET_START = 0,
|
||||
CSASSIST_OFFSET_END = 1
|
||||
};
|
||||
|
||||
CSADLL_EXPORT enum CSAssistTicketStatus
|
||||
{
|
||||
TICKET_STATUS_NEWTICKET = 0,
|
||||
TICKET_STATUS_UNUSED, // pad
|
||||
TICKET_STATUS_WAIT_PLAYER, // waiting for response from player
|
||||
TICKET_STATUS_WAIT_CSR, // waiting for response from CSR
|
||||
TICKET_STATUS_PENDING_CLOSED, // CSR has closed ticket, awaiting final read by player first
|
||||
TICKET_STATUS_CLOSED // closed MUST remain at 5 for DB stored procs!
|
||||
};
|
||||
|
||||
CSADLL_EXPORT enum CSAssistBugStatus
|
||||
{
|
||||
BUG_STATUS_NONE = 0, // not a bug
|
||||
BUG_STATUS_BUG, // A bug but not assigned another category yet
|
||||
BUG_STATUS_REPEATABLE,
|
||||
BUG_STATUS_UNREPEATABLE,
|
||||
BUG_STATUS_PENDING,
|
||||
BUG_STATUS_DUPE,
|
||||
BUG_STATUS_CLOSED
|
||||
};
|
||||
|
||||
CSADLL_EXPORT enum CSAssistGameAPICommentType
|
||||
{
|
||||
CSASSIST_COMMENT_NONE = 0,
|
||||
CSASSIST_COMMENT_FROM_CSR,
|
||||
CSASSIST_COMMENT_FROM_PLAYER
|
||||
};
|
||||
|
||||
CSADLL_EXPORT enum CSAssistGameAPIHierarchyChangeType
|
||||
{
|
||||
CSASSIST_HIERARCHY_NONE = 0,
|
||||
CSASSIST_HIERARCHY_ADDED,
|
||||
CSASSIST_HIERARCHY_UPDATED,
|
||||
CSASSIST_HIERARCHY_DELETED
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Flags passed to the instantiation of the API
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static const unsigned CSASSIST_APIFLAG_ASSUME_RECONNECT = 0x001;
|
||||
// If communication is lost with the server, the API may have already queued
|
||||
// up many requests. This flag determines whether they will be immediately
|
||||
// returned as an error to the calling application, or left on their original
|
||||
// timeout, to see if a server reconnect occurs quickly.
|
||||
// Set this flag to let the reconnect try to happen. Connection to the server
|
||||
// may reoccur with 5 seconds which is substantially less than the usual
|
||||
// timeout values of 60 secs or more.
|
||||
// Default is for this flag NOT to be set. All queued requests will be
|
||||
// immediately timed out.
|
||||
|
||||
static const unsigned CSASSIST_APIFLAG_NO_REDIRECT = 0x002;
|
||||
// This flag will not make the API make one hop via a RedirectServer to connect
|
||||
// to the actual CSAssist backend. If the RECONNECT flag above is set and this is not,
|
||||
// the API will always try to first connect to a RedirectServer to re-connect
|
||||
// to CSAssist.
|
||||
// Defailt is for this flag NOT to be set. All connect requests will attempt
|
||||
// to connect to a RedirectServer initially.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// String lengths within objects
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static const unsigned CSASSIST_TICKET_LENGTH_GAME = 25;
|
||||
static const unsigned CSASSIST_TICKET_LENGTH_SERVER = 50;
|
||||
static const unsigned CSASSIST_TICKET_LENGTH_CHARACTER = 64;
|
||||
static const unsigned CSASSIST_TICKET_LENGTH_DETAILS = 4000;
|
||||
static const unsigned CSASSIST_TICKET_LENGTH_LANGUAGE = 2;
|
||||
static const unsigned CSASSIST_TICKET_LENGTH_COMMENT = 4000;
|
||||
static const unsigned CSASSIST_TICKET_LENGTH_NAME = 64;
|
||||
static const unsigned CSASSIST_TICKET_LENGTH_LOCATION = 128;
|
||||
|
||||
static const short CSASSIST_NUM_CATEGORIES = 4;
|
||||
|
||||
static const unsigned CSASSIST_DOCUMENT_LENGTH_NAME = 25;
|
||||
static const unsigned CSASSIST_DOCUMENT_LENGTH_LANGUAGE = 2;
|
||||
static const unsigned CSASSIST_DOCUMENT_LENGTH_TITLE = 64;
|
||||
static const unsigned CSASSIST_DOCUMENT_LENGTH_GAMESUBCODE = 50;
|
||||
|
||||
static const unsigned CSASSIST_KBSEARCH_LENGTH_TITLE = 255;
|
||||
static const unsigned CSASSIST_KBSEARCH_LENGTH_ID = 64;
|
||||
|
||||
class CSAssistGameAPIcore;
|
||||
class CSAssistGameAPITicket;
|
||||
class CSAssistGameAPITicketComment;
|
||||
class CSAssistGameAPIDocumentHeader;
|
||||
class CSAssistGameAPISearchResult;
|
||||
|
||||
//---------------------------
|
||||
class CSADLL_EXPORT CSAssistGameAPI
|
||||
//---------------------------
|
||||
{
|
||||
public:
|
||||
CSAssistGameAPI(const char *host, const unsigned port, const unsigned timeout, const unsigned flags);
|
||||
CSAssistGameAPI(const char *serverList, const unsigned timeout = 0, const unsigned flags = CSASSIST_APIFLAG_ASSUME_RECONNECT);
|
||||
virtual ~CSAssistGameAPI();
|
||||
|
||||
// **** ADD CODE HERE ****
|
||||
CSAssistGameAPITrack connectCSAssist(const void *userData, const CSAssistUnicodeChar *GameName, const CSAssistUnicodeChar *ServerName);
|
||||
CSAssistGameAPITrack disconnectCSAssist(const void *userData);
|
||||
CSAssistGameAPITrack requestNewTicketActivity(const void *userData, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character);
|
||||
CSAssistGameAPITrack requestRegisterCharacter(const void *userData, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const unsigned avaconID);
|
||||
CSAssistGameAPITrack requestUnRegisterCharacter(const void *userData, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character);
|
||||
CSAssistGameAPITrack requestGetIssueHierarchy(const void *userData, const CSAssistUnicodeChar *version, const CSAssistUnicodeChar *language);
|
||||
CSAssistGameAPITrack requestCreateTicket(const void *userData, const CSAssistGameAPITicket *ticketBody, const CSAssistUnicodeChar *XMLBody, const CSAssistGameAPIUID uid);
|
||||
CSAssistGameAPITrack requestAppendTicketComment(const void *userData, const CSAssistGameAPITicketID ticket, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const CSAssistUnicodeChar *comment);
|
||||
CSAssistGameAPITrack requestGetTicketByID(const void *userData, const CSAssistGameAPITicketID ticket, const unsigned FlagAsRead);
|
||||
CSAssistGameAPITrack requestGetTicketComments(const void *userData, const CSAssistGameAPITicketID ticket, const unsigned Start, const unsigned Count, const CSAssistGameAPIOffset offset);
|
||||
CSAssistGameAPITrack requestGetTicketByCharacter(const void *userData, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const unsigned Start, const unsigned Count, const unsigned FlagAsRead);
|
||||
CSAssistGameAPITrack requestMarkTicketRead(const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
CSAssistGameAPITrack requestCancelTicket(const void *userData, const CSAssistGameAPITicketID ticket, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *comment);
|
||||
CSAssistGameAPITrack requestGetTicketCommentsCount(const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
CSAssistGameAPITrack replyGameLocation(const void *userData, const CSAssistGameAPITrack sourceTrack, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const CSAssistGameAPIUID csruid, const CSAssistUnicodeChar *locationString);
|
||||
CSAssistGameAPITrack requestGetDocumentList(const void *userData, const CSAssistUnicodeChar *version, const CSAssistUnicodeChar *language);
|
||||
CSAssistGameAPITrack requestGetDocument(const void *userData, const unsigned id);
|
||||
CSAssistGameAPITrack requestGetTicketXMLBlock(const void *userData, const CSAssistGameAPITicketID id);
|
||||
CSAssistGameAPITrack requestGetKBArticle(const void *userData, const CSAssistUnicodeChar *id, const CSAssistUnicodeChar *language, const CSAssistGameAPIUID uid);
|
||||
CSAssistGameAPITrack requestSearchKB(const void *userData, const CSAssistUnicodeChar *searchstring, const CSAssistUnicodeChar *language, const CSAssistGameAPIUID uid);
|
||||
void setMaxPacketsPerSecond(const unsigned n);
|
||||
|
||||
// ----- remember to copy off any pointer based variables for your own use -----
|
||||
// ----- when the callback returns, this data will be deleted!! -----
|
||||
|
||||
virtual void OnConnectCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
virtual void OnConnectRejectedCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
virtual void OnDisconnectCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
virtual void OnNewTicketActivity(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const unsigned NewActivityFlag, const unsigned HasTickets);
|
||||
virtual void OnRegisterCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
virtual void OnUnRegisterCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
virtual void OnGetIssueHierarchy(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML hierarchyBody, const unsigned modifyDate);
|
||||
virtual void OnCreateTicket(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
virtual void OnAppendTicketComment(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
virtual void OnGetTicketByID(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicket *ticketBody);
|
||||
virtual void OnGetTicketComments(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketComment *comments, const unsigned numberRead);
|
||||
virtual void OnGetTicketByCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const unsigned NumberReturned, const unsigned TotalNumber, const CSAssistGameAPITicket *ticketBody);
|
||||
virtual void OnTicketChange(const CSAssistGameAPITicketID ticketID, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character);
|
||||
virtual void OnMarkTicketRead(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
virtual void OnCancelTicket(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
virtual void OnGetTicketCommentsCount(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket, const unsigned count);
|
||||
virtual void OnRequestGameLocation(const CSAssistGameAPITrack sourceTrack, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const CSAssistGameAPIUID CSRUID);
|
||||
virtual void OnGetDocumentList(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIDocumentHeader *docList, const unsigned numberRead);
|
||||
virtual void OnGetDocument(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistUnicodeChar *documentBody);
|
||||
virtual void OnGetTicketXMLBlock(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML XMLBody);
|
||||
virtual void OnGetKBArticle(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML articleBody, const CSAssistUnicodeChar *articleTitle);
|
||||
virtual void OnSearchKB(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPISearchResult *results, const unsigned numberRead);
|
||||
virtual void OnIssueHierarchyChanged(const CSAssistUnicodeChar *version, const CSAssistUnicodeChar *language, const CSAssistGameAPIHierarchyChangeType type);
|
||||
|
||||
void Update();
|
||||
const char *getErrorString(const CSAssistGameAPIResult result);
|
||||
const char *GetConnectedHost();
|
||||
int GetConnectedPort();
|
||||
|
||||
private:
|
||||
CSAssistGameAPIcore *core;
|
||||
};
|
||||
|
||||
} // namespace CSAssist
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
BIN
Binary file not shown.
Vendored
+1567
File diff suppressed because it is too large
Load Diff
Vendored
+225
@@ -0,0 +1,225 @@
|
||||
#ifndef __CSASSISTGAMEAPICORE_H
|
||||
#define __CSASSISTGAMEAPICORE_H
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// CSAssistgameapicore.h
|
||||
//
|
||||
// Author: Graeme Ing ([email protected])
|
||||
// Module: CSAssist API
|
||||
//
|
||||
// copyright 2002 (c) Sony Online Entertainment Inc.
|
||||
//
|
||||
// Main API internal header file
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#ifdef USE_UDP_LIBRARY
|
||||
#include "UdpLibrary/UdpLibrary.hpp"
|
||||
#else
|
||||
#include <TcpLibrary/TcpConnection.h>
|
||||
#include <TcpLibrary/TcpHandlers.h>
|
||||
#include <TcpLibrary/TcpManager.h>
|
||||
#endif
|
||||
|
||||
#include "Base/Archive.h"
|
||||
|
||||
#include "CSAssistgameapi.h"
|
||||
#include "CSAssistgameobjects.h"
|
||||
#include "packdata.h"
|
||||
#include "Unicode/Unicode.h"
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
|
||||
static const unsigned MAX_PACKETS_PER_SEC = 500;
|
||||
static const unsigned NORMAL_TIMEOUT_VAL = 60; // 60 seconds
|
||||
//static const unsigned NORMAL_TIMEOUT_VAL = 5; // debug = 5 seconds
|
||||
static const unsigned TRACK_CONNECTLB = 0;
|
||||
static const unsigned CONNECTLB_TIMEOUT = 5; // 5 seconds
|
||||
|
||||
struct timeout {
|
||||
inline timeout()
|
||||
{
|
||||
time = 0;
|
||||
track = 0;
|
||||
}
|
||||
inline timeout(unsigned tr, int ti)
|
||||
{
|
||||
time = ti;
|
||||
track = tr;
|
||||
}
|
||||
|
||||
int time;
|
||||
unsigned track;
|
||||
};
|
||||
|
||||
enum CONNECT_STATE
|
||||
{
|
||||
CONNECT_INIT = 0
|
||||
,CONNECT_REDIRECT_INIT // 1
|
||||
,CONNECT_REDIRECT_NEGOTIATING // 2
|
||||
,CONNECT_REDIRECT_CONNECTED // 3
|
||||
,CONNECT_REDIRECT_DISCONNECTED // 4
|
||||
,CONNECT_BACKEND_INIT // 5
|
||||
,CONNECT_BACKEND_NEGOTIATING // 6
|
||||
,CONNECT_BACKEND_CONNECTED // 7
|
||||
,CONNECT_BACKEND_CONNECTED_AND_AUTHED // 8
|
||||
,CONNECT_BACKEND_DISCONNECTED // 9
|
||||
};
|
||||
|
||||
struct ServerID {
|
||||
std::string host;
|
||||
unsigned port;
|
||||
};
|
||||
|
||||
//--------------------------------------
|
||||
class RegisteredCharacter
|
||||
//--------------------------------------
|
||||
{
|
||||
public:
|
||||
|
||||
RegisteredCharacter(const unsigned uid, const Plat_Unicode::String character, const unsigned avaconID);
|
||||
virtual ~RegisteredCharacter();
|
||||
|
||||
Plat_Unicode::String getCharacter() { return character; }
|
||||
unsigned getUID() { return uid; }
|
||||
unsigned getAvaconID() { return avaconID; }
|
||||
|
||||
private:
|
||||
CSAssistGameAPIUID uid; // station UID
|
||||
Plat_Unicode::String character; // character name
|
||||
unsigned avaconID; // universal chat system UID
|
||||
};
|
||||
|
||||
class Response;
|
||||
class Request;
|
||||
class CSAssistReceiver;
|
||||
class CSAssistGameAPI;
|
||||
class RegisteredCharacter;
|
||||
|
||||
//--------------------------------------
|
||||
class CSAssistGameAPIcore
|
||||
//--------------------------------------
|
||||
{
|
||||
public:
|
||||
friend class CSAssist::CSAssistReceiver;
|
||||
|
||||
CSAssistGameAPIcore(CSAssistGameAPI *api, const char *host, const unsigned port, const unsigned timeout, const unsigned flags);
|
||||
CSAssistGameAPIcore(CSAssistGameAPI *api, const char *serverList, const unsigned timeout, const unsigned flags);
|
||||
virtual ~CSAssistGameAPIcore();
|
||||
|
||||
// **** ADD CODE HERE ****
|
||||
CSAssistGameAPITrack connectCSAssist(const void *userData, const CSAssistUnicodeChar *GameName, const CSAssistUnicodeChar *ServerName);
|
||||
CSAssistGameAPITrack disconnectCSAssist(const void *userData);
|
||||
CSAssistGameAPITrack requestNewTicketActivity(const void *userData, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character);
|
||||
CSAssistGameAPITrack requestRegisterCharacter(const void *userData, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const unsigned avaconID);
|
||||
CSAssistGameAPITrack requestUnRegisterCharacter(const void *userData, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character);
|
||||
CSAssistGameAPITrack requestGetIssueHierarchy(const void *userData, const CSAssistUnicodeChar *version, const CSAssistUnicodeChar *language);
|
||||
CSAssistGameAPITrack requestCreateTicket(const void *userData, const CSAssistGameAPITicket *ticketBody, const CSAssistUnicodeChar *XMLBody, const CSAssistGameAPIUID uid);
|
||||
CSAssistGameAPITrack requestAppendTicketComment(const void *userData, const CSAssistGameAPITicketID ticket, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const CSAssistUnicodeChar *comment);
|
||||
CSAssistGameAPITrack requestGetTicketByID(const void *userData, const CSAssistGameAPITicketID ticket, const unsigned FlagAsRead);
|
||||
CSAssistGameAPITrack requestGetTicketComments(const void *userData, const CSAssistGameAPITicketID ticket, const unsigned Start, const unsigned Count, const CSAssistGameAPIOffset offset);
|
||||
CSAssistGameAPITrack requestGetTicketByCharacter(const void *userData, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const unsigned Start, const unsigned Count, const unsigned FlagAsRead);
|
||||
CSAssistGameAPITrack requestMarkTicketRead(const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
CSAssistGameAPITrack requestCancelTicket(const void *userData, const CSAssistGameAPITicketID ticket, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *comment);
|
||||
CSAssistGameAPITrack requestGetTicketCommentsCount(const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
CSAssistGameAPITrack replyGameLocation(const void *userData, const CSAssistGameAPITrack sourceTrack, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const CSAssistGameAPIUID csruid, const CSAssistUnicodeChar *locationString);
|
||||
CSAssistGameAPITrack requestGetDocumentList(const void *userData, const CSAssistUnicodeChar *version, const CSAssistUnicodeChar *language);
|
||||
CSAssistGameAPITrack requestGetDocument(const void *userData, const unsigned id);
|
||||
CSAssistGameAPITrack requestGetTicketXMLBlock(const void *userData, const CSAssistGameAPITicketID id);
|
||||
CSAssistGameAPITrack requestGetKBArticle(const void *userData, const CSAssistUnicodeChar *id, const CSAssistUnicodeChar *language, const CSAssistGameAPIUID uid);
|
||||
CSAssistGameAPITrack requestSearchKB(const void *userData, const CSAssistUnicodeChar *searchstring, const CSAssistUnicodeChar *language, const CSAssistGameAPIUID uid);
|
||||
void setMaxPacketsPerSecond(const unsigned n);
|
||||
|
||||
void Update();
|
||||
void CSAssistGameCallback(Response *);
|
||||
void localUnRegisterCharacter(const unsigned uid, const Plat_Unicode::String character);
|
||||
void localRegisterCharacter(const unsigned uid, const Plat_Unicode::String character, const unsigned avaconID);
|
||||
void reregisterCharacters();
|
||||
bool isInternalTrackingNumber(const unsigned track);
|
||||
void batchRegisterCharacters(const unsigned numToSend);
|
||||
const char* GetConnectedHost();// { return m_ip.c_str(); }
|
||||
int GetConnectedPort();// { return m_port; }
|
||||
|
||||
private:
|
||||
void SubmitRequest(Request *req, Response *res);
|
||||
void SubmitImmediateError(Response *res);
|
||||
Response *getPending(CSAssistGameAPITrack track);
|
||||
Response *getResponse(CSAssistGameAPITrack track);
|
||||
Response *createServerResponse(short msgtype);
|
||||
void SubmitRequestInt(Request *req, Response *res);
|
||||
Response *getPendingInt(CSAssistGameAPITrack track);
|
||||
Response *getResponseInt(CSAssistGameAPITrack track);
|
||||
CSAssistGameAPITrack connectCSAssistInternal();
|
||||
void ConnectLB();
|
||||
void GetLBHost();
|
||||
void OnConnectLB(unsigned track, unsigned result, std::string serverName, unsigned serverPort, Request *, Response *);
|
||||
#ifdef USE_UDP_LIBRARY
|
||||
inline bool actuallyConnected() { return (bool)((m_connection != NULL) && (m_connection->GetStatus() == UdpConnection::cStatusConnected)); }
|
||||
UdpManager *m_conManager;
|
||||
UdpConnection *m_connection;
|
||||
#else
|
||||
inline bool actuallyConnected() { return (bool)((m_connection != NULL) && (m_connection->GetStatus() == TcpConnection::StatusConnected)); }
|
||||
TcpManager *m_conManager;
|
||||
TcpConnection *m_connection;
|
||||
#endif
|
||||
|
||||
short m_port;
|
||||
short m_oldPort;
|
||||
short m_connectedPort;
|
||||
std::string m_ip; // this is supposed to be non-internationalised
|
||||
std::string m_oldIP; // this is supposed to be non-internationalised
|
||||
std::string m_connectedIP; // this is supposed to be non-internationalised
|
||||
std::list<ServerID> m_serverList;
|
||||
std::list<ServerID>::iterator m_curServer;
|
||||
CSAssistReceiver *m_receiver;
|
||||
CSAssistGameAPI *m_api;
|
||||
std::map<CSAssistGameAPITrack, Response *> m_pending;
|
||||
std::queue<timeout *> m_timeout;
|
||||
std::queue<Request *> m_outQueue;
|
||||
std::queue<Response *> m_error;
|
||||
CSAssistGameAPITrack m_currTrack;
|
||||
|
||||
std::map<CSAssistGameAPITrack, Response *> m_pendingInt;
|
||||
std::queue<timeout *> m_timeoutInt;
|
||||
std::queue<Request *> m_outQueueInt;
|
||||
std::queue<Response *> m_errorInt;
|
||||
CSAssistGameAPITrack m_currTrackInt;
|
||||
|
||||
time_t m_reconnectTimeout;
|
||||
Plat_Unicode::String m_identityGame;
|
||||
Plat_Unicode::String m_identityServer;
|
||||
unsigned m_userTimeout;
|
||||
unsigned m_flags;
|
||||
std::multimap<unsigned, RegisteredCharacter> m_registeredCharacters;
|
||||
std::set<unsigned> m_internalTracks;
|
||||
int m_numberPacketsSendPerSec;
|
||||
time_t m_gatingSecond;
|
||||
int m_packetsLeftThisSecond;
|
||||
std::multimap<unsigned, RegisteredCharacter> m_registeredCharactersCopy;
|
||||
bool m_useRedirectServer;
|
||||
bool m_isConnectedToCSAServer;
|
||||
bool m_canConnect;
|
||||
bool m_useFailoverHosts;
|
||||
bool m_connectFailed;
|
||||
CONNECT_STATE m_connectState;
|
||||
unsigned m_connectReqCount;
|
||||
unsigned m_lastConnectReqTrack;
|
||||
};
|
||||
|
||||
|
||||
} // namespace CSAssist
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
+168
@@ -0,0 +1,168 @@
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// CSAssistgameobjects.cpp
|
||||
//
|
||||
// Class member functions for user objects
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "CSAssistgameobjects.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Unicode/UnicodeUtils.h>
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
|
||||
using namespace Plat_Unicode;
|
||||
|
||||
extern CSAssistUnicodeChar *get_c_str(Plat_Unicode::String s);
|
||||
extern CSAssistUnicodeChar *copy_c_str(Plat_Unicode::String s, CSAssistUnicodeChar *dest);
|
||||
|
||||
//-----------------------------------------------------------
|
||||
unsigned UnicodeLength(const CSAssistUnicodeChar *string)
|
||||
// Return the character length of a raw uint16 string
|
||||
//-----------------------------------------------------------
|
||||
{
|
||||
CSAssistUnicodeChar *p = const_cast<CSAssistUnicodeChar *>(string);
|
||||
unsigned count = 0;
|
||||
while (*(p++) != 0)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
CSAssistGameAPITicket::CSAssistGameAPITicket() :
|
||||
ticketID(0), uid(0), createDate(0), modifiedDate(0), status(TICKET_STATUS_NEWTICKET),
|
||||
bugstatus(BUG_STATUS_NONE), isRead(0)
|
||||
//-----------------------------------------------------------
|
||||
{
|
||||
game[0] = 0;
|
||||
server[0] = 0;
|
||||
character[0] = 0;
|
||||
details[0] = 0;
|
||||
Plat_Unicode::String lang = narrowToWide("en");
|
||||
copy_c_str(lang, language);
|
||||
location[0] = 0;
|
||||
for (short i=0; i < CSASSIST_NUM_CATEGORIES; i++)
|
||||
category[i] = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
CSAssistGameAPIResult CSAssistGameAPITicket::setUID(CSAssistGameAPIUID u)
|
||||
//-----------------------------------------------------------
|
||||
{
|
||||
if (u == 0)
|
||||
return CSASSIST_RESULT_BADPARAMS;
|
||||
uid = u;
|
||||
return CSASSIST_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
CSAssistGameAPIResult CSAssistGameAPITicket::setGame(const CSAssistUnicodeChar *string)
|
||||
//-----------------------------------------------------------
|
||||
{
|
||||
unsigned length = UnicodeLength(string);
|
||||
if (length > CSASSIST_TICKET_LENGTH_GAME)
|
||||
return CSASSIST_RESULT_BADPARAMS;
|
||||
memcpy(game, string, (length+1) * sizeof(CSAssistUnicodeChar));
|
||||
return CSASSIST_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
CSAssistGameAPIResult CSAssistGameAPITicket::setServer(const CSAssistUnicodeChar *string)
|
||||
//-----------------------------------------------------------
|
||||
{
|
||||
unsigned length = UnicodeLength(string);
|
||||
if (length > CSASSIST_TICKET_LENGTH_SERVER)
|
||||
return CSASSIST_RESULT_BADPARAMS;
|
||||
memcpy(server, string, (length+1) * sizeof(CSAssistUnicodeChar));
|
||||
return CSASSIST_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
CSAssistGameAPIResult CSAssistGameAPITicket::setCharacter(const CSAssistUnicodeChar *string)
|
||||
//-----------------------------------------------------------
|
||||
{
|
||||
unsigned length = UnicodeLength(string);
|
||||
if (length > CSASSIST_TICKET_LENGTH_CHARACTER)
|
||||
return CSASSIST_RESULT_BADPARAMS;
|
||||
memcpy(character, string, (length+1) * sizeof(CSAssistUnicodeChar));
|
||||
return CSASSIST_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
CSAssistGameAPIResult CSAssistGameAPITicket::setDetails(const CSAssistUnicodeChar *string)
|
||||
//-----------------------------------------------------------
|
||||
{
|
||||
unsigned length = UnicodeLength(string);
|
||||
if (length > CSASSIST_TICKET_LENGTH_DETAILS)
|
||||
return CSASSIST_RESULT_BADPARAMS;
|
||||
memcpy(details, string, (length+1) * sizeof(CSAssistUnicodeChar));
|
||||
return CSASSIST_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
CSAssistGameAPIResult CSAssistGameAPITicket::setLanguage(const CSAssistUnicodeChar *string)
|
||||
//-----------------------------------------------------------
|
||||
{
|
||||
unsigned length = UnicodeLength(string);
|
||||
if (length > CSASSIST_TICKET_LENGTH_LANGUAGE)
|
||||
return CSASSIST_RESULT_BADPARAMS;
|
||||
memcpy(language, string, (length+1) * sizeof(CSAssistUnicodeChar));
|
||||
return CSASSIST_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
CSAssistGameAPIResult CSAssistGameAPITicket::setLocation(const CSAssistUnicodeChar *string)
|
||||
//-----------------------------------------------------------
|
||||
{
|
||||
unsigned length = UnicodeLength(string);
|
||||
if (length > CSASSIST_TICKET_LENGTH_LOCATION)
|
||||
return CSASSIST_RESULT_BADPARAMS;
|
||||
memcpy(location, string, (length+1) * sizeof(CSAssistUnicodeChar));
|
||||
return CSASSIST_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
CSAssistGameAPIResult CSAssistGameAPITicket::setCategory(unsigned index, unsigned value)
|
||||
//-----------------------------------------------------------
|
||||
{
|
||||
if (index < 0 || index >= (short)CSASSIST_NUM_CATEGORIES)
|
||||
return CSASSIST_RESULT_BADPARAMS;
|
||||
category[index] = value;
|
||||
return CSASSIST_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------
|
||||
CSAssistGameAPITicketComment::CSAssistGameAPITicketComment() :
|
||||
ticketID(0), commentID(0), uid(0), type(CSASSIST_COMMENT_NONE), modifiedDate(0)
|
||||
//-----------------------------------------------------------
|
||||
{
|
||||
comment[0] = 0;
|
||||
name[0] = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
CSAssistGameAPIDocumentHeader::CSAssistGameAPIDocumentHeader() :
|
||||
id(0), modifiedDate(0)
|
||||
//-----------------------------------------------------------
|
||||
{
|
||||
game[0] = 0;
|
||||
language[0] = 0;
|
||||
title[0] = 0;
|
||||
version[0] = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
CSAssistGameAPISearchResult::CSAssistGameAPISearchResult()
|
||||
: matchPercent(0)
|
||||
//--------------------------------------------
|
||||
{
|
||||
title[0] = 0;
|
||||
idstring[0] = 0;
|
||||
}
|
||||
|
||||
} // namespace CSAssist
|
||||
Vendored
+115
@@ -0,0 +1,115 @@
|
||||
#ifndef __GAMEOBJECTS_H
|
||||
#define __GAMEOBJECTS_H
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// CSAssistgameobjects.h
|
||||
//
|
||||
// Header file for objects used by API clients
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "CSAssistgameapi.h"
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CSAssistGameAPITicket
|
||||
//
|
||||
// This is what a ticket looks like to the client
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class CSADLL_EXPORT CSAssistGameAPITicket
|
||||
{
|
||||
public:
|
||||
CSAssistGameAPITicket();
|
||||
|
||||
void setBug() { bugstatus = BUG_STATUS_BUG; }
|
||||
CSAssistGameAPIResult setUID(CSAssistGameAPIUID u);
|
||||
CSAssistGameAPIResult setGame(const CSAssistUnicodeChar *string);
|
||||
CSAssistGameAPIResult setServer(const CSAssistUnicodeChar *string);
|
||||
CSAssistGameAPIResult setCharacter(const CSAssistUnicodeChar *string);
|
||||
CSAssistGameAPIResult setDetails(const CSAssistUnicodeChar *string);
|
||||
CSAssistGameAPIResult setLanguage(const CSAssistUnicodeChar *string);
|
||||
CSAssistGameAPIResult setLocation(const CSAssistUnicodeChar *string);
|
||||
CSAssistGameAPIResult setCategory(unsigned index, unsigned value);
|
||||
|
||||
CSAssistGameAPITicketID ticketID; // unique ID
|
||||
CSAssistGameAPIUID uid; // station UID
|
||||
time_t createDate;
|
||||
time_t modifiedDate;
|
||||
CSAssistUnicodeChar game[CSASSIST_TICKET_LENGTH_GAME+1]; // game name
|
||||
CSAssistUnicodeChar server[CSASSIST_TICKET_LENGTH_SERVER+1]; // server name
|
||||
CSAssistUnicodeChar character[CSASSIST_TICKET_LENGTH_CHARACTER+1]; // character name
|
||||
CSAssistTicketStatus status; // status of this ticket (CSAssistTicketStatus)
|
||||
CSAssistBugStatus bugstatus; // whether this is a bug report (CSAssistBugStatus)
|
||||
unsigned category[CSASSIST_NUM_CATEGORIES]; // 'n' category codes
|
||||
CSAssistUnicodeChar details[CSASSIST_TICKET_LENGTH_DETAILS+1]; // petition text from player
|
||||
CSAssistUnicodeChar language[CSASSIST_TICKET_LENGTH_LANGUAGE+1]; // language code, e.g. en, jp, fr
|
||||
unsigned isRead; // whether ticket has been read by player or not
|
||||
CSAssistUnicodeChar location[CSASSIST_TICKET_LENGTH_LOCATION+1]; // location string
|
||||
// it is recommended that location take the form of:
|
||||
// zone: X=xx.xx Y=yy.yy Z=zz.zz
|
||||
// where zone is a textual name for a region of the game and X,Y,Z are coords
|
||||
// e.g.: 'dreadlands: X=-126.89 Y=1022.67 Z=301.65
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CSAssistGameAPITicketComment
|
||||
//
|
||||
// This is what a ticket comment looks like to the client
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class CSADLL_EXPORT CSAssistGameAPITicketComment
|
||||
{
|
||||
public:
|
||||
CSAssistGameAPITicketComment();
|
||||
|
||||
CSAssistGameAPITicketID ticketID; // ticket to which this comment belongs
|
||||
unsigned commentID; // unique ID (can be used to sort comments)
|
||||
CSAssistGameAPIUID uid; // station UID (will be 0 if a CSR comment)
|
||||
CSAssistGameAPICommentType type; // whether CSR or player comment
|
||||
time_t modifiedDate; // date of this comment
|
||||
CSAssistUnicodeChar comment[CSASSIST_TICKET_LENGTH_COMMENT+1];
|
||||
CSAssistUnicodeChar name[CSASSIST_TICKET_LENGTH_NAME+1];
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CSAssistGameAPIDocumentHeader
|
||||
//
|
||||
// This is what a DocumentHeader looks like to the client
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class CSADLL_EXPORT CSAssistGameAPIDocumentHeader
|
||||
{
|
||||
public:
|
||||
CSAssistGameAPIDocumentHeader();
|
||||
|
||||
unsigned id;
|
||||
CSAssistUnicodeChar game[CSASSIST_DOCUMENT_LENGTH_NAME+1];
|
||||
CSAssistUnicodeChar language[CSASSIST_DOCUMENT_LENGTH_LANGUAGE+1];
|
||||
CSAssistUnicodeChar title[CSASSIST_DOCUMENT_LENGTH_TITLE+1];
|
||||
CSAssistUnicodeChar version[CSASSIST_DOCUMENT_LENGTH_GAMESUBCODE+1];
|
||||
time_t modifiedDate;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CSAssistGameAPISearchResult
|
||||
//
|
||||
// This is what a Knowledge Base Search Result looks like to the client
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class CSADLL_EXPORT CSAssistGameAPISearchResult
|
||||
{
|
||||
public:
|
||||
CSAssistGameAPISearchResult();
|
||||
|
||||
CSAssistUnicodeChar title[CSASSIST_KBSEARCH_LENGTH_TITLE+1];
|
||||
CSAssistUnicodeChar idstring[CSASSIST_KBSEARCH_LENGTH_ID+1];
|
||||
short matchPercent;
|
||||
};
|
||||
|
||||
} // namespace CSAssist
|
||||
|
||||
#endif
|
||||
Vendored
+172
@@ -0,0 +1,172 @@
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// CSAssistreceiver.cpp
|
||||
//
|
||||
// Author: Graeme Ing ([email protected])
|
||||
// Module: CSAssist API
|
||||
//
|
||||
// copyright 2002 (c) Sony Online Entertainment Inc.
|
||||
//
|
||||
// UDPLibrary wrapper and handler
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
#pragma warning (disable: 4786)
|
||||
|
||||
#include "CSAssistgameapicore.h"
|
||||
#include "CSAssistreceiver.h"
|
||||
#include "response.h"
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
|
||||
using namespace Base;
|
||||
|
||||
extern CSAssistUnicodeChar *get_c_str(Plat_Unicode::String s);
|
||||
extern CSAssistUnicodeChar *copy_c_str(Plat_Unicode::String s, CSAssistUnicodeChar *dest);
|
||||
|
||||
|
||||
|
||||
CSAssistReceiver::CSAssistReceiver(CSAssistGameAPIcore *core)
|
||||
: m_api(core), m_firstConnection(false), m_reconnectTrack(0)
|
||||
{
|
||||
}
|
||||
|
||||
CSAssistReceiver::~CSAssistReceiver()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
#ifdef USE_UDP_LIBRARY
|
||||
void CSAssistReceiver::OnConnectComplete(UdpConnection *con)
|
||||
#else
|
||||
void CSAssistReceiver::OnConnectRequest(TcpConnection *con)
|
||||
#endif
|
||||
//
|
||||
// Called when API has successfully connected to server...
|
||||
//--------------------------------------------------
|
||||
{
|
||||
//fprintf(stderr, "OnConnectComplete: enter!\n");
|
||||
|
||||
if (m_api->m_useRedirectServer)
|
||||
{
|
||||
switch(m_api->m_connectState)
|
||||
{
|
||||
case CONNECT_REDIRECT_NEGOTIATING:
|
||||
m_api->m_connectState = CONNECT_REDIRECT_CONNECTED;
|
||||
//if (m_firstConnection)
|
||||
m_api->ConnectLB();
|
||||
break;
|
||||
case CONNECT_BACKEND_NEGOTIATING:
|
||||
m_api->m_connectState = CONNECT_BACKEND_CONNECTED;
|
||||
//m_firstConnection = true;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "OnConnectComplete(): unknown connect state (%u)\n", m_api->m_connectState);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_api->m_connectState = CONNECT_BACKEND_CONNECTED;
|
||||
//m_firstConnection = true;
|
||||
}
|
||||
//fprintf(stderr, "debug: OnConnectComplete(): Now m_connectState=%u\n", m_api->m_connectState);
|
||||
|
||||
// resend identity to server
|
||||
if ((m_firstConnection == true || m_api->m_connectFailed) && m_api->m_connectState == CONNECT_BACKEND_CONNECTED)
|
||||
{
|
||||
//fprintf(stderr, "Trying to auto re-connect\n");
|
||||
m_reconnectTrack = m_api->connectCSAssistInternal();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_UDP_LIBRARY
|
||||
void CSAssistReceiver::OnTerminated(UdpConnection *con)
|
||||
#else
|
||||
void CSAssistReceiver::OnTerminated(TcpConnection *con)
|
||||
#endif
|
||||
{
|
||||
//fprintf(stderr,"OnTerminated(): enter\n");
|
||||
if (m_api->m_useRedirectServer)
|
||||
{
|
||||
m_api->m_connectReqCount = 0;
|
||||
switch(m_api->m_connectState)
|
||||
{
|
||||
case CONNECT_REDIRECT_CONNECTED:
|
||||
case CONNECT_REDIRECT_NEGOTIATING:
|
||||
m_api->m_connectState = CONNECT_REDIRECT_DISCONNECTED;
|
||||
m_api->GetLBHost();
|
||||
break;
|
||||
|
||||
case CONNECT_BACKEND_CONNECTED_AND_AUTHED:
|
||||
m_api->m_api->OnDisconnectCSAssist(0, CSASSIST_RESULT_SERVER_DISCONNECT, NULL);
|
||||
case CONNECT_BACKEND_CONNECTED:
|
||||
m_api->GetLBHost();
|
||||
case CONNECT_BACKEND_NEGOTIATING: m_api->m_connectState = CONNECT_BACKEND_DISCONNECTED; break;
|
||||
default:
|
||||
fprintf(stderr,"OnTermintated(): bad connectState (%u)\n", m_api->m_connectState);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_api->m_connectState == CONNECT_BACKEND_CONNECTED_AND_AUTHED)
|
||||
m_api->m_api->OnDisconnectCSAssist(0, CSASSIST_RESULT_SERVER_DISCONNECT, NULL);
|
||||
m_api->m_connectState = CONNECT_BACKEND_DISCONNECTED;
|
||||
m_api->GetLBHost();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_UDP_LIBRARY
|
||||
void CSAssistReceiver::OnCrcReject(UdpConnection *con, uchar *data, int dataLen)
|
||||
#else
|
||||
void CSAssistReceiver::OnCrcReject(TcpConnection *con, uchar *data, int dataLen)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
#ifdef USE_UDP_LIBRARY
|
||||
void CSAssistReceiver::OnRoutePacket(UdpConnection *con, const uchar *data, int dataLen)
|
||||
#else
|
||||
void CSAssistReceiver::OnRoutePacket(TcpConnection *con, const uchar *data, int dataLen)
|
||||
#endif
|
||||
//--------------------------------------------------
|
||||
{
|
||||
unsigned track, result;
|
||||
short type;
|
||||
Response *res = 0;
|
||||
|
||||
ByteStream msg(data, dataLen);
|
||||
ByteStream::ReadIterator iter = msg.begin();
|
||||
iter.advance(2); // skip short num_args
|
||||
get(iter, type);
|
||||
get(iter, track);
|
||||
get(iter, result);
|
||||
|
||||
if (type > CSASSIST_CALL_START_SERVER_MESSAGES)
|
||||
{ // ----- server-initiated calls need to create a new Response object -----
|
||||
res = m_api->createServerResponse(type);
|
||||
}
|
||||
else if (type == CSASSIST_CALL_CONNECTLB || (type == CSASSIST_CALL_CONNECT && m_firstConnection))
|
||||
{
|
||||
//fprintf(stderr,"OnRoutePacket(): got an internal connect/lb request\n");
|
||||
res = m_api->getPendingInt(track);
|
||||
}
|
||||
else // ----- API-initiated calls already have a Response object -----
|
||||
{
|
||||
res = m_api->getPending(track);
|
||||
}
|
||||
if(res != NULL)
|
||||
{
|
||||
res->init(type, track, result);
|
||||
res->decode(iter);
|
||||
m_api->CSAssistGameCallback(res);
|
||||
}
|
||||
else
|
||||
{
|
||||
//fprintf(stderr,"Dropping timed-out response type(%u) track(%u) result(%u)", type, track, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace CSAssist
|
||||
Vendored
+68
@@ -0,0 +1,68 @@
|
||||
#ifndef __CSASSISTRECEIVER_H__
|
||||
#define __CSASSISTRECEIVER_H__
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// CSAssistreceiver.h
|
||||
//
|
||||
// Author: Graeme Ing ([email protected])
|
||||
// Module: CSAssist API
|
||||
//
|
||||
// copyright 2002 (c) Sony Online Entertainment Inc.
|
||||
//
|
||||
// UDPLibrary wrapper and handler
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
#ifdef USE_UDP_LIBRARY
|
||||
#include "UdpLibrary/UdpHandler.hpp"
|
||||
#else
|
||||
#include <TcpLibrary/TcpConnection.h>
|
||||
#include <TcpLibrary/TcpHandlers.h>
|
||||
#include <TcpLibrary/TcpManager.h>
|
||||
#endif
|
||||
|
||||
#ifndef uchar
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
|
||||
class CSAssistGameAPIcore;
|
||||
|
||||
#ifdef USE_UDP_LIBRARY
|
||||
class CSAssistReceiver : public UdpConnectionHandler
|
||||
#else
|
||||
class CSAssistReceiver : public TcpConnectionHandler, public TcpManagerHandler
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
CSAssistReceiver(CSAssistGameAPIcore *api);
|
||||
virtual ~CSAssistReceiver();
|
||||
|
||||
#ifdef USE_UDP_LIBRARY
|
||||
virtual void OnRoutePacket(UdpConnection *con, const uchar *data, int dataLen);
|
||||
virtual void OnConnectComplete(UdpConnection *con);
|
||||
virtual void OnTerminated(UdpConnection *con);
|
||||
virtual void OnCrcReject(UdpConnection *con, uchar *data, int dataLen);
|
||||
#else
|
||||
virtual void OnRoutePacket(TcpConnection *con, const uchar *data, int dataLen);
|
||||
virtual void OnConnectRequest(TcpConnection *con);
|
||||
virtual void OnTerminated(TcpConnection *con);
|
||||
virtual void OnCrcReject(TcpConnection *con, uchar *data, int dataLen);
|
||||
#endif
|
||||
|
||||
CSAssistGameAPITrack getReconnectTrack() { return m_reconnectTrack; }
|
||||
|
||||
friend class CSAssistGameAPIcore;
|
||||
private:
|
||||
CSAssistGameAPIcore *m_api;
|
||||
bool m_firstConnection;
|
||||
CSAssistGameAPITrack m_reconnectTrack;
|
||||
};
|
||||
|
||||
|
||||
} // namespace CSAssist
|
||||
|
||||
#endif
|
||||
|
||||
BIN
Binary file not shown.
Vendored
+693
@@ -0,0 +1,693 @@
|
||||
//-----------------------------------------------------------------
|
||||
//
|
||||
// CSAssist Module
|
||||
//
|
||||
// API Test Program
|
||||
//
|
||||
// Author: Graeme Ing ([email protected] x3130)
|
||||
//
|
||||
// Copyright (c) 2002 Sony Online Interactive inc.
|
||||
//
|
||||
// This program simply demonstrates some calls to the
|
||||
// CSAssist API. See main()
|
||||
//
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
|
||||
#include "test.h"
|
||||
#include "Unicode/UnicodeUtils.h"
|
||||
|
||||
using namespace CSAssist;
|
||||
using namespace Plat_Unicode;
|
||||
#include <signal.h>
|
||||
#include <iostream>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#ifdef WIN32
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
apiTest *api;
|
||||
int received = 0;
|
||||
int submitted = 0;
|
||||
CSAssistGameAPIUID gUID=623259672; // csatest account
|
||||
CSAssistGameAPITicketID globalTicketID=0;
|
||||
bool ready = false;
|
||||
Plat_Unicode::String globalArticleID;
|
||||
|
||||
//----------------------------------------------
|
||||
CSAssistUnicodeChar *get_c_str(Plat_Unicode::String s)
|
||||
// This replaces c_str() by allocating a new buffer, erasing it, and then
|
||||
// using the non-null terminated data() to copy the data into the buffer.
|
||||
//----------------------------------------------
|
||||
{
|
||||
unsigned length = s.size() + 1;
|
||||
CSAssistUnicodeChar *temp = new CSAssistUnicodeChar[length];
|
||||
memset(temp, 0, length * sizeof(CSAssistUnicodeChar));
|
||||
memcpy(temp, s.data(), (length - 1) * sizeof(CSAssistUnicodeChar));
|
||||
return temp;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
CSAssistUnicodeChar *copy_c_str(Plat_Unicode::String s, CSAssistUnicodeChar *dest)
|
||||
//----------------------------------------------
|
||||
{
|
||||
unsigned length = s.size() + 1;
|
||||
memset(dest, 0, length * sizeof(CSAssistUnicodeChar));
|
||||
memcpy(dest, s.data(), (length - 1) * sizeof(CSAssistUnicodeChar));
|
||||
return dest;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
//
|
||||
// The routines that follow display basic objects
|
||||
//
|
||||
//---------------------------------------------
|
||||
|
||||
//---------------------------------------------
|
||||
void DisplayTicket(const CSAssistGameAPITicket *t)
|
||||
//---------------------------------------------
|
||||
{
|
||||
if (t != 0)
|
||||
{
|
||||
char date1[64], date2[64];
|
||||
strcpy(date1,ctime(&t->createDate));
|
||||
Plat_Unicode::String game = t->game;
|
||||
Plat_Unicode::String server = t->server;
|
||||
Plat_Unicode::String character = t->character;
|
||||
Plat_Unicode::String language = t->language;
|
||||
Plat_Unicode::String location = t->location;
|
||||
Plat_Unicode::String details = t->details;
|
||||
// std::cout << wideToNarrow(character) << " " << t->modifiedDate << " " << date2;
|
||||
std::cout << "***Ticket: " << t->ticketID << "\n Created: " << date1;
|
||||
strcpy(date2,ctime(&t->modifiedDate));
|
||||
std::cout << " Modified: " << date2 << " Game/Server: " << wideToNarrow(game) << ", " << wideToNarrow(server);
|
||||
std::cout << "\n Character: " << wideToNarrow(character) << "\n Status: " << t->status << "," << t->bugstatus;
|
||||
std::cout << "\n UID: " << t->uid << "\n Category: ";
|
||||
for (short i=0; i < CSASSIST_NUM_CATEGORIES; i++)
|
||||
std::cout << t->category[i] << ",";
|
||||
std::cout << "\n Language: " << wideToNarrow(language);
|
||||
std::cout << "\n Location: " << wideToNarrow(location);
|
||||
std::cout << "\n IsRead: " << t->isRead << "\n ";
|
||||
std::cout << wideToNarrow(details) << "\n***\n";
|
||||
}
|
||||
else
|
||||
std::cout << "***Ticket IS NULL! ***\n";
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void DisplayComment(const CSAssistGameAPITicketComment *t)
|
||||
//---------------------------------------------
|
||||
{
|
||||
if (t != 0)
|
||||
{
|
||||
Plat_Unicode::String name = t->name;
|
||||
Plat_Unicode::String comment = t->comment;
|
||||
std::cout << "***Comment: Comment ID: " << t->commentID << " Ticket ID: " << t->ticketID << " UID: " << t->uid;
|
||||
std::cout << " Name: " << wideToNarrow(name) << " Type: " << t->type << " Modified: " << ctime(&t->modifiedDate);
|
||||
std::cout << "\n " << wideToNarrow(comment) << "\n";
|
||||
}
|
||||
else
|
||||
std::cout << "***Comment IS NULL! ***\n";
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void DisplayDocumentHeader(const CSAssistGameAPIDocumentHeader *doc)
|
||||
//---------------------------------------------
|
||||
{
|
||||
if (doc != 0)
|
||||
{
|
||||
char date2[32];
|
||||
strcpy(date2,ctime(&doc->modifiedDate));
|
||||
Plat_Unicode::String game = doc->game;
|
||||
Plat_Unicode::String language = doc->language;
|
||||
Plat_Unicode::String title = doc->title;
|
||||
Plat_Unicode::String version = doc->version;
|
||||
std::cout << "***Document Header: ID: " << doc->id << ", Game: " << wideToNarrow(game);
|
||||
std::cout << ", Lang: " << wideToNarrow(language);
|
||||
std::cout << ", Title: " << wideToNarrow(title);
|
||||
std::cout << ", Version: " << wideToNarrow(version);
|
||||
std::cout << ", Modified: " << date2 << "\n";
|
||||
}
|
||||
else
|
||||
std::cout << "***Document Header IS NULL! ***\n";
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void DisplaySearchResult(const CSAssistGameAPISearchResult *doc)
|
||||
//---------------------------------------------
|
||||
{
|
||||
if (doc != 0)
|
||||
{
|
||||
Plat_Unicode::String id = doc->idstring;
|
||||
globalArticleID = id;
|
||||
Plat_Unicode::String title = doc->title;
|
||||
std::cout << "ID: " << wideToNarrow(id) << ", Match: " << doc->matchPercent;
|
||||
std::cout << ", Title: " << wideToNarrow(title) << "\n";
|
||||
}
|
||||
else
|
||||
std::cout << "***Search Result IS NULL! ***\n";
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------
|
||||
apiTest::apiTest(const char *hostList, const unsigned timeout = 0, const unsigned flags = 0)
|
||||
: CSAssistGameAPI(hostList, timeout, flags)
|
||||
//---------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
apiTest::apiTest(const char *host, const unsigned port, const unsigned timeout, const unsigned flags)
|
||||
: CSAssistGameAPI(host, port, timeout, flags)
|
||||
//---------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
apiTest::~apiTest()
|
||||
//---------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
//
|
||||
// The routines that follow override the API
|
||||
// callbacks. You only need to override those
|
||||
// that you are interested in.
|
||||
// Default API behavior on the callbacks is to
|
||||
// delete the message and continue.
|
||||
//
|
||||
//---------------------------------------------
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnConnectCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "Connect: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << "\n";
|
||||
if (result == CSASSIST_RESULT_SUCCESS)
|
||||
{
|
||||
std::cerr <<"Connected to host("<<api->GetConnectedHost()<<") port("<<api->GetConnectedPort()<<")"<<endl;
|
||||
ready = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnConnectRejectedCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cerr << "Connect REJECTED("<<GetConnectedHost() <<","<<GetConnectedPort()<<"): Track: " << track
|
||||
<< " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << "\n";
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnDisconnectCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cerr << "DisConnect: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << "\n";
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnRegisterCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "Register: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << "\n";
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnUnRegisterCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "UnRegister: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << "\n";
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnNewTicketActivity(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const unsigned NewActivityFlag, const unsigned HasTickets)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "NewActivity: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << ", New(" << NewActivityFlag;
|
||||
std::cout << "), HasTickets(" << HasTickets << ")\n";
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetIssueHierarchy(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML hierarchyBody, const unsigned modifyDate)
|
||||
//---------------------------------------------
|
||||
{
|
||||
received++;
|
||||
Plat_Unicode::String body = hierarchyBody;
|
||||
std::cout << "Hierarchy: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData;
|
||||
std::cout << ", XML(" << wideToNarrow(body).c_str();
|
||||
std::cout << "), ModifyDate(" << ctime((const time_t *)(&modifyDate)) << ")";
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnCreateTicket(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "Create Ticket: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << ", TicketID(" << ticket << ")\n";
|
||||
received++;
|
||||
globalTicketID = ticket;
|
||||
}
|
||||
//---------------------------------------------
|
||||
void apiTest::OnAppendTicketComment(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "Append Comment: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << ", TicketID(" << ticket << ")\n";
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetTicketByID(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicket *ticketBody)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "Get Ticket ID: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << "\n";
|
||||
if (result == CSASSIST_RESULT_SUCCESS)
|
||||
DisplayTicket(ticketBody);
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetTicketComments(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketComment *comments, const unsigned numberRead)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "Get Ticket Comments: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << ", numberRead(" << numberRead << ")\n";
|
||||
if (comments == 0)
|
||||
{
|
||||
std::cout << "***Returned no data array***\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
const CSAssistGameAPITicketComment *pt = comments;
|
||||
for (unsigned i=0; i < numberRead; i++)
|
||||
{
|
||||
DisplayComment(pt);
|
||||
pt++;
|
||||
}
|
||||
}
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetTicketByCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const unsigned NumberReturned, const unsigned TotalNumber, const CSAssistGameAPITicket *tickets)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "Get Tickets Char: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << ", numberRead(" << NumberReturned;
|
||||
std::cout << ") totalNumber(" << TotalNumber << ")\n";
|
||||
if (tickets == 0)
|
||||
{
|
||||
std::cout << "***Returned no data array***\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
const CSAssistGameAPITicket *pt = tickets;
|
||||
for (unsigned i=0; i < NumberReturned; i++)
|
||||
{
|
||||
DisplayTicket(pt);
|
||||
pt++;
|
||||
}
|
||||
}
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnTicketChange(const CSAssistGameAPITicketID ticketID, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character)
|
||||
//---------------------------------------------
|
||||
{
|
||||
Plat_Unicode::String charry = character;
|
||||
std::cout << "Ticket Change: Ticket(" << ticketID << "), uid(" << uid << "), character(" << wideToNarrow(charry) << ")\n";
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnMarkTicketRead(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "Mark Read: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << "\n";
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnCancelTicket(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "Cancel Ticket: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << ", TicketID: " << ticket << "\n";
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetTicketCommentsCount(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket, const unsigned count)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "Comment Count: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << ", TicketID(" << ticket << "), Count: " << count << "\n";
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnRequestGameLocation(const CSAssistGameAPITrack sourceTrack, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const CSAssistGameAPIUID CSRUID)
|
||||
//---------------------------------------------
|
||||
{
|
||||
Plat_Unicode::String charry = character;
|
||||
Plat_Unicode::String loc = narrowToWide("-debug character=qeynos hills");
|
||||
CSAssistUnicodeChar *rawCharry = get_c_str(charry);
|
||||
CSAssistUnicodeChar *rawLoc = get_c_str(loc);
|
||||
std::cout << "Request Game Location: Source Track(" << sourceTrack << "), uid(" << uid << "), character(";
|
||||
std::cout << wideToNarrow(charry) << "), CSR UID(" << CSRUID << ")\n";
|
||||
api->replyGameLocation(NULL, sourceTrack, uid, rawCharry, CSRUID, rawLoc);
|
||||
delete [] rawCharry;
|
||||
delete [] rawLoc;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetDocumentList(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIDocumentHeader *docList, const unsigned numberRead)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "Get DocumentList: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << ", numberRead(" << numberRead << ")\n";
|
||||
if (docList == 0)
|
||||
{
|
||||
std::cout << "***Returned no data array***\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
const CSAssistGameAPIDocumentHeader *pt = docList;
|
||||
for (unsigned i=0; i < numberRead; i++)
|
||||
{
|
||||
DisplayDocumentHeader(pt);
|
||||
pt++;
|
||||
}
|
||||
}
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetDocument(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistUnicodeChar *documentBody)
|
||||
//---------------------------------------------
|
||||
{
|
||||
Plat_Unicode::String body = documentBody;
|
||||
std::cout << "Document: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << ", Text(";
|
||||
std::cout << wideToNarrow(body) << ")\n";
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetTicketXMLBlock(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML XMLBody)
|
||||
//---------------------------------------------
|
||||
{
|
||||
Plat_Unicode::String xml = XMLBody;
|
||||
std::cout << "Ticket XML Block: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData;
|
||||
std::cout << ", XML(" << wideToNarrow(xml) << ")\n";
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnSearchKB(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPISearchResult *results, const unsigned numberRead)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "Search KB: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData << ", numberRead(" << numberRead << ")\n";
|
||||
if (results == 0)
|
||||
{
|
||||
std::cout << "***Returned no data array***\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
const CSAssistGameAPISearchResult *pt = results;
|
||||
for (unsigned i=0; i < numberRead; i++)
|
||||
{
|
||||
DisplaySearchResult(pt);
|
||||
pt++;
|
||||
}
|
||||
}
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnGetKBArticle(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML articleBody)
|
||||
//---------------------------------------------
|
||||
{
|
||||
std::cout << "KB Article: Track: " << track << " - Result: " << getErrorString(result) << " UserData: " << (unsigned)userData;
|
||||
Plat_Unicode::String body = articleBody;
|
||||
std::cout << ", Text(" << wideToNarrow(body) << ")\n";
|
||||
received++;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void apiTest::OnIssueHierarchyChanged(const CSAssistUnicodeChar *version, const CSAssistUnicodeChar *language)
|
||||
//---------------------------------------------
|
||||
{
|
||||
Plat_Unicode::String ver = version;
|
||||
Plat_Unicode::String lang = language;
|
||||
std::cout << "Hierarchy Changed: " << "Version: " << wideToNarrow(ver) << ", Lang: " << wideToNarrow(lang) << "\n";
|
||||
}
|
||||
|
||||
void sigh(int signal)
|
||||
{
|
||||
cerr<<"Caught signal: "<< signal << endl;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
int main(int argc, char **argv)
|
||||
//
|
||||
// Here is some test code to demonstrate the API
|
||||
//
|
||||
// NOTE: The copy_c_str() and get_c_str() calls are simply "hacks"
|
||||
// to replace the standard c_str() member function for unicode strings (Plat_Unicode::String)
|
||||
// This is necessary because c_str() is broken under gcc 2.96 and will not compile with
|
||||
// unicode strings :(
|
||||
// In replace of these hacks and the associated "delete [] foo" code,
|
||||
// simply use .c_str()
|
||||
//
|
||||
//---------------------------------------------
|
||||
{
|
||||
//signal(SIGPIPE, sigh);
|
||||
printf("CSAssist test client\n");
|
||||
// int serverport = 3010;
|
||||
int serverport = 3019;
|
||||
char *host = "sdplatdev2";
|
||||
string gameStr("SWG");
|
||||
for (int i(0); i < argc; i++)
|
||||
{
|
||||
if (!strcmp(argv[i],"-host"))
|
||||
host = argv[i+1];
|
||||
else if(!strcmp(argv[i], "-port"))
|
||||
serverport = atoi(argv[i+1]);
|
||||
else if(!strcmp(argv[i], "-server"))
|
||||
gameStr = argv[i+1];
|
||||
}
|
||||
//api = new apiTest(host, serverport, 160, CSASSIST_APIFLAG_ASSUME_RECONNECT);
|
||||
//api = new apiTest(host, serverport, 160, CSASSIST_APIFLAG_ASSUME_RECONNECT|CSASSIST_APIFLAG_NO_REDIRECT);
|
||||
api = new apiTest("sdplatdev2:3016 ", 30, CSASSIST_APIFLAG_ASSUME_RECONNECT);
|
||||
std::cout << "Client API ceated.\n";
|
||||
//std::cout <<"Connected to host via("<<api->GetConnectedHost()<<") port("<<api->GetConnectedPort()<<")"<<endl;
|
||||
//api->setMaxPacketsPerSecond(40);
|
||||
|
||||
//---------------------------------------------
|
||||
// test out some calls:
|
||||
// for a list of all those available, see
|
||||
// CSAssistgameapi.h
|
||||
//---------------------------------------------
|
||||
|
||||
Plat_Unicode::String game = narrowToWide(gameStr); //EQOA
|
||||
Plat_Unicode::String server = narrowToWide("CsatestServer"); // Test
|
||||
CSAssistUnicodeChar rawGame[16];
|
||||
CSAssistUnicodeChar rawServer[16];
|
||||
copy_c_str(game, rawGame);
|
||||
copy_c_str(server, rawServer);
|
||||
api->connectCSAssist((void *)6000, rawGame, rawServer);
|
||||
while (!ready)
|
||||
api->Update();
|
||||
|
||||
//return 0;
|
||||
Plat_Unicode::String lang = narrowToWide("en");
|
||||
CSAssistUnicodeChar rawLanguage[16];
|
||||
copy_c_str(lang, rawLanguage);
|
||||
/* Plat_Unicode::String hversion = narrowToWide("test"); // test
|
||||
CSAssistUnicodeChar rawVersion[32];
|
||||
copy_c_str(hversion, rawVersion);
|
||||
api->requestGetIssueHierarchy((void *)1, rawVersion, rawLanguage);
|
||||
submitted++;
|
||||
*/
|
||||
|
||||
/* Plat_Unicode::String search = narrowToWide("jedi");
|
||||
CSAssistUnicodeChar rawSearch[64];
|
||||
copy_c_str(search, rawSearch);
|
||||
api->requestSearchKB((void *)1, rawSearch, rawLanguage);
|
||||
submitted++;
|
||||
while (submitted > received)
|
||||
{
|
||||
api->Update();
|
||||
}
|
||||
Plat_Unicode::String kbid = narrowToWide("soe603");
|
||||
CSAssistUnicodeChar rawkbid[64];
|
||||
copy_c_str(kbid, rawkbid);
|
||||
api->requestGetKBArticle((void *)1, rawkbid, rawLanguage);
|
||||
submitted++;
|
||||
while (submitted > received)
|
||||
{
|
||||
api->Update();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
api->setMaxPacketsPerSecond(200);
|
||||
|
||||
Plat_Unicode::String testc;
|
||||
//unsigned i;
|
||||
unsigned j;
|
||||
//while (1)
|
||||
{
|
||||
CSAssistUnicodeChar rawChar[64];
|
||||
for (j=0; j < 100; j++)
|
||||
{
|
||||
char buff[100] = {0};
|
||||
char uidc[25] = {0};
|
||||
sprintf(buff,"TestChar%04d", j+1);
|
||||
testc = narrowToWide(buff);
|
||||
copy_c_str(testc, rawChar);
|
||||
sprintf(uidc, "%04d", j+1);
|
||||
unsigned uid = atoi(uidc);
|
||||
api->requestRegisterCharacter((void *)uid, uid, rawChar, 0);
|
||||
submitted++;
|
||||
//api->requestNewTicketActivity((void *)6002, uid, rawChar);
|
||||
//submitted++;
|
||||
//while (submitted > received)
|
||||
{
|
||||
api->Update();
|
||||
}
|
||||
}
|
||||
/* for (j=0; j < 20; j++)
|
||||
{
|
||||
for (i=0; i < 100; i++)
|
||||
{
|
||||
sprintf(buff,"TestChar%d%d", j+1, i+1);
|
||||
testc = narrowToWide(buff);
|
||||
copy_c_str(testc, rawChar);
|
||||
api->requestUnRegisterCharacter((void *)6001, (i+1)*(j+1), rawChar);
|
||||
submitted++;
|
||||
}
|
||||
//while (submitted > received)
|
||||
//{
|
||||
// api->Update();
|
||||
//}
|
||||
}
|
||||
*/
|
||||
api->Update();
|
||||
cerr<<"Waiting for register requests..."<<endl;
|
||||
while (submitted > received)
|
||||
{
|
||||
api->Update();
|
||||
}
|
||||
cerr<<"done waiting for registers."<<endl;
|
||||
|
||||
}
|
||||
|
||||
// now wait for events
|
||||
std::cerr <<"Connected to host("<<api->GetConnectedHost()<<") port("<<api->GetConnectedPort()<<")"<<endl;
|
||||
while (1)
|
||||
{
|
||||
api->Update();
|
||||
Base::sleep(50);
|
||||
}
|
||||
|
||||
|
||||
Plat_Unicode::String character = narrowToWide("CSATestChar1");
|
||||
CSAssistUnicodeChar rawChar[64];
|
||||
copy_c_str(character, rawChar);
|
||||
api->requestRegisterCharacter((void *)6001, gUID, rawChar, 0);
|
||||
submitted++;
|
||||
while (submitted > received)
|
||||
{
|
||||
api->Update();
|
||||
}
|
||||
api->requestNewTicketActivity((void *)6002, gUID, rawChar);
|
||||
submitted++;
|
||||
while (submitted > received)
|
||||
{
|
||||
api->Update();
|
||||
}
|
||||
|
||||
getchar();return 0;
|
||||
|
||||
Plat_Unicode::String details = narrowToWide("CsaTest's petition text.");
|
||||
CSAssistUnicodeChar rawDetails[64];
|
||||
copy_c_str(details, rawDetails);
|
||||
Plat_Unicode::String xml = narrowToWide("CsaTest's XML text.");
|
||||
CSAssistUnicodeChar rawxml[64];
|
||||
copy_c_str(xml, rawxml);
|
||||
CSAssistGameAPITicket t;
|
||||
t.setUID(gUID);
|
||||
t.setGame(rawGame);
|
||||
t.setServer(rawServer);
|
||||
t.setCharacter(rawChar);
|
||||
t.setDetails(rawDetails);
|
||||
t.setLanguage(rawLanguage);
|
||||
t.setCategory(0, 12);
|
||||
t.setCategory(1, 2);
|
||||
//t.setBug();
|
||||
api->requestCreateTicket((void *)1, &t, rawxml, gUID);
|
||||
submitted++;
|
||||
while (submitted > received)
|
||||
{
|
||||
api->Update();
|
||||
}
|
||||
|
||||
// api->requestNewTicketActivity((void *)6002, 99709401, 0);
|
||||
// submitted++;
|
||||
// while (submitted > received)
|
||||
// {
|
||||
// api->Update();
|
||||
// }
|
||||
|
||||
/* api->requestGetTicketByID((void *)6001, 156368, 1);
|
||||
submitted++;
|
||||
while (submitted > received)
|
||||
{
|
||||
api->Update();
|
||||
}
|
||||
*/
|
||||
// api->requestGetTicketXMLBlock((void *)1, globalTicketID);
|
||||
// submitted++;
|
||||
// while (submitted > received)
|
||||
// {
|
||||
// api->Update();
|
||||
// }
|
||||
|
||||
/* Plat_Unicode::String comment = narrowToWide("Fippys closing comment");
|
||||
CSAssistUnicodeChar rawComment[64];
|
||||
copy_c_str(comment, rawComment);
|
||||
api->requestCancelTicket((void *)1, 267997, 99709401, rawComment);
|
||||
submitted++;
|
||||
while (submitted > received)
|
||||
{
|
||||
api->Update();
|
||||
}
|
||||
*/
|
||||
#ifdef WIN32
|
||||
while (submitted > received || !kbhit()) // make sure everything is complete before disconnecting
|
||||
#else
|
||||
while (submitted > received) // make sure everything is complete before disconnecting
|
||||
#endif
|
||||
{
|
||||
api->Update();
|
||||
}
|
||||
|
||||
api->disconnectCSAssist((void *)6013);
|
||||
submitted++;
|
||||
|
||||
// ----- loop here until all sent messages have arrived -----
|
||||
// ----- in your application, just call api->Update() at regular intervals -----
|
||||
|
||||
while (submitted > received)
|
||||
{
|
||||
api->Update();
|
||||
}
|
||||
|
||||
delete api;
|
||||
return(0);
|
||||
}
|
||||
Vendored
+50
@@ -0,0 +1,50 @@
|
||||
#ifndef TEST_H
|
||||
#define TEST_H
|
||||
|
||||
#include "CSAssistgameapi.h"
|
||||
#include "CSAssistgameobjects.h"
|
||||
|
||||
extern "C" {
|
||||
#include <stdio.h>
|
||||
};
|
||||
|
||||
using namespace CSAssist;
|
||||
|
||||
//---------------------------------------------
|
||||
class apiTest : public CSAssistGameAPI
|
||||
//---------------------------------------------
|
||||
{
|
||||
public:
|
||||
apiTest(const char *, const unsigned, const unsigned);
|
||||
apiTest(const char *, const unsigned, const unsigned, const unsigned);
|
||||
virtual ~apiTest();
|
||||
|
||||
void OnConnectCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
void OnConnectRejectedCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
void OnDisconnectCSAssist(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
void OnNewTicketActivity(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const unsigned NewActivityFlag, const unsigned HasTickets);
|
||||
void OnRegisterCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
void OnUnRegisterCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
void OnGetIssueHierarchy(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML hierarchyBody, const unsigned modifyDate);
|
||||
void OnCreateTicket(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
void OnAppendTicketComment(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
void OnGetTicketByID(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicket *ticketBody);
|
||||
void OnGetTicketComments(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketComment *comments, const unsigned numberRead);
|
||||
void OnGetTicketByCharacter(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const unsigned NumberReturned, const unsigned TotalNumber, const CSAssistGameAPITicket *ticketBody);
|
||||
void OnTicketChange(const CSAssistGameAPITicketID ticketID, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character);
|
||||
void OnMarkTicketRead(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData);
|
||||
void OnCancelTicket(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket);
|
||||
void OnGetTicketCommentsCount(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPITicketID ticket, const unsigned count);
|
||||
void OnRequestGameLocation(const CSAssistGameAPITrack sourceTrack, const CSAssistGameAPIUID uid, const CSAssistUnicodeChar *character, const CSAssistGameAPIUID CSRUID);
|
||||
void OnGetDocumentList(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIDocumentHeader *docList, const unsigned numberRead);
|
||||
void OnGetDocument(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistUnicodeChar *documentBody);
|
||||
void OnGetTicketXMLBlock(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML XMLBody);
|
||||
void OnSearchKB(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPISearchResult *results, const unsigned numberRead);
|
||||
void OnGetKBArticle(const CSAssistGameAPITrack track, const CSAssistGameAPIResult result, const void *userData, const CSAssistGameAPIXML articleBody);
|
||||
void OnIssueHierarchyChanged(const CSAssistUnicodeChar *version, const CSAssistUnicodeChar *language);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// packdata.cpp
|
||||
//
|
||||
// Author: Graeme Ing ([email protected])
|
||||
// Module: CSAssist API
|
||||
//
|
||||
// copyright 2002 (c) Sony Online Entertainment Inc.
|
||||
//
|
||||
// decode/encode class data for sending over the wire
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "Base/Archive.h"
|
||||
#include "CSAssistgameapi.h"
|
||||
#include "CSAssistgameobjects.h"
|
||||
#include "Unicode/UnicodeUtils.h"
|
||||
#include "packdata.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
|
||||
using namespace Base;
|
||||
using namespace std;
|
||||
using namespace CSAssist;
|
||||
using namespace Plat_Unicode;
|
||||
|
||||
|
||||
//----------------------------------------------
|
||||
CSAssistUnicodeChar *get_c_str(Plat_Unicode::String s)
|
||||
// This replaces c_str() by allocating a new buffer, erasing it, and then
|
||||
// using the non-null terminated data() to copy the data into the buffer.
|
||||
//----------------------------------------------
|
||||
{
|
||||
unsigned length = s.size() + 1;
|
||||
CSAssistUnicodeChar *temp = new CSAssistUnicodeChar[length];
|
||||
memset(temp, 0, length * sizeof(CSAssistUnicodeChar));
|
||||
memcpy(temp, s.data(), (length - 1) * sizeof(CSAssistUnicodeChar));
|
||||
return temp;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
CSAssistUnicodeChar *copy_c_str(Plat_Unicode::String s, CSAssistUnicodeChar *dest)
|
||||
//----------------------------------------------
|
||||
{
|
||||
unsigned length = s.size() + 1;
|
||||
memset(dest, 0, length * sizeof(CSAssistUnicodeChar));
|
||||
memcpy(dest, s.data(), (length - 1) * sizeof(CSAssistUnicodeChar));
|
||||
return dest;
|
||||
}
|
||||
|
||||
namespace Base
|
||||
{
|
||||
//----------------------------------------------
|
||||
void put(Base::ByteStream & target, const CSAssistGameAPITicket & source)
|
||||
//----------------------------------------------
|
||||
{
|
||||
Plat_Unicode::String sgame = source.game;
|
||||
Plat_Unicode::String sserver = source.server;
|
||||
Plat_Unicode::String sdetails = source.details;
|
||||
Plat_Unicode::String slanguage = source.language;
|
||||
Plat_Unicode::String scharacter = source.character;
|
||||
Plat_Unicode::String slocation = source.location;
|
||||
|
||||
put(target, source.ticketID);
|
||||
put(target, source.uid);
|
||||
put(target, (unsigned)source.createDate);
|
||||
put(target, (unsigned)source.modifiedDate);
|
||||
put(target, sgame);
|
||||
put(target, sserver);
|
||||
put(target, scharacter);
|
||||
put(target, (unsigned)source.status);
|
||||
put(target, (unsigned)source.bugstatus);
|
||||
for (short i=0; i < CSASSIST_NUM_CATEGORIES; i++)
|
||||
put(target, source.category[i]);
|
||||
put(target, sdetails);
|
||||
put(target, slanguage);
|
||||
put(target, source.isRead);
|
||||
put(target, slocation);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void get(ByteStream::ReadIterator & source, CSAssistGameAPITicket & target)
|
||||
//----------------------------------------------
|
||||
{
|
||||
Plat_Unicode::String sgame;
|
||||
Plat_Unicode::String sserver;
|
||||
Plat_Unicode::String scharacter;
|
||||
Plat_Unicode::String sdetails;
|
||||
Plat_Unicode::String slanguage;
|
||||
Plat_Unicode::String slocation;
|
||||
unsigned create, modified, gstatus, bstatus;
|
||||
|
||||
get(source, target.ticketID);
|
||||
get(source, target.uid);
|
||||
get(source, create);
|
||||
get(source, modified);
|
||||
get(source, sgame);
|
||||
get(source, sserver);
|
||||
get(source, scharacter);
|
||||
get(source, gstatus);
|
||||
get(source, bstatus);
|
||||
for (short i=0; i < CSASSIST_NUM_CATEGORIES; i++)
|
||||
get(source, target.category[i]);
|
||||
get(source, sdetails);
|
||||
get(source, slanguage);
|
||||
get(source, target.isRead);
|
||||
get(source, slocation);
|
||||
|
||||
copy_c_str(sgame, target.game);
|
||||
copy_c_str(sserver, target.server);
|
||||
copy_c_str(scharacter, target.character);
|
||||
copy_c_str(sdetails, target.details);
|
||||
copy_c_str(slanguage, target.language);
|
||||
copy_c_str(slocation, target.location);
|
||||
|
||||
target.createDate = (time_t)create;
|
||||
target.modifiedDate = (time_t)modified;
|
||||
target.status = (CSAssistTicketStatus)gstatus;
|
||||
target.bugstatus = (CSAssistBugStatus)bstatus;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void get(ByteStream::ReadIterator & source, CSAssistGameAPITicket * target)
|
||||
//----------------------------------------------
|
||||
{
|
||||
CSAssistGameAPITicket &t = *target;
|
||||
get(source, t);
|
||||
}
|
||||
} // namespace Base
|
||||
|
||||
//----------------------------------------------
|
||||
void decodeTicketComment(ByteStream::ReadIterator & msg,CSAssistGameAPITicketComment *dest)
|
||||
//----------------------------------------------
|
||||
{
|
||||
Plat_Unicode::String comment, name;
|
||||
unsigned modified, type;
|
||||
|
||||
get(msg, dest->ticketID);
|
||||
get(msg, dest->commentID);
|
||||
get(msg, dest->uid);
|
||||
get(msg, modified);
|
||||
get(msg, type);
|
||||
get(msg, comment);
|
||||
get(msg, name);
|
||||
|
||||
copy_c_str(comment, dest->comment);
|
||||
copy_c_str(name, dest->name);
|
||||
dest->modifiedDate = (time_t)modified;
|
||||
dest->type = (CSAssistGameAPICommentType)type;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void decodeDocumentHeader(ByteStream::ReadIterator & msg,CSAssistGameAPIDocumentHeader *dest)
|
||||
//----------------------------------------------
|
||||
{
|
||||
Plat_Unicode::String game, language, title, version;
|
||||
unsigned modified;
|
||||
|
||||
get(msg, dest->id);
|
||||
get(msg, game);
|
||||
get(msg, language);
|
||||
get(msg, title);
|
||||
get(msg, version);
|
||||
get(msg, modified);
|
||||
|
||||
copy_c_str(game, dest->game);
|
||||
copy_c_str(language, dest->language);
|
||||
copy_c_str(title, dest->title);
|
||||
copy_c_str(version, dest->version);
|
||||
dest->modifiedDate = (time_t)modified;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void decodeSearchResult(ByteStream::ReadIterator & msg,CSAssistGameAPISearchResult *dest)
|
||||
//----------------------------------------------
|
||||
{
|
||||
Plat_Unicode::String atitle, id;
|
||||
|
||||
get(msg, id);
|
||||
get(msg, dest->matchPercent);
|
||||
get(msg, atitle);
|
||||
|
||||
copy_c_str(id, dest->idstring);
|
||||
copy_c_str(atitle, dest->title);
|
||||
}
|
||||
|
||||
} // namespace CSAssist
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
#ifndef PACKDATA_H
|
||||
#define PACKDATA_H
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// packdata.h
|
||||
//
|
||||
// Author: Graeme Ing ([email protected])
|
||||
// Module: CSAssist API
|
||||
//
|
||||
// copyright 2002 (c) Sony Online Entertainment Inc.
|
||||
//
|
||||
// encoding/decoding API-user objects for transmission over the wire
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include <Base/Archive.h>
|
||||
#include "CSAssistgameapi.h"
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
extern void decodeTicketComment(Base::ByteStream::ReadIterator & msg,CSAssistGameAPITicketComment *dest);
|
||||
extern void decodeDocumentHeader(Base::ByteStream::ReadIterator & msg,CSAssistGameAPIDocumentHeader *dest);
|
||||
extern void decodeSearchResult(Base::ByteStream::ReadIterator & msg,CSAssistGameAPISearchResult *dest);
|
||||
|
||||
|
||||
namespace Base
|
||||
{
|
||||
//using namespace CSAssist;
|
||||
|
||||
void put(Base::ByteStream & target, const CSAssistGameAPITicket & source);
|
||||
void get(ByteStream::ReadIterator & source, CSAssistGameAPITicket & target);
|
||||
void get(ByteStream::ReadIterator & source, CSAssistGameAPITicket * target);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
RELEASE NOTES - CSASSIST GAME API
|
||||
------------- -----------------
|
||||
06-22-04 - v2.0.1
|
||||
* Changed API_VERSION to 201 from 2.
|
||||
* Added UserID parameter to GetKBArticle and SearchArticle.
|
||||
* Added HierarchyChangeType to OnIssueHierarchyChange notification.
|
||||
|
||||
03-23-04 - V2.00
|
||||
* Completely Reworked connection mechanism. Added host failover functionality.
|
||||
* Added CSASSIST_RESULT_SERVER_DISCONNECT result code to indicate connection loss to server.
|
||||
* Fixed broken character re-registration upon auto-reconnect to backend.
|
||||
* Added articleTitle to GetKBArticle() request.
|
||||
* The old API constructor should be replaced with the new one in client code.
|
||||
|
||||
12-05-03 - RC2
|
||||
* Added the throttling from the main line.
|
||||
* Added the CSASSIST_APIFLAG_NO_REDIRECT option to connect directly to CSAssist avoiding the RedirectServer.
|
||||
* Patched a leak and crash bug due to the connectCSAssistRequest().
|
||||
|
||||
11-24-2003 - RC1
|
||||
* New API release based on the TCP scalable backend branch.
|
||||
* Changed functionality of connectCSAssist: Now the API will try to contact an IP Load Balancing
|
||||
server (RedirecServer) to get the IP of a valid CSAssist server to connect to. This is
|
||||
all done transparently inside the connectCSAssist() request. The api constructor should now use
|
||||
the host and port of the RedirectServer, as all connection requests will expect this one hop
|
||||
handshake. Re-connects (after a disconnect) will also first connect to the RedirectServer and connect to an appropriate CSAssist backend.
|
||||
* All client/server connections use the Platform utils TCPLibrary.
|
||||
* requestNewTicketActivity() will now ignore all "closed" tickets - this became an issue due to
|
||||
the new server architecture using db calls to fetch tickets, not loading them into memory.
|
||||
|
||||
*** This release does not contain changes made for the throttling. Need to integrate/merge those changes from the main line udp-only code base.
|
||||
|
||||
10-17-2003
|
||||
* In 10-15 version, during a reconnect, all the cached "register character" requests were placed in the
|
||||
output buffer en masse, which meant that any new requests coming through the API had to wait until
|
||||
all the registers were sent, which might take a minute or more. This could result in those new
|
||||
requests hitting timeouts.
|
||||
|
||||
-----------------
|
||||
05-28-2003
|
||||
* m_currTrack(0) now initialised as m_currTrack(1). This allows clients to distinguish
|
||||
between the connection reply (now on track 1), and any server-initiated broadcasts (track=0)
|
||||
(Internals, no need to worry about this as a user)
|
||||
* requestNewTicketActivity() and requestGetTicketByCharacter() will now ignore all tickets that are "bug" tickets.
|
||||
You no longer need to filter out bug-tickets at the application end. You will never be sent a bug-ticket unless
|
||||
you request it by ID.
|
||||
|
||||
|
||||
|
||||
04-04-2003
|
||||
* Versioning code: To ensure that old API's do not connect to new servers, or incompatible API's and servers
|
||||
do not talk to each other, a transparent versioning layer has been added. The client will now receive one of
|
||||
two callbacks: OnConnectCSAssist( ) will be received when connection is successful.
|
||||
OnConnectRejectedCSAssist( ) will be received if the connection was NOT successful. In the later case, the
|
||||
result code may give some indication of why the connect was rejected, e.g. code 21 = CSASSIST_RESULT_BAD_VERSION.
|
||||
A result code is still passed back to OnConnectCSAssist( ) for backwards compatibility, although it will always
|
||||
be CSASSIST_RESULT_SUCCESS (0).
|
||||
* Primus Knowledge Base searches will now only return results for YOUR game and not all games.
|
||||
|
||||
3-17-2003
|
||||
* Unicode no longer exposed through header files. This should allow EQOA to link with the library without problems.
|
||||
|
||||
3-10-2003
|
||||
* Can not create a ticket without setting the game, server, character and details fields,
|
||||
using the appropriate setXXX() calls.
|
||||
|
||||
3-7-2003
|
||||
* 3-7 Release. Minor efficiency improvements since 1-31 release.
|
||||
|
||||
1-31-2003
|
||||
* Fixed namespace and include file issue where a Unicode header file was accidently extended through the API
|
||||
to the client
|
||||
* Distribution is now monolithic, i.e. all Platform libraries (Base, UdpLibrary, Unicode) are now moved within
|
||||
the CSAssist namespace to prevent clashes with other versions of these libraries.
|
||||
|
||||
1-9-2003
|
||||
* Fully internationalised. Note that this has caused almost every string parameter to every API call
|
||||
to change from a char * to a unicode char pointer.
|
||||
* EstablishConnection NULL bug fixed
|
||||
* Ticket object modified to add in Bug Reporting fields for Q/A. Bug reports are treated like tickets.
|
||||
As well as ticket status there is now a bug status field. Set this if the ticket is a bug report.
|
||||
Two more subcategories have been requested, making a total of 4 now instead of 2. The previous
|
||||
category and subcategory have been consolidated into a new array of categories, currently 4.
|
||||
Finally, a location string has been added. Fill this in with the zone/area of the player and his
|
||||
X,Y,Z coordinates.
|
||||
For further details of Bug Reporting, see the API documentation and CSAssistgameapi.h and
|
||||
CSAssistgameobjects.h
|
||||
* The monolithic constructor for creating a basic ticket has been replaced with a series of setXX()
|
||||
member functions. See CSAssistgameobjects.h for details. This was done for reasons of clarity
|
||||
(no huge list of parameters), future expandability and so that individual fields can be validated.
|
||||
* All dates returned now have full date and time stamps, they were previously just dates (DD-MON-YY).
|
||||
|
||||
11-27-2002
|
||||
* alternative constructor for CSAssistGameAPITicket for a convenient way for the game application
|
||||
to create a ticket object for use in requestCreateTicket(). Constructor takes only that
|
||||
info required to create a ticket.
|
||||
* Application will no longer receive OnConnect() callbacks whenever the API makes an
|
||||
automatic reconnect to the CSAssist server. The application will only receive callbacks
|
||||
in response to its own, application-initiated, connect requests.
|
||||
* In the event of a loss of connection to the CSAssist server, upon reconnection, the API
|
||||
will automatically submit register requests for all characters previously registered.
|
||||
This obviates the need for the application/game to issue those register requests.
|
||||
* The following calls are now functional:
|
||||
requestGetKBArticle
|
||||
requestSearchKB
|
||||
OnIssueHierarchyChanged
|
||||
* new call: getErrorString(result) is a local blocking call that returns a matching error
|
||||
string for a result code passed in. This is for debugging/logging only, not for presenting
|
||||
to the player.
|
||||
|
||||
11-13-2002
|
||||
* API constructor altered to move the default parameters into the header file.
|
||||
This removes the need for the application to include the default/optional
|
||||
parameters even if they will not be used
|
||||
* All parameters in the API constructor made const
|
||||
* The following calls are now functional:
|
||||
requestGetDocumentList
|
||||
requestGetDocument
|
||||
requestGetTicketXMLBlock
|
||||
* KNOWN BUG: requestGetTicketXMLBlock has a problem with the DB stored procedure.
|
||||
It is likely to time out and not return data. You *will* receive an error code,
|
||||
just note that this call is currently unreliable.
|
||||
|
||||
11-08-2002
|
||||
* As soon as connection is lost with the server, all requests that are queued
|
||||
at the client API side will be immediately dumped back to the calling
|
||||
application with a code of CSASSIST_RESULT_TIMEOUT.
|
||||
This is default behavior, to change this see the description of
|
||||
CSASSIST_APIFLAG_ASSUME_RECONNECT in CSAssistgameapi.h, and the API docs.
|
||||
* If a request is made and the API is in a NON-connected state with the server,
|
||||
the request will be immediately returned with a code of CSASSIST_RESULT_TIMEOUT.
|
||||
It will NOT be queued as happened previously. Thus the application will
|
||||
not have to wait for the timeout (60-90 secs) to know that the server
|
||||
is non-responsive.
|
||||
* Extra 2 optional parameters to the constructor of the API class:
|
||||
Timeout, and Flags. See API doc for details.
|
||||
Your new overloaded constructor will look something like:
|
||||
|
||||
apiTest::apiTest(char *host, unsigned port, unsigned timeout = 0, unsigned flags = 0)
|
||||
: CSAssistGameAPI(host, port, timeout, flags)
|
||||
|
||||
* Default timeout reduced from 90 to 60 seconds.
|
||||
* Parameters to constructor of the API class changed from ints to unsigned
|
||||
for consistency.
|
||||
* Additional parameter added to requestGetIssueHierarchy():
|
||||
"Version String", which is the identifier for the Hierarchy you require.
|
||||
This is typically a server name but more accurately a server type, e.g.
|
||||
Dev, Test, Live, PvP, Japan, etc.
|
||||
|
||||
11-5-2002
|
||||
* The following calls are now functional:
|
||||
requestGetIssueHierarchy
|
||||
OnRequestGameLocation
|
||||
replyGameLocation
|
||||
|
||||
10-28-2002
|
||||
* IPAddress parameter removed from connect call
|
||||
* Character Name added to parameter list for requestAppendTicketComment
|
||||
|
||||
10-12-2002
|
||||
* Note that the directory structure has changed from previous version.
|
||||
This new structure mirrors all future releases by the Server Engineering team.
|
||||
* The following calls are now functional:
|
||||
requestGetTicketCommentsCount
|
||||
* void *userData added to all calls
|
||||
|
||||
10-02-2002
|
||||
* Deleted requestGetErrorText function as no longer useful
|
||||
* Expanded CSAssistGameAPITicketComment object (see CSAssistGameobjects.h)
|
||||
* Parameters changed for requestAppendTicketComment (see CSAssistgameapi.h)
|
||||
* The following calls are now functional:
|
||||
requestAppendTicketComment
|
||||
requestGetTicketComments
|
||||
requestMarkTicketRead
|
||||
requestCancelTicket
|
||||
|
||||
9-25-2002
|
||||
* Parameters changed for OnGetTicketByID()
|
||||
* see CSAssistcsrapi.h for list of new parameters
|
||||
* The following calls are operational (see notes below):
|
||||
connectCSAssist
|
||||
requestNewTicketActivity
|
||||
requestRegisterCharacter
|
||||
disconnectCSAssist
|
||||
requestUnRegisterCharacter
|
||||
requestCreateTicket
|
||||
requestGetTicketByCharacter
|
||||
requstGetTicketByID
|
||||
OnTicketChange
|
||||
requestGetErrorText
|
||||
* The following calls will return dummy data
|
||||
requestGetIssueHierarchy
|
||||
requestAppendTicketComment
|
||||
requestGetTicketComments
|
||||
* Note that tickets are only RAM-persistent, not database-persistent.
|
||||
i.e. Tickets will remain alive as long as the test CSAssist server is up
|
||||
You may want to write a small app to go and generate a batch of test
|
||||
tickets if you perceive that the Test CSAssist server has been rebooted.
|
||||
|
||||
9-20-2002
|
||||
* Parameters changed for connectCSAssist
|
||||
* Parameters changed for requestCreateTicket
|
||||
* see CSAssistgameapi.h for list of new parameters
|
||||
* linuxtest directory replaced by csassisttest
|
||||
This has project files to build under WIN32, and
|
||||
make file to build under linux. (use make -f linux.mak)
|
||||
|
||||
+498
@@ -0,0 +1,498 @@
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// request.cpp
|
||||
//
|
||||
// Author: Graeme Ing ([email protected])
|
||||
// Module: CSAssist API
|
||||
//
|
||||
// copyright 2002 (c) Sony Online Entertainment Inc.
|
||||
//
|
||||
// Request functions, prepare data to send to servers
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "request.h"
|
||||
#include "packdata.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
|
||||
using namespace Base;
|
||||
using namespace std;
|
||||
using namespace Plat_Unicode;
|
||||
|
||||
const static unsigned CSASSIST_VERSION_MAGIC = (4 + (256 * 3) + (65536 * 2) + (65536 * 256 * 1));
|
||||
const static unsigned API_VERSION = 201;
|
||||
|
||||
//------------------------------------------------
|
||||
Request::Request(short type, unsigned track) :
|
||||
mType(type), mTrack(track), timeout(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void Request::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 2;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
//
|
||||
// Add new Request objects for each API call here
|
||||
// **** ADD CODE HERE ****
|
||||
//
|
||||
//----------------------------------------------
|
||||
|
||||
//----------------------------------------------
|
||||
RConnectCSAssist::RConnectCSAssist(unsigned track, Plat_Unicode::String GameName, const Plat_Unicode::String ServerName)
|
||||
: Request(CSASSIST_CALL_CONNECT, track),
|
||||
mGameName(GameName),
|
||||
mServerName(ServerName)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RConnectCSAssist::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 4;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, (unsigned)CSASSIST_VERSION_MAGIC);
|
||||
put(msg, (unsigned)API_VERSION);
|
||||
put(msg, mGameName);
|
||||
put(msg, mServerName);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RDisconnectCSAssist::RDisconnectCSAssist(unsigned track)
|
||||
: Request(CSASSIST_CALL_DISCONNECT, track)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RNewTicketActivity::RNewTicketActivity(unsigned track, const unsigned uid, const Plat_Unicode::String character)
|
||||
: Request(CSASSIST_CALL_NEWTICKETACTIVITY, track),
|
||||
mUID(uid),
|
||||
mCharacter(character)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RNewTicketActivity::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 4;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mUID);
|
||||
put(msg, mCharacter);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RRegisterCharacter::RRegisterCharacter(unsigned track, const unsigned uid, const Plat_Unicode::String character, const unsigned avaconID)
|
||||
: Request(CSASSIST_CALL_REGISTERCHARACTER, track),
|
||||
mUID(uid),
|
||||
mCharacter(character),
|
||||
mAvaconID(avaconID)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RRegisterCharacter::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 5;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mUID);
|
||||
put(msg, mCharacter);
|
||||
put(msg, mAvaconID);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RUnRegisterCharacter::RUnRegisterCharacter(unsigned track, const unsigned uid, const Plat_Unicode::String character)
|
||||
: Request(CSASSIST_CALL_UNREGISTERCHARACTER, track),
|
||||
mUID(uid),
|
||||
mCharacter(character)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RUnRegisterCharacter::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 4;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mUID);
|
||||
put(msg, mCharacter);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RGetIssueHierarchy::RGetIssueHierarchy(unsigned track, const Plat_Unicode::String version, const Plat_Unicode::String language)
|
||||
: Request(CSASSIST_CALL_GETISSUEHIERARCHY, track),
|
||||
mVersion(version),
|
||||
mLanguage(language)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RGetIssueHierarchy::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 4;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mVersion);
|
||||
put(msg, mLanguage);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RCreateTicket::RCreateTicket(unsigned track, const CSAssistGameAPITicket *ticketBody, const Plat_Unicode::String XMLBody, const unsigned uid)
|
||||
: Request(CSASSIST_CALL_CREATETICKET, track),
|
||||
mXMLBody(XMLBody),
|
||||
mUID(uid)
|
||||
//----------------------------------------------
|
||||
{
|
||||
mTicketStruct = *ticketBody;
|
||||
}
|
||||
//----------------------------------------------
|
||||
void RCreateTicket::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 5;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mTicketStruct);
|
||||
put(msg, mXMLBody);
|
||||
put(msg, mUID);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RAppendComment::RAppendComment(unsigned track, const unsigned ticket, const unsigned uid, const Plat_Unicode::String character, const Plat_Unicode::String comment)
|
||||
: Request(CSASSIST_CALL_APPENDCOMMENT, track),
|
||||
mTicketID(ticket),
|
||||
mUID(uid),
|
||||
mComment(comment),
|
||||
mCharacter(character)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RAppendComment::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 6;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mTicketID);
|
||||
put(msg, mUID);
|
||||
put(msg, mComment);
|
||||
put(msg, mCharacter);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RGetTicketByID::RGetTicketByID(unsigned track, const unsigned ticket, const unsigned MarkAsRead)
|
||||
: Request(CSASSIST_CALL_GETTICKETBYID, track),
|
||||
mTicketID(ticket),
|
||||
mMarkAsRead(MarkAsRead)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RGetTicketByID::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 4;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mTicketID);
|
||||
put(msg, mMarkAsRead);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RGetTicketComments::RGetTicketComments(unsigned track, const unsigned ticket, const unsigned start, const unsigned count, const unsigned offset)
|
||||
: Request(CSASSIST_CALL_GETTICKETCOMMENTS, track),
|
||||
mTicketID(ticket),
|
||||
mStart(start),
|
||||
mCount(count),
|
||||
mOffset(offset)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RGetTicketComments::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 6;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mTicketID);
|
||||
put(msg, mStart);
|
||||
put(msg, mCount);
|
||||
put(msg, mOffset);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RGetTicketByCharacter::RGetTicketByCharacter(unsigned track, const unsigned uid, const Plat_Unicode::String character, const unsigned Start, const unsigned Count, const unsigned MarkAsRead)
|
||||
: Request(CSASSIST_CALL_GETTICKET, track),
|
||||
mUID(uid),
|
||||
mCharacter(character),
|
||||
mStart(Start),
|
||||
mCount(Count),
|
||||
mMarkAsRead(MarkAsRead)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RGetTicketByCharacter::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 7;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mUID);
|
||||
put(msg, mCharacter);
|
||||
put(msg, mStart);
|
||||
put(msg, mCount);
|
||||
put(msg, mMarkAsRead);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RMarkTicketRead::RMarkTicketRead(unsigned track, const unsigned ticket)
|
||||
: Request(CSASSIST_CALL_MARKREAD, track),
|
||||
mTicketID(ticket)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RMarkTicketRead::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 3;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mTicketID);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RCancelTicket::RCancelTicket(unsigned track, const unsigned ticket, const unsigned uid, const Plat_Unicode::String comment)
|
||||
: Request(CSASSIST_CALL_CANCELTICKET, track),
|
||||
mTicketID(ticket),
|
||||
mUID(uid),
|
||||
mComment(comment)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RCancelTicket::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 5;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mTicketID);
|
||||
put(msg, mUID);
|
||||
put(msg, mComment);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RCommentCount::RCommentCount(unsigned track, const unsigned ticket)
|
||||
: Request(CSASSIST_CALL_COMMENTCOUNT, track),
|
||||
mTicketID(ticket)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RCommentCount::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 3;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mTicketID);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RReplyGameLocation::RReplyGameLocation(unsigned track, const unsigned sourceTrack, const unsigned uid, const Plat_Unicode::String character, const unsigned csruid, const Plat_Unicode::String location)
|
||||
: Request(CSASSIST_CALL_REPLYLOCATION, track),
|
||||
mSourceTrack(sourceTrack),
|
||||
mUID(uid),
|
||||
mCharacter(character),
|
||||
mCSRUID(csruid),
|
||||
mLocationString(location)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RReplyGameLocation::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 7;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mSourceTrack);
|
||||
put(msg, mUID);
|
||||
put(msg, mCharacter);
|
||||
put(msg, mCSRUID);
|
||||
put(msg, mLocationString);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RGetDocumentList::RGetDocumentList(unsigned track, Plat_Unicode::String version, Plat_Unicode::String language)
|
||||
: Request(CSASSIST_CALL_GETDOCUMENTLIST, track), mVersion(version), mLanguage(language)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RGetDocumentList::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 4;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mVersion);
|
||||
put(msg, mLanguage);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RGetDocument::RGetDocument(unsigned track, const unsigned id)
|
||||
: Request(CSASSIST_CALL_GETDOCUMENT, track), mID(id)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RGetDocument::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 3;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mID);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RGetTicketXMLBlock::RGetTicketXMLBlock(unsigned track, const unsigned id)
|
||||
: Request(CSASSIST_CALL_GETTICKETXMLBLOCK, track),
|
||||
mID(id)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RGetTicketXMLBlock::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 3;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mID);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RGetKBArticle::RGetKBArticle(unsigned track, const Plat_Unicode::String id, const Plat_Unicode::String language, const unsigned uid)
|
||||
: Request(CSASSIST_CALL_GETKBARTICLE, track),
|
||||
mID(id),
|
||||
mLanguage(language),
|
||||
mUID(uid)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RGetKBArticle::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 5;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mID);
|
||||
put(msg, mLanguage);
|
||||
put(msg, mUID);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RSearchKB::RSearchKB(unsigned track, const Plat_Unicode::String searchstring, const Plat_Unicode::String language, const unsigned uid)
|
||||
: Request(CSASSIST_CALL_SEARCHKB, track),
|
||||
mSearchString(searchstring),
|
||||
mLanguage(language),
|
||||
mUID(uid)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RSearchKB::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 5;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mSearchString);
|
||||
put(msg, mLanguage);
|
||||
put(msg, mUID);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
RConnectLB::RConnectLB(unsigned track, const std::string connectString)
|
||||
: Request(CSASSIST_CALL_CONNECTLB, track),
|
||||
mConnectString(connectString)
|
||||
//----------------------------------------------
|
||||
{
|
||||
setTimeout(time(0) + 5);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RConnectLB::pack(ByteStream &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
short num_args = 3;
|
||||
put(msg, num_args);
|
||||
put(msg, mType);
|
||||
put(msg, mTrack);
|
||||
put(msg, mConnectString);
|
||||
}
|
||||
|
||||
} // namespace CSAssist
|
||||
+355
@@ -0,0 +1,355 @@
|
||||
#ifndef REQUEST_H
|
||||
#define REQUEST_H
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// request.h
|
||||
//
|
||||
// Author: Graeme Ing ([email protected])
|
||||
// Module: CSAssist API
|
||||
//
|
||||
// copyright 2002 (c) Sony Online Entertainment Inc.
|
||||
//
|
||||
// Class definitions for all user-initiated requests
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "Base/Archive.h"
|
||||
#include "Unicode/UnicodeUtils.h"
|
||||
#include "CSAssistgameapi.h"
|
||||
#include "CSAssistgameobjects.h"
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
|
||||
// ----- Add all new messages to this list! -----
|
||||
|
||||
// **** ADD CODE HERE ****
|
||||
enum SubCMessage
|
||||
{
|
||||
CSASSIST_CALL_CONNECT, // 0
|
||||
CSASSIST_CALL_DISCONNECT, // 1
|
||||
CSASSIST_CALL_NEWTICKETACTIVITY, // 2
|
||||
CSASSIST_CALL_REGISTERCHARACTER, // 3
|
||||
CSASSIST_CALL_UNREGISTERCHARACTER, // 4
|
||||
CSASSIST_CALL_ERRORTEXT, // 5
|
||||
CSASSIST_CALL_GETISSUEHIERARCHY, // 6
|
||||
CSASSIST_CALL_CREATETICKET, // 7
|
||||
CSASSIST_CALL_APPENDCOMMENT, // 8
|
||||
CSASSIST_CALL_GETTICKETBYID, // 9
|
||||
CSASSIST_CALL_GETTICKETCOMMENTS, // 10
|
||||
CSASSIST_CALL_GETTICKET, // 11
|
||||
CSASSIST_CALL_MARKREAD, // 12
|
||||
CSASSIST_CALL_CANCELTICKET, // 13
|
||||
CSASSIST_CALL_COMMENTCOUNT, // 14
|
||||
CSASSIST_CALL_REPLYLOCATION, // 15
|
||||
CSASSIST_CALL_GETDOCUMENTLIST, // 16
|
||||
CSASSIST_CALL_GETDOCUMENT, // 17
|
||||
CSASSIST_CALL_GETTICKETXMLBLOCK, // 18
|
||||
CSASSIST_CALL_GETKBARTICLE, // 19
|
||||
CSASSIST_CALL_SEARCHKB, // 20
|
||||
// insert API message types above this line
|
||||
CSASSIST_CALL_REQUEST_MAX, // 21 - always needs to be last of API messages
|
||||
|
||||
CSASSIST_CALL_CONNECTLB = 2001, // only used internally to connect to connection-load balancing server
|
||||
|
||||
CSASSIST_CALL_START_SERVER_MESSAGES=10000,
|
||||
// insert server-initiated message types below this line
|
||||
CSASSIST_SERVER_TICKETCHANGE, // 10001
|
||||
CSASSIST_SERVER_BROADCASTTICKET, // 10002
|
||||
CSASSIST_SERVER_BROADCASTCOMMENT, // 10003
|
||||
CSASSIST_SERVER_REQUESTLOCATION, // 10004
|
||||
CSASSIST_SERVER_REPORTLOCATION, // 10005
|
||||
CSASSIST_SERVER_HIERARCHYCHANGE // 10006
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
Request(short type, unsigned track);
|
||||
virtual ~Request() { }
|
||||
unsigned getType() { return (unsigned)mType; }
|
||||
unsigned getTrack() { return mTrack; }
|
||||
void setTimeout(unsigned t) { timeout = t; }
|
||||
unsigned getTimeout() { return timeout; }
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
|
||||
protected:
|
||||
short mType;
|
||||
unsigned mTrack;
|
||||
|
||||
private:
|
||||
unsigned timeout;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
//
|
||||
// Add new Request objects for each API call here
|
||||
//
|
||||
// **** ADD CODE HERE ****
|
||||
//----------------------------------------------
|
||||
|
||||
//----------------------------------------------
|
||||
class RConnectCSAssist : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RConnectCSAssist(unsigned track, const Plat_Unicode::String GameName, const Plat_Unicode::String ServerName);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
Plat_Unicode::String mGameName;
|
||||
Plat_Unicode::String mServerName;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RDisconnectCSAssist : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RDisconnectCSAssist(unsigned track);
|
||||
private:
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RNewTicketActivity : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RNewTicketActivity(unsigned track, const unsigned uid, const Plat_Unicode::String character);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mUID;
|
||||
Plat_Unicode::String mCharacter;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RRegisterCharacter : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RRegisterCharacter(unsigned track, const unsigned uid, const Plat_Unicode::String character, const unsigned avaconID);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mUID;
|
||||
Plat_Unicode::String mCharacter;
|
||||
unsigned mAvaconID;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RUnRegisterCharacter : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RUnRegisterCharacter(unsigned track, const unsigned uid, const Plat_Unicode::String character);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mUID;
|
||||
Plat_Unicode::String mCharacter;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RGetIssueHierarchy : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RGetIssueHierarchy(unsigned track, const Plat_Unicode::String version, const Plat_Unicode::String language);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
Plat_Unicode::String mVersion;
|
||||
Plat_Unicode::String mLanguage;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RCreateTicket : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RCreateTicket(unsigned track, const CSAssistGameAPITicket *ticketBody, const Plat_Unicode::String XMLBody, const unsigned uid);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
CSAssistGameAPITicket mTicketStruct;
|
||||
Plat_Unicode::String mXMLBody;
|
||||
unsigned mUID;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RAppendComment : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RAppendComment(unsigned track, const unsigned ticket, const unsigned uid, const Plat_Unicode::String character, const Plat_Unicode::String comment);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mTicketID;
|
||||
unsigned mUID;
|
||||
Plat_Unicode::String mComment;
|
||||
Plat_Unicode::String mCharacter;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RGetTicketByID : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RGetTicketByID(unsigned track, const unsigned ticket, const unsigned MarkAsRead);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mTicketID;
|
||||
unsigned mMarkAsRead;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RGetTicketComments : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RGetTicketComments(unsigned track, const unsigned ticket, const unsigned start, const unsigned count, const unsigned offset);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mTicketID;
|
||||
unsigned mStart;
|
||||
unsigned mCount;
|
||||
unsigned mOffset;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RGetTicketByCharacter : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RGetTicketByCharacter(unsigned track, const unsigned uid, const Plat_Unicode::String character, const unsigned Start, const unsigned Count, const unsigned MarkAsRead);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mUID;
|
||||
Plat_Unicode::String mCharacter;
|
||||
unsigned mStart;
|
||||
unsigned mCount;
|
||||
unsigned mMarkAsRead;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RMarkTicketRead : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RMarkTicketRead(unsigned track, const unsigned ticket);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mTicketID;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RCancelTicket : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RCancelTicket(unsigned track, const unsigned ticket, const unsigned uid, const Plat_Unicode::String comment);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mTicketID;
|
||||
unsigned mUID;
|
||||
Plat_Unicode::String mComment;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RCommentCount : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RCommentCount(unsigned track, const unsigned ticket);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mTicketID;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RReplyGameLocation : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RReplyGameLocation(unsigned track, const unsigned sourceTrack, const unsigned uid, const Plat_Unicode::String character, const unsigned csruid, const Plat_Unicode::String locationString);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mSourceTrack;
|
||||
unsigned mUID;
|
||||
Plat_Unicode::String mCharacter;
|
||||
unsigned mCSRUID;
|
||||
Plat_Unicode::String mLocationString;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RGetDocumentList : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RGetDocumentList(unsigned track, Plat_Unicode::String version, Plat_Unicode::String language);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
Plat_Unicode::String mVersion;
|
||||
Plat_Unicode::String mLanguage;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RGetDocument : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RGetDocument(unsigned track, const unsigned id);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mID;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RGetTicketXMLBlock : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RGetTicketXMLBlock(unsigned track, const unsigned id);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
unsigned mID;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RGetKBArticle : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RGetKBArticle(unsigned track, const Plat_Unicode::String id, const Plat_Unicode::String language, const unsigned uid);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
Plat_Unicode::String mID;
|
||||
Plat_Unicode::String mLanguage;
|
||||
unsigned mUID;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RSearchKB : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RSearchKB(unsigned track, const Plat_Unicode::String searchstring, const Plat_Unicode::String language, const unsigned uid);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
Plat_Unicode::String mSearchString;
|
||||
Plat_Unicode::String mLanguage;
|
||||
unsigned mUID;
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
class RConnectLB : public Request
|
||||
//----------------------------------------------
|
||||
{
|
||||
public:
|
||||
RConnectLB(unsigned track, const std::string connectString);
|
||||
virtual void pack(Base::ByteStream &msg);
|
||||
private:
|
||||
std::string mConnectString;
|
||||
};
|
||||
|
||||
} // namespace CSAssist
|
||||
|
||||
#endif
|
||||
+582
@@ -0,0 +1,582 @@
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// CSAssistgameapi.cpp
|
||||
//
|
||||
// Author: Graeme Ing ([email protected])
|
||||
// Module: CSAssist API
|
||||
//
|
||||
// copyright 2002 (c) Sony Online Entertainment Inc.
|
||||
//
|
||||
// Response functions, process data from the servers
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
#pragma warning (disable: 4786)
|
||||
|
||||
#include "response.h"
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
|
||||
using namespace Base;
|
||||
using namespace std;
|
||||
|
||||
extern CSAssistUnicodeChar *get_c_str(Plat_Unicode::String s);
|
||||
extern CSAssistUnicodeChar *copy_c_str(Plat_Unicode::String s, CSAssistUnicodeChar *dest);
|
||||
|
||||
|
||||
//----------------------------------------------
|
||||
Response::Response(unsigned type, unsigned track, const void *userData)
|
||||
: mType(type),
|
||||
mTrack(track),
|
||||
mResult(CSASSIST_RESULT_TIMEOUT)
|
||||
//----------------------------------------------
|
||||
{
|
||||
muserData = (void *)userData;
|
||||
//fprintf(stderr,"Response(%p) type(%d),track(%d)\n", this, mType,mTrack);
|
||||
}
|
||||
|
||||
Response::~Response()
|
||||
{
|
||||
//fprintf(stderr,"~Response(%p) type(%d),track(%d)\n", this,mType,mTrack);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void Response::decode(ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------
|
||||
//
|
||||
// Add new Response objects for each API call here
|
||||
//
|
||||
// **** ADD CODE HERE ****
|
||||
//----------------------------------------------
|
||||
|
||||
//----------------------------------------------
|
||||
ResConnectCSAssist::ResConnectCSAssist(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_CONNECT, track, userData)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResDisconnectCSAssist::ResDisconnectCSAssist(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_DISCONNECT, track, userData)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResNewTicketActivity::ResNewTicketActivity(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_NEWTICKETACTIVITY, track, userData), mNewActivityFlag(0), mHasTickets(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
ResNewTicketActivity::~ResNewTicketActivity()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResNewTicketActivity::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg, mNewActivityFlag);
|
||||
get(msg, mHasTickets);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResRegisterCharacter::ResRegisterCharacter(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_REGISTERCHARACTER, track, userData)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResUnRegisterCharacter::ResUnRegisterCharacter(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_UNREGISTERCHARACTER, track, userData)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetIssueHierarchy::ResGetIssueHierarchy(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_GETISSUEHIERARCHY, track, userData), mModifyDate(0), rawStringPtr(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetIssueHierarchy::~ResGetIssueHierarchy()
|
||||
//----------------------------------------------
|
||||
{
|
||||
if (rawStringPtr)
|
||||
delete [] rawStringPtr;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResGetIssueHierarchy::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg, mHierarchyBody);
|
||||
get(msg, mModifyDate);
|
||||
rawStringPtr = get_c_str(mHierarchyBody);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResCreateTicket::ResCreateTicket(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_CREATETICKET, track, userData), mTicketID(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
ResCreateTicket::~ResCreateTicket()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResCreateTicket::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg, mTicketID);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResAppendComment::ResAppendComment(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_APPENDCOMMENT, track, userData), mTicketID(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
ResAppendComment::~ResAppendComment()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResAppendComment::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg, mTicketID);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetTicketByID::ResGetTicketByID(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_GETTICKETBYID, track, userData), mTicketBody(CSAssist::CSAssistGameAPITicket())
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
ResGetTicketByID::~ResGetTicketByID()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResGetTicketByID::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg, mTicketBody);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetTicketComments::ResGetTicketComments(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_GETTICKETCOMMENTS, track, userData), mNumberRead(0), mCommentArray(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetTicketComments::~ResGetTicketComments()
|
||||
//----------------------------------------------
|
||||
{
|
||||
if (mCommentArray != 0)
|
||||
delete [] mCommentArray; // be sure to free up any resources!
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResGetTicketComments::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg,mNumberRead);
|
||||
|
||||
mCommentArray = 0;
|
||||
if (mNumberRead > 0)
|
||||
{
|
||||
mCommentArray = new CSAssistGameAPITicketComment[mNumberRead];
|
||||
if (mCommentArray == 0) // memory allocation error, return error code
|
||||
{
|
||||
mNumberRead = 0;
|
||||
setResult(CSASSIST_RESULT_OUTOFMEMORY);
|
||||
return;
|
||||
}
|
||||
CSAssistGameAPITicketComment *pcomments = mCommentArray;
|
||||
for (unsigned i=0; i < mNumberRead; i++)
|
||||
{
|
||||
decodeTicketComment(msg, pcomments);
|
||||
pcomments++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetTicketByCharacter::ResGetTicketByCharacter(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_GETTICKET, track, userData), mNumberReturned(0), mTotalNumber(0), mTicketArray(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetTicketByCharacter::~ResGetTicketByCharacter()
|
||||
//----------------------------------------------
|
||||
{
|
||||
if (mTicketArray != 0)
|
||||
delete [] mTicketArray; // be sure to free up any resources!
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResGetTicketByCharacter::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg, mNumberReturned);
|
||||
get(msg, mTotalNumber);
|
||||
|
||||
mTicketArray = 0;
|
||||
if (mNumberReturned > 0)
|
||||
{
|
||||
mTicketArray = new CSAssistGameAPITicket[mNumberReturned];
|
||||
if (mTicketArray == 0) // memory allocation error, return error code
|
||||
{
|
||||
mNumberReturned = 0;
|
||||
mTotalNumber = 0;
|
||||
setResult(CSASSIST_RESULT_OUTOFMEMORY);
|
||||
return;
|
||||
}
|
||||
CSAssistGameAPITicket *ptickets = mTicketArray;
|
||||
for (unsigned i=0; i < mNumberReturned; i++)
|
||||
{
|
||||
get(msg, ptickets);
|
||||
ptickets++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResTicketChange::ResTicketChange(unsigned track)
|
||||
: Response(CSASSIST_SERVER_TICKETCHANGE, track, 0), mTicketID(0), mUID(0), rawCharacter(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResTicketChange::~ResTicketChange()
|
||||
//----------------------------------------------
|
||||
{
|
||||
if (rawCharacter)
|
||||
delete [] rawCharacter;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResTicketChange::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg, mTicketID);
|
||||
get(msg, mUID);
|
||||
get(msg, mCharacter);
|
||||
rawCharacter = get_c_str(mCharacter);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResMarkTicketRead::ResMarkTicketRead(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_MARKREAD, track, userData)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResCancelTicket::ResCancelTicket(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_CANCELTICKET, track, userData), mTicketID(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
ResCancelTicket::~ResCancelTicket()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResCancelTicket::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg, mTicketID);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResCommentCount::ResCommentCount(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_COMMENTCOUNT, track, userData), mTicketID(0), mCount(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
ResCommentCount::~ResCommentCount()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResCommentCount::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg, mTicketID);
|
||||
get(msg, mCount);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResRequestGameLocation::ResRequestGameLocation(unsigned track)
|
||||
: Response(CSASSIST_SERVER_REQUESTLOCATION, track, 0), mSourceTrack(0), mUID(0), mCSRUID(0),
|
||||
rawCharacter(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResRequestGameLocation::~ResRequestGameLocation()
|
||||
//----------------------------------------------
|
||||
{
|
||||
if (rawCharacter)
|
||||
delete [] rawCharacter;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResRequestGameLocation::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg,mSourceTrack);
|
||||
get(msg,mUID);
|
||||
get(msg,mCharacter);
|
||||
get(msg,mCSRUID);
|
||||
rawCharacter = get_c_str(mCharacter);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResReplyGameLocation::ResReplyGameLocation(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_REPLYLOCATION, track, userData)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetDocumentList::ResGetDocumentList(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_GETDOCUMENTLIST, track, userData), mNumberRead(0), mDocumentArray(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetDocumentList::~ResGetDocumentList()
|
||||
//----------------------------------------------
|
||||
{
|
||||
if (mDocumentArray != 0)
|
||||
delete [] mDocumentArray; // be sure to free up any resources!
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResGetDocumentList::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg,mNumberRead);
|
||||
|
||||
mDocumentArray = 0;
|
||||
if (mNumberRead > 0)
|
||||
{
|
||||
mDocumentArray = new CSAssistGameAPIDocumentHeader[mNumberRead];
|
||||
if (mDocumentArray == 0) // memory allocation error, return error code
|
||||
{
|
||||
mNumberRead = 0;
|
||||
setResult(CSASSIST_RESULT_OUTOFMEMORY);
|
||||
return;
|
||||
}
|
||||
CSAssistGameAPIDocumentHeader *pdocs = mDocumentArray;
|
||||
for (unsigned i=0; i < mNumberRead; i++)
|
||||
{
|
||||
decodeDocumentHeader(msg, pdocs);
|
||||
pdocs++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetDocument::ResGetDocument(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_GETDOCUMENT, track, userData), rawDocument(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetDocument::~ResGetDocument()
|
||||
//----------------------------------------------
|
||||
{
|
||||
if (rawDocument)
|
||||
delete [] rawDocument;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResGetDocument::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg,mDocumentBody);
|
||||
rawDocument = get_c_str(mDocumentBody);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetTicketXMLBlock::ResGetTicketXMLBlock(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_GETTICKETXMLBLOCK, track, userData), rawXML(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetTicketXMLBlock::~ResGetTicketXMLBlock()
|
||||
//----------------------------------------------
|
||||
{
|
||||
if (rawXML)
|
||||
delete [] rawXML;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResGetTicketXMLBlock::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg,mXMLBody);
|
||||
rawXML = get_c_str(mXMLBody);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetKBArticle::ResGetKBArticle(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_GETKBARTICLE, track, userData), rawArticle(0), rawTitle(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResGetKBArticle::~ResGetKBArticle()
|
||||
//----------------------------------------------
|
||||
{
|
||||
if (rawArticle)
|
||||
delete [] rawArticle;
|
||||
if (rawTitle)
|
||||
delete [] rawTitle;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResGetKBArticle::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg,mArticleBody);
|
||||
rawArticle = get_c_str(mArticleBody);
|
||||
// don't try to read title from older servers
|
||||
if (msg.getSize() <= 0)
|
||||
return;
|
||||
get(msg,mArticleTitle);
|
||||
rawTitle = get_c_str(mArticleTitle);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResSearchKB::ResSearchKB(unsigned track, const void *userData)
|
||||
: Response(CSASSIST_CALL_SEARCHKB, track, userData), mNumberRead(0), mArticleArray(0)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResSearchKB::~ResSearchKB()
|
||||
//----------------------------------------------
|
||||
{
|
||||
if (mArticleArray != 0)
|
||||
delete [] mArticleArray; // be sure to free up any resources!
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResSearchKB::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg, mNumberRead);
|
||||
|
||||
mArticleArray = 0;
|
||||
if (mNumberRead > 0)
|
||||
{
|
||||
mArticleArray = new CSAssistGameAPISearchResult[mNumberRead];
|
||||
if (mArticleArray == 0) // memory allocation error, return error code
|
||||
{
|
||||
mNumberRead = 0;
|
||||
setResult(CSASSIST_RESULT_OUTOFMEMORY);
|
||||
return;
|
||||
}
|
||||
CSAssistGameAPISearchResult *pdocs = mArticleArray;
|
||||
for (unsigned i=0; i < mNumberRead; i++)
|
||||
{
|
||||
decodeSearchResult(msg, pdocs);
|
||||
pdocs++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
ResHierarchyChange::ResHierarchyChange(unsigned track)
|
||||
: Response(CSASSIST_SERVER_HIERARCHYCHANGE, track, 0),
|
||||
rawGame(0), rawVersion(0), rawLanguage(0), mChangeType(CSASSIST_HIERARCHY_NONE)
|
||||
//----------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
ResHierarchyChange::~ResHierarchyChange()
|
||||
{
|
||||
if (rawGame)
|
||||
delete [] rawGame;
|
||||
if (rawVersion)
|
||||
delete [] rawVersion;
|
||||
if (rawLanguage)
|
||||
delete [] rawLanguage;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void ResHierarchyChange::decode(Base::ByteStream::ReadIterator &msg)
|
||||
//----------------------------------------------
|
||||
{
|
||||
get(msg,mGame);
|
||||
get(msg,mVersion);
|
||||
get(msg,mLanguage);
|
||||
rawGame = get_c_str(mGame);
|
||||
rawVersion = get_c_str(mVersion);
|
||||
rawLanguage = get_c_str(mLanguage);
|
||||
get(msg, mChangeType);
|
||||
}
|
||||
|
||||
ResConnectLB::ResConnectLB(unsigned track, Request *req, Response *res)
|
||||
: Response(CSASSIST_CALL_CONNECTLB, track, 0),
|
||||
mServerPort(0),
|
||||
mConnectRequest(req),
|
||||
mConnectResponse(res)
|
||||
{
|
||||
//fprintf(stderr,"Const:Req=%p,Res=%p\n", mConnectRequest,mConnectResponse);
|
||||
}
|
||||
|
||||
ResConnectLB::~ResConnectLB()
|
||||
{
|
||||
if (mResult == CSASSIST_RESULT_TIMEOUT)
|
||||
{
|
||||
//fprintf(stderr,"Dest: Req=%p,Res=%p\n", mConnectRequest,mConnectResponse);
|
||||
delete mConnectRequest;
|
||||
delete mConnectResponse;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ResConnectLB::decode(Base::ByteStream::ReadIterator &msg)
|
||||
{
|
||||
get(msg, mServerName);
|
||||
get(msg, mServerPort);
|
||||
}
|
||||
|
||||
} // namespace CSAssist
|
||||
+405
@@ -0,0 +1,405 @@
|
||||
#ifndef RESPONSE_H
|
||||
#define RESPONSE_H
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// response.h
|
||||
//
|
||||
// Author: Graeme Ing ([email protected])
|
||||
// Module: CSAssist API
|
||||
//
|
||||
// copyright 2002 (c) Sony Online Entertainment Inc.
|
||||
//
|
||||
// Class definitions for all response objects from servers
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "Base/Archive.h"
|
||||
#include "CSAssistgameapicore.h"
|
||||
#include "request.h"
|
||||
|
||||
namespace CSAssist
|
||||
{
|
||||
|
||||
//------------------------------------------------
|
||||
class Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
Response(unsigned type, unsigned track, const void *muserData);
|
||||
virtual ~Response();
|
||||
unsigned getType() { return (unsigned)mType; }
|
||||
virtual CSAssistGameAPITrack getTrack() { return (CSAssistGameAPITrack)mTrack; }
|
||||
virtual CSAssistGameAPIResult getResult() { return (CSAssistGameAPIResult)mResult; }
|
||||
inline void *getUserData() { return muserData; }
|
||||
inline void init(short type, unsigned track, unsigned result)
|
||||
{ mType = type; mTrack = track; mResult = result; }
|
||||
inline void setResult(unsigned result) { mResult = result; }
|
||||
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
|
||||
protected:
|
||||
short mType;
|
||||
unsigned mTrack;
|
||||
unsigned mResult;
|
||||
void *muserData;
|
||||
|
||||
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
//
|
||||
// Add new Response objects for each API call here
|
||||
//
|
||||
// **** ADD CODE HERE ****
|
||||
//----------------------------------------------
|
||||
|
||||
//------------------------------------------------
|
||||
class ResConnectCSAssist : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResConnectCSAssist(unsigned track, const void *userData);
|
||||
private:
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResDisconnectCSAssist : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResDisconnectCSAssist(unsigned track, const void *userData);
|
||||
private:
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResNewTicketActivity : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResNewTicketActivity(unsigned track, const void *userData);
|
||||
~ResNewTicketActivity();
|
||||
inline unsigned getNewActivityFlag() { return mNewActivityFlag; }
|
||||
inline unsigned getHasTickets() { return mHasTickets; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
unsigned mNewActivityFlag;
|
||||
unsigned mHasTickets;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResRegisterCharacter : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResRegisterCharacter(unsigned track, const void *userData);
|
||||
private:
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResUnRegisterCharacter : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResUnRegisterCharacter(unsigned track, const void *userData);
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------
|
||||
class ResGetIssueHierarchy : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResGetIssueHierarchy(unsigned track, const void *userData);
|
||||
virtual ~ResGetIssueHierarchy();
|
||||
inline CSAssistUnicodeChar *getHierarchyBody() { return rawStringPtr; }
|
||||
inline unsigned getModifyDate() { return mModifyDate; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
Plat_Unicode::String mHierarchyBody;
|
||||
unsigned mModifyDate;
|
||||
CSAssistUnicodeChar *rawStringPtr;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResCreateTicket : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResCreateTicket(unsigned track, const void *userData);
|
||||
~ResCreateTicket();
|
||||
inline unsigned getTicketID() { return mTicketID; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
unsigned mTicketID;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResAppendComment : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResAppendComment(unsigned track, const void *userData);
|
||||
~ResAppendComment();
|
||||
inline unsigned getTicketID() { return mTicketID; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
unsigned mTicketID;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResGetTicketByID : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResGetTicketByID(unsigned track, const void *userData);
|
||||
~ResGetTicketByID();
|
||||
inline CSAssistGameAPITicket &getTicketBody() { return (CSAssistGameAPITicket &)mTicketBody; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
CSAssistGameAPITicket mTicketBody;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResGetTicketComments : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResGetTicketComments(unsigned track, const void *userData);
|
||||
~ResGetTicketComments();
|
||||
inline unsigned getNumberRead() { return mNumberRead; }
|
||||
inline CSAssistGameAPITicketComment *getCommentArray() { return mCommentArray; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
|
||||
private:
|
||||
unsigned mNumberRead;
|
||||
CSAssistGameAPITicketComment *mCommentArray;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResGetTicketByCharacter : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResGetTicketByCharacter(unsigned track, const void *userData);
|
||||
~ResGetTicketByCharacter();
|
||||
inline unsigned getNumberReturned() { return mNumberReturned; }
|
||||
inline unsigned getTotalNumber() { return mTotalNumber; }
|
||||
inline CSAssistGameAPITicket *getTicketArray() { return mTicketArray; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
|
||||
private:
|
||||
unsigned mNumberReturned;
|
||||
unsigned mTotalNumber;
|
||||
CSAssistGameAPITicket *mTicketArray;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResTicketChange : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResTicketChange(unsigned track);
|
||||
~ResTicketChange();
|
||||
inline unsigned getTicketID() { return mTicketID; }
|
||||
inline unsigned getUID() { return mUID; }
|
||||
inline CSAssistUnicodeChar *getCharacter() { return rawCharacter; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
unsigned mTicketID;
|
||||
unsigned mUID;
|
||||
Plat_Unicode::String mCharacter;
|
||||
CSAssistUnicodeChar *rawCharacter;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResMarkTicketRead : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResMarkTicketRead(unsigned track, const void *userData);
|
||||
private:
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResCancelTicket : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResCancelTicket(unsigned track, const void *userData);
|
||||
~ResCancelTicket();
|
||||
inline unsigned getTicketID() { return mTicketID; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
unsigned mTicketID;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResCommentCount : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResCommentCount(unsigned track, const void *userData);
|
||||
~ResCommentCount();
|
||||
inline unsigned getTicketID() { return mTicketID; }
|
||||
inline unsigned getCount() { return mCount; };
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
unsigned mTicketID;
|
||||
unsigned mCount;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResRequestGameLocation : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResRequestGameLocation(unsigned track);
|
||||
~ResRequestGameLocation();
|
||||
inline unsigned getSourceTrack() { return mSourceTrack; }
|
||||
inline unsigned getUID() { return mUID; }
|
||||
inline CSAssistUnicodeChar *getCharacter() { return rawCharacter; }
|
||||
inline unsigned getCSRUID() { return mCSRUID; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
unsigned mSourceTrack;
|
||||
unsigned mUID;
|
||||
Plat_Unicode::String mCharacter;
|
||||
unsigned mCSRUID;
|
||||
CSAssistUnicodeChar *rawCharacter;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResReplyGameLocation : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResReplyGameLocation(unsigned track, const void *userData);
|
||||
private:
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResGetDocumentList : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResGetDocumentList(unsigned track, const void *userData);
|
||||
virtual ~ResGetDocumentList();
|
||||
inline unsigned getNumberRead() { return mNumberRead; }
|
||||
inline CSAssistGameAPIDocumentHeader *getDocumentList() { return mDocumentArray; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
|
||||
private:
|
||||
unsigned mNumberRead;
|
||||
CSAssistGameAPIDocumentHeader *mDocumentArray;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResGetDocument : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResGetDocument(unsigned track, const void *userData);
|
||||
virtual ~ResGetDocument();
|
||||
inline CSAssistUnicodeChar *getDocumentBody() { return rawDocument; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
Plat_Unicode::String mDocumentBody;
|
||||
CSAssistUnicodeChar *rawDocument;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResGetTicketXMLBlock : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResGetTicketXMLBlock(unsigned track, const void *userData);
|
||||
~ResGetTicketXMLBlock();
|
||||
inline CSAssistUnicodeChar *getXMLBody() { return rawXML; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
Plat_Unicode::String mXMLBody;
|
||||
CSAssistUnicodeChar *rawXML;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResGetKBArticle : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResGetKBArticle(unsigned track, const void *userData);
|
||||
~ResGetKBArticle();
|
||||
inline CSAssistUnicodeChar *getArticleBody() { return rawArticle; }
|
||||
inline CSAssistUnicodeChar *getArticleTitle() { return rawTitle; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
Plat_Unicode::String mArticleBody;
|
||||
CSAssistUnicodeChar *rawArticle;
|
||||
Plat_Unicode::String mArticleTitle;
|
||||
CSAssistUnicodeChar *rawTitle;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResSearchKB : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResSearchKB(unsigned track, const void *userData);
|
||||
~ResSearchKB();
|
||||
inline unsigned getNumberRead() { return mNumberRead; }
|
||||
inline CSAssistGameAPISearchResult *getArticleList() { return mArticleArray; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
|
||||
private:
|
||||
unsigned mNumberRead;
|
||||
CSAssistGameAPISearchResult *mArticleArray;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResHierarchyChange : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResHierarchyChange(unsigned track);
|
||||
~ResHierarchyChange();
|
||||
inline CSAssistUnicodeChar *getGame() { return rawGame; }
|
||||
inline CSAssistUnicodeChar *getVersion() { return rawVersion; }
|
||||
inline CSAssistUnicodeChar *getLanguage() { return rawLanguage; }
|
||||
inline CSAssistGameAPIHierarchyChangeType getChangeType() { return (CSAssistGameAPIHierarchyChangeType)mChangeType; }
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
private:
|
||||
Plat_Unicode::String mGame;
|
||||
Plat_Unicode::String mVersion;
|
||||
Plat_Unicode::String mLanguage;
|
||||
CSAssistUnicodeChar *rawGame;
|
||||
CSAssistUnicodeChar *rawVersion;
|
||||
CSAssistUnicodeChar *rawLanguage;
|
||||
unsigned mChangeType;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
class ResConnectLB : public Response
|
||||
//------------------------------------------------
|
||||
{
|
||||
public:
|
||||
ResConnectLB(unsigned track, Request *req, Response *res);
|
||||
~ResConnectLB();
|
||||
virtual void decode(Base::ByteStream::ReadIterator &msg);
|
||||
inline std::string getServerName() { return mServerName; }
|
||||
inline unsigned getServerPort() { return mServerPort; }
|
||||
Request *getRequest() { return mConnectRequest; }
|
||||
Response *getResponse() { return mConnectResponse; }
|
||||
|
||||
private:
|
||||
std::string mServerName;
|
||||
unsigned short mServerPort;
|
||||
Request *mConnectRequest;
|
||||
Response *mConnectResponse;
|
||||
|
||||
};
|
||||
|
||||
} // namespace CSAssist
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
||||
// Default to Data object reuse
|
||||
bool ByteStream::ms_reuseData = true;
|
||||
|
||||
#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, (const char *)(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
|
||||
|
||||
ByteStream::ReadIterator::ReadIterator() :
|
||||
readPtr(0),
|
||||
stream(0)
|
||||
{
|
||||
}
|
||||
|
||||
ByteStream::ReadIterator::ReadIterator(const ReadIterator & source) :
|
||||
readPtr(source.readPtr),
|
||||
stream(source.stream)
|
||||
{
|
||||
}
|
||||
|
||||
ByteStream::ReadIterator::ReadIterator(const ByteStream & source) :
|
||||
readPtr(0),
|
||||
stream(&source)
|
||||
{
|
||||
}
|
||||
|
||||
ByteStream::ReadIterator::~ReadIterator()
|
||||
{
|
||||
stream = 0;
|
||||
}
|
||||
|
||||
ByteStream::ByteStream() :
|
||||
allocatedSize(0),
|
||||
beginReadIterator(),
|
||||
data(NULL),
|
||||
size(0),
|
||||
lastPutSize(0)
|
||||
{
|
||||
data = Data::getNewData();
|
||||
beginReadIterator = ReadIterator(*this);
|
||||
}
|
||||
|
||||
ByteStream::ByteStream(const unsigned char * const newBuffer, const unsigned int bufferSize) :
|
||||
allocatedSize(bufferSize),
|
||||
data(0),
|
||||
size(bufferSize),
|
||||
lastPutSize(0)
|
||||
{
|
||||
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()),
|
||||
lastPutSize(source.lastPutSize)
|
||||
{
|
||||
source.data->ref();
|
||||
beginReadIterator = ReadIterator(*this);
|
||||
}
|
||||
|
||||
ByteStream::ByteStream(ReadIterator & source) :
|
||||
allocatedSize(0),
|
||||
size(0),
|
||||
lastPutSize(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;
|
||||
if (sourceSize > 0)
|
||||
lastPutSize = sourceSize;
|
||||
}
|
||||
|
||||
bool ByteStream::overwriteEnd(const void * const source, const unsigned int sourceSize)
|
||||
{
|
||||
if(data->getRef() <= 1 &&
|
||||
lastPutSize == sourceSize &&
|
||||
sourceSize <= data->size)
|
||||
{
|
||||
memcpy(&data->buffer[size-sourceSize], source, sourceSize);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -0,0 +1,756 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
bool overwriteEnd(const void * const source, const unsigned int sourceSize);
|
||||
|
||||
static bool ms_reuseData;
|
||||
|
||||
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;
|
||||
unsigned int lastPutSize;
|
||||
|
||||
};
|
||||
|
||||
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 (ByteStream::ms_reuseData)
|
||||
{
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Lock();
|
||||
#endif
|
||||
|
||||
getDataFreeList().push_back(oldData);
|
||||
oldData->refCount = 0;
|
||||
|
||||
#if defined(USE_ARCHIVE_MUTEX)
|
||||
ByteStreamMutex.Unlock();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
delete oldData;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool overwriteEnd(ByteStream & target, const double value)
|
||||
{
|
||||
double temp = byteSwap(value);
|
||||
return target.overwriteEnd(&temp, 8);
|
||||
}
|
||||
|
||||
inline bool overwriteEnd(ByteStream & target, const float value)
|
||||
{
|
||||
float temp = byteSwap(value);
|
||||
return target.overwriteEnd(&temp, 4);
|
||||
}
|
||||
|
||||
inline bool overwriteEnd(ByteStream & target, const uint64 value)
|
||||
{
|
||||
uint64 temp = byteSwap(value);
|
||||
return target.overwriteEnd(&temp, 8);
|
||||
}
|
||||
|
||||
inline bool overwriteEnd(ByteStream & target, const int64 value)
|
||||
{
|
||||
int64 temp = byteSwap(value);
|
||||
return target.overwriteEnd(&temp, 8);
|
||||
}
|
||||
|
||||
inline bool overwriteEnd(ByteStream & target, const uint32 value)
|
||||
{
|
||||
uint32 temp = byteSwap(value);
|
||||
return target.overwriteEnd(&temp, 4);
|
||||
}
|
||||
|
||||
inline bool overwriteEnd(ByteStream & target, const int32 value)
|
||||
{
|
||||
int32 temp = byteSwap(value);
|
||||
return target.overwriteEnd(&temp, 4);
|
||||
}
|
||||
|
||||
inline bool overwriteEnd(ByteStream & target, const uint16 value)
|
||||
{
|
||||
uint16 temp = byteSwap(value);
|
||||
return target.overwriteEnd(&temp, 2);
|
||||
}
|
||||
|
||||
inline bool overwriteEnd(ByteStream & target, const int16 value)
|
||||
{
|
||||
int16 temp = byteSwap(value);
|
||||
return target.overwriteEnd(&temp, 2);
|
||||
}
|
||||
|
||||
inline bool overwriteEnd(ByteStream & target, const uint8 value)
|
||||
{
|
||||
return target.overwriteEnd(&value, 1);
|
||||
}
|
||||
|
||||
inline bool overwriteEnd(ByteStream & target, const int8 value)
|
||||
{
|
||||
return target.overwriteEnd(&value, 1);
|
||||
}
|
||||
|
||||
inline bool overwriteEnd(ByteStream & target, const bool & source)
|
||||
{
|
||||
return target.overwriteEnd(&source, 1);
|
||||
}
|
||||
|
||||
inline bool overwriteEnd(ByteStream & target, const unsigned char * const source, const unsigned int sourceSize)
|
||||
{
|
||||
return target.overwriteEnd(source, sourceSize);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,349 @@
|
||||
#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;
|
||||
|
||||
pFilename = strdup(filename);
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
#ifndef _AUTOLOG_H
|
||||
#define _AUTOLOG_H
|
||||
|
||||
#pragma warning (disable : 4786)
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
class CAutoLog
|
||||
{
|
||||
public:
|
||||
enum eLogLevel {
|
||||
eLOG_NONE = 0, // log entries are discarded
|
||||
eLOG_ERROR = 1, // log errors only
|
||||
eLOG_ALERT = 2, // log alerts and errors only
|
||||
eLOG_NORMAL = 3, // log all normal events, no debug
|
||||
eLOG_DEBUG = 4 // log everything
|
||||
};
|
||||
|
||||
// Global setting for all AutoLog instances for this application. Can be set on the fly. Default is eLOG_NORMAL.
|
||||
void SetLogLevel(eLogLevel loglevel);
|
||||
|
||||
// Global setting for all AutoLog instances for this application. Can be set on the fly. Default is eLOG_ERROR.
|
||||
void SetPrintLevel(eLogLevel printlevel);
|
||||
|
||||
// Global setting for all AutoLog instances for this application. Can be set on the fly. Default is eLOG_ERROR.
|
||||
void SetFlushLevel(eLogLevel flushlevel);
|
||||
|
||||
// constructor, no file loaded
|
||||
CAutoLog();
|
||||
|
||||
// version of constructor that calls Open(file)
|
||||
CAutoLog(const char * file);
|
||||
|
||||
// destructor, will close file if opened
|
||||
~CAutoLog();
|
||||
|
||||
// Open log file. If a file is already open, function will fail.
|
||||
// returns true if no error
|
||||
bool Open(const char * file);
|
||||
|
||||
// Close log file if opened.
|
||||
void Close(void);
|
||||
|
||||
// Make an entry in the log. Format and variable arguments are identical to printf.
|
||||
// severity will be compared to master log level to determine if the log entry will be made
|
||||
// severity will be compared to master print level to determine if the log entry will be printed to stdout
|
||||
void Log(eLogLevel severity, char * format, ...);
|
||||
|
||||
// Equivalent to the above with the approriate severity argument
|
||||
void LogError(char * format, ...);
|
||||
void LogAlert(char * format, ...);
|
||||
void Log(char * format, ...);
|
||||
void LogDebug(char * format, ...);
|
||||
|
||||
private:
|
||||
FILE * pFile; // current log file opened
|
||||
char * pFilename; // current log file opened
|
||||
int nTodaysDayOfYear; // remember the current day to detect change of day
|
||||
void Archive(void); // archives current log
|
||||
|
||||
static eLogLevel nLogMask; // master severity level
|
||||
static eLogLevel nPrintMask; // master severity level
|
||||
static eLogLevel nFlushMask; // master severity level
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
inline void CAutoLog::SetLogLevel(eLogLevel loglevel)
|
||||
{
|
||||
nLogMask = loglevel;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
inline void CAutoLog::SetPrintLevel(eLogLevel printlevel)
|
||||
{
|
||||
nPrintMask = printlevel;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
inline void CAutoLog::SetFlushLevel(eLogLevel flushlevel)
|
||||
{
|
||||
nFlushMask = flushlevel;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
inline CAutoLog::CAutoLog()
|
||||
{
|
||||
pFilename = NULL;
|
||||
pFile = (FILE *)-1;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
inline CAutoLog::CAutoLog(const char * file)
|
||||
{
|
||||
pFilename = NULL;
|
||||
pFile = (FILE *)-1;
|
||||
Open(file);
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
inline CAutoLog::~CAutoLog()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
#include "Base.h"
|
||||
@@ -0,0 +1,63 @@
|
||||
////////////////////////////////////////
|
||||
// Base.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Provide a single header file that may be used to include all
|
||||
// Base library header files.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef _BASEPCH_H
|
||||
#define _BASEPCH_H
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32/Platform.h"
|
||||
#include "win32/Types.h"
|
||||
#include "win32/Mutex.h"
|
||||
#include "win32/Event.h"
|
||||
#include "win32/Thread.h"
|
||||
#include "Logger.h"
|
||||
#include "Config.h"
|
||||
#include "ScopeLock.h"
|
||||
#include "Statistics.h"
|
||||
#include "TemplateObjectAllocator.h"
|
||||
#include "BlockAllocator.h"
|
||||
|
||||
#elif linux
|
||||
|
||||
#include "linux/Platform.h"
|
||||
#include "linux/Types.h"
|
||||
#include "linux/Mutex.h"
|
||||
#include "linux/Event.h"
|
||||
#include "linux/Thread.h"
|
||||
#include "Logger.h"
|
||||
#include "Config.h"
|
||||
#include "ScopeLock.h"
|
||||
#include "Statistics.h"
|
||||
#include "TemplateObjectAllocator.h"
|
||||
#include "BlockAllocator.h"
|
||||
|
||||
#elif sparc
|
||||
|
||||
#include "solaris/Platform.h"
|
||||
#include "solaris/Types.h"
|
||||
#include "solaris/Mutex.h"
|
||||
#include "solaris/Event.h"
|
||||
#include "solaris/Thread.h"
|
||||
#include "Logger.h"
|
||||
#include "Config.h"
|
||||
#include "ScopeLock.h"
|
||||
#include "Statistics.h"
|
||||
#include "TemplateObjectAllocator.h"
|
||||
#include "BlockAllocator.h"
|
||||
|
||||
#else
|
||||
|
||||
#error Base.h: Undefine platform type
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _BASEPCH_H
|
||||
@@ -0,0 +1,30 @@
|
||||
#if !defined (BLOCKALLOCATOR_H_)
|
||||
#define BLOCKALLOCATOR_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
class BlockAllocator
|
||||
{
|
||||
public:
|
||||
BlockAllocator();
|
||||
~BlockAllocator();
|
||||
void *getBlock(unsigned accum);
|
||||
void returnBlock(unsigned *handle);
|
||||
|
||||
private:
|
||||
unsigned *m_blocks[31];
|
||||
};
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,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 != '-')
|
||||
pCursor++;
|
||||
|
||||
int c = 0;
|
||||
while (*pCursor && (isdigit(*pCursor) || *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
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
; Example syntax of a config file.
|
||||
# This is a comment to end of line.
|
||||
; This is a comment too....both comments are to end of line
|
||||
[KEYWORD] ; all keywords must be upper case to be recognized
|
||||
|
||||
; single number, with code example
|
||||
# long number = config.GetLong("PORT");
|
||||
[PORT] 5999 ; common single-value case
|
||||
|
||||
; list of strings, with code example
|
||||
# config.FindKey("NUMBERS");
|
||||
# while (number = config.GetLong(NULL))
|
||||
# YourHandleNumber(number);
|
||||
[NUMBERS] 100
|
||||
200, 300 ; formatting is very flexible as long as numbers are delimited by non-numbers
|
||||
400 500
|
||||
600 ; This is badly formatted for example purposes only
|
||||
|
||||
; single string, with code example
|
||||
# strcpy(mystring, config.GetString("STRING"));
|
||||
[STRING] "This is a string"
|
||||
|
||||
; list of strings, with code example
|
||||
# config.FindKey("HOSTS");
|
||||
# while (string = config.GetString(NULL))
|
||||
# YourHandleString(string);
|
||||
[HOSTS]
|
||||
"206.19.151.173:5999"
|
||||
"206.19.151.173:5998"
|
||||
"206.19.151.173:2000"
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
class CConfig
|
||||
{
|
||||
public:
|
||||
// constructor, no file loaded
|
||||
CConfig();
|
||||
|
||||
// version of constructor that calls LoadFile(file)
|
||||
CConfig(char * file);
|
||||
|
||||
// destructor, will delete all buffers
|
||||
~CConfig();
|
||||
|
||||
// copy text config file into memory. Required to use extraction methods.
|
||||
// if called with a different filename, existing file will be discarded.
|
||||
bool LoadFile(char * file);
|
||||
|
||||
// delete memory buffer of file
|
||||
void UnloadFile();
|
||||
|
||||
// set cursor in file based on key name. Alternate way to select first key when extracting lists.
|
||||
// returns TRUE if key is found.
|
||||
bool FindKey(char *key);
|
||||
|
||||
// extract string from config. If key is NULL, extract next string in list, else extract first string.
|
||||
// if key was not found, returns NULL
|
||||
char * GetString(char *key = NULL);
|
||||
|
||||
// extract number from config. If key is NULL, extract next number in list, else extract first number.
|
||||
// if key was not found, returns 0
|
||||
long GetLong(char *key = NULL); // extract number from config.
|
||||
|
||||
// indicate if config file has been loaded
|
||||
inline bool FileLoaded() { return pConfig == NULL ? false : true; }
|
||||
|
||||
private:
|
||||
char * pConfig; // pointer to file memory
|
||||
char * pCursor; // current cursor into file memory
|
||||
char strBuffer[8196]; // buffer for GetString return pointer -- reused
|
||||
};
|
||||
|
||||
inline CConfig::CConfig()
|
||||
{
|
||||
pConfig = NULL;
|
||||
pCursor = NULL;
|
||||
}
|
||||
|
||||
inline CConfig::CConfig(char * file)
|
||||
{
|
||||
pConfig = NULL;
|
||||
pCursor = NULL;
|
||||
LoadFile(file);
|
||||
}
|
||||
|
||||
inline CConfig::~CConfig()
|
||||
{
|
||||
UnloadFile();
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef BASE_EVENT_H
|
||||
#define BASE_EVENT_H
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32/Event.h"
|
||||
|
||||
#elif linux
|
||||
|
||||
#include "linux/Event.h"
|
||||
|
||||
#elif sparc
|
||||
|
||||
#include "solaris/Event.h"
|
||||
|
||||
#else
|
||||
|
||||
#error /Base/Event.h: Undefine platform type
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BASE_EVENT_H
|
||||
@@ -0,0 +1,688 @@
|
||||
#include "Logger.h"
|
||||
#include "Mutex.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
const long kDateLenAllowance = 256;
|
||||
|
||||
#ifndef _BASE_LOGGER_MAX_BUF_SIZE_
|
||||
#define _BASE_LOGGER_MAX_BUF_SIZE_ 2048
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
const char file_sep = '\\';
|
||||
|
||||
#define LOGGER_GET_CURR_TIME(__tm_struct__, __time_t_var__) \
|
||||
memcpy(&__tm_struct__, localtime(&__time_t_var__), sizeof(__tm_struct__))
|
||||
|
||||
#define LOGGER_MAKE_DIR(__dir_name__, __mode__) mkdir(__dir_name__)
|
||||
|
||||
# ifdef _MT
|
||||
# define LOGGER_LOCK rLock.Lock();
|
||||
# define LOGGER_UNLOCK rLock.Unlock();
|
||||
# else // ifndef _MT
|
||||
# define LOGGER_LOCK
|
||||
# define LOGGER_UNLOCK
|
||||
# endif // _MT
|
||||
|
||||
|
||||
|
||||
|
||||
#define vsnprintf _vsnprintf
|
||||
|
||||
#else // ifndef WIN32
|
||||
const char file_sep = '/';
|
||||
|
||||
const char *syslogLevels[] = {
|
||||
"EMERG", "ALERT", "CRIT", "ERR", "WARNING", "NOTICE", "INFO", "DEBUG" };
|
||||
|
||||
const int numSysLogLevels = sizeof(syslogLevels) / sizeof(char *);
|
||||
|
||||
#define LOGGER_GET_CURR_TIME(__tm_struct__, __time_t_var__) \
|
||||
localtime_r(&__time_t_var__, &__tm_struct__)
|
||||
|
||||
#define LOGGER_MAKE_DIR(__dir_name__, __mode__) mkdir(__dir_name__, __mode__)
|
||||
|
||||
# ifdef _REENTRANT
|
||||
# define LOGGER_LOCK rLock.Lock();
|
||||
# define LOGGER_UNLOCK rLock.Unlock();
|
||||
# else // ifndef _REENTRANT
|
||||
# define LOGGER_LOCK
|
||||
# define LOGGER_UNLOCK
|
||||
# endif // _REENTRANT
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
Logger::Logger(const char *prefix,
|
||||
int level,
|
||||
unsigned size,
|
||||
bool rollDate)
|
||||
: m_defaultLevel(level),
|
||||
m_defaultSize(size),
|
||||
m_dirPrefix(prefix),
|
||||
m_rollDate(rollDate)
|
||||
{
|
||||
m_logType = eUseLocalFile;
|
||||
LoggerInit("UnNamedServer");
|
||||
}
|
||||
|
||||
Logger::Logger(const char *programName,
|
||||
const ELogType logType,
|
||||
const char *prefix,
|
||||
int level,
|
||||
unsigned size,
|
||||
bool rollDate)
|
||||
: m_defaultLevel(level),
|
||||
m_defaultSize(size),
|
||||
m_dirPrefix(prefix),
|
||||
m_rollDate(rollDate),
|
||||
m_logType(logType)
|
||||
{
|
||||
LoggerInit(programName);
|
||||
}
|
||||
|
||||
|
||||
void Logger::LoggerInit(const char *programName)
|
||||
{
|
||||
char buf[1024];
|
||||
FILE *logDir = NULL;
|
||||
|
||||
if (0 != (m_logType & eUseLocalFile))
|
||||
{
|
||||
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);
|
||||
|
||||
LOGGER_GET_CURR_TIME(now, t);
|
||||
|
||||
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;
|
||||
m_logRolloverSize = 0x80000000; // Default: 2 GB upper limit on file size
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
// Open connection to syslog
|
||||
if (0 != (m_logType & eUseSysLog))
|
||||
openlog(programName, LOG_NDELAY | LOG_PID, LOG_LOCAL5);
|
||||
#endif // !WIN32
|
||||
|
||||
}
|
||||
|
||||
Logger::~Logger()
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
logWithSys((*iter).first, LOG_INFO, LOG_FILEONLY, "---=== Log Stopped ===---");
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
delete((*iter).second);
|
||||
|
||||
}
|
||||
m_logTable.clear();
|
||||
|
||||
#ifndef WIN32
|
||||
// close connection to syslog
|
||||
if (0 != (m_logType & eUseSysLog))
|
||||
closelog();
|
||||
#endif // !WIN32
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
if (0 != (m_logType & eUseLocalFile))
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (0 != (m_logType & eUseLocalFile))
|
||||
{
|
||||
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+");
|
||||
}
|
||||
logWithSys(logenum, LOG_INFO, LOG_FILEONLY, "---=== Log Started ===---");
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::addLog(const char *id, unsigned logenum)
|
||||
{
|
||||
if (0 != (m_logType & eUseLocalFile))
|
||||
{
|
||||
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+");
|
||||
}
|
||||
logWithSys(logenum, LOG_INFO, LOG_FILEONLY, "---===Log Started ===---");
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::updateLog(unsigned logenum, int level, unsigned size)
|
||||
{
|
||||
if (0 != (m_logType & eUseLocalFile))
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (0 != (m_logType & eUseLocalFile))
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
#ifdef WIN32
|
||||
logWithSys((*iter).first, LOG_INFO, LOG_FILEONLY, "---=== Log Stopped ===---");
|
||||
#else // ifndef WIN32
|
||||
logWithSys((*iter).first, LOG_INFO, LOG_ALWAYS, "---=== Log Stopped ===---");
|
||||
#endif // WIN32
|
||||
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;
|
||||
}
|
||||
#ifndef WIN32
|
||||
if(level == LOG_FILEONLY && ((info->file == stderr) || (info->file == stdout)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif // !WIN32
|
||||
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)
|
||||
{
|
||||
LOGGER_LOCK
|
||||
|
||||
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
|
||||
rollDate(t);
|
||||
}
|
||||
|
||||
LOGGER_UNLOCK
|
||||
}
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
if(info->max > 0)
|
||||
{
|
||||
info->used += fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s", (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 += fputc('\n', info->file);
|
||||
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", (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);
|
||||
fputc('\n', info->file);
|
||||
fflush(info->file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Logger::logSimpleWithSys(unsigned logenum, unsigned priority, int level, const char *message)
|
||||
{
|
||||
|
||||
#ifndef WIN32
|
||||
if (0 != (m_logType & eUseSysLog))
|
||||
syslog(priority, "%s: %s", syslogLevels[priority % numSysLogLevels], message);
|
||||
#endif // !WIN32
|
||||
|
||||
if (0 != (m_logType & eUseLocalFile))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
if(level == LOG_FILEONLY && ((info->file == stderr) || (info->file == stdout)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif // !WIN32
|
||||
|
||||
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)
|
||||
{
|
||||
LOGGER_LOCK
|
||||
|
||||
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
|
||||
rollDate(t);
|
||||
}
|
||||
|
||||
LOGGER_UNLOCK
|
||||
}
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
if (m_logRolloverSize> 0)
|
||||
checkLogRoll(info, ::strlen(message) + kDateLenAllowance);
|
||||
|
||||
if(info->max > 0)
|
||||
{
|
||||
info->used += fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s", (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 += fputc('\n', info->file);
|
||||
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", (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);
|
||||
fputc('\n', info->file);
|
||||
fflush(info->file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::log(unsigned logenum, int level, const char *message, ...)
|
||||
{
|
||||
char buf[_BASE_LOGGER_MAX_BUF_SIZE_];
|
||||
va_list varg;
|
||||
va_start(varg, message);
|
||||
vsnprintf(buf, _BASE_LOGGER_MAX_BUF_SIZE_, message, varg);
|
||||
buf[_BASE_LOGGER_MAX_BUF_SIZE_ - 1] = 0;
|
||||
va_end(varg);
|
||||
|
||||
// ensure that the buf does not contain any '%' characters.
|
||||
// prevent crash problem
|
||||
char *rv;
|
||||
while((rv = strchr(buf, '%')) != NULL)
|
||||
{
|
||||
*rv = ' '; // replace with space
|
||||
}
|
||||
|
||||
|
||||
logWithSys(logenum, LOG_NOTICE, level, buf);
|
||||
}
|
||||
|
||||
|
||||
void Logger::logWithSys(unsigned logenum, unsigned priority, int level, const char *message, ...)
|
||||
{
|
||||
char buf[_BASE_LOGGER_MAX_BUF_SIZE_];
|
||||
va_list varg;
|
||||
va_start(varg, message);
|
||||
vsnprintf(buf, _BASE_LOGGER_MAX_BUF_SIZE_, message, varg);
|
||||
buf[_BASE_LOGGER_MAX_BUF_SIZE_ - 1] = 0;
|
||||
va_end(varg);
|
||||
|
||||
#ifndef WIN32
|
||||
if (0 != (m_logType & eUseSysLog))
|
||||
syslog(priority, "%s: %s", syslogLevels[priority % numSysLogLevels], buf);
|
||||
#endif // !WIN32
|
||||
|
||||
if (0 != (m_logType & eUseLocalFile))
|
||||
{
|
||||
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)
|
||||
{
|
||||
LOGGER_GET_CURR_TIME(info->ts, t);
|
||||
|
||||
info->last = t;
|
||||
}
|
||||
if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
LOGGER_LOCK
|
||||
|
||||
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
|
||||
rollDate(t);
|
||||
}
|
||||
|
||||
LOGGER_UNLOCK
|
||||
}
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
if (m_logRolloverSize> 0)
|
||||
checkLogRoll(info, ::strlen(buf) + kDateLenAllowance);
|
||||
|
||||
if(info->max > 0)
|
||||
{
|
||||
info->used += fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s", (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 += fputc('\n', info->file);
|
||||
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", (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);
|
||||
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;
|
||||
|
||||
LOGGER_GET_CURR_TIME(now, t);
|
||||
|
||||
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+");
|
||||
if ((*iter).second->file == 0)
|
||||
abort();
|
||||
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;
|
||||
#ifdef WIN32
|
||||
handle = open(j, O_EXCL);
|
||||
|
||||
if((handle > 0) || (errno != EISDIR && errno != ENOENT && errno != EACCES))
|
||||
{
|
||||
perror("Logger::cmkdir():");
|
||||
abort();
|
||||
}
|
||||
#else // ifndef WIN32
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
#endif // WIN32
|
||||
LOGGER_MAKE_DIR(j, mode);
|
||||
close(handle);
|
||||
(*i) = file_sep;
|
||||
}
|
||||
else if(*(i + 1) == 0)
|
||||
{
|
||||
LOGGER_MAKE_DIR(j, mode);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::rollLog(LogInfo *logInfo)
|
||||
{
|
||||
std::string newLogName;
|
||||
char timeStampBuffer[256];
|
||||
time_t t = time(NULL);
|
||||
tm now;
|
||||
int r;
|
||||
int nTries = 10;
|
||||
|
||||
fflush(logInfo->file);
|
||||
fclose(logInfo->file);
|
||||
|
||||
do
|
||||
{
|
||||
LOGGER_GET_CURR_TIME(now, t);
|
||||
sprintf(timeStampBuffer, "-%4.4d-%2.2d-%2.2d-%2.2d-%2.2d-%2.2d.log",
|
||||
(now.tm_year + 1900), (now.tm_mon + 1), now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec);
|
||||
newLogName = logInfo->filename.substr(0, logInfo->filename.length() - 4) + timeStampBuffer;
|
||||
r = rename(logInfo->filename.c_str(), newLogName.c_str());
|
||||
nTries--;
|
||||
t++;
|
||||
}
|
||||
while ((r != 0) && (nTries > 0));
|
||||
|
||||
logInfo->file = fopen(logInfo->filename.c_str(), "a+");
|
||||
memcpy(&(logInfo->ts), &now, sizeof(tm));
|
||||
}
|
||||
|
||||
void Logger::checkLogRoll(LogInfo *logInfo, unsigned long lenToAdd)
|
||||
{
|
||||
unsigned long logSize = ftell(logInfo->file);
|
||||
|
||||
if ((logSize + lenToAdd) > m_logRolloverSize)
|
||||
{
|
||||
LOGGER_LOCK
|
||||
|
||||
rollLog(logInfo);
|
||||
|
||||
LOGGER_UNLOCK
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
#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"
|
||||
#ifndef WIN32
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
/* Use these flags defined in syslog.h for the priority level
|
||||
LOG_EMERG,
|
||||
LOG_ALERT,
|
||||
LOG_CRIT,
|
||||
LOG_ERR,
|
||||
LOG_WARNING,
|
||||
LOG_NOTICE,
|
||||
LOG_INFO,
|
||||
LOG_DEBUG
|
||||
*/
|
||||
|
||||
//-----------------------------------------------
|
||||
// Windows doesn't have syslog (?) so we define the
|
||||
// syslog warning levels here to satisfy the compiler
|
||||
// but then ignore them in log() and logSimple()
|
||||
//-----------------------------------------------
|
||||
|
||||
#ifdef WIN32
|
||||
enum _WIN32_LOG_LEVELS_
|
||||
{
|
||||
LOG_EMERG = 0,
|
||||
LOG_ALERT,
|
||||
LOG_CRIT,
|
||||
LOG_ERR,
|
||||
LOG_WARNING,
|
||||
LOG_NOTICE,
|
||||
LOG_INFO,
|
||||
LOG_DEBUG
|
||||
};
|
||||
#endif
|
||||
|
||||
enum ELogType
|
||||
{
|
||||
eUseNone = 0,
|
||||
eUseLocalFile = 1,
|
||||
eUseSysLog = 2,
|
||||
eUseBoth = 3
|
||||
};
|
||||
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
Logger(const char *programName,
|
||||
const ELogType logType = eUseLocalFile,
|
||||
const char *prefix = "logs",
|
||||
int level = 10,
|
||||
unsigned size = 0,
|
||||
bool rollDate = true);
|
||||
|
||||
Logger(const char *prefix,
|
||||
int level,
|
||||
unsigned size,
|
||||
bool rollDate = true); // Backwards compatibility
|
||||
void LoggerInit(const char *programName);
|
||||
|
||||
~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 logSimpleWithSys(unsigned logenum, unsigned priority, int level, const char *message);
|
||||
void logWithSys(unsigned logenum, unsigned priority, int level, const char *message, ...);
|
||||
void log(unsigned logenum, int level, const char *message, ...);
|
||||
|
||||
void flushAll();
|
||||
void flush(unsigned logenum);
|
||||
unsigned long getLogRolloverSize() { return m_logRolloverSize; }
|
||||
void setLogRolloverSize(unsigned long maxLogSize) { m_logRolloverSize = maxLogSize; }
|
||||
|
||||
private:
|
||||
void rollDate(time_t now);
|
||||
void cmkdir(const char *dir, int mode);
|
||||
void rollLog(LogInfo *logInfo);
|
||||
void checkLogRoll(LogInfo *logInfo, unsigned long lenToAdd);
|
||||
|
||||
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;
|
||||
ELogType m_logType;
|
||||
unsigned long m_logRolloverSize;
|
||||
};
|
||||
|
||||
extern const char file_sep;
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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(const std::string &input);
|
||||
|
||||
void Init();
|
||||
std::vector<char> Final();
|
||||
void Update(char char0);
|
||||
void Update(State & state1, std::vector<char> achar0, int i, int j);
|
||||
void Update(std::string s);
|
||||
void Update(std::vector<char> achar0);
|
||||
void Update(std::vector<char> achar0, int i);
|
||||
void Update(std::vector<char> achar0, int i, int j);
|
||||
std::string asHex();
|
||||
static std::string asHex(std::vector<char> achar0);
|
||||
|
||||
private:
|
||||
std::vector<int> Decode(std::vector<char> achar0, int i, int j);
|
||||
std::vector<char> Encode(std::vector<int> ai, int i);
|
||||
int FF(int i, int j, int k, int l, int i1, int j1, int k1);
|
||||
int GG(int i, int j, int k, int l, int i1, int j1, int k1);
|
||||
int HH(int i, int j, int k, int l, int i1, int j1, int k1);
|
||||
int II(int i, int j, int k, int l, int i1, int j1, int k1);
|
||||
void Transform(State & state1, std::vector<char> achar0, int i);
|
||||
int rotate_left(int i, int j);
|
||||
int uadd(int i, int j);
|
||||
int uadd(int i, int j, int k);
|
||||
int uadd(int i, int j, int k, int l);
|
||||
|
||||
private:
|
||||
State state;
|
||||
State finals;
|
||||
bool finalsNull;
|
||||
static std::vector<char> padding;
|
||||
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // MD5_H
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef BASE_MUTEX_H
|
||||
#define BASE_MUTEX_H
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32/Mutex.h"
|
||||
|
||||
#elif linux
|
||||
|
||||
#include "linux/Mutex.h"
|
||||
|
||||
#elif sparc
|
||||
|
||||
#include "solaris/Mutex.h"
|
||||
|
||||
#else
|
||||
|
||||
#error /Base/Mutex.h: Undefine platform type
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BASE_MUTEX_H
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
#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::int64 requestAge;
|
||||
Base::int64 freq = Base::getTimerFrequency();
|
||||
Base::uint64 finish = (finishTime ? finishTime : Base::getTimer());
|
||||
if (finish < startTime)
|
||||
requestAge = (0 - 1) - startTime - finish;
|
||||
else
|
||||
requestAge = finish - startTime;
|
||||
return (double)requestAge/freq;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // BASE_PLATFORM_H
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "ScopeLock.h"
|
||||
|
||||
#ifdef INCLUDE_SCOPELOCK
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CScopeLock::CScopeLock(CMutex& mutex) :
|
||||
mMutex(&mutex)
|
||||
{
|
||||
mMutex->Lock();
|
||||
}
|
||||
|
||||
CScopeLock::CScopeLock(CScopeLock& lock) :
|
||||
mMutex(lock.mMutex)
|
||||
{
|
||||
mMutex->Lock();
|
||||
}
|
||||
|
||||
CScopeLock::~CScopeLock()
|
||||
{
|
||||
mMutex->Unlock();
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_SCOPELOCK
|
||||
@@ -0,0 +1,40 @@
|
||||
// ScopeLock.h: interface for the CScopeLock class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SCOPELOCK_H
|
||||
#define SCOPELOCK_H
|
||||
|
||||
#if defined _MT || defined _REENTRANT
|
||||
# define INCLUDE_SCOPELOCK
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_SCOPELOCK
|
||||
|
||||
#include "Mutex.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
class CScopeLock
|
||||
{
|
||||
public:
|
||||
CScopeLock(CMutex& mutex);
|
||||
CScopeLock(CScopeLock& lock);
|
||||
virtual ~CScopeLock();
|
||||
|
||||
private:
|
||||
CMutex *mMutex;
|
||||
};
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_SCOPELOCK
|
||||
|
||||
#endif // SCOPELOCK_H
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "Statistics.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CStatisticTimer::CStatisticTimer(bool running) :
|
||||
mTotal(0),
|
||||
mStart(getTimer()),
|
||||
mRunning(running)
|
||||
{
|
||||
}
|
||||
|
||||
double CStatisticTimer::GetTime()
|
||||
{
|
||||
uint64 total = mTotal;
|
||||
|
||||
if (mRunning)
|
||||
total += getTimer()-mStart;
|
||||
|
||||
return (double)((int64)(total/getTimerFrequency()));
|
||||
}
|
||||
|
||||
uint64 CStatisticTimer::GetFraction(uint32 fraction)
|
||||
{
|
||||
uint64 total = mTotal;
|
||||
|
||||
if (mRunning)
|
||||
total += getTimer()-mStart;
|
||||
|
||||
if (fraction == 0)
|
||||
return total;
|
||||
else
|
||||
return total/(getTimerFrequency()/fraction);
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
#ifndef STATISTICS_H
|
||||
#define STATISTICS_H
|
||||
|
||||
#include <time.h>
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
template <class TYPE, uint32 COUNT>
|
||||
class CStatistic
|
||||
{
|
||||
public:
|
||||
CStatistic(uint32 freq=0) :
|
||||
mSampleFrequency(freq),
|
||||
mLastSampleTime(0),
|
||||
mSample(0),
|
||||
mSampleTotal(0),
|
||||
mAggregateTotal(0),
|
||||
mAggregateMaximum(0),
|
||||
mAggregateMinimum(0),
|
||||
mAverageTotal(0),
|
||||
mAverageIndex(0),
|
||||
mAverageCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool Sample(TYPE value)
|
||||
{
|
||||
bool commit = false;
|
||||
|
||||
if (!mLastSampleTime)
|
||||
mLastSampleTime = time(NULL);
|
||||
|
||||
if (!mSampleFrequency || mLastSampleTime + mSampleFrequency < (unsigned)time(NULL))
|
||||
{
|
||||
mSampleTotal++;
|
||||
mAggregateTotal += value;
|
||||
if (value > mAggregateMaximum)
|
||||
mAggregateMaximum = value;
|
||||
if (value < mAggregateMinimum)
|
||||
mAggregateMinimum = value;
|
||||
|
||||
if (mAverageIndex == COUNT)
|
||||
mAverageIndex = 0;
|
||||
if (mAverageCount > COUNT)
|
||||
mAverageTotal -= mAverageData[mAverageIndex];
|
||||
|
||||
mAverageData[mAverageIndex++] = value;
|
||||
mAverageTotal += value;
|
||||
|
||||
if (mAverageCount < COUNT)
|
||||
mAverageCount++;
|
||||
|
||||
commit = true;
|
||||
mSample = 0;
|
||||
}
|
||||
|
||||
mSample += value;
|
||||
|
||||
return commit;
|
||||
}
|
||||
|
||||
TYPE GetSample(uint32 age = 0)
|
||||
{
|
||||
if (age > mAverageCount)
|
||||
return 0;
|
||||
|
||||
uint32 index = mAverageIndex;
|
||||
if (age > index)
|
||||
index = COUNT - (age - index);
|
||||
else
|
||||
index -= age;
|
||||
|
||||
return mAverageData[index];
|
||||
}
|
||||
|
||||
double GetAverage()
|
||||
{
|
||||
return (double)mAverageTotal/mAverageCount;
|
||||
}
|
||||
|
||||
double GetAggregateAverage()
|
||||
{
|
||||
return (double)mAggregateTotal/mSampleTotal;
|
||||
}
|
||||
|
||||
TYPE GetMaximum()
|
||||
{
|
||||
return mAggregateMaximum;
|
||||
}
|
||||
|
||||
TYPE GetMinimum()
|
||||
{
|
||||
return mAggregateMinimum;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 mSampleFrequency;
|
||||
time_t mLastSampleTime;
|
||||
TYPE mSample;
|
||||
uint32 mSampleTotal;
|
||||
TYPE mAggregateTotal;
|
||||
TYPE mAggregateMaximum;
|
||||
TYPE mAggregateMinimum;
|
||||
|
||||
TYPE mAverageData[COUNT];
|
||||
TYPE mAverageTotal;
|
||||
uint32 mAverageIndex;
|
||||
uint32 mAverageCount;
|
||||
};
|
||||
|
||||
class CStatisticTimer
|
||||
{
|
||||
public:
|
||||
CStatisticTimer(bool running = true);
|
||||
|
||||
void Start() { if (mRunning) return; mStart = getTimer(); mRunning = true; }
|
||||
void Stop() { if (!mRunning) return; mTotal += getTimer()-mStart; mRunning = false; }
|
||||
void Reset() { mTotal = 0; mStart = getTimer(); }
|
||||
|
||||
double GetTime();
|
||||
uint64 GetFraction(uint32 fraction=1000);
|
||||
|
||||
private:
|
||||
uint64 mTotal;
|
||||
uint64 mStart;
|
||||
bool mRunning;
|
||||
};
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // STATISTICS_H
|
||||
+238
@@ -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
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
// TemplateCBlockAlloc.h: interface for the CBlockAlloc class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _TEMPLATE_COBJECTALLOCATOR_H
|
||||
#define _TEMPLATE_COBJECTALLOCATOR_H
|
||||
|
||||
#if defined _MT || defined _REENTRANT
|
||||
# define USE_ALLOCATOR_MUTEX
|
||||
#endif
|
||||
|
||||
|
||||
#include <new>
|
||||
#include "Types.h"
|
||||
#include "Mutex.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
const uint32 MAX_BLOCK_COUNT = 32;
|
||||
|
||||
template <class TYPE>
|
||||
class CObjectAllocator
|
||||
{
|
||||
public:
|
||||
CObjectAllocator(uint32 size=32)
|
||||
{
|
||||
if (size < 32)
|
||||
size = 32;
|
||||
|
||||
for (uint32 index=0; index<MAX_BLOCK_COUNT; index++)
|
||||
mMemoryBlock[index] = 0;
|
||||
|
||||
mMemoryBlockCount = 0;
|
||||
mObjectsAllocated = 0;
|
||||
mObjectCount = 0;
|
||||
mUnusedList = 0;
|
||||
|
||||
mBytesAllocated = 0;
|
||||
|
||||
Allocate(size);
|
||||
}
|
||||
|
||||
~CObjectAllocator()
|
||||
{
|
||||
for (uint32 index=0; index<MAX_BLOCK_COUNT; index++)
|
||||
delete[] mMemoryBlock[index];
|
||||
}
|
||||
|
||||
TYPE *Construct()
|
||||
{
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Lock();
|
||||
#endif
|
||||
if (!mUnusedList)
|
||||
Allocate(mObjectCount);
|
||||
|
||||
Node *node = mUnusedList;
|
||||
mUnusedList = mUnusedList->next;
|
||||
|
||||
new (node) TYPE;
|
||||
|
||||
mObjectCount++;
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Unlock();
|
||||
#endif
|
||||
return (TYPE *)node;
|
||||
}
|
||||
|
||||
TYPE *Construct(const TYPE& object)
|
||||
{
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Lock();
|
||||
#endif
|
||||
if (!mUnusedList)
|
||||
Allocate(mObjectCount);
|
||||
|
||||
Node *node = mUnusedList;
|
||||
mUnusedList = mUnusedList->next;
|
||||
|
||||
new (node) TYPE(object);
|
||||
|
||||
mObjectCount++;
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Unlock();
|
||||
#endif
|
||||
return (TYPE *)node;
|
||||
}
|
||||
|
||||
void Destroy(TYPE *object)
|
||||
{
|
||||
if (object == NULL)
|
||||
return;
|
||||
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Lock();
|
||||
#endif
|
||||
object->~TYPE();
|
||||
|
||||
Node *node = reinterpret_cast<Node *>(object);
|
||||
|
||||
node->next = mUnusedList;
|
||||
mUnusedList = node;
|
||||
|
||||
mObjectCount--;
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
mMutex.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
TYPE *FastConstruct()
|
||||
{
|
||||
if (!mUnusedList)
|
||||
Allocate(mObjectCount);
|
||||
|
||||
Node *node = mUnusedList;
|
||||
mUnusedList = mUnusedList->next;
|
||||
|
||||
new (node) TYPE;
|
||||
|
||||
mObjectCount++;
|
||||
return (TYPE *)node;
|
||||
}
|
||||
|
||||
TYPE *FastConstruct(const TYPE& object)
|
||||
{
|
||||
if (!mUnusedList)
|
||||
Allocate(mObjectCount);
|
||||
|
||||
Node *node = mUnusedList;
|
||||
mUnusedList = mUnusedList->next;
|
||||
|
||||
new (node) TYPE(object);
|
||||
|
||||
mObjectCount++;
|
||||
return (TYPE *)node;
|
||||
}
|
||||
|
||||
void FastDestroy(TYPE *object)
|
||||
{
|
||||
if (object == NULL)
|
||||
return;
|
||||
|
||||
object->~TYPE();
|
||||
|
||||
Node *node = reinterpret_cast<Node *>(object);
|
||||
|
||||
node->next = mUnusedList;
|
||||
mUnusedList = node;
|
||||
|
||||
mObjectCount--;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Node
|
||||
{
|
||||
char buffer[sizeof(TYPE)];
|
||||
Node* next;
|
||||
};
|
||||
|
||||
bool Allocate(uint32 size)
|
||||
{
|
||||
if (mMemoryBlockCount == MAX_BLOCK_COUNT)
|
||||
return false;
|
||||
|
||||
Node* newMemoryBlock = new Node[size];
|
||||
mBytesAllocated += size * sizeof(Node);
|
||||
|
||||
for (uint32 i=0; i<size-1; i++)
|
||||
newMemoryBlock[i].next = &newMemoryBlock[i+1];
|
||||
newMemoryBlock[size-1].next = mUnusedList;
|
||||
|
||||
mUnusedList = newMemoryBlock;
|
||||
mMemoryBlock[mMemoryBlockCount++] = newMemoryBlock;
|
||||
mObjectsAllocated += size;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Node* mMemoryBlock[MAX_BLOCK_COUNT];
|
||||
uint32 mMemoryBlockCount;
|
||||
uint32 mObjectsAllocated;
|
||||
uint32 mObjectCount;
|
||||
Node* mUnusedList;
|
||||
#ifdef USE_ALLOCATOR_MUTEX
|
||||
CMutex mMutex;
|
||||
#endif
|
||||
|
||||
uint64 mBytesAllocated;
|
||||
};
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // _TEMPLATE_CBLOCKALLOC_H
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef BASE_THREAD_H
|
||||
#define BASE_THREAD_H
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32/Thread.h"
|
||||
|
||||
#elif linux
|
||||
|
||||
#include "linux/Thread.h"
|
||||
|
||||
#elif sparc
|
||||
|
||||
#include "solaris/Thread.h"
|
||||
|
||||
#else
|
||||
|
||||
#error /Base/Thread.h: Undefine platform type
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BASE_THREAD_H
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef BASE_TYPES_H
|
||||
#define BASE_TYPES_H
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32/Types.h"
|
||||
|
||||
#elif linux
|
||||
|
||||
#include "linux/Types.h"
|
||||
|
||||
#elif sparc
|
||||
|
||||
#include "solaris/Types.h"
|
||||
|
||||
#else
|
||||
|
||||
#error /Base/Types.h: Undefine platform type
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,664 @@
|
||||
#ifndef BASE__UCS2_H
|
||||
#define BASE__UCS2_H
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Base/Archive.h"
|
||||
|
||||
|
||||
namespace ucs2
|
||||
{
|
||||
|
||||
class string
|
||||
{
|
||||
public:
|
||||
typedef unsigned short char_type;
|
||||
typedef unsigned size_type;
|
||||
|
||||
public:
|
||||
string();
|
||||
string(const string & copy);
|
||||
string(const char * copy);
|
||||
string(const char_type * copy);
|
||||
explicit string(const std::string & copy);
|
||||
~string();
|
||||
|
||||
string & operator=(const char * rhs);
|
||||
string & operator=(const std::string & rhs);
|
||||
string & operator=(const char_type * rhs);
|
||||
string & operator=(const string & rhs);
|
||||
|
||||
string & operator+=(const char * rhs);
|
||||
string & operator+=(const std::string & rhs);
|
||||
string & operator+=(const char_type * rhs);
|
||||
string & operator+=(const string & rhs);
|
||||
|
||||
const char_type & at(size_type index) const;
|
||||
char_type & at(size_type index);
|
||||
|
||||
const char_type & operator[](size_type index) const;
|
||||
char_type & operator[](size_type index);
|
||||
|
||||
bool operator==(const string & rhs) const;
|
||||
bool operator!=(const string & rhs) const;
|
||||
bool operator<(const string & rhs) const;
|
||||
bool operator<=(const string & rhs) const;
|
||||
bool operator>(const string & rhs) const;
|
||||
bool operator>=(const string & rhs) const;
|
||||
|
||||
string & assign(const char_type * rhs);
|
||||
string & assign(const char_type * rhs, size_type count);
|
||||
string & assign(const string & rhs, size_type position, size_type count);
|
||||
string & assign(const string & rhs);
|
||||
string & assign(size_type count, char_type c);
|
||||
string & assign(const char_type * first, const char_type * last);
|
||||
|
||||
string & append(const char_type * rhs);
|
||||
string & append(const char_type * rhs, size_type count);
|
||||
string & append(const string & rhs, size_type position, size_type count);
|
||||
string & append(const string & rhs);
|
||||
string & append(size_type count, char_type c);
|
||||
string & append(const char_type * first, const char_type * last);
|
||||
|
||||
std::string narrow() const;
|
||||
const char_type * c_str() const;
|
||||
const char_type * data() const;
|
||||
|
||||
size_type length() const;
|
||||
size_type size() const;
|
||||
size_type max_size() const;
|
||||
void resize(size_type n, char_type c = 0x0032);
|
||||
size_type capacity() const;
|
||||
void reserve(size_type n = 0);
|
||||
bool empty() const;
|
||||
|
||||
private:
|
||||
size_type mLength;
|
||||
std::vector<char_type> mData;
|
||||
static char_type mOutOfRangeCharacter;
|
||||
};
|
||||
|
||||
inline char WideToNarrow(string::char_type c) { return (char)c; }
|
||||
inline string::char_type NarrowToWide(char c) { return (string::char_type)c; }
|
||||
|
||||
string::char_type string::mOutOfRangeCharacter(0);
|
||||
|
||||
////////////////////////////////////////
|
||||
// default constructor allocates 8 characters and sets length to zero
|
||||
inline string::string() :
|
||||
mLength(0),
|
||||
mData(8,0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// target string is a null-terminated C string
|
||||
inline string::string(const char * copy) :
|
||||
mLength(0),
|
||||
mData(8,0)
|
||||
{
|
||||
// (1) protect from null pointer
|
||||
if (!copy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// (2) linear copy the string, must reserve before each character
|
||||
// because the string length is unknown
|
||||
while (*copy)
|
||||
{
|
||||
reserve(mLength+1);
|
||||
mData[mLength++] = *copy++;
|
||||
}
|
||||
// (3) ensure null termination
|
||||
mData[mLength]=0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// target string is a C string that may or may not include null characters
|
||||
inline string::string(const std::string & copy) :
|
||||
mLength(copy.length()),
|
||||
mData(8,0)
|
||||
{
|
||||
// (1) ensure we have the storage for the entire string
|
||||
reserve(mLength);
|
||||
// (2) perform transform to copy the narrow string to our
|
||||
// wide string
|
||||
std::transform(copy.begin(), copy.end(), mData.begin(), NarrowToWide);
|
||||
// (3) ensure null termination
|
||||
mData[mLength] = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// target string is a wide null-terminated C string
|
||||
inline string::string(const char_type * copy) :
|
||||
mLength(0),
|
||||
mData(8,0)
|
||||
{
|
||||
// (1) protect from null pointer
|
||||
if (!copy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// (2) linear copy the string, must reserve before each character
|
||||
// because the string length is unknown
|
||||
while (*copy)
|
||||
{
|
||||
reserve(mLength+1);
|
||||
mData[mLength++] = *copy++;
|
||||
}
|
||||
// (3) ensure null termination
|
||||
mData[mLength]=0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// copy constructor
|
||||
inline string::string(const string & copy) :
|
||||
mLength(copy.mLength),
|
||||
mData(8,0)
|
||||
{
|
||||
reserve(mLength);
|
||||
mData.assign(copy.mData.begin(), copy.mData.begin()+copy.mLength+1);
|
||||
}
|
||||
|
||||
inline string::~string()
|
||||
{
|
||||
}
|
||||
|
||||
inline string & string::operator=(const char * rhs)
|
||||
{
|
||||
mLength = 0;
|
||||
// (1) protect from null pointer
|
||||
if (!rhs)
|
||||
{
|
||||
mData[0] = 0;
|
||||
return *this;
|
||||
}
|
||||
// (2) linear copy the string, must reserve before each character
|
||||
// because the string length is unknown
|
||||
while (*rhs)
|
||||
{
|
||||
reserve(mLength+1);
|
||||
mData[mLength++] = *rhs++;
|
||||
}
|
||||
// (3) ensure null termination
|
||||
mData[mLength]=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::operator=(const std::string & rhs)
|
||||
{
|
||||
mLength = rhs.length();
|
||||
// (1) ensure we have the storage for the entire string
|
||||
reserve(mLength);
|
||||
// (2) perform transform to copy the narrow string to our
|
||||
// wide string
|
||||
std::transform(rhs.begin(), rhs.end(), mData.begin(), NarrowToWide);
|
||||
// (3) ensure null termination
|
||||
mData[mLength] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::operator=(const char_type * rhs)
|
||||
{
|
||||
mLength = 0;
|
||||
// (1) protect from null pointer
|
||||
if (!rhs)
|
||||
{
|
||||
mData[0] = 0;
|
||||
return *this;
|
||||
}
|
||||
// (2) linear copy the string, must reserve before each character
|
||||
// because the string length is unknown
|
||||
while (*rhs)
|
||||
{
|
||||
reserve(mLength+1);
|
||||
mData[mLength++] = *rhs++;
|
||||
}
|
||||
// (3) ensure null termination
|
||||
mData[mLength]=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::operator=(const string & rhs)
|
||||
{
|
||||
// (1) protect from assigning to self
|
||||
if (&rhs != this)
|
||||
{
|
||||
mLength = rhs.mLength;
|
||||
reserve(mLength);
|
||||
mData.assign(rhs.mData.begin(), rhs.mData.begin()+rhs.mLength+1);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::operator+=(const char * rhs)
|
||||
{
|
||||
// (1) protect from null pointer
|
||||
if (!rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
// (2) linear copy the string, must reserve before each character
|
||||
// because the string length is unknown
|
||||
while (*rhs)
|
||||
{
|
||||
reserve(mLength+1);
|
||||
mData[mLength++] = *rhs++;
|
||||
}
|
||||
// (3) ensure null termination
|
||||
mData[mLength]=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::operator+=(const std::string & rhs)
|
||||
{
|
||||
// (1) ensure we have the storage for the entire string
|
||||
reserve(mLength+rhs.length());
|
||||
// (2) perform transform to copy the narrow string to our
|
||||
// wide string
|
||||
std::transform(rhs.begin(), rhs.end(), mData.begin()+mLength, NarrowToWide);
|
||||
// (3) ensure null termination
|
||||
mLength += rhs.length();
|
||||
mData[mLength] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::operator+=(const char_type * rhs)
|
||||
{
|
||||
// (1) protect from null pointer
|
||||
if (!rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
// (2) linear copy the string, must reserve before each character
|
||||
// because the string length is unknown
|
||||
while (*rhs)
|
||||
{
|
||||
reserve(mLength+1);
|
||||
mData[mLength++] = *rhs++;
|
||||
}
|
||||
// (3) ensure null termination
|
||||
mData[mLength]=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::operator+=(const string & rhs)
|
||||
{
|
||||
reserve(mLength+rhs.mLength);
|
||||
std::copy(rhs.mData.begin(), rhs.mData.begin()+rhs.mLength+1, mData.begin()+mLength);
|
||||
mLength += rhs.mLength;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const string::char_type & string::at(string::size_type index) const
|
||||
{
|
||||
return (index > mLength) ? mOutOfRangeCharacter : mData[index];
|
||||
}
|
||||
|
||||
inline string::char_type & string::at(string::size_type index)
|
||||
{
|
||||
return (index > mLength) ? mOutOfRangeCharacter : mData[index];
|
||||
}
|
||||
|
||||
inline const string::char_type & string::operator[](string::size_type index) const
|
||||
{
|
||||
return (index > mLength) ? mOutOfRangeCharacter : mData[index];
|
||||
}
|
||||
|
||||
inline string::char_type & string::operator[](string::size_type index)
|
||||
{
|
||||
return (index > mLength) ? mOutOfRangeCharacter : mData[index];
|
||||
}
|
||||
|
||||
inline bool string::operator==(const string & rhs) const
|
||||
{
|
||||
if (mLength != rhs.mLength)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*mLength) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool string::operator!=(const string & rhs) const
|
||||
{
|
||||
if (mLength != rhs.mLength)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*mLength) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool string::operator<(const string & rhs) const
|
||||
{
|
||||
if (mLength <= rhs.mLength)
|
||||
{
|
||||
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*mLength) < 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*rhs.mLength) < 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool string::operator<=(const string & rhs) const
|
||||
{
|
||||
if (mLength <= rhs.mLength)
|
||||
{
|
||||
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*mLength) <= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*rhs.mLength) <= 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool string::operator>(const string & rhs) const
|
||||
{
|
||||
if (mLength <= rhs.mLength)
|
||||
{
|
||||
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*mLength) > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*rhs.mLength) > 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool string::operator>=(const string & rhs) const
|
||||
{
|
||||
if (mLength <= rhs.mLength)
|
||||
{
|
||||
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*mLength) >= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*rhs.mLength) >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline string & string::assign(const char_type * rhs)
|
||||
{
|
||||
mLength = 0;
|
||||
// (1) protect from null pointer
|
||||
if (!rhs)
|
||||
{
|
||||
mData[0] = 0;
|
||||
return *this;
|
||||
}
|
||||
// (2) linear copy the string, must reserve before each character
|
||||
// because the string length is unknown
|
||||
while (*rhs)
|
||||
{
|
||||
reserve(mLength+1);
|
||||
mData[mLength++] = *rhs++;
|
||||
}
|
||||
// (3) ensure null termination
|
||||
mData[mLength]=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::assign(const char_type * rhs, size_type count)
|
||||
{
|
||||
mLength = 0;
|
||||
// (1) protect from null pointer
|
||||
if (!rhs)
|
||||
{
|
||||
mData[0] = 0;
|
||||
return *this;
|
||||
}
|
||||
// (2) linear copy the string, must reserve before each character
|
||||
// because the string length is unknown
|
||||
while (count--)
|
||||
{
|
||||
reserve(mLength+1);
|
||||
mData[mLength++] = *rhs++;
|
||||
}
|
||||
// (3) ensure null termination
|
||||
mData[mLength]=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::assign(const string & rhs, size_type position, size_type count)
|
||||
{
|
||||
// (1) protect from assigning to self
|
||||
if (&rhs != this)
|
||||
{
|
||||
mLength = count;
|
||||
reserve(mLength);
|
||||
mData.assign(rhs.mData.begin()+position, rhs.mData.begin()+position+count+1);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::assign(const string & rhs)
|
||||
{
|
||||
// (1) protect from assigning to self
|
||||
if (&rhs != this)
|
||||
{
|
||||
mLength = rhs.mLength;
|
||||
reserve(mLength);
|
||||
mData.assign(rhs.mData.begin(), rhs.mData.begin()+rhs.mLength+1);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::assign(size_type count, char_type c)
|
||||
{
|
||||
mLength = count;
|
||||
reserve(mLength);
|
||||
std::fill(mData.begin(), mData.end(), c);
|
||||
mData[mLength]=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::assign(const char_type * first, const char_type * last)
|
||||
{
|
||||
mLength = 0;
|
||||
// (1) protect from null pointer
|
||||
if (!first || !last)
|
||||
{
|
||||
mData[0] = 0;
|
||||
return *this;
|
||||
}
|
||||
// (2) linear copy the string, must reserve before each character
|
||||
// because the string length is unknown
|
||||
while (first != last)
|
||||
{
|
||||
reserve(mLength+1);
|
||||
mData[mLength++] = *first++;
|
||||
}
|
||||
// (3) ensure null termination
|
||||
mData[mLength]=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::append(const char_type * rhs)
|
||||
{
|
||||
// (1) protect from null pointer
|
||||
if (!rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
// (2) linear copy the string, must reserve before each character
|
||||
// because the string length is unknown
|
||||
while (*rhs)
|
||||
{
|
||||
reserve(mLength+1);
|
||||
mData[mLength++] = *rhs++;
|
||||
}
|
||||
// (3) ensure null termination
|
||||
mData[mLength]=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::append(const char_type * rhs, size_type count)
|
||||
{
|
||||
// (1) protect from null pointer
|
||||
if (!rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
// (2) linear copy the string, must reserve before each character
|
||||
// because the string length is unknown
|
||||
while (count--)
|
||||
{
|
||||
reserve(mLength+1);
|
||||
mData[mLength++] = *rhs++;
|
||||
}
|
||||
// (3) ensure null termination
|
||||
mData[mLength]=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::append(const string & rhs, size_type position, size_type count)
|
||||
{
|
||||
// (1) protect from invalid position value
|
||||
if (rhs.mLength <= position)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
// (2) make sure we copy count charatcers, or to the end of the string
|
||||
if (rhs.mLength < position+count)
|
||||
{
|
||||
count = rhs.mLength-position;
|
||||
}
|
||||
// (3) perform copy
|
||||
reserve(mLength+count);
|
||||
std::copy(rhs.mData.begin()+position, rhs.mData.begin()+position+count+1, mData.begin()+mLength);
|
||||
mLength += count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::append(const string & rhs)
|
||||
{
|
||||
// (1) perform copy
|
||||
reserve(mLength+rhs.mLength);
|
||||
std::copy(rhs.mData.begin(), rhs.mData.begin()+rhs.mLength+1, mData.begin()+mLength);
|
||||
mLength += rhs.mLength;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::append(size_type count, char_type c)
|
||||
{
|
||||
reserve(mLength+count);
|
||||
std::fill(mData.begin()+mLength, mData.begin()+mLength+count, c);
|
||||
mLength += count;
|
||||
mData[mLength]=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline string & string::append(const char_type * first, const char_type * last)
|
||||
{
|
||||
// (1) protect from null pointer
|
||||
if (!first || !last)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
// (2) linear copy the string, must reserve before each character
|
||||
// because the string length is unknown
|
||||
while (first != last)
|
||||
{
|
||||
reserve(mLength+1);
|
||||
mData[mLength++] = *first++;
|
||||
}
|
||||
// (3) ensure null termination
|
||||
mData[mLength]=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline std::string string::narrow() const
|
||||
{
|
||||
std::string narrow;
|
||||
narrow.resize(mLength);
|
||||
std::transform(mData.begin(), mData.begin()+mLength+1, narrow.begin(), WideToNarrow);
|
||||
return narrow;
|
||||
}
|
||||
|
||||
inline const string::char_type * string::c_str() const
|
||||
{
|
||||
return &mData[0];
|
||||
}
|
||||
|
||||
inline const string::char_type * string::data() const
|
||||
{
|
||||
return &mData[0];
|
||||
}
|
||||
|
||||
inline string::size_type string::length() const
|
||||
{
|
||||
return mLength;
|
||||
}
|
||||
|
||||
inline string::size_type string::size() const
|
||||
{
|
||||
return mLength;
|
||||
}
|
||||
|
||||
inline void string::resize(string::size_type n, string::char_type c)
|
||||
{
|
||||
reserve(n);
|
||||
|
||||
while (mLength<n)
|
||||
{
|
||||
mData[mLength++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
inline string::size_type string::capacity() const
|
||||
{
|
||||
return mData.size()-1;
|
||||
}
|
||||
|
||||
inline void string::reserve(string::size_type n)
|
||||
{
|
||||
while (n > capacity())
|
||||
mData.resize((capacity()+1)*2,0x0000);
|
||||
}
|
||||
|
||||
inline bool string::empty() const
|
||||
{
|
||||
return mLength == 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
inline void get(ByteStream::ReadIterator & source, ucs2::string & target)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
get(source, size);
|
||||
|
||||
const unsigned char * const buf = source.getBuffer();
|
||||
const ucs2::string::char_type * const ubuf = reinterpret_cast<const ucs2::string::char_type *>(buf);
|
||||
|
||||
target.assign(ubuf, ubuf + size);
|
||||
|
||||
const unsigned int readSize = size * sizeof(ucs2::string::char_type);
|
||||
source.advance(readSize);
|
||||
}
|
||||
|
||||
inline void put(ByteStream & target, const ucs2::string & source)
|
||||
{
|
||||
const unsigned int size = source.size();
|
||||
put(target, size);
|
||||
put(target, (const unsigned char *)source.data(), size*sizeof(ucs2::string::char_type));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#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
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
#include "../BlockAllocator.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
BlockAllocator::BlockAllocator()
|
||||
{
|
||||
for(unsigned i = 0; i < 31; i++)
|
||||
{
|
||||
m_blocks[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BlockAllocator::~BlockAllocator()
|
||||
{
|
||||
// free all allocated memory blocks
|
||||
for(unsigned i = 0; i < 31; i++)
|
||||
{
|
||||
while(m_blocks[i] != NULL)
|
||||
{
|
||||
unsigned *tmp = m_blocks[i];
|
||||
m_blocks[i] = (unsigned *)*m_blocks[i];
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate a block that is the next power of two greater than the # of bytes passed.
|
||||
// 33 bytes yields a 64 byte block of memory and so forth.
|
||||
|
||||
void *BlockAllocator::getBlock(unsigned bytes)
|
||||
{
|
||||
unsigned accum = 16, bits = 16;
|
||||
unsigned *handle = NULL;
|
||||
|
||||
// Perform a binary search looking for the highest bit.
|
||||
|
||||
while(bits != 0)
|
||||
{
|
||||
// If bytes is less than the bit we're testing for, subtract half
|
||||
// from the bit value and repeat
|
||||
if(bytes < (unsigned)(1 << accum))
|
||||
{
|
||||
bits /= 2;
|
||||
accum -= bits;
|
||||
}
|
||||
// If bytes is greater than the bit we're testing for, add half
|
||||
// from the but value and repeat
|
||||
else if(bytes > (unsigned)(1 << accum))
|
||||
{
|
||||
bits /= 2;
|
||||
accum += bits;
|
||||
}
|
||||
// Got lucky and hit the value dead on
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// At this point accum contains the most significant bit index, increment
|
||||
accum++;
|
||||
if(accum < 2)
|
||||
{
|
||||
accum = 2;
|
||||
}
|
||||
|
||||
// Note that when memory is actually allocated, 8 extra bytes will be allocated.at the front
|
||||
// The first integer is the address of the next block of memory when the block is in the allocator
|
||||
// The second integer is the bit length of the block
|
||||
// Memory is allocated on 4 byte boundaries to sidestep byte alignment problems
|
||||
|
||||
|
||||
// Check if the allocator already has a block of that size
|
||||
if(m_blocks[accum] == 0)
|
||||
{
|
||||
// remove the pre allocated block from the linked list
|
||||
handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned));
|
||||
handle[1] = accum;
|
||||
handle[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate a new block
|
||||
handle = m_blocks[accum];
|
||||
m_blocks[accum] = (unsigned *)handle[0];
|
||||
handle[0] = 0;
|
||||
}
|
||||
// return a pointer that skips over the header used for the allocator's purposes
|
||||
return(handle + 2);
|
||||
}
|
||||
|
||||
void BlockAllocator::returnBlock(unsigned *handle)
|
||||
{
|
||||
// C++ allows for safe deletion of a NULL pointer
|
||||
if(handle)
|
||||
{
|
||||
// Update the allocator linked list, insert this entry at the head
|
||||
*(handle - 2) = (unsigned)m_blocks[*(handle - 1)];
|
||||
// Add this entry to the proper linked list node
|
||||
m_blocks[*(handle - 1)] = (handle - 2);
|
||||
}
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
////////////////////////////////////////
|
||||
// Event.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CEvent class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#if defined(_REENTRANT)
|
||||
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CEvent::CEvent() :
|
||||
mMutex(),
|
||||
mCond(),
|
||||
mThreadCount(0)
|
||||
{
|
||||
pthread_mutex_init(&mMutex, NULL);
|
||||
pthread_cond_init(&mCond, NULL);
|
||||
}
|
||||
|
||||
CEvent::~CEvent()
|
||||
{
|
||||
pthread_cond_destroy(&mCond);
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
}
|
||||
|
||||
bool CEvent::Signal()
|
||||
{
|
||||
pthread_mutex_lock(&mMutex);
|
||||
if (mThreadCount == 0)
|
||||
mThreadCount = SIGNALED;
|
||||
pthread_cond_signal(&mCond);
|
||||
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 CEvent::Wait(uint32 timeout)
|
||||
{
|
||||
int result;
|
||||
|
||||
pthread_mutex_lock(&mMutex);
|
||||
if (mThreadCount == SIGNALED)
|
||||
{
|
||||
mThreadCount = 0;
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
|
||||
return eWAIT_SIGNAL;
|
||||
}
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
mThreadCount++;
|
||||
result = pthread_cond_wait(&mCond, &mMutex);
|
||||
mThreadCount--;
|
||||
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct timeval now;
|
||||
struct timespec abs_timeout;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
abs_timeout.tv_sec = now.tv_sec + timeout/1000;
|
||||
abs_timeout.tv_nsec = now.tv_usec * 1000 + (timeout%1000)*1000000;
|
||||
abs_timeout.tv_sec += abs_timeout.tv_nsec / 1000000000;
|
||||
abs_timeout.tv_nsec %= 1000000000;
|
||||
|
||||
mThreadCount++;
|
||||
result = pthread_cond_timedwait(&mCond, &mMutex, &abs_timeout);
|
||||
mThreadCount--;
|
||||
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
|
||||
if (result == 0 || result == EINTR)
|
||||
return eWAIT_SIGNAL;
|
||||
else if (result == ETIMEDOUT)
|
||||
return eWAIT_TIMEOUT;
|
||||
else
|
||||
return eWAIT_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_REENTRANT)
|
||||
@@ -0,0 +1,74 @@
|
||||
////////////////////////////////////////
|
||||
// Event.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CEvent class that encapsulates the functionality of a
|
||||
// single-locking semaphore.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_EVENT_H
|
||||
#define BASE_LINUX_EVENT_H
|
||||
|
||||
#if !defined(_REENTRANT)
|
||||
# pragma message( "Excluding Base::CEvent - requires multi-threaded compile. (_REENTRANT)" )
|
||||
#else
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CEvent
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates the functionality of a singal-locking semaphore.
|
||||
// This class is valuable for thread syncronization when a thead's
|
||||
// execution needs to be dependent upon another thread.
|
||||
//
|
||||
// Public Methods:
|
||||
// Signal() : Signals a thread that has called Wait() so that it can
|
||||
// continue execution. This function returns true if the waiting
|
||||
// thread was signalled successfully, otherwise false is returned.
|
||||
// Wait() : Halts the calling thread's execution indefinately until
|
||||
// a Singal() call is made by an external thread. If the thread is
|
||||
// successfully signalled, the function returns eWAIT_SIGNAL. If
|
||||
// timeout period expires without a signal, eWAIT_TIMEOUT is returned.
|
||||
// If the function fails, eWAIT_ERROR is returned.
|
||||
//
|
||||
class CEvent
|
||||
{
|
||||
public:
|
||||
CEvent();
|
||||
virtual ~CEvent();
|
||||
|
||||
bool Signal();
|
||||
int32 Wait(uint32 timeout = 0);
|
||||
|
||||
public:
|
||||
enum { eWAIT_ERROR, eWAIT_SIGNAL, eWAIT_TIMEOUT };
|
||||
enum { SIGNALED = -1 };
|
||||
private:
|
||||
pthread_mutex_t mMutex;
|
||||
pthread_cond_t mCond;
|
||||
int mThreadCount;
|
||||
};
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_LINUX_EVENT_H
|
||||
@@ -0,0 +1,40 @@
|
||||
////////////////////////////////////////
|
||||
// Mutex.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CMutex class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#if defined(_REENTRANT)
|
||||
|
||||
|
||||
#include "Mutex.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CMutex::CMutex()
|
||||
{
|
||||
mInitialized = (pthread_mutex_init(&mMutex, 0) == 0);
|
||||
}
|
||||
|
||||
CMutex::~CMutex()
|
||||
{
|
||||
if (mInitialized)
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // #if defined(_REENTRANT)
|
||||
@@ -0,0 +1,79 @@
|
||||
////////////////////////////////////////
|
||||
// Mutex.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CMutex class that encapsulates the functionality of a
|
||||
// mutually-exclusive device.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_MUTEX_H
|
||||
#define BASE_LINUX_MUTEX_H
|
||||
|
||||
#if !defined(_REENTRANT)
|
||||
# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_REENTRANT)" )
|
||||
#else
|
||||
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CMutex
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates the functionality of a mutually-exclusive device.
|
||||
// This class is valuable for protecting against race conditions
|
||||
// within threaded applications. The CMutex class can be used to
|
||||
// only allow a single thread to run within a specified code
|
||||
// segment at a time.
|
||||
//
|
||||
// Public Methods:
|
||||
// Lock() : Locks the mutex. If the mutex is already locked, the
|
||||
// operating system will block the calling thread until another
|
||||
// thread has unlocked the mutex.
|
||||
// Unlock() : Unlocks the mutex.
|
||||
//
|
||||
class CMutex
|
||||
{
|
||||
public:
|
||||
CMutex();
|
||||
~CMutex();
|
||||
|
||||
void Lock();
|
||||
void Unlock();
|
||||
private:
|
||||
pthread_mutex_t mMutex;
|
||||
bool mInitialized;
|
||||
};
|
||||
|
||||
inline void CMutex::Lock(void)
|
||||
{
|
||||
if (mInitialized)
|
||||
pthread_mutex_lock(&mMutex);
|
||||
}
|
||||
|
||||
inline void CMutex::Unlock(void)
|
||||
{
|
||||
if (mInitialized)
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_LINUX_MUTEX_H
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
////////////////////////////////////////
|
||||
// Platform.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the global functionality declaired in Platform.h.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#include <ctype.h>
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
// Implementation of microsoft strlwr extension
|
||||
// This non-ANSI function is not supported under UNIX
|
||||
void _strlwr(char * s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
*s = tolower(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of microsoft strlwr extension
|
||||
// This non-ANSI function is not supported under UNIX
|
||||
void _strupr(char * s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CTimer::CTimer() :
|
||||
mTimer(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
////////////////////////////////////////
|
||||
// Platform.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Include relevent system headers that are platform specific.
|
||||
// 2. Declair global platform specific functionality.
|
||||
// 3. Include primative type definitions
|
||||
//
|
||||
// Global Functions:
|
||||
// getTimer() : Return the current high resolution clock count.
|
||||
// getTimerFrequency() : Return the frequency of the high resolution clock.
|
||||
// sleep() : Voluntarily relinquish timeslice of the calling thread for a
|
||||
// specified number of milliseconds.
|
||||
// strlwr() : Alters the contents of a string, making it all lower-case.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_PLATFORM_H
|
||||
#define BASE_LINUX_PLATFORM_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <sys/errno.h>
|
||||
#include <pthread.h>
|
||||
#include <resolv.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
uint64 getTimer(void);
|
||||
uint64 getTimerFrequency(void);
|
||||
void sleep(uint32 ms);
|
||||
|
||||
inline uint64 getTimer(void)
|
||||
{
|
||||
uint64 t;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, 0);
|
||||
t = tv.tv_sec;
|
||||
t = t * 1000000;
|
||||
t += tv.tv_usec;
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint64 getTimerFrequency(void)
|
||||
{
|
||||
uint64 f = 1000000;
|
||||
return f;
|
||||
}
|
||||
|
||||
inline void sleep(uint32 ms)
|
||||
{
|
||||
usleep(static_cast<unsigned long>(ms * 1000));
|
||||
}
|
||||
|
||||
void _strlwr(char * s);
|
||||
void _strupr(char * s);
|
||||
|
||||
|
||||
class CTimer
|
||||
{
|
||||
public:
|
||||
CTimer();
|
||||
|
||||
void Set(uint32 seconds);
|
||||
void Signal();
|
||||
bool Expired();
|
||||
|
||||
private:
|
||||
uint32 mTimer;
|
||||
};
|
||||
|
||||
inline void CTimer::Set(uint32 interval)
|
||||
{
|
||||
mTimer = (uint32)time(0) + interval;
|
||||
}
|
||||
|
||||
inline void CTimer::Signal()
|
||||
{
|
||||
mTimer = 0;
|
||||
}
|
||||
|
||||
inline bool CTimer::Expired()
|
||||
{
|
||||
return (mTimer <= (uint32)time(0));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // BASE_LINUX_PLATFORM_H
|
||||
@@ -0,0 +1,274 @@
|
||||
////////////////////////////////////////
|
||||
// Thread.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CThread class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#if defined(_REENTRANT)
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include "Thread.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
void *threadProc(void *threadPtr)
|
||||
{
|
||||
CThread &thread = *((CThread*)threadPtr);
|
||||
thread.mThreadActive = true;
|
||||
thread.ThreadProc();
|
||||
thread.mThreadActive = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CThread::CThread()
|
||||
{
|
||||
mThreadID = 0;
|
||||
mThreadActive = false;
|
||||
mThreadContinue = false;
|
||||
}
|
||||
|
||||
CThread::~CThread()
|
||||
{
|
||||
StopThread();
|
||||
}
|
||||
|
||||
void CThread::StartThread()
|
||||
{
|
||||
mThreadContinue = true;
|
||||
pthread_create(&mThreadID,0,threadProc,this);
|
||||
while (!IsThreadActive())
|
||||
Base::sleep(1);
|
||||
}
|
||||
|
||||
int32 CThread::StopThread(int timeout)
|
||||
{
|
||||
timeout += time(0);
|
||||
|
||||
mThreadContinue = false;
|
||||
while (mThreadActive && time(0)<timeout)
|
||||
sleep(1);
|
||||
if (mThreadActive)
|
||||
{
|
||||
mThreadActive = false;
|
||||
return eSTOP_TIMEOUT;
|
||||
}
|
||||
return eSTOP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CThreadPool::CMember::CMember(CThreadPool * parent) :
|
||||
mParent(parent),
|
||||
mFunction(NULL),
|
||||
mArgument(NULL),
|
||||
mSemaphore()
|
||||
{
|
||||
StartThread();
|
||||
}
|
||||
|
||||
CThreadPool::CMember::~CMember()
|
||||
{
|
||||
}
|
||||
|
||||
void CThreadPool::CMember::Destroy()
|
||||
{
|
||||
mThreadContinue = false;
|
||||
mSemaphore.Signal();
|
||||
}
|
||||
|
||||
bool CThreadPool::CMember::Execute(void( *function )( void * ), void * arg)
|
||||
{
|
||||
if (mFunction)
|
||||
return false;
|
||||
|
||||
mArgument = arg;
|
||||
mFunction = function;
|
||||
mSemaphore.Signal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CThreadPool::CMember::ThreadProc()
|
||||
{
|
||||
mParent->OnStartup(this);
|
||||
while (mThreadContinue)
|
||||
{
|
||||
mParent->OnIdle(this);
|
||||
mSemaphore.Wait(mParent->GetTimeOut()*1000);
|
||||
|
||||
if (mFunction)
|
||||
{
|
||||
mFunction(mArgument);
|
||||
mArgument = NULL;
|
||||
mFunction = NULL;
|
||||
}
|
||||
else if (mParent->OnDestory(this))
|
||||
mThreadContinue = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CThreadPool::CThreadPool(uint32 maxThreads, uint32 minThreads, uint32 timeout) :
|
||||
mMutex(),
|
||||
mIdleMember(),
|
||||
mBusyMember(),
|
||||
mNullMember(),
|
||||
mThreadCount(0),
|
||||
mMaxThreads(maxThreads),
|
||||
mMinThreads(minThreads),
|
||||
mTimeOut(timeout)
|
||||
{
|
||||
if (mMaxThreads == 0) mMaxThreads = 1;
|
||||
if (mMinThreads == 0) mMinThreads = 1;
|
||||
if (mMinThreads > mMaxThreads) mMinThreads = mMaxThreads;
|
||||
|
||||
for (uint32 i=0; i<mMinThreads; i++)
|
||||
new CMember(this);
|
||||
}
|
||||
|
||||
CThreadPool::~CThreadPool()
|
||||
{
|
||||
set<CMember *>::iterator setIterator;
|
||||
|
||||
////////////////////////////////////////
|
||||
// (1) Destory all busy member threads
|
||||
mMutex.Lock();
|
||||
setIterator = mBusyMember.begin();
|
||||
while (setIterator != mBusyMember.end())
|
||||
(*setIterator++)->Destroy();
|
||||
mMutex.Unlock();
|
||||
|
||||
////////////////////////////////////////
|
||||
// (2) Destory all idle member threads
|
||||
while (mThreadCount)
|
||||
{
|
||||
mMutex.Lock();
|
||||
setIterator = mIdleMember.begin();
|
||||
while (setIterator != mIdleMember.end())
|
||||
(*setIterator++)->Destroy();
|
||||
mMutex.Unlock();
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (3) Delete the null member threads
|
||||
mMutex.Lock();
|
||||
while (!mNullMember.empty())
|
||||
{
|
||||
delete mNullMember.front();
|
||||
mNullMember.pop_front();
|
||||
}
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
bool CThreadPool::Execute(void( *function )( void * ), void * arg)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
////////////////////////////////////////
|
||||
// (1) If no idle members, return false to indicate that no threads
|
||||
// were available. If the thread count is below the max, create
|
||||
// a new thread.
|
||||
if (mIdleMember.empty())
|
||||
{
|
||||
if (mThreadCount < mMaxThreads)
|
||||
new CMember(this);
|
||||
mMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (2) Delete any null member threads.
|
||||
while (!mNullMember.empty())
|
||||
{
|
||||
delete mNullMember.front();
|
||||
mNullMember.pop_front();
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (3) Move the first idle thread to the busy set and signal the
|
||||
// thread to execute the specified function.
|
||||
CMember * member = *(mIdleMember.begin());
|
||||
mIdleMember.erase(member);
|
||||
mBusyMember.insert(member);
|
||||
member->Execute(function,arg);
|
||||
|
||||
mMutex.Unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 CThreadPool::GetTimeOut()
|
||||
{
|
||||
return mTimeOut;
|
||||
}
|
||||
|
||||
void CThreadPool::OnStartup(CMember * member)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
mThreadCount++;
|
||||
mIdleMember.insert(member);
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
void CThreadPool::OnIdle(CMember * member)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
mBusyMember.erase(member);
|
||||
mIdleMember.insert(member);
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
bool CThreadPool::OnDestory(CMember * member)
|
||||
{
|
||||
set<CMember *>::iterator setIterator;
|
||||
|
||||
mMutex.Lock();
|
||||
|
||||
bool result = (setIterator = mIdleMember.find(member)) != mIdleMember.end();
|
||||
if (result)
|
||||
{
|
||||
mNullMember.push_back(member);
|
||||
mIdleMember.erase(setIterator);
|
||||
mThreadCount--;
|
||||
}
|
||||
|
||||
mMutex.Unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_REENTRANT)
|
||||
@@ -0,0 +1,146 @@
|
||||
////////////////////////////////////////
|
||||
// Thread.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CThread class that encapsulates threading functionality.
|
||||
// This abstract base class in intended to be used to encapsulate
|
||||
// individual tasks that require threading in derived classes.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_THREAD_H
|
||||
#define BASE_LINUX_THREAD_H
|
||||
|
||||
#if !defined(_REENTRANT)
|
||||
# pragma message( "Excluding Base::CThread - requires multi-threaded compile. (_REENTRANT)" )
|
||||
#else
|
||||
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include "Platform.h"
|
||||
#include "Mutex.h"
|
||||
#include "Event.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CThread
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates threading functionality. Creating classes derived
|
||||
// from CThread provides an easy way to encapsulate tasks that require
|
||||
// their own thread.
|
||||
//
|
||||
// Public Methods:
|
||||
// StartThread() : Creates the low-level thread handle and begins executing
|
||||
// the CThread::ThreadProc() function within the new thread.
|
||||
// StopThread() : Signals the ThreadProc() function to stop executing using
|
||||
// the mThreadContinue member variable, and waits for the ThreadProc()
|
||||
// function to exit. By default, the function will block for a maximum
|
||||
// of 5 seconds before exiting without the thread halting.
|
||||
// IsThreadActive() : Returns true if the physical thread is still executing
|
||||
// within the ThreadProc() function, otherwise it returns false.
|
||||
// ThreadProc() : Pure-virtual function that will be executed when the StartThread()
|
||||
// function is called. Derived classes must implement this function. The
|
||||
// mThreadContinue member variable should be used internal the the ThreadProc()
|
||||
// function to indicate whether it should continue executing or exit.
|
||||
// Protected Attributes:
|
||||
// mThreadContinue : Boolean value indicating to the ThreadProc() function
|
||||
// whether to continue executing or to exit. If mThreadContinue is true,
|
||||
// ThreadProc() should continue, otherwise ThreadProc() should exit. It
|
||||
// left up to the derived class to implement a ThreadProc() function that
|
||||
// uses the mThreadContinue member.
|
||||
//
|
||||
//
|
||||
class CThread
|
||||
{
|
||||
friend void * threadProc(void *);
|
||||
|
||||
public:
|
||||
enum { eSTOP_SUCCESS, eSTOP_TIMEOUT };
|
||||
public:
|
||||
CThread();
|
||||
virtual ~CThread();
|
||||
|
||||
void StartThread();
|
||||
int32 StopThread(int timeout=5);
|
||||
bool IsThreadActive() { return mThreadActive; }
|
||||
|
||||
protected:
|
||||
virtual void ThreadProc() {}
|
||||
|
||||
protected:
|
||||
bool mThreadContinue;
|
||||
private:
|
||||
pthread_t mThreadID;
|
||||
bool mThreadActive;
|
||||
};
|
||||
|
||||
|
||||
class CThreadPool
|
||||
{
|
||||
private:
|
||||
class CMember : public CThread
|
||||
{
|
||||
public:
|
||||
CMember(CThreadPool * parent);
|
||||
virtual ~CMember();
|
||||
|
||||
bool Execute(void( *function )( void * ), void * arg);
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
virtual void ThreadProc();
|
||||
|
||||
private:
|
||||
CThreadPool * mParent;
|
||||
void( * mFunction )( void * );
|
||||
void * mArgument;
|
||||
CEvent mSemaphore;
|
||||
};
|
||||
friend class CMember;
|
||||
|
||||
public:
|
||||
CThreadPool(uint32 maxThreads, uint32 minThreads=1, uint32 timeout=15*60);
|
||||
~CThreadPool();
|
||||
|
||||
bool Execute(void( *function )( void * ), void * arg);
|
||||
|
||||
private:
|
||||
uint32 GetTimeOut();
|
||||
void OnStartup(CMember * member);
|
||||
void OnIdle(CMember * member);
|
||||
bool OnDestory(CMember * member);
|
||||
|
||||
private:
|
||||
CMutex mMutex;
|
||||
std::set<CMember *> mIdleMember;
|
||||
std::set<CMember *> mBusyMember;
|
||||
std::list<CMember *> mNullMember;
|
||||
uint32 mThreadCount;
|
||||
|
||||
uint32 mMaxThreads;
|
||||
uint32 mMinThreads;
|
||||
uint32 mTimeOut;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_REENTRANT)
|
||||
|
||||
#endif // BASE_LINUX_THREAD_H
|
||||
@@ -0,0 +1,42 @@
|
||||
////////////////////////////////////////
|
||||
// Types.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Define integer types that are unambiguous with respect to size
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_TYPES_H
|
||||
#define BASE_LINUX_TYPES_H
|
||||
|
||||
#include <sys/bitypes.h>
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
|
||||
namespace Base
|
||||
{
|
||||
#define INT32_MAX 0x7FFFFFFF
|
||||
#define INT32_MIN 0x80000000
|
||||
#define UINT32_MAX 0xFFFFFFFF
|
||||
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
|
||||
typedef int32_t int32;
|
||||
typedef u_int32_t uint32;
|
||||
typedef int64_t int64;
|
||||
typedef u_int64_t uint64;
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // BASE_LINUX_TYPES_H
|
||||
|
||||
@@ -0,0 +1,585 @@
|
||||
#ifndef SOE__SERIALIZE_H
|
||||
#define SOE__SERIALIZE_H
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Types.h"
|
||||
|
||||
#if (defined(WIN32) || defined(linux)) && !defined(NETWORK_BIG_ENDIAN)
|
||||
#define BYTE1 0
|
||||
#define BYTE2 1
|
||||
#define BYTE3 2
|
||||
#define BYTE4 3
|
||||
#define BYTE5 4
|
||||
#define BYTE6 5
|
||||
#define BYTE7 6
|
||||
#define BYTE8 7
|
||||
#elif defined(sparc) || defined(NETWORK_BIG_ENDIAN)
|
||||
#define BYTE1 7
|
||||
#define BYTE2 6
|
||||
#define BYTE3 5
|
||||
#define BYTE4 4
|
||||
#define BYTE5 3
|
||||
#define BYTE6 2
|
||||
#define BYTE7 1
|
||||
#define BYTE8 0
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
|
||||
namespace soe
|
||||
{
|
||||
|
||||
using namespace Base;//for types
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// 388 ns (50 bytes)
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, const unsigned char * data, unsigned dataLen)
|
||||
{
|
||||
if (size < dataLen)
|
||||
return 0;
|
||||
memcpy(stream, data, dataLen);
|
||||
return dataLen;
|
||||
}
|
||||
|
||||
// 353 ns
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, bool data)
|
||||
{
|
||||
if (size < sizeof(uint8))
|
||||
return 0;
|
||||
stream[BYTE1] = data;
|
||||
return sizeof(uint8);
|
||||
}
|
||||
|
||||
// 362 ns
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, int8 data)
|
||||
{
|
||||
if (size < sizeof(int8))
|
||||
return 0;
|
||||
stream[BYTE1] = data;
|
||||
return sizeof(int8);
|
||||
}
|
||||
|
||||
// 362 ns
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, uint8 data)
|
||||
{
|
||||
if (size < sizeof(uint8))
|
||||
return 0;
|
||||
stream[BYTE1] = data;
|
||||
return sizeof(uint8);
|
||||
}
|
||||
|
||||
// 355 ns
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, int16 data)
|
||||
{
|
||||
if (size < sizeof(int16))
|
||||
return 0;
|
||||
stream[BYTE1] = data&0xff;
|
||||
stream[BYTE2] = (data>>8)&0xff;
|
||||
return sizeof(int16);
|
||||
}
|
||||
|
||||
// 360 ns
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, uint16 data)
|
||||
{
|
||||
if (size < sizeof(uint16))
|
||||
return 0;
|
||||
stream[BYTE1] = data&0xff;
|
||||
stream[BYTE2] = (data>>8)&0xff;
|
||||
return sizeof(uint16);
|
||||
}
|
||||
|
||||
// 360 ns
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, int32 data)
|
||||
{
|
||||
if (size < sizeof(int32))
|
||||
return 0;
|
||||
stream[BYTE1] = data&0xff;
|
||||
stream[BYTE2] = (data>>8)&0xff;
|
||||
stream[BYTE3] = (data>>16)&0xff;
|
||||
stream[BYTE4] = (data>>24)&0xff;
|
||||
return sizeof(int32);
|
||||
}
|
||||
|
||||
// 360 ns
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, uint32 data)
|
||||
{
|
||||
if (size < sizeof(uint32))
|
||||
return 0;
|
||||
stream[BYTE1] = data&0xff;
|
||||
stream[BYTE2] = (data>>8)&0xff;
|
||||
stream[BYTE3] = (data>>16)&0xff;
|
||||
stream[BYTE4] = (data>>24)&0xff;
|
||||
return sizeof(uint32);
|
||||
}
|
||||
|
||||
// 370 ns
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, int64 data)
|
||||
{
|
||||
if (size < sizeof(int64))
|
||||
return 0;
|
||||
#if (defined(WIN32) || defined(linux))
|
||||
uint32 low = *(uint32 *)(&data);
|
||||
uint32 high = *((uint32 *)&data+1);
|
||||
#elif defined(sparc)
|
||||
uint32 low = *((uint32 *)&data+1);
|
||||
uint32 high = *(uint32 *)(&data);
|
||||
#endif
|
||||
stream[BYTE1] = (unsigned char)low&0xff;
|
||||
stream[BYTE2] = (unsigned char)(low>>8)&0xff;
|
||||
stream[BYTE3] = (unsigned char)(low>>16)&0xff;
|
||||
stream[BYTE4] = (unsigned char)(low>>24)&0xff;
|
||||
stream[BYTE5] = (unsigned char)high&0xff;
|
||||
stream[BYTE6] = (unsigned char)(high>>8)&0xff;
|
||||
stream[BYTE7] = (unsigned char)(high>>16)&0xff;
|
||||
stream[BYTE8] = (unsigned char)(high>>24)&0xff;
|
||||
return sizeof(int64);
|
||||
}
|
||||
|
||||
// 370 ns
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, uint64 data)
|
||||
{
|
||||
if (size < sizeof(uint64))
|
||||
return 0;
|
||||
#if (defined(WIN32) || defined(linux))
|
||||
uint32 low = *(uint32 *)(&data);
|
||||
uint32 high = *((uint32 *)&data+1);
|
||||
#elif defined(sparc)
|
||||
uint32 low = *((uint32 *)&data+1);
|
||||
uint32 high = *(uint32 *)(&data);
|
||||
#endif
|
||||
stream[BYTE1] = (unsigned char)low&0xff;
|
||||
stream[BYTE2] = (unsigned char)(low>>8)&0xff;
|
||||
stream[BYTE3] = (unsigned char)(low>>16)&0xff;
|
||||
stream[BYTE4] = (unsigned char)(low>>24)&0xff;
|
||||
stream[BYTE5] = (unsigned char)high&0xff;
|
||||
stream[BYTE6] = (unsigned char)(high>>8)&0xff;
|
||||
stream[BYTE7] = (unsigned char)(high>>16)&0xff;
|
||||
stream[BYTE8] = (unsigned char)(high>>24)&0xff;
|
||||
return sizeof(uint64);
|
||||
}
|
||||
|
||||
// 360 ns
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, float data)
|
||||
{
|
||||
uint32 & dataRef = *(uint32 *)(&data);
|
||||
if (size < sizeof(float))
|
||||
return 0;
|
||||
stream[BYTE1] = dataRef&0xff;
|
||||
stream[BYTE2] = (dataRef>>8)&0xff;
|
||||
stream[BYTE3] = (dataRef>>16)&0xff;
|
||||
stream[BYTE4] = (dataRef>>24)&0xff;
|
||||
return sizeof(float);
|
||||
}
|
||||
|
||||
// 370 ns
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, double data)
|
||||
{
|
||||
if (size < sizeof(double))
|
||||
return 0;
|
||||
#if (defined(WIN32) || defined(linux))
|
||||
uint32 low = *(uint32 *)(&data);
|
||||
uint32 high = *((uint32 *)&data+1);
|
||||
#elif defined(sparc)
|
||||
uint32 low = *((uint32 *)&data+1);
|
||||
uint32 high = *(uint32 *)(&data);
|
||||
#endif
|
||||
stream[BYTE1] = (unsigned char)low&0xff;
|
||||
stream[BYTE2] = (unsigned char)(low>>8)&0xff;
|
||||
stream[BYTE3] = (unsigned char)(low>>16)&0xff;
|
||||
stream[BYTE4] = (unsigned char)(low>>24)&0xff;
|
||||
stream[BYTE5] = (unsigned char)high&0xff;
|
||||
stream[BYTE6] = (unsigned char)(high>>8)&0xff;
|
||||
stream[BYTE7] = (unsigned char)(high>>16)&0xff;
|
||||
stream[BYTE8] = (unsigned char)(high>>24)&0xff;
|
||||
return sizeof(double);
|
||||
}
|
||||
|
||||
// 361 ns
|
||||
inline unsigned WriteEncoded(unsigned char * stream, unsigned size, uint32 data)
|
||||
{
|
||||
unsigned encoded = ((data & 0xffffffc0) << 2) | (data & 0x3f);
|
||||
if (data > 0x3fffffff)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (data > 0x3fffff && size >= 4)
|
||||
{
|
||||
encoded |= 0xc0;
|
||||
stream[BYTE1] = encoded & 0xff;
|
||||
stream[BYTE2] = (encoded>>8) & 0xff;
|
||||
stream[BYTE3] = (encoded>>16) & 0xff;
|
||||
stream[BYTE4] = (encoded>>24) & 0xff;
|
||||
return 4;
|
||||
}
|
||||
else if (data > 0x3fff)
|
||||
{
|
||||
encoded |= 0x80;
|
||||
stream[BYTE1] = encoded & 0xff;
|
||||
stream[BYTE2] = (encoded>>8) & 0xff;
|
||||
stream[BYTE3] = (encoded>>16) & 0xff;
|
||||
return 3;
|
||||
}
|
||||
else if (data > 0x3f)
|
||||
{
|
||||
encoded |= 0x40;
|
||||
stream[BYTE1] = encoded & 0xff;
|
||||
stream[BYTE2] = (encoded>>8) & 0xff;
|
||||
return 2;
|
||||
}
|
||||
else if (size >= 1)
|
||||
{
|
||||
stream[BYTE1] = encoded & 0xff;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 630 ns
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, const std::string & data, bool isPascal=true)
|
||||
{
|
||||
if (isPascal)
|
||||
{
|
||||
unsigned fieldLen = 0;
|
||||
unsigned bytes = 0;
|
||||
fieldLen = Write(stream, size, static_cast<unsigned>(data.length()));
|
||||
if (!fieldLen)
|
||||
return 0;
|
||||
bytes += fieldLen;
|
||||
if (data.length())
|
||||
{
|
||||
fieldLen = Write(stream+bytes, size-bytes, reinterpret_cast<const unsigned char *>(data.data()), data.length());
|
||||
if (!fieldLen)
|
||||
return 0;
|
||||
bytes += fieldLen;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned bytes = Write(stream, size, reinterpret_cast<const unsigned char *>(data.c_str()), data.size()+1);
|
||||
if (!bytes)
|
||||
return 0;
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline unsigned Write(unsigned char * stream, unsigned size, const std::vector<T> & data)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
unsigned elementBytes = 0;
|
||||
bytes += Write(stream, size, static_cast<unsigned>(data.size()));
|
||||
if (!bytes)
|
||||
return 0;
|
||||
for (typename std::vector<T>::const_iterator iter = data.begin(); iter != data.end(); iter++)
|
||||
{
|
||||
elementBytes = Write(stream+bytes, size-bytes, *iter);
|
||||
if (!elementBytes)
|
||||
return 0;
|
||||
bytes += elementBytes;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, unsigned char * data, unsigned dataLen)
|
||||
{
|
||||
if (size < dataLen)
|
||||
return 0;
|
||||
memcpy(data, stream, dataLen);
|
||||
return dataLen;
|
||||
}
|
||||
|
||||
// 355 ns
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, bool & data, unsigned = 1/*unused*/)
|
||||
{
|
||||
if (size < sizeof(uint8))
|
||||
return 0;
|
||||
data = stream[BYTE1] != 0;
|
||||
return sizeof(uint8);
|
||||
}
|
||||
|
||||
// 355 ns
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, int8 & data, unsigned = 1/*unused*/)
|
||||
{
|
||||
if (size < sizeof(int8))
|
||||
return 0;
|
||||
data = stream[BYTE1];
|
||||
return sizeof(int8);
|
||||
}
|
||||
|
||||
// 355 ns
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, uint8 & data, unsigned = 1/*unused*/)
|
||||
{
|
||||
if (size < sizeof(uint8))
|
||||
return 0;
|
||||
data = stream[BYTE1];
|
||||
return sizeof(uint8);
|
||||
}
|
||||
|
||||
// 355 ns
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, int16 & data, unsigned = 1/*unused*/)
|
||||
{
|
||||
if (size < sizeof(int16))
|
||||
return 0;
|
||||
data = stream[BYTE1];
|
||||
data |= stream[BYTE2]<<8;
|
||||
return sizeof(int16);
|
||||
}
|
||||
|
||||
// 355 ns
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, uint16 & data, unsigned = 1/*unused*/)
|
||||
{
|
||||
if (size < sizeof(uint16))
|
||||
return 0;
|
||||
data = stream[BYTE1];
|
||||
data |= stream[BYTE2]<<8;
|
||||
return sizeof(uint16);
|
||||
}
|
||||
|
||||
// 360 ns
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, int32 & data, unsigned = 1/*unused*/)
|
||||
{
|
||||
if (size < sizeof(int32))
|
||||
return 0;
|
||||
data = stream[BYTE1];
|
||||
data |= stream[BYTE2]<<8;
|
||||
data |= stream[BYTE3]<<16;
|
||||
data |= stream[BYTE4]<<24;
|
||||
return sizeof(int32);
|
||||
}
|
||||
|
||||
// 360 ns
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, uint32 & data, unsigned = 1/*unused*/)
|
||||
{
|
||||
if (size < sizeof(uint32))
|
||||
return 0;
|
||||
data = stream[BYTE1];
|
||||
data |= stream[BYTE2]<<8;
|
||||
data |= stream[BYTE3]<<16;
|
||||
data |= stream[BYTE4]<<24;
|
||||
return sizeof(uint32);
|
||||
}
|
||||
|
||||
// 380 ns
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, int64 & data, unsigned = 1/*unused*/)
|
||||
{
|
||||
if (size < sizeof(int64))
|
||||
return 0;
|
||||
#if (defined(WIN32) || defined(linux))
|
||||
uint32 & low = *(uint32 *)(&data);
|
||||
uint32 & high = *((uint32 *)&data+1);
|
||||
#elif defined(sparc)
|
||||
uint32 & low = *(uint32 *)(&data+1);
|
||||
uint32 & high = *(uint32 *)(&data);
|
||||
#endif
|
||||
low = stream[BYTE1];
|
||||
low |= stream[BYTE2]<<8;
|
||||
low |= stream[BYTE3]<<16;
|
||||
low |= stream[BYTE4]<<24;
|
||||
high = stream[BYTE5];
|
||||
high |= stream[BYTE6]<<8;
|
||||
high |= stream[BYTE7]<<16;
|
||||
high |= stream[BYTE8]<<24;
|
||||
return sizeof(int64);
|
||||
}
|
||||
|
||||
// 380 ns
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, uint64 & data, unsigned = 1/*unused*/)
|
||||
{
|
||||
if (size < sizeof(uint64))
|
||||
return 0;
|
||||
#if (defined(WIN32) || defined(linux))
|
||||
uint32 & low = *(uint32 *)(&data);
|
||||
uint32 & high = *((uint32 *)&data+1);
|
||||
#elif defined(sparc)
|
||||
uint32 & low = *(uint32 *)(&data+1);
|
||||
uint32 & high = *(uint32 *)(&data);
|
||||
#endif
|
||||
low = stream[BYTE1];
|
||||
low |= stream[BYTE2]<<8;
|
||||
low |= stream[BYTE3]<<16;
|
||||
low |= stream[BYTE4]<<24;
|
||||
high = stream[BYTE5];
|
||||
high |= stream[BYTE6]<<8;
|
||||
high |= stream[BYTE7]<<16;
|
||||
high |= stream[BYTE8]<<24;
|
||||
return sizeof(uint64);
|
||||
}
|
||||
|
||||
// 370 ns
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, float & data, unsigned = 1/*unused*/)
|
||||
{
|
||||
assert(sizeof(float) == 4);
|
||||
uint32 & dataRef = *(uint32 *)(&data);
|
||||
if (size < sizeof(float))
|
||||
return 0;
|
||||
dataRef = stream[BYTE1];
|
||||
dataRef |= stream[BYTE2]<<8;
|
||||
dataRef |= stream[BYTE3]<<16;
|
||||
dataRef |= stream[BYTE4]<<24;
|
||||
return sizeof(float);
|
||||
}
|
||||
|
||||
// 380 ns
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, double & data, unsigned = 1/*unused*/)
|
||||
{
|
||||
assert(sizeof(double) == 8);
|
||||
if (size < sizeof(double))
|
||||
return 0;
|
||||
#if (defined(WIN32) || defined(linux))
|
||||
uint32 & low = *(uint32 *)(&data);
|
||||
uint32 & high = *((uint32 *)&data+1);
|
||||
#elif defined(sparc)
|
||||
uint32 & low = *(uint32 *)(&data+1);
|
||||
uint32 & high = *(uint32 *)(&data);
|
||||
#endif
|
||||
low = stream[BYTE1];
|
||||
low |= stream[BYTE2]<<8;
|
||||
low |= stream[BYTE3]<<16;
|
||||
low |= stream[BYTE4]<<24;
|
||||
high = stream[BYTE5];
|
||||
high |= stream[BYTE6]<<8;
|
||||
high |= stream[BYTE7]<<16;
|
||||
high |= stream[BYTE8]<<24;
|
||||
return sizeof(double);
|
||||
}
|
||||
|
||||
// 360 ns
|
||||
inline unsigned ReadEncoded(const unsigned char * stream, unsigned size, uint32 & data)
|
||||
{
|
||||
if (size < 1)
|
||||
return 0;
|
||||
|
||||
unsigned encoded = stream[BYTE1];
|
||||
unsigned mask = encoded & 0xc0;
|
||||
if (mask == 0)
|
||||
{
|
||||
data = encoded & 0x3f;
|
||||
return 1;
|
||||
}
|
||||
else if (mask == 0x40 && size >=2)
|
||||
{
|
||||
data = (stream[BYTE2]<<6) | (encoded & 0x3f);
|
||||
return 2;
|
||||
}
|
||||
else if (mask == 0x80 && size >=3)
|
||||
{
|
||||
data = (stream[BYTE3]<<14) | (stream[BYTE2]<<6) | (encoded & 0x3f);
|
||||
return 3;
|
||||
}
|
||||
else if (mask == 0xc0 && size >=4)
|
||||
{
|
||||
data = (stream[BYTE4]<<22) | (stream[BYTE3]<<14) | (stream[BYTE2]<<6) | (encoded & 0x3f);
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, std::string & data, unsigned maxLen, bool isPascal=true)
|
||||
{
|
||||
if (isPascal)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
unsigned length = 0;
|
||||
bytes += Read(stream, size, length);
|
||||
if (!bytes || size < bytes+length || length > maxLen)
|
||||
return 0;
|
||||
data.assign((const char *)stream+bytes, (const char *)stream+bytes+length); // assign would be dangerous if unicode, single-byte characters are ok
|
||||
return bytes + length;
|
||||
}
|
||||
else
|
||||
{
|
||||
//find null terminator, if don't find it before maxLen, then err
|
||||
const unsigned char *strEnd = NULL;
|
||||
unsigned strLen = 0;
|
||||
for (;strLen<maxLen && strLen < size;strLen++)
|
||||
{
|
||||
if (stream[strLen] == 0)
|
||||
{
|
||||
//found it
|
||||
strEnd = (stream+strLen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (strEnd == NULL)
|
||||
return 0;
|
||||
|
||||
data.assign((const char *)stream, (const char *)strEnd);
|
||||
return strLen+1;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline unsigned Read(const unsigned char * stream, unsigned size, std::vector<T> & data, unsigned maxVecLen, unsigned maxFieldLen = 1)
|
||||
{
|
||||
T element;
|
||||
unsigned bytes = 0;
|
||||
unsigned elementBytes = 0;
|
||||
unsigned length = 0;
|
||||
data.clear();
|
||||
bytes += Read(stream, size, length);
|
||||
if (!bytes || length > maxVecLen)
|
||||
return 0;
|
||||
for (unsigned i=0; i<length; i++)
|
||||
{
|
||||
elementBytes = Read(stream+bytes, size-bytes, element, maxFieldLen);
|
||||
if (!elementBytes)
|
||||
return 0;
|
||||
data.push_back(element);
|
||||
bytes += elementBytes;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class AutoVariableBase
|
||||
{
|
||||
public:
|
||||
AutoVariableBase() {}
|
||||
virtual ~AutoVariableBase() {}
|
||||
|
||||
virtual unsigned Write(unsigned char * stream, unsigned size) const = 0;
|
||||
virtual unsigned Read(const unsigned char * stream, unsigned size, unsigned maxLen=1) = 0;
|
||||
};
|
||||
|
||||
template<class ValueType>
|
||||
class AutoVariable : public AutoVariableBase
|
||||
{
|
||||
public:
|
||||
AutoVariable() : AutoVariableBase(), mValue() {}
|
||||
explicit AutoVariable(const ValueType & source) : AutoVariableBase(), mValue(source) {}
|
||||
AutoVariable(const AutoVariable & copy) : AutoVariableBase(), mValue(copy.mValue) {}
|
||||
virtual ~AutoVariable() {}
|
||||
|
||||
const ValueType & Get() const { return mValue; }
|
||||
void Set(const ValueType & rhs) { mValue = rhs; }
|
||||
virtual unsigned Write(unsigned char * stream, unsigned size) const { return soe::Write(stream, size, mValue); }
|
||||
virtual unsigned Read(const unsigned char * stream, unsigned size, unsigned maxLen) { return soe::Read(stream, size, mValue, maxLen); }
|
||||
|
||||
private:
|
||||
ValueType mValue;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
+102
@@ -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,387 @@
|
||||
#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);
|
||||
#ifdef REENTRANT
|
||||
localtime_r(&t, &now);
|
||||
#else
|
||||
now = *(localtime(&t));
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef REENTRANT
|
||||
localtime_r(&t, &info->ts);
|
||||
#else
|
||||
info->ts = *(localtime(&t));
|
||||
#endif
|
||||
|
||||
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;
|
||||
#ifdef REENTRANT
|
||||
localtime_r(&t, &now);
|
||||
#else
|
||||
now = *(localtime(&t));
|
||||
#endif
|
||||
|
||||
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,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
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
#include "../BlockAllocator.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
BlockAllocator::BlockAllocator()
|
||||
{
|
||||
for(unsigned i = 0; i < 31; i++)
|
||||
{
|
||||
m_blocks[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BlockAllocator::~BlockAllocator()
|
||||
{
|
||||
// free all allocated memory blocks
|
||||
for(unsigned i = 0; i < 31; i++)
|
||||
{
|
||||
while(m_blocks[i] != NULL)
|
||||
{
|
||||
unsigned *tmp = m_blocks[i];
|
||||
m_blocks[i] = (unsigned *)*m_blocks[i];
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate a block that is the next power of two greater than the # of bytes passed.
|
||||
// 33 bytes yields a 64 byte block of memory and so forth.
|
||||
|
||||
void *BlockAllocator::getBlock(unsigned bytes)
|
||||
{
|
||||
unsigned accum = 16, bits = 16;
|
||||
unsigned *handle = NULL;
|
||||
|
||||
// Perform a binary search looking for the highest bit.
|
||||
|
||||
while(bits != 0)
|
||||
{
|
||||
// If bytes is less than the bit we're testing for, subtract half
|
||||
// from the bit value and repeat
|
||||
if(bytes < (unsigned)(1 << accum))
|
||||
{
|
||||
bits /= 2;
|
||||
accum -= bits;
|
||||
}
|
||||
// If bytes is greater than the bit we're testing for, add half
|
||||
// from the but value and repeat
|
||||
else if(bytes > (unsigned)(1 << accum))
|
||||
{
|
||||
bits /= 2;
|
||||
accum += bits;
|
||||
}
|
||||
// Got lucky and hit the value dead on
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// At this point accum contains the most significant bit index, increment
|
||||
accum++;
|
||||
if(accum < 2)
|
||||
{
|
||||
accum = 2;
|
||||
}
|
||||
|
||||
// Note that when memory is actually allocated, 8 extra bytes will be allocated.at the front
|
||||
// The first integer is the address of the next block of memory when the block is in the allocator
|
||||
// The second integer is the bit length of the block
|
||||
// Memory is allocated on 4 byte boundaries to sidestep byte alignment problems
|
||||
|
||||
|
||||
// Check if the allocator already has a block of that size
|
||||
if(m_blocks[accum] == 0)
|
||||
{
|
||||
// remove the pre allocated block from the linked list
|
||||
handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned));
|
||||
handle[1] = accum;
|
||||
handle[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate a new block
|
||||
handle = m_blocks[accum];
|
||||
m_blocks[accum] = (unsigned *)handle[0];
|
||||
handle[0] = 0;
|
||||
}
|
||||
// return a pointer that skips over the header used for the allocator's purposes
|
||||
return(handle + 2);
|
||||
}
|
||||
|
||||
void BlockAllocator::returnBlock(unsigned *handle)
|
||||
{
|
||||
// C++ allows for safe deletion of a NULL pointer
|
||||
if(handle)
|
||||
{
|
||||
// Update the allocator linked list, insert this entry at the head
|
||||
*(handle - 2) = (unsigned)m_blocks[*(handle - 1)];
|
||||
// Add this entry to the proper linked list node
|
||||
m_blocks[*(handle - 1)] = (handle - 2);
|
||||
}
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
////////////////////////////////////////
|
||||
// Event.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CEvent class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
|
||||
#if !defined(_MT)
|
||||
# pragma message( "Excluding Base::CEvent - requires multi-threaded compile. (_MT)" )
|
||||
#else
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CEvent::CEvent()
|
||||
{
|
||||
mEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
|
||||
}
|
||||
|
||||
CEvent::~CEvent()
|
||||
{
|
||||
if (mEvent)
|
||||
CloseHandle(mEvent);
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
////////////////////////////////////////
|
||||
// Event.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CEvent class that encapsulates the functionality of a
|
||||
// single-locking semaphore.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_WIN32_EVENT_H
|
||||
#define BASE_WIN32_EVENT_H
|
||||
|
||||
#if defined(_MT)
|
||||
|
||||
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CEvent
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates the functionality of a singal-locking semaphore.
|
||||
// This class is valuable for thread syncronization when a thead's
|
||||
// execution needs to be dependent upon another thread.
|
||||
//
|
||||
// Public Methods:
|
||||
// Signal() : Signals a thread that has called Wait() so that it can
|
||||
// continue execution. This function returns true if the waiting
|
||||
// thread was signalled successfully, otherwise false is returned.
|
||||
// Wait() : Halts the calling thread's execution indefinately until
|
||||
// a Singal() call is made by an external thread. If the thread is
|
||||
// successfully signalled, the function returns eWAIT_SIGNAL. If
|
||||
// timeout period expires without a signal, eWAIT_TIMEOUT is returned.
|
||||
// If the function fails, eWAIT_ERROR is returned.
|
||||
//
|
||||
class CEvent
|
||||
{
|
||||
public:
|
||||
CEvent();
|
||||
virtual ~CEvent();
|
||||
|
||||
bool Signal();
|
||||
int32 Wait(uint32 timeout = 0);
|
||||
|
||||
public:
|
||||
enum { eWAIT_ERROR, eWAIT_SIGNAL, eWAIT_TIMEOUT };
|
||||
private:
|
||||
HANDLE mEvent;
|
||||
};
|
||||
|
||||
inline bool CEvent::Signal()
|
||||
{
|
||||
if (mEvent)
|
||||
return SetEvent(mEvent)!=0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline int32 CEvent::Wait(uint32 timeout)
|
||||
{
|
||||
if (!mEvent)
|
||||
return CEvent::eWAIT_ERROR;
|
||||
|
||||
DWORD result = WaitForSingleObjectEx(mEvent, timeout ? timeout : INFINITE, FALSE);
|
||||
if (result == WAIT_OBJECT_0)
|
||||
return CEvent::eWAIT_SIGNAL;
|
||||
else if (result == WAIT_TIMEOUT)
|
||||
return CEvent::eWAIT_TIMEOUT;
|
||||
else
|
||||
return CEvent::eWAIT_ERROR;
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
|
||||
#endif // BASE_WIN32_EVENT_H
|
||||
@@ -0,0 +1,19 @@
|
||||
// File.cpp: implementation of the CFile class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "File.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CFile::CFile(const char *)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CFile::~CFile()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// File.h: interface for the CFile class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BASE_FILE_H
|
||||
#define BASE_FILE_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class CFile
|
||||
{
|
||||
public:
|
||||
CFile(const char *);
|
||||
virtual ~CFile();
|
||||
|
||||
bool IsOpen();
|
||||
|
||||
private:
|
||||
FILE* mFileHandle;
|
||||
};
|
||||
|
||||
#endif // BASE_FILE_H
|
||||
@@ -0,0 +1,40 @@
|
||||
////////////////////////////////////////
|
||||
// Mutex.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CMutex class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
#if !defined(_MT)
|
||||
# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_MT)" )
|
||||
#else
|
||||
|
||||
#include "Mutex.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CMutex::CMutex()
|
||||
{
|
||||
InitializeCriticalSection(&mCriticalSection);
|
||||
}
|
||||
|
||||
CMutex::~CMutex()
|
||||
{
|
||||
DeleteCriticalSection(&mCriticalSection);
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
////////////////////////////////////////
|
||||
// Mutex.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CMutex class that encapsulates the functionality of a
|
||||
// mutually-exclusive device.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_WIN32_MUTEX_H
|
||||
#define BASE_WIN32_MUTEX_H
|
||||
|
||||
#if defined (_MT)
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CMutex
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates the functionality of a mutually-exclusive device.
|
||||
// This class is valuable for protecting against race conditions
|
||||
// within threaded applications. The CMutex class can be used to
|
||||
// only allow a single thread to run within a specified code
|
||||
// segment at a time.
|
||||
//
|
||||
// Public Methods:
|
||||
// Lock() : Locks the mutex. If the mutex is already locked, the
|
||||
// operating system will block the calling thread until another
|
||||
// thread has unlocked the mutex.
|
||||
// Unlock() : Unlocks the mutex.
|
||||
//
|
||||
class CMutex
|
||||
{
|
||||
public:
|
||||
CMutex();
|
||||
~CMutex();
|
||||
|
||||
void Lock();
|
||||
void Unlock();
|
||||
private:
|
||||
CRITICAL_SECTION mCriticalSection;
|
||||
};
|
||||
|
||||
inline void CMutex::Lock()
|
||||
{
|
||||
EnterCriticalSection(&mCriticalSection);
|
||||
}
|
||||
|
||||
inline void CMutex::Unlock()
|
||||
{
|
||||
LeaveCriticalSection(&mCriticalSection);
|
||||
}
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_WIN32_MUTEX_H
|
||||
@@ -0,0 +1,31 @@
|
||||
////////////////////////////////////////
|
||||
// Platform.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the global functionality declaired in Platform.h.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
CTimer::CTimer() :
|
||||
mTimer(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
////////////////////////////////////////
|
||||
// Platform.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Include relevent system headers that are platform specific.
|
||||
// 2. Declair global platform specific functionality.
|
||||
// 3. Include primative type definitions
|
||||
//
|
||||
// Global Functions:
|
||||
// getTimer() : Return the current high resolution clock count.
|
||||
// getTimerFrequency() : Return the frequency of the high resolution clock.
|
||||
// sleep() : Voluntarily relinquish timeslice of the calling thread for a
|
||||
// specified number of milliseconds.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_WIN32_PLATFORM_H
|
||||
#define BASE_WIN32_PLATFORM_H
|
||||
|
||||
#include <memory.h>
|
||||
#include <winsock2.h>
|
||||
#include <time.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <direct.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
uint64 getTimer(void);
|
||||
uint64 getTimerFrequency(void);
|
||||
|
||||
inline uint64 getTimer(void)
|
||||
{
|
||||
uint64 result;
|
||||
if (!QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&result)))
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline uint64 getTimerFrequency(void)
|
||||
{
|
||||
uint64 result;
|
||||
if (!QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER *>(&result)))
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void sleep(uint32 ms)
|
||||
{
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
|
||||
class CTimer
|
||||
{
|
||||
public:
|
||||
CTimer();
|
||||
|
||||
void Set(uint32 seconds);
|
||||
void Signal();
|
||||
bool Expired();
|
||||
|
||||
private:
|
||||
uint32 mTimer;
|
||||
};
|
||||
|
||||
inline void CTimer::Set(uint32 interval)
|
||||
{
|
||||
mTimer = (uint32)time(0) + interval;
|
||||
}
|
||||
|
||||
inline void CTimer::Signal()
|
||||
{
|
||||
mTimer = 0;
|
||||
}
|
||||
|
||||
inline bool CTimer::Expired()
|
||||
{
|
||||
return (mTimer <= (uint32)time(0));
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif BASE_WIN32_PLATFORM_H
|
||||
@@ -0,0 +1,279 @@
|
||||
////////////////////////////////////////
|
||||
// Thread.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CThread class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
|
||||
#pragma warning ( disable: 4786 )
|
||||
|
||||
|
||||
#if !defined(_MT)
|
||||
# pragma message( "Excluding Base::CThread - requires multi-threaded compile. (_MT)" )
|
||||
#else
|
||||
|
||||
#include <process.h>
|
||||
#include <time.h>
|
||||
#include "Thread.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
void threadProc(void *threadPtr)
|
||||
{
|
||||
CThread &thread = *((CThread*)threadPtr);
|
||||
thread.mThreadActive = true;
|
||||
thread.ThreadProc();
|
||||
thread.mThreadActive = false;
|
||||
}
|
||||
|
||||
CThread::CThread()
|
||||
{
|
||||
mThreadID = 0;
|
||||
mThreadActive = false;
|
||||
mThreadContinue = false;
|
||||
}
|
||||
|
||||
CThread::~CThread()
|
||||
{
|
||||
StopThread();
|
||||
}
|
||||
|
||||
void CThread::StartThread()
|
||||
{
|
||||
mThreadContinue = true;
|
||||
mThreadID = _beginthread(threadProc,0,this);
|
||||
while (!IsThreadActive())
|
||||
Base::sleep(1);
|
||||
}
|
||||
|
||||
int32 CThread::StopThread(int32 timeout)
|
||||
{
|
||||
timeout += time(0);
|
||||
|
||||
mThreadContinue = false;
|
||||
while (mThreadActive && time(0)<timeout)
|
||||
sleep(1);
|
||||
if (mThreadActive)
|
||||
{
|
||||
mThreadActive = false;
|
||||
return eSTOP_TIMEOUT;
|
||||
}
|
||||
return eSTOP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CThreadPool::CMember::CMember(CThreadPool * parent) :
|
||||
mParent(parent),
|
||||
mFunction(NULL),
|
||||
mArgument(NULL),
|
||||
mSemaphore()
|
||||
{
|
||||
StartThread();
|
||||
}
|
||||
|
||||
CThreadPool::CMember::~CMember()
|
||||
{
|
||||
}
|
||||
|
||||
void CThreadPool::CMember::Destroy()
|
||||
{
|
||||
mThreadContinue = false;
|
||||
mSemaphore.Signal();
|
||||
}
|
||||
|
||||
bool CThreadPool::CMember::Execute(void( __cdecl *function )( void * ), void * arg)
|
||||
{
|
||||
if (mFunction)
|
||||
return false;
|
||||
|
||||
mArgument = arg;
|
||||
mFunction = function;
|
||||
mSemaphore.Signal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CThreadPool::CMember::ThreadProc()
|
||||
{
|
||||
mParent->OnStartup(this);
|
||||
while (mThreadContinue)
|
||||
{
|
||||
mParent->OnIdle(this);
|
||||
mSemaphore.Wait(mParent->GetTimeOut()*1000);
|
||||
|
||||
if (mFunction)
|
||||
{
|
||||
mFunction(mArgument);
|
||||
mArgument = NULL;
|
||||
mFunction = NULL;
|
||||
}
|
||||
else if (mParent->OnDestory(this))
|
||||
mThreadContinue = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CThreadPool::CThreadPool(uint32 maxThreads, uint32 minThreads, uint32 timeout) :
|
||||
mMutex(),
|
||||
mIdleMember(),
|
||||
mBusyMember(),
|
||||
mNullMember(),
|
||||
mThreadCount(0),
|
||||
mMaxThreads(maxThreads),
|
||||
mMinThreads(minThreads),
|
||||
mTimeOut(timeout)
|
||||
{
|
||||
if (mMaxThreads == 0) mMaxThreads = 1;
|
||||
if (mMinThreads == 0) mMinThreads = 1;
|
||||
if (mMinThreads > mMaxThreads) mMinThreads = mMaxThreads;
|
||||
|
||||
for (uint32 i=0; i<mMinThreads; i++)
|
||||
new CMember(this);
|
||||
}
|
||||
|
||||
CThreadPool::~CThreadPool()
|
||||
{
|
||||
set<CMember *>::iterator setIterator;
|
||||
|
||||
////////////////////////////////////////
|
||||
// (1) Destory all busy member threads
|
||||
mMutex.Lock();
|
||||
setIterator = mBusyMember.begin();
|
||||
while (setIterator != mBusyMember.end())
|
||||
(*setIterator++)->Destroy();
|
||||
mMutex.Unlock();
|
||||
|
||||
////////////////////////////////////////
|
||||
// (2) Destory all idle member threads
|
||||
while (mThreadCount)
|
||||
{
|
||||
mMutex.Lock();
|
||||
setIterator = mIdleMember.begin();
|
||||
while (setIterator != mIdleMember.end())
|
||||
(*setIterator++)->Destroy();
|
||||
mMutex.Unlock();
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (3) Delete the null member threads
|
||||
mMutex.Lock();
|
||||
while (!mNullMember.empty())
|
||||
{
|
||||
delete mNullMember.front();
|
||||
mNullMember.pop_front();
|
||||
}
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
bool CThreadPool::Execute(void( __cdecl *function )( void * ), void * arg)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
////////////////////////////////////////
|
||||
// (1) If no idle members, return false to indicate that no threads
|
||||
// were available. If the thread count is below the max, create
|
||||
// a new thread.
|
||||
if (mIdleMember.empty())
|
||||
{
|
||||
if (mThreadCount < mMaxThreads)
|
||||
new CMember(this);
|
||||
mMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (2) Delete any null member threads.
|
||||
while (!mNullMember.empty())
|
||||
{
|
||||
delete mNullMember.front();
|
||||
mNullMember.pop_front();
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (3) Move the first idle thread to the busy set and signal the
|
||||
// thread to execute the specified function.
|
||||
CMember * member = *(mIdleMember.begin());
|
||||
mIdleMember.erase(member);
|
||||
mBusyMember.insert(member);
|
||||
member->Execute(function,arg);
|
||||
|
||||
mMutex.Unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 CThreadPool::GetTimeOut()
|
||||
{
|
||||
return mTimeOut;
|
||||
}
|
||||
|
||||
void CThreadPool::OnStartup(CMember * member)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
mThreadCount++;
|
||||
mIdleMember.insert(member);
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
void CThreadPool::OnIdle(CMember * member)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
mBusyMember.erase(member);
|
||||
mIdleMember.insert(member);
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
bool CThreadPool::OnDestory(CMember * member)
|
||||
{
|
||||
set<CMember *>::iterator setIterator;
|
||||
|
||||
mMutex.Lock();
|
||||
|
||||
bool result = (setIterator = mIdleMember.find(member)) != mIdleMember.end();
|
||||
if (result)
|
||||
{
|
||||
mNullMember.push_back(member);
|
||||
mIdleMember.erase(setIterator);
|
||||
mThreadCount--;
|
||||
}
|
||||
|
||||
mMutex.Unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
////////////////////////////////////////
|
||||
// Thread.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CThread class that encapsulates threading functionality.
|
||||
// This abstract base class in intended to be used to encapsulate
|
||||
// individual tasks that require threading in derived classes.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_WIN32_THREAD_H
|
||||
#define BASE_WIN32_THREAD_H
|
||||
|
||||
#if defined(_MT)
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include "Platform.h"
|
||||
#include "Mutex.h"
|
||||
#include "Event.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CThread
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates threading functionality. Creating classes derived
|
||||
// from CThread provides an easy way to encapsulate tasks that require
|
||||
// their own thread.
|
||||
//
|
||||
// Public Methods:
|
||||
// StartThread() : Creates the low-level thread handle and begins executing
|
||||
// the CThread::ThreadProc() function within the new thread.
|
||||
// StopThread() : Signals the ThreadProc() function to stop executing using
|
||||
// the mThreadContinue member variable, and waits for the ThreadProc()
|
||||
// function to exit. By default, the function will block for a maximum
|
||||
// of 5 seconds before exiting without the thread halting.
|
||||
// IsThreadActive() : Returns true if the physical thread is still executing
|
||||
// within the ThreadProc() function, otherwise it returns false.
|
||||
// ThreadProc() : Pure-virtual function that will be executed when the StartThread()
|
||||
// function is called. Derived classes must implement this function. The
|
||||
// mThreadContinue member variable should be used internal the the ThreadProc()
|
||||
// function to indicate whether it should continue executing or exit.
|
||||
// Protected Attributes:
|
||||
// mThreadContinue : Boolean value indicating to the ThreadProc() function
|
||||
// whether to continue executing or to exit. If mThreadContinue is true,
|
||||
// ThreadProc() should continue, otherwise ThreadProc() should exit. It
|
||||
// left up to the derived class to implement a ThreadProc() function that
|
||||
// uses the mThreadContinue member.
|
||||
//
|
||||
//
|
||||
class CThread
|
||||
{
|
||||
friend void threadProc(void *);
|
||||
|
||||
public:
|
||||
enum { eSTOP_SUCCESS, eSTOP_TIMEOUT };
|
||||
public:
|
||||
CThread();
|
||||
virtual ~CThread();
|
||||
|
||||
void StartThread();
|
||||
int32 StopThread(int32 timeout=5);
|
||||
bool IsThreadActive() { return mThreadActive; }
|
||||
|
||||
protected:
|
||||
virtual void ThreadProc() = 0;
|
||||
|
||||
protected:
|
||||
bool mThreadContinue;
|
||||
private:
|
||||
uint32 mThreadID;
|
||||
bool mThreadActive;
|
||||
};
|
||||
|
||||
|
||||
class CThreadPool
|
||||
{
|
||||
private:
|
||||
class CMember : public CThread
|
||||
{
|
||||
public:
|
||||
CMember(CThreadPool * parent);
|
||||
virtual ~CMember();
|
||||
|
||||
bool Execute(void( __cdecl *function )( void * ), void * arg);
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
virtual void ThreadProc();
|
||||
|
||||
private:
|
||||
CThreadPool * mParent;
|
||||
void( __cdecl * mFunction )( void * );
|
||||
void * mArgument;
|
||||
CEvent mSemaphore;
|
||||
};
|
||||
friend class CMember;
|
||||
|
||||
public:
|
||||
CThreadPool(uint32 maxThreads, uint32 minThreads=1, uint32 timeout=15*60);
|
||||
~CThreadPool();
|
||||
|
||||
bool Execute(void( __cdecl *function )( void * ), void * arg);
|
||||
|
||||
private:
|
||||
uint32 GetTimeOut();
|
||||
void OnStartup(CMember * member);
|
||||
void OnIdle(CMember * member);
|
||||
bool OnDestory(CMember * member);
|
||||
|
||||
private:
|
||||
CMutex mMutex;
|
||||
std::set<CMember *> mIdleMember;
|
||||
std::set<CMember *> mBusyMember;
|
||||
std::list<CMember *> mNullMember;
|
||||
uint32 mThreadCount;
|
||||
|
||||
uint32 mMaxThreads;
|
||||
uint32 mMinThreads;
|
||||
uint32 mTimeOut;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_WIN32_THREAD_H
|
||||
@@ -0,0 +1,42 @@
|
||||
////////////////////////////////////////
|
||||
// Types.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Define integer types that are unambiguous with respect to size
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_WIN32_TYPES_H
|
||||
#define BASE_WIN32_TYPES_H
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
#define INT32_MAX 0x7FFFFFFF
|
||||
#define INT32_MIN 0x80000000
|
||||
#define UINT32_MAX 0xFFFFFFFF
|
||||
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
typedef short int16;
|
||||
typedef unsigned short uint16;
|
||||
|
||||
typedef int int32;
|
||||
typedef unsigned uint32;
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // BASE_WIN32_TYPES_H
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
#include "Clock.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock.h>
|
||||
#else //WIN32
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
#endif
|
||||
|
||||
Clock::Clock()
|
||||
: m_lastStart(0),
|
||||
m_totalRunTime(0)
|
||||
{
|
||||
}
|
||||
|
||||
ClockStamp Clock::getCurTime()
|
||||
{
|
||||
#if defined(WIN32)
|
||||
static int sClockHigh = 0;
|
||||
static ClockStamp sClockLast = 0;
|
||||
|
||||
int high = sClockHigh;
|
||||
DWORD low = GetTickCount();
|
||||
ClockStamp holdLast = sClockLast; // this should be interlocked too
|
||||
ClockStamp ret = ((ClockStamp)high << 32) | low;
|
||||
|
||||
// crazy trick to allow threading to work, by putting in a 1000 second fudge factor, we effective say
|
||||
// that it is ok to time-slice us at a bad point and we will still handle it, provided that our thread
|
||||
// gets processing time again within 1000 seconds
|
||||
if (ret < holdLast - 1000000)
|
||||
{
|
||||
sClockHigh = high + 1;
|
||||
ret = ((ClockStamp)high << 32) | low;
|
||||
}
|
||||
|
||||
sClockLast = ret; // this really should be interlocked to be totally safe since it is a 64 bit value, but I don't see a way to do that and am not sure it would mess up anything but the one call anyways
|
||||
|
||||
return ret;
|
||||
#else
|
||||
struct timeval tv;
|
||||
int err;
|
||||
err = gettimeofday(&tv, NULL);
|
||||
return (static_cast<ClockStamp>(tv.tv_sec) * 1000 + static_cast<ClockStamp>(tv.tv_usec / 1000));
|
||||
#endif
|
||||
}
|
||||
|
||||
ClockStamp Clock::getElapsedSinceLastStart()
|
||||
{
|
||||
if (m_lastStart == 0)
|
||||
{
|
||||
//hasn't been started
|
||||
return 0;
|
||||
}
|
||||
|
||||
ClockStamp elapsed = getCurTime() - m_lastStart;
|
||||
|
||||
if (elapsed > 2000000000) // only time differences up to 23 days can be measured with this function
|
||||
elapsed = 2000000000;
|
||||
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
void Clock::start()
|
||||
{
|
||||
if (m_lastStart != 0)
|
||||
{
|
||||
//already started
|
||||
return;
|
||||
}
|
||||
|
||||
//set last start to curtime
|
||||
m_lastStart = getCurTime();
|
||||
}
|
||||
|
||||
void Clock::stop()
|
||||
{
|
||||
if (m_lastStart == 0)
|
||||
{
|
||||
//need to start before stoping
|
||||
return;
|
||||
}
|
||||
|
||||
m_totalRunTime += (unsigned)getElapsedSinceLastStart(); //rlsmith - explicit cast to prevent compiler warning
|
||||
m_lastStart = 0;
|
||||
}
|
||||
|
||||
|
||||
bool Clock::isDone(unsigned runTime)
|
||||
{
|
||||
if (m_lastStart == 0)
|
||||
{
|
||||
//never started, so say no
|
||||
return false;
|
||||
}
|
||||
|
||||
ClockStamp totalElapsed = getElapsedSinceLastStart() + m_totalRunTime;
|
||||
|
||||
return (totalElapsed >= runTime);
|
||||
}
|
||||
|
||||
void Clock::reset()
|
||||
{
|
||||
m_lastStart = 0;
|
||||
m_totalRunTime = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef CLOCK_H
|
||||
#define CLOCK_H
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
typedef __int64 ClockStamp;
|
||||
#else
|
||||
typedef long long ClockStamp;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief A Clock can be used as a millisecond timer.
|
||||
*/
|
||||
class Clock
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Creates a clock, must still be started with Clock::start method.
|
||||
*
|
||||
* Once created, a clock can be started, and stoped as often as possible.
|
||||
*/
|
||||
Clock();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Starts the timer running.
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* @brief Stops the timer from running (note: can still be started again later).
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* @brief Tells you if the timer has been in the started state for longer than runTime.
|
||||
*
|
||||
* @param runTime The amount of time to test if this timer has ran longer than.
|
||||
*
|
||||
* @return 'true' if timer has ran for longer than or equal to runTime, false otherwise.
|
||||
*/
|
||||
bool isDone(unsigned runTime);
|
||||
|
||||
/**
|
||||
* @brief Resets this clock (as if it were never started).
|
||||
*/
|
||||
void reset();
|
||||
|
||||
private:
|
||||
ClockStamp m_lastStart;
|
||||
unsigned m_totalRunTime;
|
||||
|
||||
ClockStamp getCurTime();
|
||||
ClockStamp getElapsedSinceLastStart();
|
||||
};
|
||||
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif //CLOCK_H
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "IPAddress.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <winsock.h>
|
||||
typedef int socklen_t;
|
||||
#else // for non-windows platforms (linux)
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
#endif
|
||||
|
||||
IPAddress::IPAddress(unsigned int ip)
|
||||
: m_IP(ip)
|
||||
{
|
||||
}
|
||||
|
||||
char *IPAddress::GetAddress(char *buffer) const
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_addr.s_addr = m_IP;
|
||||
strcpy(buffer, inet_ntoa(addr.sin_addr));
|
||||
return(buffer);
|
||||
}
|
||||
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef TCPIPADDRESS_H
|
||||
#define TCPIPADDRESS_H
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Container object for IP Address.
|
||||
*/
|
||||
class IPAddress
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Constructor, sets the ip address if specified.
|
||||
*/
|
||||
IPAddress(unsigned int ip = 0);
|
||||
|
||||
/**
|
||||
* @brief Sets the ip address.
|
||||
*/
|
||||
void SetAddress(unsigned int ip){ m_IP = ip; }
|
||||
|
||||
/**
|
||||
* @brief Returns the unsigned int representation of this address.
|
||||
*/
|
||||
unsigned int GetAddress() const { return m_IP; }
|
||||
|
||||
/**
|
||||
* @brief Used to retreive the the dot-notation represenatatiion of this address.
|
||||
*
|
||||
* @param buffer A pointer to the buffer to place the ip address into.
|
||||
* Must be at least 17 characters long, will be null terminated.
|
||||
*
|
||||
* @return A pointer to the buffer the address was placed into.
|
||||
*/
|
||||
char *GetAddress(char *buffer) const;
|
||||
|
||||
private:
|
||||
unsigned int m_IP;
|
||||
};
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif //TCPIPADDRESS_H
|
||||
|
||||
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
#include "TcpBlockAllocator.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
#endif
|
||||
|
||||
TcpBlockAllocator::TcpBlockAllocator(const unsigned initSize, const unsigned initCount)
|
||||
: m_freeHead(NULL), m_blockCount(initCount), m_blockSize(initSize), m_numAvailBlocks(0)
|
||||
{
|
||||
realloc();
|
||||
}
|
||||
|
||||
TcpBlockAllocator::~TcpBlockAllocator()
|
||||
{
|
||||
while(m_freeHead)
|
||||
{
|
||||
data_block *tmp = m_freeHead;
|
||||
m_freeHead = m_freeHead->m_next;
|
||||
delete[] tmp->m_data;
|
||||
delete tmp;m_numAvailBlocks--;
|
||||
}
|
||||
}
|
||||
|
||||
data_block *TcpBlockAllocator::getBlock()
|
||||
{
|
||||
data_block *tmp;
|
||||
|
||||
if(!m_freeHead)
|
||||
{
|
||||
realloc();
|
||||
}
|
||||
|
||||
tmp = m_freeHead;
|
||||
m_freeHead = m_freeHead->m_next;
|
||||
tmp->m_next = NULL;
|
||||
m_numAvailBlocks--;
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
void TcpBlockAllocator::returnBlock(data_block *b)
|
||||
{
|
||||
b->m_usedSize = 0;
|
||||
b->m_sentSize = 0;
|
||||
|
||||
if (m_numAvailBlocks >= m_blockCount)
|
||||
{
|
||||
delete[] b->m_data;
|
||||
delete b;
|
||||
return;
|
||||
}
|
||||
|
||||
b->m_next = m_freeHead;
|
||||
m_freeHead = b; m_numAvailBlocks++;
|
||||
}
|
||||
|
||||
void TcpBlockAllocator::realloc()
|
||||
{
|
||||
data_block *tmp = NULL, *cursor = NULL;
|
||||
|
||||
tmp = new data_block; m_numAvailBlocks++;
|
||||
cursor = tmp;
|
||||
memset(cursor, 0, sizeof(data_block));
|
||||
cursor->m_data = new char[m_blockSize];
|
||||
cursor->m_totalSize = m_blockSize;
|
||||
|
||||
for(unsigned i = 1; i < m_blockCount; i++)
|
||||
{
|
||||
cursor->m_next = new data_block; m_numAvailBlocks++;
|
||||
cursor = cursor->m_next;
|
||||
memset(cursor, 0, sizeof(data_block));
|
||||
cursor->m_data = new char[m_blockSize];
|
||||
cursor->m_totalSize = m_blockSize;
|
||||
}
|
||||
|
||||
if(m_freeHead)
|
||||
{
|
||||
cursor->m_next = m_freeHead;
|
||||
m_freeHead = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_freeHead = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
#ifndef TCPBLOCKALLOCATOR_H
|
||||
#define TCPBLOCKALLOCATOR_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
#endif
|
||||
|
||||
struct data_block
|
||||
{
|
||||
unsigned m_usedSize;
|
||||
unsigned m_sentSize;
|
||||
unsigned m_totalSize;
|
||||
char *m_data;
|
||||
data_block *m_next;
|
||||
};
|
||||
|
||||
class TcpBlockAllocator
|
||||
{
|
||||
public:
|
||||
TcpBlockAllocator(const unsigned initSize, const unsigned initCount);
|
||||
~TcpBlockAllocator();
|
||||
data_block *getBlock();
|
||||
void returnBlock(data_block *);
|
||||
|
||||
private:
|
||||
void realloc();
|
||||
data_block *m_freeHead;
|
||||
unsigned m_blockCount;
|
||||
unsigned m_blockSize;
|
||||
unsigned m_numAvailBlocks;
|
||||
};
|
||||
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif //TCPBLOCKALLOCATOR_H
|
||||
|
||||
|
||||
|
||||
|
||||
+784
@@ -0,0 +1,784 @@
|
||||
#include "TcpConnection.h"
|
||||
#include "TcpManager.h"
|
||||
#include "Clock.h"
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
//used when want to open new connection with this socket
|
||||
TcpConnection::TcpConnection(TcpManager *tcpManager, TcpBlockAllocator *sendAlloc, TcpManager::TcpParams ¶ms, const IPAddress &destIP, short destPort, unsigned timeout)
|
||||
: m_nextConnection(NULL),
|
||||
m_prevConnection(NULL),
|
||||
m_socket(INVALID_SOCKET),
|
||||
m_nextKeepAliveConnection(NULL),
|
||||
m_prevKeepAliveConnection(NULL),
|
||||
m_aliveListId(tcpManager->m_aliveList.m_listID),
|
||||
m_nextRecvDataConnection(NULL),
|
||||
m_prevRecvDataConnection(NULL),
|
||||
m_recvDataListId(tcpManager->m_dataList.m_listID),
|
||||
m_manager(tcpManager),
|
||||
m_status(StatusNegotiating),
|
||||
m_handler(NULL),
|
||||
m_destIP(destIP),
|
||||
m_destPort(destPort),
|
||||
m_refCount(0),
|
||||
m_sendAllocator(sendAlloc),
|
||||
m_head(NULL),
|
||||
m_tail(NULL),
|
||||
m_bytesRead(0),
|
||||
m_bytesNeeded(0),
|
||||
m_params(params),
|
||||
m_recvBuff(NULL),
|
||||
m_connectTimeout(timeout),
|
||||
m_connectTimer(),
|
||||
m_wasConRemovedFromMgr(false)
|
||||
{
|
||||
//start connection timer
|
||||
m_connectTimer.start();
|
||||
|
||||
memset(&m_addr, 0, sizeof(m_addr));
|
||||
if (m_params.maxRecvMessageSize != 0)
|
||||
{
|
||||
m_recvBuff = new char[m_params.maxRecvMessageSize];
|
||||
}
|
||||
|
||||
m_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
|
||||
setOptions();
|
||||
|
||||
|
||||
m_addr.sin_family = AF_INET;
|
||||
m_addr.sin_port = htons(m_destPort);
|
||||
m_addr.sin_addr.s_addr = m_destIP.GetAddress();
|
||||
|
||||
int err = connect(m_socket, (sockaddr *)&m_addr, sizeof(m_addr));
|
||||
|
||||
if(err == SOCKET_ERROR)
|
||||
{
|
||||
#ifdef WIN32
|
||||
int sockerr = WSAGetLastError();
|
||||
if(sockerr != WSAEWOULDBLOCK)
|
||||
{
|
||||
//a real error
|
||||
m_status = StatusDisconnected;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_status = StatusNegotiating;
|
||||
}
|
||||
|
||||
#else // UNIX
|
||||
|
||||
if (errno != EINPROGRESS)
|
||||
{
|
||||
m_status = StatusDisconnected;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_status = StatusNegotiating;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
//we are connected, wow
|
||||
m_status = StatusConnected;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//used when server mode creates new connection object representing a connect request
|
||||
TcpConnection::TcpConnection(TcpManager *tcpManager, TcpBlockAllocator *sendAlloc, TcpManager::TcpParams ¶ms, SOCKET socket, const IPAddress &destIP, short destPort)
|
||||
: m_nextConnection(NULL),
|
||||
m_prevConnection(NULL),
|
||||
m_socket(socket),
|
||||
m_nextKeepAliveConnection(NULL),
|
||||
m_prevKeepAliveConnection(NULL),
|
||||
m_aliveListId(tcpManager->m_aliveList.m_listID),
|
||||
m_nextRecvDataConnection(NULL),
|
||||
m_prevRecvDataConnection(NULL),
|
||||
m_recvDataListId(tcpManager->m_dataList.m_listID),
|
||||
m_manager(tcpManager),
|
||||
m_status(StatusConnected),
|
||||
m_handler(NULL),
|
||||
m_destIP(destIP),
|
||||
m_destPort(destPort),
|
||||
m_refCount(0),
|
||||
m_sendAllocator(sendAlloc),
|
||||
m_head(NULL),
|
||||
m_tail(NULL),
|
||||
m_bytesRead(0),
|
||||
m_bytesNeeded(0),
|
||||
m_params(params),
|
||||
m_recvBuff(NULL),
|
||||
m_connectTimeout(0),
|
||||
m_connectTimer(),
|
||||
m_wasConRemovedFromMgr(false)
|
||||
{
|
||||
memset(&m_addr, 0, sizeof(m_addr));
|
||||
if (m_params.maxRecvMessageSize != 0)
|
||||
{
|
||||
m_recvBuff = new char[m_params.maxRecvMessageSize];
|
||||
}
|
||||
|
||||
|
||||
setOptions();
|
||||
}
|
||||
|
||||
void TcpConnection::setOptions()
|
||||
{
|
||||
if (m_socket != INVALID_SOCKET)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
unsigned long isNonBlocking = 1;
|
||||
int outBufSize = m_params.outgoingBufferSize;
|
||||
int inBufSize = m_params.incomingBufferSize;
|
||||
int keepAlive = 1;
|
||||
int reuseAddr = 1;
|
||||
struct linger ld;
|
||||
ld.l_onoff = 0;
|
||||
ld.l_linger = 0;
|
||||
|
||||
if (ioctlsocket(m_socket, FIONBIO, &isNonBlocking) != 0
|
||||
|| setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&outBufSize, sizeof(outBufSize)) != 0
|
||||
|| setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&inBufSize, sizeof(inBufSize)) != 0
|
||||
|| setsockopt(m_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepAlive, sizeof(keepAlive)) != 0
|
||||
|| setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseAddr, sizeof(reuseAddr)) != 0
|
||||
|| setsockopt(m_socket, SOL_SOCKET, SO_LINGER, (char *)&ld, sizeof(ld)) != 0 )
|
||||
{
|
||||
//bummer, but no need to crash now.... ?
|
||||
}
|
||||
|
||||
#else // linux is to remain the default compile mode
|
||||
unsigned long isNonBlocking = 1;
|
||||
unsigned long keepAlive = 1;
|
||||
unsigned long outBufSize = m_params.outgoingBufferSize;
|
||||
unsigned long inBufSize = m_params.incomingBufferSize;
|
||||
unsigned long reuseAddr = 1;
|
||||
struct linger ld;
|
||||
ld.l_onoff = 0;
|
||||
ld.l_linger = 0;
|
||||
|
||||
if (ioctl(m_socket, FIONBIO, &isNonBlocking) != 0
|
||||
|| setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, &outBufSize, sizeof(outBufSize)) != 0
|
||||
|| setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, &inBufSize, sizeof(inBufSize)) != 0
|
||||
|| setsockopt(m_socket, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(keepAlive)) != 0
|
||||
|| setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)) != 0
|
||||
|| setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &ld, sizeof(ld)) != 0)
|
||||
{
|
||||
//bummer, but no need to crash now.... ?
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int TcpConnection::finishConnect()
|
||||
{
|
||||
AddRef();
|
||||
int returnVal = 0;
|
||||
/**< returns < 0 if fatal error and connect will not work, =0 if need more time, >0 if connect completed */
|
||||
switch (m_status)
|
||||
{
|
||||
case StatusDisconnected:
|
||||
{
|
||||
//something went wrong
|
||||
Disconnect(false);
|
||||
returnVal = -1;
|
||||
}
|
||||
break;
|
||||
case StatusNegotiating:
|
||||
{
|
||||
#ifdef WIN32
|
||||
//try to finish connection
|
||||
fd_set wrSet;
|
||||
FD_ZERO(&wrSet);
|
||||
|
||||
FD_SET(m_socket, &wrSet);
|
||||
|
||||
timeval t;
|
||||
t.tv_sec = 0;
|
||||
t.tv_usec = 0;
|
||||
|
||||
int err = select(m_socket + 1, NULL, &wrSet, NULL, &t);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
//needs more time
|
||||
returnVal = 0;
|
||||
}
|
||||
else if (err == SOCKET_ERROR)
|
||||
{
|
||||
//huhoh, let's hope it needs more time
|
||||
int sockerr = WSAGetLastError();
|
||||
if (sockerr == WSAEINPROGRESS
|
||||
|| sockerr == WSAEWOULDBLOCK
|
||||
|| sockerr == WSAEALREADY
|
||||
|| sockerr == WSAEINVAL)
|
||||
{
|
||||
//yep
|
||||
returnVal = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Disconnect(false);
|
||||
returnVal = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//check if write bit set for socket
|
||||
if (FD_ISSET(m_socket, &wrSet))
|
||||
{
|
||||
//connection complete
|
||||
m_status = StatusConnected;
|
||||
returnVal = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//give it more time??
|
||||
returnVal = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else // not WIN32
|
||||
int err = connect(m_socket, (sockaddr *)&m_addr, sizeof(m_addr));
|
||||
|
||||
if(err == SOCKET_ERROR)
|
||||
{
|
||||
if (errno != EINPROGRESS && errno != EALREADY)
|
||||
{
|
||||
Disconnect(false);
|
||||
returnVal = -1;//failure
|
||||
}
|
||||
else
|
||||
{
|
||||
returnVal = 0;//need to wait
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_status = StatusConnected;
|
||||
returnVal = 1;//connect success
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case StatusConnected:
|
||||
{
|
||||
//wierd, shouldn't be trying to do this here
|
||||
Disconnect(true);
|
||||
returnVal = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (returnVal == 0 && m_connectTimeout != 0 && m_connectTimer.isDone(m_connectTimeout))
|
||||
{
|
||||
Disconnect(false);
|
||||
returnVal = -1;
|
||||
}
|
||||
else if (returnVal ==1/* && m_connectTimeout != 0*/)
|
||||
{
|
||||
//need to give, onConnect callback
|
||||
if (m_manager->m_handler)
|
||||
m_manager->m_handler->OnConnectRequest(this);
|
||||
}
|
||||
|
||||
Release();
|
||||
return returnVal;
|
||||
|
||||
}
|
||||
|
||||
|
||||
TcpConnection::~TcpConnection()
|
||||
{
|
||||
if (m_recvBuff != NULL)
|
||||
{
|
||||
delete [] m_recvBuff;
|
||||
}
|
||||
|
||||
while(m_head != NULL)
|
||||
{
|
||||
data_block *tmp = m_head;
|
||||
m_head = m_head->m_next;
|
||||
m_sendAllocator->returnBlock(tmp);
|
||||
}
|
||||
|
||||
//TODO: need to notify app if are currently connected
|
||||
}
|
||||
|
||||
void TcpConnection::Send(const char *data, unsigned int dataLen)
|
||||
{
|
||||
//add msg to buf
|
||||
int totalLen = dataLen + sizeof(int);
|
||||
|
||||
if(m_status == StatusDisconnected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_params.keepAliveDelay > 0 && m_aliveListId == m_manager->m_aliveList.m_listID)
|
||||
{
|
||||
m_aliveListId = m_manager->m_keepAliveList.m_listID;
|
||||
|
||||
if (m_prevKeepAliveConnection != NULL)
|
||||
m_prevKeepAliveConnection->m_nextKeepAliveConnection = m_nextKeepAliveConnection;
|
||||
if (m_nextKeepAliveConnection != NULL)
|
||||
m_nextKeepAliveConnection->m_prevKeepAliveConnection = m_prevKeepAliveConnection;
|
||||
if (m_manager->m_keepAliveList.m_beginList == this)
|
||||
m_manager->m_keepAliveList.m_beginList = m_nextKeepAliveConnection;
|
||||
|
||||
m_nextKeepAliveConnection = m_manager->m_aliveList.m_beginList;
|
||||
m_prevKeepAliveConnection = NULL;
|
||||
if (m_manager->m_aliveList.m_beginList != NULL)
|
||||
m_manager->m_aliveList.m_beginList->m_prevKeepAliveConnection = this;
|
||||
m_manager->m_aliveList.m_beginList = this;
|
||||
}
|
||||
|
||||
|
||||
data_block *work = NULL;
|
||||
|
||||
// this connection has no send buffer. Get a block
|
||||
if(!m_tail)
|
||||
{
|
||||
m_head = m_sendAllocator->getBlock();
|
||||
m_tail = m_head;
|
||||
}
|
||||
work = m_tail;
|
||||
|
||||
//send message len first
|
||||
unsigned nLen = htonl(totalLen);
|
||||
unsigned lenLength = sizeof(int);
|
||||
unsigned lenIndex = 0;
|
||||
while(lenIndex < lenLength)
|
||||
{
|
||||
if ((lenLength - lenIndex) <= (work->m_totalSize - work->m_usedSize))
|
||||
{
|
||||
//size will fit in this block
|
||||
memcpy(work->m_data + work->m_usedSize, (char *)(&nLen) + lenIndex, lenLength - lenIndex);
|
||||
work->m_usedSize += (lenLength - lenIndex);
|
||||
lenIndex += (lenLength - lenIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
//size will not fit in this block
|
||||
memcpy(work->m_data + work->m_usedSize, (char *)(&nLen) + lenIndex, work->m_totalSize - work->m_usedSize);
|
||||
lenIndex += work->m_totalSize - work->m_usedSize;
|
||||
work->m_usedSize += work->m_totalSize - work->m_usedSize;
|
||||
work->m_next = m_sendAllocator->getBlock();
|
||||
work = work->m_next;
|
||||
m_tail = work;
|
||||
}
|
||||
}
|
||||
|
||||
//now send message payload
|
||||
unsigned messageIndex = 0;
|
||||
while(messageIndex < dataLen)
|
||||
{
|
||||
if((dataLen - messageIndex) <= (work->m_totalSize - work->m_usedSize))
|
||||
{
|
||||
// data will fit in this block
|
||||
memcpy(work->m_data + work->m_usedSize, data + messageIndex, (dataLen - messageIndex));
|
||||
work->m_usedSize += (dataLen - messageIndex);
|
||||
messageIndex += (dataLen - messageIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// data will not fit in this block. Fill this block and get another block
|
||||
memcpy(work->m_data + work->m_usedSize, data + messageIndex, work->m_totalSize - work->m_usedSize);
|
||||
messageIndex += work->m_totalSize - work->m_usedSize;
|
||||
work->m_usedSize += work->m_totalSize - work->m_usedSize;
|
||||
work->m_next = m_sendAllocator->getBlock();
|
||||
work = work->m_next;
|
||||
m_tail = work;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void TcpConnection::Disconnect(bool notifyApplication)
|
||||
{
|
||||
AddRef();
|
||||
m_status = StatusDisconnected;
|
||||
if (!m_wasConRemovedFromMgr)
|
||||
{
|
||||
m_manager->removeConnection(this);
|
||||
m_wasConRemovedFromMgr = true;
|
||||
}
|
||||
|
||||
|
||||
if(m_socket != INVALID_SOCKET)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
closesocket(m_socket);
|
||||
#else
|
||||
close(m_socket);
|
||||
#endif
|
||||
m_socket = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
|
||||
if (notifyApplication && m_handler)
|
||||
m_handler->OnTerminated(this);
|
||||
|
||||
Release();
|
||||
}
|
||||
|
||||
|
||||
void TcpConnection::AddRef()
|
||||
{
|
||||
m_refCount++;
|
||||
}
|
||||
|
||||
|
||||
void TcpConnection::Release()
|
||||
{
|
||||
if (--m_refCount == 0)
|
||||
{
|
||||
//make sure manager knows I'm gone
|
||||
if (m_status != StatusDisconnected)
|
||||
Disconnect(false);
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
int TcpConnection::processIncoming()
|
||||
{
|
||||
/**< returns < 0 if fatal error and socket has been closed,
|
||||
=0 if read anything (full or partial message),
|
||||
>0 if nothing to read now, or would block so shouldn't try again immediately. */
|
||||
|
||||
if (m_status != StatusConnected)
|
||||
{
|
||||
//wait until connect succeeds
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (m_params.noDataTimeout > 0 && m_recvDataListId == m_manager->m_dataList.m_listID)
|
||||
{
|
||||
m_recvDataListId = m_manager->m_noDataList.m_listID;
|
||||
|
||||
if (m_prevRecvDataConnection != NULL)
|
||||
m_prevRecvDataConnection->m_nextRecvDataConnection = m_nextRecvDataConnection;
|
||||
if (m_nextRecvDataConnection != NULL)
|
||||
m_nextRecvDataConnection->m_prevRecvDataConnection = m_prevRecvDataConnection;
|
||||
if (m_manager->m_noDataList.m_beginList == this)
|
||||
m_manager->m_noDataList.m_beginList = m_nextRecvDataConnection;
|
||||
|
||||
m_nextRecvDataConnection = m_manager->m_dataList.m_beginList;
|
||||
m_prevRecvDataConnection = NULL;
|
||||
if (m_manager->m_dataList.m_beginList != NULL)
|
||||
m_manager->m_dataList.m_beginList->m_prevRecvDataConnection = this;
|
||||
m_manager->m_dataList.m_beginList = this;
|
||||
}
|
||||
|
||||
|
||||
int newMsg = 0;
|
||||
|
||||
|
||||
if (m_bytesRead < sizeof(int))
|
||||
{
|
||||
//new msg
|
||||
newMsg = 1;
|
||||
//printf("socket: %d\n", m_socket);
|
||||
int ret = recv(m_socket, ((char *)(&m_bytesNeeded) + m_bytesRead),
|
||||
4 - m_bytesRead, 0);
|
||||
//fprintf(stderr, "READ: %d\n", ret);
|
||||
if (ret == 0)
|
||||
{
|
||||
//We did a select, so there should be data. Socket was closed.
|
||||
Disconnect();
|
||||
return -1;
|
||||
}
|
||||
else if (ret == -1)
|
||||
{
|
||||
if (translateRecvSocketEror())
|
||||
{
|
||||
//fatal error
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//need to wait
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bytesRead += ret;
|
||||
if (m_bytesRead < 4)
|
||||
{
|
||||
return 1;//need to wait
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
m_bytesNeeded = ntohl(m_bytesNeeded);
|
||||
|
||||
//printf("m_bytesNeeded = %i\n", m_bytesNeeded);
|
||||
if (m_bytesNeeded == sizeof(int))
|
||||
{
|
||||
//keepalive, ignore
|
||||
m_bytesRead = 0;
|
||||
m_bytesNeeded = 0;
|
||||
return 0;
|
||||
}
|
||||
else if (m_bytesNeeded < sizeof(int))
|
||||
{
|
||||
//major protocol violation
|
||||
Disconnect();
|
||||
return -1;
|
||||
}
|
||||
else if (m_params.maxRecvMessageSize == 0)
|
||||
{
|
||||
if (m_recvBuff!=NULL)
|
||||
delete [] m_recvBuff;
|
||||
m_recvBuff = new char[m_bytesNeeded-4];
|
||||
}
|
||||
else if (m_params.maxRecvMessageSize != 0 && (m_bytesNeeded-4) > m_params.maxRecvMessageSize)
|
||||
{
|
||||
//error, maxRecvMeessageSize exceeded, Disconnect
|
||||
Disconnect();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int msgBytesRead = m_bytesRead - 4;
|
||||
int msgBytesNeeded = m_bytesNeeded - 4;
|
||||
|
||||
int ret = recv(m_socket, (char *)(m_recvBuff + msgBytesRead),
|
||||
msgBytesNeeded - msgBytesRead, 0);
|
||||
if (ret == 0 && !newMsg)
|
||||
{
|
||||
//We did a select, so there should be data. Socket was closed.
|
||||
Disconnect();
|
||||
return -1;
|
||||
}
|
||||
if (ret == -1)
|
||||
{
|
||||
if (translateRecvSocketEror())
|
||||
{
|
||||
//fatal error
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//need to wait
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
{
|
||||
m_bytesRead += ret;
|
||||
}
|
||||
|
||||
if (m_bytesRead == m_bytesNeeded)
|
||||
{
|
||||
m_bytesRead = 0;
|
||||
m_bytesNeeded = 0;
|
||||
if (m_handler)
|
||||
{
|
||||
AddRef();//could get deleted during this callback
|
||||
m_handler->OnRoutePacket(this, (unsigned char *)m_recvBuff, msgBytesNeeded);
|
||||
|
||||
if (m_status == StatusDisconnected)
|
||||
{
|
||||
Release();
|
||||
return -1;
|
||||
}
|
||||
Release();
|
||||
}
|
||||
|
||||
//entire message received
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;//couldn't get entire msg
|
||||
}
|
||||
}
|
||||
|
||||
int TcpConnection::processOutgoing()
|
||||
{
|
||||
/**< returns < 0 if fatal error and socket has been closed,
|
||||
=0 if sent data, call again immediately if want to,
|
||||
>0 may have sent data, but calling again would do no good because there is either no more data to send, or would block. */
|
||||
if (m_status != StatusConnected)
|
||||
{
|
||||
//wait until connect succeeds
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int sendError = 1;
|
||||
|
||||
// If m_head is not null, then this connection has something to send
|
||||
|
||||
|
||||
if(m_head)
|
||||
{
|
||||
|
||||
|
||||
int amt = ::send(m_socket, m_head->m_data + m_head->m_sentSize, m_head->m_usedSize - m_head->m_sentSize, 0);
|
||||
if(amt < 0)
|
||||
{
|
||||
#ifdef WIN32
|
||||
switch(WSAGetLastError())
|
||||
{
|
||||
case WSAEWOULDBLOCK:
|
||||
case WSAEINTR:
|
||||
case WSAEINPROGRESS:
|
||||
case WSAEALREADY:
|
||||
case WSA_IO_PENDING:
|
||||
case WSA_NOT_ENOUGH_MEMORY:
|
||||
case WSATRY_AGAIN:
|
||||
//try again
|
||||
sendError = 1;
|
||||
break;
|
||||
default:
|
||||
//assume broken, Disconnect
|
||||
Disconnect();
|
||||
sendError = -1;
|
||||
break;
|
||||
}
|
||||
#else //not WIN32
|
||||
|
||||
// error condition, EAGAIN is recoverable, otherwise raise an error condition. Break from loop
|
||||
switch(errno)
|
||||
{
|
||||
case EAGAIN:
|
||||
//try again
|
||||
sendError = 1;
|
||||
break;
|
||||
default:
|
||||
//assume broken, Disconnect
|
||||
Disconnect();
|
||||
sendError = -1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(static_cast<unsigned>(amt) < (m_head->m_usedSize - m_head->m_sentSize))
|
||||
{
|
||||
// partial send: trying to do anything more now would be a waste of time. Break from loop
|
||||
m_head->m_sentSize += amt;
|
||||
sendError = 1;
|
||||
}
|
||||
else if(amt == 0)
|
||||
{
|
||||
Disconnect();
|
||||
sendError = -1;
|
||||
// client closed connection
|
||||
}
|
||||
else
|
||||
{
|
||||
// everything was sent from this block. Return it to the pool, advance m_head. Attempt to continue
|
||||
// sending
|
||||
data_block *tmp = m_head;
|
||||
if(m_tail == m_head)
|
||||
{
|
||||
m_tail = m_tail->m_next;
|
||||
m_head = m_head->m_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_head = m_head->m_next;
|
||||
}
|
||||
m_sendAllocator->returnBlock(tmp);
|
||||
|
||||
sendError = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return sendError;
|
||||
}
|
||||
|
||||
|
||||
bool TcpConnection::translateRecvSocketEror()
|
||||
{
|
||||
/**< returns false if fatal error and socket has been closed,
|
||||
true if should try again. */
|
||||
bool fatalError=false;
|
||||
#ifdef WIN32
|
||||
|
||||
switch(WSAGetLastError())
|
||||
{
|
||||
case WSAENOBUFS:
|
||||
case WSAEINPROGRESS:
|
||||
case WSAEINTR:
|
||||
case WSAEWOULDBLOCK:
|
||||
case WSABASEERR:
|
||||
fatalError=false;
|
||||
break;
|
||||
|
||||
case WSANOTINITIALISED:
|
||||
case WSAENETDOWN:
|
||||
case WSAEFAULT:
|
||||
case WSAENOTCONN:
|
||||
case WSAENETRESET:
|
||||
case WSAENOTSOCK:
|
||||
case WSAEOPNOTSUPP:
|
||||
case WSAESHUTDOWN:
|
||||
case WSAEMSGSIZE:
|
||||
case WSAEINVAL:
|
||||
case WSAECONNABORTED:
|
||||
case WSAETIMEDOUT:
|
||||
case WSAECONNRESET:
|
||||
default:
|
||||
//fatal
|
||||
fatalError=true;
|
||||
Disconnect();
|
||||
break;
|
||||
}
|
||||
|
||||
#else //not WIN32
|
||||
|
||||
switch(errno)
|
||||
{
|
||||
case EWOULDBLOCK:
|
||||
case EINTR:
|
||||
case ETIMEDOUT:
|
||||
case ENOBUFS:
|
||||
//try later
|
||||
fatalError=false;
|
||||
break;
|
||||
|
||||
case EBADF:
|
||||
case ECONNRESET:
|
||||
case EFAULT:
|
||||
case EINVAL:
|
||||
case ENOTCONN:
|
||||
case ENOTSOCK:
|
||||
case EOPNOTSUPP:
|
||||
case EPIPE:
|
||||
case EIO:
|
||||
case ENOMEM:
|
||||
case ENOSR:
|
||||
default:
|
||||
//fatal
|
||||
fatalError=true;
|
||||
Disconnect();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return fatalError;
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
#ifndef TCPCONNECTION_H
|
||||
#define TCPCONNECTION_H
|
||||
|
||||
|
||||
#include "TcpHandlers.h"
|
||||
#include "TcpManager.h"
|
||||
#include "IPAddress.h"
|
||||
#include "TcpBlockAllocator.h"
|
||||
#include "Clock.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <winsock2.h>
|
||||
typedef int socklen_t;
|
||||
#else // for non-windows platforms (linux)
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Manages a single connection.
|
||||
*/
|
||||
class TcpConnection
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief The connection status.
|
||||
*/
|
||||
enum Status {
|
||||
StatusNegotiating, /**< Currently attempting to connect. */
|
||||
StatusConnected, /**< Currently connected. */
|
||||
StatusDisconnected /**< Currently disconnected. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Sets the handler object which will receive callback methods.
|
||||
*
|
||||
* To have the TcpConnection call your object directly when packets are received, and when the
|
||||
* connection is disconnected, you simply need to derive your class
|
||||
* (multiply if necessary) from TcpConnectionHandler, then you can use
|
||||
* this method to set the object the TcpConnection will call as appropriate.
|
||||
* default = NULL (no callbacks made)
|
||||
*
|
||||
* @param handler The object which will be called for notifications.
|
||||
*/
|
||||
void SetHandler(TcpConnectionHandler *handler){ m_handler = handler; }
|
||||
|
||||
/**
|
||||
* @brief Returns the handler associated with this object.
|
||||
*/
|
||||
TcpConnectionHandler *GetHandler(){ return m_handler; }
|
||||
|
||||
/**
|
||||
* @brief Returns the current status of this connection.
|
||||
*/
|
||||
Status GetStatus(){ return m_status; }
|
||||
|
||||
/**
|
||||
* @brief Queues a message to be sent on this connection.
|
||||
*/
|
||||
void Send(const char *data, unsigned dataLen);
|
||||
|
||||
/**
|
||||
* @brief Disconnects and recycles the socket.
|
||||
*
|
||||
* @param notifyApplication primarily used internally, but when set to 'true', it will cause the application
|
||||
* to be called back via the onTerminated handler due to this call (the callback will not occur if the connection was
|
||||
* already disconnected)
|
||||
*/
|
||||
void Disconnect(bool notifyApplication=true);
|
||||
|
||||
/**
|
||||
* @brief Returns the ip on the other side of this connection.
|
||||
*/
|
||||
IPAddress GetDestinationIp(){ return m_destIP; }
|
||||
|
||||
/**
|
||||
* @brief Returns the port on the other side of this conection.
|
||||
*/
|
||||
short GetDestinationPort(){ return m_destPort; }
|
||||
|
||||
/**
|
||||
* @brief Standard AddRef/Release scheme
|
||||
*/
|
||||
void AddRef();
|
||||
|
||||
/**
|
||||
* @brief Standard AddRef/Release scheme
|
||||
*/
|
||||
void Release();
|
||||
|
||||
bool wasRemovedFromMgr() { return m_wasConRemovedFromMgr; }
|
||||
void setRemovedFromMgr() { m_wasConRemovedFromMgr = true; }
|
||||
|
||||
protected:
|
||||
friend class TcpManager;
|
||||
TcpConnection(TcpManager *tcpManager, TcpBlockAllocator *sendAlloc, TcpManager::TcpParams ¶ms, const IPAddress &destIP, short destPort, unsigned timeout);
|
||||
int finishConnect();/**< returns < 0 if fatal error and connect will not work, =0 if need more time, >0 if connect completed */
|
||||
TcpConnection(TcpManager *tcpManager, TcpBlockAllocator *sendAlloc, TcpManager::TcpParams ¶ms, SOCKET socket, const IPAddress &destIP, short destPort);
|
||||
TcpConnection *m_nextConnection; /**< Double linked list imp. */
|
||||
TcpConnection *m_prevConnection; /**< Double linked list imp. */
|
||||
SOCKET m_socket;
|
||||
int processOutgoing();/**< returns < 0 if fatal error and socket has been closed, =0 if sent data, call again immediately if want to, >0 may have sent data, but calling again would do no good because there is either no more data to send, or would block. */
|
||||
int processIncoming();/**< returns < 0 if fatal error and socket has been closed, =0 if read anything (full or partial message), >0 if nothing to read now, or would block so shouldn't try again immediately. */
|
||||
|
||||
|
||||
TcpConnection *m_nextKeepAliveConnection; /**< Double linked list imp. */
|
||||
TcpConnection *m_prevKeepAliveConnection; /**< Double linked list imp. */
|
||||
int m_aliveListId;
|
||||
|
||||
TcpConnection *m_nextRecvDataConnection;
|
||||
TcpConnection *m_prevRecvDataConnection;
|
||||
int m_recvDataListId;
|
||||
|
||||
private:
|
||||
~TcpConnection();
|
||||
void setOptions();
|
||||
TcpManager *m_manager;
|
||||
bool translateRecvSocketEror();
|
||||
Status m_status;
|
||||
TcpConnectionHandler *m_handler;
|
||||
IPAddress m_destIP;
|
||||
short m_destPort;
|
||||
unsigned m_refCount;
|
||||
TcpBlockAllocator *m_sendAllocator;
|
||||
data_block *m_head;
|
||||
data_block *m_tail;
|
||||
unsigned m_bytesRead;
|
||||
unsigned m_bytesNeeded;
|
||||
TcpManager::TcpParams m_params;
|
||||
char *m_recvBuff;
|
||||
sockaddr_in m_addr;
|
||||
unsigned m_connectTimeout;
|
||||
Clock m_connectTimer;
|
||||
|
||||
bool m_wasConRemovedFromMgr;
|
||||
};
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif //TCPCONNECTION_H
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user