#include "M8MsgProcess.h" #include "path.h" M8MsgProcess::M8MsgProcess(CMzWndEx* ipWnd, IPMsg* ipIPMsg):pWnd(ipWnd),pIPMsg(ipIPMsg) { pConfig = Configuration::GetInstance(); m_Mutex = ::CreateMutex(NULL, FALSE, L"progressDialog"); } M8MsgProcess::~M8MsgProcess(void) { ::CloseHandle(m_Mutex); } int M8MsgProcess::processMsg(MsgBuf* pMsg) { switch(GET_MODE(pMsg->command)) { case IPMSG_BR_ENTRY: { char buf[MAX_BUF]; in_addr addr; memcpy(&addr, & pMsg->hostSub.addr, sizeof(in_addr)); sprintf(buf,"%s (%s)", pMsg->hostSub.userName, inet_ntoa(addr)); pMsg->hostSub.hostType = 0xFF000000 & pMsg->command; userMap[buf] = pMsg->hostSub; pWnd->PostMessageW(WM_UPDATELIST,(WPARAM)&userMap,NULL); pIPMsg->SendCommand(pMsg->hostSub.addr,IPMSG_ANSENTRY | IPMSG_M8); delete pMsg; break; } case IPMSG_ANSENTRY: { char buf[MAX_BUF]; in_addr addr; memcpy(&addr, & pMsg->hostSub.addr, sizeof(in_addr)); sprintf(buf,"%s (%s)", pMsg->hostSub.userName, inet_ntoa(addr)); pMsg->hostSub.hostType = 0xFF000000 & pMsg->command; userMap[buf] = pMsg->hostSub; pWnd->PostMessageW(WM_UPDATELIST,(WPARAM)&userMap,NULL); delete pMsg; break; } case IPMSG_SENDMSG: { ULONG opt = GET_OPT(pMsg->command); if(opt & IPMSG_SENDCHECKOPT) //需要回执 { char buf[200]; sprintf(buf, "%d", pMsg->packetNo); pIPMsg->SendCommand(pMsg->hostSub.addr, IPMSG_RECVMSG , buf ); } if(opt & IPMSG_FILEATTACHOPT ) //接收文件 { if(!(opt & IPMSG_RETRYOPT)) { //Start thread to receive the file. MessageProcess *mp = new MessageProcess(); mp->pMsg = pMsg; mp->process = this; DWORD id; ::CreateThread(NULL, 0, M8MsgProcess::RecvFile_Thread, mp, 0 , &id); //processFile(pMsg); } } else { pWnd->PostMessageW(WM_SHOWMSG,(WPARAM)pMsg,NULL); } break; } case IPMSG_BR_EXIT: { char buf[MAX_BUF]; in_addr addr; memcpy(&addr, & pMsg->hostSub.addr, sizeof(in_addr)); sprintf(buf,"%s (%s)", pMsg->hostSub.userName, inet_ntoa(addr)); string username(buf); userMap.erase(username); pWnd->PostMessageW(WM_UPDATELIST,(WPARAM)&userMap,NULL); delete pMsg; break; } case IPMSG_NOOPERATION: delete pMsg; break; default: { /* Ignore other command */ delete pMsg; } } return 0; } BOOL M8MsgProcess::processFile(MsgBuf* pMsg) { ShareInfo * shareInfo; if( (shareInfo = DecodeShareMsg(pMsg->msgBuf + pMsg->exOffset )) != NULL) { if(shareInfo->fileCnt > 0 ) { recevFileNo = 0; //char dir[] = "/Disk/Received Files/"; for(int i= 0 ;i < shareInfo->fileCnt; i++) { FileInfo* pFileInfo = shareInfo->fileInfo[i]; ReceiveFile(pMsg, pFileInfo); } pWnd->PostMessageW(WM_RECVFILE,(WPARAM)recevFileNo,NULL); //shareInfo->fileCnt } } delete pMsg; delete shareInfo; return TRUE; } #define PEEK_SIZE 8 void M8MsgProcess::ReceiveFile(MsgBuf* pMsg, FileInfo* pFileInfo) { SOCKADDR_IN addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = pMsg->hostSub.addr; addr.sin_port = htons(pIPMsg->default_port); char buf[MAX_PATH], tcpbuf[MAX_BUF]; SOCKET tcp = ::socket(AF_INET, SOCK_STREAM, 0); int buf_size = MAX_SOCKBUF; ::setsockopt(tcp, SOL_SOCKET, SO_RCVBUF, (char *)&buf_size, sizeof(int)); if (tcp == INVALID_SOCKET) return; if(::connect(tcp, (sockaddr*)&addr, sizeof(sockaddr))==SOCKET_ERROR) return; if( GET_MODE(pFileInfo->Attr()) == IPMSG_FILE_REGULAR ) // receive file { if(pConfig) sprintf(buf, "%x:%x:%x:", pMsg->packetNo, pFileInfo->Id(), 0); int buf_len = 0; pIPMsg->MakeMsg(tcpbuf, IPMSG_GETFILEDATA, buf, NULL , &buf_len); if(::send(tcp,tcpbuf,buf_len,0)!= SOCKET_ERROR) { //ReceiveFileData(pFileInfo,tcp, dir); wstring dir; wstring fileName; A2W(pFileInfo->Fname(), fileName); pConfig->GetSmartPath(fileName,dir); CreateDirectoryEx(dir.c_str()); this->SaveDataToFile(dir + fileName,pFileInfo,tcp); } closesocket(tcp); } else if( GET_MODE(pFileInfo->Attr()) == IPMSG_FILE_DIR) { sprintf(buf, "%x:%x:%x:", pMsg->packetNo, pFileInfo->Id(), 0); int buf_len = 0; pIPMsg->MakeMsg(tcpbuf, IPMSG_GETDIRFILES, buf, NULL , &buf_len); if(::send(tcp,tcpbuf,buf_len,0)!= SOCKET_ERROR) { char peek_buf[PEEK_SIZE]; FileInfo subFile; char* header = new char[ MAX_BUF ]; if(recv(tcp, header,PEEK_SIZE,0)<=0) goto exit; memcpy(peek_buf, header, PEEK_SIZE); char *tok, *p; if ((tok = separate_token(peek_buf, ':', &p)) == NULL) // header size goto exit; int headerSize = (int) hex2ll(tok); RecvTCP(tcp, header+PEEK_SIZE, headerSize - PEEK_SIZE); header[headerSize]='\0'; if( DecodeDirEntry(header, &subFile)) { WCHAR path[MAX_PATH]; wstring fileName; A2W(subFile.Fname(), fileName); wsprintf(path,L"%s%s\\", pConfig->Dir().c_str(), fileName.c_str()); ::CreateDirectoryEx(path); ReceiveDirData(pFileInfo,tcp,path); } exit: delete[] header; ::closesocket(tcp); } } } void M8MsgProcess::ReceiveDirData(FileInfo* pFileInfo, SOCKET& tcp, WCHAR* dir) { char peek_buf[PEEK_SIZE+1]; char* header = new char[ MAX_BUF ]; bool notFinished = true; while(notFinished) { header[0]='\0'; RecvTCP(tcp, header, PEEK_SIZE); memcpy(peek_buf, header, PEEK_SIZE); peek_buf[PEEK_SIZE]='\0'; char *tok, *p; if ((tok = separate_token(peek_buf, ':', &p)) == NULL) // header size { delete[] header; return; } int headerSize = (int) hex2ll(tok); //recv(tcp, header + PEEK_SIZE ,headerSize - PEEK_SIZE ,0 ); RecvTCP(tcp, header+PEEK_SIZE, headerSize - PEEK_SIZE); header[headerSize]='\0'; FileInfo subFile; WCHAR path[MAX_PATH]; if( DecodeDirEntry(header, &subFile)) { switch( GET_MODE(subFile.Attr())) { case IPMSG_FILE_DIR: { wstring fileName; A2W(subFile.Fname(), fileName); wsprintf(path,L"%s%s/",dir,fileName.c_str()); ::CreateDirectory(path, NULL); ReceiveDirData(&subFile, tcp, path); } break; case IPMSG_FILE_REGULAR: { wstring fileName; A2W(subFile.Fname(), fileName); wsprintf(path,L"%s%s",dir,fileName.c_str()); fileName = path; SaveDataToFile(fileName, &subFile,tcp); } break; case IPMSG_FILE_RETPARENT: notFinished=false; break; } } } delete[] header; } void M8MsgProcess::SaveDataToFile(wstring& fileName, FileInfo* pFileInfo, SOCKET& tcp) { //wstring wPath; //A2W(fileName,wPath); //HANDLE fHandle = CreateFile(wPath.c_str(), GENERIC_WRITE,FILE_SHARE_WRITE, NULL,CREATE_ALWAYS,FILE_FLAG_WRITE_THROUGH,NULL); HANDLE fHandle = CreateFile(fileName.c_str(), GENERIC_WRITE,0, 0, OPEN_ALWAYS, FILE_FLAG_NO_BUFFERING, 0); pWnd->PostMessageW(WM_BEGIN_PROGRESS, (WPARAM)pFileInfo,NULL); long recved = 0L; int recv_buf_len; char* file_buf = new char[MAX_SOCKBUF]; while(recved < pFileInfo->Size()) { file_buf[0] ='\0'; if(pFileInfo->Size() - recved > MAX_SOCKBUF) { recv_buf_len = MAX_SOCKBUF; } else { recv_buf_len = pFileInfo->Size() - recved; } /* int actrecv = recv(tcp,file_buf,recv_buf_len,0); if(actrecv == SOCKET_ERROR || actrecv == 0) break; */ if(RecvTCP(tcp,file_buf, recv_buf_len) != 0) { //file.write(file_buf,recv_buf_len); WriteFile(fHandle, file_buf, recv_buf_len, NULL, NULL); } else { break; } recved += recv_buf_len; pWnd->PostMessageW(WM_UPDATE_PROGRESS, (WPARAM)pFileInfo,(LPARAM)recved); } pWnd->PostMessageW(WM_END_PROGRESS, (WPARAM)pFileInfo,NULL); ::CloseHandle(fHandle); delete[] file_buf; recevFileNo ++; } DWORD WINAPI M8MsgProcess::RecvFile_Thread(LPVOID lparam) { MessageProcess* mp = (MessageProcess*) lparam; M8MsgProcess* process = mp->process; MsgBuf* pMsgBuf = mp->pMsg; ::WaitForSingleObject(process->m_Mutex,INFINITE); process->processFile(pMsgBuf); ::ReleaseMutex(process->m_Mutex); delete mp; return 0; }