⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buffermgr.cpp

📁 mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体播放系统。在应有了P2P技术和一系列先进流媒体技术之后
💻 CPP
字号:
/*
 *  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;
}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -