#include #include "ChatRecord.h" #include "MemPool.h" #include "MemNode.h" CChatRecord::CChatRecord(CChatRecordMng& ChatRecordMng) : m_ChatRecordMng(ChatRecordMng), m_FilePath(GetDefaultDirectory()) { m_PartRec = NULL; m_FileHandle = INVALID_HANDLE_VALUE; } CChatRecord::~CChatRecord(void) { if (m_PartRec) { m_ChatRecordMng.m_MemPool->ReleaseMemNode(m_PartRec); } if (m_FileHandle != INVALID_HANDLE_VALUE) { CloseHandle(m_FileHandle); } } int CChatRecord::Write(const char *pData, unsigned long ulDataLen) { //把日志写入文件 CMemNode* pMemNode = m_ChatRecordMng.m_MemPool->NewMemNode(); pMemNode->AddData(pData, ulDataLen); pMemNode->SetBufType(CChatRecordMng::IO_WRITE_REQ); PostQueuedCompletionStatus(m_ChatRecordMng.m_Iocp, pMemNode->GetUsedSize(), (ULONG_PTR)this, pMemNode); return 0; } int CChatRecord::Write(const char* strFormat, ...) { //把日志内容解析进缓冲区中 char szBuf[1024]; va_list vaLog; va_start(vaLog, strFormat); _vsntprintf(szBuf, sizeof(szBuf), strFormat, vaLog); va_end(vaLog); sprintf(szBuf, "%s%s", szBuf, NEWLINE_CHAR); //把日志写入文件 CMemNode* pMemNode = m_ChatRecordMng.m_MemPool->NewMemNode(); pMemNode->AddData(szBuf, strlen(szBuf)); pMemNode->SetBufType(CChatRecordMng::IO_WRITE_REQ); PostQueuedCompletionStatus(m_ChatRecordMng.m_Iocp, pMemNode->GetUsedSize(), (ULONG_PTR)this, pMemNode); return 0; } string CChatRecord::GetDefaultDirectory() { char szbuf[MAX_PATH]; try { GetCurrentDirectory(MAX_PATH, szbuf); } catch (...) { } return szbuf; } int CChatRecord::SetLogPath(const std::string &strLogPath) { if (m_FilePath == strLogPath) { return 0; } m_FilePath = strLogPath; return 0; } int CChatRecord::Read() { CMemNode* pMemNode = m_ChatRecordMng.m_MemPool->NewMemNode(); m_CurPos = 0; pMemNode->Offset = m_CurPos; pMemNode->SetBufType(CChatRecordMng::IO_READ); BOOL bResult = ReadFile(m_FileHandle, pMemNode->GetBufferPrt(), pMemNode->GetSize(), NULL, pMemNode); if (!bResult) { DWORD dwError = GetLastError(); switch(dwError) { case ERROR_HANDLE_EOF: { pMemNode->SetUseSize(0); OnData(pMemNode); } break; case ERROR_IO_PENDING: { } break; default: { m_ChatRecordMng.m_MemPool->ReleaseMemNode(pMemNode); } } } return 0; } int CChatRecord::Open(const std::string &strFileName) { if (m_FileHandle != INVALID_HANDLE_VALUE) { CloseHandle(m_FileHandle); m_FileHandle = INVALID_HANDLE_VALUE; } m_FileName = strFileName; string strFullFileName; strFullFileName = m_FilePath + "\\" + m_FileName; HANDLE hHandle = INVALID_HANDLE_VALUE; hHandle = CreateFile(strFullFileName.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (hHandle != INVALID_HANDLE_VALUE) { m_CurPos = 0; m_FileHandle = hHandle; m_ChatRecordMng.AddRecord(this); } return 0; } int CChatRecord::Clear() { SetFilePointer(m_FileHandle, 0, 0, FILE_BEGIN); SetEndOfFile(m_FileHandle); return 0; } int CChatRecord::OnData(CMemNode* pMemNode) { if (pMemNode->GetUsedSize() == 0) { m_ChatRecordMng.m_MemPool->ReleaseMemNode(pMemNode); return 0; } //先处理上次没有处理完的部分数据 if (m_PartRec != NULL) { //上次剩下的数据不到一个包头 if (m_PartRec->GetUsedSize() < sizeof(FILEHEADER)) { pMemNode->AddToMemNode(m_PartRec, sizeof(FILEHEADER) - m_PartRec->GetUsedSize()); } //合并后仍然不到一个包头 if (m_PartRec->GetUsedSize() < sizeof(FILEHEADER)) { if (pMemNode->GetUsedSize() != 0) { OutputDebugString("解包错误.\n"); } m_ChatRecordMng.m_MemPool->ReleaseMemNode(pMemNode); m_ChatRecordMng.m_MemPool->ReleaseMemNode(m_PartRec); return 0; } PFILEHEADER pMsgHeader = reinterpret_cast(m_PartRec->GetBufferPrt()); //请求的数据大于部分包中的数据量,把新的MemNode中的数据拷贝过去 if (pMsgHeader->m_DataLen >= m_PartRec->GetUsedSize()) { int nCopyBytes; if ((pMsgHeader->m_DataLen - m_PartRec->GetUsedSize()) > pMemNode->GetUsedSize()) { nCopyBytes = pMemNode->GetUsedSize(); } else { nCopyBytes = pMsgHeader->m_DataLen - m_PartRec->GetUsedSize(); } pMemNode->AddToMemNode(m_PartRec, nCopyBytes); } else { m_ChatRecordMng.m_MemPool->ReleaseMemNode(pMemNode); return 0; } if (pMsgHeader->m_DataLen == m_PartRec->GetUsedSize()) { CChatRecordMng::ChatLog cl; LoadChatRec(m_PartRec->GetBufferPrt() + sizeof(FILEHEADER), m_PartRec->GetUsedSize() - sizeof(FILEHEADER), cl); m_ChatRecordMng.m_MemPool->ReleaseMemNode(m_PartRec); m_PartRec = NULL; } } //当前包并到半包中去 if (pMemNode->GetUsedSize() == 0) { m_ChatRecordMng.m_MemPool->ReleaseMemNode(pMemNode); return 0; } //获得接收的消息长度和地址 //pData指向MemNode中的缓冲区首地址 char* pData = pMemNode->GetBufferPrt(); //nDataLen表示MemNode中有用信息的字节数 size_t nDataLen= pMemNode->GetUsedSize(); //数据包没有包头大,作为数据不全的包处理 if (nDataLen < sizeof(FILEHEADER)) { m_PartRec = pMemNode; return 0; } //一个CMemNode中可能存在多个消息包,nMsgLen记录每个消息包的长度 PFILEHEADER pmsgHeader; unsigned short nMsgLen = 0; while (nDataLen > 0) { pmsgHeader = reinterpret_cast(pData); if (pmsgHeader == NULL) { OutputDebugString("数据包错误, 不能获取包头!\n"); m_ChatRecordMng.m_MemPool->ReleaseMemNode(pMemNode); break; } nMsgLen = pmsgHeader->m_DataLen; if (nMsgLen == 0) { m_ChatRecordMng.m_MemPool->ReleaseMemNode(pMemNode); break; } if (nMsgLen == nDataLen) //MemNode中仅有一个消息包 { CChatRecordMng::ChatLog cl; LoadChatRec(pMemNode->GetBufferPrt() + sizeof(FILEHEADER), pMemNode->GetUsedSize() - sizeof(FILEHEADER), cl); m_ChatRecordMng.m_MemPool->ReleaseMemNode(pMemNode); break; //直接跳出while循环 } else if (nMsgLen < nDataLen) //MemNode中包含多个消息包 { CMemNode* pNewMemNode = pMemNode->SplitBuf(nMsgLen); CChatRecordMng::ChatLog cl; LoadChatRec(pNewMemNode->GetBufferPrt() + sizeof(FILEHEADER), pNewMemNode->GetUsedSize() - sizeof(FILEHEADER), cl); m_ChatRecordMng.m_MemPool->ReleaseMemNode(pNewMemNode); } else if(nMsgLen > nDataLen) //一个完整的消息包没有取完整 { m_PartRec = pMemNode; break; } //继续处理余下的消息包 nDataLen = pMemNode->GetUsedSize(); } return 0; } int CChatRecord::LoadChatRec(char* pData, unsigned short usDataLen, struct CChatRecordMng::ChatLog &cl) { memset(&cl, 0, sizeof(cl)); int nSpan = strlen(pData); strncpy(cl.PeerName, pData, nSpan); pData += nSpan + 1; nSpan = strlen(pData); strncpy(cl.LocalName, pData, nSpan); pData += nSpan + 1; cl.ChatDirection = *((CChatRecordMng::ChatLog::CHATDIRECT*)pData); nSpan = sizeof(cl.ChatDirection); pData += nSpan; cl.ClientType = *((unsigned char*)pData); nSpan = sizeof(cl.ClientType); pData += nSpan; cl.LogTime = *(SYSTEMTIME*)pData; nSpan = sizeof(SYSTEMTIME); pData += nSpan; strncpy(cl.Chat, pData, strlen(pData)); m_ChatRecordMng.m_pChatRecEvent->OnChatRecord(&cl); return 0; }