#ifdef _WIN32 #define _CRT_SECURE_NO_WARNINGS #include #include #include #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "winmm.lib") #else #include #include #include // sockaddr_in #include // inet_ntoa() #include // close() #include // gethostbyname() #include // F_GETFL, O_NONBLOCK #include // TCP_NODELAY #include #include #include //#include #include 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 #include #include #include #include #ifdef _DEBUG #include #endif #include ////////////////////////////////////////////////////////////////////////////// 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 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 { 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; }