최종완료보고 버전

This commit is contained in:
CodeTempla
2026-05-20 03:08:08 +09:00
commit 10d255ed51
548 changed files with 435582 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
#ifndef BAIL_BUFFER__H_
#define BAIL_BUFFER__H_
#ifdef _WIN32
#pragma once
#endif
class HBailBuffer : public HObject
{
public:
HBailBuffer(size_t nSize)
{
m_pBuffer = (char *)malloc(nSize);
m_nBufferSize = nSize;
m_pBufferOffset = m_pBuffer;
m_nStoredSize = 0;
}
~HBailBuffer()
{
free(m_pBuffer);
}
inline char * Offset() { return m_pBufferOffset; }
inline void MoveOffset(size_t nSize)
{
m_pBufferOffset += nSize;
m_nStoredSize += nSize;
}
inline void Reset()
{
m_pBufferOffset = m_pBuffer;
m_nStoredSize = 0;
}
public:
char * m_pBuffer;
size_t m_nBufferSize;
size_t m_nStoredSize;
protected:
char * m_pBufferOffset;
};
#endif // BAIL_BUFFER__H_
+397
View File
@@ -0,0 +1,397 @@
#ifndef BLOCK_LIST_BUFFER__H_
#define BLOCK_LIST_BUFFER__H_
#ifdef _WIN32
#pragma once
#endif
struct _TBinaryBlock
{
char * pData;
char * pDataOffset;
int nSize;
};
typedef struct _TBinaryBlock TBinaryBlock;
class HBlockListBuffer : public HObject
{
public:
HBlockListBuffer(int nBlockSize)
{
m_nBlockSize = nBlockSize;
m_nTotalSize = 0; //...
}
~HBlockListBuffer()
{
RemoveAll();
}
inline size_t GetCount() { return listBinaryBlock.size(); }
inline int GetTotalSize()
{
int nTotalSize = 0;
for (std::list<TBinaryBlock>::iterator iter = listBinaryBlock.begin();
iter != listBinaryBlock.end(); iter++)
{
if (iter->nSize > 0)
nTotalSize += iter->nSize;
}
return nTotalSize;
}
inline bool Enqueue(const char * pData, int nSize)
{
if (nSize <= 0) //... command, -1 = end mark
{
TBinaryBlock blockNew;
blockNew.nSize = nSize;
listBinaryBlock.push_back(blockNew);
return true;
}
if (listBinaryBlock.empty() == false)
{
#if 1
std::list<TBinaryBlock>::iterator iter = listBinaryBlock.end();
iter--;
if (iter->nSize <= 0)
return false;
int nRemainBufer = m_nBlockSize - iter->nSize - (iter->pDataOffset - iter->pData);
if (nRemainBufer > nSize)
{
memcpy(iter->pDataOffset + iter->nSize, pData, nSize);
iter->nSize += nSize;
return true;
}
else
{
if (nRemainBufer > 0)
{
memcpy(iter->pDataOffset + iter->nSize, pData, nRemainBufer);
iter->nSize += nRemainBufer;
pData += nRemainBufer;
nSize -= nRemainBufer;
}
}
#endif
}
while (nSize > 0)
{
TBinaryBlock blockNew;
blockNew.pData = (char *)malloc(m_nBlockSize);
blockNew.pDataOffset = blockNew.pData;
if (nSize <= m_nBlockSize)
{
memcpy(blockNew.pDataOffset, pData, nSize);
blockNew.nSize = nSize;
nSize = 0;
}
else
{
memcpy(blockNew.pDataOffset, pData, m_nBlockSize);
blockNew.nSize = m_nBlockSize;
pData += m_nBlockSize;
nSize -= m_nBlockSize;
}
listBinaryBlock.push_back(blockNew);
}
return true;
}
inline bool Dequeue(char * pDst, int nCount)
{
if (nCount > GetTotalSize())
return false;
int nRemainSize = nCount;
std::list<TBinaryBlock>::iterator iter = listBinaryBlock.begin();
while (iter != listBinaryBlock.end())
{
if (iter->nSize < 0)
return false;
if (nRemainSize < nCount)
{
if (iter->nSize < nRemainSize)
{
memcpy(pDst, iter->pDataOffset, iter->nSize);
pDst += iter->nSize;
nRemainSize -= iter->nSize;
free(iter->pData);
iter = listBinaryBlock.erase(iter);
}
else
{
memcpy(pDst, iter->pDataOffset, nRemainSize);
if (iter->nSize == nRemainSize)
{
free(iter->pData);
listBinaryBlock.erase(iter);
}
else
{
iter->pDataOffset += nRemainSize;
iter->nSize -= nRemainSize;
}
return true;
}
}
else if (iter->nSize > 0)
{
if (iter->nSize < nCount)
{
memcpy(pDst, iter->pDataOffset, iter->nSize);
pDst += iter->nSize;
nRemainSize -= iter->nSize;
free(iter->pData);
iter = listBinaryBlock.erase(iter);
}
else
{
memcpy(pDst, iter->pDataOffset, nCount);
if (iter->nSize == nCount)
{
free(iter->pData);
listBinaryBlock.erase(iter);
}
else
{
iter->pDataOffset += nCount;
iter->nSize -= nCount;
}
return true;
}
}
}
return false;
}
bool DequeueAll(char * pDst)
{
std::list<TBinaryBlock>::iterator iter = listBinaryBlock.begin();
while (iter != listBinaryBlock.end())
{
if (iter->nSize <= 0) //...
return false;
memcpy(pDst, iter->pDataOffset, iter->nSize);
pDst += iter->nSize;
free(iter->pData);
iter = listBinaryBlock.erase(iter);
}
return true;
}
inline bool GetFront(char ** ppData, int * pnSize)
{
std::list<TBinaryBlock>::iterator iter = listBinaryBlock.begin();
if (iter == listBinaryBlock.end())
return false;
if (iter->nSize > 0)
*ppData = iter->pDataOffset;
*pnSize = iter->nSize;
return true;
}
inline void PopFront()
{
std::list<TBinaryBlock>::iterator iter = listBinaryBlock.begin();
if (iter == listBinaryBlock.end())
return;
if (iter->nSize > 0)
free(iter->pData);
listBinaryBlock.erase(iter);
}
inline bool ReduceFront(int nSize)
{
if (nSize > m_nBlockSize)
return false;
std::list<TBinaryBlock>::iterator iter = listBinaryBlock.begin();
if (iter == listBinaryBlock.end())
return false;
if (iter->nSize <= 0)
{
return false;
}
else if (nSize > iter->nSize)
{
return false;
}
else if (nSize == iter->nSize)
{
free(iter->pData);
listBinaryBlock.erase(iter);
return true;
}
iter->pDataOffset += nSize;
iter->nSize -= nSize;
return true;
}
inline void RemoveAll()
{
for (std::list<TBinaryBlock>::iterator iter = listBinaryBlock.begin();
iter != listBinaryBlock.end(); iter++)
{
if (iter->nSize > 0)
free(iter->pData);
}
listBinaryBlock.clear();
}
HDynamicArray<char> ChangeAndClear(int * pnSize, int nExtra)
{
*pnSize = GetTotalSize();
if (*pnSize <= 0)
return (char *)NULL;
char * pBuffer = (char *)malloc(*pnSize + nExtra);
char * pOffset = pBuffer;
for (std::list<TBinaryBlock>::iterator iter = listBinaryBlock.begin();
iter != listBinaryBlock.end(); iter++)
{
if (iter->nSize > 0) //...
{
memcpy(pOffset, iter->pDataOffset, iter->nSize);
pOffset += iter->nSize;
}
free(iter->pData);
}
listBinaryBlock.clear();
return pBuffer;
}
inline bool Copy(char * pDst, int nStartPos, int nCount)
{
int nRemainSize = nCount;
int i = 0;
for (std::list<TBinaryBlock>::iterator iter = listBinaryBlock.begin();
iter != listBinaryBlock.end(); iter++)
{
if (iter->nSize < 0)
return false;
i += iter->nSize;
if (nRemainSize < nCount)
{
if (iter->nSize < nRemainSize)
{
memcpy(pDst, iter->pDataOffset, iter->nSize);
pDst += iter->nSize;
nRemainSize -= iter->nSize;
}
else
{
memcpy(pDst, iter->pDataOffset, nRemainSize);
return true;
}
}
else if (i > nStartPos) //...
{
int nBlockRemain = i - nStartPos;
int nBlockStartIndex = iter->nSize - nBlockRemain;
if (nBlockRemain < nCount)
{
memcpy(pDst, iter->pDataOffset + nBlockStartIndex, nBlockRemain);
pDst += nBlockRemain;
nRemainSize -= nBlockRemain;
}
else
{
memcpy(pDst, iter->pDataOffset + nBlockStartIndex, nCount);
return true;
}
}
}
return false;
}
int SearchChr(int nStartPos, char ch)
{
int i = 0, j;
for (std::list<TBinaryBlock>::iterator iter = listBinaryBlock.begin();
iter != listBinaryBlock.end(); iter++)
{
if (iter->nSize < 0)
return -1;
if (i + iter->nSize > nStartPos)
{
for (j = 0; j < iter->nSize; j++)
{
if (i >= nStartPos && iter->pDataOffset[j] == ch)
return i;
i++;
}
}
else
i += iter->nSize;
}
return -1;
}
#ifdef _DEBUG
void Print()
{
printf("Print, count = %d\n", listBinaryBlock.size());
int i = 0;
for (std::list<TBinaryBlock>::iterator iter = listBinaryBlock.begin();
iter != listBinaryBlock.end(); iter++)
{
printf("%d, ", i++);
if (iter->nSize > 0)
{
for (int j = 0; j < iter->nSize; j++)
putchar(iter->pDataOffset[j]);
}
putchar('\n');
}
}
#endif
protected:
std::list<TBinaryBlock> listBinaryBlock;
int m_nBlockSize;
int m_nTotalSize;
};
#endif // BLOCK_LIST_BUFFER__H_
+109
View File
@@ -0,0 +1,109 @@
#include "Common.h"
unsigned int ELFHash(const char * str, unsigned int len)
{
unsigned int hash = 0;
unsigned int x = 0;
unsigned int i = 0;
for (i = 0; i < len; str++, i++)
{
hash = (hash << 4) + (*str);
if ((x = hash & 0xF0000000L) != 0)
{
hash ^= (x >> 24);
}
hash &= ~x;
}
return hash;
}
// Caution! : 0 ~ RAND_MAX
unsigned _GetRandNum(unsigned nMin, unsigned nMax)
{
if ((nMin == 0 && nMax == 0) ||
nMin > nMax)
{
//printf("[WARN] Invalide parameter.\n");
return 0;
}
if (nMax > RAND_MAX)
{
nMax = RAND_MAX;
//printf("[WARN] Invalide parameter.\n");
}
static bool bRandInit = false;
if (bRandInit == false)
{
bRandInit = true;
srand((unsigned)time(NULL));
}
unsigned nRandNum;
for (;;)
{
nRandNum = (unsigned)rand();
if (nRandNum >= nMin && nRandNum <= nMax)
break;
}
return nRandNum;
}
bool RealignPathDepth(const char * pszSrc, char * pszDst)
{
if (pszSrc == NULL || pszDst == NULL)
return false;
if (pszSrc[0] == '\0')
{
pszDst[0] = '\0';
return true;
}
const char * p1 = pszSrc;
char * p2 = pszDst;
do
{
if (p1[0] == '.' && p1[1] == '.' && p1[2] == '.')
{
do
{
if (*p1 == '/' || *p1 == '\\' || *p1 == '\0')
break;
*p2++ = *p1;
} while (p1++);
}
if (*p1 == '\0')
break;
if (p1[0] == '.' && p1[1] == '.' && (p1[2] == '/' || p1[2] == '\\'))
{
for (int i = 0; i < 2; i++)
{
while (p2 != pszDst && p2--)
{
if (*p2 == '/' || *p2 == '\\' || p2 == pszDst)
break;
}
}
p1 += 2;
}
*p2++ = *p1;
} while (p1++);
*p2 = '\0';
return true;
}
+372
View File
@@ -0,0 +1,372 @@
#ifndef COMMON__H_
#define COMMON__H_
#ifdef _WIN32
#pragma once
//#define FD_SETSIZE 1024
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib, "winmm.lib")
#pragma warning(disable:4996)
#include <io.h>
#else
#include <unistd.h> // fork
#include <errno.h> // errno
#include <sys/wait.h> // wait
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/timeb.h> // ftime
#include <fcntl.h>
#include <sys/stat.h>
#ifdef USE_STD_ASSERT
#include <assert.h>
#elif USE_TENMIN_ASSERT
#define assert(EXP) (void)((!!(EXP)) || (tmassert((#EXP), __FILE__, __LINE__), 0))
inline void tmassert(const char * psz, const char * pszFileName, unsigned nLine)
{
//ALOG(1, "[FATAL ERROR], Assertion failed : %s, file : %s, line : %d\n", psz, pszFileName, nLine);
exit(-1);
}
#else
#if _MSC_VER <= 1200
#define assert(EXP) ((void)0)
#else
#define assert(EXP) __noop
#endif
#endif
#ifdef _WIN32
#pragma once
#else
#ifndef NULL
#define NULL 0
#endif
typedef unsigned int DWORD;
#ifndef false
#define false 0
#endif
#ifndef true
#define true 1
#endif
#endif // _WIN32
#define TENMIN_FAILED 0
#define TENMIN_SUCCESS 1
#ifdef _WIN32
#if _MSC_VER <= 1200
#ifdef _DEBUG
#include <crtdbg.h>
#include <malloc.h>
#include <list>
#include <queue>
#include <set>
#include <map>
#include <string>
// add stl header ...
inline void * operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
{
return _malloc_dbg(nSize, _NORMAL_BLOCK, lpszFileName, nLine);
}
inline void operator delete(void * p)
{
_free_dbg(p, _NORMAL_BLOCK);
}
inline void operator delete(void * p, LPCSTR, int)
{
_free_dbg(p, _NORMAL_BLOCK);
}
#define new new(__FILE__, __LINE__)
#define malloc(SIZE) _malloc_dbg(SIZE, _NORMAL_BLOCK, __FILE__, __LINE__)
#define free(PTR) _free_dbg(PTR, _NORMAL_BLOCK)
#endif // _DEBUG
#endif // _MSC_VER <= 1200
#ifndef snprintf
#define snprintf _snprintf
#endif
#ifndef strcasecmp
#define strcasecmp stricmp
#endif
#define sched_yield() Sleep(0)
#endif // _WIN32
unsigned GetRandNum(unsigned nMin, unsigned nMax); // return 0 ~ RAND_MAX
unsigned int ELFHash(const char * str, unsigned int len);
extern inline int GetLastDayOfTheMonth(int nYear, int nMonth)
{
struct tm tmTmp = { 0, 0, 0, 1, nMonth, nYear - 1900 };
time_t timeTmp = mktime(&tmTmp) - 86400;
if (timeTmp < 0)
return -1;
struct tm * ptmNewTmp = localtime(&timeTmp);
return ptmNewTmp->tm_mday;
}
extern inline unsigned int TimeDiff(unsigned int nTimePrev, unsigned int nTimeCurr)
{
if (nTimePrev <= nTimeCurr)
return nTimeCurr - nTimePrev;
return nTimeCurr + (0xFFFFFFFFU - nTimePrev) + 1U;
}
///////////////////////////////////////
#define TERR_INVALID_PROCESSNAME 2 // Failed to access()
#define TERR_FAILED_FORK 3 // Failed to fork()
#define TERR_FAILED_WAIT 4 // Failed to wait()
extern inline int ExecuteProcess(const char * pszProcessName,
const char * pszCommandLine, bool bWaiting = false, int * pnExitCode = NULL)
{
#ifdef _WIN32
STARTUPINFO startUpInfo;
memset(&startUpInfo, 0, sizeof startUpInfo);
startUpInfo.cb = sizeof(STARTUPINFO);
//char cmdline[] = "dir /w";
char cmdline[] = "calc";
PROCESS_INFORMATION processInfo;
memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
BOOL b = CreateProcess( NULL, cmdline, NULL, NULL, false,
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &startUpInfo, &processInfo);
DWORD dwErr = 0;
if( b ) {
WaitForSingleObject( processInfo.hProcess, INFINITE );
GetExitCodeProcess( processInfo.hProcess, &dwErr );
CloseHandle( processInfo.hProcess );
printf("\n\n ------- ExecuteProcess error1 --------\n\n");
} else {
dwErr = GetLastError();
printf("\n\n ------- ExecuteProcess error2 --------\n\n");
}
if( dwErr ) {
// deal with error here
printf("\n\n ------- ExecuteProcess error3 --------\n\n");
}
return TENMIN_SUCCESS;
#else
if (pszProcessName == NULL || pszProcessName[0] == '\0' || access(pszProcessName, X_OK) == -1)
return TERR_INVALID_PROCESSNAME;
int nPid = fork();
if (nPid == -1)
{
return TERR_FAILED_FORK;
}
else if (nPid == 0)
{
//if (execvp(pszProcessName, (char* const*)lpszArgList) == -1)
{
if (errno)
_exit(errno);
}
_exit(255);
}
if (bWaiting)
{
int nStatVal;
if (wait(&nStatVal) == -1)
return TERR_FAILED_WAIT;
if (pnExitCode)
{
if (WIFEXITED(nStatVal))
*pnExitCode = WEXITSTATUS(nStatVal);
}
}
return TENMIN_SUCCESS;
#endif
}
#ifndef _WIN32
#if defined(__ANDROID__) || defined(ANDROID)
#ifndef S_IREAD
#define S_IREAD S_IRUSR
#endif
#ifndef S_IWRITE
#define S_IWRITE S_IWUSR
#endif
#ifndef S_IEXEC
#define S_IEXEC S_IXUSR
#endif
#endif
extern inline DWORD timeGetTime()
{
#if 0
struct timeval tv;
gettimeofday(&tv, NULL); // obsolescent at 2008
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
#endif
}
#define GetTickCount timeGetTime
extern inline void Sleep(DWORD nTime)
{
#if 0
struct timeval tv;
tv.tv_sec = nTime / 1000;
tv.tv_usec = (nTime % 1000) * 1000; // msec
select(0, NULL, NULL, NULL, &tv);
#else
struct timespec ts;
ts.tv_sec = nTime / 1000;
ts.tv_nsec = (nTime % 1000) * 1000000; // nsec
nanosleep(&ts, NULL);
#endif
}
typedef struct tagSYSTEMTIME
{
DWORD wYear;
DWORD wMonth;
DWORD wDay;
DWORD wHour;
DWORD wMinute;
DWORD wSecond;
DWORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME;
extern inline void GetLocalTime(PSYSTEMTIME lpSystemTime)
{
struct tm * tmTmp;
struct timeb tTimeb;
ftime(&tTimeb);
tmTmp = localtime(&tTimeb.time);
lpSystemTime->wYear = tmTmp->tm_year + 1900;
lpSystemTime->wMonth = tmTmp->tm_mon + 1;
lpSystemTime->wDay = tmTmp->tm_mday;
lpSystemTime->wHour = tmTmp->tm_hour;
lpSystemTime->wMinute = tmTmp->tm_min;
lpSystemTime->wSecond = tmTmp->tm_sec;
lpSystemTime->wMilliseconds = tTimeb.millitm;
}
#endif // _WIN32
extern inline void GetCurrentDatetime(char * pszDst, int nType = 0)
{
SYSTEMTIME systemTime;
GetLocalTime(&systemTime);
if (nType == 0) // YYYY-MM-DD hh:mm:ss
sprintf(pszDst, "%.4ld-%.2ld-%.2ld %.2ld:%.2ld:%.2ld", systemTime.wYear, systemTime.wMonth, systemTime.wDay,
systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
else if (nType == 1) // YYYYMMDDhhmmss
sprintf(pszDst, "%.4ld%.2ld%.2ld%.2ld%.2ld%.2ld", systemTime.wYear, systemTime.wMonth, systemTime.wDay,
systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
else if (nType == 2) // YYYYMMDDhhmmss.msec
sprintf(pszDst, "%.4ld%.2ld%.2ld%.2ld%.2ld%.2ld.%.3ld", systemTime.wYear,
systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds);
}
extern inline void GetDateTimeNum(char * pszDst)
{
SYSTEMTIME systemTime;
GetLocalTime(&systemTime);
sprintf(pszDst, "%.4ld%.2ld%.2ld%.2ld%.2ld%.2ld.%.3ld", systemTime.wYear,
systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds);
}
extern inline void GetDateTimeNum2(char * pszDst)
{
SYSTEMTIME systemTime;
GetLocalTime(&systemTime);
sprintf(pszDst, "%.4ld%.2ld%.2ld%.2ld%.2ld%.2ld", systemTime.wYear,
systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
}
bool RealignPathDepth(const char * pszSrc, char * pszDst);
extern inline bool GetProcessDirectory(char * pszDir, DWORD nBufferLength)
{
#ifdef _WIN32
if (::GetModuleFileName(NULL, pszDir, nBufferLength) == FALSE)
return false;
if (::GetLongPathName(pszDir, pszDir, nBufferLength) == FALSE)
return false;
char * pTemp;
if ((pTemp = strrchr(pszDir, '\\')) != NULL ||
(pTemp = strrchr(pszDir, '/')) != NULL)
{
size_t nLen = strlen(pszDir) - strlen(pTemp);
pszDir[nLen + 1] = '\0';
}
#else
//...
#endif
return true;
}
extern inline void Hassert(bool b)
{
}
#endif // COMMON__H_
+69
View File
@@ -0,0 +1,69 @@
#include "stringex.h"
#include "Defines.h"
#include "Common.h"
#include "Object.h"
#include "String.h"
#include "File.h"
#include "Config.h"
#include "inifile.h"
HConfig::HConfig()
{
m_pIniFile = new HIniFile;
}
HConfig::~HConfig()
{
delete m_pIniFile;
}
bool HConfig::OpenConfig(const char * pszPathName)
{
HFile file;
if (file.Open(pszPathName, HFile::FMODE_RDONLY) == false)
return false;
m_pIniFile->SetIniFile(pszPathName);
m_strConfigFile = pszPathName;
return true;
}
void HConfig::CloseConfig()
{
}
HString HConfig::ReadString(const char * pszSetionName, const char * pszKeyName, const char * pszDefault)
{
return m_pIniFile->ReadString(pszSetionName, pszKeyName, pszDefault);
}
bool HConfig::WriteString(const char * pszSetionName, const char * pszKeyName, const char * pszString)
{
return m_pIniFile->WriteString(pszSetionName, pszKeyName, pszString);
}
int HConfig::ReadNumber(const char * pszSetionName, const char * pszKeyName, int nDefault)
{
return m_pIniFile->ReadNumber(pszSetionName, pszKeyName, nDefault);
}
bool HConfig::WriteNumber(const char * pszSetionName, const char * pszKeyName, int nNumber)
{
return m_pIniFile->WriteNumber(pszSetionName, pszKeyName, nNumber);
}
bool HConfig::ReadBoolean(const char * pszSetionName, const char * pszKeyName, bool bDefault)
{
return m_pIniFile->ReadBoolean(pszSetionName, pszKeyName, bDefault);
}
bool HConfig::WriteBoolean(const char * pszSetionName, const char * pszKeyName, bool bValue)
{
return m_pIniFile->WriteBoolean(pszSetionName, pszKeyName, bValue);
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef CONFIG__H_
#define CONFIG__H_
#ifdef _WIN32
#pragma once
#endif
class HIniFile;
class HConfig : public HObject
{
public:
HConfig();
~HConfig();
virtual bool OpenConfig(const char * pszPathName);
virtual void CloseConfig();
virtual inline const char * GetConfigPathName() { return m_strConfigFile; }
virtual HString ReadString(const char * pszSetionName, const char * pszKeyName, const char * pszDefault);
virtual bool WriteString(const char * pszSetionName, const char * pszKeyName, const char * pszString);
virtual int ReadNumber(const char * pszSetionName, const char * pszKeyName, int nDefault);
virtual bool WriteNumber(const char * pszSetionName, const char * pszKeyName, int nNumber);
virtual bool ReadBoolean(const char * pszSetionName, const char * pszKeyName, bool bDefault);
virtual bool WriteBoolean(const char * pszSetionName, const char * pszKeyName, bool bValue);
private:
HString m_strConfigFile;
HIniFile * m_pIniFile;
};
#endif // CONFIG__H_
+111
View File
@@ -0,0 +1,111 @@
#ifndef DATA_STRUCT__H_
#define DATA_STRUCT__H_
#ifdef _WIN32
#pragma once
#endif
#include <list>
#include <vector>
#include <map>
#if 0
template<class _T>
class HBuffer
{
public:
HBuffer() { m_pBuf = NULL; m_nSize = 0; }
HBuffer(size_t n) { if (n) m_pBuf = (_T *)malloc(n * sizeof(_T)); else m_pBuf = NULL; m_nSize = n; }
virtual ~HBuffer() { if (m_pBuf) free(m_pBuf); }
inline _T * GetPtr() { return m_pBuf; }
inline size_t GetSize() { return m_nSize; }
inline void Create(size_t n)
{
if (n)
m_pBuf = (_T *)malloc(n * sizeof(_T));
m_nSize = n;
}
inline bool Copy(_T * pData, size_t nSize)
{
if (pData == NULL || nSize <= 0)
return false;
memcpy(m_pBuf, pData, nSize);
}
protected:
_T * m_pBuf;
size_t m_nSize;
};
#endif
template<class _T>
class HDynamicArray
{
public:
HDynamicArray(size_t n) { if (n) m_p = (_T *)malloc(n * sizeof(_T)); else m_p = NULL; }
HDynamicArray(_T * p) { m_p = p; }
~HDynamicArray() { if (m_p) free(m_p); }
inline void Attach(_T * p) { m_p = p; }
inline void Detatch() { m_p = NULL; }
inline void Realloc(size_t n) { free(m_p); m_p = (_T *)malloc(n * sizeof(_T)); }
inline void Restruct(_T * p) { free(m_p); m_p = p; }
_T * m_p;
};
class HStrList : public std::list<HString>
{
public:
HStrList() {}
~HStrList() {}
inline void SplitAdd(const HString & str, char chDelimiter)
{
HStringTokenizer token(str, chDelimiter);
for (size_t i = 0; i < token.GetCount(); i++)
{
push_back(token[i]);
}
}
};
class HStrVector : public std::vector<HString>
{
public:
HStrVector() {}
~HStrVector() {}
inline void Remove(const char * psz)
{
erase(std::remove(begin(), end(), psz), end());
}
inline bool IsExist(const char * psz)
{
HString str = psz;
return std::find(begin(), end(), str) != end();
}
};
class HStrStrMap : public std::map<HString, HString>
{
public:
HStrStrMap() {}
~HStrStrMap() {}
inline void Insert(const char * pszKey, const char * pszValue)
{
insert(std::pair<HString, HString>(pszKey, pszValue));
}
};
#endif // DATA_STRUCT__H
+17
View File
@@ -0,0 +1,17 @@
#ifndef DEFINES__H_
#define DEFINES__H_
#ifdef _WIN32
#pragma once
#endif
#define HLOG_ERROR 1
#define HLOG_WARNING 3
#define HLOG_INFO1 5
#define HLOG_INFO2 6
#define HLOG_INFO3 7
#define HLOG_INFO4 9
#define HLOG_INFO5 11
#endif
+180
View File
@@ -0,0 +1,180 @@
#ifndef EMAIL_SENDER__H_
#define EMAIL_SENDER__H_
#ifdef _WIN32
#pragma once
#endif
class HEmailSender : public HThread
{
public:
HEmailSender(const HString & strIp, u_short nPort, const HString & strSubject, const HString & strMessage, const HString & strFrom, const HStrList & listTo)
: HThread(true)
{
HLOGF(HLOG_INFO5, "INFO, EmailSender, new, %s, %d, %s, %s, %s\n", strIp.psz(), nPort, strFrom.psz(), strSubject.psz(), strMessage.psz());
m_strIp = strIp;
m_nPort = nPort;
m_strSubject = strSubject;
m_strMessage = strMessage;
m_strFrom = strFrom;
m_listTo = listTo;
Begin();
}
~HEmailSender() {}
bool SendCompleteSize(SOCKET sock, const char * pszPacket, size_t nPacketSize)
{
HLOGF(HLOG_ERROR, "[TRACE], EmailSender, tx, %s", pszPacket);
off_t nSentSize;
const char * pszPacketOffset = pszPacket;
while (nPacketSize > 0)
{
nSentSize = send(sock, pszPacketOffset, nPacketSize, 0);
if (nSentSize <= 0)
{
HLOG(HLOG_ERROR, "[ERROR], EmailSender, Failed to send.\n");
return false;
}
nPacketSize -= nSentSize;
pszPacketOffset += nSentSize;
}
return true;
}
bool RecvCompleteResponse(SOCKET sock)
{
int nRecvSize;
char pBuffer[8192];
char * pBufferOffset = pBuffer;
for (;;)
{
nRecvSize = recv(sock, pBufferOffset, 8191, 0);
if (nRecvSize <= 0 || (pBuffer[0] != '2' && pBuffer[0] != '3')) // '2' is error return
break;
pBufferOffset[nRecvSize] = '\0';
if (strstr(pBuffer, "\r\n"))
{
HLOGF(HLOG_ERROR, "[TRACE], EmailSender, rx, %s", pBuffer);
return true;
}
pBufferOffset += nRecvSize;
}
return false;
}
void Main()
{
// send message /////////////////////////////////////
SOCKET sockClient;
// create socket
sockClient = socket(AF_INET, SOCK_STREAM, 0);
if (sockClient == INVALID_SOCKET)
{
HLOG(HLOG_ERROR, "[ERROR], EmailSender, Failed to socket()\n");
return;
}
// set destination address
struct sockaddr_in sai;
memset(&sai, '\0', sizeof(struct sockaddr_in));
sai.sin_addr.s_addr = inet_addr(m_strIp);
sai.sin_family = AF_INET;
sai.sin_port = htons(m_nPort);
HLOG(HLOG_INFO5, "INFO, EmailSender, Trying to connect...\n");
if (connect(sockClient, (struct sockaddr *)&sai, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
HLOGF(HLOG_ERROR, "[ERROR], EmailSender, connect timeout. socket = %d\n", sockClient);
return;
}
HLOG(HLOG_INFO5, "INFO, EmailSender, Connected\n");
//HELO 14.34.59.93
//MAIL FROM: sender@nate.com
//RCPT TO: comicgum@nate.com
//DATA
//From: tester<sender@nate.com>
//To: comicgum<comicgum@nate.com>
//Subject: test subject
//Test Message...
//.
//QUIT
size_t nSendSize;
char szCommand[16384];
if (RecvCompleteResponse(sockClient) == false)
return;
nSendSize = sprintf(szCommand, "HELO %s\r\n", m_strIp.psz()); // SMTP server address
if (SendCompleteSize(sockClient, szCommand, nSendSize) == false || RecvCompleteResponse(sockClient) == false)
return;
nSendSize = sprintf(szCommand, "MAIL FROM: %s\r\n", m_strFrom.psz()); // sender email address
if (SendCompleteSize(sockClient, szCommand, nSendSize) == false || RecvCompleteResponse(sockClient) == false)
return;
HString strTo;
HStrList::iterator iter = m_listTo.begin();
for (;;)
{
nSendSize = sprintf(szCommand, "RCPT TO: %s\r\n", iter->psz()); // return email address
if (SendCompleteSize(sockClient, szCommand, nSendSize) == false || RecvCompleteResponse(sockClient) == false)
return;
strTo += iter->psz();
if (++iter == m_listTo.end())
break;
strTo += ",";
}
nSendSize = sprintf(szCommand, "DATA\r\n"); // messgae start
if (SendCompleteSize(sockClient, szCommand, nSendSize) == false || RecvCompleteResponse(sockClient) == false)
return;
nSendSize = sprintf(szCommand, //"%s\r\n",
"From: LibProxy3<%s>\r\n"
"To: %s\r\n"
"Subject: %s\r\n"
"%s\r\n.\r\n", m_strFrom.psz(), strTo.psz(), m_strSubject.psz(), m_strMessage.psz()); // message
if (SendCompleteSize(sockClient, szCommand, nSendSize) == false || RecvCompleteResponse(sockClient) == false)
return;
nSendSize = sprintf(szCommand, "QUIT\r\n"); // end
if (SendCompleteSize(sockClient, szCommand, nSendSize) == false || RecvCompleteResponse(sockClient) == false)
return;
#ifdef _WIN32
closesocket(sockClient);
#else
closesocket(sockClient);
#endif
}
protected:
HString m_strIp;
u_short m_nPort;
HString m_strSubject;
HString m_strMessage;
HString m_strFrom;
HStrList m_listTo;
};
#endif // EMAIL_SENDER__H_
+130
View File
@@ -0,0 +1,130 @@
#ifndef FILE__H_
#define FILE__H_
#ifdef _WIN32
#pragma once
#endif
class HFile
{
public:
enum
{
FMODE_CREATE = 0x0001,
FMODE_RDONLY = 0x0002,
FMODE_WRONLY = 0x0004,
FMODE_RW = 0x0008
};
static off_t GetSize(const char * pszFileName)
{
struct stat statTemp;
stat(pszFileName, &statTemp);
return statTemp.st_size;
}
////
HFile()
{
m_fdFile = -1;
}
~HFile()
{
Close();
}
inline int GetFile();
inline bool Open(const char * pszFileName, int nMode, bool bIsContinue = false, bool bIsBinary = true);
inline void Close();
inline int Read(void * buffer, unsigned int count);
inline int ReadString(char * buffer, unsigned int count);
inline int Write(const void * buffer, unsigned int count);
private:
int m_fdFile;
};
inline int HFile::GetFile() { return m_fdFile; }
inline bool HFile::Open(const char * pszFileName, int nMode, bool bIsContinue, bool bIsBinary)
{
int oflag = 0;
if ((nMode & FMODE_CREATE) == FMODE_CREATE)
oflag = O_CREAT;
if ((nMode & FMODE_RDONLY) == FMODE_RDONLY)
oflag |= O_RDONLY;
else if ((nMode & FMODE_WRONLY) == FMODE_WRONLY)
oflag |= O_WRONLY;
else
oflag |= O_RDWR;
if (bIsContinue == false && ((nMode & FMODE_CREATE) == FMODE_CREATE))
oflag |= O_TRUNC;
#ifdef _WIN32
if (bIsBinary)
oflag |= O_BINARY;
else
oflag |= O_TEXT;
m_fdFile = open(pszFileName, oflag, S_IREAD | S_IWRITE);
#else
m_fdFile = open(pszFileName, oflag, S_IREAD | S_IWRITE | S_IRGRP | S_IROTH);
#endif
if (m_fdFile == -1)
return false;
if (bIsContinue && ((nMode & FMODE_WRONLY) == FMODE_WRONLY || (nMode & FMODE_RW) == FMODE_RW))
lseek(m_fdFile, 0L, SEEK_END);
return true;
}
inline void HFile::Close()
{
if (m_fdFile != -1)
{
close(m_fdFile);
m_fdFile = -1;
}
}
inline int HFile::Read(void * buffer, unsigned int count)
{
if (m_fdFile == -1)
return -1;
return read(m_fdFile, buffer, count);
}
inline int HFile::ReadString(char * buffer, unsigned int count)
{
if (m_fdFile == -1)
return -1;
int nResult = read(m_fdFile, buffer, count);
if (nResult > 0)
buffer[nResult] = '\0';
return nResult;
}
inline int HFile::Write(const void * buffer, unsigned int count)
{
if (m_fdFile == -1)
return -1;
return write(m_fdFile, buffer, count);
}
#endif // FILE__H_
+25
View File
@@ -0,0 +1,25 @@
#ifndef _WIN32
#include <sys/types.h>
#endif
#include "Global.h"
size_t g_nMaxPathNameLength = 4096;
//size_t g_nSocketReceiveBlockSize = 8192;
size_t g_nSocketReceiveBlockSize = 32768;
//size_t g_nSocketSendingBlockSize = 1200; // for MTU
//size_t g_nSocketSendingBlockSize = 8192;
size_t g_nSocketSendingBlockSize = 32768;
//size_t g_nMaxHsHeaderSize = 16384; // in Apache default limit is 8KB, in IIS it's 16K.
size_t g_nMaxHsHeaderSize = 32768; // because of elsevier.com
unsigned long g_nTcpConnectTimeout = 15000;
//unsigned long g_nTcpConnectTimeout = 3000;
//unsigned long g_nTcpAutoReconnectTime = 15000;
unsigned long g_nTcpKeepAliveTime = 3000;
+21
View File
@@ -0,0 +1,21 @@
#ifndef GLOBAL__H_
#define GLOBAL__H_
#ifdef _WIN32
#pragma once
#endif
extern size_t g_nMaxPathNameLength;
extern size_t g_nSocketReceiveBlockSize;
extern size_t g_nSocketSendingBlockSize;
extern size_t g_nMaxHsHeaderSize;
extern unsigned long g_nTcpConnectTimeout;
//extern unsigned long g_nTcpAutoReconnectTime;
extern unsigned long g_nTcpKeepAliveTime;
#endif // GLOBAL__H_
+550
View File
@@ -0,0 +1,550 @@
#include "huslib.h"
#include "huslibex.h"
bool HHttpHandler::UriCmp(const char * pszRequestUri, const char * pszPrefix)
{
const char * p1 = pszRequestUri;
const char * p2 = pszPrefix;
for (;;)
{
if (*p1 == '?' && *p2 == '\0')
break;
else if (strcmp(p1, "/") == 0 && *p2 == '\0')
break;
else if (*p1 != '\0' && *p2 == '*')
break;
else if (*p1 != *p2)
return false;
else if (*p1 == '\0' && *p2 == '\0')
break;
else if (*p1 == '\0' || *p2 == '\0')
return false;
p1++;
p2++;
}
return true;
}
bool HHttpHandler::GetParamValue(const char * pszString, const char * pszKey, char * pszValue)
{
pszValue[0] = '\0';
char * pszKeyString = (char *)malloc(strlen(pszKey) + 2);
strcpy(pszKeyString, pszKey);
strcat(pszKeyString, "=");
const char * pszSearch = strstr(pszString, pszKeyString);
free(pszKeyString);
if (pszSearch == NULL)
return false;
int nIndex = (int)(pszSearch - pszString);
if (nIndex > 0 &&
pszString[nIndex - 1] != '?' &&
pszString[nIndex - 1] != '&' &&
#if 0
pszString[nIndex - 1] != ' ' && pszString[nIndex - 1] != '\\' &&
pszString[nIndex - 1] != '/' && pszString[nIndex - 1] != ':' &&
pszString[nIndex - 1] != '\"' && pszString[nIndex - 1] != '\'' &&
#endif
pszString[nIndex - 1] != ';')
{
return false;
}
int nStart = strlen(pszKey) + 1;
int nCount = strlen(pszSearch);
int i;
for (i = nStart; i < nCount; i++)
{
if (pszSearch[i] == '?' ||
pszSearch[i] == '&' ||
#if 0
pszSearch[i] == ' ' || pszSearch[i] == '\\' ||
pszSearch[i] == '/' || pszSearch[i] == ':' ||
pszSearch[i] == '\"' || pszSearch[i] == '\'' ||
#endif
pszSearch[i] == ';')
{
break;
}
}
if (nStart == i)
{
pszValue[0] = '\0';
return true;
}
strncpy(pszValue, pszSearch + nStart, i - nStart);
pszValue[i - nStart] = '\0';
return true;
}
bool HHttpHandler::GetCookieValue(const char * pszCookie, const char * pszKeyName, char * pszValue)
{
*pszValue = '\0';
const char * pszOffset = stristr(pszCookie, pszKeyName);
if (pszOffset == NULL)
return false;
pszOffset += strlen(pszKeyName);
while (*pszOffset)
{
if (*pszOffset == '=')
{
pszOffset++;
break;
}
else if (*pszOffset == ' ' || *pszOffset == '\t')
;
else if (*pszOffset == '\0')
return true;
else
return false;
pszOffset++;
}
int i = 0;
while (*pszOffset)
{
if (*pszOffset == ';' || *pszOffset == '\r' || *pszOffset == '\n' || *pszOffset == '\0')
{
pszValue[i] = '\0';
return true;
}
else if (*pszOffset == '\t' || *pszOffset == ' ')
;
else
pszValue[i++] = *pszOffset;
pszOffset++;
}
pszValue[i] = '\0';
return true;
}
bool HHttpHandler::SetCookieValue(char * pszNewCookie, const char * pszCookie, const char * pszKeyName, const char * pszValue)
{
*pszNewCookie = '\0';
bool bIsSearch = false;
const char * pFirst = NULL;
const char * pSecond = NULL;
const char * pszOffset = pszCookie;
for (;;)
{
pszOffset = stristr(pszOffset, pszKeyName);
if (pszOffset == NULL)
break;
if (pszOffset != pszCookie)
{
const char * pTemp = pszOffset - 1;
if (*pTemp != ' ' && *pTemp != ';' && *pTemp != '\t')
{
pszOffset += strlen(pszKeyName);
continue;
}
}
pszOffset += strlen(pszKeyName);
for (; *pszOffset; pszOffset++)
{
if (bIsSearch == false)
{
if (*pszOffset == '=')
{
bIsSearch = true;
pFirst = pszOffset + 1;
}
else if (*pszOffset != ' ' && *pszOffset != '\t' && *pszOffset != '\r' && *pszOffset != '\n')
break;
}
else
{
if (*pszOffset == ';')
{
pSecond = pszOffset;
break;
}
}
}
if (bIsSearch == true)
break;
}
if (bIsSearch == true)
{
int nCopySize = pFirst - pszCookie;
strncpy(pszNewCookie, pszCookie, nCopySize);
pszNewCookie[nCopySize] = '\0';
strcat(pszNewCookie, pszValue);
if (pSecond)
strcat(pszNewCookie, pSecond);
}
else
{
bool bAddSemiColon = true;
int nTotalLength = strlen(pszCookie);
for (int i = nTotalLength; i > 0; i--)
{
if (pszCookie[i - 1] == ';')
{
bAddSemiColon = false;
break;
}
else if (pszCookie[i - 1] == ' ' || pszCookie[i - 1] == '\t' ||
pszCookie[i - 1] == '\r' || pszCookie[i - 1] == '\n')
{
}
else
break;
}
strcpy(pszNewCookie, pszCookie);
if (bAddSemiColon == true)
strcat(pszNewCookie, "; ");
strcat(pszNewCookie, pszKeyName);
strcat(pszNewCookie, "=");
strcat(pszNewCookie, pszValue);
}
return true;
}
int HHttpHandler::RemoveCookieValue(char * pszCookie, const char * pszKeyName, int nIndex)
{
const char * pszOffset = pszCookie;
for (;;)
{
pszOffset = stristr(pszOffset, pszKeyName);
if (pszOffset == NULL || pszOffset[strlen(pszKeyName)] != '=')
return 0;
if (nIndex-- > 0)
{
pszOffset += 2;
continue;
}
break;
}
char * pszFront = (char *)pszOffset;
while (*pszOffset)
{
if (*pszOffset == ';' || *pszOffset == '\r' || *pszOffset == '\n' || *pszOffset == '\0')
break;
pszOffset++;
}
if (*pszOffset == ';')
pszOffset++;
if (*pszOffset == '\r' || *pszOffset == '\n' || *pszOffset == '\0')
{
if (pszCookie == pszFront) // empty cookie
{
*pszFront = '\0';
return 2;
}
*pszFront = '\0';
return 1;
}
if (*pszOffset == ' ')
pszOffset++;
char * pszTemp = (char *)malloc(strlen(pszOffset) + 1);
strcpy(pszTemp, pszOffset);
strcpy(pszFront, pszTemp);
free(pszTemp);
return 1;
}
int HHttpHandler::MakeCookie(char * pszSetCookie, const char * pszKeyName,
const char * pszKeyValue, const char * pszDomain, const char * pszPath, long nExpireMinute)
{
if (nExpireMinute < 0)
{
return sprintf(pszSetCookie, "%s=%s; expires=Thu, 01 Jan 1970 23:59:59 GMT%s%s%s%s",
pszKeyName, pszKeyValue,
pszDomain ? "; domain=" : "", pszDomain ? pszDomain : "",
pszPath ? "; path=" : "", pszPath ? pszPath : "");
}
else if (nExpireMinute == 0)
{
return sprintf(pszSetCookie, "%s=%s%s%s%s%s",
pszKeyName, pszKeyValue,
pszDomain ? "; domain=" : "", pszDomain ? pszDomain : "",
pszPath ? "; path=" : "", pszPath ? pszPath : "");
}
char szDateTime[32];
struct tm * tmTmp;
timeb tTimeb;
ftime(&tTimeb);
tTimeb.time += nExpireMinute;
tmTmp = localtime(&tTimeb.time);
strftime(szDateTime, 32, "%a, %d-%b-%Y %H:%M:%S", tmTmp);
return sprintf(pszSetCookie, "%s=%s; expires=%s GMT%s%s%s%s",
pszKeyName, pszKeyValue, szDateTime,
pszDomain ? "; domain=" : "", pszDomain ? pszDomain : "",
pszPath ? "; path=" : "", pszPath ? pszPath : "");
}
const char * HHttpHandler::EnumExtractCookie(const char * pszCookie, char ** ppName, char ** ppValue)
{
*ppName = NULL;
*ppValue = NULL;
if (pszCookie == NULL || pszCookie[0] == '\0')
return NULL;
const char * pOffset1 = strchr(pszCookie, ';');
const char * pOffset2 = strchr(pszCookie, '=');
if (pOffset1 == NULL && pOffset2 == NULL)
return NULL;
else if (pOffset2 == NULL || (pOffset1 && pOffset1 <= pOffset2 + 1))
return pOffset1 + 1;
int nNameSize = pOffset2 - pszCookie;
*ppName = (char *)malloc(nNameSize + 1);
StrNTrimCpy(*ppName, pszCookie, nNameSize);
int nValueSize;
if (pOffset1)
nValueSize = pOffset1 - (pOffset2 + 1);
else
nValueSize = strlen(pOffset2 + 1);
*ppValue = (char *)malloc(nValueSize + 1);
StrNTrimCpy(*ppValue, pOffset2 + 1, nValueSize);
if (pOffset1)
return pOffset1 + 1;
return NULL;
}
int HHttpHandler::MakeResponse(char * pszResponse, const char * pszResponseType, const char * pszHtml)
{
HString strRear;
if (pszHtml)
{
strRear = "Content-Length: ";
strRear += strlen(pszHtml);
strRear += "\r\n\r\n";
strRear += pszHtml;
}
size_t nSize = sprintf(pszResponse, "HTTP/1.1 %s\n"
"Server: HUSS/2.0\r\n"
"X-UA-Compatible: IE=Edge\r\n"
"Content-Security-Policy: script-src 'self' 'unsafe-inline'; object-src 'self';\r\n"
"X-Content-Type-Options: nosniff\r\n"
"X-XSS-Protection: 1; mode=block\r\n"
"Connection: close\r\n"
"%s", pszResponseType, pszHtml ? strRear.psz() : "\r\n");
return nSize;
}
int HHttpHandler::Make200Header(char * pszResponse, const char * pszContentType, unsigned long nBodySize, const char * pszAddtionalHeaders)
{
size_t nSize = sprintf(pszResponse, "HTTP/1.1 200 OK\r\n"
"Server: HUSS/2.0\r\n"
"X-UA-Compatible: IE=Edge\r\n"
"Content-Security-Policy: script-src 'self' 'unsafe-inline'; object-src 'self';\r\n"
"X-Content-Type-Options: nosniff\r\n"
"X-XSS-Protection: 1; mode=block\r\n"
"%s%s"
"Content-Type: %s\r\n"
"Connection: close\r\n"
"Content-Length: %ld\r\n"
"\r\n", pszAddtionalHeaders && pszAddtionalHeaders[0] != '\0' ? pszAddtionalHeaders : "",
pszAddtionalHeaders && pszAddtionalHeaders[0] != '\0' ? "\r\n" : "",
pszContentType, nBodySize);
return nSize;
}
int HHttpHandler::Make302Response(char * pszResponse, const char * pszLocation, const char * pszSetCookie)
{
size_t nSize = sprintf(pszResponse, "HTTP/1.1 302 Moved Temporarily\r\n"
"Server: HUSS/2.0\r\n"
"Location: %s\r\n"
"Connection: close\r\n"
"%s%s%s"
"\r\n", pszLocation, pszSetCookie ? "Set-Cookie: " : "",
pszSetCookie ? pszSetCookie : "", pszSetCookie ? "\r\n" : "");
return nSize;
}
int HHttpHandler::Make307Response(char * pszResponse, const char * pszLocation, const char * pszSetCookie)
{
size_t nSize = sprintf(pszResponse, "HTTP/1.1 307 Temporary Redirect\r\n"
"Server: HUSS/2.0\r\n"
"Location: %s\r\n"
"Connection: close\r\n"
"%s%s%s"
"\r\n", pszLocation, pszSetCookie ? "Set-Cookie: " : "",
pszSetCookie ? pszSetCookie : "", pszSetCookie ? "\r\n" : "");
return nSize;
}
void HHttpHandler::MakeRedirectBody(HString * pstrBody, const char * pszUrl)
{
*pstrBody = "<html><head><META HTTP-EQUIV=Refresh CONTENT=\"0; URL='";
*pstrBody += pszUrl;
*pstrBody += "'\"></head></html>";
}
//////////////////////////////////////////////////////////////////////////////
HHttpHandler::HHttpHandler()
{
m_pRecvStreamBuffer = new HStreamBuffer(g_nMaxHsHeaderSize + g_nSocketReceiveBlockSize);
m_pHttpParser = NULL;
m_nProtocolStatus = HHsParser::HP_NOT_HTTP_PACKET;
m_nRemainBodySize = 0;
}
HHttpHandler::~HHttpHandler()
{
if (m_pHttpParser)
delete m_pHttpParser;
delete m_pRecvStreamBuffer;
}
void HHttpHandler::InitParser()
{
if (m_pHttpParser)
{
m_pRecvStreamBuffer->Reset();
m_nProtocolStatus = HHsParser::HP_NOT_HTTP_PACKET;
delete m_pHttpParser;
m_pHttpParser = NULL;
}
}
void HHttpHandler::WriteStreamPacket(const char * pszDir, const char * pszPrefix)
{
HString strFileName = pszDir;
strFileName += pszPrefix;
char szDateTime[32];
GetDateTimeNum(szDateTime);
strFileName += szDateTime;
HFile file;
if (file.Open(strFileName, HFile::FMODE_CREATE | HFile::FMODE_WRONLY) == false)
return;
file.Write(m_pRecvStreamBuffer->Head(), m_pRecvStreamBuffer->StoredSize());
}
int HHttpHandler::OnReceivedFromTransport(const char * pData, int nSize)
{
//HLOGF(HLOG_WARNING, "TestLog, HttpHdler, inst = 0x%x, recv size = %d\n", this, nSize);
//HLOGD(HLOG_WARNING, pData, 40, true);
if (m_nProtocolStatus == HHsParser::HP_BODY_REMAIN_PACKET)
{
m_nRemainBodySize -= nSize;
int nResult = OnReceivedBodyStream(pData, nSize);
if (m_nRemainBodySize <= 0)
{
m_pRecvStreamBuffer->Reset();
m_nProtocolStatus = HHsParser::HP_NOT_HTTP_PACKET;
delete m_pHttpParser;
m_pHttpParser = NULL;
}
return nResult;
}
else if (m_nProtocolStatus == HHsParser::HP_BODYSIZE_UNKNOWN_PACKET)
{
return OnReceivedBodyStream(pData, nSize);
}
if (m_pRecvStreamBuffer->Store(pData, nSize) == false)
{
HLOGF(HLOG_ERROR, "[ERROR], HttpHdler, Failed to insert data, inst = 0x%x, buffer = %d, stored = %d, recv size = %d\n", this, m_pRecvStreamBuffer->Size(), m_pRecvStreamBuffer->StoredSize(), nSize);
return -1; // disconnect
}
// simply verify header
if (isalnum(m_pRecvStreamBuffer->Head()[0]) == 0)
{
HLOGF(HLOG_WARNING, "[WARN], HttpHdler, Invalid http protocol 1, inst = 0x%x, buffer = %d, stored = %d, recv size = %d\n", this, m_pRecvStreamBuffer->Size(), m_pRecvStreamBuffer->StoredSize(), nSize);
HLOGD(HLOG_WARNING, m_pRecvStreamBuffer->Head(), 20, false);
return -1; // disconnect
}
m_pRecvStreamBuffer->Head()[m_pRecvStreamBuffer->StoredSize()] = '\0'; // for using string operation
char * pszBodyPtr = HHsParser::SearchBodyPtr((char *)pData, nSize); //... search "\r\n\r\n" or "\n\n"
if (pszBodyPtr == NULL)
return 0; // continue received (remain header)
m_pHttpParser = new HHsParser("HTTP");
m_nProtocolStatus = m_pHttpParser->Parse(m_pRecvStreamBuffer->Head(), m_pRecvStreamBuffer->StoredSize());
if (m_nProtocolStatus == HHsParser::HP_NOT_HTTP_PACKET ||
m_nProtocolStatus == HHsParser::HP_PARAMETER_ERROR)
{
HLOGF(HLOG_WARNING, "[WARN], HttpHdler, Invalid http protocol 2, inst = 0x%x, buffer = %d, stored = %d, recv size = %d\n", this, m_pRecvStreamBuffer->Size(), m_pRecvStreamBuffer->StoredSize(), nSize);
HLOGD(HLOG_WARNING, m_pRecvStreamBuffer->Head(), 20, false);
return -1; // disconnect
}
else if (m_nProtocolStatus == HHsParser::HP_BODY_REMAIN_PACKET)
{
m_nRemainBodySize = m_pHttpParser->GetContentLength() - m_pHttpParser->GetBodySize();
return OnPacketProcessing(m_pHttpParser->GetBodyPtr(), m_pHttpParser->GetBodySize());
}
else if (m_nProtocolStatus == HHsParser::HP_BODYSIZE_UNKNOWN_PACKET)
{
return OnPacketProcessing(m_pHttpParser->GetBodyPtr(), m_pHttpParser->GetBodySize());
}
else if (m_nProtocolStatus == HHsParser::HP_COMPLETE_PACKET)
{
int nResult = OnPacketProcessing(m_pHttpParser->GetBodyPtr(), m_pHttpParser->GetBodySize());
m_pRecvStreamBuffer->Reset();
m_nProtocolStatus = HHsParser::HP_NOT_HTTP_PACKET;
delete m_pHttpParser;
m_pHttpParser = NULL;
return nResult;
}
return 0;
}
+58
View File
@@ -0,0 +1,58 @@
#ifndef HTTP_HANDLER__H
#define HTTP_HANDLER__H
#ifdef _WIN32
#pragma once
#endif
#define ON_HTTP_REQUEST(RURI, FN) if (HHttpHandler::UriCmp(m_pHttpParser->GetRequestUri(), RURI)) { return FN(pBodyData, nBodySize); }
class HHttpHandler : public HProtocolHandler
{
public:
static bool UriCmp(const char * pszRequestUri, const char * pszPrefix);
static bool GetParamValue(const char * pszString, const char * pszKey, char * pszValue);
static bool GetCookieValue(const char * pszCookie, const char * pszKeyName, char * pszValue);
static bool SetCookieValue(char * pszNewCookie, const char * pszCookie, const char * pszKeyName, const char * pszValue);
static int RemoveCookieValue(char * pszCookie, const char * pszKeyName, int nIndex = 0); // return 0 : not found key, 1 : delete, 2 : delete and empty cookie string
static int MakeCookie(char * pszSetCookie, const char * pszKeyName, const char * pszKeyValue, const char * pszDomain, const char * pszPath, long nExpireMinute = 0); // nExpireMinute = -1 : delete, 0 : not set expire, (86400 * 10) : 10 days
static const char * EnumExtractCookie(const char * pszCookie, char ** ppName, char ** ppValue);
static int MakeResponse(char * pszResponse, const char * pszResponseType, const char * pszHtml);
static int Make200Header(char * pszResponse, const char * pszContentType, unsigned long nBodySize, const char * pszAddtionalHeaders = NULL);
static int Make302Response(char * pszResponse, const char * pszLocation, const char * pszSetCookie = NULL);
static int Make307Response(char * pszResponse, const char * pszLocation, const char * pszSetCookie = NULL);
static void MakeRedirectBody(HString * pstrBody, const char * pszUrl);
//
HHttpHandler();
~HHttpHandler();
protected:
void InitParser();
void WriteStreamPacket(const char * pszDir, const char * pszPrefix);
virtual void OnReceivedStatusFromTransport(int nStatus) {}
bool OnPrepareReceive() { return true; }
virtual int OnReceivedFromTransport(const char * pData, int nSize);
virtual int OnPacketProcessing(const char * pBodyData, int nBodySize) { return -1; }
virtual int OnReceivedBodyStream(const char * pData, int nSize) { return -1; }
protected:
HHsParser * m_pHttpParser;
int m_nProtocolStatus;
long m_nRemainBodySize;
private:
HStreamBuffer * m_pRecvStreamBuffer;
};
#endif // HTTP_HANDLER__H
+111
View File
@@ -0,0 +1,111 @@
#ifdef _WIN32
#include "huslib/huslib.h"
#include "huslib/huslibex.h"
#include <windows.h>
#ifdef _DEBUG
#include <crtdbg.h>
#endif // _DEBUG
#include "windows/WinService.h"
#define WRITE_MINI_DUMP
#if defined(_WIN32) && !defined(_DEBUG) && defined(WRITE_MINI_DUMP)
#include "windows/DebugAssist.h"
#endif // WRITE_MINI_DUMP
#else
#include <signal.h>
#endif // _WIN32
#include <stdio.h>
#include "Object.h"
#include "HusApp.h"
HApp * HApp::m_pApp = NULL;
HApp::HApp()
{
m_pApp = this;
}
///////////////////////////////////////
#ifdef _WIN32
#define TIMEOUT_SERVICE_START_PENDING 5000
VOID ServiceStart(DWORD nArgc, LPTSTR *pArgv, BOOL bConsoleMode)
{
#if defined(_WIN32) && !defined(_DEBUG)
InitialDumpWriting(); // for Windows Dump File
#endif
#ifdef _DEBUG
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
#endif // _DEBUG
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
printf("[ERROR] Windows sockets initialization failed. WSAGetLastError = %d\n", WSAGetLastError());
return;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
printf("[ERROR] Could not find a usable WinSock DLL.\n");
WSACleanup();
return;
}
if (!ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, TIMEOUT_SERVICE_START_PENDING))
return;
if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))
return;
HApp::m_pApp->OnMain(nArgc, pArgv);
WSACleanup();
}
VOID ServiceStop()
{
HApp::m_pApp->OnExit(0);
if (!ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, TIMEOUT_SERVICE_START_PENDING))
return;
if (!ReportStatusToSCMgr(SERVICE_STOPPED, NO_ERROR, 0))
return;
}
#endif // _WIN32
int main(int nArgc, char ** pArgv)
{
if (HApp::m_pApp == NULL)
{
printf("ERROR: Can't find an object that derives from HApp.\n");
return 0;
}
#ifdef _WIN32
WinServiceMain(nArgc, pArgv);
return 0;
#else
signal(SIGPIPE, SIG_IGN);
#endif // _WIN32
return HApp::m_pApp->OnMain(nArgc, pArgv);
}
+21
View File
@@ -0,0 +1,21 @@
#ifndef APP__H_
#define APP__H_
class HApp : public HObject
{
public:
static HApp * m_pApp;
//
HApp();
virtual ~HApp() {}
virtual int OnMain(int nArgc, char ** pArgv) = 0;
virtual void OnExit(int nCode) = 0;
};
#define APPINIT(APP_CLASS_NAME) APP_CLASS_NAME __g_main$Application$Instance_;
#define HAPP() (&__g_main$Application$Instance_)
#endif // APP__H_
+535
View File
@@ -0,0 +1,535 @@
#include "Common.h"
#include "Object.h"
#include "Thread.h"
#include "Timer.h"
#include "Logger.h"
#include <fcntl.h>
#ifdef _WIN32
//#include <io.h>
//#pragma warning(disable:4201)
//#include <mmsystem.h>
//#pragma warning(default:4201)
//#pragma comment(lib, "winmm.lib")
#include <time.h>
#else
#include <sys/stat.h>
#endif // _WIN32
// my defines for portablity
#ifdef _WIN32
#define ftime _ftime
#define timeb _timeb
#define vsnprintf _vsnprintf
#define snprintf _snprintf
#define FILECRETEFAIL_CAPTION "HLogger Message"
#endif // _WIN32
#ifdef SINGLE_THREADED_MODEL
#if _MSC_VER <= 1200
#define Lock() ((void)0)
#define Unlock() ((void)0)
#else
#define Lock() __noop
#define Unlock() __noop
#endif
#endif // SINGLE_THREADED_MODEL
HLogger * g_pLogFile__Logger = NULL;
HLogger::HLogger()
{
m_fhLog = -1;
m_nLevel = 0;
m_flagOption = dayWrite | timeWrite;
m_bIsContinue = false;
m_nFileSplitSize = 0;
m_nFileLimitSize = 0;
m_nLogFileNameExt = 0;
m_bIsFileNameChange = false;
m_nSrcLine = 0;
m_szPathName[0] = '\0';
#ifndef SINGLE_THREADED_MODEL
#ifdef _WIN32
InitializeCriticalSection(&m_csInstance);
#else
pthread_mutex_init(&m_mutex, NULL);
#endif // _WIN32
#endif // SINGLE_THREADED_MODEL
m_pExtension = NULL;
m_szWriteString = (char *)malloc(MD_MAX_STRING);
m_szLogString = (char *)malloc(MD_MAX_STRING);
m_szTmpString = (char *)malloc(MD_MAX_STRING);
}
HLogger::~HLogger()
{
free(m_szWriteString);
free(m_szLogString);
free(m_szTmpString);
#ifndef SINGLE_THREADED_MODEL
#ifdef _WIN32
DeleteCriticalSection(&m_csInstance);
#else
pthread_mutex_destroy(&m_mutex);
#endif // _WIN32
#endif // SINGLE_THREADED_MODEL
}
bool HLogger::Create(unsigned nLevel, bool bContinue,
const char * szPathName, bool bIsBinary)
{
Lock();
m_bIsContinue = bContinue;
m_bIsBinary = bIsBinary;
bool bSuccess = OpenFile(nLevel, szPathName);
Unlock();
return bSuccess;
}
void HLogger::Release()
{
Lock();
CloseFile();
m_nFileSplitSize = 0;
m_nFileLimitSize = 0;
m_nLogFileNameExt = 0;
m_bIsFileNameChange = false;
if (m_pExtension)
{
delete m_pExtension;
m_pExtension = NULL;
}
Unlock();
}
bool HLogger::OpenFile(unsigned nLevel, const char * szPathName)
{
if (m_fhLog != -1) return false;
m_nLevel = nLevel;
if (szPathName != NULL && !(szPathName[strlen(szPathName) - 1] == '/' ||
szPathName[strlen(szPathName) - 1] == '\\'))
{
// Full Path Name ==> equal.
if (m_szPathName[0] == '\0')
{
strncpy(m_szPathName, szPathName, MD_MAX_PATH - 1);
m_szPathName[MD_MAX_PATH - 1] = '\0';
}
strncpy(m_szLogFileName, szPathName, MD_MAX_PATH - 1);
m_szLogFileName[MD_MAX_PATH - 1] = '\0';
}
else
{
m_bIsFileNameChange = true;
// Directory ==> log name is date. ex) Start("log/") = log/20030201.log
if (szPathName != NULL && m_szPathName[0] == '\0')
{
strncpy(m_szPathName, szPathName, MD_MAX_PATH - 1);
m_szPathName[MD_MAX_PATH - 1] = '\0';
}
char szDay[MD_MAX_DATE];
GetDateTime(szDay, NULL);
sprintf(m_szLogFileName, "%s%s.log", m_szPathName, szDay);
strncpy(m_szPrevDate, szDay, MD_MAX_DATE - 1);
m_szPrevDate[MD_MAX_DATE - 1] = '\0';
//#ifdef _WIN32
// CreateDirectory(m_szPathName, NULL);
//#else
// mkdir(m_szPathName, S_IRWXU | S_IRWXG | S_IRWXO);
//#endif
}
int oflag = O_CREAT | O_RDWR;
if (m_bIsContinue == false)
oflag |= O_TRUNC;
#ifdef _WIN32
if (m_bIsBinary)
oflag |= O_BINARY;
else
oflag |= O_TEXT;
m_fhLog = open(m_szLogFileName, oflag, S_IREAD | S_IWRITE);
#else
m_fhLog = open(m_szLogFileName, oflag, S_IREAD | S_IWRITE | S_IRGRP | S_IROTH);
#endif
if (m_fhLog == -1)
{
char szMessage[MD_MAX_PATH + 32];
sprintf(szMessage, "[ERROR], Failed to create log file, [%s]\n", m_szLogFileName);
#ifdef _WIN32
MessageBoxA(HWND_TOP, szMessage, FILECRETEFAIL_CAPTION, MB_OK | MB_ICONERROR);
#else
printf(szMessage);
#endif
return false;
}
if (m_bIsContinue)
lseek(m_fhLog, 0L, SEEK_END);
return true;
}
void HLogger::CloseFile()
{
if (m_fhLog == -1) return;
if (m_nFileLimitSize > 0)
{
const char * pszEndTxt = "--------------------------------\nEnd of log writing.\n--------------------------------\n\n";
#ifdef _WIN32
#pragma warning(disable:4267)
#endif
write(m_fhLog, pszEndTxt, strlen(pszEndTxt));
#ifdef _WIN32
#pragma warning(default:4267)
#endif
}
close(m_fhLog);
m_fhLog = -1;
}
void HLogger::GetDateTime(char * szDate, char * szTime)
{
SYSTEMTIME systemTime;
HTIMER()->GetSystemTime(&systemTime);
if (szDate != NULL)
sprintf(szDate, "%.4ld%.2ld%.2ld", systemTime.wYear, systemTime.wMonth, systemTime.wDay);
if (szTime != NULL)
sprintf(szTime, "%.2ld:%.2ld:%.2ld.%.3ld", systemTime.wHour, systemTime.wMinute, systemTime.wSecond,
systemTime.wMilliseconds);
}
void HLogger::Write(int nLevel, const char * pszLog)
{
Lock();
if (m_fhLog == -1 || nLevel > m_nLevel ||
((m_flagOption & onlyLevel) == onlyLevel && m_nLevel != nLevel))
{
Unlock();
return;
}
char * pszSwap = m_szLogString;
m_szLogString = (char *)pszLog;
m_nLogLength = (int)strlen(pszLog);
WriteLog(false);
m_szLogString = pszSwap;
Unlock();
}
void HLogger::Dump(int nLevel, const char * pszLog, size_t nSize, bool bWithHex)
{
Lock();
if (m_fhLog == -1 || nLevel > m_nLevel ||
((m_flagOption & onlyLevel) == onlyLevel && m_nLevel != nLevel))
{
Unlock();
return;
}
if (nSize > MD_MAX_STRING - 3)
nSize = MD_MAX_STRING - 3;
strncpy(m_szLogString, pszLog, nSize);
m_szLogString[nSize] = '\0';
m_nLogLength = (int)nSize;
if (bWithHex)
{
char * pszTemp = m_szLogString + nSize;
pszTemp[0] = '\n';
const char HEX[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char cByte;
unsigned i = 0, j = 1;
for (; i < nSize; i++)
{
cByte = pszLog[i];
pszTemp[j++] = HEX[(cByte & 0xF0) >> 4];
pszTemp[j++] = HEX[(cByte & 0x0F) >> 0];
pszTemp[j++] = ' ';
}
m_nLogLength += j;
}
m_szLogString[m_nLogLength] = '\n';
m_szLogString[m_nLogLength + 1] = '\0';
m_nLogLength += 1;
WriteLog(false);
Unlock();
}
void HLogger::Format(int nLevel, const char *fmt, ...)
{
Lock();
if (m_fhLog == -1 || nLevel > m_nLevel ||
((m_flagOption & onlyLevel) == onlyLevel && m_nLevel != nLevel))
{
Unlock();
return;
}
va_list vaList;
va_start(vaList, fmt);
m_nLogLength = vsnprintf(m_szLogString, MD_MAX_STRING - 1, fmt, vaList);
if (m_nLogLength < 0 || m_nLogLength >= MD_MAX_STRING)
{
m_nLogLength = MD_MAX_STRING;
m_szLogString[MD_MAX_STRING - 1] = '\0';
}
va_end(vaList);
WriteLog(false);
Unlock();
}
void HLogger::Trace(const char * szSrcFileName, const unsigned nSrcLine, int nLevel, const char *fmt, ...)
{
Lock();
if (m_fhLog == -1 || nLevel > m_nLevel ||
((m_flagOption & onlyLevel) == onlyLevel && m_nLevel != nLevel))
{
Unlock();
return;
}
#ifdef _WIN32
// remove path name
const char * pPos = strrchr(szSrcFileName, '\\');
if (pPos == NULL)
pPos = strrchr(szSrcFileName, '/');
if (pPos != NULL)
{
strncpy(m_szSrcFileName, ++pPos, MD_MAX_PATH);
m_szSrcFileName[MD_MAX_PATH - 1] = '\0';
}
else
#endif // _WIN32
strncpy(m_szSrcFileName, szSrcFileName, MD_MAX_PATH - 1);
m_szSrcFileName[MD_MAX_PATH - 1] = '\0';
m_nSrcLine = nSrcLine;
va_list vaList;
va_start(vaList, fmt);
m_nLogLength = vsnprintf(m_szLogString, MD_MAX_STRING - 1, fmt, vaList);
if (m_nLogLength < 0 || m_nLogLength >= MD_MAX_STRING)
{
m_nLogLength = MD_MAX_STRING;
m_szLogString[MD_MAX_STRING - 1] = '\0';
}
va_end(vaList);
WriteLog(true);
Unlock();
}
void HLogger::SetSrcInfoWithLock(const char * szSrcFileName, const unsigned nSrcLine)
{
Lock();
#ifdef _WIN32
// remove path name
const char * pPos = strrchr(szSrcFileName, '\\');
if (pPos == NULL)
pPos = strrchr(szSrcFileName, '/');
if (pPos != NULL)
{
strncpy(m_szSrcFileName, ++pPos, MD_MAX_PATH);
m_szSrcFileName[MD_MAX_PATH - 1] = '\0';
}
else
#endif // _WIN32
strncpy(m_szSrcFileName, szSrcFileName, MD_MAX_PATH - 1);
m_szSrcFileName[MD_MAX_PATH - 1] = '\0';
m_nSrcLine = nSrcLine;
}
void HLogger::TraceWithUnlock(int nLevel)
{
if (m_fhLog == -1 || nLevel > m_nLevel ||
((m_flagOption & onlyLevel) == onlyLevel && m_nLevel != nLevel))
{
Unlock();
return;
}
WriteLog(true);
Unlock();
}
inline void HLogger::WriteLog(const bool bIsTrace)
{
m_szWriteString[0] = '\0';
m_nWriteLength = 0;
if (m_bIsFileNameChange)
{
char szDate[MD_MAX_DATE];
GetDateTime(szDate, NULL);
if (strcmp(m_szPrevDate, szDate) != 0)
{
CloseFile();
OpenFile(m_nLevel, NULL);
m_nLogFileNameExt = 0;
}
}
if (m_nFileSplitSize > 0 && m_nFileSplitSize <= lseek(m_fhLog, 0L, SEEK_CUR))
{
// file split : filename.001, filename.002, ...
char szLogFileName[MD_MAX_PATH], szFileName[MD_MAX_PATH];
char * pRear;
pRear = strrchr(m_szLogFileName, '.');
strncpy(szFileName, m_szLogFileName, pRear - m_szLogFileName);
szFileName[pRear - m_szLogFileName] = '\0';
sprintf(szLogFileName, "%s.%.3d", szFileName, ++m_nLogFileNameExt);
CloseFile();
OpenFile(m_nLevel, szLogFileName);
}
if ((m_flagOption & dayWrite) == dayWrite)
{
GetDateTime(m_szWriteString, NULL);
m_szWriteString[8] = ' ';
m_szWriteString[9] = '\0';
m_nWriteLength += 9;
}
if ((m_flagOption & timeWrite) == timeWrite)
{
GetDateTime(NULL, m_szTmpString);
memcpy(m_szWriteString + m_nWriteLength, m_szTmpString, 12);
m_szWriteString[m_nWriteLength + 12] = '\t';
m_szWriteString[m_nWriteLength + 13] = '\0';
m_nWriteLength += 13;
}
if (bIsTrace)
{
m_nTracePathLength = sprintf(m_szTracePathName, "%s(%d)", m_szSrcFileName, m_nSrcLine);
if (m_nTracePathLength < 26)
m_nTracePathLength = sprintf(m_szTmpString, "%25s\t", m_szTracePathName);
else if (m_nTracePathLength < 32)
m_nTracePathLength = sprintf(m_szTmpString, "%31s\t", m_szTracePathName);
else if (m_nTracePathLength < 38)
m_nTracePathLength = sprintf(m_szTmpString, "%37s\t", m_szTracePathName);
else
m_nTracePathLength = sprintf(m_szTmpString, "%43s\t", m_szTracePathName);
memcpy(m_szWriteString + m_nWriteLength, m_szTmpString, m_nTracePathLength + 1);
m_nWriteLength += m_nTracePathLength;
}
if (m_nLogLength + m_nWriteLength > MD_MAX_STRING - 1)
m_nLogLength = MD_MAX_STRING - m_nWriteLength - 1;
memcpy(m_szWriteString + m_nWriteLength, m_szLogString, m_nLogLength);
m_nWriteLength += m_nLogLength;
if (m_nWriteLength >= MD_MAX_STRING - 1 || (m_flagOption & autoNewLine) == autoNewLine)
{
if (m_nWriteLength >= MD_MAX_STRING - 1)
m_nWriteLength--;
m_szWriteString[m_nWriteLength++] = '\n';
}
#ifdef _WIN32
#pragma warning(disable:4267)
#endif
if (m_nFileLimitSize > 0 && m_nFileLimitSize <= lseek(m_fhLog, 0L, SEEK_CUR))
{
const static char * pszFirstTxt = "Log writing was contiued from file end. See date and time of end line.\n--------------------------------\n";
#ifdef _WIN32
_chsize(m_fhLog, m_nFileLimitSize / 4);
#else
ftruncate(m_fhLog, m_nFileLimitSize / 4);
#endif
lseek(m_fhLog, 0L, SEEK_SET);
write(m_fhLog, pszFirstTxt, strlen(pszFirstTxt));
}
OnWrite(m_szWriteString, m_nWriteLength);
if ((m_flagOption & consoleWrite) == consoleWrite)
fwrite(m_szWriteString, sizeof(char), m_nWriteLength, stdout);
//#ifdef _WIN32
//#pragma warning(default:4267)
// _commit(m_fhLog);
//#endif
if (m_pExtension)
m_pExtension->OnWrite(m_szWriteString, m_nWriteLength);
}
+389
View File
@@ -0,0 +1,389 @@
#ifndef LOGGER__H_
#define LOGGER__H_
#ifdef _WIN32
#pragma once
//#pragma warning(disable:4710)
#pragma warning(disable:4996)
#include <io.h>
#include <sys/stat.h>
#include <sys/timeb.h>
#else
#ifndef SINGLE_THREADED_MODEL
#include <pthread.h>
#endif
#include <stdarg.h>
#endif // _WIN32
class HLoggerExtension
{
public:
HLoggerExtension() {}
virtual ~HLoggerExtension() {}
protected:
virtual void OnWrite(const char * pszText, unsigned nLength) = 0;
friend class HLogger;
};
///////////////////////////////////////
class HLogger
{
public:
enum
{
MD_MAX_STRING = 1024, // max one-line log length
MD_MAX_PATH = 1024, // max path name length
MD_MAX_DATE = 16, // max date string length
MIN_LIMIT_SIZE = 4096
};
enum Options
{
dayWrite = 0x0001, // add day : default
timeWrite = 0x0002, // add time : default
autoNewLine = 0x0004, // ...
onlyLevel = 0x0008,
consoleWrite = 0x0010
};
HLogger();
virtual ~HLogger();
bool Create(unsigned nLevel, bool bContinue, const char * szPathName = NULL, bool bIsBinary = false);
// nLevel : max write level
// bContinue : true is contiue writing to exist log file.
// szPathName : NULL ==> log name is date. ex) 20030201.log
// szPathName : Directory ==> log name is date. ex) Create("log/") = log/20030201.log
// szPathName : full path name or file name ==> equal.
void Release(); // for log file close.
inline int GetLevel();
inline void SetLevel(unsigned nLevel);
inline int GetOption();
inline void SetOption(int flagOption);
inline void SetFileSplitSize(off_t nFileSize);
inline off_t GetFileSplitSize();
inline off_t GetFileLimitSize();
inline void SetFileLimitSize(off_t nFileSize);
inline void SetExtension(HLoggerExtension * pExtension); // auto delete instance
void Write(int nLevel, const char * pszLog);
void Dump(int nLevel, const char * pszLog, size_t nSize, bool bWithHex);
void Format(int nLevel, const char * fmt, ...);
void Trace(const char * szSrcFileName, const unsigned nSrcLine, int nLevel, const char *fmt, ...);
protected:
inline char * GetLogStringBuffer();
inline void SetLogStringBuffer(const char * pszLog);
bool OpenFile(unsigned nLevel, const char * szPathName);
void CloseFile();
void GetDateTime(char *szDate, char *szTime);
void WriteLog(const bool bIsTrace);
virtual inline void OnWrite(const char * pszText, unsigned nLength);
#ifndef SINGLE_THREADED_MODEL
inline void Lock();
inline void Unlock();
#endif
public:
// Two pair fuctions for source file name and line
// Must be called pair.
void SetSrcInfoWithLock(const char * szSrcFileName, const unsigned nSrcLine);
void TraceWithUnlock(int nLevel);
friend void __Logger_Format(int nLevel, const char *fmt, ...);
friend void __Logger_SetSrcInfoWithLock(const char * szSrcFileName, const unsigned nSrcLine);
friend void __Logger_TraceWithUnlock(int nLevel, const char *fmt, ...);
public:
int m_nLogLength;
private:
char * m_szWriteString;
char * m_szLogString;
char * m_szTmpString;
int m_fhLog;
int m_nLevel;
int m_flagOption;
bool m_bIsContinue;
bool m_bIsBinary;
off_t m_nFileSplitSize; // bytes
off_t m_nFileLimitSize; // bytes
char m_szPathName[MD_MAX_PATH];
char m_szLogFileName[MD_MAX_PATH];
unsigned m_nLogFileNameExt;
bool m_bIsFileNameChange;
char m_szPrevDate[MD_MAX_DATE];
char m_szSrcFileName[MD_MAX_PATH];
unsigned m_nSrcLine;
int m_nWriteLength;
#ifdef _WIN32
struct _timeb m_tTimeb;
#else
struct timeb m_tTimeb;
#endif
char m_szMiliSec[8];
char m_szTracePathName[MD_MAX_PATH];
int m_nTracePathLength;
#ifndef SINGLE_THREADED_MODEL
#ifdef _WIN32
CRITICAL_SECTION m_csInstance;
#else
pthread_mutex_t m_mutex;
#endif // _WIN32
#endif // SINGLE_THREADED_MODEL
HLoggerExtension * m_pExtension;
};
inline int HLogger::GetLevel()
{
return m_nLevel;
}
inline void HLogger::SetLevel(unsigned nLevel)
{
m_nLevel = nLevel;
}
inline int HLogger::GetOption()
{
return m_flagOption;
}
inline void HLogger::SetOption(int flagOption)
{
m_flagOption = flagOption;
}
inline void HLogger::SetFileSplitSize(off_t nFileSize)
{
m_nFileSplitSize = nFileSize;
}
inline off_t HLogger::GetFileSplitSize()
{
return m_nFileSplitSize;
}
inline off_t HLogger::GetFileLimitSize()
{
return m_nFileLimitSize;
}
inline void HLogger::SetFileLimitSize(off_t nFileSize)
{
if (nFileSize < MIN_LIMIT_SIZE)
m_nFileLimitSize = MIN_LIMIT_SIZE;
else
m_nFileLimitSize = nFileSize;
}
inline char * HLogger::GetLogStringBuffer()
{
return m_szLogString;
}
inline void HLogger::SetLogStringBuffer(const char * pszLog)
{
m_szLogString = (char *)pszLog;
}
inline void HLogger::OnWrite(const char * pszText, unsigned nLength)
{
write(m_fhLog, pszText, nLength);
}
inline void HLogger::SetExtension(HLoggerExtension * pExtension)
{
if (m_pExtension)
delete m_pExtension;
m_pExtension = pExtension;
}
#ifndef SINGLE_THREADED_MODEL
inline void HLogger::Lock()
{
#ifdef _WIN32
EnterCriticalSection(&m_csInstance);
#else
pthread_mutex_lock(&m_mutex);
#endif
}
inline void HLogger::Unlock()
{
#ifdef _WIN32
LeaveCriticalSection(&m_csInstance);
#else
pthread_mutex_unlock(&m_mutex);
#endif
}
#endif // SINGLE_THREADED_MODEL
///////////////////////////////////////
extern HLogger * g_pLogFile__Logger;
extern inline int __Logger_GetLevel()
{
if (g_pLogFile__Logger == NULL)
return 0;
return g_pLogFile__Logger->GetLevel();
}
extern inline void __Logger_SetLevel(unsigned nLevel)
{
if (g_pLogFile__Logger == NULL)
return;
g_pLogFile__Logger->SetLevel(nLevel);
}
extern inline int __Logger_GetOption()
{
if (g_pLogFile__Logger == NULL)
return 0;
return g_pLogFile__Logger->GetOption();
}
extern inline void __Logger_SetOption(int flagOption)
{
if (g_pLogFile__Logger == NULL)
return;
g_pLogFile__Logger->SetOption(flagOption);
}
extern inline void __Logger_SetExtension(HLoggerExtension * pExtension)
{
if (g_pLogFile__Logger == NULL)
return;
g_pLogFile__Logger->SetExtension(pExtension);
}
extern inline void __Logger_Write(int nLevel, const char * pszLog)
{
if (g_pLogFile__Logger == NULL)
return;
g_pLogFile__Logger->Write(nLevel, pszLog);
}
extern inline void __Logger_Dump(int nLevel, const char * pszLog, size_t nSize, bool bWithHex)
{
if (g_pLogFile__Logger == NULL)
return;
g_pLogFile__Logger->Dump(nLevel, pszLog, nSize, bWithHex);
}
extern inline void __Logger_Format(int nLevel, const char * fmt, ...)
{
if (g_pLogFile__Logger == NULL)
return;
if (nLevel > g_pLogFile__Logger->GetLevel() ||
((g_pLogFile__Logger->GetOption() & HLogger::onlyLevel) == HLogger::onlyLevel && g_pLogFile__Logger->GetLevel() != nLevel))
return;
va_list vaList;
va_start(vaList, fmt);
#ifndef SINGLE_THREADED_MODEL
g_pLogFile__Logger->Lock();
#endif
#ifdef _WIN32
g_pLogFile__Logger->m_nLogLength = _vsnprintf(g_pLogFile__Logger->GetLogStringBuffer(), HLogger::MD_MAX_STRING - 1, fmt, vaList);
#else
g_pLogFile__Logger->m_nLogLength = vsnprintf(g_pLogFile__Logger->GetLogStringBuffer(), HLogger::MD_MAX_STRING - 1, fmt, vaList);
#endif
if (g_pLogFile__Logger->m_nLogLength < 0 || g_pLogFile__Logger->m_nLogLength >= HLogger::MD_MAX_STRING)
{
g_pLogFile__Logger->m_nLogLength = HLogger::MD_MAX_STRING;
g_pLogFile__Logger->GetLogStringBuffer()[HLogger::MD_MAX_STRING - 1] = '\0';
}
va_end(vaList);
g_pLogFile__Logger->WriteLog(false);
#ifndef SINGLE_THREADED_MODEL
g_pLogFile__Logger->Unlock();
#endif
}
extern inline void __Logger_SetSrcInfoWithLock(const char * szSrcFileName, const unsigned nSrcLine)
{
if (g_pLogFile__Logger == NULL)
return;
g_pLogFile__Logger->SetSrcInfoWithLock(szSrcFileName, nSrcLine);
}
extern inline void __Logger_TraceWithUnlock(int nLevel, const char *fmt, ...)
{
if (g_pLogFile__Logger == NULL)
return;
if (nLevel > g_pLogFile__Logger->GetLevel() ||
((g_pLogFile__Logger->GetLevel() & HLogger::onlyLevel) == HLogger::onlyLevel && g_pLogFile__Logger->GetLevel() != nLevel))
{
#ifndef SINGLE_THREADED_MODEL
g_pLogFile__Logger->Unlock();
#endif
return;
}
va_list vaList;
va_start(vaList, fmt);
#ifdef _WIN32
g_pLogFile__Logger->m_nLogLength = _vsnprintf(g_pLogFile__Logger->GetLogStringBuffer(), HLogger::MD_MAX_STRING - 1, fmt, vaList);
#else
g_pLogFile__Logger->m_nLogLength = vsnprintf(g_pLogFile__Logger->GetLogStringBuffer(), HLogger::MD_MAX_STRING - 1, fmt, vaList);
#endif
if (g_pLogFile__Logger->m_nLogLength < 0 || g_pLogFile__Logger->m_nLogLength >= HLogger::MD_MAX_STRING)
{
g_pLogFile__Logger->m_nLogLength = HLogger::MD_MAX_STRING;
g_pLogFile__Logger->GetLogStringBuffer()[HLogger::MD_MAX_STRING - 1] = '\0';
}
va_end(vaList);
g_pLogFile__Logger->TraceWithUnlock(nLevel);
}
#define HLOG_OPEN(LEVEL, CONTINUE, FILENAME) { if (g_pLogFile__Logger == NULL) { g_pLogFile__Logger = new HLogger; if (g_pLogFile__Logger->Create(LEVEL, CONTINUE, FILENAME) == false) g_pLogFile__Logger = NULL; } }
#define HLOG_CLOSE() { if (g_pLogFile__Logger) { delete g_pLogFile__Logger; g_pLogFile__Logger = NULL; } }
#define HLOG_GETLEVEL __Logger_GetLevel
#define HLOG_SETLEVEL __Logger_SetLevel
#define HLOG_GETOPTION __Logger_GetOption
#define HLOG_SETOPTION __Logger_SetOption
#define HLOG_SETEXTENSION __Logger_SetExtension
#define HLOG __Logger_Write
#define HLOGD __Logger_Dump
#define HLOGF __Logger_Format
#define PSTRACE __Logger_SetSrcInfoWithLock(__FILE__, __LINE__),__Logger_TraceWithUnlock
#endif // LOGGER__H_
+125
View File
@@ -0,0 +1,125 @@
################################################################################
# Common settings
AR = ar
RANLIB = ranlib
CC = g++
C = gcc
PREC = cpp
LD = g++
MAKE = make
################################################################################
# OS definition
# LINUX, FREEBSD, OSX55, SOLARIS
ifndef os
os = LINUX
endif
################################################################################
# Standard Configuration
STD_CCFLAGS += -O2 -Wall -fPIC
STD_CCFLAGS += -D_REENTRANT
STD_INC += -I/usr/local/include
STD_LIBS += -L/usr/local/lib
################################################################################
# External Library Definitions
ifeq ($(os), LINUX)
OPENSSLDIR = ../external/linux/openssl-1.0.2j
else ifeq ($(os), SOLARIS)
OPENSSLDIR = ../external/solaris/openssl-1.0.2j
endif
OPENSSL_INCDIR = $(OPENSSLDIR)/include
################################################################################
# Include Definitions
INCDIR += $(STD_INC)
INCDIR += -I$(OPENSSL_INCDIR)
#ifeq ($(use_curl), true)
#INCDIR += -I../external/curl/include
#endif
################################################################################
# c++ flags Definitions
CCFLAGS += $(INCDIR)
CCFLAGS += $(STD_CCFLAGS)
################################################################################
# Library Definitions
LIBS += $(STD_LIBS)
ifeq ($(use_curl), true)
#LIBS += -L../external/curl/lib -lcurl
#LIBS += -lcurl
endif
################################################################################
# obj generation directory flags Definitions
OBJDIR = huslib
OBJDIR_PATH = ../tmp/obj/$(OBJDIR)
################################################################################
# Source file names
SOURCES = Common.cpp Config.cpp Global.cpp hsparser.cpp HttpHandler.cpp HusApp.cpp inifile.cpp Logger.cpp MultiplexSocket.cpp MultiplexSslSocket.cpp NetUtil.cpp stringex.cpp TelnetHandler.cpp TelnetServer.cpp Timer.cpp WebServer.cpp VspHandler.cpp SohHandler.cpp
ifeq ($(use_curl), true)
SOURCES += curl_manager.cpp
endif
################################################################################
# Target file names
LIB_TOOL = libhuslib.a
LIB_SHARED = libhuslib.so
OBJS := $(SOURCES:%.c=$(OBJDIR_PATH)/%.o)
OBJS := $(OBJS:%.cxx=$(OBJDIR_PATH)/%.o)
OBJS := $(OBJS:%.cpp=$(OBJDIR_PATH)/%.o)
DEPENDS := $(SOURCES:%.c=$(OBJDIR_PATH)/%.dep)
DEPENDS := $(DEPENDS:%.cxx=$(OBJDIR_PATH)/%.dep)
DEPENDS := $(DEPENDS:%.cpp=$(OBJDIR_PATH)/%.dep)
$(OBJDIR_PATH)/%.o:%.c
$(CC) $(CCFLAGS) -c -o $@ -g $<
$(OBJDIR_PATH)/%.o:%.cxx
$(CC) $(CCFLAGS) -c -o $@ -g $<
$(OBJDIR_PATH)/%.o:%.cpp
$(CC) $(CCFLAGS) -c -o $@ -g $<
$(OBJDIR_PATH)/%.dep:%.c
@mkdir -p $(OBJDIR_PATH)
$(CC) -c $(CCFLAGS) -MM $< > $@
@sed -e "s/.o:/.c:/" $@ | sed -e "s/$<:/$(OBJDIR)\/$<:/" | sed -e "s/.c:/.o:/" > $@
@rm $@
$(OBJDIR_PATH)/%.dep:%.cxx
@mkdir -p $(OBJDIR_PATH)
$(CC) -c $(CCFLAGS) -MM $< > $@
@sed -e "s/.o:/.cxx:/" $@ | sed -e "s/$<:/$(OBJDIR)\/$<:/" | sed -e "s/.cxx:/.o:/" > $@
@rm $@
$(OBJDIR_PATH)/%.dep:%.cpp
@mkdir -p $(OBJDIR_PATH)
$(CC) -c $(CCFLAGS) -MM $< > $@
@sed -e "s/.o:/.cpp:/" $@ | sed -e "s/$<:/$(OBJDIR)\/$<:/" | sed -e "s/.cpp:/.o:/" > $@
@rm $@
#all : $(LIB_TOOL) $(LIB_SHARED)
all : $(LIB_TOOL)
$(LIB_TOOL) : $(DEPENDS) $(OBJS)
$(AR) rcv $@ $(OBJS)
$(LIB_SHARED) : $(DEPENDS) $(OBJS)
$(LD) -shared -o $(LIB_SHARED) $(OBJS) $(LIBS)
clean :
rm -f $(DEPENDS) $(OBJS)
rm -f $(LIB_TOOL) $(LIB_SHARED)
+765
View File
@@ -0,0 +1,765 @@
#ifndef _WIN32
#include <fcntl.h> // fcntl()
#include <netinet/tcp.h> // TCP_NODELAY
#endif
#include "stringex.h"
#include "Defines.h"
#include "Common.h"
#include "Object.h"
#include "String.h"
#include "Logger.h"
#include "Socket.h"
#ifndef SINGLE_THREADED_MODEL
#include "Thread.h"
#endif
#include "Timer.h"
#include "Global.h"
#include "MultiplexSocket.h"
#ifdef _WIN32
typedef int socklen_t;
#else
#define SD_BOTH SHUT_RDWR
#define FD_READ SHUT_RD
#define FD_WRITE SHUT_WR
#define closesocket close
#endif
HMultiplexSocket::HMultiplexSocket()
{
m_fdSocket = INVALID_SOCKET;
m_nState = MPS_DISABLE;
m_bSendRetry = false;
m_nLastReceivedTime = 0;
m_pDispatcher = NULL;
m_nConnectTime = g_nTcpConnectTimeout;
memset(&m_saiRemote, 0, sizeof(m_saiRemote));
}
HMultiplexSocket::HMultiplexSocket(SOCKET sock, struct sockaddr_in * psaiRemote, HMpsDispatcher * pDispatcher)
{
m_fdSocket = sock;
m_nState = MPS_READY;
m_bSendRetry = false;
m_nLastReceivedTime = 0;
m_pDispatcher = pDispatcher;
m_nConnectTime = g_nTcpConnectTimeout;
memcpy(&m_saiRemote, psaiRemote, sizeof(m_saiRemote));
}
HMultiplexSocket::~HMultiplexSocket()
{
Close();
}
bool HMultiplexSocket::Close()
{
if (m_nState == MPS_DISABLE ||
(m_nState == MPS_DELETE && m_fdSocket == INVALID_SOCKET))
//if (m_fdSocket == INVALID_SOCKET)
return false;
OnClose();
if (m_nState != MPS_LISTENING)
shutdown(m_fdSocket, SD_BOTH);
if (m_nState != MPS_DELETE)
m_nState = MPS_DISABLE;
closesocket(m_fdSocket);
HLOGF(HLOG_INFO5, "INFO, MpSock, socket closed, socket = %d\n", m_fdSocket);
m_fdSocket = INVALID_SOCKET;
return true;
}
bool HMultiplexSocket::Connect(unsigned nConnectTime)
{
if (m_fdSocket == INVALID_SOCKET)
{
HLOGF(HLOG_WARNING, "[WARN], MpSock, This socket did not created.\n");
return false;
}
m_nLastTryConnectTime = 0;
if (nConnectTime)
m_nConnectTime = nConnectTime;
int nResult = connect(m_fdSocket, (struct sockaddr *)&m_saiRemote, sizeof(struct sockaddr));
if (nResult == SOCKET_ERROR &&
#ifdef _WIN32
SockErrorNo() != WSAEWOULDBLOCK)
#else
SockErrorNo() != EWOULDBLOCK && SockErrorNo() != EINPROGRESS)
#endif
{
HLOGF(HLOG_WARNING, "[WARN], MpSock, Failed to connect. socket = %d, error = %d\n", m_fdSocket, SockErrorNo());
OnConnect(false);
m_nState = MPS_CLOSING;
return 0;
}
HLOGF(HLOG_INFO4, "INFO, MpSock, TCP connecting... to %s:%d (socket = %d)\n", inet_ntoa(m_saiRemote.sin_addr), ntohs(m_saiRemote.sin_port), m_fdSocket);
m_nState = MPS_CONNECTING;
return true;
}
bool HMultiplexSocket::IsConnectTimeout(DWORD nCurrTime)
{
if (m_nConnectTime <= 0)
return false;
if (m_nLastTryConnectTime == 0)
m_nLastTryConnectTime = nCurrTime;
if (m_nConnectTime <= TimeDiff(m_nLastTryConnectTime, nCurrTime))
return true;
return false;
}
bool HMultiplexSocket::Bind(struct sockaddr_in * psaiLocal)
{
if (m_fdSocket == INVALID_SOCKET)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, This socket did not created.\n");
return false;
}
if (bind(m_fdSocket, (struct sockaddr *)psaiLocal, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Failed to bind, (%s:%d), error = %d\n", inet_ntoa(psaiLocal->sin_addr), ntohs(psaiLocal->sin_port), SockErrorNo());
return false;
}
HLOGF(HLOG_INFO4, "INFO, MpSock, Succeed to bind, (%s:%d), socket = %d\n", inet_ntoa(psaiLocal->sin_addr), ntohs(psaiLocal->sin_port), m_fdSocket);
return true;
}
bool HMultiplexSocket::Bind(const char * pszAddress, u_short nPort)
{
if (m_fdSocket == INVALID_SOCKET)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, This socket did not created.\n");
return false;
}
struct sockaddr_in sai;
sai.sin_family = AF_INET;
sai.sin_addr.s_addr = inet_addr(pszAddress);
sai.sin_port = htons(nPort);
return HMultiplexSocket::Bind(&sai);
}
bool HMultiplexSocket::GetRemoteAddress(char * pBuf, u_short * pnPort)
{
if (pBuf)
strcpy(pBuf, inet_ntoa(m_saiRemote.sin_addr));
if (pnPort)
*pnPort = ntohs(m_saiRemote.sin_port);
return true;
}
bool HMultiplexSocket::SetRemoteAddress(struct sockaddr_in * psaiLocal)
{
memcpy(&m_saiRemote, psaiLocal, sizeof(struct sockaddr_in));
return true;
}
bool HMultiplexSocket::SetRemoteAddress(const char * pszAddress, u_short nPort)
{
m_saiRemote.sin_family = AF_INET;
m_saiRemote.sin_addr.s_addr = inet_addr(pszAddress);
m_saiRemote.sin_port = htons(nPort);
return true;
}
bool HMultiplexSocket::SetRemoteAddressHostByName(const char * pszHostName, u_short nPort)
{
struct hostent * pHE;
// resolve host address
if ((pHE = gethostbyname(pszHostName)) == NULL)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Failed to gethostbyname, socket = %d, error = %d\n", m_fdSocket, SockErrorNo());
#if _MSC_VER <= 1200
return false;
#else
char szPort[16];
struct addrinfo aiHints;
struct addrinfo *aiList = NULL;
struct addrinfo *aiPtr = NULL;
int retVal;
memset(&aiHints, 0, sizeof(aiHints));
aiHints.ai_family = AF_INET;
aiHints.ai_socktype = SOCK_STREAM;
aiHints.ai_protocol = IPPROTO_TCP;
sprintf(szPort, "%d", nPort);
if ((retVal = getaddrinfo(pszHostName, szPort, &aiHints, &aiList)) != 0)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Failed to getaddrinfo, socket = %d, error = %d, retVal = %d\n", m_fdSocket, SockErrorNo(), retVal);
return false;
}
for(aiPtr = aiList; aiPtr != NULL; aiPtr=aiPtr->ai_next)
{
if (aiPtr->ai_family == AF_INET)
{
memcpy(&m_saiRemote, aiPtr->ai_addr, sizeof(struct sockaddr_in));
freeaddrinfo(aiList);
return true;
}
}
return false;
#endif
}
memcpy(&m_saiRemote.sin_addr, pHE->h_addr_list[0], pHE->h_length);
m_saiRemote.sin_port = htons(nPort); // short, network byte order
m_saiRemote.sin_family = AF_INET; // host byte order
return true;
}
void HMultiplexSocket::OnConnect(bool /* bIsSuccess */)
{
HLOGF(HLOG_WARNING, "[WARN], MpSock, Called to OnConnect of parent class, socket = %d\n", m_fdSocket);
}
void HMultiplexSocket::OnReceive()
{
HLOGF(HLOG_WARNING, "[WARN], MpSock, Called to OnReceive of parent class, socket = %d\n", m_fdSocket);
}
int HMultiplexSocket::OnSendRetry()
{
HLOGF(HLOG_WARNING, "[WARN], MpSock, Called to OnReceive of parent class, socket = %d\n", m_fdSocket);
return -1;
}
//////////////////////////////////////////////////////////////////////////////
bool HMultiplexTcpSocket::Create(bool bIsTcpNoDelay)
{
if (m_fdSocket != INVALID_SOCKET)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, This socket aleady created. socket = %d\n", m_fdSocket);
return false;
}
if ((m_fdSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Don't create socket. error = %d\n", SockErrorNo());
return false;
}
// Set non blocking mode
#ifdef _WIN32
ULONG nNonBlock = 1;
if (ioctlsocket(m_fdSocket, FIONBIO, &nNonBlock) == SOCKET_ERROR)
{
m_fdSocket = INVALID_SOCKET;
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Failed to ioctlsocket. socket = %d, WSAGetLastError = %d\n", m_fdSocket, SockErrorNo());
return false;
}
#else
int nFlags = fcntl(m_fdSocket, F_GETFL, 0);
fcntl(m_fdSocket, F_SETFL, nFlags | O_NONBLOCK);
#endif
int nBuffSize = MPS_MAX_SOCKET_BUFFER;
if (setsockopt(m_fdSocket, SOL_SOCKET, SO_SNDBUF, (const char *)&nBuffSize, sizeof(nBuffSize)) == SOCKET_ERROR)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Failed to setsockopt SO_SNDBUF. socket = %d, error = %d\n", m_fdSocket, SockErrorNo());
}
if (setsockopt(m_fdSocket, SOL_SOCKET, SO_RCVBUF, (const char *)&nBuffSize, sizeof(nBuffSize)) == SOCKET_ERROR)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Failed to setsockopt SO_RCVBUF. socket = %d, error = %d\n", m_fdSocket, SockErrorNo());
}
if (bIsTcpNoDelay) //... linux error
{
bool bNoDelay = false;
if (setsockopt(m_fdSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&bNoDelay, sizeof(bNoDelay)) == SOCKET_ERROR)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Failed setsockopt TCP_NODELAY. socket = %d, error = %d\n", m_fdSocket, SockErrorNo());
}
}
int nKeepAlive = 1;
if (setsockopt(m_fdSocket, SOL_SOCKET, SO_KEEPALIVE, (const char *)&nKeepAlive, sizeof(nKeepAlive)) == SOCKET_ERROR)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Failed to setsockopt SO_KEEPALIVE. socket = %d, error = %d\n", m_fdSocket, SockErrorNo());
}
HLOGF(HLOG_INFO5, "INFO, MpSock, TCP socket created. socket = %d\n", m_fdSocket);
return true;
}
int HMultiplexTcpSocket::Send(const char * pData, int nSize)
{
int nSentSize = send(m_fdSocket, pData, nSize, 0);
if (nSentSize == SOCKET_ERROR)
{
int nError = SockErrorNo();
#ifdef _WIN32
if (nError != WSAEWOULDBLOCK)
#else
if (nError != EWOULDBLOCK && nError != EAGAIN)
#endif
{
HLOGF(HLOG_WARNING, "[WARN], MpSock, Failed to send, socket = %d, error = %d\n", m_fdSocket, nError);
m_nState = MPS_CLOSING;
return -1;
}
m_bSendRetry = true;
return 0;
}
else if (nSentSize < nSize)
{
m_bSendRetry = true;
return nSentSize;
}
if (m_bSendRetry)
m_bSendRetry = false;
return nSentSize;
}
int HMultiplexTcpSocket::Receive(char * pBuffer, int nSize)
{
int nReceivedSize = recv(m_fdSocket, pBuffer, nSize, 0);
if (nReceivedSize == SOCKET_ERROR)
{
HLOGF(HLOG_INFO4, "INFO, MpSock, The virtual circuit was reset by the remote side executing a \"hard\" or \"abortive\" close, socket = %d, error = %d\n", m_fdSocket, SockErrorNo());
m_nState = MPS_CLOSING;
return SOCKET_ERROR;
}
else if (nReceivedSize == 0)
{
HLOGF(HLOG_INFO4, "INFO, MpSock, The virtual circuit was reset by the remote side executing a \"gracefull\" shutdown, socket = %d\n", m_fdSocket);
m_nState = MPS_CLOSING;
return 0;
}
return nReceivedSize;
}
void HMultiplexTcpSocket::FinishTcp()
{
shutdown(m_fdSocket, FD_WRITE);
HLOGF(HLOG_INFO5, "INFO, MPSock, write shutdown, socket = %d\n", m_fdSocket);
m_nState = MPS_CLOSING;
}
//////////////////////////////////////////////////////////////////////////////
bool HMultiplexUdpSocket::Create()
{
if (m_fdSocket != INVALID_SOCKET)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, This socket aleady created. socket = %d\n", m_fdSocket);
return false;
}
if ((m_fdSocket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Don't create socket. error = %d\n", SockErrorNo());
return false;
}
// Set non blocking mode
#ifdef _WIN32
ULONG nNonBlock = 1;
if (ioctlsocket(m_fdSocket, FIONBIO, &nNonBlock) == SOCKET_ERROR)
{
m_fdSocket = INVALID_SOCKET;
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Failed to ioctlsocket. socket = %d, WSAGetLastError = %d\n", m_fdSocket, SockErrorNo());
return false;
}
#else
int nFlags = fcntl(m_fdSocket, F_GETFL, 0);
fcntl(m_fdSocket, F_SETFL, nFlags | O_NONBLOCK);
#endif
int nBuffSize = MPS_MAX_SOCKET_BUFFER;
if (setsockopt(m_fdSocket, SOL_SOCKET, SO_SNDBUF, (const char *)&nBuffSize, sizeof(nBuffSize)) == SOCKET_ERROR)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Failed to setsockopt SO_SNDBUF. socket = %d, error = %d\n", m_fdSocket, SockErrorNo());
}
if (setsockopt(m_fdSocket, SOL_SOCKET, SO_RCVBUF, (const char *)&nBuffSize, sizeof(nBuffSize)) == SOCKET_ERROR)
{
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Failed to setsockopt SO_RCVBUF. socket = %d, error = %d\n", m_fdSocket, SockErrorNo());
}
HLOGF(HLOG_INFO5, "INFO, MpSock, UDP socket created. socket = %d\n", m_fdSocket);
return true;
}
bool HMultiplexUdpSocket::Bind(struct sockaddr_in * psaiLocal)
{
if (HMultiplexSocket::Bind(psaiLocal) == false)
return false;
m_nState = MPS_READY;
return true;
}
bool HMultiplexUdpSocket::SetRemoteAddress(struct sockaddr_in * psaiLocal)
{
memcpy(&m_saiRemote, psaiLocal, sizeof(struct sockaddr_in));
m_nState = MPS_READY;
return true;
}
bool HMultiplexUdpSocket::SetRemoteAddress(const char * pszAddress, u_short nPort)
{
m_saiRemote.sin_family = AF_INET;
m_saiRemote.sin_addr.s_addr = inet_addr(pszAddress);
m_saiRemote.sin_port = htons(nPort);
m_nState = MPS_READY;
return true;
}
//////////////////////////////////////////////////////////////////////////////
HMpsDispatcher::HMpsDispatcher()
{
m_nLoopInterval = 0;
m_bTerminate = false;
#ifndef SINGLE_THREADED_MODEL
m_bProecessing = false;
#endif
}
HMpsDispatcher::~HMpsDispatcher()
{
RemoveAllSocket();
}
bool HMpsDispatcher::Attach(HMultiplexSocket * pSocket)
{
pSocket->SetDispatcher(this);
m_listSocket.push_front(pSocket);
return true;
}
bool HMpsDispatcher::AttachWithLock(HMultiplexSocket * pSocket)
{
pSocket->SetDispatcher(this);
#ifndef SINGLE_THREADED_MODEL
m_syncObject.Lock();
#endif
m_listSocket.push_front(pSocket);
#ifndef SINGLE_THREADED_MODEL
m_syncObject.Unlock();
#endif
return true;
}
bool HMpsDispatcher::Detach(HMultiplexSocket * pSocket)
{
pSocket->m_pDispatcher = NULL;
pSocket->SetState(HMultiplexSocket::MPS_DELETE);
return true;
}
void HMpsDispatcher::RemoveAllSocket()
{
if (m_listSocket.empty())
return;
#ifndef SINGLE_THREADED_MODEL
m_syncObject.Lock();
#endif
for (LIST_MULTIPLEX_SOCKET::iterator iter = m_listSocket.begin();
iter != m_listSocket.end(); iter++)
{
HMultiplexSocket * pSocket = *iter;
if (pSocket)
{
pSocket->Close();
delete pSocket;
}
}
m_listSocket.clear();
#ifndef SINGLE_THREADED_MODEL
m_syncObject.Unlock();
#endif
}
bool HMpsDispatcher::Dispatch()
{
HMultiplexSocket * pSocket;
fd_set fdSetRead, fdSetWrite;//, fdSetError;
int nSelectResult, nFDMax, nFDCount;
LIST_MULTIPLEX_SOCKET::iterator iter;
struct timeval tvWait;
long nTimeout = m_nLoopInterval * 1000; // msec
m_bTerminate = false;
while (m_bTerminate == false)
{
FD_ZERO(&fdSetRead);
FD_ZERO(&fdSetWrite);
//FD_ZERO(&fdSetError);
tvWait.tv_sec = 0;
tvWait.tv_usec = nTimeout;
nFDMax = 0;
nFDCount = 0;
#ifndef SINGLE_THREADED_MODEL
m_bProecessing = true;
m_syncObject.Lock();
#endif
for (iter = m_listSocket.begin(); iter != m_listSocket.end(); iter++)
{
pSocket = *iter;
if (pSocket->GetState() == HMultiplexSocket::MPS_CLOSING ||
pSocket->GetState() == HMultiplexSocket::MPS_DELETE)
{
pSocket->Close();
if (pSocket->GetState() == HMultiplexSocket::MPS_DELETE)
{
delete pSocket;
iter = m_listSocket.erase(iter);
if (m_listSocket.empty() || iter == m_listSocket.end())
break;
pSocket = *iter;
}
}
if (pSocket->GetState() == HMultiplexSocket::MPS_READY ||
pSocket->GetState() == HMultiplexSocket::MPS_LISTENING)
{
FD_SET(pSocket->GetSocket(), &fdSetRead);
//FD_SET(pSocket->GetSocket(), &fdSetError);
nFDCount++;
#ifndef _WIN32
if (nFDMax < pSocket->GetSocket())
nFDMax = pSocket->GetSocket();
#endif
}
else if (pSocket->GetState() == HMultiplexSocket::MPS_CONNECTING)
{
if (pSocket->IsConnectTimeout(HTIMER()->GetTickCount()))
{
HLOGF(HLOG_WARNING, "[WARN], MpsDisp, Failed to connect because of timeout. socket = %d\n", pSocket->GetSocket());
pSocket->OnConnect(false);
pSocket->SetState(HMultiplexSocket::MPS_CLOSING);
}
else
{
FD_SET(pSocket->GetSocket(), &fdSetRead);
FD_SET(pSocket->GetSocket(), &fdSetWrite);
//FD_SET(pSocket->GetSocket(), &fdSetError);
nFDCount++;
#ifndef _WIN32
if (nFDMax < pSocket->GetSocket())
nFDMax = pSocket->GetSocket();
#endif
}
}
if (pSocket->IsSendRetry())
{
FD_SET(pSocket->GetSocket(), &fdSetWrite);
nFDCount++;
#ifndef _WIN32
if (nFDMax < pSocket->GetSocket())
nFDMax = pSocket->GetSocket();
#endif
}
}
#ifndef SINGLE_THREADED_MODEL
m_bProecessing = false;
m_syncObject.Unlock();
#endif
if (m_listSocket.empty() || nFDCount == 0)
{
Sleep(10);
continue;
}
//if ((nSelectResult = select(nFDMax + 1, &fdSetRead, &fdSetWrite, &fdSetError, &tvWait)) == SOCKET_ERROR)
if ((nSelectResult = select(nFDMax + 1, &fdSetRead, &fdSetWrite, NULL, m_nLoopInterval ? &tvWait : NULL)) == SOCKET_ERROR)
{
Sleep(10);
continue;
}
//printf("nSelectResult = %d\n", nSelectResult);
if (nSelectResult <= 0)
continue;
#ifndef SINGLE_THREADED_MODEL
m_bProecessing = true;
m_syncObject.Lock();
#endif
for (iter = m_listSocket.begin(); iter != m_listSocket.end(); iter++)
{
pSocket = *iter;
if (pSocket->GetState() == HMultiplexSocket::MPS_DISABLE ||
pSocket->GetState() == HMultiplexSocket::MPS_CLOSING ||
pSocket->GetState() == HMultiplexSocket::MPS_DELETE)
{
continue;
}
if (FD_ISSET(pSocket->GetSocket(), &fdSetRead) != 0)
{
if (pSocket->GetState() == HMultiplexSocket::MPS_READY)
{
pSocket->OnReceive();
pSocket->m_nLastReceivedTime = HTIMER()->GetTickCount();
}
else if (pSocket->GetState() == HMultiplexSocket::MPS_LISTENING)
{
SOCKET sock = INVALID_SOCKET;
socklen_t len = sizeof(struct sockaddr);
struct sockaddr_in sai;
if ((sock = accept(pSocket->GetSocket(), (struct sockaddr *)&sai, &len)) == INVALID_SOCKET)
{
HLOGF(HLOG_WARNING, "[WARN], MpsDisp, Failed to accept, socket = %d, error = %d\n", pSocket->GetSocket(), SockErrorNo());
Sleep(50);
}
else
{
char szListenIp[32];
u_short nListenPort = 0;
pSocket->GetLocalAddress(szListenIp, &nListenPort);
HLOGF(HLOG_INFO4, "INFO, MpsDisp, Succeeded to accept, (%s:%d), (%s:%d), socket = %d\n", szListenIp, nListenPort, inet_ntoa(sai.sin_addr), ntohs(sai.sin_port), sock);
HMultiplexSocket * pAcceptedSocket = pSocket->OnAccept(sock, &sai);
if (pAcceptedSocket)
{
// Set non blocking mode
#ifdef _WIN32
ULONG nNonBlock = 1;
if (ioctlsocket(pAcceptedSocket->GetSocket(), FIONBIO, &nNonBlock) == SOCKET_ERROR)
HLOGF(HLOG_ERROR, "[ERROR], MpSock, Failed to ioctlsocket, socket = %d, WSAGetLastError = %d\n", pAcceptedSocket->GetSocket(), SockErrorNo());
#else
int nFlags = fcntl(pAcceptedSocket->GetSocket(), F_GETFL, 0);
fcntl(pAcceptedSocket->GetSocket(), F_SETFL, nFlags | O_NONBLOCK);
#endif
m_listSocket.push_front(pAcceptedSocket);
pAcceptedSocket->m_nLastReceivedTime = HTIMER()->GetTickCount();
pAcceptedSocket->OnAccepted();
}
else
closesocket(sock);
}
}
FD_CLR(pSocket->GetSocket(), &fdSetRead);
if (--nSelectResult <= 0)
break;
}
if (FD_ISSET(pSocket->GetSocket(), &fdSetWrite) != 0)
{
if (pSocket->GetState() == HMultiplexSocket::MPS_CONNECTING)
{
int nSocketError = pSocket->GetSockOptError();
if (nSocketError != 0)
{
HLOGF(HLOG_WARNING, "[WARN], MpsDisp, Failed to connect (%s:%d), socket = %d, error = %d\n",
inet_ntoa(pSocket->GetRemoteAddress()->sin_addr), ntohs(pSocket->GetRemoteAddress()->sin_port), pSocket->GetSocket(), nSocketError);
pSocket->OnConnect(false);
pSocket->SetState(HMultiplexSocket::MPS_CLOSING);
}
else
{
HLOGF(HLOG_INFO4, "INFO, MpsDisp, Succeeded to connect (%s:%d) socket = %d\n",
inet_ntoa(pSocket->GetRemoteAddress()->sin_addr), ntohs(pSocket->GetRemoteAddress()->sin_port), pSocket->GetSocket());
pSocket->SetState(HMultiplexSocket::MPS_READY);
pSocket->OnConnect(true);
pSocket->m_nLastReceivedTime = HTIMER()->GetTickCount();
}
}
else if (pSocket->GetState() == HMultiplexSocket::MPS_READY)
{
if (pSocket->OnSendRetry() < 0) // remain packet send
pSocket->FinishTcp();
}
FD_CLR(pSocket->GetSocket(), &fdSetWrite);
if (--nSelectResult <= 0)
break;
}
}
#ifndef SINGLE_THREADED_MODEL
m_bProecessing = false;
m_syncObject.Unlock();
#endif
}
return false;
}
+486
View File
@@ -0,0 +1,486 @@
#ifndef MULTIPLEX_SOCKET__H_
#define MULTIPLEX_SOCKET__H_
#ifdef _WIN32
#pragma once
#pragma warning(disable:4244)
#pragma warning(disable:4267)
#endif
#include <list>
class HMpsDispatcher;
class HMultiplexSocket : public HSocket
{
public:
enum
{
MPS_DISABLE = 1,
MPS_READY,
MPS_CONNECTING,
MPS_LISTENING,
MPS_CLOSING,
MPS_DELETE
};
enum
{
MPS_MAX_SOCKET_BUFFER = 16384
};
HMultiplexSocket();
HMultiplexSocket(SOCKET sock, struct sockaddr_in * psaiRemote, HMpsDispatcher * pDispatcher);
~HMultiplexSocket();
inline int GetState() { return m_nState; }
inline void SetState(int nState) { m_nState = nState; }
inline unsigned int GetLastReceivedTime() { return m_nLastReceivedTime; }
inline bool IsSendRetry() { return m_bSendRetry; }
HMpsDispatcher * GetDispatcher() { return m_pDispatcher; }
void SetDispatcher(HMpsDispatcher * pDispatcher) { m_pDispatcher = pDispatcher; }
virtual bool Close();
virtual bool Connect(unsigned nConnectTime = 60000); // msec
bool IsConnectTimeout(DWORD nCurrTime);
bool Bind(struct sockaddr_in * psaiLocal);
bool Bind(const char * pszAddress, u_short nPort);
struct sockaddr_in * GetRemoteAddress() { return &m_saiRemote; }
bool GetRemoteAddress(char * pBuf, u_short * pnPort);
bool SetRemoteAddress(struct sockaddr_in * psaiLocal);
bool SetRemoteAddress(const char * pszAddress, u_short nPort);
bool SetRemoteAddressHostByName(const char * pszHostName, u_short nPort);
virtual int Send(const char * pData, int nSize) = 0;
virtual int Receive(char * pBuffer, int nSize) = 0;
virtual void FinishTcp() {}
protected:
virtual void OnClose() {}
virtual void OnConnect(bool bIsSuccess); // only called for client socket
virtual void OnReceive();
virtual int OnSendRetry();
virtual void OnAccepted() {} // only called for child socket
public:
virtual HMultiplexSocket * OnAccept(SOCKET /* sock */, struct sockaddr_in * /* psaiRemote */) { return NULL; }
protected:
int m_nState;
bool m_bSendRetry;
unsigned int m_nLastReceivedTime;
struct sockaddr_in m_saiRemote;
HMpsDispatcher * m_pDispatcher;
private:
unsigned long m_nConnectTime;
unsigned long m_nLastTryConnectTime;
friend class HMpsDispatcher;
template<class _Ty> friend class HMultiplexListenThread;
};
class HMultiplexTcpSocket : public HMultiplexSocket
{
public:
HMultiplexTcpSocket() {}
HMultiplexTcpSocket(SOCKET sock, struct sockaddr_in * psaiRemote, HMpsDispatcher * pDispatcher) : HMultiplexSocket(sock, psaiRemote, pDispatcher) {}
~HMultiplexTcpSocket() {}
bool Create(bool bIsTcpNoDelay = false);
virtual bool IsSslSocket() { return false; }
virtual int Send(const char * pData, int nSize);
virtual int Receive(char * pBuffer, int nSize);
virtual void FinishTcp(); // remain send and shutdown
};
class HMultiplexUdpSocket : public HMultiplexSocket
{
public:
HMultiplexUdpSocket() {}
~HMultiplexUdpSocket() {}
virtual bool Create();
virtual bool SetRemoteAddress(struct sockaddr_in * psaiLocal);
virtual bool SetRemoteAddress(const char * pszAddress, u_short nPort);
virtual bool Bind(struct sockaddr_in * psaiLocal);
virtual inline int Send(const char * pData, int nSize)
{
return sendto(m_fdSocket, pData, nSize, 0, (struct sockaddr *)&m_saiRemote, sizeof(struct sockaddr));
}
virtual inline int Receive(char * pBuffer, int nSize)
{
return recvfrom(m_fdSocket, pBuffer, nSize, 0, NULL, 0);
}
virtual inline int Receive(char * pBuffer, int nSize, struct sockaddr_in * psaiUDPFrom)
{
socklen_t len = sizeof(struct sockaddr);
return recvfrom(m_fdSocket, pBuffer, nSize, 0, (struct sockaddr *)psaiUDPFrom, &len);
}
};
class HMultiplexListenSocket : public HMultiplexTcpSocket
{
public:
HMultiplexListenSocket() {}
~HMultiplexListenSocket() {}
bool Listen(const char * pszAddress, u_short nPort, int nBackLog = 10)
{
if (Create() == false)
return false;
#ifdef REUSEADDR
int nOptVal = 1;
SetSockOpt(SOL_SOCKET, SO_REUSEADDR, (const char *)&nOptVal, sizeof(nOptVal)); // for multiple ip in UNIX
#endif
if (Bind(pszAddress, nPort) == false)
{
HLOGF(HLOG_ERROR, "[ERROR], MpLstnSock, Failed to bind, (%s:%d), error = %d\n", pszAddress, nPort, SockErrorNo());
return false;
}
if (listen(m_fdSocket, nBackLog) == SOCKET_ERROR)
{
HLOGF(HLOG_ERROR, "[ERROR], MpLstnSock, Failed to listen, (%s:%d), error = %d\n", pszAddress, nPort, SockErrorNo());
return false;
}
m_nState = MPS_LISTENING;
HLOGF(HLOG_INFO1, "INFO, MpLstnSock, Succeed to listen TCP, (%s:%d), socket = %d\n", pszAddress, nPort, m_fdSocket);
return true;
}
private:
virtual HMultiplexTcpSocket * OnAccept(SOCKET sock, struct sockaddr_in * psaiRemote) = 0;
};
typedef std::list<HMultiplexSocket *> LIST_MULTIPLEX_SOCKET;
class HMpsDispatcher
{
public:
HMpsDispatcher();
virtual ~HMpsDispatcher();
void Initialize(unsigned long nLoopInterval) { m_nLoopInterval = nLoopInterval; } // msec, for connect timeout
void SetTerminateFlag() { m_bTerminate = true; }
LIST_MULTIPLEX_SOCKET * GetSocketList() { return &m_listSocket; }
bool Attach(HMultiplexSocket * pSocket);
bool AttachWithLock(HMultiplexSocket * pSocket);
bool Detach(HMultiplexSocket * pSocket);
void RemoveAllSocket();
#ifndef SINGLE_THREADED_MODEL
inline bool IsProcessing() { return m_bProecessing; }
#endif
bool Dispatch();
//private:
public:
LIST_MULTIPLEX_SOCKET m_listSocket;
unsigned long m_nLoopInterval;
volatile bool m_bTerminate;
public: //...TempCode
#ifndef SINGLE_THREADED_MODEL
HSyncObject m_syncObject;
volatile bool m_bProecessing;
#endif
};
class HMpsDispatcherList : public std::list<HMpsDispatcher *>
{
public:
HMpsDispatcherList() { m_nLazyIndex = 0; }
~HMpsDispatcherList() {}
HMpsDispatcher * GetLazyDispatcher()
{
iterator iter;
int i = 0;
for (iter = begin(); iter != end(); iter++)
{
if ((*iter)->IsProcessing() == false)
i++;
}
//HLOGF(HLOG_WARNING, "[TRACE], DispatcherList_0x%x, lazy count = %d\n", this, i);
i = 0;
for (iter = begin(); iter != end(); iter++)
{
if (i == m_nLazyIndex)
{
m_nLazyIndex++;
if (m_nLazyIndex >= (int)size())
m_nLazyIndex = 0;
return *iter;
}
i++;
}
return NULL;
}
public:
volatile int m_nLazyIndex;
};
///////////////////////////////////////
class HMultiplexSocketDispatchThread : public HThread
{
public:
HMultiplexSocketDispatchThread()
: HThread(true, 1024 * 1024 * 4) // stack size : 4MB
{
m_pMpsDispatcher = new HMpsDispatcher;
}
~HMultiplexSocketDispatchThread()
{
delete m_pMpsDispatcher;
}
inline HMpsDispatcher * GetDispatcher() { return m_pMpsDispatcher; }
inline void DispatchLock() { m_pMpsDispatcher->m_syncObject.Lock(); }
inline void DispatchUnlock() { m_pMpsDispatcher->m_syncObject.Unlock(); }
inline unsigned long BeginDispatch(unsigned long nLoopInterval = 50)
{
m_pMpsDispatcher->Initialize(nLoopInterval);
return HThread::Begin();
}
void Terminate()
{
m_pMpsDispatcher->SetTerminateFlag();
}
protected:
void Main() { m_pMpsDispatcher->Dispatch(); }
private:
inline unsigned long Begin() { return 0; } // do not use
private:
HMpsDispatcher * m_pMpsDispatcher;
};
///////////////////////////////////////
template<class _Ty>
class HMultiplexListenThread : public HThread
{
public:
HMultiplexListenThread()
: HThread(true, 0)
{
m_sockListen = INVALID_SOCKET;
m_bTerminate = false;
}
~HMultiplexListenThread() {}
inline void SetDispatcherList(HMpsDispatcherList * pList) { m_pListDispatcher = pList; }
bool Listen(const char * pszAddress, u_short nPort, int nBackLog = 10)
{
if (m_sockListen != INVALID_SOCKET)
{
HLOGF(HLOG_ERROR, "[ERROR], MpLstnThr, This socket aleady created. socket = %d\n", m_sockListen);
return false;
}
if ((m_sockListen = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
HLOGF(HLOG_ERROR, "[ERROR], MpLstnThr, Don't create socket. Error = %d\n", SockErrorNo());
return false;
}
// Set non blocking mode
#ifdef _WIN32
ULONG nNonBlock = 1;
if (ioctlsocket(m_sockListen, FIONBIO, &nNonBlock) == SOCKET_ERROR)
{
m_sockListen = INVALID_SOCKET;
HLOGF(HLOG_ERROR, "[ERROR], MpLstnThrd, Failed to ioctlsocket, socket = %d, error = %d\n", m_sockListen, SockErrorNo());
return false;
}
#else
int nFlags = fcntl(m_sockListen, F_GETFL, 0);
fcntl(m_sockListen, F_SETFL, nFlags | O_NONBLOCK);
#endif
struct sockaddr_in sai;
memset(&sai, 0, sizeof(struct sockaddr_in));
if (pszAddress == NULL || pszAddress[0] == '\0')
sai.sin_addr.s_addr = htonl(INADDR_ANY);
else
sai.sin_addr.s_addr = inet_addr(pszAddress);
sai.sin_family = AF_INET;
sai.sin_port = htons(nPort);
#ifdef REUSEADDR
int nOptVal = 1;
setsockopt(m_sockListen, SOL_SOCKET, SO_REUSEADDR, (const char *)&nOptVal, sizeof(nOptVal)); // for multiple ip in UNIX
#endif
if (bind(m_sockListen, (struct sockaddr *)&sai, sizeof(struct sockaddr)) < 0)
{
HLOGF(HLOG_ERROR, "[ERROR], MpLstnThrd, Failed to bind, (%s:%d), socket = %d, error = %d\n", pszAddress, nPort, m_sockListen, SockErrorNo());
return false;
}
if (listen(m_sockListen, nBackLog) == SOCKET_ERROR)
{
HLOGF(HLOG_ERROR, "[ERROR], MpLstnThrd, Failed to listen, (%s:%d), socket = %d, error = %d\n", pszAddress, nPort, m_sockListen, SockErrorNo());
return false;
}
HLOGF(HLOG_INFO1, "INFO, MpLstnThrd, Succeed to listen TCP, (%s:%d), socket = %d\n", pszAddress, nPort, m_sockListen);
m_strListenIp = pszAddress;
m_nListenPort = nPort;
Begin();
return true;
}
void Terminate()
{
closesocket(m_sockListen);
for (HMpsDispatcherList::iterator iter = m_pListDispatcher->begin(); iter != m_pListDispatcher->end(); iter++)
{
(*iter)->SetTerminateFlag(); // auto delete
}
m_bTerminate = true;
}
protected:
void Main()
{
HLOGF(HLOG_INFO5, "INFO, MpLstnThrd, listen thread begins, (%s:%d)\n", m_strListenIp.psz(), m_nListenPort);
fd_set fdSetRead;//, fdSetError;
int nSelectResult;
SOCKET sockClient = INVALID_SOCKET;
socklen_t len = sizeof(struct sockaddr);
struct sockaddr_in sai;
FD_ZERO(&fdSetRead);
//FD_ZERO(&fdSetError);
while (m_bTerminate == false)
{
FD_SET(m_sockListen, &fdSetRead);
//FD_SET(m_sockListen, &fdSetError);
if ((nSelectResult = select(m_sockListen + 1, &fdSetRead, NULL, NULL, NULL)) == SOCKET_ERROR)
{
Sleep(10);
continue;
}
if ((sockClient = accept(m_sockListen, (struct sockaddr *)&sai, &len)) == INVALID_SOCKET)
{
HLOGF(HLOG_WARNING, "[WARN], MpLstnThrd, Failed to accept, (%s:%d), socket = %d, error = %d\n", m_strListenIp.psz(), m_nListenPort, m_sockListen, SockErrorNo());
Sleep(50);
}
else
{
HLOGF(HLOG_INFO4, "INFO, MpLstnThrd, Succeeded to accept, (%s:%d), (%s:%d), socket = %d\n", m_strListenIp.psz(), m_nListenPort, inet_ntoa(sai.sin_addr), ntohs(sai.sin_port), sockClient);
// Set non blocking mode
#ifdef _WIN32
ULONG nNonBlock = 1;
if (ioctlsocket(sockClient, FIONBIO, &nNonBlock) == SOCKET_ERROR)
HLOGF(HLOG_ERROR, "[ERROR], MpLstnThrd, Failed to ioctlsocket, socket = %d, error = %d\n", sockClient, SockErrorNo());
#else
int nFlags = fcntl(sockClient, F_GETFL, 0);
fcntl(sockClient, F_SETFL, nFlags | O_NONBLOCK);
#endif
HMultiplexTcpSocket * pAcceptedSocket = OnAccept(sockClient, &sai);
if (pAcceptedSocket)
{
pAcceptedSocket->m_nLastReceivedTime = HTIMER()->GetTickCount();
pAcceptedSocket->OnAccepted();
}
else
closesocket(sockClient);
}
}
}
private:
virtual HMultiplexTcpSocket * OnAccept(SOCKET sock, struct sockaddr_in * psaiRemote)
{
#if 1
HMpsDispatcher * pDispatcher = m_pListDispatcher->GetLazyDispatcher();
HMultiplexTcpSocket * pMpSocket = new _Ty(sock, psaiRemote, pDispatcher);
pDispatcher->Attach(pMpSocket);
return pMpSocket;
#else
HMpsDispatcherList::iterator iter;
int i = 0;
for (iter = m_pListDispatcher->begin(); iter != m_pListDispatcher->end(); iter++)
{
if ((*iter)->IsProcessing() == false)
i++;
}
//HLOGF(HLOG_WARNING, "[TRACE], MplxLstnThr_0x%x, lazy dispatcher count = %d\n", this, i);
for (;;)
{
for (iter = m_pListDispatcher->begin(); iter != m_pListDispatcher->end(); iter++)
{
if ((*iter)->IsProcessing() == false)
{
HMultiplexTcpSocket * pMpSocket = new _Ty(sock, psaiRemote, *iter);
(*iter)->Attach(pMpSocket);
return pMpSocket;
}
}
Sleep(10);
}
#endif
}
protected:
HMpsDispatcherList * m_pListDispatcher;
SOCKET m_sockListen;
HString m_strListenIp;
u_short m_nListenPort;
volatile bool m_bTerminate;
};
#endif // MULTIPLEX_SOCKET__H_
+627
View File
@@ -0,0 +1,627 @@
#include "stringex.h"
#include "Defines.h"
#include "Common.h"
#include "Object.h"
#include "String.h"
#include "Logger.h"
#include "Socket.h"
#ifndef SINGLE_THREADED_MODEL
#include "Thread.h"
#endif
#include "Timer.h"
#include "NetUtil.h"
#include "Global.h"
#include "StreamBuffer.h"
#include "MultiplexSocket.h"
#include "MultiplexSslSocket.h"
//#include <limits.h>
/* common define */
typedef int bool_t;
//#define errlog printf
#if defined(_WIN32) /* Windows specific #includes and #defines */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400 /* To make it link in VS2005 */
#endif
//#include <windows.h>
#define SSL_LIB "ssleay32.dll"
#define CRYPTO_LIB "libeay32.dll"
static HANDLE dlopen(const char *dll_name, int flags)
{
return (LoadLibraryA(dll_name));
}
#define dlsym(x,y) GetProcAddress((HINSTANCE) (x), (y))
#define RTLD_LAZY 0
#if _MSC_VER <= 1200
#define __func__ ""
#else
#define __func__ __FUNCTION__
#endif
#else
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/mman.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <pwd.h>
#include <unistd.h>
#include <dirent.h>
#include <dlfcn.h>
#define SSL_LIB "libssl.so"
#define CRYPTO_LIB "libcrypto.so"
typedef int SOCKET;
//#define false 0
//#define true 1
#define closesocket close
#endif
#include "openssl/ssl.h"
#include "openssl/tls1.h"
#include "openssl/err.h"
#ifdef _WIN32
#pragma comment(lib, "libeay32.lib")
#pragma comment(lib, "ssleay32.lib")
#endif
HSyncObject * g_arrSyncObject;
void ssl_locking_callback(int mode, int n, const char *file, int line)
{
if (mode & CRYPTO_LOCK)
g_arrSyncObject[n].Lock();
else
g_arrSyncObject[n].Unlock();
}
/* This is a context that we pass to callbacks */
typedef struct tlsextctx_st {
BIO *biodebug;
int ack;
} tlsextctx;
static int ssl_servername_cb(SSL *s, int *ad, void *arg)
{
tlsextctx *p = (tlsextctx *) arg;
const char *hn = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
if (SSL_get_servername_type(s) != -1)
p->ack = !SSL_session_reused(s) && hn != NULL;
//else
// BIO_printf(bio_err, "Can't use SSL_get_servername\n");
return SSL_TLSEXT_ERR_OK;
}
void ssl_init()
{
int nLockCount = CRYPTO_num_locks();
g_arrSyncObject = new HSyncObject[nLockCount];
CRYPTO_set_locking_callback((void (*)(int, int, const char *, int))ssl_locking_callback);
/* Initialize SSL crap */
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
}
SSL_CTX * ssl_client_init(const char * pszHostName) //...
{
if (pszHostName[0])
{
//if (strcmp(GetDomainNamePtr(pszHostName), "igi-global.com") == 0) // www.igi-global.com
// return SSL_CTX_new(TLSv1_1_client_method());
if (strcmp(GetDomainNamePtr(pszHostName), "wipson.com") == 0 || // www.wipson.com
strcmp(GetDomainNamePtr(pszHostName), "ibfd.org") == 0 || // www.ibfd.org
strcmp(GetDomainNamePtr(pszHostName), "igi-global.com") == 0 || // www.igi-global.com
strcmp(GetDomainNamePtr(pszHostName), "wisdomain.com") == 0 || // www.igi-global.com
strcmp(GetDomainNamePtr(pszHostName), "tobaccojournal.com") == 0 || // www.tobaccojournal.com
strcmp(GetDomainNamePtr(pszHostName), "cabdirect.org") == 0 || // www.tobaccojournal.com
strcmp(GetDomainNamePtr(pszHostName), "ebsco.com") == 0)// || // atoz.ebsco.com
//strcmp(GetDomainNamePtr(pszHostName), "refworks.com") == 0) // www.refworks.com
return SSL_CTX_new(TLSv1_client_method());
else if (strcmp(GetDomainNamePtr(pszHostName), "dbpia.co.kr") == 0)
return SSL_CTX_new(SSLv23_client_method());
//else if (strcmp(pszHostName, "saemobilus.sae.org") == 0 ||
// strcmp(pszHostName, "www.samsungdesign.net") == 0)
// return SSL_CTX_new(TLSv1_2_client_method());
//return SSL_CTX_new(SSLv23_client_method()); // www.samsungdesign.net, hb8xw4yu6z.search.serialssolutions.com fail
//return SSL_CTX_new(TLSv1_client_method()); // saemobilus.sae.org fail
}
return SSL_CTX_new(TLSv1_2_client_method());
}
int verify_callback(int ok, X509_STORE_CTX *store)
{
char data[256];
/* if (ok) to debug */
if (!ok)
{
X509 *cert = X509_STORE_CTX_get_current_cert(store);
int depth = X509_STORE_CTX_get_error_depth(store);
int err = X509_STORE_CTX_get_error(store);
fprintf(stderr, "-Error with certificate at depth: %i\n", depth);
X509_NAME_oneline(X509_get_issuer_name(cert), data, 256);
fprintf(stderr, " issuer = %s\n", data);
X509_NAME_oneline(X509_get_subject_name(cert), data, 256);
fprintf(stderr, " subject = %s\n", data);
fprintf(stderr, " err %i:%s\n", err, X509_verify_cert_error_string(err) );
}
return ok;
}
SSL_CTX * ssl_server_init(const char * pszCertPath, const char * pszKeyPath, const char * pszCaPath)
{
SSL_CTX * ssl_ctx = SSL_CTX_new(SSLv23_server_method());
if (ssl_ctx == NULL)
{
HLOGF(HLOG_ERROR, "[ERROR], SslSock, Failed to SSL_CTX_new in ssl_server_init\n");
return NULL;
}
//if (ctx->ssl_password_callback != NULL)
// SSL_CTX_set_default_passwd_cb(CTX, ctx->ssl_password_callback);
if (SSL_CTX_use_certificate_file(ssl_ctx, pszCertPath, SSL_FILETYPE_PEM) == 0)
{
HLOGF(HLOG_ERROR, "[ERROR], SslSock, Failed to SSL_CTX_use_certificate_file, %s\n", pszCertPath);
return NULL;
}
if (SSL_CTX_use_PrivateKey_file(ssl_ctx, pszKeyPath, SSL_FILETYPE_PEM) == 0)
{
HLOGF(HLOG_ERROR, "[ERROR], SslSock, Failed to SSL_CTX_use_certificate_file, %s\n", pszKeyPath);
return NULL;
}
#if 0
sprintf(szPemFile, "%slibproxy_chain.pem", pszAppDir);
if (SSL_CTX_use_certificate_chain_file(ssl_ctx, szPemFile) == 0)
{
HLOGF(2, "openssl\t[ERROR] Failed to SSL_CTX_use_certificate_chain_file, %s\n", szPemFile);
return NULL;
}
#endif
/* Load the CAs we trust*/
if (SSL_CTX_load_verify_locations(ssl_ctx, pszCaPath, 0) == 0)
{
HLOGF(HLOG_ERROR, "[ERROR], SslSock, Failed to SSL_CTX_load_verify_locations, %s\n", pszCaPath);
return NULL;
}
//SSL_CTX_set_verify_depth(ssl_ctx, 1);
//SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, verify_callback);
return ssl_ctx;
}
void ssl_ctx_destroy(SSL_CTX * ssl_ctx)
{
if (!ssl_ctx)
return;
SSL_CTX_free(ssl_ctx);
}
int ssl_send(SSL * ssl, char * buf, int len, int flags)
{
if (!ssl)
return -1;
return SSL_write(ssl, buf, len);
}
int ssl_recv(SSL * ssl, char * buf, int len, int flags)
{
if (!ssl)
return -1;
return SSL_read(ssl, buf, len);
}
//////////////////////////////////////////////////////////////////////////////
SSL_CTX * HMultiplexSslSocket::m_sslCtxServer = NULL;
void HMultiplexSslSocket::SslInit(const char * pszCertPath, const char * pszKeyPath, const char * pszCaPath)
{
static bool bIsSslInit = false;
if (bIsSslInit == false)
{
bIsSslInit = true;
ssl_init();
HMultiplexSslSocket::m_sslCtxServer = ssl_server_init(pszCertPath, pszKeyPath, pszCaPath);
}
}
void HMultiplexSslSocket::SslDestroy()
{
ssl_ctx_destroy(m_sslCtxServer);
m_sslCtxServer = NULL;
ERR_remove_state(0);
//ENGINE_cleanup();
//CONF_modules_unload(1);
ERR_free_strings();
EVP_cleanup();
sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
CRYPTO_cleanup_all_ex_data();
delete [] g_arrSyncObject;
}
///////////////////////////////////////
HMultiplexSslSocket::HMultiplexSslSocket()
{
m_ssl_ctx = NULL;
m_ssl = NULL;
m_rbio = NULL;
m_pStreamBufferForDecrypt = new HStreamBuffer(65536);
m_wbio = NULL;
m_pStreamBufferForSend = new HStreamBuffer(SSL3_RT_MAX_PACKET_SIZE);
m_pBufferForRecv = (char *)malloc(g_nSocketReceiveBlockSize);
m_szDstServerName[0] = '\0';
m_bIsSslConnecting = false;
m_bEncryptRetry = false;
}
HMultiplexSslSocket::HMultiplexSslSocket(SOCKET sock, struct sockaddr_in * psaiRemote, HMpsDispatcher * pDispatcher)
: HMultiplexTcpSocket(sock, psaiRemote, pDispatcher)
{
m_ssl_ctx = NULL;
m_ssl = NULL;
m_rbio = NULL;
m_pStreamBufferForDecrypt = new HStreamBuffer(65536);
m_wbio = NULL;
m_pStreamBufferForSend = new HStreamBuffer(SSL3_RT_MAX_PACKET_SIZE);
m_pBufferForRecv = (char *)malloc(g_nSocketReceiveBlockSize);
m_szDstServerName[0] = '\0';
m_bIsSslConnecting = false;
m_bEncryptRetry = false;
}
HMultiplexSslSocket::~HMultiplexSslSocket()
{
if (m_ssl)
SSL_free(m_ssl);
if (m_ssl_ctx != m_sslCtxServer)
ssl_ctx_destroy(m_ssl_ctx);
delete m_pStreamBufferForDecrypt;
delete m_pStreamBufferForSend;
free(m_pBufferForRecv);
}
bool HMultiplexSslSocket::Close()
{
if (m_nState == MPS_DISABLE ||
(m_nState == MPS_DELETE && m_fdSocket == INVALID_SOCKET))
//if (m_fdSocket == INVALID_SOCKET)
return false;
OnClose();
if (m_nState != MPS_LISTENING)
shutdown(m_fdSocket, SD_BOTH);
if (m_nState != MPS_DELETE)
m_nState = MPS_DISABLE;
SSL_free(m_ssl); // free the SSL object and its BIO's
m_ssl = NULL;
closesocket(m_fdSocket);
HLOGF(HLOG_INFO5, "INFO, SslSock, socket closed, socket = %d\n", m_fdSocket);
m_fdSocket = INVALID_SOCKET;
return true;
}
int HMultiplexSslSocket::Send(const char * pData, int nSize)
{
if ((size_t)nSize > m_pStreamBufferForSend->RemainSize())
{
SendBufferedData();
m_bEncryptRetry = true;
m_bSendRetry = true;
return 0;
}
if (!SSL_is_init_finished(m_ssl))
{
m_bEncryptRetry = true;
m_bSendRetry = true;
return 0;
}
const char * pDataOffset = pData;
int nRemainSize = nSize;
int nResult;
int nSslError;
while (nRemainSize > 0)
{
nResult = SSL_write(m_ssl, pDataOffset, nRemainSize);
nSslError = SSL_get_error(m_ssl, nResult);
if (nResult > 0)
{
pDataOffset += nResult;
nRemainSize -= nResult;
do
{
nResult = BIO_read(m_wbio, m_pStreamBufferForSend->Tail(), m_pStreamBufferForSend->RemainSize());
if (nResult > 0)
m_pStreamBufferForSend->MoveTail(nResult);
else if (!BIO_should_retry(m_wbio))
{
HLOGF(HLOG_ERROR, "SSL_TRACE, 1, socket = %d\n", m_fdSocket);
m_nState = MPS_CLOSING;
return SOCKET_ERROR;
}
} while (nResult > 0);
}
if (nSslError != SSL_ERROR_NONE && nSslError != SSL_ERROR_WANT_WRITE && nSslError != SSL_ERROR_WANT_READ)
{
HLOGF(HLOG_WARNING, "[WARN], SslSock, socket = %d, error = %d, %d\n", m_fdSocket, nSslError, nResult);
m_nState = MPS_CLOSING;
return SOCKET_ERROR;
}
if (nResult == 0)
break;
}
m_bEncryptRetry = false;
if (m_pStreamBufferForSend->StoredSize() > 0)
SendBufferedData();
if (nRemainSize > 0)
{
m_bEncryptRetry = true;
m_bSendRetry = true;
return nSize - nRemainSize;
}
return nSize;
}
int HMultiplexSslSocket::SendBufferedData()
{
if (m_pStreamBufferForSend->StoredSize() == 0)
return SOCKET_ERROR;
int nSentSize = HMultiplexTcpSocket::Send(m_pStreamBufferForSend->Head(), m_pStreamBufferForSend->StoredSize());
if (nSentSize <= 0)
return nSentSize;
m_pStreamBufferForSend->Pop(nSentSize);
return nSentSize;
}
int HMultiplexSslSocket::Receive()
{
int nReceivedSize = HMultiplexTcpSocket::Receive(m_pBufferForRecv, g_nSocketReceiveBlockSize);
if (nReceivedSize <= 0)
return nReceivedSize;
char * pBufferOffset = m_pBufferForRecv;
int nResult;
while (nReceivedSize > 0)
{
nResult = BIO_write(m_rbio, pBufferOffset, nReceivedSize);
if (nResult <= 0)
{
HLOGF(HLOG_INFO4, "INFO, SslSock, assume bio write failure is unrecoverable, socket = %d\n", m_fdSocket);
m_nState = MPS_CLOSING;
return SOCKET_ERROR;
}
pBufferOffset += nResult;
nReceivedSize -= nResult;
if (!SSL_is_init_finished(m_ssl))
{
if (ProcHandShake() == false)
{
if (m_bIsSslConnecting)
OnConnectChild(false);
return -1;
}
if (!SSL_is_init_finished(m_ssl))
return 0;
}
do {
nResult = SSL_read(m_ssl, m_pStreamBufferForDecrypt->Tail(), m_pStreamBufferForDecrypt->RemainSize());
if (nResult > 0)
m_pStreamBufferForDecrypt->MoveTail(nResult);
} while (nResult > 0);
int nSslError = SSL_get_error(m_ssl, nResult);
if (nSslError == SSL_ERROR_WANT_WRITE || nSslError == SSL_ERROR_WANT_READ)
{
do
{
nResult = BIO_read(m_wbio, m_pStreamBufferForSend->Tail(), m_pStreamBufferForSend->RemainSize());
if (nResult > 0)
m_pStreamBufferForSend->MoveTail(nResult);
else if (!BIO_should_retry(m_wbio))
{
HLOGF(HLOG_WARNING, "TRACE, SslSock, 1. Did SSL request to write bytes? This can happen if peer has requested SSL * renegotiation, socket = %d, %d, %d\n", m_fdSocket, nSslError, nResult);
m_nState = MPS_CLOSING;
return SOCKET_ERROR;
}
} while (nResult > 0);
}
else if (nSslError == SSL_ERROR_ZERO_RETURN || nSslError == SSL_ERROR_SYSCALL)
{
HLOGF(HLOG_WARNING, "TRACE, SslSock, 2. Did SSL request to write bytes? This can happen if peer has requested SSL * renegotiation, socket = %d, %d, %d\n", m_fdSocket, nSslError, nResult);
//...???
}
}
if (m_pStreamBufferForSend->StoredSize() > 0)
SendBufferedData();
if (m_bIsSslConnecting)
{
m_bIsSslConnecting = false;
OnConnectChild(true);
return 0;
}
return m_pStreamBufferForDecrypt->StoredSize();
}
bool HMultiplexSslSocket::SetRemoteAddressHostByName(const char * pszHostName, u_short nPort)
{
strcpy(m_szDstServerName, pszHostName);
return HMultiplexTcpSocket::SetRemoteAddressHostByName(pszHostName, nPort);
}
bool HMultiplexSslSocket::IsRemain()
{
if (m_ssl == NULL)
return false;
return SSL_pending(m_ssl) > 0;
}
void HMultiplexSslSocket::OnConnect(bool bIsSuccess)
{
if (bIsSuccess)
{
m_ssl_ctx = ssl_client_init(m_szDstServerName);
//tlsextcbp.biodebug = bio_err;
//SSL_CTX_set_tlsext_servername_callback(m_ssl_ctx, ssl_servername_cb);
//SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
if ((m_ssl = SSL_new(m_ssl_ctx)) == NULL)
{
HLOGF(HLOG_ERROR, "[ERROR], SslSock, Faield to SSL_new 1, socket = %d\n", m_fdSocket);
OnConnectChild(false);
return;
}
if (m_szDstServerName[0] && !SSL_set_tlsext_host_name(m_ssl, m_szDstServerName))
{
HLOGF(HLOG_ERROR, "[ERROR], SslSock, Unable to set TLS servername extension, socket = %d\n", m_fdSocket);
OnConnectChild(false);
return;
}
SSL_set_connect_state(m_ssl);
m_rbio = BIO_new(BIO_s_mem());
m_wbio = BIO_new(BIO_s_mem());
SSL_set_bio(m_ssl, m_rbio, m_wbio);
m_bIsSslConnecting = true;
ProcHandShake();
}
else
{
OnConnectChild(false);
}
}
void HMultiplexSslSocket::OnAccepted()
{
if ((m_ssl = SSL_new(m_sslCtxServer)) == NULL)
{
HLOGF(HLOG_ERROR, "[ERROR], SslSock, Faield to SSL_new 2, socket = %d\n", m_fdSocket);
return;
}
m_ssl_ctx = m_sslCtxServer;
SSL_set_accept_state(m_ssl);
m_rbio = BIO_new(BIO_s_mem());
m_wbio = BIO_new(BIO_s_mem());
SSL_set_bio(m_ssl, m_rbio, m_wbio);
//m_bIsSslConnecting = true;
}
bool HMultiplexSslSocket::ProcHandShake()
{
int nSslResult = SSL_do_handshake(m_ssl);
int nSslError = SSL_get_error(m_ssl, nSslResult);
if (nSslError == SSL_ERROR_WANT_WRITE || nSslError == SSL_ERROR_WANT_READ)
{
do
{
nSslResult = BIO_read(m_wbio, m_pStreamBufferForSend->Tail(), m_pStreamBufferForSend->RemainSize());
if (nSslResult > 0)
m_pStreamBufferForSend->MoveTail(nSslResult);
else if (!BIO_should_retry(m_wbio))
{
m_pStreamBufferForSend->Reset();
HLOGF(HLOG_WARNING, "[WARN], SslSock, Failed to HandShake 1, socket = %d, error = %d\n", m_fdSocket, nSslError);
return false;
}
} while (nSslResult > 0);
if (m_pStreamBufferForSend->StoredSize() > 0)
SendBufferedData();
}
else if (nSslError == SSL_ERROR_ZERO_RETURN || nSslError == SSL_ERROR_SYSCALL)
{
HLOGF(HLOG_WARNING, "[WARN], SslSock, Failed to HandShake 2, socket = %d, error = %d\n", m_fdSocket, nSslError);
return false;
}
return true;
}
+72
View File
@@ -0,0 +1,72 @@
#ifndef MULTIPLEX_SSL_SOCKET__H_
#define MULTIPLEX_SSL_SOCKET__H_
#ifdef _WIN32
#pragma once
#endif
typedef struct ssl_ctx_st SSL_CTX;
typedef struct ssl_st SSL;
typedef struct bio_st BIO;
class HMultiplexSslSocket : public HMultiplexTcpSocket
{
public:
static SSL_CTX * m_sslCtxClient;
static SSL_CTX * m_sslCtxServer;
static void SslInit(const char * pszCertPath, const char * pszKeyPath, const char * pszCaPath);
static void SslDestroy();
//
HMultiplexSslSocket();
HMultiplexSslSocket(SOCKET sock, struct sockaddr_in * psaiRemote, HMpsDispatcher * pDispatcher);
~HMultiplexSslSocket();
bool Close();
int Send(const char * pData, int nSize);
int SendBufferedData();
//int Receive(char * pBuffer, int nSize);
int Receive();
bool SetRemoteAddressHostByName(const char * pszHostName, u_short nPort);
bool IsRemain();
inline bool IsEncryptRetry() { return m_bEncryptRetry; }
virtual bool IsSslSocket() { return true; }
protected:
enum {
TIMER_CHANNEL_CLOSE = 100,
TIMER_CHECK_RECEIVE = 101
};
void OnConnect(bool bIsSuccess);
virtual void OnConnectChild(bool bIsSuccess) {}
void OnAccepted();
//virtual void OnAcceptedChild() {}
bool ProcHandShake();
protected:
SSL_CTX * m_ssl_ctx;
SSL * m_ssl;
BIO * m_rbio;
HStreamBuffer * m_pStreamBufferForDecrypt;
BIO * m_wbio;
HStreamBuffer * m_pStreamBufferForSend;
char * m_pBufferForRecv;
char m_szDstServerName[512];
bool m_bIsSslConnecting; //...
bool m_bEncryptRetry;
};
#endif // MULTIPLEX_SSL_SOCKET__H_
+511
View File
@@ -0,0 +1,511 @@
#ifndef MULTIPLEX_TRANSPORT__H_
#define MULTIPLEX_TRANSPORT__H_
#ifdef _WIN32
#pragma once
#endif
class HMultiplexTransportTcpSocket;
class HMultiplexTransport : public HTransport
{
public:
HMultiplexTransport() {}
~HMultiplexTransport() {}
inline void SetMpSocket(HMultiplexTcpSocket * pSocket) { m_pMulplexTransportSocket = pSocket; }
inline HMultiplexTcpSocket * GetMpSocket() { return m_pMulplexTransportSocket; }
inline bool GetTransportInfo(const char * pName, void * pValue);
inline void Terminate();
inline int Send(const char * pData, int nSize);
protected:
HMultiplexTcpSocket * m_pMulplexTransportSocket;
friend class HMultiplexTransportTcpSocket;
friend class HMultiplexTransportSslSocket;
};
///////////////////////////////////////
class HMultiplexTransportTcpSocket : public HMultiplexTcpSocket
{
public:
HMultiplexTransportTcpSocket()
{
m_bAutoDelete = false;
m_nReconnectTime = 0;
m_pReceiveBuffer = (char *)malloc(g_nSocketReceiveBlockSize + 1);
m_pTransport = NULL;
}
HMultiplexTransportTcpSocket(SOCKET sock, struct sockaddr_in * psaiRemote, HMpsDispatcher * pDispatcher)
: HMultiplexTcpSocket(sock, psaiRemote, pDispatcher)
{
m_bAutoDelete = false;
m_nReconnectTime = 0;
m_pReceiveBuffer = (char *)malloc(g_nSocketReceiveBlockSize + 1);
m_pTransport = NULL;
}
~HMultiplexTransportTcpSocket()
{
if (m_pTransport)
delete m_pTransport;
free(m_pReceiveBuffer);
}
inline void AttachTransport(HMultiplexTransport * pTransport) { m_pTransport = pTransport; }
inline HMultiplexTransport * GetTransport() { return m_pTransport; }
inline void SetAutoDelete(bool bAutoDelete) { m_bAutoDelete = bAutoDelete; }
inline void SetAutoReconnect(DWORD nTime) { m_nReconnectTime = nTime; }
protected:
inline void OnClose()
{
if (m_bAutoDelete)
SetState(MPS_DELETE); // auto delete
else if (m_nReconnectTime > 0)
SetTimer(2181006, m_nReconnectTime);
m_pTransport->OnReceivedStatus(HTransport::T_END_TRANSPORT);
}
inline void OnConnect(bool bIsSuccess)
{
if (bIsSuccess == false)
{
m_pTransport->OnReceivedStatus(HTransport::T_FAILED_BEGIN);
return;
}
m_pTransport->OnReceivedStatus(HTransport::T_BEGIN_TRANSPORT);
}
inline void OnReceive()
{
if (m_pTransport == NULL)
return;
if (m_pTransport->OnPrepareReceive() == false)
return;
int nReceivedSize = Receive(m_pReceiveBuffer, g_nSocketReceiveBlockSize);
if (nReceivedSize <= 0)
return;
if (m_pTransport->OnReceived(m_pReceiveBuffer, nReceivedSize) < 0)
FinishTcp();
}
inline int OnSendRetry()
{
return m_pTransport->OnSendRetry();
}
inline void OnAccepted()
{
m_pTransport->OnReceivedStatus(HTransport::T_BEGIN_TRANSPORT);
}
ON_TIMER(HMultiplexTransportTcpSocket, OnTimer) // add void OnTimer(DWORD nTimerID) {}
protected:
char * m_pReceiveBuffer;
bool m_bAutoDelete;
DWORD m_nReconnectTime;
HMultiplexTransport * m_pTransport;
};
inline void HMultiplexTransportTcpSocket::OnTimer(unsigned int nTimerId)
{
KillTimer(2181006);
Create();
Connect(0);
}
///////////////////////////////////////
class HMultiplexTransportSslSocket : public HMultiplexSslSocket
{
public:
HMultiplexTransportSslSocket()
{
m_bAutoDelete = false;
m_nReconnectTime = 0;
m_pTransport = NULL;
}
HMultiplexTransportSslSocket(SOCKET sock, struct sockaddr_in * psaiRemote, HMpsDispatcher * pDispatcher)
: HMultiplexSslSocket(sock, psaiRemote, pDispatcher)
{
m_bAutoDelete = false;
m_nReconnectTime = 0;
m_pTransport = NULL;
}
~HMultiplexTransportSslSocket()
{
if (m_pTransport)
delete m_pTransport;
}
inline void AttachTransport(HMultiplexTransport * pTransport) { m_pTransport = pTransport; }
inline HMultiplexTransport * GetTransport() { return m_pTransport; }
inline void SetAutoDelete(bool bAutoDelete) { m_bAutoDelete = bAutoDelete; }
inline void SetAutoReconnect(DWORD nTime) { m_nReconnectTime = nTime; }
inline void OnAccepted()
{
HMultiplexSslSocket::OnAccepted();
m_pTransport->OnReceivedStatus(HTransport::T_BEGIN_TRANSPORT);
}
protected:
inline void OnClose()
{
if (m_bAutoDelete)
SetState(MPS_DELETE); // auto delete
else if (m_nReconnectTime > 0)
SetTimer(2181006, m_nReconnectTime);
m_pTransport->OnReceivedStatus(HTransport::T_END_TRANSPORT);
}
inline void OnReceive()
{
if (m_pTransport == NULL)
return;
if (m_pTransport->OnPrepareReceive() == false)
return;
Receive();
while (m_pStreamBufferForDecrypt->StoredSize() > 0)
{
//HLOGF(HLOG_WARNING, "SSL_TRACE, recv size = %d\n", m_pStreamBufferForDecrypt->StoredSize());
//HLOGD(HLOG_WARNING, m_pStreamBufferForDecrypt->Head(), 40, true);
if (m_pStreamBufferForDecrypt->StoredSize() > (size_t)g_nSocketReceiveBlockSize)
{
if (m_pTransport->OnReceived(m_pStreamBufferForDecrypt->Head(), g_nSocketReceiveBlockSize) < 0)
{
FinishTcp();
return;
}
m_pStreamBufferForDecrypt->Pop(g_nSocketReceiveBlockSize);
}
else
{
if (m_pTransport->OnReceived(m_pStreamBufferForDecrypt->Head(), m_pStreamBufferForDecrypt->StoredSize()) < 0)
{
FinishTcp();
return;
}
m_pStreamBufferForDecrypt->Reset();
}
}
}
inline int OnSendRetry()
{
if (m_bEncryptRetry)
return m_pTransport->OnSendRetry();
return SendBufferedData();
}
inline void OnConnectChild(bool bIsSuccess)
{
if (bIsSuccess == false)
{
SetState(MPS_CLOSING);
m_pTransport->OnReceivedStatus(HTransport::T_FAILED_BEGIN);
return;
}
m_pTransport->OnReceivedStatus(HTransport::T_BEGIN_TRANSPORT);
}
ON_TIMER(HMultiplexTransportSslSocket, OnTimer) // add void OnTimer(DWORD nTimerID) {}
protected:
bool m_bAutoDelete;
DWORD m_nReconnectTime;
HMultiplexTransport * m_pTransport;
};
inline void HMultiplexTransportSslSocket::OnTimer(unsigned int nTimerId)
{
KillTimer(2181006);
Create();
Connect(0);
}
/////////////////////////////////////////////////
inline bool HMultiplexTransport::GetTransportInfo(const char * pName, void * pValue)
{
if (strcmp(pName, "peer_ip") == 0)
{
int nResult = m_pMulplexTransportSocket->GetPeerAddress((char *)pValue, NULL);
if (nResult)
{
HLOGF(HLOG_WARNING, "[WARN], MplxTrnsp, Failed to GetPeerAddress 1, error = %d\n", nResult);
return false;
}
return true;
}
else if (strcmp(pName, "peer_port") == 0)
{
int nResult = m_pMulplexTransportSocket->GetPeerAddress(NULL, (u_short *)pValue);
if (nResult)
{
HLOGF(HLOG_WARNING, "[WARN], MplxTrnsp, Failed to GetPeerAddress 2, error = %d\n", nResult);
return false;
}
return true;
}
else if (strcmp(pName, "peer_address") == 0)
{
char szIp[32];
u_short nPort = 0;
int nResult = m_pMulplexTransportSocket->GetPeerAddress(szIp, &nPort);
if (nResult)
{
HLOGF(HLOG_WARNING, "[WARN], MplxTrnsp, Failed to GetPeerAddress 3, error = %d\n", nResult);
return false;
}
sprintf((char *)pValue, "%s:%d", szIp, nPort);
return true;
}
else if (strcmp(pName, "is_ssl_socket") == 0)
{
*((bool *)pValue) = m_pMulplexTransportSocket->IsSslSocket();
return true;
}
return false;
}
inline void HMultiplexTransport::Terminate()
{
m_pMulplexTransportSocket->FinishTcp();
}
inline int HMultiplexTransport::Send(const char * pData, int nSize)
{
return m_pMulplexTransportSocket->Send(pData, nSize);
}
/////////////////////////////////////////////////
template<class _THandler, class _TSocket>
class HMulplexTransportListenSocket : public HMultiplexListenSocket
{
public:
HMulplexTransportListenSocket() {}
~HMulplexTransportListenSocket() {}
protected:
HMultiplexTcpSocket * OnAccept(SOCKET sock, struct sockaddr_in * psaiRemote)
{
HMultiplexTransport * pMultiplexTransport = new HMultiplexTransport;
pMultiplexTransport->AttachHandler(new _THandler);
_TSocket * pSocket = new _TSocket(sock, psaiRemote, GetDispatcher());
pMultiplexTransport->SetMpSocket(pSocket);
pSocket->AttachTransport(pMultiplexTransport);
pSocket->SetAutoDelete(true);
return pSocket;
}
};
/////////////////////////////////////////////////
class HMulplexSocketConnector
{
public:
HMulplexSocketConnector() { m_pVecOutboundIp = NULL; m_nOutboundIpIndex = -1; }
virtual ~HMulplexSocketConnector() {}
inline void SetOutboundIpList(HStrVector * pVector) { m_pVecOutboundIp = pVector; }
inline void SetOutboundIpIndex(int nIndex) { m_nOutboundIpIndex = nIndex; }
virtual bool Connect(const char * pszAddress, u_short nPort, unsigned nTimeout, HMpsDispatcher * pDispatcher) { return false; }
protected:
HStrVector * m_pVecOutboundIp;
int m_nOutboundIpIndex;
};
template<class _THandler, class _TSocket>
class HMulplexTransportConnector : public HMulplexSocketConnector
{
public:
HMulplexTransportConnector() { m_pHandler = NULL; }
~HMulplexTransportConnector() {}
inline _THandler * GetHandler() { return m_pHandler; }
inline bool Connect(const char * pszAddress, u_short nPort, unsigned nTimeout, HMpsDispatcher * pDispatcher, unsigned long nAutoReconnectTime = 0)
{
HMultiplexTransport * pMultiplexTransport = new HMultiplexTransport;
m_pHandler = new _THandler;
pMultiplexTransport->AttachHandler(m_pHandler);
_TSocket * pSocket = new _TSocket;
if (pSocket->Create() == false)
{
delete pSocket;
delete pMultiplexTransport;
return false;
}
pMultiplexTransport->SetMpSocket(pSocket);
pSocket->AttachTransport(pMultiplexTransport);
if (nAutoReconnectTime > 0)
pSocket->SetAutoReconnect(nAutoReconnectTime);
else
pSocket->SetAutoDelete(true);
HLOGF(HLOG_INFO3, "INFO, MpConnector, Connect, inst = 0x%x, %s:%d\n", this, pszAddress, nPort);
if (IsIpString(pszAddress))
pSocket->SetRemoteAddress(pszAddress, nPort);
else
pSocket->SetRemoteAddressHostByName(pszAddress, nPort);
if (m_pVecOutboundIp && m_pVecOutboundIp->size() > 0)
{
// outbound load balance
static int nIpCount = m_pVecOutboundIp->size();
static int nIpIndex = 0;
static u_short nPort = 20000;
if (nIpCount <= 0)
return false;
if (++nIpIndex >= nIpCount)
nIpIndex = 0;
for (int i = 20000; i < 60000; i++)
{
if (++nPort >= 60000)
nPort = 20000;
if (m_nOutboundIpIndex != -1)
{
if (pSocket->Bind((*m_pVecOutboundIp)[m_nOutboundIpIndex], nPort))
break;
}
else
{
if (pSocket->Bind((*m_pVecOutboundIp)[nIpIndex], nPort))
break;
}
Sleep(50);
}
}
if (pSocket->Connect(nTimeout) == false)
{
delete pSocket;
return false;
}
pDispatcher->Attach(pSocket);
return true;
}
private:
_THandler * m_pHandler;
};
/////////////////////////////////////////////////
template<class _THandler, class _TSocket>
class HMulplexTransportListenThread : public HMultiplexListenThread<HMultiplexTcpSocket>
{
public:
HMulplexTransportListenThread() {}
~HMulplexTransportListenThread() {}
protected:
HMultiplexTcpSocket * OnAccept(SOCKET sock, struct sockaddr_in * psaiRemote)
{
HMultiplexTransport * pMultiplexTransport = new HMultiplexTransport;
pMultiplexTransport->AttachHandler(new _THandler);
#if 1
HMpsDispatcher * pDispatcher = m_pListDispatcher->GetLazyDispatcher();
_TSocket * pSocket = new _TSocket(sock, psaiRemote, pDispatcher);
pMultiplexTransport->SetMpSocket(pSocket);
pSocket->AttachTransport(pMultiplexTransport);
pSocket->SetAutoDelete(true);
pDispatcher->AttachWithLock(pSocket);
return pSocket;
#else
HMpsDispatcherList::iterator iter;
int i = 0;
for (iter = m_pListDispatcher->begin(); iter != m_pListDispatcher->end(); iter++)
{
if ((*iter)->IsProcessing() == false)
i++;
}
//HLOGF(HLOG_WARNING, "[TRACE], MplxTrnspLstnThr_0x%x, lazy dispatcher count = %d\n", this, i);
for (;;)
{
for (iter = m_pListDispatcher->begin(); iter != m_pListDispatcher->end(); iter++)
{
if ((*iter)->IsProcessing() == false)
{
_TSocket * pSocket = new _TSocket(sock, psaiRemote, *iter);
pMultiplexTransport->SetMpSocket(pSocket);
pSocket->AttachTransport(pMultiplexTransport);
pSocket->SetAutoDelete(true);
(*iter)->AttachWithLock(pSocket);
return pSocket;
}
}
Sleep(10);
}
#endif
}
};
#if 1
typedef std::list<HMultiplexListenThread<HMultiplexTcpSocket> *> HMultiplexListenThreadList;
#else
class HMultiplexListenThreadList : public std::list<HMultiplexListenThread<HMultiplexTcpSocket> *>
{
public:
HMultiplexListenThreadList() {}
~HMultiplexListenThreadList() {}
};
#endif
#endif // MULTIPLEX_TRANSPORT__H_
+592
View File
@@ -0,0 +1,592 @@
#include "stringex.h"
#include "Defines.h"
#include "Common.h"
#include "Object.h"
#include "String.h"
#include "DataStruct.h"
#include "NetUtil.h"
#ifdef _WIN32
#include <winsock2.h>
#else
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
static struct {
const char * pszSecondLevelDomain;
int nBaseDot;
} SecondLevelDomain[] = {
{ ".com.br", 2 },
{ ".com.cn", 2 },
{ ".com.hk", 2 },
{ ".com.pl", 2 },
{ ".co.kr", 2 },
{ ".go.kr", 2 },
{ ".ac.kr", 2 },
{ ".ac.uk", 2 },
{ ".or.kr", 2 },
{ ".re.kr", 2 },
{ ".co.uk", 2 },
{ ".ac.at", 2 },
{ ".ac.id", 2 },
{ ".ac.jp", 2 },
{ ".ac.rs", 2 },
{ ".co.jp", 2 },
{ ".go.jp", 2 },
{ ".or.jp", 2 },
{ ".ed.gov", 2 },
{ ".gov.pl", 2 },
{ ".gc.ca", 2 },
{ ".edu.au", 2 },
{ ".edu.tw", 2 },
{ ".gov.tr", 2 },
{ ".gov.uk", 2 },
{ ".org.au", 2 },
{ ".org.in", 2 },
{ ".gda.pl", 2 },
{ ".org.au", 2 },
{ ".org.uk", 2 },
{ ".org.br", 2 },
{ ".org.tw", 2 },
{ ".com.sg", 2 },
{ ".edu.pl", 2 }
};
#define ARRAYCOUNT(array) ((unsigned)(sizeof(array)/sizeof(array[0])))
bool IsIpString(const char * psz)
{
int nCount = 0;
char * pOne = (char *)psz;
while (*pOne)
{
if (*pOne == '.')
nCount++;
else if (*pOne < 48 || *pOne > 57)
return false;
pOne++;
}
if (nCount != 3)
return false;
return true;
}
void ConvertHexStrIP(char * pszDst, unsigned long nS_Addr)
{
if (pszDst == NULL)
return;
#if 0
_snprintf(pszDst, 9, "%X", nS_Addr);
#else
// 4bit number to hex character
#define NUMTOHEXC(N) (((N) < 10) ? ((N) + '0') : ((N) - 10 + 'A'))
unsigned long nNum = nS_Addr;
int nFigure;
for(nFigure = 0; nNum != 0; nFigure++)
nNum = nNum >> 4;
for (int i = 0; i < nFigure; i++)
pszDst[i] = (char)NUMTOHEXC((nS_Addr >> ((nFigure - (i + 1)) * 4)) & 0xF);
pszDst[nFigure] = '\0';
#endif
}
void RestoreDotIP(char * pszDst, const char * pszSrc)
{
if (pszDst == NULL || pszSrc == NULL) return;
struct in_addr sin_addr;
sin_addr.s_addr = strtoul(pszSrc, NULL, 16);
//strcpy(pszDst, inet_ntoa(sin_addr));
strncpy(pszDst, inet_ntoa(sin_addr), 16);
}
bool IsInsideIp(const char * pszIpRange, const char * pszIp)
{
const char * pTild;
const char * pLastDot;
if ((pTild = strchr(pszIpRange, '~')))
{
if ((pLastDot = strrchr(pszIpRange, '.')) && pLastDot + 1 < pTild)
{
size_t nFrontSize = (size_t)(pLastDot - pszIpRange);
if (strncmp(pszIpRange, pszIp, nFrontSize) == 0)
{
char szStartRange[128], szEndRange[128];
StrNCpy(szStartRange, pLastDot + 1, pTild - pLastDot - 1);
strcpy(szEndRange, pTild + 1);
int nDotCount = 0;
const char * pOne = pszIpRange;
while (*pOne)
{
if (*pOne == '.')
nDotCount++;
pOne++;
}
pOne = pszIp;
while (*pOne)
{
if (*pOne == '.')
{
if (--nDotCount <= 0)
{
pOne++;
break;
}
}
pOne++;
}
int nCompare;
if ((pLastDot = strchr(pOne, '.')))
{
char szCompare[128];
StrNCpy(szCompare, pOne, pLastDot - pOne);
nCompare = atoi(szCompare);
}
else
{
nCompare = atoi(pOne);
}
if (nCompare >= atoi(szStartRange) && nCompare <= atoi(szEndRange))
return true;
}
}
}
return false;
}
bool IsDomainName(const char * pszName)
{
if (IsIpString(pszName) == true)
return false;
//if (IsFileLinkString(pszName))
// return false;
int nDotCount = 0;
char * pOne = (char *)pszName;
while (*pOne)
{
if (*pOne == '.')
nDotCount++;
pOne++;
}
if (nDotCount == 1)
return true;
int nBaseDot = 0;
for (unsigned i = 0; i < ARRAYCOUNT(SecondLevelDomain); i++)
{
if (strstr(pszName, SecondLevelDomain[i].pszSecondLevelDomain) != NULL)
{
nBaseDot = SecondLevelDomain[i].nBaseDot;
break;
}
}
if (nDotCount == nBaseDot)
return true;
return false;
}
bool IsHostName(const char * pszName)
{
const char * p = pszName;
for (; *p; p++)
{
if (!isalnum(*p) && *p != '.' && *p != '-' && *p != ':')
return false;
}
return true;
}
void ExtractDomainName(char * pszDest, const char * pszHostName)
{
if (IsIpString(pszHostName))
{
const char * pszTemp = strstr(pszHostName, ":");
if (pszTemp)
{
// ex) 192.168.0.1:8080 -> 192.168.0.1
size_t nFrontLength = pszTemp - pszHostName;
memcpy(pszDest, pszHostName, nFrontLength);
pszDest[nFrontLength] = '\0';
}
else
{
strcpy(pszDest, pszHostName); // ex) 192.168.0.1 -> 192.168.0.1
}
return;
}
int nDotCount = 0;
char * pOne = (char *)pszHostName;
while (*pOne)
{
if (*pOne == '.')
nDotCount++;
pOne++;
}
if (nDotCount <= 1)
{
strcpy(pszDest, pszHostName);
return;
}
int nBaseDot = 1;
for (unsigned i = 0; i < ARRAYCOUNT(SecondLevelDomain); i++)
{
if (strstr(pszHostName, SecondLevelDomain[i].pszSecondLevelDomain) != NULL)
{
nBaseDot = SecondLevelDomain[i].nBaseDot;
break;
}
}
pOne = (char *)pszHostName;
while (*pOne)
{
if (nDotCount == nBaseDot)
{
pszHostName = pOne;
break;
}
if (*pOne == '.')
nDotCount--;
pOne++;
}
#ifdef WITH_PORT
strcpy(pszDest, pszHostName); // ex) www.domain.com:8080 -> domain.com:8080
#else
const char * pOffset = strchr(pszHostName, ':');
if (pOffset)
{
// ex) www.domain.com:8080 -> domain.com
size_t nLength = pOffset - pszHostName;
strncpy(pszDest, pszHostName, nLength);
pszDest[nLength] = '\0';
}
else
{
strcpy(pszDest, pszHostName);
}
#endif
}
const char * GetDomainNamePtr(const char * pszHostName)
{
if (IsIpString(pszHostName))
return pszHostName;
int nDotCount = 0;
char * pOne = (char *)pszHostName;
while (*pOne)
{
if (*pOne == '.')
nDotCount++;
pOne++;
}
if (nDotCount <= 1)
return pszHostName;
int nBaseDot = 1;
for (unsigned i = 0; i < ARRAYCOUNT(SecondLevelDomain); i++)
{
if (strstr(pszHostName, SecondLevelDomain[i].pszSecondLevelDomain) != NULL)
{
nBaseDot = SecondLevelDomain[i].nBaseDot;
break;
}
}
pOne = (char *)pszHostName;
while (*pOne)
{
if (nDotCount == nBaseDot)
{
pszHostName = pOne;
break;
}
if (*pOne == '.')
nDotCount--;
pOne++;
}
return pszHostName;
}
const char * GetRequestUriPtr(const char * pszUrl)
{
int nCount = 0;
if (strnicmp(pszUrl, "http", 4) != 0 && pszUrl[0] != '/' && pszUrl[1] != '/')
nCount = 2;
for (const char * p = pszUrl; *p; p++)
{
if (*p == '/')
{
if (nCount++ == 2)
return p;
}
}
return pszUrl;
}
bool ExtractHostNameFromUrl(HString * pstrHostName, const char * pszUrl)
{
const char * pszRequestUri = GetRequestUriPtr(pszUrl);
if (strnicmp(pszUrl, "http://", 7) == 0)
pszUrl += 7;
else if (strnicmp(pszUrl, "https://", 8) == 0)
pszUrl += 8;
else if (strncmp(pszUrl, "//", 2) == 0)
pszUrl += 2;
if (pszUrl >= pszRequestUri)
return false;
pstrHostName->Assign(pszUrl, pszRequestUri - pszUrl);
return true;
}
const char * GetNextLevelHostName(const char * pszHostName, bool bIncludeDot)
{
const char * p = pszHostName;
while (*p)
{
if (*p == '.')
{
if (bIncludeDot)
return p;
return ++p;
}
p++;
}
return pszHostName;
}
int EncodeURIComponent(char * pszDst, const char * pszSrc)
{
int nLength = 0;
char * pOffset = pszDst;
while (*pszSrc)
{
if ((*pszSrc > 47 && *pszSrc < 57) ||
(*pszSrc > 64 && *pszSrc < 92) ||
(*pszSrc > 96 && *pszSrc < 123) ||
*pszSrc == '-' || *pszSrc == '.' || *pszSrc == '_')
{
*pOffset = *pszSrc;
}
else
{
sprintf(pOffset, "%%%02X", *pszSrc);
pOffset += 2;
nLength += 2;
}
pszSrc++;
pOffset++;
nLength++;
}
pszDst[nLength] = '\0';
return nLength;
}
int DecodeURIComponent(char * pszDst, char * pszSrc)
{
int i, nNum = 0, nLength = 0;
int nTemp = 0;
while (*pszSrc)
{
if (*pszSrc == '%')
{
nNum = 0;
nTemp = 0;
for (i = 0; i < 2; i++)
{
pszSrc++;
if (*(pszSrc) < ':')
{
nNum = *(pszSrc) - 48;
}
else if (*(pszSrc) > '@' && *(pszSrc) < '[')
{
nNum = (*(pszSrc) - 'A') + 10;
}
else
{
nNum = (*(pszSrc) - 'a') + 10;
}
if ((16*(1-i)))
nNum = (nNum*16);
nTemp += nNum;
}
pszDst[nLength] = nTemp;
nLength++;
}
else
{
pszDst[nLength] = *pszSrc;
nLength++;
}
pszSrc++;
}
pszDst[nLength] = '\0';
return nLength;
}
// base64 part
static const std::string strBase64Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static inline bool IsBase64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
int EncodeBase64(std::string * pstrEncoded, const unsigned char * pszSrc, unsigned int nSrcLen)
{
int i = 0, j = 0;
unsigned char bufTemp1[3], bufTemp2[4];
*pstrEncoded = "";
while (nSrcLen--) {
bufTemp1[i++] = *(pszSrc++);
if (i == 3) {
bufTemp2[0] = (bufTemp1[0] & 0xfc) >> 2;
bufTemp2[1] = ((bufTemp1[0] & 0x03) << 4) + ((bufTemp1[1] & 0xf0) >> 4);
bufTemp2[2] = ((bufTemp1[1] & 0x0f) << 2) + ((bufTemp1[2] & 0xc0) >> 6);
bufTemp2[3] = bufTemp1[2] & 0x3f;
for(i = 0; (i <4) ; i++)
*pstrEncoded += strBase64Char[bufTemp2[i]];
i = 0;
}
}
if (i)
{
for(j = i; j < 3; j++)
bufTemp1[j] = '\0';
bufTemp2[0] = (bufTemp1[0] & 0xfc) >> 2;
bufTemp2[1] = ((bufTemp1[0] & 0x03) << 4) + ((bufTemp1[1] & 0xf0) >> 4);
bufTemp2[2] = ((bufTemp1[1] & 0x0f) << 2) + ((bufTemp1[2] & 0xc0) >> 6);
bufTemp2[3] = bufTemp1[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
*pstrEncoded += strBase64Char[bufTemp2[j]];
while((i++ < 3))
*pstrEncoded += '=';
}
return pstrEncoded->length();
}
int DecodeBase64(std::string * pstrDecoded, const unsigned char * pszSrc, unsigned int nSrcLen)
{
int i = 0, j = 0, pos = 0;
unsigned char bufTemp2[4], bufTemp1[3];
*pstrDecoded = "";
while (nSrcLen-- && ( pszSrc[pos] != '=') && IsBase64(pszSrc[pos])) {
bufTemp2[i++] = pszSrc[pos]; pos++;
if (i ==4) {
for (i = 0; i <4; i++)
bufTemp2[i] = strBase64Char.find(bufTemp2[i]);
bufTemp1[0] = (bufTemp2[0] << 2) + ((bufTemp2[1] & 0x30) >> 4);
bufTemp1[1] = ((bufTemp2[1] & 0xf) << 4) + ((bufTemp2[2] & 0x3c) >> 2);
bufTemp1[2] = ((bufTemp2[2] & 0x3) << 6) + bufTemp2[3];
for (i = 0; (i < 3); i++)
*pstrDecoded += bufTemp1[i];
i = 0;
}
}
if (i) {
for (j = i; j <4; j++)
bufTemp2[j] = 0;
for (j = 0; j <4; j++)
bufTemp2[j] = strBase64Char.find(bufTemp2[j]);
bufTemp1[0] = (bufTemp2[0] << 2) + ((bufTemp2[1] & 0x30) >> 4);
bufTemp1[1] = ((bufTemp2[1] & 0xf) << 4) + ((bufTemp2[2] & 0x3c) >> 2);
bufTemp1[2] = ((bufTemp2[2] & 0x3) << 6) + bufTemp2[3];
for (j = 0; (j < i - 1); j++) *pstrDecoded += bufTemp1[j];
}
return pstrDecoded->length();
}
void DecodeUriBase64(HString & strDst, const HString & strSrc)
{
if (strSrc.GetLength() <= 0)
return;
std::string strTemp;
DecodeBase64(&strTemp, (const unsigned char *)strSrc.psz(), strSrc.GetLength());
HDynamicArray<char> dszUriDecode(strTemp.length() * 2);
DecodeURIComponent(dszUriDecode.m_p, (char *)strTemp.c_str());
strDst = dszUriDecode.m_p;
}
void DecodeUriBase64(HString & strSelf)
{
if (strSelf.GetLength() <= 0)
return;
std::string strTemp;
DecodeBase64(&strTemp, (const unsigned char *)strSelf.psz(), strSelf.GetLength());
HDynamicArray<char> dszUriDecode(strTemp.length() * 2);
DecodeURIComponent(dszUriDecode.m_p, (char *)strTemp.c_str());
strSelf = dszUriDecode.m_p;
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef NET_UTIL__H_
#define NET_UTIL__H_
#ifdef _WIN32
#pragma once
#endif
bool IsIpString(const char * psz);
void ConvertHexStrIP(char * pszDst, unsigned long nS_Addr);
void RestoreDotIP(char * pszDst, const char * pszSrc);
bool IsInsideIp(const char * pszIpRange, const char * pszIp);
bool IsDomainName(const char * pszName);
bool IsHostName(const char * pszName);
void ExtractDomainName(char * pszDest, const char * pszHostName); // pszHostName : hostname or hostname:port
const char * GetDomainNamePtr(const char * pszHostName); // pszHostName : without port - hostname(o), hostname:port(x)
const char * GetRequestUriPtr(const char * pszUrl);
bool ExtractHostNameFromUrl(HString * pstrHostName, const char * pszUrl);
const char * GetNextLevelHostName(const char * pszHostName, bool bIncludeDot); // www.aaa.bbb.ccc.com -> aaa.bbb.ccc.com or .aaa.bbb.ccc.com
int EncodeURIComponent(char * pszDst, const char * pszSrc);
int DecodeURIComponent(char * pszDst, char * pszSrc);
int EncodeBase64(std::string * pstrEncoded, const unsigned char * pszSrc, unsigned int nSrcLen);
int DecodeBase64(std::string * pstrDecoded, const unsigned char * pszSrc, unsigned int nSrcLen);
void DecodeUriBase64(HString & strDst, const HString & strSrc);
void DecodeUriBase64(HString & strSelf);
#endif // NET_UTIL__H_
+16
View File
@@ -0,0 +1,16 @@
#ifndef OBJECT__H_
#define OBJECT__H_
#ifdef _WIN32
#pragma once
#endif
class HObject
{
public:
HObject() {}
virtual ~HObject() {}
};
#endif // OBJECT__H_
+93
View File
@@ -0,0 +1,93 @@
#ifndef PROTOCOL_HANDLER__H_
#define PROTOCOL_HANDLER__H_
#ifdef _WIN32
#pragma once
#endif
class HTransport;
class HProtocolHandler : public HObject
{
public:
HProtocolHandler() {}
~HProtocolHandler() {}
virtual inline void SetTransport(HTransport * pTransport);
virtual inline int SendToTransport(const char * pData, int nSize);
virtual inline void TerminateTransport();
virtual inline bool GetTransportInfo(const char * pName, void * pValue);
protected:
virtual void OnReceivedStatusFromTransport(int nStatus) = 0;
virtual int OnSendRetryToTransport() = 0;
virtual bool OnPrepareReceive() = 0;
virtual int OnReceivedFromTransport(const char * pData, int nSize) = 0;
protected:
HTransport * m_pTransport;
friend class HTransport;
};
///////////////////////////////////////
class HTransport : public HObject
{
public:
enum
{
T_BEGIN_TRANSPORT = 1,
T_END_TRANSPORT,
T_FAILED_BEGIN
};
HTransport() {}
~HTransport() { delete m_pHandler; }
virtual inline void AttachHandler(HProtocolHandler * pHandler);
virtual inline HProtocolHandler * GetHandler();
virtual inline bool GetTransportInfo(const char * pName, void * pValue) { return false; }
virtual inline void Terminate() {}
virtual int Send(const char * pData, int nSize) = 0;
protected:
inline void OnReceivedStatus(int nStatus);
inline bool OnPrepareReceive();
inline int OnReceived(const char * pData, int nSize);
inline int OnSendRetry();
protected:
HProtocolHandler * m_pHandler;
friend class HProtocolHandler;
};
inline void HProtocolHandler::SetTransport(HTransport * pTransport) { m_pTransport = pTransport; }
inline int HProtocolHandler::SendToTransport(const char * pData, int nSize) { return m_pTransport->Send(pData, nSize); }
inline void HProtocolHandler::TerminateTransport() { m_pTransport->Terminate(); }
inline bool HProtocolHandler::GetTransportInfo(const char * pName, void * pValue) { return m_pTransport->GetTransportInfo(pName, pValue); }
inline void HTransport::AttachHandler(HProtocolHandler * pHandler)
{
pHandler->SetTransport(this);
m_pHandler = pHandler;
}
inline HProtocolHandler * HTransport::GetHandler() { return m_pHandler; }
inline void HTransport::OnReceivedStatus(int nStatus) { m_pHandler->OnReceivedStatusFromTransport(nStatus); }
inline bool HTransport::OnPrepareReceive() { return m_pHandler->OnPrepareReceive(); }
inline int HTransport::OnReceived(const char * pData, int nSize) { return m_pHandler->OnReceivedFromTransport(pData, nSize); }
inline int HTransport::OnSendRetry() { return m_pHandler->OnSendRetryToTransport(); }
#endif // PROTOCOL_HANDLER__H_
+16
View File
@@ -0,0 +1,16 @@
#ifndef ROUTER__H_
#define ROUTER__H_
#ifdef _WIN32
#pragma once
#endif
class HRouter : public HObject
{
public:
HRouter() {}
~HRouter() {}
}
#endif // ROUTER__H_
+537
View File
@@ -0,0 +1,537 @@
#ifndef SOCKET__H_
#define SOCKET__H_
#ifdef MASS_SERVICE_SERVER
#define FD_SETSIZE 2048
#endif
#ifdef _WIN32
#pragma once
//#pragma comment(lib, "wsock32.lib") // old ver
#pragma comment(lib, "ws2_32.lib")
#if _MSC_VER <= 1200
typedef int socklen_t;
#else
#include <ws2tcpip.h> // getaddrinfo
#endif
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> // sockaddr_in
#include <arpa/inet.h> // inet_ntoa()
#include <netdb.h> // gethostbyname()
#include <fcntl.h>
#include <errno.h>
typedef int SOCKET;
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket close
#define SD_BOTH SHUT_RDWR
#endif // _WIN32
extern inline int SockErrorNo()
{
#ifdef _WIN32
return WSAGetLastError();
#else
return errno;
#endif
}
extern inline int GetAddrByHostName(const char * pAddress, struct sockaddr_in * pSai) // blocking operation
{
struct hostent * pHe;
// resolve host address
if ((pHe = gethostbyname(pAddress)) == NULL)
{
#if defined(_WIN32) && _MSC_VER <= 1200
return WSAGetLastError();
#else
struct addrinfo aiHints;
struct addrinfo *aiList = NULL;
struct addrinfo *aiPtr = NULL;
int retVal;
memset(&aiHints, 0, sizeof(aiHints));
aiHints.ai_family = AF_INET;
aiHints.ai_socktype = SOCK_STREAM;
aiHints.ai_protocol = IPPROTO_TCP;
if ((retVal = getaddrinfo(pAddress, NULL, &aiHints, &aiList)))
return SockErrorNo();
for(aiPtr = aiList; aiPtr != NULL; aiPtr = aiPtr->ai_next)
{
if (aiPtr->ai_family == AF_INET)
{
memset(pSai, 0, sizeof(struct sockaddr_in));
memcpy(pSai, aiPtr->ai_addr, sizeof(struct sockaddr_in));
freeaddrinfo(aiList);
return 0; // success
}
}
freeaddrinfo(aiList);
return SOCKET_ERROR;
#endif
}
memset(pSai, 0, sizeof(struct sockaddr_in));
pSai->sin_addr.s_addr = *(u_long *)pHe->h_addr_list[0];
pSai->sin_family = AF_INET;
return 0; // success
}
extern inline void SetSockAddr(struct sockaddr_in * pSai, const char * pIp, u_short nPort)
{
memset(pSai, 0, sizeof(struct sockaddr_in));
pSai->sin_addr.s_addr = inet_addr(pIp);
pSai->sin_family = AF_INET;
pSai->sin_port = htons(nPort);
}
//////////////////////////////////////////////////////////////////////////////
class HSocket : public HObject
{
public:
enum
{
#ifdef _WIN32
ERR_TIMEOUT = WSAETIMEDOUT
#else
ERR_TIMEOUT = ETIMEDOUT
#endif
};
public:
HSocket()
{
m_fdSocket = INVALID_SOCKET;
}
virtual ~HSocket()
{
if (m_fdSocket != INVALID_SOCKET)
closesocket(m_fdSocket);
}
inline SOCKET GetSocket();
inline void SetSocket(SOCKET sock);
inline SOCKET Create(int nDomain, int nType, int nProtocol = 0);
inline int Close();
inline int Bind(u_short nPort);
inline int Bind(struct sockaddr_in * psaiLocal);
inline int Bind(const char * pAddress, u_short nPort);
inline int Listen(int nBackLog);
inline SOCKET Accept(HSocket & sockClient, char * pszPeerIp = NULL, u_short * pnPeerPort = NULL);
inline int Connect(struct sockaddr_in * psaiRemote);
inline int Connect(const char * pHostAddress, u_short nPort);
inline int Send(const char * pData, int nLen, int nFlags = 0);
inline int Receive(char * pBuf, int nLen, int nFlags = 0);
inline int SendTo(const char * pData, int nLen, int flags, struct sockaddr_in * pSaiRemote);
inline int ReceiveFrom(char * pBuf, int nLen, int nFlags = 0, struct sockaddr_in * pSaiRemote = NULL, socklen_t * pnSaiLen = NULL);
inline int GetLocalAddress(struct sockaddr_in * psai);
inline int GetLocalAddress(char * pBuf, u_short * pnPort);
inline int GetPeerAddress(struct sockaddr_in * psai);
inline int GetPeerAddress(char * pBuf, u_short * pnPort);
inline int SetSockOpt(int nLevel, int nOptname, const char * pOptval,
int nOptlen);
inline int GetSockOpt(int nLevel, int nOptname, char * pOptval,
int * pnOptlen);
inline int GetSockOptError();
inline int SetNonBlockMode(bool bNonBlock);
//
inline bool TimoutConnect(struct sockaddr_in * psaiRemote, unsigned long nTimeout, bool bRestoreSyncMode, int * pnError);
inline bool TimoutConnect(const char * pHostAddress, u_short nPort, unsigned long nTimeout, bool bRestoreSyncMode, int * pnError);
inline bool WaitForSending(unsigned long nTimeout, int * pnError); // for non-block mode, *pnError = errno or WSAGetLastError()
inline bool WaitForReceiving(unsigned long nTimeout, int * pnError); // for non-block mode, *pnError = errno or WSAGetLastError()
protected:
SOCKET m_fdSocket;
};
inline SOCKET HSocket::GetSocket()
{
return m_fdSocket;
}
inline void HSocket::SetSocket(SOCKET sock)
{
m_fdSocket = sock;
}
inline SOCKET HSocket::Create(int nDomain, int nType, int nProtocol)
{
return (m_fdSocket = socket(nDomain, nType, nProtocol));
}
inline int HSocket::Close()
{
int nResult = closesocket(m_fdSocket);
m_fdSocket = INVALID_SOCKET;
return nResult;
}
inline int HSocket::Bind(u_short nPort)
{
return Bind(NULL, nPort);
}
inline int HSocket::Bind(struct sockaddr_in * psaiLocal)
{
return bind(m_fdSocket, (struct sockaddr *)psaiLocal, sizeof(struct sockaddr));
}
inline int HSocket::Bind(const char * pAddress, u_short nPort)
{
struct sockaddr_in sai;
memset(&sai, 0, sizeof(struct sockaddr_in));
if (pAddress == NULL || pAddress[0] == '\0')
sai.sin_addr.s_addr = htonl(INADDR_ANY);
else
sai.sin_addr.s_addr = inet_addr(pAddress);
sai.sin_family = AF_INET;
sai.sin_port = htons(nPort);
return bind(m_fdSocket, (struct sockaddr *)&sai, sizeof(struct sockaddr));
}
inline int HSocket::Listen(int nBackLog)
{
return listen(m_fdSocket, nBackLog);
}
inline SOCKET HSocket::Accept(HSocket & sockClient, char * pszPeerIp, u_short * pnPeerPort)
{
if (pszPeerIp != NULL || pnPeerPort != NULL)
{
struct sockaddr_in sai;
socklen_t len = sizeof(struct sockaddr);
SOCKET sock = (sockClient.m_fdSocket = accept(m_fdSocket, (struct sockaddr *)&sai, &len));
if (pszPeerIp != NULL)
strcpy(pszPeerIp, inet_ntoa(sai.sin_addr));
if (pnPeerPort != NULL)
*pnPeerPort = ntohs(sai.sin_port);
return sock;
}
return (sockClient.m_fdSocket = accept(m_fdSocket, NULL, NULL));
}
inline int HSocket::Connect(struct sockaddr_in * psaiRemote)
{
return connect(m_fdSocket, (struct sockaddr *)psaiRemote, sizeof(struct sockaddr));
}
inline int HSocket::Connect(const char * pHostAddress, u_short nPort)
{
struct sockaddr_in sai;
memset(&sai, 0, sizeof(struct sockaddr_in));
sai.sin_addr.s_addr = inet_addr(pHostAddress);
sai.sin_family = AF_INET;
sai.sin_port = htons(nPort);
return connect(m_fdSocket, (struct sockaddr *)&sai, sizeof(struct sockaddr));
}
inline int HSocket::Send(const char * pData, int nLen, int nFlags)
{
return send(m_fdSocket, pData, nLen, nFlags);
}
inline int HSocket::Receive(char * pBuf, int nLen, int nFlags)
{
return recv(m_fdSocket, pBuf, nLen, nFlags);
}
inline int HSocket::SendTo(const char * pData, int nLen, int flags, struct sockaddr_in * pSaiRemote)
{
return sendto(m_fdSocket, pData, nLen, flags, (struct sockaddr *)pSaiRemote, sizeof(struct sockaddr));
}
inline int HSocket::ReceiveFrom(char * pBuf, int nLen, int nFlags, struct sockaddr_in * pSaiRemote, socklen_t * pnSaiLen)
{
return recvfrom(m_fdSocket, pBuf, nLen, nFlags, (struct sockaddr *)pSaiRemote, pnSaiLen);
}
inline int HSocket::GetLocalAddress(struct sockaddr_in * psai)
{
socklen_t len = sizeof(struct sockaddr);
return getsockname(m_fdSocket, (struct sockaddr *)psai, &len);
}
inline int HSocket::GetLocalAddress(char * pBuf, u_short * pnPort)
{
struct sockaddr_in sai;
socklen_t len = sizeof(struct sockaddr);
if (getsockname(m_fdSocket, (struct sockaddr *)&sai, &len) < 0)
return SockErrorNo();
if (pBuf)
strcpy(pBuf, inet_ntoa(sai.sin_addr));
if (pnPort)
*pnPort = ntohs(sai.sin_port);
return 0;
}
inline int HSocket::GetPeerAddress(struct sockaddr_in * psai)
{
socklen_t len = sizeof(struct sockaddr);
return getpeername(m_fdSocket, (struct sockaddr *)psai, &len);
}
inline int HSocket::GetPeerAddress(char * pBuf, u_short * pnPort)
{
struct sockaddr_in sai;
socklen_t len = sizeof(struct sockaddr);
if (getpeername(m_fdSocket, (struct sockaddr *)&sai, &len) < 0)
return SockErrorNo();
if (pBuf)
strcpy(pBuf, inet_ntoa(sai.sin_addr));
if (pnPort)
*pnPort = ntohs(sai.sin_port);
return 0;
}
inline int HSocket::SetSockOpt(int nLevel, int nOptname, const char * pOptval, int nOptlen)
{
return setsockopt(m_fdSocket, nLevel, nOptname, pOptval, nOptlen);
}
inline int HSocket::GetSockOpt(int nLevel, int nOptname, char * pOptval, int * pnOptlen)
{
return getsockopt(m_fdSocket, nLevel, nOptname, pOptval, (socklen_t *)pnOptlen);
}
inline int HSocket::GetSockOptError()
{
int nOptVal;
int nOptLen = sizeof(int);
if (getsockopt(m_fdSocket, SOL_SOCKET, SO_ERROR, (char *)(&nOptVal), (socklen_t *)&nOptLen) < 0)
return SockErrorNo();
return nOptVal;
}
inline int HSocket::SetNonBlockMode(bool bNonBlock)
{
#ifdef _WIN32
ULONG nFlags = bNonBlock;
return ioctlsocket(m_fdSocket, FIONBIO, &nFlags);
#else
int nFlags = fcntl(m_fdSocket, F_GETFL, 0);
return fcntl(m_fdSocket, F_SETFL, (bNonBlock ? nFlags | O_NONBLOCK : nFlags & ~O_NONBLOCK));
#endif
}
inline bool HSocket::TimoutConnect(struct sockaddr_in * psaiRemote,
unsigned long nTimeout, bool bRestoreSyncMode, int * pnError)
{
#ifdef _WIN32
ULONG nFlags = 1;
if (ioctlsocket(m_fdSocket, FIONBIO, &nFlags) < 0)
#else
int nFlags = fcntl(m_fdSocket, F_GETFL, 0);
if (fcntl(m_fdSocket, F_SETFL, nFlags | O_NONBLOCK) < 0)
#endif
{
*pnError = SockErrorNo();
return false;
}
socklen_t len = sizeof(struct sockaddr);
int nResult;
if ((nResult = connect(m_fdSocket, (struct sockaddr *)psaiRemote, len)) < 0)
{
*pnError = SockErrorNo();
#ifdef _WIN32
if (*pnError != WSAEINPROGRESS && *pnError != WSAEWOULDBLOCK)
#else
if (*pnError != EINPROGRESS)
#endif
return false;
}
fd_set fsRead, fsWrite;
struct timeval tv;
FD_ZERO(&fsRead);
FD_SET(m_fdSocket, &fsRead);
fsWrite = fsRead;
tv.tv_sec = nTimeout / 1000;
tv.tv_usec = (nTimeout % 1000) * 1000;
if ((nResult = select((int)(m_fdSocket + 1), &fsRead, &fsWrite, NULL, &tv)) == 0)
{
*pnError = ERR_TIMEOUT;
return false;
}
if (FD_ISSET(m_fdSocket, &fsRead) || FD_ISSET(m_fdSocket, &fsWrite))
{
len = sizeof(nResult);
if (getsockopt(m_fdSocket, SOL_SOCKET, SO_ERROR, (char *)&nResult, &len) < 0)
{
*pnError = SOCKET_ERROR;
return false; // Solaris pending error
}
}
else
{
*pnError = SOCKET_ERROR; // select error: m_fdSocket not set
return false;
}
if (bRestoreSyncMode)
{
#ifdef _WIN32
nFlags = 0;
if (ioctlsocket(m_fdSocket, FIONBIO, &nFlags) < 0)
#else
if (fcntl(m_fdSocket, F_SETFL, nFlags) < 0)
#endif
{
*pnError = SockErrorNo();
return false;
}
}
*pnError = 0;
return true;
}
inline bool HSocket::TimoutConnect(const char * pHostAddress, u_short nPort, unsigned long nTimeout, bool bRestoreSyncMode, int * pnError)
{
struct sockaddr_in sai;
memset(&sai, 0, sizeof(struct sockaddr_in));
sai.sin_addr.s_addr = inet_addr(pHostAddress);
sai.sin_family = AF_INET;
sai.sin_port = htons(nPort);
return TimoutConnect(&sai, nTimeout, bRestoreSyncMode, pnError);
}
inline bool HSocket::WaitForSending(unsigned long nTimeout, int * pnError)
{
fd_set fsWrite;
struct timeval tv;
FD_ZERO(&fsWrite);
FD_SET(m_fdSocket, &fsWrite);
tv.tv_sec = nTimeout / 1000;
tv.tv_usec = (nTimeout % 1000) * 1000;
int nResult = select((int)m_fdSocket + 1, NULL, &fsWrite, NULL, nTimeout ? &tv : NULL);
if (nResult < 0)
{
*pnError = SockErrorNo();
return false;
}
if (nResult == 0 || FD_ISSET(m_fdSocket, &fsWrite) == 0)
{
*pnError = ERR_TIMEOUT;
return false;
}
*pnError = 0;
return true;
}
inline bool HSocket::WaitForReceiving(unsigned long nTimeout, int * pnError)
{
fd_set fsRead;
struct timeval tv;
FD_ZERO(&fsRead);
FD_SET(m_fdSocket, &fsRead);
tv.tv_sec = nTimeout / 1000;
tv.tv_usec = (nTimeout % 1000) * 1000;
int nResult = select((int)m_fdSocket + 1, &fsRead, NULL, NULL, nTimeout ? &tv : NULL);
if (nResult < 0)
{
*pnError = SockErrorNo();
return false;
}
if (nResult == 0 || FD_ISSET(m_fdSocket, &fsRead) == 0)
{
*pnError = ERR_TIMEOUT;
return false;
}
*pnError = 0;
return true;
}
//////////////////////////////////////////////////////////////////////////////
extern inline int TcpCompleteSend(SOCKET sock, const char * pszPacket, int nPacketSize)
{
int nSentSize;
const char * pszPacketOffset = pszPacket;
while (nPacketSize > 0)
{
nSentSize = send(sock, pszPacketOffset, nPacketSize, 0);
if (nSentSize <= 0)
{
//HLOG(HLOG_ERROR, "[ERROR], EmailSender, Failed to send.\n");
return -1;
}
nPacketSize -= nSentSize;
pszPacketOffset += nSentSize;
}
return 1;
}
#endif // SOCKET__H_
+118
View File
@@ -0,0 +1,118 @@
#include "huslib.h"
#include "huslibex.h"
#include "SohHandler.h"
HSohHandler::HSohHandler()
{
m_pRecvBuffer = new HStreamBuffer(HH_SOH_MAX_COMMAND_PACKET_SIZE);
m_nBodySize = 0;
m_pSendBuffer = new HStreamBuffer(HH_SOH_MAX_COMMAND_PACKET_SIZE);
}
HSohHandler::~HSohHandler()
{
delete m_pRecvBuffer;
delete m_pSendBuffer;
}
int HSohHandler::SendBufferedPacket()
{
int nSentSize = SendToTransport(m_pSendBuffer->Head(), m_pSendBuffer->StoredSize());
if (nSentSize <= 0)
return nSentSize;
m_pSendBuffer->Pop(nSentSize);
return nSentSize;
}
int HSohHandler::SendPacket(const char * pData, size_t nSize)
{
if (m_pSendBuffer->StoredSize() == 0)
{
int nSentSize = SendToTransport(pData, nSize);
if (nSentSize < 0)
return -1;
if (nSentSize != nSize)
m_pSendBuffer->Store(pData + nSentSize, nSize - nSentSize);
return nSentSize;
}
m_pSendBuffer->Store(pData, nSize);
return SendBufferedPacket();
}
void HSohHandler::OnReceivedStatusFromTransport(int nStatus)
{
if (nStatus == HTransport::T_BEGIN_TRANSPORT)
{
OnInitialize(true);
}
else if (nStatus == HTransport::T_FAILED_BEGIN)
{
OnInitialize(false);
}
else if (nStatus == HTransport::T_END_TRANSPORT)
{
OnTerminate();
}
}
int HSohHandler::OnReceivedFromTransport(const char * pData, int nSize)
{
if (m_pRecvBuffer->Store(pData, nSize) == false)
{
HLOGF(HLOG_ERROR, "[ERROR], SohHdler, Failed to insert data, buffer = %d, stored = %d, recv size = %d\n", m_pRecvBuffer->Size(), m_pRecvBuffer->StoredSize(), nSize);
return -1; // close connection
}
for (;;)
{
if (m_nBodySize > 0)
{
if (m_nBodySize > m_pRecvBuffer->StoredSize())
return 0; // receive remain packet
}
else
{
if (m_pRecvBuffer->StoredSize() < 4)
return 0; // receive remain packet
// get body size
m_nBodySize = ntohs(*((u_short *)(m_pRecvBuffer->Head() + 2)));
m_pRecvBuffer->Pop(4); // pop header
//
/*static int i = 0;
if (i++ == 0)
m_nBodySize = 69; //TestCode
else
m_nBodySize = 197; //TestCode*/
HLOGF(HLOG_ERROR, "[TRACE], SohHdler, m_nBodySize = %d\n", m_nBodySize);
if (m_nBodySize > m_pRecvBuffer->StoredSize())
return 0; // receive remain packet
}
m_pRecvBuffer->Head()[m_nBodySize] = '\0';
if (OnReceivedBody(m_pRecvBuffer->Head(), m_nBodySize) < 0)
return -1; // close connection
m_pRecvBuffer->Pop(m_nBodySize);
m_nBodySize = 0;
}
return -1; // close connection
}
int HSohHandler::OnSendRetryToTransport()
{
return SendBufferedPacket();
}
+53
View File
@@ -0,0 +1,53 @@
#ifndef SOH_HANDLER__H_
#define SOH_HANDLER__H_
#ifdef _WIN32
#pragma once
#endif
// size only in header
class HSohHandler : public HProtocolHandler
{
public:
enum
{
HH_SOH_MAX_COMMAND_PACKET_SIZE = 65536
};
HSohHandler();
~HSohHandler();
int SendPacket(const char * pData, size_t nSize);
// for zero copy
char * GetSBufPtr() { return m_pSendBuffer->Tail(); }
size_t GetSBufSize() { return m_pSendBuffer->RemainSize(); }
bool MarkUsedSBuf(size_t nSize) { return m_pSendBuffer->MoveTail(nSize); }
int SendBufferedPacket();
protected:
int SendBufferCommand();
void OnReceivedStatusFromTransport(int nStatus);
int OnReceivedFromTransport(const char * pData, int nSize);
int OnSendRetryToTransport();
bool OnPrepareReceive() { return true; }
virtual void OnInitialize(bool bIsSuccess) = 0;
virtual void OnTerminate() = 0;
virtual int OnReceivedBody(const char * pBody, int nSize) = 0;
protected:
HStreamBuffer * m_pRecvBuffer;
size_t m_nBodySize;
HStreamBuffer * m_pSendBuffer;
};
#endif // REDUNDANCY__H_
+130
View File
@@ -0,0 +1,130 @@
#ifndef STREAM_BUFFER__H_
#define STREAM_BUFFER__H_
#ifdef _WIN32
#pragma once
#endif
class HStreamBuffer : public HObject
{
public:
HStreamBuffer(size_t nSize)
{
m_pBuffer = (char *)malloc(nSize); //...??? 2048 : because of openssl buffer overflow?
m_nBufferSize = nSize;
m_pBufferHead = m_pBuffer;
m_pBufferTail = m_pBuffer;
m_nStoredSize = 0;
m_nRemainSize = m_nBufferSize;
}
~HStreamBuffer()
{
free(m_pBuffer);
}
inline char * Head() { return m_pBufferHead; }
inline char * Tail() { return m_pBufferTail; }
inline size_t Size() { return m_nBufferSize; }
inline size_t StoredSize() { return m_nStoredSize; }
inline size_t RemainSize() { return m_nRemainSize; }
inline bool MoveTail(size_t nSize)
{
if (nSize > m_nRemainSize)
return false;
m_pBufferTail += nSize;
m_nStoredSize += nSize;
m_nRemainSize -= nSize;
return true;
}
inline bool Pop(size_t nSize)
{
if (nSize > m_nStoredSize)
return false;
m_nStoredSize -= nSize;
if (m_nStoredSize == 0)
{
m_pBufferHead = m_pBuffer;
m_pBufferTail = m_pBuffer;
m_nRemainSize = m_nBufferSize;
}
else
{
m_pBufferHead += nSize;
}
return true;
}
inline bool PopAndRewind(size_t nSize)
{
if (nSize > m_nStoredSize)
return false;
m_nStoredSize -= nSize;
memcpy(m_pBufferHead, m_pBufferHead + nSize, m_nStoredSize);
m_pBufferTail = m_pBufferHead + m_nStoredSize;
m_nRemainSize += nSize;
return true;
}
inline bool Store(const char * pData, size_t nSize)
{
if (nSize > m_nRemainSize)
return false;
memcpy(m_pBufferTail, pData, nSize);
m_pBufferTail += nSize;
m_nStoredSize += nSize;
m_nRemainSize -= nSize;
return true;
}
inline void Reset()
{
m_pBufferHead = m_pBuffer;
m_pBufferTail = m_pBuffer;
m_nStoredSize = 0;
m_nRemainSize = m_nBufferSize;
}
inline int MemCmp(const void * p, size_t n)
{
return memcmp(m_pBufferHead, p, n);
}
inline int Find(const char ch, size_t offset, size_t n = 0)
{
if (n == 0)
n = m_nStoredSize;
for (size_t i = offset; i < n; i++)
{
if (m_pBufferHead[i] == ch)
return (int)i;
}
return -1;
}
protected:
char * m_pBuffer;
char * m_pBufferHead;
char * m_pBufferTail;
size_t m_nBufferSize;
size_t m_nStoredSize;
size_t m_nRemainSize;
};
#endif // STREAM_BUFFER__H_
+983
View File
@@ -0,0 +1,983 @@
#ifndef STRING__H_
#define STRING__H_
#ifdef _WIN32
#pragma once
#endif
#include <string>
#include <sstream>
#include <algorithm>
#ifndef _WIN32
#include <iconv.h>
#endif
class HString : public std::string
{
public:
static int ReadOneLine(HString * pstrDst, const char * pszSrc, int nStartOffset)
{
const char * p = pszSrc + nStartOffset;
int i, nResult = -1;
for (i = 0; *p != '\0' ; i++)
{
if (*p == '\r')
{
nResult = nStartOffset + i + 1;
if (*(p + 1) == '\n')
nResult++;
pstrDst->Assign(pszSrc + nStartOffset, i);
break;
}
else if (*p == '\n')
{
nResult = nStartOffset + i + 1;
pstrDst->Assign(pszSrc + nStartOffset, i);
break;
}
p++;
}
if (nResult == -1 && i > 0)
{
nResult = nStartOffset + i;
pstrDst->Assign(pszSrc + nStartOffset, i);
}
return nResult;
}
public:
HString() {}
HString(char ch) { operator=(ch); }
//HString(const char * psz) : std::string(psz) {}
HString(const char * psz) { if (psz) std::string::operator=(psz); }
HString(const char * p, size_t nSize) : std::string(p, nSize) {}
HString(const std::string & str) : std::string(str) {}
HString(short num) { operator=(num); } //??? HString * pstr = NULL; pstr ? *pstr : NULL
HString(unsigned short num) { operator=(num); }
HString(int num) { operator=(num); }
HString(unsigned int num) { operator=(num); }
HString(long num) { operator=(num); }
HString(unsigned long num) { operator=(num); }
HString(float num) { operator=(num); }
HString(double num) { operator=(num); }
#ifdef _WIN32
HString(time_t num) { operator=(num); }
#endif
~HString() {}
inline std::string & operator=(char ch)
{
return std::string::operator=(ch);
}
inline std::string & operator=(const char * psz)
{
if (psz)
return std::string::operator=(psz);
return std::string::operator=("");
}
inline std::string & operator=(short num) //...
{
char szBuf[16]; sprintf(szBuf, "%d", num);
return std::string::operator=(szBuf);
}
inline std::string & operator=(unsigned short num) //...
{
char szBuf[16]; sprintf(szBuf, "%hd", num);
return std::string::operator=(szBuf);
}
inline std::string & operator=(int num) //...
{
char szBuf[32]; sprintf(szBuf, "%d", num);
return std::string::operator=(szBuf);
}
inline std::string & operator=(unsigned int num) //...
{
char szBuf[32]; sprintf(szBuf, "%u", num);
return std::string::operator=(szBuf);
}
inline std::string & operator=(long num) //...
{
char szBuf[64]; sprintf(szBuf, "%ld", num);
return std::string::operator=(szBuf);
}
inline std::string & operator=(unsigned long num) //...
{
char szBuf[64]; sprintf(szBuf, "%lu", num);
return std::string::operator=(szBuf);
}
inline std::string & operator=(float num) //...
{
char szBuf[64]; sprintf(szBuf, "%f", num);
return std::string::operator=(szBuf);
}
inline std::string & operator=(double num) //...
{
char szBuf[64]; sprintf(szBuf, "%lf", num);
return std::string::operator=(szBuf);
}
#ifdef _WIN32
inline std::string & operator=(time_t num) //...
{
char szBuf[64]; sprintf(szBuf, "%lld", num);
return std::string::operator=(szBuf);
}
#endif
inline std::string & operator+=(char ch)
{
return std::string::operator+=(ch);
}
inline std::string & operator+=(const char * psz)
{
if (psz == NULL)
return *this;
return std::string::operator+=(psz);
}
inline std::string & operator+=(const std::string & str)
{
return std::string::operator+=(str);
}
inline std::string & operator+=(short num) //...
{
char szBuf[16]; sprintf(szBuf, "%d", num);
return append(szBuf);
}
inline std::string & operator+=(unsigned short num) //...
{
char szBuf[16]; sprintf(szBuf, "%hd", num);
return append(szBuf);
}
inline std::string & operator+=(int num) //...
{
char szBuf[32]; sprintf(szBuf, "%d", num);
return append(szBuf);
}
inline std::string & operator+=(unsigned int num) //...
{
char szBuf[32]; sprintf(szBuf, "%u", num);
return append(szBuf);
}
inline std::string & operator+=(long num) //...
{
char szBuf[64]; sprintf(szBuf, "%ld", num);
return append(szBuf);
}
inline std::string & operator+=(unsigned long num) //...
{
char szBuf[64]; sprintf(szBuf, "%lu", num);
return append(szBuf);
}
inline std::string & operator+=(float num) //...
{
char szBuf[64]; sprintf(szBuf, "%f", num);
return append(szBuf);
}
inline std::string & operator+=(double num) //...
{
char szBuf[64]; sprintf(szBuf, "%lf", num);
return append(szBuf);
}
#ifdef _WIN32
inline std::string & operator+=(time_t num) //...
{
char szBuf[64]; sprintf(szBuf, "%lld", num);
return append(szBuf);
}
#endif
inline operator const char *() const
{
return c_str();
}
inline operator short() const
{
return atoi(c_str());
}
inline operator unsigned short() const
{
return atoi(c_str());
}
inline operator int() const
{
return atoi(c_str());
}
inline operator unsigned int() const
{
return atoi(c_str());
}
inline operator long() const
{
return atol(c_str());
}
inline operator unsigned long() const
{
return atol(c_str());
}
inline const char * psz() const
{
return c_str();
}
inline size_t GetLength() const
{
return length();
}
inline bool IsEmpty() const
{
return empty();
}
inline void Reserve(size_t nSize)
{
reserve(nSize);
}
inline std::string & Assign(const char * psz, size_t nOffset)
{
return assign(psz, nOffset);
}
inline size_t Copy(char * psz, size_t len, size_t pos = 0) const
{
return copy(psz, len, pos);
}
inline HString SubStr(const size_t pos, size_t len) const
{
return substr(pos, len);
}
inline int StrNCmp(const char * psz, unsigned int nCount)
{
return ::strncmp(c_str(), psz, nCount);
}
inline int StrNICmp(const char * psz, unsigned int nCount)
{
return ::strnicmp(c_str(), psz, nCount);
}
inline const char * StrNStr(const char * psz, int nCount = -1) const
{
return ::StrNStr(c_str(), psz, nCount);
}
inline const char * StrNIStr(const char * psz, int nCount = -1) const
{
return ::StrNIStr(c_str(), psz, nCount);
}
inline const char * ToUpper()
{
char * pszDst = (char *)malloc(GetLength() + 1);
char * pszOffset = pszDst;
const char * pszSrc = psz();
while (*pszSrc)
{
*pszOffset++ = toupper(*pszSrc++);
}
*pszOffset = '\0';
std::string::operator=(pszDst);
free(pszDst);
return c_str();
}
inline const char * ToLower()
{
char * pszDst = (char *)malloc(GetLength() + 1);
char * pszOffset = pszDst;
const char * pszSrc = psz();
while (*pszSrc)
{
*pszOffset++ = tolower(*pszSrc++);
}
*pszOffset = '\0';
std::string::operator=(pszDst);
free(pszDst);
return c_str();
}
inline int CompareNoCase(const char * p) const
{
return stricmp(psz(), p);
}
inline char GetLast() const
{
if (empty())
return -1;
return psz()[GetLength() - 1];
}
#ifdef _WIN32
#pragma warning(disable:4267)
#endif
inline long Find(const HString & str, size_t pos = 0) const
{
size_t nResult = find(str, pos);
if (nResult == std::string::npos)
return -1;
return nResult;
}
inline long Find(const char * psz, size_t pos = 0) const
{
size_t nResult = find(psz, pos);
if (nResult == std::string::npos)
return -1;
return nResult;
}
inline long Find(const char * psz, size_t pos, size_t n) const
{
size_t nResult = find(psz, pos, n);
if (nResult == std::string::npos)
return -1;
return nResult;
}
inline long Find(char c, size_t pos = 0) const
{
size_t nResult = find(c, pos);
if (nResult == std::string::npos)
return -1;
return nResult;
}
#ifdef _WIN32
#pragma warning(default:4267)
#endif
void Trim(bool bRemoveFront, bool bRemoveRear)
{
char * pszBuffer = (char *)malloc(GetLength() + 1);
char * pszDst = pszBuffer;
strcpy(pszDst, psz());
StrTrim(&pszDst, GetLength(), bRemoveFront, bRemoveRear);
std::string::operator=(pszDst);
free(pszBuffer);
}
bool Replace(const char * pszKeyword, const char * pszReplace, int nMode = 0, int nCount = -1) // nMode : 0 = case sensitive, 1 = no case, 2 = keyword
{
if (nCount == 0)
return false;
const char * (*fnStrStr)(const char *, const char *);
if (nMode == 0)
fnStrStr = (const char*(*)(const char*, const char*))strstr;
else if (nMode == 1)
fnStrStr = stristr;
else
fnStrStr = StrIKeyword;
int nRepeatCount = nCount;
size_t nKeywordLength = strlen(pszKeyword);
const char * pszNext = psz();
int nKeywordCount = 0;
for (;;)
{
if ((pszNext = fnStrStr(pszNext, pszKeyword)) == NULL)
break;
nKeywordCount++;
if (nRepeatCount > -1 && --nRepeatCount == 0)
break;
pszNext += nKeywordLength;
}
if (nKeywordCount == 0)
return false;
size_t nReplaceLength = strlen(pszReplace);
size_t nTextLength = GetLength();
size_t nNewTextLength = nTextLength + (nReplaceLength - nKeywordLength) * nKeywordCount;
char * pszNewText = (char *)malloc(nNewTextLength + 1);
size_t nCopySize;
size_t nRemainSize = nTextLength;
char * pszNewTextOffset = pszNewText;
const char * pszTextOffset = psz();
nRepeatCount = nCount;
for (;;)
{
if ((pszNext = fnStrStr(pszTextOffset, pszKeyword)) == NULL)
break;
nCopySize = pszNext - pszTextOffset;
memcpy(pszNewTextOffset, pszTextOffset, nCopySize);
memcpy(pszNewTextOffset + nCopySize, pszReplace, nReplaceLength);
pszTextOffset += nCopySize + nKeywordLength;
pszNewTextOffset += nCopySize + nReplaceLength;
nRemainSize -= nCopySize + nKeywordLength;
if (nRepeatCount > -1 && --nRepeatCount == 0)
break;
}
if (nRemainSize > 0)
memcpy(pszNewTextOffset, pszTextOffset, nRemainSize);
pszNewText[nNewTextLength] = '\0';
std::string::operator=(pszNewText);
free(pszNewText);
return true;
}
// " a b c " --> " a b c "
void RemoveRedundancyChar(const char * pszSrc, size_t nLength, char ch)
{
*this = "";
if (pszSrc == NULL || nLength == 0)
return;
for (size_t i = 0; i < nLength; i++)
{
if (pszSrc[i] == ch && pszSrc[i + 1] == ch)
continue;
*this += pszSrc[i];
}
}
void RemoveRedundancyRow(const char * pszSrc, size_t nLength)
{
*this = "";
if (pszSrc == NULL || nLength == 0)
return;
for (size_t i = 0; i < nLength; i++)
{
if (pszSrc[i] == '\r' && pszSrc[i + 1] == '\n' && pszSrc[i + 2] == '\r' && pszSrc[i + 3] == '\n')
{
i++;
continue;
}
*this += pszSrc[i];
}
}
void Cut(char chDelimiter)
{
char * p = (char *)psz();
size_t nLength = GetLength();
for (size_t i = 0; i < nLength; i++)
{
if (p[i] == chDelimiter)
{
p[i] = '\0';
break;
}
}
}
void PartAssign(const char * psz, char chDelimiter)
{
size_t i = 0;
for (; psz[i]; i++)
{
if (psz[i] == chDelimiter)
break;
}
if (i == 0)
return;
Assign(psz, i);
}
/*int Tokenize(const char * psz, size_t nSize, char chDelimiter)
{
for (size_t i = 0; i < nSize; i++)
{
if (psz[i] == ' ')
{
if (i > 0)
Assign(psz, i);
return (int)(i + 1);
}
}
return -1;
}*/
// 2019-11-01 0:02 -> YYYY-MM-DD HH:MM
void ConvertDateTime()
{
if (GetLength() == 15)
{
HString str(psz(), 11);
str += "0";
str += this->SubStr(11, 4);
*this = str;
}
}
};
///////////////////////////////////////
class HStringTokenizer : public HObject
{
public:
HStringTokenizer(const HString & str, const char cDelimiter)
{
Tokenize(str, cDelimiter);
}
HStringTokenizer(const char * psz, const char cDelimiter)
{
HString str = psz;
Tokenize(str, cDelimiter);
}
~HStringTokenizer()
{
if (m_arr)
delete [] m_arr;
}
inline size_t GetCount() { return m_nCount; }
//inline HString & operator [] (int nIndex)
inline HString & operator [] (size_t nIndex)
{
return m_arr[nIndex];
}
protected:
// |a|b - fail
inline void Tokenize(const HString & str, const char cDelimiter)
{
if (str.IsEmpty())
{
m_arr = NULL;
m_nCount = 0;
return;
}
m_nCount = std::count(str.begin(), str.end(), cDelimiter) + 1;
m_arr = new HString[m_nCount];
std::istringstream stream(str);
std::string token;
int i = 0;
while (std::getline(stream, token, cDelimiter))
{
m_arr[i++] = token;
}
}
private:
HString * m_arr;
size_t m_nCount;
};
///////////////////////////////////////
class HUtf16ToUtf8
{
public:
HUtf16ToUtf8()
{
#ifndef _WIN32
m_iconv = iconv_open("UTF-8", "UTF-16LE");
#endif
m_pUtf8 = NULL;
}
~HUtf16ToUtf8()
{
if (m_pUtf8)
free(m_pUtf8);
#ifndef _WIN32
iconv_close(m_iconv);
#endif
}
char * Convert(const char * pSrc, int nLen)
{
if (m_pUtf8)
free(m_pUtf8);
#ifndef _WIN32
size_t nDstLen = nLen * 2;
m_pUtf8 = (char *)calloc(nDstLen + 1, 1);
char * pSrc2 = (char *)calloc(nLen + 1, 1);
memcpy(pSrc2, pSrc, nLen + 1);
char * pUtf16 = pSrc2;
char * pDst = m_pUtf8;
iconv(m_iconv, &pUtf16, (size_t *)&nLen, &pDst, &nDstLen);
free(pSrc2);
#else
int nDstLen = WideCharToMultiByte(CP_UTF8, 0, (const wchar_t *)pSrc, (int)nLen, NULL, 0, NULL, NULL);
if (nDstLen > 0)
{
m_pUtf8 = (char *)malloc(nDstLen + 1);
WideCharToMultiByte(CP_UTF8, 0, (const wchar_t *)pSrc, (int)nLen, m_pUtf8, nDstLen, NULL, NULL);
m_pUtf8[nDstLen] = '\0';
}
#endif
return m_pUtf8;
}
protected:
#ifndef _WIN32
iconv_t m_iconv;
#endif
char * m_pUtf8;
};
class HUtf8ToEucKr
{
public:
HUtf8ToEucKr()
{
#ifndef _WIN32
m_iconv = iconv_open("EUC-KR", "UTF-8");
#endif
m_pEucKr = NULL;
}
~HUtf8ToEucKr()
{
if (m_pEucKr)
free(m_pEucKr);
#ifndef _WIN32
iconv_close(m_iconv);
#endif
}
char * Convert(const char * pSrc, int nLen)
{
if (pSrc == NULL || pSrc[0] == '\0' || nLen <= 0)
return "";
if (m_pEucKr)
free(m_pEucKr);
#ifndef _WIN32
size_t nDstLen = nLen * 2;
m_pEucKr = (char *)calloc(nDstLen + 1, 1);
char * pSrc2 = (char *)calloc(nLen + 1, 1);
strcpy(pSrc2, pSrc);
char * pUtf8 = pSrc2;
char * pDst = m_pEucKr;
iconv(m_iconv, &pUtf8, (size_t *)&nLen, &pDst, &nDstLen);
free(pSrc2);
#else
int nLength = MultiByteToWideChar(CP_UTF8, 0, pSrc, nLen + 1, NULL, NULL);
BSTR bstrWide = SysAllocStringLen(NULL, nLength);
MultiByteToWideChar(CP_UTF8, 0, pSrc, nLen + 1, bstrWide, nLength);
nLength = WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, NULL, 0, NULL, NULL);
m_pEucKr = (char *)malloc(nLength);
WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, m_pEucKr, nLength, NULL, NULL);
SysFreeString(bstrWide);
#endif
return m_pEucKr;
}
protected:
#ifndef _WIN32
iconv_t m_iconv;
#endif
char * m_pEucKr;
};
class HEucKrToUtf8
{
public:
HEucKrToUtf8()
{
#ifndef _WIN32
m_iconv = iconv_open("UTF-8", "EUC-KR");
#endif
m_pUtf8 = NULL;
}
~HEucKrToUtf8()
{
if (m_pUtf8)
free(m_pUtf8);
#ifndef _WIN32
iconv_close(m_iconv);
#endif
}
char * Convert(const char * pSrc, int nLen)
{
if (m_pUtf8)
free(m_pUtf8);
#ifndef _WIN32
size_t nDstLen = nLen * 4;
m_pUtf8 = (char *)calloc(nDstLen + 1, 1);
char * pSrc2 = (char *)calloc(nLen + 1, 1);
strcpy(pSrc2, pSrc);
char * pUtf16 = pSrc2;
char * pDst = m_pUtf8;
iconv(m_iconv, &pUtf16, (size_t *)&nLen, &pDst, &nDstLen);
free(pSrc2);
#else
int nLength = MultiByteToWideChar(CP_ACP, 0, pSrc, nLen, NULL, NULL);
BSTR bstrCode = SysAllocStringLen(NULL, nLength);
MultiByteToWideChar(CP_ACP, 0, pSrc, nLen, bstrCode, nLength);
int nLength2 = WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, m_pUtf8, 0, NULL, NULL);
m_pUtf8 = (char*)malloc(nLength2 + 1);
WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, m_pUtf8, nLength2, NULL, NULL);
SysFreeString(bstrCode);
#endif
return m_pUtf8;
}
protected:
#ifndef _WIN32
iconv_t m_iconv;
#endif
char * m_pUtf8;
};
///////////////////////////////////////
extern inline void RemoveTagElement(HString * pstrDst, const char * pszSrc, size_t nLength, const char * pszTag)
{
*pstrDst = "";
if (pszSrc == NULL || nLength == 0)
return;
HString strFrontTag = "<"; strFrontTag += pszTag;
HString strRearTag = "</"; strRearTag += pszTag; strRearTag += ">";
bool bSkip = false;
for (size_t i = 0; i < nLength; i++, pszSrc++)
{
if (bSkip)
{
if (strnicmp(pszSrc, strRearTag, strRearTag.GetLength()) == 0)
{
bSkip = false;
i += strRearTag.GetLength() - 1;
pszSrc += strRearTag.GetLength() - 1;
}
continue;
}
else if (strnicmp(pszSrc, strFrontTag, strFrontTag.GetLength()) == 0)
{
bSkip = true;
i += strFrontTag.GetLength() - 1;
pszSrc += strFrontTag.GetLength() - 1;
continue;
}
*pstrDst += *pszSrc;
}
}
extern inline void RemoveMarkupTag(HString * pstrDst, const char * pszSrc, size_t nLength)
{
*pstrDst = "";
if (pszSrc == NULL || nLength == 0)
return;
int nSkipMode = 0; // 0 : no skip, 1 : normal tag, 2 : comment tag
for (size_t i = 0; i < nLength; i++)
{
if (nSkipMode == 1)
{
if (pszSrc[i] == '>')
nSkipMode = 0;
continue;
}
else if (nSkipMode == 2)
{
if (pszSrc[i] == '-' && pszSrc[i + 1] == '-' && pszSrc[i + 2] == '>')
{
i += 2;
nSkipMode = 0;
}
continue;
}
else if (pszSrc[i] == '<')
{
if (pszSrc[i + 1] == '!' && pszSrc[i + 2] == '-' && pszSrc[i + 3] == '-')
{
i += 2;
nSkipMode = 2;
}
else
nSkipMode = 1;
continue;
}
*pstrDst += pszSrc[i];
}
}
extern inline size_t ClearSpaceAndRow(HString * pstrDst, const char * pszSrc, size_t nLength, bool bRemoveRow)
{
size_t nRowCount = 0;
*pstrDst = "";
if (pszSrc == NULL || nLength == 0)
return nRowCount;
char * pNextLine = (char *)pszSrc;
char * pOneLine;
do
{
pOneLine = pNextLine;
pNextLine = StrSlice(pOneLine);
StrTrim(&pOneLine, strlen(pOneLine), true, true);
if (pOneLine[0] == '\0')
continue;
*pstrDst += pOneLine;
nRowCount++;
if (bRemoveRow == false)
*pstrDst += "\r\n";
} while (pNextLine);
return nRowCount;
}
extern inline void StrRemoveRow(HString * pstrDst, const char * pszSrc, const char * pszKeyword)
{
*pstrDst = "";
if (pszSrc == NULL || pszKeyword == NULL)
return;
char * pNextLine = (char *)pszSrc;
char * pOneLine;
do
{
pOneLine = pNextLine;
pNextLine = StrSlice(pOneLine);
StrTrim(&pOneLine, strlen(pOneLine), true, true);
if (pOneLine[0] == '\0' || stristr(pOneLine, pszKeyword))
continue;
*pstrDst += pOneLine;
*pstrDst += "\r\n";
} while (pNextLine);
}
// nMode = 0 : between, 1 : with front, 2 : with rear, 3 : both remove
extern inline void StrBetweenRemove(HString * pstrDst, const char * pszSrc, const char * pszFront, const char * pszRear, int nMode)
{
*pstrDst = "";
if (pszSrc == NULL || pszFront == NULL || pszRear == NULL)
return;
char * pszStart, * pszEnd;
if ((pszStart = (char *)strstr(pszSrc, pszFront)) == NULL)
return;
size_t nFrontSize = strlen(pszFront);
pszStart += nFrontSize;
if ((pszEnd = strstr(pszStart, pszRear)) == NULL)
return;
if (nMode == 1 || nMode == 3)
pszStart -= nFrontSize;
pstrDst->Assign(pszSrc, pszStart - pszSrc);
if (nMode == 2 || nMode == 3)
*pstrDst += (pszEnd + strlen(pszRear));
else
*pstrDst += pszEnd;
}
#endif // STRING__H_
+106
View File
@@ -0,0 +1,106 @@
#include "huslib.h"
#include "huslibex.h"
#include "MultiplexSocket.h"
#include "MultiplexTransport.h"
HTelnetHandler::HTelnetHandler()
{
m_nCommandBufferedLength = 0;
m_bInitialStep = 0;
}
HTelnetHandler::~HTelnetHandler()
{
}
void HTelnetHandler::OnReceivedStatusFromTransport(int nStatus)
{
if (nStatus == HTransport::T_BEGIN_TRANSPORT)
{
char bufSend[4];
bufSend[0] = (char)IAC;
bufSend[1] = (char)WILL;
bufSend[2] = (char)SGAHEAD;
SendToTransport(bufSend, 3);
}
}
int HTelnetHandler::OnReceivedFromTransport(const char * pData, int nSize)
{
if (m_bInitialStep == 0 && pData[0] == (char)IAC && pData[1] == (char)DO &&
pData[2] == (char)SGAHEAD)
{
if (m_bInitialStep != 0)
return -1; // close connection
m_bInitialStep = 1;
char bufSend[4];
bufSend[0] = (char)IAC;
bufSend[1] = (char)WILL;
bufSend[2] = (char)ECHO;
SendToTransport(bufSend, 3);
return 0;
}
else if (m_bInitialStep == 1 && pData[0] == (char)IAC && pData[1] == (char)DO &&
pData[2] == (char)ECHO)
{
if (m_bInitialStep != 1)
return -1; // close connection
m_bInitialStep = 2;
OnEstablished();
return 0;
}
if (pData[0] == '\t' || ((nSize >= 3 && pData[0] == 0x1b && pData[1] == 0x5b) &&
(pData[2] == 0x41 || // up
pData[2] == 0x42 || // down
pData[2] == 0x43 || // right
pData[2] == 0x44))) // left
{
return 0;
}
else if (pData[0] == '\b')
{
if (m_nCommandBufferedLength > 0)
m_nCommandBufferedLength--;
SendToTransport("\b \b", 3);
return 0;
}
if (m_bInitialStep == 2 && OnInitialReceive(pData, nSize))
m_bInitialStep = 3;
if (m_bInitialStep == 3)
SendToTransport(pData, nSize);
memcpy(m_pCommandBuffer + m_nCommandBufferedLength, pData, nSize);
m_nCommandBufferedLength += nSize;
HString strTemp(pData, nSize);
if (strTemp.Find('\n') > 0)
{
for (int i = m_nCommandBufferedLength - 1; i >= 0; i--)
{
if (m_pCommandBuffer[i] == '\r' || m_pCommandBuffer[i] == '\n')
m_pCommandBuffer[i] = '\0';
}
int nResult = OnReceivedCommand(m_pCommandBuffer);
m_nCommandBufferedLength = 0;
if (nResult >= 0)
SendToTransport("> ", 2);
return nResult;
}
return 0;
}
+70
View File
@@ -0,0 +1,70 @@
#ifndef TELNET_HANDLER__H_
#define TELNET_HANDLER__H_
#ifdef _WIN32
#pragma once
#endif
class HTelnetHandler : public HProtocolHandler
{
public:
enum eCommand
{
SE = 240, // End of subnegotiation parameters.
NOP = 241, // No operation Data mark. Indicates the position of a Synch event within the data stream.
DM = 242, // This should always be accompanied by a TCP urgent notification.
BRK = 243, // Break. Indicates that the "break" or "attention" key was hit.
IP = 244, // Suspend, interrupt or abort the process to which the NVT is connected.
AO = 245, // Abort output. Allows the current process to run to completion but donot send its output to the user.
AYT = 246, // Are you there. Send back to the NVT some visible evidence that the AYT was received.
EC = 247, // Erase character. The receiver should delete the last preceding undeleted character from the data stream.
EL = 248, // Erase line. Delete characters from the data stream back to but not including the previous CRLF.
GA = 249, // Go ahead. Used, under certain circumstances, to tell the other end that it can transmit.
SB = 250, // Subnegotiation of the indicated option follows.
WILL = 251, // Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option.
WONT = 252, // Indicates the refusal to perform, or continue performing, the indicated option.
DO = 253, // Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option.
DONT = 254, // Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option.
IAC = 255 // Interpret as command.
};
enum EOption
{
ECHO = 1, // echo (RFC 857)
SGAHEAD = 3, // suppress go ahead (RFC 858)
STATUS = 5, // status (RFC 859)
TMARK = 6, // timing mark (RFC 860)
TTYPE = 24, // terminal type (RFC 1091)
WSIZE = 31, // window size (RFC 1073)
TSPEED = 32, // terminal speed (RFC 1079)
RFCONTROL = 33, // remote flow control (RFC 1372)
LMODE = 34, // linemode (RFC 1184)
EVARIABLES = 36, // environment variables (RFC 1408)
};
enum
{
MAX_COMMAND_BUFFER_SIZE = 4096
};
HTelnetHandler();
~HTelnetHandler();
protected:
void OnReceivedStatusFromTransport(int nStatus);
int OnReceivedFromTransport(const char * pData, int nSize);
virtual void OnEstablished() {}
virtual bool OnInitialReceive(const char * pData, unsigned nSize) { return true; }
virtual int OnReceivedCommand(const char * pszCommand) = 0;
protected:
char m_pCommandBuffer[MAX_COMMAND_BUFFER_SIZE + 1];
unsigned int m_nCommandBufferedLength;
int m_bInitialStep;
};
#endif // PROTOCOL_HANDLER__H_
+12
View File
@@ -0,0 +1,12 @@
#include "huslib.h"
#include "huslibex.h"
HTelnetServer::HTelnetServer()
{
}
HTelnetServer::~HTelnetServer()
{
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef TELNET_SERVER__H
#define TELNET_SERVER__H
#ifdef _WIN32
#pragma once
#endif
class HTelnetServer : public HTelnetHandler
{
public:
HTelnetServer();
~HTelnetServer();
int OnSendRetryToTransport() { return -1; }
bool OnPrepareReceive() { return true; }
};
#endif // HTTP_HANDLER__H
+453
View File
@@ -0,0 +1,453 @@
#ifndef THREAD__H_
#define THREAD__H_
#ifndef COMMON__H_
#include "common.h"
#endif
#ifdef _WIN32
#pragma once
#else
#include <errno.h>
#include <pthread.h>
//#include <signal.h>
//#define WAIT_NEW_VER_
#endif // WIN32
#ifdef _WIN32
#define pthread_self GetCurrentThreadId
#else
#define GetCurrentThreadId pthread_self
#endif // _WIN32
class HSyncObject : public HObject
{
public:
HSyncObject()
{
#ifdef _WIN32
InitializeCriticalSection(&m_instance);
#else
pthread_mutex_init(&m_instance, NULL);
#endif // _WIN32
}
virtual ~HSyncObject()
{
#ifdef _WIN32
DeleteCriticalSection(&m_instance);
#else
pthread_mutex_destroy(&m_instance);
#endif // _WIN32
}
bool IsLocked();
int Lock();
int Unlock();
protected:
#ifdef _WIN32
CRITICAL_SECTION m_instance;
#else
pthread_mutex_t m_instance;
#endif
};
inline int HSyncObject::Lock()
{
#ifdef _WIN32
EnterCriticalSection(&m_instance);
return 0;
#else
return pthread_mutex_lock(&m_instance);
#endif // WIN32
}
inline int HSyncObject::Unlock()
{
#ifdef _WIN32
LeaveCriticalSection(&m_instance);
return 0;
#else
return pthread_mutex_unlock(&m_instance);
#endif // WIN32
}
///////////////////////////////////////
class HAutoLock : public HObject
{
public:
HAutoLock(HSyncObject * pObject) : m_pObject(pObject) { m_pObject->Lock(); }
~HAutoLock() { m_pObject->Unlock(); }
private:
HSyncObject * m_pObject;
};
class HSyncEvent : public HObject
{
public:
HSyncEvent(bool bManualReset = false, bool bInitialState = false)
{
#ifdef _WIN32
m_hEvent = CreateEvent(NULL, bManualReset, bInitialState, NULL);
#else
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_cond, NULL);
m_bManualReset = bManualReset;
if (bInitialState)
m_bEventSet = true;
#endif // _WIN32
}
~HSyncEvent()
{
#ifdef _WIN32
CloseHandle(m_hEvent);
#else
pthread_cond_destroy(&m_cond);
pthread_mutex_destroy(&m_mutex);
#endif // _WIN32
}
bool SetEvent()
{
#ifdef _WIN32
return ::SetEvent(m_hEvent) != false;
#else
pthread_mutex_lock(&m_mutex);
m_bEventSet = true;
pthread_cond_signal(&m_cond);
pthread_mutex_unlock(&m_mutex);
#endif // _WIN32
return true;
}
bool ResetEvent()
{
#ifdef _WIN32
return ::ResetEvent(m_hEvent) != false;
#else
pthread_mutex_lock(&m_mutex);
m_bEventSet = false;
pthread_mutex_unlock(&m_mutex);
#endif // _WIN32
return true;
}
bool Wait(DWORD dwWaitTime) // dwTimeout : msec
{
#ifdef _WIN32
if (WaitForSingleObject(m_hEvent, dwWaitTime) == WAIT_TIMEOUT)
return false;
#else
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
return true;
ts.tv_sec += dwWaitTime / 1000; // seconds
ts.tv_nsec += (dwWaitTime % 1000) * 1000000; // nanoseconds
pthread_mutex_lock(&m_mutex);
if (m_bEventSet)
{
pthread_mutex_unlock(&m_mutex);
if (m_bManualReset == false)
m_bEventSet = false;
return true;
}
int nResult = pthread_cond_timedwait(&m_cond, &m_mutex, &ts);
pthread_mutex_unlock(&m_mutex);
if (nResult == ETIMEDOUT)
return false;
if (m_bManualReset == false)
m_bEventSet = false;
#endif // _WIN32
return true;
}
private:
#ifdef _WIN32
HANDLE m_hEvent;
#else
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
bool m_bManualReset;
volatile bool m_bEventSet;
#endif // _WIN32
};
class HThread : public HObject
{
public:
HThread(bool bAutoDelete = false, size_t nStackSize = 0)
: m_bAutoDelete(bAutoDelete)
, m_nStackSize(nStackSize)
{
#ifdef _WIN32
m_hThread = NULL;
#else
m_tId = 0;
#ifndef WAIT_NEW_VER_
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_cond, NULL);
#endif
#endif // WIN32
}
~HThread() {}
#ifdef _WIN32
inline HANDLE GetThreadId() { return m_hThread; }
#else
inline pthread_t GetThreadId() { return m_tId; }
#endif
virtual inline unsigned long Begin();
bool WaitForTermination(DWORD dwWaitTime)
{
#ifdef _WIN32
if (m_hThread == NULL)
return true;
if (WaitForSingleObject(m_hThread, dwWaitTime) == WAIT_TIMEOUT)
return false;
#else
if (m_tId == 0)
return true;
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
return true;
ts.tv_sec += dwWaitTime / 1000; // seconds
ts.tv_nsec += (dwWaitTime % 1000) * 1000000; // nanoseconds
#ifndef WAIT_NEW_VER_
pthread_mutex_lock(&m_mutex);
int nResult = pthread_cond_timedwait(&m_cond, &m_mutex, &ts);
pthread_mutex_unlock(&m_mutex);
if (nResult == ETIMEDOUT)
return false;
#else
if (pthread_timedjoin_np(m_tId, NULL, &ts) == ETIMEDOUT)
return false;
#endif // WAIT_NEW_VER_
#endif // WIN32
return true;
}
#if !defined(__ANDROID__) && !defined(ANDROID)
void TerminateThread(DWORD dwExitCode = 0)
{
#ifdef _WIN32
if (m_hThread == NULL)
return;
::TerminateThread(m_hThread, dwExitCode);
CloseHandle(m_hThread);
m_hThread = NULL;
#else
if (m_tId == 0)
return;
pthread_cancel(m_tId);
m_tId = 0;
#endif
}
#endif //
protected:
virtual void Main() = 0;
virtual void OnTerminated() {}
#ifdef _WIN32
inline static DWORD WINAPI
#else
inline static void *
#endif
BeginThread(void * lpParameter);
private:
void MainCallBack();
private:
bool m_bAutoDelete;
size_t m_nStackSize; // bytes
#ifdef _WIN32
HANDLE m_hThread;
#else
pthread_t m_tId;
#ifndef WAIT_NEW_VER_
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
#endif
#endif
};
inline unsigned long HThread::Begin()
{
#ifdef _WIN32
DWORD dwThreadId;
if ((m_hThread = ::CreateThread(NULL, m_nStackSize, BeginThread, this, 0, &dwThreadId)) == NULL)
return ::GetLastError();
return 0;
#else
if (m_nStackSize > 0)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, m_nStackSize);
#if 0 // do not use
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
#endif
int nResult = pthread_create(&m_tId, &attr, BeginThread, (void *)this);
pthread_attr_destroy(&attr);
return nResult;
}
return pthread_create(&m_tId, NULL, BeginThread, (void *)this);
#endif // WIN32
}
#ifdef _WIN32
inline DWORD WINAPI
#else
inline void *
#endif
HThread::BeginThread(void * lpParameter)
{
((HThread *)lpParameter)->MainCallBack();
return NULL;
}
inline void HThread::MainCallBack()
{
Main();
#ifndef _WIN32
#ifndef WAIT_NEW_VER_
pthread_mutex_lock(&m_mutex);
pthread_cond_broadcast(&m_cond);
pthread_mutex_unlock(&m_mutex);
#endif // WAIT_NEW_VER_
pthread_detach(m_tId);
#endif
OnTerminated();
if (m_bAutoDelete)
delete this;
}
///////////////////////////////////////
class HThreadExecuter : public HThread
{
public:
HThreadExecuter()
{
m_fnThreadMainCallBack = NULL;
m_pThreadMainParam = NULL;
m_fnExitThreadCallBack = NULL;
m_pOnExitThreadParam = NULL;
}
HThreadExecuter(bool bAutoDelete, size_t nStackSize) : HThread(bAutoDelete, nStackSize)
{
m_fnThreadMainCallBack = NULL;
m_pThreadMainParam = NULL;
m_fnExitThreadCallBack = NULL;
m_pOnExitThreadParam = NULL;
}
~HThreadExecuter()
{
m_fnThreadMainCallBack = NULL;
m_pThreadMainParam = NULL;
m_fnExitThreadCallBack = NULL;
m_pOnExitThreadParam = NULL;
}
inline void Initialize(void (*fnThreadMainCallBack)(void * pThreadParameter), // thread main procedure
void * pThreadMainParam, // parmeter for thread main
void (*fnExitThreadCallBack)(void * pThreadParameter), // terminated thread call back
void * pOnExitThreadParam) // parmeter for terminated thread
{
m_fnThreadMainCallBack = fnThreadMainCallBack;
m_pThreadMainParam = pThreadMainParam;
m_fnExitThreadCallBack = fnExitThreadCallBack;
m_pOnExitThreadParam = pOnExitThreadParam;
}
protected:
inline void Main()
{
if (m_fnThreadMainCallBack)
m_fnThreadMainCallBack(m_pThreadMainParam);
}
inline void OnTerminated()
{
if (m_fnExitThreadCallBack)
m_fnExitThreadCallBack(m_pOnExitThreadParam);
}
protected:
void (*m_fnThreadMainCallBack)(void * pThreadParameter);
void * m_pThreadMainParam;
void (*m_fnExitThreadCallBack)(void * pThreadParameter);
void * m_pOnExitThreadParam;
};
/*
<below add to .h file>
protected:
// $(Name) thread part
static inline void $(Name)ThreadCallBack(void * pParam) { return static_cast<$(ClassName) *>(pParam)->$(Name)ThreadMain(); }
static inline void $(Name)ThreadTerminatedCallBack(void * pParam) { static_cast<$(ClassName) *>(pParam)->On$(Name)ThreadTerminated(); }
void $(Name)ThreadMain();
void On$(Name)ThreadTerminated();
HThreadExecuter * m_p$(Name)Thread;
//
<add to constructor>
m_p$(Name)Thread = new HThreadExecuter();
m_p$(Name)Thread->Initialize($(Name)ThreadCallBack, this, $(Name)ThreadTerminatedCallBack, this);
m_p$(Name)Thread->Begin();
<add to destructor or termination code>
delete m_p$(Name)Thread;
*/
#endif // THREAD__H_
+200
View File
@@ -0,0 +1,200 @@
#include "Common.h"
#include "Object.h"
#include "Thread.h"
#include "Timer.h"
HTimer g_timerGlobal;
HTimer::HTimer()
: HThread(false, 1024 * 128) // default stack size : 128kb
{
m_bThreadStarted = false;
m_bTerminate = false;
struct tm * tmTmp;
struct timeb tTimeb;
ftime(&tTimeb);
tmTmp = localtime(&tTimeb.time);
m_systemTime.wYear = tmTmp->tm_year + 1900;
m_systemTime.wMonth = tmTmp->tm_mon + 1;
m_systemTime.wDay = tmTmp->tm_mday;
m_systemTime.wHour = tmTmp->tm_hour;
m_systemTime.wMinute = tmTmp->tm_min;
m_systemTime.wSecond = tmTmp->tm_sec;
m_systemTime.wMilliseconds = tTimeb.millitm;
m_nTickCount = ::GetTickCount();
Begin(); // start timer thread
while (m_bThreadStarted == false) // wait for thread started
Sleep(10);
}
HTimer::~HTimer()
{
RemoveAllTimer();
}
void HTimer::GetSystemTime(PSYSTEMTIME pSystemTime)
{
#ifndef SINGLE_THREADED_MODEL
m_syncSystemTime.Lock();
#endif
memcpy(pSystemTime, (void *)&m_systemTime, sizeof(SYSTEMTIME));
#ifndef SINGLE_THREADED_MODEL
m_syncSystemTime.Unlock();
#endif
}
bool HTimer::SetTimer(unsigned int nTimerID, unsigned int nElapse, void (*fnCallBack)(unsigned int, void *), void * pParam)
{
struct HTimerObject * pTimerObject = new struct HTimerObject;
pTimerObject->nTimerID = nTimerID;
pTimerObject->nElapse = nElapse;
pTimerObject->dwLastCheckTime = m_nTickCount;
pTimerObject->bDelete = false;
pTimerObject->fnOnTimerCallBack = fnCallBack;
pTimerObject->pOnTimerCallBackParam = pParam;
#ifndef SINGLE_THREADED_MODEL
// m_sync.Lock();
#endif
m_listTimer.push_front(pTimerObject);
#ifndef SINGLE_THREADED_MODEL
// m_sync.Unlock();
#endif
return true;
}
bool HTimer::KillTimer(unsigned int nTimerID)
{
struct HTimerObject * pTimerObject;
#ifndef SINGLE_THREADED_MODEL
// m_sync.Lock();
#endif
for(LIST_TIMER_OBJECT::iterator iter = m_listTimer.begin();
iter != m_listTimer.end(); iter++)
{
pTimerObject = *iter;
if (pTimerObject->nTimerID == nTimerID)
{
#if 0
delete pTimerObject;
m_listTimer.erase(iter);
#else
pTimerObject->bDelete = true;
#endif
#ifndef SINGLE_THREADED_MODEL
// m_sync.Unlock();
#endif
return true;
}
}
#ifndef SINGLE_THREADED_MODEL
// m_sync.Unlock();
#endif
return false;
}
void HTimer::RemoveAllTimer()
{
#ifndef SINGLE_THREADED_MODEL
// m_sync.Lock();
#endif
struct HTimerObject * pTimerObject;
for(LIST_TIMER_OBJECT::iterator iter = m_listTimer.begin();
iter != m_listTimer.end(); iter++)
{
pTimerObject = *iter;
delete pTimerObject;
}
m_listTimer.clear();
#ifndef SINGLE_THREADED_MODEL
// m_sync.Unlock();
#endif
}
void HTimer::Main()
{
m_bThreadStarted = true;
struct tm * tmTmp;
struct timeb tTimeb;
struct HTimerObject * pTimerObject;
while (m_bTerminate == false)
{
Sleep(HTIMER_INTERVAL_TIME);
#ifndef SINGLE_THREADED_MODEL
// m_sync.Lock();
#endif
for(LIST_TIMER_OBJECT::iterator iter = m_listTimer.begin();
iter != m_listTimer.end(); iter++)
{
pTimerObject = *iter;
if (pTimerObject->bDelete)
{
delete pTimerObject;
iter = m_listTimer.erase(iter);
if (iter == m_listTimer.end())
break;
}
else if (pTimerObject->nElapse <= TimeDiff(pTimerObject->dwLastCheckTime, m_nTickCount))
{
if (pTimerObject->fnOnTimerCallBack)
pTimerObject->fnOnTimerCallBack(pTimerObject->nTimerID, pTimerObject->pOnTimerCallBackParam);
pTimerObject->dwLastCheckTime = m_nTickCount;
}
}
#ifndef SINGLE_THREADED_MODEL
// m_sync.Unlock();
#endif
ftime(&tTimeb);
tmTmp = localtime(&tTimeb.time);
#ifndef SINGLE_THREADED_MODEL
m_syncSystemTime.Lock();
#endif
m_systemTime.wYear = tmTmp->tm_year + 1900;
m_systemTime.wMonth = tmTmp->tm_mon + 1;
m_systemTime.wDay = tmTmp->tm_mday;
m_systemTime.wHour = tmTmp->tm_hour;
m_systemTime.wMinute = tmTmp->tm_min;
m_systemTime.wSecond = tmTmp->tm_sec;
m_systemTime.wMilliseconds = tTimeb.millitm;
#ifndef SINGLE_THREADED_MODEL
m_syncSystemTime.Unlock();
#endif
m_nTickCount = ::GetTickCount();
}
}
+74
View File
@@ -0,0 +1,74 @@
#ifndef TIMER__H_
#define TIMER__H_
#ifdef _WIN32
#pragma once
#endif
#include <list>
#define HTIMER_INTERVAL_TIME 100 // 100 ms
#define HTIMER_TERMINATE_WAIT_TIME 300 // 300 ms
#define HTIMER() (&g_timerGlobal)
#define ON_TIMER(CLASS_NAME, FN_CALLBACK) \
inline bool SetTimer(unsigned int nTimerID, unsigned int nElapse) { return HTIMER()->SetTimer(nTimerID, nElapse, TimerCallBack##FN_CALLBACK, this); } \
inline bool KillTimer(unsigned int nTimerID) { return HTIMER()->KillTimer(nTimerID); } \
static void TimerCallBack##FN_CALLBACK(unsigned int nTimerID, void * pParam) { static_cast<CLASS_NAME *>(pParam)->FN_CALLBACK(nTimerID); } \
void FN_CALLBACK(unsigned int nTimerID);
struct HTimerObject
{
unsigned int nTimerID;
unsigned int nElapse;
unsigned int dwLastCheckTime;
bool bDelete;
void (*fnOnTimerCallBack)(unsigned int, void *);
void * pOnTimerCallBackParam;
};
typedef std::list<struct HTimerObject *> LIST_TIMER_OBJECT;
class HTimer : public HThread
{
public:
HTimer();
~HTimer();
inline void Terminate() { m_bTerminate = true; Sleep(HTIMER_TERMINATE_WAIT_TIME); }
void GetSystemTime(PSYSTEMTIME pSystemTime);
inline unsigned int GetTickCount() { return m_nTickCount; }
LIST_TIMER_OBJECT * GetTimerList() { return &m_listTimer; }
bool SetTimer(unsigned int nTimerID, unsigned int nElapse, void (*fnCallBack)(unsigned int, void *), void * pParam);
bool KillTimer(unsigned int nTimerID);
void RemoveAllTimer();
protected:
void Main();
private:
volatile bool m_bThreadStarted;
volatile bool m_bTerminate;
#ifndef SINGLE_THREADED_MODEL
HSyncObject m_sync;
HSyncObject m_syncSystemTime;
#endif
volatile SYSTEMTIME m_systemTime;
volatile DWORD m_nTickCount;
LIST_TIMER_OBJECT m_listTimer;
};
extern HTimer g_timerGlobal;
#endif // TIMER__H_
+182
View File
@@ -0,0 +1,182 @@
#include "huslib.h"
#include "huslibex.h"
HVspHandler::HVspHandler()
{
m_pRecvBuffer = new HStreamBuffer(HH_VSP_MAX_COMMAND_PACKET_SIZE);
m_nBodyOffset = -1;
m_nBodySize = -1;
m_nRemainBodySize = -1;
m_pSendBuffer = new HStreamBuffer(HH_VSP_MAX_COMMAND_PACKET_SIZE);
}
HVspHandler::~HVspHandler()
{
delete m_pRecvBuffer;
delete m_pSendBuffer;
}
int HVspHandler::SendCommand(const HString & strCommand)
{
if (m_pSendBuffer->RemainSize() < strCommand.GetLength() + 5)
return -1;
size_t nLength = sprintf(m_pSendBuffer->Tail(), "VSP %d %s", strCommand.GetLength(), strCommand.psz());
m_pSendBuffer->MoveTail(nLength);
return SendBufferCommand();
}
int HVspHandler::SendBinary(const char * pData, size_t nSize)
{
if (m_pSendBuffer->StoredSize() == 0)
{
int nSentSize = SendToTransport(pData, nSize);
if (nSentSize < 0)
return -1;
if (nSentSize != nSize)
m_pSendBuffer->Store(pData + nSentSize, nSize - nSentSize);
return nSentSize;
}
m_pSendBuffer->Store(pData, nSize);
return SendBufferCommand();
}
int HVspHandler::SendBufferCommand()
{
//if (m_pSendBuffer->StoredSize() == 0)
// return SOCKET_ERROR;
int nSentSize = SendToTransport(m_pSendBuffer->Head(), m_pSendBuffer->StoredSize());
if (nSentSize <= 0)
return nSentSize;
m_pSendBuffer->Pop(nSentSize);
return nSentSize;
}
void HVspHandler::OnReceivedStatusFromTransport(int nStatus)
{
if (nStatus == HTransport::T_BEGIN_TRANSPORT)
{
OnInitialize(true);
}
else if (nStatus == HTransport::T_FAILED_BEGIN)
{
OnInitialize(false);
}
else if (nStatus == HTransport::T_END_TRANSPORT)
{
OnTerminate();
}
}
int HVspHandler::OnReceivedFromTransport(const char * pData, int nSize)
{
if (m_pRecvBuffer->Store(pData, nSize) == false)
{
HLOGF(HLOG_ERROR, "[ERROR], VspHdler, Failed to insert data, buffer = %d, stored = %d, recv size = %d\n", m_pRecvBuffer->Size(), m_pRecvBuffer->StoredSize(), nSize);
return -1; // close connection
}
if (m_nRemainBodySize > 0)
{
int nResult = ProcPacketBodyReceive();
if (nResult < 0)
return -1; // close connection
else if (nResult == 0)
return 0;
}
for (;;)
{
if (m_pRecvBuffer->StoredSize() < 6)
return 0;
// verify protocol name
if (m_pRecvBuffer->MemCmp("VSP ", 4) != 0)
{
HLOGF(HLOG_WARNING, "[WARN], VspHdler, Invalid VSP protocol, buffer = %d, stored = %d, recv size = %d\n", m_pRecvBuffer->Size(), m_pRecvBuffer->StoredSize(), nSize);
HLOGD(HLOG_WARNING, m_pRecvBuffer->Head(), m_pRecvBuffer->StoredSize(), false);
return -1; // close connection
}
// extract body size
m_nBodyOffset = m_pRecvBuffer->Find(' ', 4);
if (m_nBodyOffset < 0)
return 0; // receive remain packet
if (m_nBodyOffset > 13) // 9 + 4
{
HLOGF(HLOG_WARNING, "[WARN], VspHdler, Invalid VSP body size, buffer = %d, stored = %d, recv size = %d\n", m_pRecvBuffer->Size(), m_pRecvBuffer->StoredSize(), nSize);
HLOGD(HLOG_WARNING, m_pRecvBuffer->Head(), m_pRecvBuffer->StoredSize(), false);
return -1; // close connection
}
HString strBodySize(m_pRecvBuffer->Head() + 4, m_nBodyOffset - 4);
m_nBodySize = strBodySize;
m_nBodyOffset++;
//if (m_nBodySize + nPos > HH_VSP_MAX_COMMAND_PACKET_SIZE)
//{
//... extra size packet
//}
int nResult = ProcPacketBodyReceive();
if (nResult < 0)
return -1;
else if (nResult == 0)
return 0;
}
return -1; // close connection
}
int HVspHandler::ProcPacketBodyReceive()
{
int nResult = 0;
m_nRemainBodySize = m_nBodySize - (m_pRecvBuffer->StoredSize() - m_nBodyOffset);
if (m_nRemainBodySize <= 0)
{
nResult = OnReceivedCommand(m_pRecvBuffer->Head() + m_nBodyOffset, m_nBodySize);
if (nResult < 0)
return -1;
if (m_nRemainBodySize < 0)
nResult = 1;
else
nResult = 0;
m_pRecvBuffer->PopAndRewind(m_nBodyOffset + m_nBodySize);
m_nBodyOffset = -1;
m_nBodySize = -1;
m_nRemainBodySize = -1;
}
return nResult;
}
int HVspHandler::OnSendRetryToTransport()
{
return SendBufferCommand();
}
bool HVspHandler::OnPrepareReceive()
{
if (m_pRecvBuffer->RemainSize() < g_nSocketReceiveBlockSize)
return false;
return true;
}
+59
View File
@@ -0,0 +1,59 @@
#ifndef VSP_HANDLER__H_
#define VSP_HANDLER__H_
#ifdef _WIN32
#pragma once
#endif
#define EXTRACT_NEXT_PARAM(VALIABLE, NEXT, SIZE, OFFSET) \
if ((OFFSET = VALIABLE.Tokenize(NEXT, SIZE, ' ')) <= 1) { \
if (SIZE > 0) { VALIABLE.Assign(NEXT, SIZE); OFFSET = SIZE; } \
else { HLOGF(HLOG_ERROR, "[ERROR], Invalid param, %s\n", NEXT); \
return -1; } } \
NEXT += OFFSET; SIZE -= OFFSET;
class HVspHandler : public HProtocolHandler
{
public:
enum
{
//HH_VSP_MAX_COMMAND_PACKET_SIZE = 8192
HH_VSP_MAX_COMMAND_PACKET_SIZE = 65536
};
HVspHandler();
~HVspHandler();
int SendCommand(const HString & strCommand);
int SendBinary(const char * pData, size_t nSize);
protected:
int SendBufferCommand();
void OnReceivedStatusFromTransport(int nStatus);
int OnReceivedFromTransport(const char * pData, int nSize);
int ProcPacketBodyReceive();
int OnSendRetryToTransport();
bool OnPrepareReceive();
virtual void OnInitialize(bool bIsSuccess) = 0;
virtual void OnTerminate() = 0;
virtual int OnReceivedCommand(const char * pPacket, int nSize) = 0;
protected:
HStreamBuffer * m_pRecvBuffer;
int m_nBodyOffset;
long m_nBodySize;
long m_nRemainBodySize;
HStreamBuffer * m_pSendBuffer;
};
#endif // REDUNDANCY__H_
+206
View File
@@ -0,0 +1,206 @@
#include "huslib.h"
#include "huslibex.h"
#define ARRAYCOUNT(array) ((unsigned)(sizeof(array)/sizeof(array[0])))
static struct {
const char * pszExtention;
const char * pszContentType;
} ContentTypeTab[] = {
{ ".htm", "text/html" },
{ ".html", "text/html" },
{ ".asp", "text/html" },
{ ".php", "text/html" },
{ ".jsp", "text/html" },
{ ".css", "text/css" },
{ ".js", "application/x-javascript" },
{ ".txt", "text/plain" },
{ ".ini", "text/plain" },
{ ".gif", "image/gif" },
{ ".jpg", "image/jpeg" },
{ ".png", "image/png" },
{ ".bmp", "image/bmp" },
{ ".swf", "application/x-shockwave-flash" },
{ ".zip", "application/zip" }
};
HWebServer::HWebServer()
{
m_pszResponse = (char *)malloc(g_nMaxHsHeaderSize);
m_pszResponseOffset = m_pszResponse;
m_nResponseRemainSize = 0;
m_pFileBuffer = (char *)malloc(WS_READ_BYTES + 1);
m_pFileBufferOffset = m_pFileBuffer;
m_nRemainBufferSize = 0;
}
HWebServer::~HWebServer()
{
free(m_pszResponse);
free(m_pFileBuffer);
}
const char * HWebServer::GetContentType(const char * pszRequestUri)
{
for (unsigned i = 0; i < ARRAYCOUNT(ContentTypeTab); i++)
{
if (stristr(pszRequestUri, ContentTypeTab[i].pszExtention))
return ContentTypeTab[i].pszContentType;
}
return "application/octet-stream";
}
void HWebServer::AddStaticDir(const char * pszDir)
{
m_listStaticDir.push_back(pszDir);
}
int HWebServer::SendResponse()
{
int nSentSize = SendToTransport(m_pszResponseOffset, m_nResponseRemainSize);
if (nSentSize <= 0)
return nSentSize; // -1 : shutdown, 0 : buffering because of wouldblock
else if (nSentSize < m_nResponseRemainSize)
{
m_pszResponseOffset += nSentSize;
m_nResponseRemainSize -= nSentSize;
return 0; // buffering because of wouldblock
}
return -1; // shutdown
}
int HWebServer::SendFileHeader()
{
int nSentSize = SendToTransport(m_pFileBufferOffset, m_nRemainBufferSize);
if (nSentSize <= 0)
return nSentSize; // -1 : shutdown, 0 : buffering because of wouldblock
else if (nSentSize < m_nRemainBufferSize)
{
m_pFileBufferOffset += nSentSize;
m_nRemainBufferSize -= nSentSize;
return 0; // buffering because of wouldblock
}
return 1; // continue
}
int HWebServer::SendOpenedFile()
{
int nSendSize;
int nSentSize;
int nReadSize = WS_READ_BYTES;
while (m_nFileSize > 0)
{
while (m_nRemainBufferSize)
{
if (m_nRemainBufferSize > (long)g_nSocketSendingBlockSize)
nSendSize = g_nSocketSendingBlockSize;
else
nSendSize = m_nRemainBufferSize;
nSentSize = SendToTransport(m_pFileBufferOffset, nSendSize);
if (nSentSize <= 0)
return nSentSize; // -1 : shutdown, 0 : buffering because of wouldblock
m_pFileBufferOffset += nSentSize;
m_nRemainBufferSize -= nSentSize;
if (nSentSize < nSendSize)
return 0;
}
if (nReadSize < WS_READ_BYTES)
break;
if ((nReadSize = m_file.Read(m_pFileBuffer, WS_READ_BYTES)) <= 0)
break;
m_pFileBufferOffset = m_pFileBuffer;
m_nRemainBufferSize = nReadSize;
}
m_file.Close();
m_pFileBufferOffset = m_pFileBuffer;
m_nRemainBufferSize = 0;
return -1;
}
int HWebServer::OnSendRetryToTransport()
{
if (m_nResponseRemainSize > 0)
return SendResponse();
return SendOpenedFile();
}
int HWebServer::OnPacketProcessing(const char * pBodyData, int nBodySize)
{
int nResult = OnPrepareRequest(pBodyData, nBodySize);
if (nResult <= 0)
return nResult;
nResult = OnReceivedRequest(pBodyData, nBodySize);
if (nResult <= 0)
return nResult;
HDynamicArray<char> darrNewPath(strlen(m_pHttpParser->GetRequestUri()) + 1);
RealignPathDepth(m_pHttpParser->GetRequestUri(), darrNewPath.m_p);
int nCopySize = 0;
const char * pOffset = strchr(darrNewPath.m_p, '?');
if (pOffset)
nCopySize = pOffset - darrNewPath.m_p;
else
nCopySize = strlen(darrNewPath.m_p);
size_t nPathLength = m_strHomeDir.GetLength() + nCopySize;
if (nPathLength > (size_t)g_nMaxPathNameLength)
{
m_nResponseRemainSize = MakeResponse(m_pszResponse, "400 Bad Request", "<html><body>400 Bad Request</body></html>");
return SendResponse();
}
HString strCopyPath = darrNewPath.m_p;
HString strLastPath = strCopyPath.SubStr(0, nCopySize);
if (strLastPath == "/")
strLastPath = "/index.htm";
HString strPathName = m_strHomeDir;
strPathName += strLastPath;
if (m_file.Open(strPathName, HFile::FMODE_RDONLY))
{
m_nFileSize = HFile::GetSize(strPathName);
m_nRemainBufferSize = Make200Header(m_pFileBufferOffset, GetContentType(strPathName), m_nFileSize);
int nResult = SendFileHeader();
if (nResult <= 0)
return nResult;
m_nRemainBufferSize = 0;
return SendOpenedFile();
}
// 404 Not found
m_nResponseRemainSize = MakeResponse(m_pszResponse, "404 Not found", "<html><body>404 Not found</body></html>");
return SendResponse();
}
bool HWebServer::IsStaticRequest()
{
for (HStrList::iterator iter = m_listStaticDir.begin(); iter != m_listStaticDir.end(); iter++)
{
if (iter->StrNICmp(m_pHttpParser->GetRequestUri(), iter->GetLength()) == 0)
return true;
}
return false;
}
+54
View File
@@ -0,0 +1,54 @@
#ifndef WEB_SERVER__H_
#define WEB_SERVER__H_
#ifdef _WIN32
#pragma once
#endif
class HWebServer : public HHttpHandler
{
public:
enum
{
WS_READ_BYTES = (256 * 1024 - 1) // 256Kbyte
};
HWebServer();
~HWebServer();
inline void SetHomeDir(const char * pszDir) { m_strHomeDir = pszDir; }
const char * GetContentType(const char * pszRequestUri);
void AddStaticDir(const char * pszDir);
protected:
int SendResponse();
int SendFileHeader();
int SendOpenedFile();
int OnSendRetryToTransport();
int OnPacketProcessing(const char * pBodyData, int nBodySize);
virtual int OnPrepareRequest(const char * pBodyData, int nBodySize) { return 1; }
virtual int OnReceivedRequest(const char * pBodyData, int nBodySize) { return -1; }
bool IsStaticRequest();
protected:
HString m_strHomeDir;
HStrList m_listStaticDir;
char * m_pszResponse;
char * m_pszResponseOffset;
int m_nResponseRemainSize;
HFile m_file;
off_t m_nFileSize;
char * m_pFileBuffer;
char * m_pFileBufferOffset;
long m_nRemainBufferSize;
};
#endif // WEB_SERVER__H_
+65
View File
@@ -0,0 +1,65 @@
#ifndef ZLIB_EX__H_
#define ZLIB_EX__H_
#ifdef _WIN32
#pragma once
#endif
#include "zlib.h"
#ifdef _WIN32
#pragma comment(lib, "zlib.lib")
#endif
extern inline bool Gunzip(const char * pSrc, unsigned long nSrcSize, HDynamicArray<char> * pdaDst, unsigned long * pnDstSize)
{
if (nSrcSize == 0)
return false;
unsigned full_length = nSrcSize;
unsigned half_length = nSrcSize / 2;
unsigned uncompLength = full_length;
pdaDst->m_p = (char *)malloc(uncompLength + 8); // 8 : safety space for post process
z_stream strm;
strm.next_in = (Bytef *)pSrc;
strm.avail_in = nSrcSize;
strm.total_out = 0;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
bool done = false ;
if (inflateInit2(&strm, (16+MAX_WBITS)) != Z_OK)
return false;
while (!done)
{
if (strm.total_out >= uncompLength)
{
char * uncomp2 = (char *)malloc(uncompLength + half_length + 8); // 8 : safety space for post process
memcpy(uncomp2, pdaDst->m_p, uncompLength);
uncompLength += half_length;
pdaDst->Restruct(uncomp2);
}
strm.next_out = (Bytef *) (pdaDst->m_p + strm.total_out);
strm.avail_out = uncompLength - strm.total_out;
int err = inflate(&strm, Z_SYNC_FLUSH);
if (err == Z_STREAM_END)
done = true;
else if (err != Z_OK)
break;
}
if (inflateEnd(&strm) != Z_OK)
return false;
*pnDstSize = strm.total_out;
return true ;
}
#endif // ZLIB_EX__H_
+551
View File
@@ -0,0 +1,551 @@
#include "stringex.h"
#include "hsparser.h"
#include <time.h>
#include <sys/timeb.h>
static char * SliceHeader(char * pszBuffer)
{
for (unsigned int i = 0; pszBuffer[i]; i++)
{
if (pszBuffer[i] == '\r' && pszBuffer[i + 1] == '\n')
{
pszBuffer[i] = '\0';
return (pszBuffer + i + 2);
}
else if (pszBuffer[i] == '\n')
{
pszBuffer[i] = '\0';
return (pszBuffer + i + 1);
}
}
return NULL;
}
static char * SliceToken(char * pszLine, char cDelimiter)
{
for (unsigned int i = 0; pszLine[i]; i++)
{
if (pszLine[i] == cDelimiter)
{
pszLine[i] = '\0';
return (pszLine + i + 1);
}
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////////
char * HHsParser::SearchBodyPtr(char * pData, unsigned int nSize)
{
for (unsigned int i = 0; i < nSize; i++)
{
if (pData[i] == '\r' && pData[i + 1] == '\n' && pData[i + 2] == '\r' && pData[i + 3] == '\n')
return (pData + i + 4);
else if (pData[i] == '\n' && pData[i + 1] == '\n')
return (pData + i + 2);
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////////
HHsHeaderElement::HHsHeaderElement(const char * pszName, bool bNameMewMemory, const char * pszValue, bool bValueNewMemory)
{
m_bNameNewMemory = bNameMewMemory;
m_bValueNewMemory = bValueNewMemory;
m_nNameLength = strlen(pszName);
m_nValueLength = strlen(pszValue);
if (bNameMewMemory)
{
m_pszName = (char *)malloc(m_nNameLength + 1);
strcpy(m_pszName, pszName);
}
else
{
m_pszName = (char *)pszName;
}
if (bValueNewMemory)
{
m_pszValue = (char *)malloc(m_nValueLength + 1);
strcpy(m_pszValue, pszValue);
}
else
{
m_pszValue = (char *)pszValue;
}
m_pNext = NULL;
}
HHsHeaderElement::~HHsHeaderElement()
{
if (m_bNameNewMemory)
free(m_pszName);
if (m_bValueNewMemory)
free(m_pszValue);
}
//////////////////////////////////////////////////////////////////////////////
HHsParser::HHsParser(const char * pszProtocolName)
{
strcpy(m_szProtocolName, pszProtocolName);
m_nProtocolNameLength = strlen(pszProtocolName);
m_pszMethod = NULL;
m_pszRequestUri = NULL;
m_bRequestUriNewMemory = false;
m_pszVersion = NULL;
m_nStatusCode = -1;
m_pszReasonPhrase = NULL;
m_bReasonPhraseNewMemory = false;
m_pElementHead = NULL;
m_pElementRear = NULL;
m_nHeaderSize = 0;
m_nContentLength = 0;
m_pBody = NULL;
m_bBodyNewMemory = false;
m_nBodySize = 0;
}
HHsParser::~HHsParser()
{
if (m_bRequestUriNewMemory)
free(m_pszRequestUri);
if (m_bReasonPhraseNewMemory)
free(m_pszReasonPhrase);
if (m_pElementHead)
{
HHsHeaderElement * pTemp;
HHsHeaderElement * pNext = m_pElementHead;
do
{
pTemp = pNext;
pNext = pNext->m_pNext;
delete pTemp;
} while (pNext != NULL);
}
if (m_bBodyNewMemory)
free(m_pBody);
}
void HHsParser::SetRequestUri(const char * pszRequestUri)
{
size_t oldLen = strlen(m_pszRequestUri);
size_t newLen = strlen(pszRequestUri);
if (newLen > oldLen)
{
if (m_bRequestUriNewMemory)
free(m_pszRequestUri);
else
m_bRequestUriNewMemory = true;
m_pszRequestUri = (char *)malloc(newLen + 1);
}
strcpy(m_pszRequestUri, pszRequestUri);
m_nHeaderSize += (newLen - oldLen);
}
void HHsParser::SetVersion(const char * pszVersion)
{
strcpy(m_pszVersion, pszVersion); //...
}
void HHsParser::SetReasonPhrase(const char * pszReasonPhrase)
{
size_t oldLen = strlen(m_pszReasonPhrase);
size_t newLen = strlen(pszReasonPhrase);
if (newLen > oldLen)
{
if (m_bReasonPhraseNewMemory)
free(m_pszReasonPhrase);
else
m_bReasonPhraseNewMemory = true;
m_pszReasonPhrase = (char *)malloc(newLen + 1);
}
strcpy(m_pszReasonPhrase, pszReasonPhrase);
m_nHeaderSize += (newLen - oldLen);
}
void HHsParser::SetBody(char * pData, unsigned int nSize)
{
if (nSize > m_nBodySize)
{
if (m_bBodyNewMemory)
free(m_pBody);
else
m_bBodyNewMemory = true;
m_pBody = (char *)malloc(nSize + 1);
}
memcpy(m_pBody, pData, nSize);
m_pBody[nSize] = '\0';
m_nBodySize = nSize;
}
HHsHeaderElement * HHsParser::GetHeaderElement(const char * pszHeaderName, int nIndex)
{
int i = 0;
for (HHsHeaderElement * pNext = m_pElementHead; pNext != NULL; pNext = pNext->m_pNext)
{
if (stricmp(pszHeaderName, pNext->m_pszName) == 0)
{
if (nIndex != i++)
continue;
return pNext;
}
}
return NULL;
}
const char * HHsParser::GetHeaderValue(const char * pszHeaderName, int nIndex)
{
int i = 0;
for (HHsHeaderElement * pNext = m_pElementHead; pNext != NULL; pNext = pNext->m_pNext)
{
if (stricmp(pszHeaderName, pNext->m_pszName) == 0)
{
if (nIndex != i++)
continue;
return pNext->m_pszValue;
}
}
return NULL;
}
bool HHsParser::AddHeader(const char * pszHeaderName, const char * pszHeaderValue)
{
HHsHeaderElement * pElement = new HHsHeaderElement(pszHeaderName, true, pszHeaderValue, true);
if (m_pElementHead == NULL)
m_pElementHead = pElement;
if (m_pElementRear)
m_pElementRear->m_pNext = pElement;
m_pElementRear = pElement;
m_nHeaderSize += (pElement->m_nNameLength + pElement->m_nValueLength + 4); // 4 = ": " + "\r\n"
return true;
}
bool HHsParser::SetHeader(const char * pszHeaderName, const char * pszHeaderValue, int nIndex)
{
HHsHeaderElement * pFindElement = GetHeaderElement(pszHeaderName, nIndex);
if (pFindElement)
{
size_t newLen = strlen(pszHeaderValue);
if (newLen > pFindElement->m_nValueLength)
{
if (pFindElement->m_bValueNewMemory)
free(pFindElement->m_pszValue);
else
pFindElement->m_bValueNewMemory = true;
pFindElement->m_pszValue = (char *)malloc(newLen + 1);
}
strcpy(pFindElement->m_pszValue, pszHeaderValue);
m_nHeaderSize += (newLen - pFindElement->m_nValueLength);
pFindElement->m_nValueLength = newLen;
return true;
}
return AddHeader(pszHeaderName, pszHeaderValue);
}
bool HHsParser::OrganizeHeader(char * pszHeaderName, char * pszHeaderValue)
{
HHsHeaderElement * pElement = new HHsHeaderElement(pszHeaderName, false, pszHeaderValue, false);
if (m_pElementHead == NULL)
m_pElementHead = pElement;
if (m_pElementRear)
m_pElementRear->m_pNext = pElement;
m_pElementRear = pElement;
return true;
}
void HHsParser::RemoveHeader(const char * pszHeaderName, const char * pszHeaderValue, int nIndex)
{
int i = 0;
HHsHeaderElement * pPrevNext = m_pElementHead;
for (HHsHeaderElement * pNext = m_pElementHead; pNext != NULL; pNext = pNext->m_pNext)
{
if (stricmp(pszHeaderName, pNext->m_pszName) == 0)
{
if (nIndex != i++)
continue;
if (pszHeaderValue && stricmp(pszHeaderValue, pNext->m_pszValue) != 0)
{
pPrevNext = pNext;
continue;
}
if (pNext == m_pElementHead)
{
m_pElementHead = pNext->m_pNext;
if (pNext == m_pElementRear)
m_pElementRear = m_pElementHead;
}
else if (pNext == m_pElementRear)
{
m_pElementRear = pPrevNext;
m_pElementRear->m_pNext = NULL;
}
else
{
pPrevNext->m_pNext = pNext->m_pNext;
}
m_nHeaderSize -= (pNext->m_nNameLength + pNext->m_nValueLength + 4); // 4 = ": " + "\rn"
delete pNext;
break;
}
pPrevNext = pNext;
}
}
size_t HHsParser::RefleshHeaderSize()
{
size_t nHeaderSize = 0;
if (m_pszMethod && m_pszRequestUri && m_pszVersion)
{
nHeaderSize += strlen(m_pszMethod) + 1;
nHeaderSize += strlen(m_pszRequestUri) + 1;
nHeaderSize += m_nProtocolNameLength + strlen(m_pszVersion) + 3; // GET / HTTP/1.1\r\n
}
else if (m_pszVersion && m_nStatusCode > 0 && m_pszReasonPhrase)
{
nHeaderSize += m_nProtocolNameLength + strlen(m_pszVersion) + 2; // HTTP/1.1 200 OK
int nNum = m_nStatusCode;
int nFigure = 0;
for (; nNum != 0; nFigure++)
nNum = nNum / 10;
nHeaderSize += nFigure + 1;
nHeaderSize += strlen(m_pszReasonPhrase) + 2;
}
else
return 0;
if (m_pElementHead == 0)
return 0;
for (HHsHeaderElement * pNext = m_pElementHead; pNext != NULL; pNext = pNext->m_pNext)
{
nHeaderSize += pNext->m_nNameLength + 2;
nHeaderSize += pNext->m_nValueLength + 2;
}
nHeaderSize += 2; // + \r\n
m_nHeaderSize = nHeaderSize;
return nHeaderSize;
}
int HHsParser::Parse(char * pData, unsigned int nSize, char * pBodyPtr)
{
if (pData == NULL || pData[0] == '\0')
return HP_PARAMETER_ERROR;
if (pBodyPtr == NULL)
{
pBodyPtr = SearchBodyPtr(pData, nSize);
if (pBodyPtr == NULL)
return HP_HEADER_REMAIN_PACKET;
}
m_nHeaderSize = pBodyPtr - pData;
char * pNextToken;
char * pNextLine = SliceHeader(pData);
if (strncmp(pData, m_szProtocolName, m_nProtocolNameLength) == 0)
{
// Response Start-Line (ex: HTTP/1.1 200 OK)
m_pszVersion = pData + m_nProtocolNameLength + 1;
if ((pNextToken = SliceToken(m_pszVersion, ' ')) == NULL)
return HP_NOT_HTTP_PACKET;
char * pszStatusCode = pNextToken;
if ((pNextToken = SliceToken(pszStatusCode, ' ')) == NULL)
return HP_NOT_HTTP_PACKET;
m_nStatusCode = atoi(pszStatusCode);
m_pszReasonPhrase = pNextToken;
}
else
{
// Request Start-Line
m_pszMethod = pData;
if ((pNextToken = SliceToken(m_pszMethod, ' ')) == NULL)
return HP_NOT_HTTP_PACKET;
//... check method name
m_pszRequestUri = pNextToken;
if ((pNextToken = SliceToken(m_pszRequestUri, ' ')) == NULL)
return HP_NOT_HTTP_PACKET;
m_pszVersion = pNextToken + m_nProtocolNameLength + 1;
}
bool bHasContentLength = false;
bool bIsChunkded = false;
bool bIsConnectionClose = false;
bool bHasContentType = false;
char * pOneLine;
char * pszHeaderName;
do
{
pOneLine = pNextLine;
if ((pNextLine = SliceHeader(pOneLine)) == NULL)
break;
pszHeaderName = pOneLine;
if ((pNextToken = SliceToken(pszHeaderName, ':')) == NULL)
return HP_NOT_HTTP_PACKET;
for (int i = 0; ; i++) // front trim
{
if (*pNextToken == ' ') pNextToken++;
else break;
}
if (stricmp(pszHeaderName, "Content-Length") == 0)
{
m_nContentLength = atol(pNextToken);
bHasContentLength = true;
}
else if (stricmp(pszHeaderName, "Transfer-Encoding") == 0)
{
if (stricmp(pNextToken, "chunked") == 0)
bIsChunkded = true;
}
else if (stricmp(pszHeaderName, "Connection") == 0)
{
if (stricmp(pNextToken, "close") == 0)
bIsConnectionClose = true;
}
else if (stricmp(pszHeaderName, "Content-Type") == 0)
bHasContentType = true;
OrganizeHeader(pszHeaderName, pNextToken);
} while (*pNextLine != '\r' && *pNextLine != '\n'); // header end
if (m_nHeaderSize == nSize && m_nContentLength == 0)
{
if (bIsChunkded || (bHasContentType && m_pszMethod == NULL && bHasContentLength == false && bIsConnectionClose))
return HP_BODYSIZE_UNKNOWN_PACKET;
else
return HP_COMPLETE_PACKET;
}
unsigned int nRemainSize = nSize - m_nHeaderSize;
if (m_nContentLength == 0 || m_nContentLength >= nRemainSize)
m_nBodySize = nRemainSize;
else
m_nBodySize = m_nContentLength;
if (m_nBodySize > 0)
{
m_pBody = pBodyPtr;
m_pBody[m_nBodySize] = '\0';
}
if (m_nContentLength == 0)
return HP_BODYSIZE_UNKNOWN_PACKET;
else if (m_nContentLength == m_nBodySize)
return HP_COMPLETE_PACKET;
else if (m_nContentLength > m_nBodySize)
return HP_BODY_REMAIN_PACKET;
return HP_BODYSIZE_UNKNOWN_PACKET;
}
bool HHsParser::ToString(char * pBuffer, bool bOnlyHeader)
{
if (m_pszVersion == NULL || m_pElementHead == NULL)
{
pBuffer[0] = '\0';
return false;
}
if (m_pszMethod)
sprintf(pBuffer, "%s %s %s/%s\r\n", m_pszMethod, m_pszRequestUri, m_szProtocolName, m_pszVersion);
else
sprintf(pBuffer, "%s/%s %d %s\r\n", m_szProtocolName, m_pszVersion, m_nStatusCode, m_pszReasonPhrase);
size_t nTempSize = strlen(pBuffer);
char * pBufferOffset = pBuffer + nTempSize;
for (HHsHeaderElement * pNext = m_pElementHead; pNext != NULL; pNext = pNext->m_pNext)
{
strcpy(pBufferOffset, pNext->m_pszName);
pBufferOffset += pNext->m_nNameLength;
strcpy(pBufferOffset, ": ");
pBufferOffset += 2;
strcpy(pBufferOffset, pNext->m_pszValue);
pBufferOffset += pNext->m_nValueLength;
strcpy(pBufferOffset, "\r\n");
pBufferOffset += 2;
}
strcpy(pBufferOffset, "\r\n");
if (bOnlyHeader == false && m_pBody)
{
pBufferOffset += 2;
memcpy(pBufferOffset, m_pBody, m_nBodySize);
pBufferOffset[m_nBodySize] = '\0';
}
return true;
}
+117
View File
@@ -0,0 +1,117 @@
#ifndef HS_PARSER__H_
#define HS_PARSER__H_
#ifdef _WIN32
#pragma once
#pragma warning(disable:4996)
#endif
class HHsHeaderElement
{
public:
HHsHeaderElement(const char * pszName, bool bNameMewMemory, const char * pszValue, bool bValueNewMemory);
~HHsHeaderElement();
public:
char * m_pszName;
size_t m_nNameLength;
bool m_bNameNewMemory;
char * m_pszValue;
size_t m_nValueLength;
bool m_bValueNewMemory;
HHsHeaderElement * m_pNext;
};
///////////////////////////////////////
class HHsParser
{
public:
enum
{
HP_PARAMETER_ERROR = 0,
HP_NOT_HTTP_PACKET = 1,
HP_HEADER_REMAIN_PACKET = 2,
HP_BODY_REMAIN_PACKET = 3,
HP_BODYSIZE_UNKNOWN_PACKET = 4,
HP_COMPLETE_PACKET = 5
};
static char * SearchBodyPtr(char * pData, unsigned int nSize);
////////////
HHsParser(const char * pszProtocolName);
virtual ~HHsParser();
char * GetProtocolName() { return m_szProtocolName; }
char * GetMethod() { return m_pszMethod; }
void SetRequestUri(const char * pszRequestUri);
char * GetRequestUri() { return m_pszRequestUri; }
void SetVersion(const char * pszVersion);
char * GetVersion() { return m_pszVersion; }
void SetStatusCode(int nStatusCode) { m_nStatusCode = nStatusCode; }
int GetStatusCode() { return m_nStatusCode; }
void SetReasonPhrase(const char * pszReasonPhrase);
char * GetReasonPhrase() { return m_pszReasonPhrase; }
size_t GetHeaderSize() { return m_nHeaderSize; }
unsigned long GetContentLength() { return m_nContentLength; }
void SetBody(char * pData, unsigned int nSize);
char * GetBodyPtr() { return m_pBody; }
size_t GetBodySize() { return m_nBodySize; }
HHsHeaderElement * GetHeaderElement(const char * pszHeaderName, int nIndex = 0);
const char * GetHeaderValue(const char * pszHeaderName, int nIndex = 0);
bool AddHeader(const char * pszHeaderName, const char * pszHeaderValue);
bool SetHeader(const char * pszHeaderName, const char * pszHeaderValue, int nIndex = 0);
void RemoveHeader(const char * pszHeaderName, const char * pszHeaderValue = NULL, int nIndex = 0);
size_t RefleshHeaderSize();
int Parse(char * pData, unsigned int nSize, char * pBodyPtr = NULL);
bool ToString(char * pBuffer, bool bOnlyHeader);
protected:
bool OrganizeHeader(char * pszHeaderName, char * pszHeaderValue);
private:
char m_szProtocolName[8];
size_t m_nProtocolNameLength;
char * m_pszMethod;
char * m_pszRequestUri;
bool m_bRequestUriNewMemory;
char * m_pszVersion;
int m_nStatusCode;
char * m_pszReasonPhrase;
bool m_bReasonPhraseNewMemory;
HHsHeaderElement * m_pElementHead;
HHsHeaderElement * m_pElementRear;
size_t m_nHeaderSize;
unsigned long m_nContentLength;
char * m_pBody;
bool m_bBodyNewMemory;
size_t m_nBodySize;
};
#endif // HS_PARSER__H_
+66
View File
@@ -0,0 +1,66 @@
#ifndef HUSLIB__H_
#define HUSLIB__H_
#ifdef _WIN32
#pragma once
#endif
#ifndef STRINGEX__H_
#include "stringex.h"
#endif
#ifndef DEFINES__H_
#include "Defines.h"
#endif
#ifndef COMMON__H_
#include "Common.h"
#endif
#ifndef OBJECT__H_
#include "Object.h"
#endif
#ifndef STRING__H_
#include "String.h"
#endif
#ifndef FILE__H_
#include "File.h"
#endif
#ifndef SOCKET__H_
#include "Socket.h"
#endif
#ifndef THREAD__H_
#include "Thread.h"
#endif
#ifndef DATA_STRUCT__H_
#include "DataStruct.h"
#endif
////
#ifndef TIMER__H_
#include "Timer.h"
#endif
#ifndef LOGGER__H_
#include "Logger.h"
#endif
#ifndef CONFIG__H_
#include "Config.h"
#endif
#ifndef MULTIPLEX_SOCKET__H_
#include "MultiplexSocket.h"
#endif
#ifndef APP__H_
#include "HusApp.h"
#endif
#endif // HUSLIB__H_
+62
View File
@@ -0,0 +1,62 @@
#ifndef HUSLIBEX__H_
#define HUSLIBEX__H_
#ifdef _WIN32
#pragma once
#endif
#ifndef NET_UTIL__H_
#include "NetUtil.h"
#endif
#ifndef GLOBAL__H_
#include "Global.h"
#endif
#ifndef STREAM_BUFFER__H_
#include "StreamBuffer.h"
#endif
#ifndef BLOCK_LIST_BUFFER__H_
#include "BlockListBuffer.h"
#endif
#ifndef MULTIPLEX_SSL_SOCKET__H_
#include "MultiplexSslSocket.h"
#endif
#ifndef PROTOCOL_HANDLER__H_
#include "ProtocolHandler.h"
#endif
#ifndef MULTIPLEX_TRANSPORT__H_
#include "MultiplexTransport.h"
#endif
#ifndef HS_PARSER__H_
#include "hsparser.h"
#endif
#ifndef HTTP_HANDLER__H_
#include "HttpHandler.h"
#endif
#ifndef TELNET_HANDLER__H_
#include "TelnetHandler.h"
#endif
#ifndef VSP_HANDLER__H_
#include "VspHandler.h"
#endif
#ifndef WEB_SERVER__H_
#include "WebServer.h"
#endif
#ifndef TELNET_SERVER__H
#include "TelnetServer.h"
#endif
#endif // HUSLIBEX__H_
+716
View File
@@ -0,0 +1,716 @@
#include "inifile.h"
#include <stdio.h>
#include <fcntl.h>
#ifdef _WIN32
#include <sys/stat.h>
#include <io.h>
#else
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#endif
#ifndef _WIN32
#ifndef BOOL
typedef int BOOL;
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#endif
#ifdef MULTI_THREAD_MODEL
pthread_mutex_t g_mutex_for_ini_file;
#define MDF_lock() pthread_mutex_lock(&g_mutex_for_ini_file);
#define MDF_unlock() pthread_mutex_unlock(&g_mutex_for_ini_file);
#else
#define MDF_lock() ((void)0)
#define MDF_unlock() ((void)0)
#endif // MULTI_THREAD_MODEL
#define MAX_INI_FILE_SIZE 1024 * 1024 * 8 // 8Mb
#define MAX_INI_SECTION_NAME_BUFFER_SIZE 512
#ifdef _WIN32
#define MD_FA_WOPEN O_RDONLY | O_BINARY, S_IREAD | S_IWRITE | S_IRGRP | S_IROTH
#define MD_FA_WCREATE O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, S_IREAD | S_IWRITE | S_IRGRP | S_IROTH
#else
//#define MD_FA_WOPEN O_RDONLY, S_IREAD | S_IWRITE | S_IRGRP | S_IROTH
//#define MD_FA_WCREATE O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE | S_IRGRP | S_IROTH
#define MD_FA_WOPEN O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
#define MD_FA_WCREATE O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
#endif // _WIN32
#define GetPrivateProfileString_P GetPrivateProfileString
#define GetPrivateProfileInt_P GetPrivateProfileInt
#define WritePrivateProfileString_P WritePrivateProfileString
char * __g_ini_file__search_section_ptr(const char * S1, const char * S2, int nFileSize, int * pnPos)
{
int j;
char chBeforeCharacter = '\0';
if (S1 == NULL || S1[0] == '\0' || S2 == NULL || S2[0] == '\0')
return NULL;
for (*pnPos = 0; *pnPos < nFileSize; (*pnPos)++)
{
if (((*pnPos) == 0 && *S1 == '[') ||
(*S1 == '[' && (chBeforeCharacter == '\r' || chBeforeCharacter == '\n')))
{
S1++;
(*pnPos)++;
BOOL bIsSectionFound = TRUE;
for (j = 0; *pnPos < nFileSize; (*pnPos)++)
{
if (*S1 == ']' && S2[j] == '\0')
break;
if (*S1 != S2[j])
{
bIsSectionFound = FALSE;
break;
}
if (*S1 == ']' || *S1 == '\r' || *S1 == '\n')
{
bIsSectionFound = FALSE;
break;
}
S1++;
j++;
}
if (*pnPos >= nFileSize)
return NULL;
if (bIsSectionFound == TRUE)
return (char *)S1;
}
chBeforeCharacter = *S1;
S1++;
}
return NULL;
}
char * __g_ini_file__search_key_ptr(const char * S1, const char * S2, int nFileSize, int * pnPos)
{
int j;
char chBeforeCharacter = '\0';
if (S1 == NULL || S1[0] == '\0' || S2 == NULL || S2[0] == '\0')
return NULL;
for (; *pnPos < nFileSize; (*pnPos)++)
{
if (*S1 == S2[0] && (chBeforeCharacter == '\r' || chBeforeCharacter == '\n'))
{
S1++;
(*pnPos)++;
BOOL bIsKeyFound = TRUE;
for (j = 1; *pnPos < nFileSize; (*pnPos)++)
{
if (*S1 == '=' && S2[j] == '\0')
break;
if (*S1 != S2[j])
{
bIsKeyFound = FALSE;
break;
}
if (*S1 == '\r' || *S1 == '\n')
{
bIsKeyFound = FALSE;
break;
}
S1++;
j++;
}
if (*pnPos >= nFileSize)
return NULL;
if (bIsKeyFound == TRUE)
return (char *)S1;
else
{
for (; *pnPos < nFileSize; (*pnPos)++)
{
if (*S1 == '\r' || *S1 == '\n')
break;
S1++;
}
if (*pnPos >= nFileSize)
return NULL;
}
}
if (*S1 == '[' && (chBeforeCharacter == '\r' || chBeforeCharacter == '\n'))
{
for (S1--; *pnPos > 0; (*pnPos)--)
{
if (*S1 != '\r' && *S1 != '\n')
break;
S1--;
}
return NULL;
}
chBeforeCharacter = *S1;
S1++;
}
return NULL;
}
size_t __g_ini_file__value_len_without_rear_space(const char * STR)
{
int i;
if (STR == NULL || STR[0] == '\0')
return 0;
for (i = 0; STR[i] != '\0'; i++)
{
if (STR[i] == '\r' || STR[i] == '\n')
break;
}
for (i--; i >= 0; i--)
{
if (STR[i] != ' ')
return i + 1;
}
return 0;
}
int GetPrivateProfileString_P(
const char * lpAppName, // section name
const char * lpKeyName, // key name
const char * lpDefault, // default string
char * lpReturnedString, // destination buffer
unsigned int nSize, // size of destination buffer
const char * lpFileName // initialization file name
)
{
int fhINIFile;
long nFileSize;
char * pszBuffer;
char * pszBufferPtr;
char * pszSectionName;
char * pszKeyName;
size_t nCopySize;
int nPos;
if (lpReturnedString == NULL)
return 0;
if (lpAppName == NULL || lpAppName[0] == '\0' ||
lpKeyName == NULL || lpKeyName[0] == '\0' ||
lpDefault == NULL ||
lpFileName == NULL || lpFileName[0] == '\0' ||
nSize <= 0)
{
goto GetPrivateProfileString_P_Fail;
}
if (strlen(lpAppName) > MAX_INI_SECTION_NAME_BUFFER_SIZE - 3)
{
printf("inifile\t[ERROR] Too large section name. over %d byte.\n", MAX_INI_SECTION_NAME_BUFFER_SIZE - 3);
goto GetPrivateProfileString_P_Fail;
}
lpReturnedString[0] = '\0';
MDF_lock();
fhINIFile = open(lpFileName, MD_FA_WOPEN);
if (fhINIFile == -1)
{
MDF_unlock();
//printf("inifile\t[ERROR] Failed to open file. errno = %d\n", errno);
nCopySize = __g_ini_file__value_len_without_rear_space(lpDefault);
if (nSize <= nCopySize)
nCopySize = nSize - 1;
strncpy(lpReturnedString, lpDefault, nCopySize);
lpReturnedString[nCopySize] = '\0';
return strlen(lpReturnedString);
}
nFileSize = lseek(fhINIFile, 0L, SEEK_END);
if (nFileSize > MAX_INI_FILE_SIZE)
{
printf("inifile\t[ERROR] Too large file. over %d byte.\n", MAX_INI_FILE_SIZE);
close(fhINIFile);
MDF_unlock();
goto GetPrivateProfileString_P_Fail;
}
lseek(fhINIFile, 0L, SEEK_SET);
pszBuffer = (char *)malloc(nFileSize + 1);
if (read(fhINIFile, pszBuffer, nFileSize) == -1)
{
printf("inifile\t[ERROR] Failed to read file. errno = %d\n", errno);
close(fhINIFile);
MDF_unlock();
free(pszBuffer);
goto GetPrivateProfileString_P_Fail;
}
pszBuffer[nFileSize] = '\0';
close(fhINIFile);
nCopySize = __g_ini_file__value_len_without_rear_space(lpAppName);
pszSectionName = (char *)malloc(nCopySize + 1);
strncpy(pszSectionName, lpAppName, nCopySize);
pszSectionName[nCopySize] = '\0';
nCopySize = __g_ini_file__value_len_without_rear_space(lpKeyName);
pszKeyName = (char *)malloc(nCopySize + 1);
strncpy(pszKeyName, lpKeyName, nCopySize);
pszKeyName[nCopySize] = '\0';
pszBufferPtr = __g_ini_file__search_section_ptr(pszBuffer, pszSectionName, nFileSize, &nPos);
if (pszBufferPtr != NULL)
pszBufferPtr = __g_ini_file__search_key_ptr(pszBufferPtr, pszKeyName, nFileSize, &nPos);
if (pszBufferPtr != NULL && nPos < nFileSize)
{
pszBufferPtr++;
nCopySize = __g_ini_file__value_len_without_rear_space(pszBufferPtr);
if (nSize <= nCopySize)
nCopySize = nSize - 1;
strncpy(lpReturnedString, pszBufferPtr, nCopySize);
lpReturnedString[nCopySize] = '\0';
}
else
{
nCopySize = __g_ini_file__value_len_without_rear_space(lpDefault);
if (nSize <= nCopySize)
nCopySize = nSize - 1;
strncpy(lpReturnedString, lpDefault, nCopySize);
lpReturnedString[nCopySize] = '\0';
}
MDF_unlock();
free(pszSectionName);
free(pszKeyName);
free(pszBuffer);
return strlen(lpReturnedString);
GetPrivateProfileString_P_Fail:
lpReturnedString[0] = '\0';
return 0;
}
int GetPrivateProfileInt_P(
const char* lpAppName, // section name
const char* lpKeyName, // key name
int nDefault, // return value if key name not found
const char* lpFileName // initialization file name
)
{
char szBuf[128];
GetPrivateProfileString_P(lpAppName, lpKeyName, "",
szBuf, 128, lpFileName);
if (strlen(szBuf) <= 0)
return nDefault;
return atoi(szBuf);
}
BOOL WritePrivateProfileString_P(
const char* lpAppName, // section name
const char* lpKeyName, // key name
const char* lpString, // string to add
const char* lpFileName // initialization file
)
{
#define FREE_BUFFERS() free(pszSectionName); free(pszKeyName); free(pszWriteString); free(pszBuffer)
int fhINIFile;
long nFileSize;
char * pszBuffer;
char * pszBufferPtr;
char * pszSectionName;
char * pszKeyName;
char * pszWriteString;
size_t nWriteSize;
int nPos;
if (lpAppName == NULL || lpAppName[0] == '\0' ||
lpKeyName == NULL || lpKeyName[0] == '\0' ||
lpFileName == NULL || lpFileName[0] == '\0')
{
return FALSE;
}
if (strlen(lpAppName) > MAX_INI_SECTION_NAME_BUFFER_SIZE - 3)
{
printf("inifile\t[ERROR] Too large section name. over %d byte.\n", MAX_INI_SECTION_NAME_BUFFER_SIZE - 3);
return FALSE;
}
nWriteSize = __g_ini_file__value_len_without_rear_space(lpAppName);
pszSectionName = (char *)malloc(nWriteSize + 1);
strncpy(pszSectionName, lpAppName, nWriteSize);
pszSectionName[nWriteSize] = '\0';
nWriteSize = __g_ini_file__value_len_without_rear_space(lpKeyName);
pszKeyName = (char *)malloc(nWriteSize + 1);
strncpy(pszKeyName, lpKeyName, nWriteSize);
pszKeyName[nWriteSize] = '\0';
nWriteSize = __g_ini_file__value_len_without_rear_space(lpString);
pszWriteString = (char *)malloc(nWriteSize + 1);
strncpy(pszWriteString, lpString, nWriteSize);
pszWriteString[nWriteSize] = '\0';
MDF_lock();
fhINIFile = open(lpFileName, MD_FA_WOPEN);
if (fhINIFile == -1)
{
//printf("inifile\t[ERROR] Failed to open file. errno = %d\n", errno);
goto WritePrivateProfileString_P_New;
}
nFileSize = lseek(fhINIFile, 0L, SEEK_END);
if (nFileSize > MAX_INI_FILE_SIZE)
{
printf("inifile\t[ERROR] Too large file. over %d byte.\n", MAX_INI_FILE_SIZE);
close(fhINIFile);
MDF_unlock();
free(pszSectionName);
free(pszKeyName);
free(pszWriteString);
return FALSE;
}
if (nFileSize == 0)
{
close(fhINIFile);
goto WritePrivateProfileString_P_New;
}
lseek(fhINIFile, 0L, SEEK_SET);
pszBuffer = (char *)malloc(nFileSize + strlen(lpAppName) +
strlen(lpKeyName) + strlen(lpString) + 10); // 10 : \r \n [ ] \r \n = \r \n \0
if (read(fhINIFile, pszBuffer, nFileSize) == -1)
{
printf("inifile\t[ERROR] Failed to read file. errno = %d\n", errno);
close(fhINIFile);
MDF_unlock();
FREE_BUFFERS();
return FALSE;
}
pszBuffer[nFileSize] = '\0';
close(fhINIFile);
pszBufferPtr = __g_ini_file__search_section_ptr(pszBuffer, pszSectionName, nFileSize, &nPos);
if (pszBufferPtr == NULL)
{
pszBufferPtr = pszBuffer + nFileSize;
#ifdef _WIN32
sprintf(pszBufferPtr, "\r\n[%s]\r\n%s=%s\r\n", pszSectionName, pszKeyName, pszWriteString);
#else
sprintf(pszBufferPtr, "\n[%s]\n%s=%s\n", pszSectionName, pszKeyName, pszWriteString);
#endif
fhINIFile = open(lpFileName, MD_FA_WCREATE);
if (fhINIFile == -1)
{
printf("inifile\t[ERROR] Failed to open file. errno = %d\n", errno);
MDF_unlock();
FREE_BUFFERS();
return FALSE;
}
if (write(fhINIFile, pszBuffer, strlen(pszBuffer)) == -1)
{
printf("inifile\t[ERROR] Failed to write file. errno = %d\n", errno);
close(fhINIFile);
MDF_unlock();
FREE_BUFFERS();
return FALSE;
}
close(fhINIFile);
MDF_unlock();
FREE_BUFFERS();
return TRUE;
}
pszBufferPtr = __g_ini_file__search_key_ptr(pszBufferPtr, pszKeyName, nFileSize, &nPos);
if (pszBufferPtr == NULL)
{
char * pszTempBuffer;
fhINIFile = open(lpFileName, MD_FA_WCREATE);
if (fhINIFile == -1)
{
printf("inifile\t[ERROR] Failed to open file. errno = %d\n", errno);
MDF_unlock();
FREE_BUFFERS();
return FALSE;
}
pszBufferPtr = pszBuffer + nPos;
pszTempBuffer = (char *)malloc(strlen(pszKeyName) +
strlen(pszWriteString) + 6); // 6 : \r \n = \r \n \0
#ifdef _WIN32
if (*(pszBufferPtr - 1) != '\r' && *(pszBufferPtr - 1) != '\n')
sprintf(pszTempBuffer, "\r\n%s=%s", pszKeyName, pszWriteString);
else
sprintf(pszTempBuffer, "%s=%s", pszKeyName, pszWriteString);
#else
if (*(pszBufferPtr - 1) != '\r' && *(pszBufferPtr - 1) != '\n')
sprintf(pszTempBuffer, "\n%s=%s", pszKeyName, pszWriteString);
else
sprintf(pszTempBuffer, "%s=%s", pszKeyName, pszWriteString);
#endif
if (write(fhINIFile, pszBuffer, nPos) == -1 ||
write(fhINIFile, pszTempBuffer, strlen(pszTempBuffer)) == -1 ||
write(fhINIFile, pszBufferPtr, nFileSize - nPos) == -1)
{
printf("inifile\t[ERROR] Failed to write file. errno = %d\n", errno);
close(fhINIFile);
MDF_unlock();
free(pszTempBuffer);
FREE_BUFFERS();
return FALSE;
}
close(fhINIFile);
MDF_unlock();
free(pszTempBuffer);
FREE_BUFFERS();
return TRUE;
}
pszBufferPtr++;
nPos++;
fhINIFile = open(lpFileName, MD_FA_WCREATE);
if (fhINIFile == -1)
{
printf("inifile\t[ERROR] Failed to open file. errno = %d\n", errno);
MDF_unlock();
FREE_BUFFERS();
return FALSE;
}
if (write(fhINIFile, pszBuffer, nPos) != -1 &&
write(fhINIFile, pszWriteString, strlen(pszWriteString)) != -1)
{
for (;;)
{
if (*pszBufferPtr == '\0' || *pszBufferPtr == '\r' || *pszBufferPtr == '\n')
break;
pszBufferPtr++;
nPos++;
}
if (*pszBufferPtr == '\0' || write(fhINIFile, pszBufferPtr, nFileSize - nPos) != -1)
{
close(fhINIFile);
MDF_unlock();
FREE_BUFFERS();
return TRUE;
}
}
printf("inifile\t[ERROR] Failed to write file. errno = %d\n", errno);
close(fhINIFile);
MDF_unlock();
FREE_BUFFERS();
return FALSE;
WritePrivateProfileString_P_New:
fhINIFile = open(lpFileName, MD_FA_WCREATE);
if (fhINIFile == -1)
{
printf("inifile\t[ERROR] Failed to open file. errno = %d\n", errno);
MDF_unlock();
free(pszSectionName);
free(pszKeyName);
free(pszWriteString);
return FALSE;
}
pszBuffer = (char *)malloc(strlen(pszSectionName) +
strlen(pszKeyName) + strlen(pszWriteString) + 8); // 8 : [ ] \r \n = \r \n \0
#ifdef _WIN32
sprintf(pszBuffer, "[%s]\r\n%s=%s\r\n", pszSectionName, pszKeyName, pszWriteString);
#else
sprintf(pszBuffer, "[%s]\n%s=%s\n", pszSectionName, pszKeyName, pszWriteString);
#endif
if (write(fhINIFile, pszBuffer, strlen(pszBuffer)) == -1)
{
printf("inifile\t[ERROR] Failed to write file. errno = %d\n", errno);
close(fhINIFile);
MDF_unlock();
FREE_BUFFERS();
return FALSE;
}
close(fhINIFile);
MDF_unlock();
FREE_BUFFERS();
return TRUE;
}
#endif // _WIN32
HIniFile::HIniFile()
{
m_szIniFileName[0] = '\0';
m_pszBuffer = NULL;
}
HIniFile::~HIniFile()
{
if (m_pszBuffer)
free(m_pszBuffer);
}
bool HIniFile::SetIniFile(const char * pszFileName)
{
if (pszFileName && pszFileName[0] != '\0')
{
strncpy(m_szIniFileName, pszFileName, IF_MAX_PATH);
m_pszBuffer = (char *)malloc(IF_DEFAULT_BUFFER_SIZE);
m_dwBufferLength = IF_DEFAULT_BUFFER_SIZE;
return true;
}
return false;
}
const char * HIniFile::ReadString(const char * pszSetionName, const char * pszKeyName,
const char * pszDefault, unsigned long nMaxSize)
{
if (m_szIniFileName[0] == '\0')
return "";
if (nMaxSize > IF_DEFAULT_BUFFER_SIZE)
{
free(m_pszBuffer);
m_pszBuffer = (char *)malloc(nMaxSize);
m_dwBufferLength = nMaxSize;
}
GetPrivateProfileString(pszSetionName, pszKeyName, pszDefault, m_pszBuffer, nMaxSize, m_szIniFileName);
return m_pszBuffer;
}
bool HIniFile::WriteString(const char * pszSetionName, const char * pszKeyName, const char * pszString)
{
if (m_szIniFileName[0] == '\0')
return false;
return WritePrivateProfileString(pszSetionName, pszKeyName, pszString, m_szIniFileName) != FALSE;
}
int HIniFile::ReadNumber(const char * pszSetionName, const char * pszKeyName, int nDefault)
{
if (m_szIniFileName[0] == '\0')
return 0;
return GetPrivateProfileInt(pszSetionName, pszKeyName, nDefault, m_szIniFileName);
}
bool HIniFile::WriteNumber(const char * pszSetionName, const char * pszKeyName, int nNumber)
{
if (m_szIniFileName[0] == '\0')
return false;
snprintf(m_pszBuffer, m_dwBufferLength, "%d", nNumber);
return WritePrivateProfileString(pszSetionName, pszKeyName, m_pszBuffer, m_szIniFileName) != FALSE;
}
bool HIniFile::ReadBoolean(const char * pszSetionName, const char * pszKeyName, bool bDefault)
{
if (m_szIniFileName[0] == '\0')
return false;
GetPrivateProfileString(pszSetionName, pszKeyName, "FALSE", m_pszBuffer, m_dwBufferLength, m_szIniFileName);
if (strcasecmp(m_pszBuffer, "TRUE") == 0)
return true;
return false;
}
bool HIniFile::WriteBoolean(const char * pszSetionName, const char * pszKeyName, bool bValue)
{
if (m_szIniFileName[0] == '\0')
return false;
return WritePrivateProfileString(pszSetionName, pszKeyName, bValue ? "TRUE" : "FALSE", m_szIniFileName) != FALSE;
}
+90
View File
@@ -0,0 +1,90 @@
#ifndef INI_FILE__H_
#define INI_FILE__H_
#include "Common.h"
#ifdef _WIN32
#pragma once
//#include <windows.h>
#pragma warning(disable:4996)
#else
#ifdef MULTI_THREAD_MODEL
#include <pthread.h>
#endif
#endif // _WIN32
class HIniFile
{
public:
enum
{
IF_MAX_PATH = 512,
IF_DEFAULT_BUFFER_SIZE = 1024,
};
HIniFile();
~HIniFile();
inline const char * GetIniFile() { return m_szIniFileName; }
bool SetIniFile(const char * pszFileName);
const char * ReadString(const char * pszSetionName, const char * pszKeyName,
const char * pszDefault, unsigned long nMaxSize = IF_DEFAULT_BUFFER_SIZE);
bool WriteString(const char * pszSetionName, const char * pszKeyName, const char * pszString);
int ReadNumber(const char * pszSetionName, const char * pszKeyName, int nDefault);
bool WriteNumber(const char * pszSetionName, const char * pszKeyName, int nNumber);
bool ReadBoolean(const char * pszSetionName, const char * pszKeyName, bool bDefault);
bool WriteBoolean(const char * pszSetionName, const char * pszKeyName, bool bValue);
private:
char m_szIniFileName[IF_MAX_PATH];
char * m_pszBuffer;
unsigned long m_dwBufferLength;
};
#ifndef _WIN32
// initialize file functions
int GetPrivateProfileString_P(
const char* lpAppName, // section name
const char* lpKeyName, // key name
const char* lpDefault, // default string
char* lpReturnedString, // destination buffer
unsigned int nSize, // size of destination buffer
const char* lpFileName // initialization file name
);
int GetPrivateProfileInt_P(
const char* lpAppName, // section name
const char* lpKeyName, // key name
int nDefault, // return value if key name not found
const char* lpFileName // initialization file name
);
bool WritePrivateProfileString_P(
const char* lpAppName, // section name
const char* lpKeyName, // key name
const char* lpString, // string to add
const char* lpFileName // initialization file
);
#endif // _WIN32
#endif // INI_FILE__H_
Binary file not shown.
+811
View File
@@ -0,0 +1,811 @@
#include "stringex.h"
#include "Common.h" // for debug
#include "Logger.h" // for debug
#ifdef _WIN32
#else
//#ifndef __CYGWIN__
int stricmp(const char * first, const char * last)
{
int f, l;
do
{
f = tolower(*first);
l = tolower(*last);
first++;
last++;
} while (f && l && f == l);
//return(f - l);
return f == l ? 0 : f > l ? 1 : -1;
}
int strnicmp(const char * first, const char * last, unsigned int count)
{
int f, l;
if (count)
{
do
{
f = tolower(*first);
l = tolower(*last);
first++;
last++;
} while (--count && f && l && f == l);
//return(f - l);
return f == l ? 0 : f > l ? 1 : -1;
}
return 0;
}
char * strlwr(char * str)
{
char * p = str;
do
{
*p = tolower(*p);
p++;
} while (*p);
return(str);
}
char * strupr(char * str)
{
char * p = str;
do
{
*p = toupper(*p);
p++;
} while (*p);
return(str);
}
//#endif // __CYGWIN__
#endif
char * gets_hus(char * s, int n)
{
char * ch = s;
int k;
while ((k = getchar ()) != '\n')
{
if (k == EOF)
{
if (ch == s || !feof(stdin))
return NULL;
break;
}
*ch++ = k;
if (--n <= 1)
break;
}
*ch = '\0';
return s;
}
char * stristr(char * pszStr, char * pszSearch)
{
if (pszStr == NULL)
{
//HLOG(15, "[TRACE], stristr string is NULL\n");
return NULL;
}
char *cp = pszStr;
char *s1, *s2;
int f, l;
if (!*pszSearch)
return pszStr;
while (*cp)
{
s1 = cp;
s2 = (char *)pszSearch;
f = tolower(*s1);
l = tolower(*s2);
while (f && l && !(f-l))
{
s1++, s2++;
f = tolower(*s1);
l = tolower(*s2);
}
if (!*s2)
return cp;
cp++;
}
return NULL;
}
char * StrIKeyword(char * string, char * strSearch)
{
char *cp = string;
char *s1, *s2;
int f, l;
if (!*strSearch)
return string;
while (*cp)
{
s1 = cp;
s2 = (char *)strSearch;
f = tolower(*s1);
l = tolower(*s2);
while (f && l && !(f-l))
{
s1++, s2++;
f = tolower(*s1);
l = tolower(*s2);
}
if (*s1 < 0)
{
cp++;
continue;
}
//if (!*s2) // stristr
if (!*s2 && !isalnum(*s1) && *s1 != '.') // for com, com.cn
return cp;
cp++;
}
return NULL;
}
const char * StrNStr(const char * string, const char * strSearch, int nCount)
{
char *cp = (char *)string;
char *s1, *s2;
int f, l, nRemain = nCount, nr2 = nCount;
if (nCount == 0)
return NULL;
if (!*strSearch)
return((char *)string);
while (*cp)
{
s1 = cp;
s2 = (char *)strSearch;
f = *s1;
l = *s2;
if (nCount > 0)
nr2 = nRemain;
while (f && l && !(f-l))
{
s1++, s2++;
f = *s1;
l = *s2;
if (nCount > 0 && --nr2 < 0)
return NULL;
}
if (!*s2)
return cp;
cp++;
if (nCount > 0 && --nRemain <= 0)
return NULL;
}
return NULL;
}
const char * StrNIStr(const char * string, const char * strSearch, int nCount)
{
char *cp = (char *)string;
char *s1, *s2;
int f, l, nRemain = nCount, nr2 = nCount;
if (nCount == 0)
return NULL;
if (!*strSearch)
return((char *)string);
while (*cp)
{
s1 = cp;
s2 = (char *)strSearch;
f = tolower(*s1);
l = tolower(*s2);
if (nCount > 0)
nr2 = nRemain;
while (f && l && !(f-l))
{
s1++, s2++;
f = tolower(*s1);
l = tolower(*s2);
if (nCount > 0 && --nr2 < 0)
return NULL;
}
if (!*s2)
return cp;
cp++;
if (nCount > 0 && --nRemain <= 0)
return NULL;
}
return NULL;
}
const char * StrRChr(const char * string, const char * strStart, char ch)
{
const char * s = strStart;
if (strStart == NULL || string > s)
return NULL;
while (s != string)
{
if (*s == ch)
return s;
s--;
}
return NULL;
}
#if 0
const char * StrNIKeyword(const char * string, const char * strSearch, int nCount)
{
char *cp = (char *)string;
char *s1, *s2;
int f, l, nRemain = nCount, nr2 = nCount;
if (nCount == 0)
return NULL;
if (!*strSearch)
return((char *)string);
while (*cp)
{
s1 = cp;
s2 = (char *)strSearch;
f = tolower(*s1);
l = tolower(*s2);
if (nCount > 0)
nr2 = nRemain;
while (f && l && !(f-l))
{
s1++, s2++;
f = tolower(*s1);
l = tolower(*s2);
if (nCount > 0 && --nr2 < 0)
return NULL;
}
//if (!*s2) // StrNIStr
if (!*s2 && !isalnum(*s1) && *s1 != '.')
return cp;
cp++;
if (nCount > 0 && --nRemain <= 0)
return NULL;
}
return NULL;
}
#endif
const char * StrStrUntilChr(const char * string, const char * strSearch, char chUntil)
{
char *cp = (char *)string;
char *s1, *s2;
if (!*strSearch)
return ((char *)string);
while (*cp)
{
s1 = cp;
s2 = (char *)strSearch;
if (*s1 == chUntil)
return NULL;
while (*s1 && *s2 && !(*s1-*s2))
{
s1++, s2++;
}
if (!*s2)
return cp;
cp++;
}
return NULL;
}
const char * StrStrUntilStr(const char * string, const char * strSearch, const char * strUntil)
{
char *cp = (char *)string;
char *s1, *s2, *s3;
if (!*strSearch)
return ((char *)string);
while (*cp)
{
s1 = cp;
s2 = (char *)strSearch;
s3 = (char *)strUntil;
while (*s1 && *s3 && !(*s1-*s3))
{
s1++, s3++;
}
if (!*s3)
return NULL;
while (*s1 && *s2 && !(*s1-*s2))
{
s1++, s2++;
}
if (!*s2)
return cp;
cp++;
}
return NULL;
}
const char * StrBetweenCpy(const char * pSrc, const char * pszFront, const char * pszRear, char * pDst)
{
char * pszStart, * pszEnd;
if ((pszStart = (char *)strstr(pSrc, pszFront)) == NULL)
return NULL;
pszStart += strlen(pszFront);
if ((pszEnd = strstr(pszStart, pszRear)) == NULL)
return NULL;
strncpy(pDst, pszStart, pszEnd - pszStart);
pDst[pszEnd - pszStart] = '\0';
return pszEnd + strlen(pszRear);
}
size_t StrRemoveBetween(char * pszDst, const char * pszSrc, const char * pszFront, const char * pszRear)
{
char * pszStart, * pszEnd;
if ((pszStart = (char *)strstr(pszSrc, pszFront)) == NULL)
return 0;
pszStart += strlen(pszFront);
if ((pszEnd = strstr(pszStart, pszRear)) == NULL)
return 0;
size_t nFrontSize = pszStart - pszSrc;
strncpy(pszDst, pszSrc, nFrontSize);
strcpy(pszDst + nFrontSize, pszEnd);
return nFrontSize + strlen(pszEnd);
}
int StrCountChar(const char * string, char ch)
{
int n = 0;
while (*string)
{
if (*string++ == ch)
n++;
}
return n;
}
int StrCountStr(const char * string, const char * strSearch)
{
int nCount = 0;
size_t nSrcLength = strlen(string);
size_t nFindLength = strlen(strSearch);
char * pszStart = (char *)string;
char * pszEnd = (char *)string + nSrcLength;
char * pszTarget;
while (pszStart < pszEnd)
{
while ((pszTarget = strstr(pszStart, strSearch)) != NULL)
{
nCount++;
pszStart = pszTarget + nFindLength;
}
pszStart += strlen(pszStart) + 1;
}
return nCount;
}
int StrCountRow(const char * string)
{
int nCount = 0;
const char * p = string;
while (*p)
{
if (*p++ == '\n')
nCount++;
}
if (nCount == 0)
{
p = string;
while (*p)
{
if (*p++ == '\r')
nCount++;
}
}
if (nCount == 0 && *string != '\0')
return 1;
return nCount;
}
char * StrTok(const char * pszSrc, const char * pszDelimit, char * pszTokenBuff)
{
char * pNext, * pSrcOffset = (char *)pszSrc;
for (;;)
{
pNext = strstr(pSrcOffset, pszDelimit);
if (pNext == NULL)
{
strcpy(pszTokenBuff, pSrcOffset);
return NULL;
}
else if (pNext != pSrcOffset)
break;
pSrcOffset += strlen(pszDelimit);
}
strncpy(pszTokenBuff, pSrcOffset, pNext - pSrcOffset);
pszTokenBuff[pNext - pSrcOffset] = '\0';
return pNext + strlen(pszDelimit);
}
// const char pszTest[] = " 123456 ";
// char * psz = (char *)pszTest;
// StrTrim(&psz, strlen(psz), true, true);
// psz --> "123456"
void StrTrim(char ** ppsz, size_t nLength, bool bRemoveFront, bool bRemoveRear)
{
if (bRemoveFront)
{
size_t i;
for (i = 0; i < nLength; i++)
{
if ((*ppsz)[i] == ' ' || (*ppsz)[i] == '\t')
{
continue;
}
else
{
nLength -= i;
*ppsz = *ppsz + i;
break;
}
}
if (i == nLength)
{
nLength = 0;
(*ppsz)[0] = '\0';
}
}
if (bRemoveRear)
{
for (int i = int(nLength - 1); i >= 0; i--)
{
if ((*ppsz)[i] == ' ' || (*ppsz)[i] == '\t')
{
(*ppsz)[i] = '\0';
continue;
}
else
{
break;
}
}
}
}
const char * StrNTrimPtr(const char * pszSrc, int nSrcCount)
{
int nRemain = nSrcCount;
for (;;)
{
if (*pszSrc == '\0')
break;
else if (*pszSrc == ' ' || *pszSrc == '\t')
pszSrc++;
else
break;
if (nSrcCount > 0 && --nRemain <= 0)
break;
}
return pszSrc;
}
void StrNTrimCpy(char * pszDst, const char * pszSrc, int nSrcCount)
{
if (nSrcCount == 0)
return;
int nRemain = nSrcCount;
for (;;)
{
if (*pszSrc == '\0')
break;
else if (*pszSrc == ' ' || *pszSrc == '\t')
pszSrc++;
else
*pszDst++ = *pszSrc++;
if (nSrcCount > 0 && --nRemain <= 0)
break;
}
*pszDst = '\0';
}
char * StrReadLine(char * pszDst, const char * pszSrc, int nCount)
{
int i = 0;
for (; ; i++)
{
if (nCount > 0 && i >= nCount)
break;
if (pszSrc[i] == '\r' ||
pszSrc[i] == '\n')
{
pszDst[i] = '\0';
break;
}
else if (pszSrc[i] == '\0')
{
pszDst[i] = '\0';
return NULL;
}
else
pszDst[i] = pszSrc[i];
}
for (; ; i++)
{
if (nCount > 0 && i >= nCount)
break;
if (pszSrc[i] != '\r' && pszSrc[i] != '\n' && pszSrc[i] != 0x09)
break;
}
return (char *)pszSrc + i;
}
// return new memory
const char * StrReplace(const char * pszText, const char * pszKeyword, const char * pszReplace, int nMode, int nCount)
{
if (nCount == 0)
return NULL;
const char * (*fnStrStr)(const char *, const char *);
if (nMode == 0)
fnStrStr = (const char*(*)(const char*, const char*))strstr;
else if (nMode == 1)
fnStrStr = stristr;
else
fnStrStr = StrIKeyword;
int nRepeatCount = nCount;
size_t nKeywordLength = strlen(pszKeyword);
const char * pszNext = (const char *)pszText;
int nKeywordCount = 0;
for (;;)
{
if ((pszNext = fnStrStr(pszNext, pszKeyword)) == NULL)
break;
nKeywordCount++;
if (nRepeatCount > -1 && --nRepeatCount == 0)
break;
pszNext += nKeywordLength;
}
if (nKeywordCount == 0)
return NULL;
size_t nReplaceLength = strlen(pszReplace);
size_t nTextLength = strlen(pszText);
size_t nNewTextLength = nTextLength + (nReplaceLength - nKeywordLength) * nKeywordCount;
char * pszNewText = (char *)malloc(nNewTextLength + 1);
size_t nCopySize;
size_t nRemainSize = nTextLength;
char * pszNewTextOffset = pszNewText;
const char * pszTextOffset = pszText;
nRepeatCount = nCount;
for (;;)
{
if ((pszNext = fnStrStr(pszTextOffset, pszKeyword)) == NULL)
break;
nCopySize = pszNext - pszTextOffset;
memcpy(pszNewTextOffset, pszTextOffset, nCopySize);
memcpy(pszNewTextOffset + nCopySize, pszReplace, nReplaceLength);
pszTextOffset += nCopySize + nKeywordLength;
pszNewTextOffset += nCopySize + nReplaceLength;
nRemainSize -= nCopySize + nKeywordLength;
if (nRepeatCount > -1 && --nRepeatCount == 0)
break;
}
if (nRemainSize > 0)
memcpy(pszNewTextOffset, pszTextOffset, nRemainSize);
pszNewText[nNewTextLength] = '\0';
return pszNewText;
}
size_t StrReplace2(char * pszDst, const char * pszText, const char * pszKeyword, const char * pszReplace, int nMode, int nCount)
{
if (nCount == 0)
return 0;
const char * (*fnStrStr)(const char *, const char *);
if (nMode == 0)
fnStrStr = (const char*(*)(const char*, const char*))strstr;
else if (nMode == 1)
fnStrStr = stristr;
else
fnStrStr = StrIKeyword;
size_t nKeywordLength = strlen(pszKeyword);
size_t nReplaceLength = strlen(pszReplace);
size_t nRemainSize = strlen(pszText);
char * pszNewTextOffset = pszDst;
const char * pszTextOffset = pszText;
size_t nNewTextLength = 0;
size_t nCopySize;
const char * pszNext;
int nRepeatCount = nCount;
for (;;)
{
if ((pszNext = fnStrStr(pszTextOffset, pszKeyword)) == NULL)
break;
nCopySize = pszNext - pszTextOffset;
memcpy(pszNewTextOffset, pszTextOffset, nCopySize);
memcpy(pszNewTextOffset + nCopySize, pszReplace, nReplaceLength);
pszTextOffset += nCopySize + nKeywordLength;
pszNewTextOffset += nCopySize + nReplaceLength;
nNewTextLength += nCopySize + nReplaceLength;
nRemainSize -= nCopySize + nKeywordLength;
if (nRepeatCount > -1 && --nRepeatCount == 0)
break;
}
if (nNewTextLength == 0)
return 0;
if (nRemainSize > 0)
{
memcpy(pszNewTextOffset, pszTextOffset, nRemainSize);
nNewTextLength += nRemainSize;
}
pszDst[nNewTextLength] = '\0';
return nNewTextLength;
}
const void * memmem_hus(const void * pMem, size_t nMemSize, const void * pKeymem, size_t nKeymemSize)
{
const char * p1 = (const char *)pMem;
const char * p2;
const void * p3;
size_t nP2;
do
{
p2 = (const char *)pKeymem;
nP2 = nKeymemSize;
while (*p1 != *p2)
{
p1++;
nMemSize--;
if (nMemSize <= 0)
return NULL;
}
p3 = p1;
do
{
p1++;
nMemSize--;
p2++;
nP2--;
if (nP2 <= 0)
return p3;
else if (*p1 != *p2)
break;
} while (nMemSize);
} while (nMemSize);
return NULL;
}
+235
View File
@@ -0,0 +1,235 @@
#ifndef STRINGEX__H_
#define STRINGEX__H_
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#ifdef _WIN32
#pragma once
#else
//#ifndef __CYGWIN__
int stricmp(const char * first, const char * last);
int strnicmp(const char * first, const char * last, unsigned int count);
char * strlwr(char * str);
char * strupr(char * str);
//#endif // __CYGWIN__
#endif
char * gets_hus(char * s, int n);
char * stristr(char * pszStr, char * pszSearch);
extern inline const char * stristr(const char * pszStr, const char * pszSearch)
{
return (char *)stristr((char *)pszStr, (char *)pszSearch);
}
extern inline char * strrstr(char * pszStr, char * pszSearch)
{
char * r = NULL;
if (!pszSearch[0])
return (char *)pszStr + strlen(pszStr);
for (;;)
{
char * p = strstr(pszStr, pszSearch);
if (!p)
return r;
r = p;
pszStr = p + 1;
}
}
char * StrIKeyword(char * string, char * strSearch);
extern inline const char * StrIKeyword(const char * string, const char * strSearch)
{
return (char *)StrIKeyword((char *)string, (char *)strSearch);
}
extern inline char * StrNCpy(char * pszBuf, const char * pszStr, size_t nCount)
{
char * pszResult = strncpy(pszBuf, pszStr, nCount);
pszBuf[nCount] = '\0';
return pszResult;
}
const char * StrNStr(const char * string, const char * strSearch, int nCount = -1);
const char * StrNIStr(const char * string, const char * strSearch, int nCount = -1);
const char * StrRChr(const char * string, const char * strStart, char chUntil);
const char * StrStrUntilChr(const char * string, const char * strSearch, char chUntil);
const char * StrStrUntilStr(const char * string, const char * strSearch, const char * strUntil);
const char * StrBetweenCpy(const char * pSrc, const char * pszFront, const char * pszRear, char * pDst);
size_t StrRemoveBetween(char * pszDst, const char * pszSrc, const char * pszFront, const char * pszRear);
int StrCountChar(const char * string, char ch);
int StrCountStr(const char * string, const char * strSearch);
int StrCountRow(const char * string);
char * StrTok(const char * pszSrc, const char * pszDelimit, char * pszTokenBuff); // This function is similar to strtok(), thread safe
void StrTrim(char ** ppsz, size_t nLength, bool bRemoveFront, bool bRemoveRear);
const char * StrNTrimPtr(const char * pszSrc, int nSrcCount = -1);
void StrNTrimCpy(char * pszDst, const char * pszSrc, int nSrcCount = -1);
char * StrReadLine(char * pszDst, const char * pszSrc, int nCount = -1);
const char * StrReplace(const char * pszText, const char * pszKeyword, const char * pszReplace, int nMode = 0, int nCount = -1); // nMode : 0 = case sensitive, 1 = no case, 2 = keyword
size_t StrReplace2(char * pszDst, const char * pszText, const char * pszKeyword, const char * pszReplace, int nMode = 0, int nCount = -1); // nMode : 0 = case sensitive, 1 = no case, 2 = keyword
extern inline bool IsNumeric(const char * psz)
{
const char * p = psz;
while (*p)
{
if (*p < 48 || *p > 57)
return false;
p++;
}
return true;
}
extern inline bool IsZeroString(const char * psz)
{
if (*psz == '\0')
return false;
while (*psz)
{
if (*psz != '0')
return false;
psz++;
}
return true;
}
extern inline int HexToI(char ch)
{
if ((ch >= '0') && (ch <= '9'))
return ch-'0';
else if ((ch >= 'a') && (ch <= 'f'))
return ch-'a'+10;
else if ((ch >= 'A') && (ch <= 'F'))
return ch-'A'+10;
return 0;
}
extern inline bool IsHex(char ch)
{
return (((ch>='0') && (ch <='9')) || ((ch>='a') && (ch <='f')) || ((ch >='A') && (ch <='F')));
}
extern inline int AToH(char * psz)
{
int i = 0;
while (*psz && IsHex(*psz))
{
i = i * 0x10 + HexToI(*psz);
psz++;
}
return i;
}
#if 0
extern inline bool HexStrToVec(std::vector<uint8_t> * pVec, const char * pszHex)
{
uint8_t nValue;
size_t nCount = strlen(pszHex);
for (size_t i = 0; i < nCount; i += 2)
{
nValue = HexToI(pszHex[i]) * 0x10;
nValue += HexToI(pszHex[i + 1]);
pVec->push_back(nValue);
}
return true;
}
#endif
//
extern inline void CharToHex(char * pszDst, const char ch, bool bUpperCase = false)
{
char chCase;
if (bUpperCase)
chCase = 'A';
else
chCase = 'a';
pszDst[0] = (ch >> 4) & 0x0f;
pszDst[1] = ch & 0x0f;
if (pszDst[0] >= 10)
pszDst[0] = pszDst[0] - 10 + chCase;
else
pszDst[0] = pszDst[0] + '0';
if (pszDst[1] >= 10)
pszDst[1] = pszDst[1] - 10 + chCase;
else
pszDst[1] = pszDst[1] + '0';
pszDst[2] = '\0';
}
//extern inline void ArrayToHexString(HString * pstrConverted, const unsigned char * pArray, size_t nSize, bool bUpperCase = false)
//{
// char szHex[4];
// for (int i = 0; i < nSize; i++)
// {
// CharToHex(szHex, pArray[i]);
// *pstrConverted += szHex;
// }
//}
// aaa\r\nbbb -> aaa\0bbb
extern inline char * StrSlice(char * pszBuffer)
{
for (unsigned int i = 0; pszBuffer[i]; i++)
{
if (pszBuffer[i] == '\r' && pszBuffer[i + 1] == '\n')
{
pszBuffer[i] = '\0';
return (pszBuffer + i + 2);
}
else if (pszBuffer[i] == '\n' || pszBuffer[i] == '\r')
{
pszBuffer[i] = '\0';
return (pszBuffer + i + 1);
}
}
return NULL;
}
extern inline char * StrTokenSlice(char * pszLine, char cDelimiter)
{
for (unsigned int i = 0; pszLine[i]; i++)
{
if (pszLine[i] == cDelimiter)
{
pszLine[i] = '\0';
return (pszLine + i + 1);
}
}
return NULL;
}
const void * memmem_hus(const void * pMem, size_t nMemSize, const void * pKeymem, size_t nKeymemSize);
#endif // STRINGEX__H_
+114
View File
@@ -0,0 +1,114 @@
// DebugAssist.h: interface for the DebugAssist class.
//
//////////////////////////////////////////////////////////////////////
#if defined(_WIN32) && !defined(_DEBUG)
#ifndef DEBUGASSIST_H__
#define DEBUGASSIST_H__
#pragma once
#include <DbgHelp.h> // in Platform SDK
//#include <c:\Program Files\Microsoft SDKs\Windows\v5.0\Include\DbgHelp.h>
//or #include <c:\Program Files (x86)\Microsoft SDKs\Windows\v5.0\Include\DbgHelp.h>
//or #include <c:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include\DbgHelp.h>
//or #include <c:\Program Files (x86)\Microsoft Visual Studio 8\VC\PlatformSDK\Include\DbgHelp.h>
#include <tchar.h>
TCHAR g_szDbgModulePathName[2048] = {0,};
TCHAR g_szDumpPathName[2048] = {0,};
LONG TopExceptionFilter(LPEXCEPTION_POINTERS pException)
{
HMODULE hDll = LoadLibrary(g_szDbgModulePathName);
if (hDll == NULL)
{
OutputDebugString(TEXT("tps, ERROR, Can't found DbgHelp.dll file.\n"));
return EXCEPTION_EXECUTE_HANDLER;
}
MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
exceptionInfo.ThreadId = GetCurrentThreadId();
exceptionInfo.ExceptionPointers = pException;
exceptionInfo.ClientPointers = NULL;
BOOL (WINAPI * fnWriteDump)(HANDLE, DWORD, ...);
fnWriteDump = (BOOL (WINAPI *)(HANDLE, DWORD, ...))GetProcAddress(hDll, "MiniDumpWriteDump");
if (fnWriteDump == NULL)
{
OutputDebugString(TEXT("tps, ERROR, Can't found MiniDumpWriteDump interface.\n"));
return EXCEPTION_EXECUTE_HANDLER;
}
HANDLE hFile = CreateFile(g_szDumpPathName, GENERIC_WRITE, FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
fnWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile,
MiniDumpNormal, &exceptionInfo, NULL, NULL);
FreeLibrary(hDll);
CloseHandle(hFile);
return EXCEPTION_EXECUTE_HANDLER;
}
void InitialDumpWriting(LPCTSTR pszDir = NULL, LPCTSTR pszPrefix = NULL)
{
TCHAR szPostFix[32];
SYSTEMTIME systemTime;
GetLocalTime(&systemTime);
_stprintf(szPostFix, TEXT("_%.4d%.2d%.2d%.2d%.2d%.2d.dmp"), systemTime.wYear,
systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
if (pszDir && pszPrefix)
{
// pszDir ex) "C:\\Temp\\"
_tcscpy(g_szDbgModulePathName, pszDir);
_tcscat(g_szDbgModulePathName, TEXT("dbghelp.dll"));
_tcscpy(g_szDumpPathName, pszDir);
_tcscat(g_szDumpPathName, pszPrefix);
_tcscat(g_szDumpPathName, szPostFix);
}
else
{
char szModuleFileName[2048];
GetModuleFileName(NULL, szModuleFileName, sizeof(szModuleFileName));
char szDrive[_MAX_DRIVE], szDir[1024], szFileName[1024], szExt[1024];
_splitpath_s(szModuleFileName, szDrive, _MAX_DRIVE, szDir, 1024, szFileName, 1024, szExt, 1024);
if (pszDir)
{
_tcscpy(g_szDbgModulePathName, pszDir);
_tcscpy(g_szDumpPathName, pszDir);
}
else
{
_tcscpy(g_szDbgModulePathName, szDrive);
_tcscat(g_szDbgModulePathName, szDir);
_tcscpy(g_szDumpPathName, g_szDbgModulePathName);
}
_tcscat(g_szDbgModulePathName, TEXT("dbghelp.dll"));
if (pszPrefix)
{
_tcscat(g_szDumpPathName, pszPrefix);
_tcscat(g_szDumpPathName, szPostFix);
}
else
{
_tcscat(g_szDumpPathName, szFileName);
_tcscat(g_szDumpPathName, szPostFix);
}
}
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)TopExceptionFilter);
}
#endif // DEBUGASSIST_H__
#endif // defined(_WIN32) && !defined(_DEBUG)
+645
View File
@@ -0,0 +1,645 @@
/*---------------------------------------------------------------------------
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (C) 1993 - 2000. Microsoft Corporation. All rights reserved.
MODULE: service.c
PURPOSE: Implements functions required by all Windows NT services
FUNCTIONS:
main(int argc, char **argv);
service_ctrl(DWORD dwCtrlCode);
service_main(DWORD dwArgc, LPTSTR *lpszArgv);
CmdInstallService();
CmdRemoveService();
CmdDebugService(int argc, char **argv);
ControlHandler ( DWORD dwCtrlType );
GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
---------------------------------------------------------------------------*/
#ifdef _WIN32
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <tchar.h>
#include "WinService.h"
#pragma warning(disable:4996)
// internal variables
SERVICE_STATUS g_ssStatus; // current status of the service
SERVICE_STATUS_HANDLE g_sshStatusHandle;
DWORD g_dwWinServiceErr = 0;
TCHAR g_szWinServiceErr[256];
BOOL g_bDebugExecuted = FALSE;
// internal function prototypes
VOID WINAPI service_ctrl(DWORD dwCtrlCode);
VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);
VOID CmdInstallService();
VOID CmdRemoveService();
VOID CmdDebugService(int argc, char **argv);
BOOL WINAPI ControlHandler(DWORD dwCtrlType);
LPTSTR GetLastErrorText(LPTSTR lpszBuf, DWORD dwSize);
//
// FUNCTION: main
//
// PURPOSE: entrypoint for service
//
// PARAMETERS:
// argc - number of command line arguments
// argv - array of command line arguments
//
// RETURN VALUE:
// none
//
// COMMENTS:
// main() either performs the command line task, or
// call StartServiceCtrlDispatcher to register the
// main service thread. When the this call returns,
// the service has stopped, so exit.
//
#if 0 // original code
void __cdecl main(int argc, char **argv)
#else
void WinServiceMain(int argc, char **argv)
#endif
{
SERVICE_TABLE_ENTRY dispatchTable[] =
{
{ TEXT((char *)g_szServiceName), (LPSERVICE_MAIN_FUNCTION)service_main}, { NULL, NULL}
};
if ((argc > 1) && ((*argv[1] == '-') || (*argv[1] == '/')))
{
if (_stricmp("install", argv[1] + 1) == 0)
{
CmdInstallService();
}
else if (_stricmp("remove", argv[1] + 1) == 0)
{
CmdRemoveService();
}
else if (_stricmp("debug", argv[1] + 1) == 0)
{
g_bDebugExecuted = TRUE;
CmdDebugService(argc, argv);
}
else
{
goto dispatch;
}
exit(0);
}
//else
//{
// g_bDebugExecuted = TRUE;
// CmdDebugService(argc, argv);
//}
// if it doesn't match any of the above parameters
// the service control manager may be starting the service
// so we must call StartServiceCtrlDispatcher
dispatch:
const char * pszAppName = strrchr(argv[0], '\\');
if (pszAppName)
{
pszAppName++;
}
else
{
pszAppName = strrchr(argv[0], '/');
if (pszAppName)
pszAppName++;
else
pszAppName = argv[0];
}
// this is just to be friendly
printf("%s -install to install the service\n", pszAppName);
printf("%s -remove to remove the service\n", pszAppName);
//printf("%s -debug <params> to run as a console app for debugging\n", pszAppName);
printf("\nStartServiceCtrlDispatcher being called.\n");
printf("This may take several seconds. Please wait.\n");
#if 1 // original code
if (!StartServiceCtrlDispatcher(dispatchTable))
AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed."));
#endif
}
//
// FUNCTION: service_main
//
// PURPOSE: To perform actual initialization of the service
//
// PARAMETERS:
// dwArgc - number of command line arguments
// lpszArgv - array of command line arguments
//
// RETURN VALUE:
// none
//
// COMMENTS:
// This routine performs the service initialization and then calls
// the user defined ServiceStart() routine to perform majority
// of the work.
//
void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
{
// register our service control handler:
//
g_sshStatusHandle = RegisterServiceCtrlHandler(TEXT(g_szServiceName), service_ctrl);
if (!g_sshStatusHandle)
goto cleanup;
// SERVICE_STATUS members that don't change in example
//
g_ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ssStatus.dwServiceSpecificExitCode = 0;
// report the status to the service control manager.
//
if (!ReportStatusToSCMgr(
SERVICE_START_PENDING, // service state
NO_ERROR, // exit code
3000)) // wait hint
goto cleanup;
ServiceStart(dwArgc, lpszArgv, FALSE);
cleanup:
// try to report the stopped status to the service control manager.
//
if (g_sshStatusHandle)
ReportStatusToSCMgr(SERVICE_STOPPED, g_dwWinServiceErr, 0);
return;
}
//
// FUNCTION: service_ctrl
//
// PURPOSE: This function is called by the SCM whenever
// ControlService() is called on this service.
//
// PARAMETERS:
// dwCtrlCode - type of control requested
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
VOID WINAPI service_ctrl(DWORD dwCtrlCode)
{
// Handle the requested control code.
//
switch (dwCtrlCode)
{
// Stop the service.
//
// SERVICE_STOP_PENDING should be reported before
// setting the Stop Event - hServerStopEvent - in
// ServiceStop(). This avoids a race condition
// which may result in a 1053 - The Service did not respond...
// error.
case SERVICE_CONTROL_STOP:
ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0);
ServiceStop();
return;
// Update the service status.
//
case SERVICE_CONTROL_INTERROGATE:
break;
// invalid control code
//
default:
break;
}
ReportStatusToSCMgr(g_ssStatus.dwCurrentState, NO_ERROR, 0);
}
//
// FUNCTION: ReportStatusToSCMgr()
//
// PURPOSE: Sets the current status of the service and
// reports it to the Service Control Manager
//
// PARAMETERS:
// dwCurrentState - the state of the service
// dwWin32ExitCode - error code to report
// dwWaitHint - worst case estimate to next checkpoint
//
// RETURN VALUE:
// TRUE - success
// FALSE - failure
//
// COMMENTS:
//
BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
BOOL fResult = TRUE;
if (!g_bDebugExecuted) // when debugging we don't report to the SCM
{
if (dwCurrentState == SERVICE_START_PENDING)
g_ssStatus.dwControlsAccepted = 0;
else
g_ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
g_ssStatus.dwCurrentState = dwCurrentState;
g_ssStatus.dwWin32ExitCode = dwWin32ExitCode;
g_ssStatus.dwWaitHint = dwWaitHint;
if ((dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED))
g_ssStatus.dwCheckPoint = 0;
else
g_ssStatus.dwCheckPoint = dwCheckPoint++;
// Report the status of the service to the service control manager.
//
if (!(fResult = SetServiceStatus(g_sshStatusHandle, &g_ssStatus)))
{
AddToMessageLog(TEXT("SetServiceStatus"));
}
}
return fResult;
}
//
// FUNCTION: AddToMessageLog(LPTSTR lpszMsg)
//
// PURPOSE: Allows any thread to log an error message
//
// PARAMETERS:
// lpszMsg - text for message
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
VOID AddToMessageLog(LPTSTR lpszMsg)
{
//TCHAR szMsg [(sizeof(SZSERVICENAME) / sizeof(TCHAR)) + 100 ];
TCHAR * pszMsg = (TCHAR *)malloc(((strlen(g_szServiceName) / sizeof(TCHAR)) + 100) * sizeof(TCHAR));
HANDLE hEventSource;
LPTSTR lpszStrings[2];
if (!g_bDebugExecuted)
{
g_dwWinServiceErr = GetLastError();
// Use event logging to log the error.
//
hEventSource = RegisterEventSource(NULL, TEXT(g_szServiceName));
_stprintf(pszMsg, TEXT("%s error: %d"), TEXT(g_szServiceName), g_dwWinServiceErr);
lpszStrings[0] = pszMsg;
lpszStrings[1] = lpszMsg;
if (hEventSource != NULL)
{
ReportEvent(hEventSource, // handle of event source
EVENTLOG_ERROR_TYPE, // event type
0, // event category
0, // event ID
NULL, // current user's SID
2, // strings in lpszStrings
0, // no bytes of raw data
(LPCTSTR *)lpszStrings, // array of error strings
NULL); // no raw data
DeregisterEventSource(hEventSource);
}
}
free(pszMsg);
}
///////////////////////////////////////////////////////////////////
//
// The following code handles service installation and removal
//
//
// FUNCTION: CmdInstallService()
//
// PURPOSE: Installs the service
//
// PARAMETERS:
// none
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
void CmdInstallService()
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
TCHAR szPath[2048];
if (GetModuleFileName(NULL, szPath, 2048) == 0)
{
_tprintf(TEXT("Unable to install %s - %s\n"), TEXT(g_szServiceDisplayName), GetLastErrorText(g_szWinServiceErr, 256));
return;
}
schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE // access required
);
if (schSCManager)
{
schService = CreateService(
schSCManager, // SCManager database
TEXT(g_szServiceName), // name of service
TEXT(g_szServiceDisplayName), // name to display
SERVICE_QUERY_STATUS | SERVICE_CHANGE_CONFIG | SERVICE_START, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
//SERVICE_DEMAND_START, // start type
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL, // error control type
szPath, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
TEXT(g_szDependencies), // dependencies
NULL, // LocalSystem account
NULL); // no password
if (g_szServiceDesc && g_szServiceDesc[0] != TEXT('\0'))
{
SERVICE_DESCRIPTION serviceDesc;
serviceDesc.lpDescription = (LPSTR)g_szServiceDesc;
if (ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &serviceDesc) == 0)
_tprintf(TEXT("ChangeServiceConfig2 failed - %s\n"), GetLastErrorText(g_szWinServiceErr, 256));
}
SC_ACTION scAction[1];
scAction[0].Type = SC_ACTION_RESTART;
scAction[0].Delay = 10000;
SERVICE_FAILURE_ACTIONS serviceFailAction;
serviceFailAction.lpsaActions = (SC_ACTION *)scAction;
serviceFailAction.cActions = 1;
serviceFailAction.dwResetPeriod = 600;
serviceFailAction.lpRebootMsg = TEXT("");
serviceFailAction.lpCommand = TEXT("");
if (ChangeServiceConfig2(schService, SERVICE_CONFIG_FAILURE_ACTIONS, &serviceFailAction) == 0)
_tprintf(TEXT("ChangeServiceConfig2 failed 2 - %s\n"), GetLastErrorText(g_szWinServiceErr, 256));
if (schService)
{
_tprintf(TEXT("%s installed.\n"), TEXT(g_szServiceDisplayName));
CloseServiceHandle(schService);
}
else
{
_tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(g_szWinServiceErr, 256));
}
CloseServiceHandle(schSCManager);
}
else
_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(g_szWinServiceErr, 256));
}
//
// FUNCTION: CmdRemoveService()
//
// PURPOSE: Stops and removes the service
//
// PARAMETERS:
// none
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
void CmdRemoveService()
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_CONNECT // access required
);
if (schSCManager)
{
schService = OpenService(schSCManager, TEXT(g_szServiceName), DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS);
if (schService)
{
// try to stop the service
if (ControlService(schService, SERVICE_CONTROL_STOP, &g_ssStatus))
{
_tprintf(TEXT("Stopping %s."), TEXT(g_szServiceDisplayName));
Sleep(1000);
while (QueryServiceStatus(schService, &g_ssStatus))
{
if (g_ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
{
_tprintf(TEXT("."));
Sleep(1000);
}
else
break;
}
if (g_ssStatus.dwCurrentState == SERVICE_STOPPED)
_tprintf(TEXT("\n%s stopped.\n"), TEXT(g_szServiceDisplayName));
else
_tprintf(TEXT("\n%s failed to stop.\n"), TEXT(g_szServiceDisplayName));
}
// now remove the service
if (DeleteService(schService))
_tprintf(TEXT("%s removed.\n"), TEXT(g_szServiceDisplayName));
else
_tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(g_szWinServiceErr, 256));
CloseServiceHandle(schService);
}
else
_tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(g_szWinServiceErr, 256));
CloseServiceHandle(schSCManager);
}
else
_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(g_szWinServiceErr, 256));
}
///////////////////////////////////////////////////////////////////
//
// The following code is for running the service as a console app
//
//
// FUNCTION: CmdDebugService(int argc, char ** argv)
//
// PURPOSE: Runs the service as a console application
//
// PARAMETERS:
// argc - number of command line arguments
// argv - array of command line arguments
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
void CmdDebugService(int argc, char ** argv)
{
DWORD dwArgc;
LPTSTR *lpszArgv;
#ifdef UNICODE
lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc));
if (NULL == lpszArgv)
{
// CommandLineToArvW failed!!
_tprintf(TEXT("CmdDebugService CommandLineToArgvW returned NULL\n"));
return;
}
#else
dwArgc = (DWORD) argc;
lpszArgv = argv;
#endif
_tprintf(TEXT("Debugging %s.\n"), TEXT(g_szServiceDisplayName));
SetConsoleCtrlHandler(ControlHandler, TRUE);
ServiceStart(dwArgc, lpszArgv, TRUE);
#ifdef UNICODE
// Must free memory allocated for arguments
GlobalFree(lpszArgv);
#endif // UNICODE
}
//
// FUNCTION: ControlHandler ( DWORD dwCtrlType )
//
// PURPOSE: Handled console control events
//
// PARAMETERS:
// dwCtrlType - type of control event
//
// RETURN VALUE:
// True - handled
// False - unhandled
//
// COMMENTS:
//
BOOL WINAPI ControlHandler(DWORD dwCtrlType)
{
switch (dwCtrlType)
{
case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate
case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
_tprintf(TEXT("Stopping %s.\n"), TEXT(g_szServiceDisplayName));
ServiceStop();
return TRUE;
break;
}
return FALSE;
}
//
// FUNCTION: GetLastErrorText
//
// PURPOSE: copies error message text to string
//
// PARAMETERS:
// lpszBuf - destination buffer
// dwSize - size of buffer
//
// RETURN VALUE:
// destination buffer
//
// COMMENTS:
//
LPTSTR GetLastErrorText(LPTSTR lpszBuf, DWORD dwSize)
{
DWORD dwRet;
LPTSTR lpszTemp = NULL;
dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
GetLastError(),
LANG_NEUTRAL,
(LPTSTR)&lpszTemp,
0,
NULL);
// supplied buffer is not long enough
if (!dwRet || ((long)dwSize < (long)dwRet + 14))
lpszBuf[0] = TEXT('\0');
else
{
lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); //remove cr and newline character
_stprintf(lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError());
}
if (lpszTemp)
LocalFree((HLOCAL) lpszTemp);
return lpszBuf;
}
#endif _WIN32
+120
View File
@@ -0,0 +1,120 @@
/*---------------------------------------------------------------------------
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (C) 1993 - 2000. Microsoft Corporation. All rights reserved.
MODULE: service.h
Comments: The use of this header file and the accompanying service.c
file simplifies the process of writting a service. You as a developer
simply need to follow the TODO's outlined in this header file, and
implement the ServiceStart() and ServiceStop() functions.
There is no need to modify the code in service.c. Just add service.c
to your project and link with the following libraries...
libcmt.lib kernel32.lib advapi.lib shell32.lib
This code also supports unicode. Be sure to compile both service.c and
and code #include "service.h" with the same Unicode setting.
Upon completion, your code will have the following command line interface
<service exe> -? to display this list
<service exe> -install to install the service
<service exe> -remove to remove the service
<service exe> -debug <params> to run as a console app for debugging
Note: This code also implements Ctrl+C and Ctrl+Break handlers
when using the debug option. These console events cause
your ServiceStop routine to be called
Also, this code only handles the OWN_SERVICE service type
running in the LOCAL_SYSTEM security context.
To control your service ( start, stop, etc ) you may use the
Services control panel applet or the NET.EXE program.
To aid in writing/debugging service, the
SDK contains a utility (MSTOOLS\BIN\SC.EXE) that
can be used to control, configure, or obtain service status.
SC displays complete status for any service/driver
in the service database, and allows any of the configuration
parameters to be easily changed at the command line.
For more information on SC.EXE, type SC at the command line.
------------------------------------------------------------------------------*/
#ifdef _WIN32
#ifndef WIN_SERVICE__H_
#define WIN_SERVICE__H_
extern const char * g_szServiceName; // internal name of the service
extern const char * g_szServiceDisplayName; // displayed name of the service
extern const char * g_szDependencies; // list of service dependencies - "dep1\0dep2\0\0"
extern const char * g_szServiceDesc;
//////////////////////////////////////////////////////////////////////////////
//// todo: ServiceStart()must be defined by in your code.
//// The service should use ReportStatusToSCMgr to indicate
//// progress. This routine must also be used by StartService()
//// to report to the SCM when the service is running.
////
//// If a ServiceStop procedure is going to take longer than
//// 3 seconds to execute, it should spawn a thread to
//// execute the stop code, and return. Otherwise, the
//// ServiceControlManager will believe that the service has
//// stopped responding
////
VOID ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv, BOOL bConsoleMode);
VOID ServiceStop();
//////////////////////////////////////////////////////////////////////////////
//// The following are procedures which
//// may be useful to call within the above procedures,
//// but require no implementation by the user.
//// They are implemented in service.c
//
// FUNCTION: ReportStatusToSCMgr()
//
// PURPOSE: Sets the current status of the service and
// reports it to the Service Control Manager
//
// PARAMETERS:
// dwCurrentState - the state of the service
// dwWin32ExitCode - error code to report
// dwWaitHint - worst case estimate to next checkpoint
//
// RETURN VALUE:
// TRUE - success
// FALSE - failure
//
BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
//
// FUNCTION: AddToMessageLog(LPTSTR lpszMsg)
//
// PURPOSE: Allows any thread to log an error message
//
// PARAMETERS:
// lpszMsg - text for message
//
// RETURN VALUE:
// none
//
void AddToMessageLog(LPTSTR lpszMsg);
void WinServiceMain(int argc, char **argv);
#endif // WIN_SERVICE__H_
#endif _WIN32