BufferMgr.cpp
资源名称:p2p_vod.rar [点击查看]
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:11k
源码类别:
P2P编程
开发平台:
Visual C++
- /*
- * Openmysee
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
- // BufferMgr.cpp: implementation of the BufferMgr class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "BufferMgr.h"
- #include <tlhelp32.h>
- namespace NPLayer1 {
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- BufferMgr::BufferMgr() : blockArray(NULL), blockNum(0), hBufferFile(NULL) {
- }
- BufferMgr::~BufferMgr() {
- if(hBufferFile) {
- // 删除文件
- CloseHandle(hBufferFile);
- hBufferFile = NULL;
- }
- ::DeleteFile(bufferFileName.data());
- delete [] blockArray;
- blockArray = NULL;
- blockNum = 0;
- }
- P2P_RETURN_TYPE BufferMgr::Init(string fullPath, bool& bufFileModified, UINT randNum, UINT bufferSize) {
- bufFileModified = false;
- // 只能初始化一次,如果已经初始化了,就返回错误
- if(blockArray)
- return PRT_DUP_INIT;
- // 如果没有给出缓冲文件的全路径,则在缓冲文件夹建立一个缓冲文件
- GENERATE_FILENAME:if(fullPath.empty()) {
- // Filter文件所在的路径
- char buf[MAX_PATH_EX];
- if(!GetSelfModulePath(buf, MAX_PATH_EX))
- return PRT_SYS;
- bufferFileName = buf;
- bufferFileName.append("GB");
- itoa(randNum, buf, 10);
- bufferFileName.append(buf);
- bufferFileName.append(".tmp");
- }
- else
- bufferFileName = fullPath;
- // 缓冲文件的最大长度
- bufferFileSize = bufferSize;
- // 查找缓冲文件, 如果没有找到,则创建一个
- WIN32_FIND_DATA fileData;
- HANDLE hFind = FindFirstFile(bufferFileName.data(), &fileData);
- if(hFind == INVALID_HANDLE_VALUE) {
- for(;;) {
- // 创建缓冲文件
- if(!ExCreateFile(hBufferFile, bufferFileName.data(), CREATE_ALWAYS)) {
- int err = GetLastError();
- if(err == 3) {
- // 创建文件失败,因为有不存在的中间目录,需要首先创建中间目录
- int index = 0;
- string temp;
- do {
- int offset = bufferFileName.find_first_of('\', index);
- if(offset == -1)
- break;
- temp = bufferFileName.substr(0, offset);
- index = offset+1;
- if(!CreateDirectory(temp.data(), NULL)) {
- int ret = GetLastError();
- if(ret == ERROR_ALREADY_EXISTS || ret == ERROR_ACCESS_DENIED)
- continue;
- break;
- }
- }while(1);
- // Create Again
- continue;
- }
- else
- return PRT_SYS;
- }
- // 成功创建文件
- bufFileModified = true;
- break;
- }
- // 将缓冲文件长度设为0
- ExSetFileSize(hBufferFile, 0);
- }
- else if(fullPath.empty()) {
- // 如果是随机生成的文件名,结果发现重名,则把randnum+1,再次尝试
- randNum++;
- goto GENERATE_FILENAME;
- }
- else {
- FindClose(hFind);
- // 打开缓冲文件
- if(!ExCreateFile(hBufferFile, bufferFileName.data(), OPEN_EXISTING)) {
- //assert(0);
- if(!ExCreateFile(hBufferFile, bufferFileName.data(), CREATE_ALWAYS)) {
- //assert(0);
- return PRT_CANNOT_OPEN_BUF;
- }
- bufFileModified = true;
- }
- }
- // 如果存在的文件大小超过目标文件大小,则将其大小设置为目标文件大小
- UINT realBufSize = ::GetFileSize(hBufferFile, NULL);
- if(realBufSize == INVALID_FILE_SIZE)
- return PRT_SYS;
- if(realBufSize > bufferFileSize) {
- // 将缓冲文件长度设为目标文件大小
- ExSetFileSize(hBufferFile, bufferFileSize);
- realBufSize = bufferFileSize;
- bufFileModified = true;
- }
- // 检查磁盘空间是否足够
- ULARGE_INTEGER availableBytes, totalBytes;
- string purepath = bufferFileName;
- int index = purepath.find_last_of('\');
- if(index != -1)
- purepath.resize(index);
- else
- return PRT_SYS;
- if(!GetDiskFreeSpaceEx(purepath.data(), &availableBytes, &totalBytes, NULL)) {
- return PRT_SYS;
- }
- else {
- if(availableBytes.QuadPart < bufferFileSize-realBufSize) {
- // not enough space on disk
- return PRT_DISK_FULL;
- }
- }
- // 计算数组大小, 如果不能整除,则加一
- blockNum = bufferFileSize/BLOCK_SIZE;
- if(bufferFileSize%BLOCK_SIZE != 0)
- blockNum++;
- // 初始化数组
- blockArray = new bool[blockNum];
- if(!blockArray)
- return PRT_ALLOC;
- // 将所有成员置为false, 即标记所有快为未使用
- fill(blockArray, blockArray+blockNum, false);
- return PRT_OK;
- }
- UINT BufferMgr::GetEmptyIndex(UINT randNum) {
- // 如果尚未初始化,则返回错误
- if(!blockArray)
- return UINT_MAX;
- // 使用随机数选择缓冲区中的空位,这是为了防止有人Hook我们的缓冲区
- // 如果我们是顺序存储的,那么很容易就从新建缓冲区中按顺序读出数据
- // 所以要使用随即的存储位置
- // 1. 根据随机数,确定随机位置
- UINT randPos = randNum%blockNum;
- // 2. 将遍历用的iterator移动到该随机位置
- UINT i = randPos;
- // 3. 设定第一轮循环的开始结束位置,从随机位置到hash_map尾
- UINT start = i;
- UINT end = blockNum;
- for(; ;++i) {
- if(i == end) {
- if(end == blockNum) {
- // 4. 第一轮循环结束,开始第二轮,从头到随机位置
- i = 0;
- end = start;
- // 如果两者相等说明只有一个元素,而且第一轮已经比较过了,所以跳出循环
- if(i == end) {
- break;
- }
- }
- else {
- // 5. 第二轮循环结束,跳出循环
- break;
- }
- }
- // 如果发现一个未使用的块,则标记为已使用,并返回数组下标
- if(!blockArray[i]) {
- blockArray[i] = true;
- return i;
- }
- }
- return UINT_MAX;
- }
- void BufferMgr::EraseIndex(UINT index) {
- // 如果尚未初始化,则返回
- if(!blockArray)
- return;
- // 下标越界
- if(index >= blockNum)
- return;
- // 将此块标记为未使用
- blockArray[index] = false;
- }
- // 获取剩余空间大小
- UINT BufferMgr::GetEmptySpace() {
- return BLOCK_SIZE*count(blockArray, blockArray+blockNum, false);
- }
- P2P_RETURN_TYPE BufferMgr::GetIndexData(UINT index, UINT offset, LPVOID data, UINT size) {
- // 如果参数错误或者尚未初始化,则返回错误
- if(!data || !blockArray)
- return PRT_WRONG_ARG;
- // 如果超过边界,则返回错误
- if(index >= blockNum)
- return PRT_WRONG_ARG;
- // 如果要求的数据过大,则返回错误
- if(offset+size > BLOCK_SIZE)
- return PRT_WRONG_ARG;
- // 如果要求的是最后一块,但是数据长度过大,则返回错误
- if(index == blockNum-1 && offset+size > bufferFileSize-index*BLOCK_SIZE)
- return PRT_WRONG_ARG;
- // 如果此块不存在,则返回出错
- //if(!blockArray[index])
- // return PRT_WRONG_ARG;
- // 移动文件指针到偏移位置
- if(!ExSetFilePointer(hBufferFile, index*BLOCK_SIZE+offset))
- return PRT_SYS;
- // 如果读到的数据长度不等于需要的数据长度,则返回错误
- if(ExReadFile(hBufferFile, data, size) != size)
- return PRT_SYS;
- return PRT_OK;
- }
- P2P_RETURN_TYPE BufferMgr::PutIndexData(UINT index, LPVOID data, UINT size) {
- // 如果参数错误或者尚未初始化,则返回错误
- if(!data || !blockArray)
- return PRT_WRONG_ARG;
- // 如果超过边界,则返回错误
- if(index >= blockNum)
- return PRT_WRONG_ARG;
- // 如果数据过大,则返回错误
- if(size > BLOCK_SIZE)
- return PRT_WRONG_ARG;
- // 如果是最后一块,但是数据长度过大,则返回错误
- if(index == blockNum-1 && size > bufferFileSize-index*BLOCK_SIZE)
- return PRT_WRONG_ARG;
- /*
- // 在GetEmptyIndex里已经把这里划分出去了!
- // 如果此块已经存在,则返回出错
- if(blockArray[index])
- return FALSE;
- */
- // 移动文件指针到偏移位置
- if(!ExSetFilePointer(hBufferFile, index*BLOCK_SIZE))
- return PRT_SYS;
- // 如果写入的数据长度不等于实际的数据长度,则返回错误
- if(ExWriteFile(hBufferFile, data, size) != size)
- return PRT_SYS;
- return PRT_OK;
- }
- BOOL BufferMgr::ExSetFileSize(HANDLE handle, UINT size) {
- BOOL ret = TRUE;
- if(!ExSetFilePointer(handle, size))
- ret = FALSE;
- else if(0 == SetEndOfFile(handle)) {
- ret = FALSE;
- }
- return ret;
- }
- UINT BufferMgr::ExReadFile(HANDLE handle, LPVOID buf, UINT toBeRead) {
- UINT readCount = 0;
- DWORD tmpRead;
- while(readCount < toBeRead) {
- BOOL success = ReadFile(
- handle, // file handler
- (char*)buf+readCount, // current buffer position
- toBeRead - readCount, // remaining bytes to be read
- &tmpRead, // read bytes
- NULL); // not overlaped
- if(!success)
- return 0;
- if(tmpRead == 0) // no more data
- return 0;
- readCount += tmpRead;
- }
- return readCount;
- }
- UINT BufferMgr::ExWriteFile(HANDLE handle, LPCVOID buf, UINT toBeWrite) {
- UINT writeCount = 0;
- DWORD tmpWrite;
- while(writeCount < toBeWrite) {
- BOOL success = WriteFile(
- handle, // file handler
- (char*)buf+writeCount, // current buffer position
- toBeWrite-writeCount, // remaining bytes to be read
- &tmpWrite, // written bytes
- NULL); // not overlaped
- if(!success) {
- return FALSE;
- }
- writeCount += tmpWrite;
- }
- return writeCount;
- }
- BOOL BufferMgr::ExSetFilePointer(HANDLE handle, UINT offset) {
- if(-1 == SetFilePointer(handle,
- offset,
- NULL,
- FILE_BEGIN)) {
- return FALSE;
- }
- return TRUE;
- }
- BOOL BufferMgr::ExCreateFile(HANDLE& handle,
- LPCTSTR lpFileName,
- DWORD dwDesiredAccess,
- DWORD dwShareMode,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- DWORD dwCreationDisposition,
- DWORD dwFlagsAndAttributes,
- HANDLE hTemplateFile) {
- handle = CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
- dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
- if(handle == INVALID_HANDLE_VALUE) {
- return FALSE;
- }
- return TRUE;
- }
- BOOL BufferMgr::ExCreateFile(HANDLE& handle, LPCTSTR lpFileName, DWORD dwCreationDisposition) {
- handle = CreateFile(lpFileName,
- GENERIC_WRITE | GENERIC_READ,
- 0,
- NULL,
- dwCreationDisposition,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- if(handle == INVALID_HANDLE_VALUE) {
- return FALSE;
- }
- return TRUE;
- }
- BOOL BufferMgr::GetSelfModulePath(LPTSTR buf, DWORD nSize) {
- HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
- MODULEENTRY32 me32;
- // Take a snapshot of all modules in the specified process.
- hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
- if(hModuleSnap == INVALID_HANDLE_VALUE)
- return FALSE;
- // Set the size of the structure before using it.
- me32.dwSize = sizeof(MODULEENTRY32);
- // Retrieve information about the first module,
- // and exit if unsuccessful
- if(!Module32First(hModuleSnap, &me32)) {
- CloseHandle(hModuleSnap); // Must clean up the snapshot object!
- return FALSE;
- }
- // Now walk the module list of the process,
- // and display information about each module
- do
- {
- _tcsupr(me32.szModule);
- if( _tcsncmp(me32.szModule, _T("LAYER1.DLL"), _tcslen(_T("LAYER1.DLL"))) != NULL ||
- _tcsncmp(me32.szModule, _T("LAYER1D.DLL"), _tcslen(_T("LAYER1D.DLL"))) != NULL) {
- if(_tcslen(me32.szExePath) >= nSize)
- return FALSE;
- _tcscpy(buf, me32.szExePath);
- char* index = _tcsrchr(buf, _T('\'));
- if(index == 0)
- return FALSE;
- index[1] = 0;
- return TRUE; // Find target module name
- }
- } while(Module32Next(hModuleSnap, &me32));
- // Do not forget to clean up the snapshot object.
- CloseHandle(hModuleSnap);
- return FALSE;
- }
- }