BufferMgr.cpp
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:11k
源码类别:

P2P编程

开发平台:

Visual C++

  1. /*
  2.  *  Openmysee
  3.  *
  4.  *  This program is free software; you can redistribute it and/or modify
  5.  *  it under the terms of the GNU General Public License as published by
  6.  *  the Free Software Foundation; either version 2 of the License, or
  7.  *  (at your option) any later version.
  8.  *
  9.  *  This program is distributed in the hope that it will be useful,
  10.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *  GNU General Public License for more details.
  13.  *
  14.  *  You should have received a copy of the GNU General Public License
  15.  *  along with this program; if not, write to the Free Software
  16.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17.  *
  18.  */
  19. // BufferMgr.cpp: implementation of the BufferMgr class.
  20. //
  21. //////////////////////////////////////////////////////////////////////
  22. #include "stdafx.h"
  23. #include "BufferMgr.h"
  24. #include <tlhelp32.h> 
  25. namespace NPLayer1 {
  26. //////////////////////////////////////////////////////////////////////
  27. // Construction/Destruction
  28. //////////////////////////////////////////////////////////////////////
  29. BufferMgr::BufferMgr() : blockArray(NULL), blockNum(0), hBufferFile(NULL) {
  30. }
  31. BufferMgr::~BufferMgr() {
  32. if(hBufferFile) {
  33. // 删除文件
  34. CloseHandle(hBufferFile);
  35. hBufferFile = NULL;
  36. }
  37. ::DeleteFile(bufferFileName.data());
  38. delete [] blockArray;
  39. blockArray = NULL;
  40. blockNum = 0;
  41. }
  42. P2P_RETURN_TYPE BufferMgr::Init(string fullPath, bool& bufFileModified, UINT randNum, UINT bufferSize) {
  43. bufFileModified = false;
  44. // 只能初始化一次,如果已经初始化了,就返回错误
  45. if(blockArray)
  46. return PRT_DUP_INIT;
  47. // 如果没有给出缓冲文件的全路径,则在缓冲文件夹建立一个缓冲文件
  48. GENERATE_FILENAME:if(fullPath.empty()) {
  49. // Filter文件所在的路径
  50. char buf[MAX_PATH_EX];
  51. if(!GetSelfModulePath(buf, MAX_PATH_EX))
  52. return PRT_SYS;
  53. bufferFileName = buf;
  54. bufferFileName.append("GB");
  55. itoa(randNum, buf, 10);
  56. bufferFileName.append(buf);
  57. bufferFileName.append(".tmp");
  58. }
  59. else
  60. bufferFileName = fullPath;
  61. // 缓冲文件的最大长度
  62. bufferFileSize = bufferSize;
  63. // 查找缓冲文件, 如果没有找到,则创建一个
  64. WIN32_FIND_DATA fileData;
  65. HANDLE hFind = FindFirstFile(bufferFileName.data(), &fileData);
  66. if(hFind == INVALID_HANDLE_VALUE) {
  67. for(;;) {
  68. // 创建缓冲文件
  69. if(!ExCreateFile(hBufferFile, bufferFileName.data(), CREATE_ALWAYS)) {
  70. int err = GetLastError();
  71. if(err == 3) { 
  72. // 创建文件失败,因为有不存在的中间目录,需要首先创建中间目录
  73. int index = 0;
  74. string temp;
  75. do {
  76. int offset = bufferFileName.find_first_of('\', index);
  77. if(offset == -1)
  78. break;
  79. temp = bufferFileName.substr(0, offset);
  80. index = offset+1;
  81. if(!CreateDirectory(temp.data(), NULL)) {
  82. int ret = GetLastError();
  83. if(ret == ERROR_ALREADY_EXISTS || ret == ERROR_ACCESS_DENIED)
  84. continue;
  85. break;
  86. }
  87. }while(1);
  88. // Create Again
  89. continue;
  90. }
  91. else
  92. return PRT_SYS;
  93. }
  94. // 成功创建文件
  95. bufFileModified = true;
  96. break;
  97. }
  98. // 将缓冲文件长度设为0
  99. ExSetFileSize(hBufferFile, 0);
  100. }
  101. else if(fullPath.empty()) {
  102. // 如果是随机生成的文件名,结果发现重名,则把randnum+1,再次尝试
  103. randNum++;
  104. goto GENERATE_FILENAME;
  105. }
  106. else {
  107. FindClose(hFind);
  108. // 打开缓冲文件
  109. if(!ExCreateFile(hBufferFile, bufferFileName.data(), OPEN_EXISTING)) {
  110. //assert(0);
  111. if(!ExCreateFile(hBufferFile, bufferFileName.data(), CREATE_ALWAYS)) {
  112. //assert(0);
  113. return PRT_CANNOT_OPEN_BUF;
  114. }
  115. bufFileModified = true;
  116. }
  117. }
  118. // 如果存在的文件大小超过目标文件大小,则将其大小设置为目标文件大小
  119. UINT realBufSize = ::GetFileSize(hBufferFile, NULL);
  120. if(realBufSize == INVALID_FILE_SIZE)
  121. return PRT_SYS;
  122. if(realBufSize > bufferFileSize) {
  123. // 将缓冲文件长度设为目标文件大小
  124. ExSetFileSize(hBufferFile, bufferFileSize);
  125. realBufSize = bufferFileSize;
  126. bufFileModified = true;
  127. }
  128. // 检查磁盘空间是否足够
  129. ULARGE_INTEGER availableBytes, totalBytes;
  130. string purepath = bufferFileName;
  131. int index = purepath.find_last_of('\');
  132. if(index != -1)
  133. purepath.resize(index);
  134. else
  135. return PRT_SYS;
  136. if(!GetDiskFreeSpaceEx(purepath.data(), &availableBytes, &totalBytes, NULL)) {
  137. return PRT_SYS;
  138. }
  139. else {
  140. if(availableBytes.QuadPart < bufferFileSize-realBufSize) {
  141. // not enough space on disk
  142. return PRT_DISK_FULL;
  143. }
  144. }
  145. // 计算数组大小, 如果不能整除,则加一
  146. blockNum = bufferFileSize/BLOCK_SIZE;
  147. if(bufferFileSize%BLOCK_SIZE != 0)
  148. blockNum++;
  149. // 初始化数组
  150. blockArray = new bool[blockNum];
  151. if(!blockArray)
  152. return PRT_ALLOC;
  153. // 将所有成员置为false, 即标记所有快为未使用
  154. fill(blockArray, blockArray+blockNum, false);
  155. return PRT_OK;
  156. }
  157. UINT BufferMgr::GetEmptyIndex(UINT randNum) {
  158. // 如果尚未初始化,则返回错误
  159. if(!blockArray)
  160. return UINT_MAX;
  161. // 使用随机数选择缓冲区中的空位,这是为了防止有人Hook我们的缓冲区
  162. // 如果我们是顺序存储的,那么很容易就从新建缓冲区中按顺序读出数据
  163. // 所以要使用随即的存储位置
  164. // 1. 根据随机数,确定随机位置
  165. UINT randPos = randNum%blockNum;
  166. // 2. 将遍历用的iterator移动到该随机位置
  167. UINT i = randPos;
  168. // 3. 设定第一轮循环的开始结束位置,从随机位置到hash_map尾
  169. UINT start = i;
  170. UINT end = blockNum;
  171. for(; ;++i) {
  172. if(i == end) {
  173. if(end == blockNum) {
  174. // 4. 第一轮循环结束,开始第二轮,从头到随机位置
  175. i = 0;
  176. end = start;
  177. // 如果两者相等说明只有一个元素,而且第一轮已经比较过了,所以跳出循环
  178. if(i == end) {
  179. break;
  180. }
  181. }
  182. else {
  183. // 5. 第二轮循环结束,跳出循环
  184. break;
  185. }
  186. }
  187. // 如果发现一个未使用的块,则标记为已使用,并返回数组下标
  188. if(!blockArray[i]) {
  189. blockArray[i] = true;
  190. return i;
  191. }
  192. }
  193. return UINT_MAX;
  194. }
  195. void BufferMgr::EraseIndex(UINT index) {
  196. // 如果尚未初始化,则返回
  197. if(!blockArray)
  198. return;
  199. // 下标越界
  200. if(index >= blockNum)
  201. return;
  202. // 将此块标记为未使用
  203. blockArray[index] = false;
  204. }
  205. // 获取剩余空间大小
  206. UINT BufferMgr::GetEmptySpace() {
  207. return BLOCK_SIZE*count(blockArray, blockArray+blockNum, false);
  208. }
  209. P2P_RETURN_TYPE BufferMgr::GetIndexData(UINT index, UINT offset, LPVOID data, UINT size) {
  210. // 如果参数错误或者尚未初始化,则返回错误
  211. if(!data || !blockArray)
  212. return PRT_WRONG_ARG;
  213. // 如果超过边界,则返回错误
  214. if(index >= blockNum)
  215. return PRT_WRONG_ARG;
  216. // 如果要求的数据过大,则返回错误
  217. if(offset+size > BLOCK_SIZE)
  218. return PRT_WRONG_ARG;
  219. // 如果要求的是最后一块,但是数据长度过大,则返回错误
  220. if(index == blockNum-1 && offset+size > bufferFileSize-index*BLOCK_SIZE)
  221. return PRT_WRONG_ARG;
  222. // 如果此块不存在,则返回出错
  223. //if(!blockArray[index])
  224. // return PRT_WRONG_ARG;
  225. // 移动文件指针到偏移位置
  226. if(!ExSetFilePointer(hBufferFile, index*BLOCK_SIZE+offset))
  227. return PRT_SYS;
  228. // 如果读到的数据长度不等于需要的数据长度,则返回错误
  229. if(ExReadFile(hBufferFile, data, size) != size)
  230. return PRT_SYS;
  231. return PRT_OK;
  232. }
  233. P2P_RETURN_TYPE BufferMgr::PutIndexData(UINT index, LPVOID data, UINT size) {
  234. // 如果参数错误或者尚未初始化,则返回错误
  235. if(!data || !blockArray)
  236. return PRT_WRONG_ARG;
  237. // 如果超过边界,则返回错误
  238. if(index >= blockNum)
  239. return PRT_WRONG_ARG;
  240. // 如果数据过大,则返回错误
  241. if(size > BLOCK_SIZE)
  242. return PRT_WRONG_ARG;
  243. // 如果是最后一块,但是数据长度过大,则返回错误
  244. if(index == blockNum-1 && size > bufferFileSize-index*BLOCK_SIZE)
  245. return PRT_WRONG_ARG;
  246. /*
  247. // 在GetEmptyIndex里已经把这里划分出去了!
  248. // 如果此块已经存在,则返回出错
  249. if(blockArray[index])
  250. return FALSE;
  251. */
  252. // 移动文件指针到偏移位置
  253. if(!ExSetFilePointer(hBufferFile, index*BLOCK_SIZE))
  254. return PRT_SYS;
  255. // 如果写入的数据长度不等于实际的数据长度,则返回错误
  256. if(ExWriteFile(hBufferFile, data, size) != size)
  257. return PRT_SYS;
  258. return PRT_OK;
  259. }
  260. BOOL BufferMgr::ExSetFileSize(HANDLE handle, UINT size) {
  261. BOOL ret = TRUE;
  262. if(!ExSetFilePointer(handle, size))
  263. ret = FALSE;
  264. else if(0 == SetEndOfFile(handle)) {
  265. ret = FALSE;
  266. }
  267. return ret;
  268. }
  269. UINT BufferMgr::ExReadFile(HANDLE handle, LPVOID buf, UINT toBeRead) {
  270. UINT readCount = 0;
  271. DWORD tmpRead;
  272. while(readCount < toBeRead) {
  273. BOOL success = ReadFile(
  274. handle, // file handler
  275. (char*)buf+readCount, // current buffer position
  276. toBeRead - readCount, // remaining bytes to be read
  277. &tmpRead, // read bytes
  278. NULL); // not overlaped
  279. if(!success)
  280. return 0;
  281. if(tmpRead == 0) // no more data
  282. return 0;
  283. readCount += tmpRead;
  284. }
  285. return readCount;
  286. }
  287. UINT BufferMgr::ExWriteFile(HANDLE handle, LPCVOID buf, UINT toBeWrite) {
  288. UINT writeCount = 0;
  289. DWORD tmpWrite;
  290. while(writeCount < toBeWrite) {
  291. BOOL success = WriteFile(
  292. handle, // file handler
  293. (char*)buf+writeCount, // current buffer position
  294. toBeWrite-writeCount, // remaining bytes to be read
  295. &tmpWrite, // written bytes
  296. NULL); // not overlaped
  297. if(!success) {
  298. return FALSE;
  299. }
  300. writeCount += tmpWrite;
  301. }
  302. return writeCount;
  303. }
  304. BOOL BufferMgr::ExSetFilePointer(HANDLE handle, UINT offset) {
  305. if(-1 == SetFilePointer(handle, 
  306. offset, 
  307. NULL, 
  308. FILE_BEGIN)) {
  309. return FALSE;
  310. }
  311. return TRUE;
  312. }
  313. BOOL BufferMgr::ExCreateFile(HANDLE& handle,
  314. LPCTSTR lpFileName,
  315. DWORD dwDesiredAccess,
  316. DWORD dwShareMode,
  317. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  318. DWORD dwCreationDisposition,
  319. DWORD dwFlagsAndAttributes,
  320. HANDLE hTemplateFile) {
  321. handle = CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, 
  322. dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  323. if(handle == INVALID_HANDLE_VALUE) {
  324. return FALSE;
  325. }
  326. return TRUE;
  327. }
  328. BOOL BufferMgr::ExCreateFile(HANDLE& handle, LPCTSTR lpFileName, DWORD dwCreationDisposition) {
  329. handle = CreateFile(lpFileName, 
  330. GENERIC_WRITE | GENERIC_READ, 
  331. 0, 
  332. NULL, 
  333. dwCreationDisposition, 
  334. FILE_ATTRIBUTE_NORMAL, 
  335. NULL);
  336. if(handle == INVALID_HANDLE_VALUE) {
  337. return FALSE; 
  338. }
  339. return TRUE;
  340. }
  341. BOOL BufferMgr::GetSelfModulePath(LPTSTR buf, DWORD nSize) {
  342. HANDLE hModuleSnap = INVALID_HANDLE_VALUE; 
  343. MODULEENTRY32 me32; 
  344. //  Take a snapshot of all modules in the specified process. 
  345. hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); 
  346. if(hModuleSnap == INVALID_HANDLE_VALUE) 
  347. return FALSE; 
  348. //  Set the size of the structure before using it. 
  349. me32.dwSize = sizeof(MODULEENTRY32); 
  350. //  Retrieve information about the first module, 
  351. //  and exit if unsuccessful 
  352. if(!Module32First(hModuleSnap, &me32)) { 
  353. CloseHandle(hModuleSnap);     // Must clean up the snapshot object! 
  354. return FALSE; 
  355. //  Now walk the module list of the process, 
  356. //  and display information about each module 
  357. do 
  358. {
  359. _tcsupr(me32.szModule);
  360. if( _tcsncmp(me32.szModule, _T("LAYER1.DLL"), _tcslen(_T("LAYER1.DLL"))) != NULL || 
  361. _tcsncmp(me32.szModule, _T("LAYER1D.DLL"), _tcslen(_T("LAYER1D.DLL"))) != NULL) {
  362. if(_tcslen(me32.szExePath) >= nSize)
  363. return FALSE;
  364. _tcscpy(buf, me32.szExePath);
  365. char* index = _tcsrchr(buf, _T('\'));
  366. if(index == 0)
  367. return FALSE;
  368. index[1] = 0;
  369. return TRUE;  // Find target module name
  370. }
  371. } while(Module32Next(hModuleSnap, &me32)); 
  372. //  Do not forget to clean up the snapshot object. 
  373. CloseHandle(hModuleSnap);
  374. return FALSE;
  375. }
  376. }