Files
2026-05-20 03:08:08 +09:00

1858 lines
45 KiB
C++

#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "winmm.lib")
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> // sockaddr_in
#include <arpa/inet.h> // inet_ntoa()
#include <unistd.h> // close()
#include <netdb.h> // gethostbyname()
#include <fcntl.h> // F_GETFL, O_NONBLOCK
#include <netinet/tcp.h> // TCP_NODELAY
#include <string.h>
#include <errno.h>
#include <time.h>
//#include <pthread.h>
#include <stdarg.h>
typedef int BOOL;
#define TRUE 1
#define FALSE 0
#define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR (-1)
#define SD_RECEIVE SHUT_RD
#define SD_SEND SHUT_WR
#define SD_BOTH SHUT_RDWR
typedef int SOCKET;
#define closesocket close
inline unsigned int 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);
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
uint64_t ms = (uint64_t)ts.tv_sec * 1000ULL +
(uint64_t)ts.tv_nsec / 1000000ULL;
return (unsigned int)ms; // 32bit wrap intentionally
#endif
}
#define GetTickCount timeGetTime
inline void Sleep(unsigned int 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
}
#endif
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <sys/stat.h>
#ifdef _DEBUG
#include <crtdbg.h>
#endif
#include <list>
//////////////////////////////////////////////////////////////////////////////
inline int GetSockError()
{
#ifdef _WIN32
return WSAGetLastError();
#else
return errno;
#endif
}
int GetSockOptError(SOCKET sock)
{
int nOptVal;
socklen_t nOptLen = sizeof(int);
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)(&nOptVal), &nOptLen) < 0)
return GetSockError();
return nOptVal;
}
#ifdef _WIN32
VOID WINAPI FlsBufferFree(PVOID lpFlsData)
{
if (lpFlsData != NULL)
{
fprintf(stdout, "DEBUG, FlsBufferFree, lpFlsData = 0x%p\n", lpFlsData);
LocalFree(lpFlsData);
}
}
char * GetLocalStorageBuffer(DWORD nFlsIdx, size_t nSize)
{
char * pszBuffer = (char *)FlsGetValue(nFlsIdx);
if (pszBuffer == NULL)
{
pszBuffer = (char *)LocalAlloc(LPTR, nSize);
if (pszBuffer == NULL)
return NULL;
FlsSetValue(nFlsIdx, pszBuffer);
}
return pszBuffer;
}
#endif
const char * GetErrorStr(int nError)
{
#ifdef _WIN32
static DWORD nFlsIdx = FLS_OUT_OF_INDEXES;
if (nFlsIdx == FLS_OUT_OF_INDEXES)
nFlsIdx = FlsAlloc(FlsBufferFree);
char * pszBuffer = (char *)GetLocalStorageBuffer(nFlsIdx, 512);
if (pszBuffer == NULL)
return "[SystemError], Failed to LocalAlloc";
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
nError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), pszBuffer, 512, NULL) == 0)
{
sprintf(pszBuffer, "Unknown Error", nError);
}
return pszBuffer;
#else
return strerror(nError);
#endif
}
inline unsigned int TimeDiff(unsigned int nTimePrev, unsigned int nTimeCurr)
{
if (nTimePrev <= nTimeCurr)
return nTimeCurr - nTimePrev;
return nTimeCurr + (0xFFFFFFFFU - nTimePrev) + 1U;
}
// file //////////////////////////////////////////////////////////////////////
class CtFile
{
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;
}
////
CtFile()
{
m_nFile = -1;
}
~CtFile()
{
Close();
}
int GetFile() { return m_nFile; }
bool Open(const char * pszFileName, int nMode, bool bIsBinary = true, bool bIsContinue = true)
{
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_WRONLY) == FMODE_WRONLY || (nMode & FMODE_RW) == FMODE_RW))
oflag |= O_TRUNC;
#ifdef _WIN32
if (bIsBinary)
oflag |= O_BINARY;
else
oflag |= O_TEXT;
m_nFile = open(pszFileName, oflag, S_IREAD | S_IWRITE);
#else
m_nFile = open(pszFileName, oflag, S_IREAD | S_IWRITE | S_IRGRP | S_IROTH);
#endif
if (m_nFile == -1)
return false;
if (bIsContinue && ((nMode & FMODE_WRONLY) == FMODE_WRONLY || (nMode & FMODE_RW) == FMODE_RW))
lseek(m_nFile, 0L, SEEK_END);
return true;
}
void Close()
{
if (m_nFile != -1)
{
close(m_nFile);
m_nFile = -1;
}
}
int Read(void * buffer, unsigned int count)
{
return read(m_nFile, buffer, count);
}
int Write(const void * buffer, unsigned int count)
{
return write(m_nFile, buffer, count);
}
private:
int m_nFile;
};
//////////////////////////////////////////////////////////////////////////////
class IompObject
{
public:
enum {
IOMP_DISABLE = 0,
IOMP_READY = 1,
IOMP_CONNECTING = 2,
IOMP_RECONNECTING = 3,
IOMP_LISTENING = 4,
IOMP_CLOSING = 5,
IOMP_REMOVE = 6
};
SOCKET m_sock;
int m_nState;
struct sockaddr_in m_sai; // remote or listen
unsigned int m_nPrevTick; // prev setted time
unsigned int m_nConnectTimeOut; // for connect timeout
unsigned int m_nAutoReconnectInterval; // 0: no reconnect, 1~ : msec, reconnect interval time
IompObject()
{
m_nState = IOMP_DISABLE;
memset(&m_sai, 0, sizeof(struct sockaddr_in)); // remote or listen
m_nPrevTick = 0;
m_nConnectTimeOut = 0;
m_nAutoReconnectInterval = 0;
}
int Create()
{
// create socket
m_sock = socket(AF_INET, SOCK_STREAM, 0);
if (m_sock == INVALID_SOCKET)
{
fprintf(stderr, "[ERROR], Failed to socket()\n");
return -1;
}
// Set non blocking mode
#ifdef _WIN32
ULONG nNonBlock = 1;
if (ioctlsocket(m_sock, FIONBIO, &nNonBlock) == SOCKET_ERROR)
#else
int nFlags = fcntl(m_sock, F_GETFL, 0);
if (fcntl(m_sock, F_SETFL, nFlags | O_NONBLOCK) == -1)
#endif
{
int nSockError = GetSockError();
fprintf(stderr, "[ERROR], Failed to ioctlsocket. socket = %d, error = %s(%d)\n", m_sock, GetErrorStr(nSockError), nSockError);
closesocket(m_sock);
return -1;
}
int nBuffSize = 1024 * 1024 * 4; // 4Mbyte
if (setsockopt(m_sock, SOL_SOCKET, SO_SNDBUF, (const char *)&nBuffSize, sizeof(nBuffSize)) == SOCKET_ERROR)
fprintf(stderr, "[WARN], Failed to setsockopt SO_SNDBUF, socket = %d\n", m_sock);
if (setsockopt(m_sock, SOL_SOCKET, SO_RCVBUF, (const char *)&nBuffSize, sizeof(nBuffSize)) == SOCKET_ERROR)
fprintf(stderr, "[WARN], Failed to setsockopt SO_RCVBUF, socket = %d\n", m_sock);
return 0;
}
int Bind(const char * pszIp, unsigned short nPort)
{
#define REUSEADDR_
#ifdef REUSEADDR_
int nOptVal = 1;
setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&nOptVal, sizeof(nOptVal)); // for multiple ip in UNIX
#endif
if (pszIp == NULL || pszIp[0] == '\0')
m_sai.sin_addr.s_addr = htonl(INADDR_ANY);
else
m_sai.sin_addr.s_addr = inet_addr(pszIp);
m_sai.sin_family = AF_INET;
m_sai.sin_port = htons(nPort);
if (bind(m_sock, (struct sockaddr *)&m_sai, sizeof(struct sockaddr)) == -1)
{
int nSockError = GetSockError();
fprintf(stderr, "[ERROR], Failed to bind.(%s:%d) socket = %d, error = %s(%d)\n", inet_ntoa(m_sai.sin_addr), ntohs(m_sai.sin_port),
m_sock, GetErrorStr(nSockError), nSockError);
closesocket(m_sock);
return -1;
}
fprintf(stdout, "INFO, Succeeded to bind.(%s:%d), socket = %d\n", inet_ntoa(m_sai.sin_addr), ntohs(m_sai.sin_port), m_sock); // listen ip:port
return 0;
}
int Listen(int nBackLog)
{
if (listen(m_sock, nBackLog) == -1)
{
int nSockError = GetSockError();
fprintf(stderr, "[ERROR], Failed to listen. socket = %d, error = %s(%d)\n", m_sock, GetErrorStr(nSockError), nSockError);
closesocket(m_sock);
return -1;
}
fprintf(stdout, "INFO, Succeeded to listen.(%s:%d), socket = %d\n", inet_ntoa(m_sai.sin_addr), ntohs(m_sai.sin_port), m_sock); // listen ip:port
m_nState = IOMP_LISTENING;
return 0;
}
int ConnectProc(unsigned int nCurrTick)
{
int nResult = connect(m_sock, (struct sockaddr *)&m_sai, sizeof(struct sockaddr));
#ifdef _WIN32
if (nResult == SOCKET_ERROR && GetSockError() != WSAEWOULDBLOCK)
#else
if (nResult == SOCKET_ERROR && errno != EWOULDBLOCK && errno != EINPROGRESS)
#endif
{
int nSockError = GetSockError();
fprintf(stderr, "[ERROR], Failed to connect. socket = %d, error = %s(%d)\n", m_sock, GetErrorStr(nSockError), nSockError);
closesocket(m_sock);
m_sock = INVALID_SOCKET;
return -1;
}
m_nPrevTick = nCurrTick;
m_nState = IOMP_CONNECTING;
fprintf(stdout, "INFO, TCP connecting... to %s:%d, socket = %d\n", inet_ntoa(m_sai.sin_addr), ntohs(m_sai.sin_port), m_sock);
return 0;
}
int Connect(const char * pszIp, unsigned short nPort, unsigned int nTimeout, unsigned int nCurrTick = 0, unsigned int nAutoReconnectInterval = 0)
{
if (m_sock == INVALID_SOCKET)
{
fprintf(stderr, "[ERROR], This socket did not created.\n");
return -1;
}
m_sai.sin_addr.s_addr = inet_addr(pszIp);
m_sai.sin_family = AF_INET;
m_sai.sin_port = htons(nPort);
m_nConnectTimeOut = nTimeout;
m_nAutoReconnectInterval = nAutoReconnectInterval;
return ConnectProc(nCurrTick);
}
int Disconnect()
{
return shutdown(m_sock, SD_SEND);
}
bool IsConnectTimeout(unsigned int nCurrTick)
{
//fprintf(stdout, "DEBUG, m_nPrevTick = %d, nCurrTick = %d\n", m_nPrevTick, nCurrTick);
if (m_nPrevTick == 0)
{
m_nPrevTick = nCurrTick;
return false;
}
if (m_nConnectTimeOut <= 0)
return false;
if (m_nConnectTimeOut <= TimeDiff(m_nPrevTick, nCurrTick))
return true;
return false;
}
int TcpCompleteSend(const char * pPacket, int nPacketSize)
{
off_t nSentSize;
const char * pszPacketOffset = pPacket;
while (nPacketSize > 0)
{
nSentSize = send(m_sock, pszPacketOffset, nPacketSize, 0);
if (nSentSize <= 0)
{
int nSockError = GetSockError();
fprintf(stderr, "[ERROR], Failed to send, sock = %d, error = %s(%d)\n", m_sock, GetErrorStr(nSockError), nSockError);
return -1;
}
nPacketSize -= nSentSize;
pszPacketOffset += nSentSize;
}
return 0;
}
int Receive(char * pBuffer, int nMaxSize)
{
int nReceived = recv(m_sock, pBuffer, nMaxSize, 0);
if (nReceived == -1)
{
int nSockError = GetSockError();
fprintf(stdout, "INFO, The virtual circuit was reset by the remote side executing a \"hard\" or \"abortive\" close, socket = %d, error = %s(%d)\n", m_sock, GetErrorStr(nSockError), nSockError);
shutdown(m_sock, SD_BOTH);
return -1;
}
else if (nReceived == 0)
{
fprintf(stdout, "INFO, The virtual circuit was reset by the remote side executing a \"gracefull\" shutdown, socket = %d\n", m_sock);
shutdown(m_sock, SD_SEND);
return -1;
}
return nReceived;
}
};
template<class _T>
class IompDispatcher
{
public:
IompDispatcher()
{
//m_nDispachInterval = 500; //msec, set timer
//m_nDispachInterval = 200; //msec, set timer
m_nDispachInterval = 0; //msec, set timer
m_bTerminate = false;
}
virtual ~IompDispatcher()
{
}
_T * AddSocket(_T & t)
{
m_listIomp.push_front(t);
return &m_listIomp.front();
}
int Dispatch()
{
fprintf(stdout, "INFO, IompDispatcher.Dispatch() started.\n");
fd_set fsRead, fsWrite, fsError;
int nSelectResult, nFdMax, nFdCount;
typename std::list<_T>::iterator iter;
struct timeval tvWait;
unsigned int nCurrTick = 0, nPrevTimerTick = 0;
while (m_bTerminate == false)
{
//#define TEST_TERMINATE_
#ifdef TEST_TERMINATE_ //TestCode
//static int nTestCount = 2000;
static int nTestCount = 1000;
if (nTestCount-- < 0)
break;
#endif
nCurrTick = GetTickCount();
if (m_nDispachInterval > 0 && m_nDispachInterval <= TimeDiff(nPrevTimerTick, nCurrTick))
{
OnDispatchTimer(nCurrTick);
nPrevTimerTick = nCurrTick;
}
FD_ZERO(&fsRead);
FD_ZERO(&fsWrite);
FD_ZERO(&fsError);
nFdMax = 0;
nFdCount = 0;
for (iter = m_listIomp.begin(); iter != m_listIomp.end(); iter++)
{
if (iter->m_nState == IompObject::IOMP_REMOVE)
{
OnIompDelete(&*iter, nCurrTick);
iter = m_listIomp.erase(iter);
if (m_listIomp.empty() || iter == m_listIomp.end())
break;
}
else if (iter->m_nState == IompObject::IOMP_CLOSING)
{
int nResult = OnIompClose(&*iter, nCurrTick);
iter->m_nPrevTick = nCurrTick;
closesocket(iter->m_sock);
if (iter->m_nAutoReconnectInterval > 0)
{
iter->m_sock = INVALID_SOCKET;
iter->m_nState = IompObject::IOMP_RECONNECTING;
}
else if (nResult == 0)
{
iter->m_nState = IompObject::IOMP_REMOVE;
}
else
{
iter->m_sock = INVALID_SOCKET;
iter->m_nState = IompObject::IOMP_DISABLE;
}
}
else if (iter->m_nState == IompObject::IOMP_RECONNECTING)
{
if (iter->m_nAutoReconnectInterval <= TimeDiff(iter->m_nPrevTick, nCurrTick))
{
if ((iter->Create()) == -1)
iter->m_nState = IompObject::IOMP_REMOVE;
else if (iter->ConnectProc(nCurrTick) == -1)
iter->m_nState = IompObject::IOMP_REMOVE;
}
}
else if (iter->m_nState == IompObject::IOMP_READY || iter->m_nState == IompObject::IOMP_LISTENING)
{
if (iter->m_nState == INVALID_SOCKET)
fprintf(stderr, "[ERROR_DEBUG], Invalid logic. socket = %d\n", iter->m_nState, iter->m_sock);
FD_SET(iter->m_sock, &fsRead);
//FD_SET(iter->m_sock, &fsError);
nFdCount++;
#ifndef _WIN32
if (nFdMax < iter->m_sock)
nFdMax = iter->m_sock;
#endif
}
else if (iter->m_nState == IompObject::IOMP_CONNECTING)
{
if (iter->IsConnectTimeout(nCurrTick))
{
fprintf(stdout, "[WARN], Failed to connect because of timeout. socket = %d\n", iter->m_sock);
OnIompConnect(&*iter, false, nCurrTick);
shutdown(iter->m_sock, SD_BOTH);
iter->m_nState = IompObject::IOMP_CLOSING;
}
else
{
if (iter->m_nState == INVALID_SOCKET)
fprintf(stderr, "[ERROR_DEBUG], Invalid logic. socket = %d\n", iter->m_nState, iter->m_sock);
FD_SET(iter->m_sock, &fsWrite);
nFdCount++;
#ifndef _WIN32
if (nFdMax < iter->m_sock)
nFdMax = iter->m_sock;
#endif
}
}
#if 0 // send buffer version
if (iter->m_nState != IompObject::IOMP_DISABLE && iter->m_nState != IompObject::IOMP_CLOSING && iter->m_nState != IompObject::IOMP_REMOVE &&
pSocket->GetSendBuffer()->empty() == false)
{
if (iter->m_nState == INVALID_SOCKET)
fprintf(stderr, "[ERROR_DEBUG], Invalid logic. socket = %d\n", iter->m_nState, iter->m_sock);
FD_SET(iter->m_sock, &fsWrite);
nFdCount++;
#ifndef _WIN32
if (nFdMax < iter->m_sock)
nFdMax = iter->m_sock;
#endif
}
#endif
}
if (m_listIomp.empty() || nFdCount == 0)
{
Sleep(5);
continue;
}
//#define TEST_INTERVAL_
#ifdef TEST_INTERVAL_
tvWait.tv_sec = 3; //TestCode
tvWait.tv_usec = 0;
#else
tvWait.tv_sec = 0;
tvWait.tv_usec = 50000; // 50 msec
#endif
//nSelectResult = select(nFdMax + 1, &fsRead, &fsWrite, &fsError, &tvWait);
nSelectResult = select(nFdMax + 1, &fsRead, &fsWrite, NULL, &tvWait);
//fprintf(stdout, "DEBUG, nSelectResult = %d\n", nSelectResult);
if (nSelectResult == 0)
{
continue; // timeout
}
else if (nSelectResult == -1)
{
int nSockError = GetSockError();
fprintf(stdout, "[WARN], Failed to select. error = %s(%d)\n", GetErrorStr(nSockError), nSockError);
Sleep(5);
continue;
}
for (iter = m_listIomp.begin(); iter != m_listIomp.end(); iter++)
{
if (iter->m_sock == INVALID_SOCKET ||
iter->m_nState == IompObject::IOMP_DISABLE || iter->m_nState == IompObject::IOMP_CLOSING || iter->m_nState == IompObject::IOMP_REMOVE)
continue;
if (FD_ISSET(iter->m_sock, &fsRead) != 0)
{
if (iter->m_nState == IompObject::IOMP_LISTENING)
{
_T iompSocket;
socklen_t len = sizeof(struct sockaddr);
if ((iompSocket.m_sock = accept(iter->m_sock, (struct sockaddr *)&iompSocket.m_sai, &len)) == INVALID_SOCKET)
{
int nSockError = GetSockError();
fprintf(stderr, "[ERROR], Failed to accept. socket = %d, error = %s(%d)\n", iter->m_sock, GetErrorStr(nSockError), nSockError);
}
else
{
fprintf(stdout, "INFO, Succeeded to accept.(%s:%d), socket = %d\n", inet_ntoa(iter->m_sai.sin_addr), ntohs(iter->m_sai.sin_port), iter->m_sock); // listen ip:port
fprintf(stdout, "INFO, Accepted src address (%s:%d), socket = %d\n", inet_ntoa(iompSocket.m_sai.sin_addr), ntohs(iompSocket.m_sai.sin_port), iompSocket.m_sock); // remote ip:port
if (OnIompAccept(&iompSocket, nCurrTick) != -1)
{
// Set non blocking mode
#ifdef _WIN32
ULONG nNonBlock = 1;
if (ioctlsocket(iompSocket.m_sock, FIONBIO, &nNonBlock) == SOCKET_ERROR)
#else
int nFlags = fcntl(iompSocket.m_sock, F_GETFL, 0);
if (fcntl(iompSocket.m_sock, F_SETFL, nFlags | O_NONBLOCK) == -1)
#endif
{
int nSockError = GetSockError();
fprintf(stderr, "[ERROR], Failed to ioctlsocket. socket = %d, error = %s(%d)\n", iompSocket.m_sock, GetErrorStr(nSockError), nSockError);
closesocket(iompSocket.m_sock);
}
else
{
iompSocket.m_nState = IompObject::IOMP_READY;
iompSocket.m_nPrevTick = nCurrTick;
m_listIomp.push_front(iompSocket);
}
}
else
{
closesocket(iompSocket.m_sock);
}
}
}
else if (iter->m_nState == IompObject::IOMP_READY)
{
if (OnIompReceive(&*iter, nCurrTick) == -1)
{
shutdown(iter->m_sock, SD_SEND);
iter->m_nState = IompObject::IOMP_CLOSING;
}
iter->m_nPrevTick = nCurrTick;
}
FD_CLR(iter->m_sock, &fsRead);
if (--nSelectResult <= 0)
break;
}
if (FD_ISSET(iter->m_sock, &fsWrite) != 0)
{
if (iter->m_nState == IompObject::IOMP_CONNECTING)
{
int nSocketOptError = GetSockOptError(iter->m_sock);
if (nSocketOptError != 0)
{
fprintf(stderr, "[ERROR], Failed to connect.(%s:%d) socket = %d, error = %s(%d)\n",
inet_ntoa(iter->m_sai.sin_addr), ntohs(iter->m_sai.sin_port), iter->m_sock, GetErrorStr(nSocketOptError), nSocketOptError);
OnIompConnect(&*iter, false, nCurrTick);
shutdown(iter->m_sock, SD_BOTH);
iter->m_nState = IompObject::IOMP_CLOSING;
}
else
{
fprintf(stdout, "INFO, Succeeded to connect.(%s:%d) socket = %d\n",
inet_ntoa(iter->m_sai.sin_addr), ntohs(iter->m_sai.sin_port), iter->m_sock);
OnIompConnect(&*iter, true, nCurrTick);
iter->m_nState = IompObject::IOMP_READY;
}
iter->m_nPrevTick = nCurrTick;
}
//else if (iter->m_nState == IompObject::IOMP_READY)
//{
// if (pSocket->OnSendRetry() < 0) // remain packet send
// {
// HLOGF(15, "[TRACE], MpsDisp, Failed to OnSendRetry socket = %d\n", pSocket->GetSocket());
// pSocket->FinishTcp();
// }
//}
FD_CLR(iter->m_sock, &fsWrite);
if (--nSelectResult <= 0)
break;
}
}
}
return false;
}
protected:
virtual int OnIompConnect(_T * pIomp, bool bIsSuccess, unsigned int nCurrTick) { return 0; }
virtual int OnIompReceive(_T * pIomp, unsigned int nCurrTick) { return 0; }
virtual int OnIompAccept(_T * pIomp, unsigned int nCurrTick) { return 0; }
virtual int OnIompClose(_T * pIomp, unsigned int nCurrTick) { return 0; }
virtual int OnIompDelete(_T * pIomp, unsigned int nCurrTick) { return 0; }
virtual void OnDispatchTimer(unsigned int nCurrTick) {}
protected:
unsigned int m_nDispachInterval; //msec
bool m_bTerminate;
std::list<_T> m_listIomp;
};
//////////////////////////////////////////////////////////////////////////////
void get_crc(unsigned char* data, int length, unsigned short* crc)
{
int i;
//unsigned temp;
unsigned short temp;
unsigned short SEED = 0x8005;
*crc = 0xffff;
do {
temp = *data++ & 0xff;
for (i = 0; i < 8; i++) {
if ((*crc & 0x0001) ^ (temp & 0x01))
*crc = (*crc >> 1) ^ SEED;
else
*crc >>= 1;
temp >>= 1;
}
} while (--length);
*crc = ~*crc;
temp = *crc;
*crc = (*crc << 8) | ((temp >> 8) & 0xff);
return;
}
int SendToKicc(IompObject * pIomp, unsigned short cmd, const char * pData, size_t nDataSize)
{
volatile unsigned char pPacket[8192];
memset((void *)pPacket, 0, 8192);
volatile unsigned char * ptr = pPacket;
*ptr++ = 0x02;
volatile unsigned char * LEN = ptr;
unsigned short nLen = htons(6 + nDataSize);
memcpy((void *)ptr, (void *)&nLen, sizeof(unsigned short));
#if 0
unsigned short tmpLen;
memcpy((void *)&tmpLen, (void *)ptr, sizeof(unsigned short));
printf("tmpLen = %d, %d\n", tmpLen, ntohs(tmpLen));
#endif
ptr += 2;
*ptr++ = 0;
*ptr++ = 0xFB;
*ptr++ = 0x14;
*ptr++ = cmd;
if (nDataSize > 0)
{
memcpy((void *)ptr, pData, nDataSize);
ptr += nDataSize;
}
*ptr++ = 0x03;
unsigned short * cic = (unsigned short *)ptr;
get_crc((unsigned char *)LEN, 7 + nDataSize, cic);
*cic = htons(*cic);
printf("DEBUG, SendToKicc, send = %d\n", 10 + nDataSize);
if (pIomp->TcpCompleteSend((char *)pPacket, 10 + nDataSize) == -1)
return -1;
return 0;
}
/// - log part ////////////////////////////////////////////
extern inline FILE * CtLogFilePtr(FILE * pNewFile = NULL)
{
static FILE * pFile = stdout;
if (pNewFile)
pFile = pNewFile;
return pFile;
}
extern inline void CtLog(int nLevel, const char *fmt, ...)
//void CtLog(int nLevel, const char * pszLog)
{
char szLogString[1024];
va_list vaList;
va_start(vaList, fmt);
#if defined(__ANDROID__) || defined(ANDROID)
if (vsnprintf(szLogString, 1023, fmt, vaList) > 1023)
szLogString[1023] = '\0';
va_end(vaList);
__android_log_print(ANDROID_LOG_ERROR, "CtSense", "%s", szLogString);
#else
time_t t = time(NULL);
struct tm * st = localtime(&t);
sprintf(szLogString, "%04d-%02d-%02d %02d:%02d:%02d ", 1900 + st->tm_year,
st->tm_mon + 1, st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec);
fputs(szLogString, CtLogFilePtr());
if (vsnprintf(szLogString, 1023, fmt, vaList) > 1023)
szLogString[1023] = '\0';
va_end(vaList);
fputs(szLogString, CtLogFilePtr());
#endif
}
/// - log part ////////////////////////////////////////////
///BeginHeader- protocol part /////////////////////////////////////////////////
struct CtProtocolRecvCallBack
{
virtual int OnRecvProtocol() = 0;
};
class CtProtocol
{
public:
enum
{
CP_STATE_EMPTY = 0,
CP_STATE_INVALID_PACKET = 1,
CP_STATE_HEADER_REMAIN = 2,
CP_STATE_BODY_REMAIN = 3,
CP_STATE_COMPLETE = 4,
CP_STATE_JOINED = 5,
};
public:
inline CtProtocol();
virtual inline ~CtProtocol();
inline int GetPacketSize() { return m_nPakcetSize; }
inline int GetBodySize() { return m_nBodySize; }
inline const unsigned char * GetPacketPtr() { return m_pBufPtr; }
inline const unsigned char * GetBodyPtr() { return m_pBodyPtr; }
inline unsigned char * GetBufRecvPtr() { return m_pBufRecvPtr; }
inline const int GetBufRemainSize() { return m_nBufRemainSize; }
inline const int MoveBufRecvPtr(int nSize);
inline int OnReceive(size_t nSize, CtProtocolRecvCallBack * pCallBack);
virtual void Clear() = 0;
virtual int Parse(const char * pPacket, int nSize) = 0;
virtual int MoveNext() = 0;
protected:
int m_nState;
int m_nPakcetSize;
int m_nBodySize;
unsigned char * m_pBodyPtr;
unsigned char * m_pBufPtr;
//int m_nNextSendPos;
int m_nBufRemainSize;
unsigned char * m_pBufRecvPtr;
};
///EndHeader- protocol part ///////////////////////////////////////////////
///BeginSource- protocol part /////////////////////////////////////////////////
inline CtProtocol::CtProtocol()
{
m_nState = CP_STATE_EMPTY;
m_nPakcetSize = 0;
m_nBodySize = 0;
m_pBodyPtr = NULL;
m_pBufPtr = NULL;
m_nBufRemainSize = 0;
m_pBufRecvPtr = NULL;
}
inline CtProtocol::~CtProtocol()
{
}
inline const int CtProtocol::MoveBufRecvPtr(int nSize) {
if (m_nBufRemainSize < nSize)
return -1;
m_pBufRecvPtr += nSize;
m_nPakcetSize += nSize;
m_nBufRemainSize -= nSize;
return 0;
}
inline int CtProtocol::OnReceive(size_t nSize, CtProtocolRecvCallBack * pCallBack)
{
CtLog(15, "CtProtocol::OnReceive, nSize = %d\n", nSize);
CtLog(15, "CtProtocol::OnReceive, %x %x %x %x %x %x\n", m_pBufRecvPtr[0], m_pBufRecvPtr[1], m_pBufRecvPtr[2], m_pBufRecvPtr[3], m_pBufRecvPtr[4], m_pBufRecvPtr[5]);
if (MoveBufRecvPtr((int)nSize) < 0)
{
CtLog(1, "[ERROR], CtProtocol::MoveBufRecvPtr, Not enough buffer.\n");
return -1; // disconnect
}
for (;;)
{
#ifdef USE_COPY_BUFFER
int nState = Parse(m_pRecvBuf, nSize);
#else
int nState = Parse(NULL, 0);
#endif
if (nState == CP_STATE_COMPLETE || nState == CP_STATE_JOINED)
{
if (pCallBack->OnRecvProtocol() < 0)
return -1; // disconnect
if (nState == CP_STATE_COMPLETE)
{
Clear();
}
else if (nState == CP_STATE_JOINED)
{
MoveNext();
continue;
}
}
break;
}
Clear();
//return -1; //TestCode disconnect
return 0;
}
///EndSource- protocol part ///////////////////////////////////////////////////
class KiccProtocol : public CtProtocol
{
// STX: 1byte, 0x02 : Start of Transmission
// LEN: 2byte, Ŷ (LEN DATA)
// CNT: 1byte, Ŷ Counter. Ŷ ۼ 1 ϸ, 1 255 . 1 Reset.
// CMD: 1byte, ڵ
// GCD: 1byte, ׷ ڵ ( ׷ ڵ )
// JCD: 1byte, ڵ ( ڵ )
// DATA: LEN byte, . ڵ ϱ ʿ ʵ. Type ۵Ǹ, ASCII ? .
// ETX: 1byte, End of Transmission
// CRC: 2byte, LEN ETX Check Code
public:
enum
{
CP_MAX_PACKET_SIZE = 8192,
CP_HEADER_SIZE = 3, // STX + LEN
CP_MAX_BODY_SIZE = CP_MAX_PACKET_SIZE - CP_HEADER_SIZE,
};
public:
inline KiccProtocol();
virtual inline ~KiccProtocol();
inline void Clear();
inline void Append(const char * pData, size_t nSize);
inline void SetHeader(unsigned short nBodySize);
inline void BuildHeader();
inline int Parse(const char * pPacket, int nSize);
inline int MoveNext();
protected:
unsigned char m_buffer[CP_MAX_PACKET_SIZE];
};
inline KiccProtocol::KiccProtocol()
{
Clear();
}
inline KiccProtocol::~KiccProtocol()
{
}
inline void KiccProtocol::Clear()
{
m_nState = CP_STATE_EMPTY;
m_nPakcetSize = 0;
m_nBodySize = 0;
m_pBodyPtr = m_buffer + CP_HEADER_SIZE;
m_pBufPtr = m_buffer;
m_nBufRemainSize = CP_MAX_PACKET_SIZE;
m_pBufRecvPtr = m_buffer;
}
inline void KiccProtocol::Append(const char * pData, size_t nSize)
{
memcpy(m_pBodyPtr + m_nBodySize, pData, nSize);
m_nBodySize += (int)nSize;
}
inline void KiccProtocol::SetHeader(unsigned short nBodySize)
{
// memcpy(m_buffer, ProtocolNamePtr(), 4);
unsigned short * pnBodySize = (unsigned short *)(m_buffer + 4);
*pnBodySize = htons(nBodySize);
m_nBodySize = nBodySize;
m_nPakcetSize = m_nBodySize + CP_HEADER_SIZE;
}
inline void KiccProtocol::BuildHeader()
{
// memcpy(m_buffer, ProtocolNamePtr(), 4);
unsigned short * pnBodySize = (unsigned short *)(m_buffer + 4);
*pnBodySize = htons(m_nBodySize);
m_nPakcetSize = m_nBodySize + CP_HEADER_SIZE;
m_nState = CP_STATE_COMPLETE;
}
inline int KiccProtocol::Parse(const char * pPacket, int nSize)
{
if (m_nState == CP_STATE_JOINED)
{
m_nState = CP_STATE_EMPTY;
}
else
{
if (pPacket != NULL && nSize != 0)
{
memcpy(m_buffer + m_nPakcetSize, pPacket, nSize);
m_nPakcetSize += nSize;
}
}
//fprintf(stdout, "DEBUG, Parse 1, %d, %d, %d, %d\n", nSize, m_nState, m_nPakcetSize, m_nBodySize);
if (m_nState == CP_STATE_EMPTY)
{
if (m_nPakcetSize < CP_HEADER_SIZE)
{
m_nState = CP_STATE_HEADER_REMAIN;
return m_nState;
}
}
else if (m_nState == CP_STATE_HEADER_REMAIN)
{
if (m_nPakcetSize < CP_HEADER_SIZE)
return m_nState;
}
else if (m_nState == CP_STATE_BODY_REMAIN)
{
if (m_nPakcetSize < CP_HEADER_SIZE + m_nBodySize)
return m_nState;
return CP_STATE_COMPLETE;
}
//fprintf(stdout, "DEBUG, Parse 2, %x, %x, %x\n", m_pBufPtr[0], m_pBufPtr[1], m_pBufPtr[2]);
// if (memcmp(m_pBufPtr, KiccProtocol::ProtocolNamePtr(), 4) != 0)
if (m_pBufPtr[0] != 0x02 && m_pBufPtr[0] != 0x06 && m_pBufPtr[0] != 0x14)
return CP_STATE_INVALID_PACKET;
else if (m_pBufPtr[0] == 0x06 && m_pBufPtr[1] == 0x06 && m_pBufPtr[2] == 0x06)
{
m_nBodySize = 0;
return CP_STATE_COMPLETE; //ACK
}
else if (m_pBufPtr[0] == 0x15 && m_pBufPtr[1] == 0x15 && m_pBufPtr[2] == 0x15)
{
m_nBodySize = 0;
return CP_STATE_COMPLETE; //NACK
}
//m_nBodySize = ntohs(*((unsigned short *)(m_pBufPtr + 4)));
unsigned short nBodySize;
memcpy(&nBodySize, m_pBufPtr + 1, sizeof(unsigned short));
m_nBodySize = ntohs(nBodySize);
if (m_nBodySize == 0)
{
m_nBodySize = 7; // CNT(1) + CMD(1) + GCD(1) + JCD(1) + ETX(1) + CRC(2)
if ((m_nBodySize - 7) > m_nPakcetSize - CP_HEADER_SIZE)
{
m_nState = CP_STATE_BODY_REMAIN;
return m_nState;
}
else if ((m_nBodySize - 7) < m_nPakcetSize - CP_HEADER_SIZE)
{
m_nState = CP_STATE_JOINED;
return m_nState;
}
}
else
{
m_nBodySize++; // - LEN(2) + ETX(1) + CRC(2)
if ((m_nBodySize - 1) > m_nPakcetSize - CP_HEADER_SIZE)
{
m_nState = CP_STATE_BODY_REMAIN;
return m_nState;
}
else if ((m_nBodySize - 1) < m_nPakcetSize - CP_HEADER_SIZE)
{
m_nState = CP_STATE_JOINED;
return m_nState;
}
}
return CP_STATE_COMPLETE;
}
inline int KiccProtocol::MoveNext()
{
if (m_nState != CP_STATE_JOINED)
return -1;
m_pBufPtr += CP_HEADER_SIZE + m_nBodySize;
m_pBodyPtr = m_pBufPtr + CP_HEADER_SIZE;
m_nPakcetSize -= CP_HEADER_SIZE + m_nBodySize;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///BeginHeader- size only protocol part /////////////////////////////////////////////////
class CtSizeOnlyProtocol : public CtProtocol
{
public:
enum
{
CP_MAX_PACKET_SIZE = 8192,
CP_HEADER_SIZE = 4, // PROTOCOL_NAME + BODY_SIZE(2byte)
CP_MAX_BODY_SIZE = CP_MAX_PACKET_SIZE - CP_HEADER_SIZE,
};
public:
inline CtSizeOnlyProtocol();
virtual inline ~CtSizeOnlyProtocol();
inline void Clear();
inline void Append(const char * pData, size_t nSize);
inline void SetHeader(u_short nBodySize);
inline void BuildHeader();
inline int Parse(const char * pPacket, int nSize);
inline int MoveNext();
protected:
unsigned char m_buffer[CP_MAX_PACKET_SIZE];
};
///EndHeader- size only protocol part ///////////////////////////////////////////////
///BeginSource- size only protocol part /////////////////////////////////////////////////
inline CtSizeOnlyProtocol::CtSizeOnlyProtocol()
{
Clear();
}
inline CtSizeOnlyProtocol::~CtSizeOnlyProtocol()
{
}
inline void CtSizeOnlyProtocol::Clear()
{
m_nState = CP_STATE_EMPTY;
m_nPakcetSize = 0;
m_nBodySize = 0;
m_pBodyPtr = m_buffer + CP_HEADER_SIZE;
m_pBufPtr = m_buffer;
m_nBufRemainSize = CP_MAX_PACKET_SIZE;
m_pBufRecvPtr = m_buffer;
}
inline void CtSizeOnlyProtocol::Append(const char * pData, size_t nSize)
{
memcpy(m_pBodyPtr + m_nBodySize, pData, nSize);
m_nBodySize += (int)nSize;
}
inline void CtSizeOnlyProtocol::SetHeader(u_short nBodySize)
{
//memcpy(m_buffer, ProtocolNamePtr(), 4);
unsigned short * pnBodySize = (unsigned short *)(m_buffer + 4);
*pnBodySize = htons(nBodySize);
m_nBodySize = nBodySize;
m_nPakcetSize = m_nBodySize + CP_HEADER_SIZE;
}
inline void CtSizeOnlyProtocol::BuildHeader()
{
//memcpy(m_buffer, ProtocolNamePtr(), 4);
unsigned short * pnBodySize = (unsigned short *)(m_buffer + 4);
*pnBodySize = htons(m_nBodySize);
m_nPakcetSize = m_nBodySize + CP_HEADER_SIZE;
m_nState = CP_STATE_COMPLETE;
}
inline int CtSizeOnlyProtocol::Parse(const char * pPacket, int nSize)
{
if (m_nState == CP_STATE_JOINED)
{
m_nState = CP_STATE_EMPTY;
}
else
{
if (pPacket != NULL && nSize != 0)
{
memcpy(m_buffer + m_nPakcetSize, pPacket, nSize);
m_nPakcetSize += nSize;
}
}
if (m_nState == CP_STATE_EMPTY)
{
if (m_nPakcetSize < CP_HEADER_SIZE)
{
m_nState = CP_STATE_HEADER_REMAIN;
return m_nState;
}
}
else if (m_nState == CP_STATE_HEADER_REMAIN)
{
if (m_nPakcetSize < CP_HEADER_SIZE)
return m_nState;
}
else if (m_nState == CP_STATE_BODY_REMAIN)
{
if (m_nPakcetSize < CP_HEADER_SIZE + m_nBodySize)
return m_nState;
return CP_STATE_COMPLETE;
}
//if (memcmp(m_pBufPtr, CtSizeOnlyProtocol::ProtocolNamePtr(), 4) != 0)
// return CP_STATE_INVALID_PACKET;
//m_nBodySize = ntohs(*((u_short *)(m_pBufPtr + 4)));
unsigned short nBodySize;
memcpy(&nBodySize, m_pBufPtr + 2, sizeof(unsigned short));
m_nBodySize = ntohs(nBodySize);
if (m_nBodySize > m_nPakcetSize - CP_HEADER_SIZE)
{
m_nState = CP_STATE_BODY_REMAIN;
return m_nState;
}
else if (m_nBodySize < m_nPakcetSize - CP_HEADER_SIZE)
{
m_nState = CP_STATE_JOINED;
return m_nState;
}
return CP_STATE_COMPLETE;
}
inline int CtSizeOnlyProtocol::MoveNext()
{
if (m_nState != CP_STATE_JOINED)
return -1;
m_pBufPtr += CP_HEADER_SIZE + m_nBodySize;
m_nPakcetSize -= CP_HEADER_SIZE + m_nBodySize;
return 0;
}
///////////////////////////////////////////////////////////////////////////
class KiccDispatcher;
class KiccRecvCallBack : public CtProtocolRecvCallBack
{
public:
KiccRecvCallBack() {}
virtual ~KiccRecvCallBack() {}
void SetDepends(KiccProtocol * pKiccProtocol, KiccDispatcher * pKiccDispatcher)
{
m_pKiccProtocol = pKiccProtocol;
m_pKiccDispatcher = pKiccDispatcher;
}
virtual int OnRecvProtocol();
protected:
KiccProtocol * m_pKiccProtocol;
KiccDispatcher * m_pKiccDispatcher;
};
class RemoteRecvCallBack : public CtProtocolRecvCallBack
{
public:
RemoteRecvCallBack() {}
virtual ~RemoteRecvCallBack() {}
void SetDepends(CtSizeOnlyProtocol * pSoProtocol, KiccDispatcher * pKiccDispatcher)
{
m_pSoProtocol = pSoProtocol;
m_pKiccDispatcher = pKiccDispatcher;
}
virtual int OnRecvProtocol();
protected:
CtSizeOnlyProtocol * m_pSoProtocol;
KiccDispatcher * m_pKiccDispatcher;
};
//////////////////////////////////////////////////////////////////////////////
class KiccIompObject: public IompObject
{
public:
//KiccIompObject * m_pPair;
public:
KiccIompObject()
{
//m_pPair = NULL;
}
~KiccIompObject() {}
};
#if 0
typedef struct TTerminalInfo
{
unsigned char nRespCode;
char arrModelCode[4];
char arrModelVer[4];
char arrSerialNo[12];
char arrCertNo[16];
char arrTid[10];
char arrTerminalNo[3];
char arrTerminalIpPort[30];
char * pSpecialInfo;
} TTerminalInfo;
#endif
class KiccDispatcher : public IompDispatcher<KiccIompObject>
{
public:
enum
{
KD_KICC_STATE_STARTED = 0,
KD_KICC_STATE_WAIT_CONNECT = 1,
KD_KICC_STATE_CONNECTED = 2
};
enum
{
KD_REMOTE_STATE_STARTED = 0,
KD_REMOTE_STATE_WAIT_CONNECT = 1,
KD_REMOTE_STATE_WAIT_LOGIN_OK = 2,
KD_REMOTE_STATE_LOGGED_IN = 3,
};
protected:
//int m_nState;
int m_nKiccState;
int m_nRemoteState;
char m_szTid[16];
KiccIompObject * m_pKiccIompObject;
KiccIompObject * m_pRemoteIompObject;
KiccProtocol m_kiccProtocol;
KiccRecvCallBack m_kiccRecvCallBack;
CtSizeOnlyProtocol m_remoteProtocol;
RemoteRecvCallBack m_remoteRecvCallBack;
public:
KiccDispatcher()
{
m_nKiccState = KD_KICC_STATE_STARTED;
m_nRemoteState = KD_REMOTE_STATE_STARTED;
m_szTid[0] = '\0';
}
virtual ~KiccDispatcher()
{
}
void SetTimer(unsigned int nIntervalTime) //msec
{
m_nDispachInterval = nIntervalTime;
}
void KillTimer()
{
m_nDispachInterval = 0;
}
void SendToRemote(int nType, const char * pData, int nDataSize)
{
char packet[8192];
char * ptrBodySize = (char *)packet + 2;
char * ptrBody = ptrBodySize + 2;
ptrBody[0] = nType; // 1: Command Protocol, 2: KICC protocol
unsigned short nBodySize = nDataSize;
memcpy(ptrBody + 1, pData, nBodySize);
nBodySize += 1;
unsigned short nTemp = htons(nBodySize);
memcpy(ptrBodySize, &nTemp, sizeof(unsigned short));
fprintf(stdout, "DEBUG, SendToRemote, size = %d, \n", nBodySize + 4);
m_pRemoteIompObject->TcpCompleteSend(packet, nBodySize + 4); // send kicc protocol to server
}
void SendTest1ToRemote(int nType)
{
char szFileName[128];
sprintf(szFileName, "pay%.2d.raw", nType);
CtFile file;
if (file.Open(szFileName, CtFile::FMODE_RDONLY) == false)
return;
char buffer[8192];
size_t nRecvSize = file.Read(buffer, 8192);
if (nRecvSize <= 0)
return;
SendToRemote(2, buffer, nRecvSize);
}
int OnRecvKiccProtocol() // m_nKiccState == KD_KICC_STATE_CONNECTED
{
if ((m_kiccProtocol.GetPacketPtr()[0] == 0x06 && m_kiccProtocol.GetPacketPtr()[1] == 0x06 && m_kiccProtocol.GetPacketPtr()[2] == 0x06) ||
m_kiccProtocol.GetPacketPtr()[0] == 0x15 && m_kiccProtocol.GetPacketPtr()[1] == 0x15 && m_kiccProtocol.GetPacketPtr()[2] == 0x15) // ACK
{
fprintf(stdout, "DEBUG, OnRecvKiccProtocol, ACK/NACK, 0x%x, size = %d\n", m_kiccProtocol.GetPacketPtr()[0], m_kiccProtocol.GetPacketSize());
if (m_nRemoteState == KD_REMOTE_STATE_LOGGED_IN)
{
SendToRemote(2, (const char *)m_kiccProtocol.GetPacketPtr(), m_kiccProtocol.GetPacketSize());
}
return 0;
}
fprintf(stdout, "DEBUG, OnRecvKiccProtocol, body size = %d, 0x%.2d, 0x%.2d, 0x%.2d\n", m_kiccProtocol.GetBodySize(), m_kiccProtocol.GetBodyPtr()[0], m_kiccProtocol.GetBodyPtr()[1], m_kiccProtocol.GetBodyPtr()[2]);
unsigned char ack[4];
ack[0] = 0x06;
ack[1] = 0x06;
ack[2] = 0x06;
m_pKiccIompObject->TcpCompleteSend((const char *)ack, 3); // response ack
if (m_nRemoteState == KD_REMOTE_STATE_STARTED)
{
const char * ptrTid = (const char *)m_kiccProtocol.GetBodyPtr() + 41;
int j = 0;
for (int i = 0; i < 10; i++) // front trim
{
if (ptrTid[i] == ' ')
continue;
m_szTid[j++] = ptrTid[i];
}
m_szTid[j] = '\0';
fprintf(stdout, "DEBUG, OnRecvKiccProtocol, Tid = %s\n", m_szTid);
if (m_szTid[0] == '\0')
{
//...
SendToKicc(m_pKiccIompObject, 0x02, NULL, 0); // get info
return 0;
}
KiccIompObject iompObject;
if (iompObject.Create() == -1)
return 0;
//if (iompObject.Connect("192.168.219.150", 17856, 7000, 0, 5000) == -1)
if (iompObject.Connect("43.201.46.125", 17856, 7000, 0, 5000) == -1)
return 0;
m_remoteRecvCallBack.SetDepends(&m_remoteProtocol, this);
m_pRemoteIompObject = AddSocket(iompObject);
m_nRemoteState = KD_REMOTE_STATE_WAIT_CONNECT;
return 0;
}
else if (m_nRemoteState == KD_REMOTE_STATE_WAIT_CONNECT)
{
//...
}
else if (m_nRemoteState == KD_REMOTE_STATE_WAIT_LOGIN_OK)
{
//...
}
else if (m_nRemoteState == KD_REMOTE_STATE_LOGGED_IN)
{
SendToRemote(2, (const char *)m_kiccProtocol.GetPacketPtr(), m_kiccProtocol.GetPacketSize());
}
return 0;
}
int OnRecvRemoteProtocol() // m_nRemoteState == KD_REMOTE_STATE_WAIT_LOGIN_OK or KD_REMOTE_STATE_LOGGED_IN
{
fprintf(stdout, "DEBUG, OnRecvRemoteProtocol, body size = %d, 0x%.2d, 0x%.2d\n", m_remoteProtocol.GetBodySize(), m_remoteProtocol.GetBodyPtr()[0], m_remoteProtocol.GetBodyPtr()[1]);
const unsigned char * pPacket = m_remoteProtocol.GetPacketPtr();
fprintf(stdout, "DEBUG, %x %x %x %x %x\n", pPacket[0], pPacket[1], pPacket[2], pPacket[3], pPacket[4], pPacket[5]);
if (m_nRemoteState == KD_REMOTE_STATE_WAIT_LOGIN_OK)
{
if (m_remoteProtocol.GetBodyPtr()[0] == 1 && // smart service protocol
m_remoteProtocol.GetBodyPtr()[1] == 1) // login ok
{
fprintf(stdout, "DEBUG, OnRecvRemoteProtocol, login success\n");
m_nRemoteState = KD_REMOTE_STATE_LOGGED_IN;
return 0;
}
//login failed
return -1; // disconnect
}
if (m_nKiccState == KD_KICC_STATE_WAIT_CONNECT)
{
//...
return 0;
}
else if (m_nKiccState == KD_KICC_STATE_CONNECTED)
{
if (m_remoteProtocol.GetBodyPtr()[0] == 1) // remote server protocol
{
if (m_remoteProtocol.GetBodyPtr()[1] == 2) // keep-alive
{
fprintf(stdout, "DEBUG, OnRecvRemoteProtocol, keep-alive\n");
SendToRemote(1, "3", 1); // keep-alive ack
}
else if (m_remoteProtocol.GetBodyPtr()[1] == 99) // test packet
{
SendTest1ToRemote(m_remoteProtocol.GetBodyPtr()[2]);
}
return 0;
}
else if (m_remoteProtocol.GetBodyPtr()[0] == 2) // kicc protocol
{
const char * pBody = (const char *)m_remoteProtocol.GetBodyPtr();
m_pKiccIompObject->TcpCompleteSend(pBody + 1, m_remoteProtocol.GetBodySize() - 1); // remove protocol type
return 0;
}
return 0; // disconnect
}
return -1; // disconnect
}
protected:
int OnIompConnect(KiccIompObject * pIomp, bool bIsSuccess, unsigned int nCurrTick)
{
fprintf(stdout, "DEBUG, OnIompConnect, %s, state = %d, sock = %d\n", bIsSuccess ? "true" : "false", m_nKiccState, m_nRemoteState, pIomp->m_sock);
if (bIsSuccess == false)
return 0;
if (m_pKiccIompObject == pIomp)
{
if (m_szTid[0] == '\0')
{
SendToKicc(pIomp, 0x02, NULL, 0); // get info
}
m_nKiccState = KD_KICC_STATE_CONNECTED;
}
else if (m_pRemoteIompObject == pIomp)
{
//
char packet[8192];
char * ptrBodySize = (char *)packet + 2;
char * ptrBody = ptrBodySize + 2;
ptrBody[0] = 1; // 1: Command Protocol, 2: KICC protocol
ptrBody[1] = 1; // 1: Login
//int nBodySize = sprintf(ptrBody + 2, "%s", m_szTid);
unsigned int nBodySize = strlen(m_szTid);
memcpy(ptrBody + 2, m_szTid, nBodySize);
nBodySize += 2;
unsigned short nTemp = htons(nBodySize);
memcpy(ptrBodySize, &nTemp, sizeof(unsigned short));
fprintf(stdout, "DEBUG, Send, size = %d, \n", nBodySize + 4);
m_pRemoteIompObject->TcpCompleteSend(packet, nBodySize + 4); // send login
//
m_nRemoteState = KD_REMOTE_STATE_WAIT_LOGIN_OK;
}
return 0;
}
int OnIompReceive(KiccIompObject * pIomp, unsigned int nCurrTick)
{
if (m_pKiccIompObject == pIomp)
{
int nReceived = pIomp->Receive((char *)m_kiccProtocol.GetBufRecvPtr(), m_kiccProtocol.GetBufRemainSize());
if (nReceived == -1)
return -1;
return m_kiccProtocol.OnReceive(nReceived, &m_kiccRecvCallBack);
}
else if (m_pRemoteIompObject == pIomp)
{
int nReceived = pIomp->Receive((char *)m_remoteProtocol.GetBufRecvPtr(), m_remoteProtocol.GetBufRemainSize());
if (nReceived == -1)
return -1;
return m_remoteProtocol.OnReceive(nReceived, &m_remoteRecvCallBack);
}
return -1; // disconnect
}
int OnIompAccept(KiccIompObject * pIomp, unsigned int nCurrTick)
{
fprintf(stdout, "DEBUG, OnIompAccept, sock = %d\n", pIomp->m_sock);
return 0;
}
int OnIompClose(KiccIompObject * pIomp, unsigned int nCurrTick)
{
fprintf(stdout, "DEBUG, OnIompClose, sock = %d\n", pIomp->m_sock);
if (m_pKiccIompObject == pIomp)
{
m_kiccProtocol.Clear();
m_nKiccState = KD_KICC_STATE_WAIT_CONNECT;
}
else if (m_pRemoteIompObject == pIomp)
{
m_remoteProtocol.Clear();
m_nRemoteState = KD_REMOTE_STATE_WAIT_CONNECT;
}
return 0; //default, remove from dispatch list
//return -1; //!!! no remove from dispatch list
}
int OnIompDelete(KiccIompObject * pIomp, unsigned int nCurrTick)
{
fprintf(stdout, "DEBUG, OnIompDelete, sock = %d\n", pIomp->m_sock);
return 0;
}
void OnDispatchTimer(unsigned int nCurrTick)
{
fprintf(stdout, "DEBUG, %u, OnDispatchTimer, m_listIomp.size() = %ld\n", nCurrTick, m_listIomp.size());
if (m_nKiccState == KD_KICC_STATE_STARTED)
{
KiccIompObject iompObject;
if (iompObject.Create() == -1)
return;
if (iompObject.Connect("127.0.0.1", 13189, 7000, nCurrTick, 5000) == -1)
//if (iompObject.Connect("192.168.219.150", 13189, 7000, 5000) == -1)
return;
m_kiccRecvCallBack.SetDepends(&m_kiccProtocol, this);
m_pKiccIompObject = AddSocket(iompObject);
m_nKiccState = KD_KICC_STATE_WAIT_CONNECT; // local connecting...
KillTimer();
}
}
};
int KiccRecvCallBack::OnRecvProtocol()
{
return m_pKiccDispatcher->OnRecvKiccProtocol();
}
int RemoteRecvCallBack::OnRecvProtocol()
{
return m_pKiccDispatcher->OnRecvRemoteProtocol();
}
int main (int argc, char * argv[])
{
//if (argc < 3)
//{
// printf("Usage: hdtermd [IP] [Port]\n"
// "ex) hdtermd 192.168.1.4 7788\n");
// return 0;
//}
#if defined(_WIN32) && defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
//_CrtSetBreakAlloc(631);
#endif // _DEBUG
#ifdef _WIN32
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
printf("[ERROR], Windows sockets initialization failed., WSAGetLastError = %d\n", WSAGetLastError());
return -1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
printf("[ERROR], Could not find a usable WinSock DLL.\n");
WSACleanup();
return -1;
}
#endif // _WIN32
fprintf(stdout, "hdtermd version 1.0.2\n");
// verify date
for (;;)
{
time_t now;
struct tm *local;
time(&now);
local = localtime(&now);
int year = local->tm_year + 1900;
if (year < 2026)
{
fprintf(stderr, "[ERROR], Invalid date, = %ld\n", year);
Sleep(5000);
continue;
}
break;
}
//
KiccDispatcher iompDispatcher;
iompDispatcher.SetTimer(2000);
iompDispatcher.Dispatch(); // loop
return 0;
}