MakeMetaFile.cpp
上传用户:lds876
上传日期:2013-05-25
资源大小:567k
文件大小:11k
源码类别:

P2P编程

开发平台:

Visual C++

  1. // MakeMetaFile.cpp: implementation of the CMakeMetaFile class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "testbt.h"
  6. #include "MakeMetaFile.h"
  7. #include "filebase.h"
  8. #include "Val.h"
  9. #include "sha.h"
  10. #include "btformat.h"
  11. #include "Bdecode.h"
  12. #ifdef _DEBUG
  13. #undef THIS_FILE
  14. static char THIS_FILE[]=__FILE__;
  15. #define new DEBUG_NEW
  16. #endif
  17. //////////////////////////////////////////////////////////////////////
  18. // Construction/Destruction
  19. //////////////////////////////////////////////////////////////////////
  20. CMakeMetaFile::CMakeMetaFile()
  21. {
  22. m_hevDone = CreateEvent(0, true, false, 0);
  23. m_hThreadDone = CreateEvent(0, true, true, 0);
  24. m_bResult =false;
  25. m_lPieceLenExp = 0;
  26. m_hWnd = 0;
  27. }
  28. CMakeMetaFile::~CMakeMetaFile()
  29. {
  30. Close();
  31. assert(IsEventSet(m_hThreadDone));
  32. CloseHandle(m_hevDone);
  33. CloseHandle(m_hThreadDone);
  34. }
  35. /////////////////////////////////////////////////////////////////
  36. // return value : the state of making meta file.
  37. bool CMakeMetaFile::Close()
  38. {
  39. if (!IsEventSet(m_hThreadDone))
  40. {
  41. SetEvent(m_hevDone);
  42. DWORD dwRet = WaitForSingleObject(m_hThreadDone, INFINITE);
  43. switch (dwRet)
  44. {
  45. case WAIT_OBJECT_0:
  46. break;
  47. case WAIT_TIMEOUT:
  48. break;
  49. }
  50. }
  51. return m_bResult;
  52. }
  53. string CMakeMetaFile::GetSrcPath() const
  54. {
  55. return m_strFilePath;
  56. }
  57. string CMakeMetaFile::GetSavePath() const 
  58. {
  59. return m_strSaveAs;
  60. }
  61. bool CMakeMetaFile::IsMaking()
  62. {
  63. return !IsEventSet(m_hThreadDone);
  64. }
  65. bool CMakeMetaFile::GetResult() const 
  66. {
  67. return m_bResult;
  68. }
  69. string CMakeMetaFile::GetErrorMsg() const 
  70. {
  71. return m_strErr;
  72. }
  73. bool CMakeMetaFile::MakeMetaFileEx(string strFilePath, string strSaveAs, string strUrl, string strComment, long lPieceLenExp, HWND hWnd)
  74. {
  75. // assert.
  76. assert(lPieceLenExp> 0 && lPieceLenExp< 25 && 
  77. !strFilePath.empty() && 
  78. !strSaveAs.empty() && 
  79. ::IsWindow(hWnd));
  80. m_strFilePath = strFilePath;
  81. m_strSaveAs = strSaveAs ;
  82. m_strUrl = strUrl;
  83. m_strComment = strComment;
  84. m_lPieceLenExp = lPieceLenExp;
  85. m_hWnd = hWnd;
  86. assert(::IsWindow(m_hWnd));
  87. m_bResult = false;
  88. m_strErr.erase();
  89. if (IsMaking())
  90. {
  91. assert(false);
  92. return false;
  93. }
  94. ResetEvent(m_hThreadDone);
  95. ResetEvent(m_hevDone);
  96. DWORD dwThreadId = 0;
  97. ::CreateThread(0, 0, MakeMetaFiledProc, this, 0, &dwThreadId);
  98. return true;
  99. }
  100. DWORD WINAPI CMakeMetaFile::MakeMetaFiledProc(void *pParam)
  101. {
  102. CMakeMetaFile* pMakeMetaFiled= (CMakeMetaFile* )pParam;
  103. pMakeMetaFiled->MakeMetaFiledProcEx();
  104. return 0;
  105. }
  106. void CMakeMetaFile::MakeMetaFiledProcEx()
  107. {
  108. m_bResult = MakeMetaFile();
  109. if (!IsEventSet(m_hevDone))
  110. PostMessage(m_hWnd, MAKE_METAFILE_FINISHED, 0, 0);
  111. SetEvent(m_hThreadDone);
  112. }
  113. bool CMakeMetaFile::MakeMetaFile()
  114. {
  115. // make info
  116. CVal* pInfo = makeinfo(m_strFilePath, pow(2, m_lPieceLenExp));
  117. if (!pInfo) 
  118. {
  119. m_strErr += "makeinfo error";
  120. return false;
  121. }
  122. PVALMAP pMsg = new VALMAP();
  123. (*pMsg)["info"] = pInfo;
  124. (*pMsg)["announce"] = new CVal(m_strUrl);
  125. if (!m_strComment.empty())
  126. (*pMsg)["comment"] = new CVal(string(m_strComment));
  127. CVal* pValMsg = new CVal(pMsg);
  128. auto_ptr<CVal> aMsg(pValMsg);
  129. if (IsEventSet(m_hevDone))
  130. return false;
  131. // check info.
  132. try
  133. {
  134. CBTFormat::CheckInfo(pInfo);
  135. }
  136. catch (string e)
  137. {
  138. m_strErr += "check info error";
  139. return false;
  140. }
  141. // encode.
  142. memstream memBuf;
  143. CBdecode::bencode(pValMsg, memBuf);
  144. // save as torrent file.
  145. FILE* pfile = fopen(m_strSaveAs.data(), "wb");
  146. if (!pfile)
  147. {
  148. m_strErr = string("write torrent file (") + m_strSaveAs + ") error";
  149. return false;
  150. }
  151. long lWrite = fwrite(memBuf, sizeof(char), memBuf.size(), pfile);
  152. fclose(pfile);
  153. return true;
  154. }
  155. CVal* CMakeMetaFile::makeinfo(string strFilePath, long lPieceLength)
  156. {
  157. DWORD dwAttr = GetFileAttributes(strFilePath.data());
  158. if (dwAttr ==  0xffffffff)
  159. return false;
  160. // get name map.
  161. if (strFilePath[strFilePath.size() - 1] == '\')
  162. strFilePath.erase(strFilePath.size() - 1);
  163. char *pszFileName = 0;
  164. char szPathName[MAX_PATH] = {0};
  165. if (!GetFullPathName(strFilePath.data(), MAX_PATH, szPathName, &pszFileName))
  166. {
  167. assert(false);
  168. return 0;
  169. }
  170. if (pszFileName == 0) // strFilePath is the root driver.
  171. {
  172. assert(false);
  173. return 0;
  174. }
  175. if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
  176. {
  177. // get vFiles.
  178. vector<string> vSubPaths;
  179. CSubFilesList SubFilesList;
  180. if (!SubFiles(strFilePath, vSubPaths, SubFilesList, m_hevDone))
  181. {
  182. for (int i=0; i<SubFilesList.size(); i++)
  183. {
  184. if (SubFilesList[i].m_pPathList)
  185. delete SubFilesList[i].m_pPathList;
  186. }
  187. return 0;
  188. }
  189. //
  190. // get pieces and files map.
  191. //
  192. int iPiecesCount = 0;
  193. memstream memPieces;
  194. PVALLIST pFileList = new VALLIST();
  195. long lDone = 0;
  196. long lTotalHashsed = 0;
  197. long lTotalSize = 0;
  198. for (int i=0; i<SubFilesList.size(); i++)
  199. {
  200. if (IsEventSet(m_hevDone))
  201. return 0;
  202. lTotalSize += GetFileSize(SubFilesList[i].m_strPath);
  203. }
  204. CSHA sha;
  205. sha.start();
  206. unsigned char sha1sum[20];
  207. for (i=0; i<SubFilesList.size(); i++)
  208. {
  209. FILE* pfile = fopen(SubFilesList[i].m_strPath.data(), "rb");
  210. if (!pfile) 
  211. {
  212. m_strErr = "no such file : (" + SubFilesList[i].m_strPath + ")";
  213. break;
  214. }
  215. long lsize = GetFileSize(SubFilesList[i].m_strPath);
  216. long lPos = 0;
  217. unsigned char* pszBuf = new unsigned char[lPieceLength];
  218. auto_ptr<unsigned char> aszBuf(pszBuf);
  219. while (lPos < lsize)
  220. {
  221. long lLeftLen = min(lsize - lPos, lPieceLength - lDone);
  222. int iRead = fread(pszBuf, sizeof(char), lLeftLen, pfile);
  223. if (iRead != lLeftLen)
  224. {
  225. assert(false);
  226. fclose(pfile);
  227. break;
  228. }
  229. TRACE("Iseventset read in filern");
  230. if (IsEventSet(m_hevDone))
  231. break;
  232. lPos += iRead;
  233. lDone += iRead;
  234. lTotalHashsed += iRead;
  235. sha.update(pszBuf, lLeftLen);
  236. if (lDone == lPieceLength)
  237. {
  238. lDone = 0;
  239. sha.finish(sha1sum);
  240. memPieces.write((char*)sha1sum, 20);
  241. sha.start();
  242. iPiecesCount++;
  243. }
  244. if (lTotalSize > 0)
  245. ProgressInfo(float(lTotalHashsed)/ lTotalSize);
  246. else
  247. ProgressInfo(float(1));
  248. } // end while
  249. if (lPos < lsize)
  250. {
  251. // assert(false);
  252. fclose(pfile);
  253. break;
  254. }
  255. PVALMAP pFileMap = new VALMAP;
  256. (*pFileMap) ["length"] = new CVal(lsize);
  257. assert(SubFilesList[i].m_pPathList);
  258. (*pFileMap) ["path"] = SubFilesList[i].m_pPathList;
  259. SubFilesList[i].m_pPathList = 0;
  260. pFileList->push_back(new CVal(pFileMap));
  261. fclose(pfile);
  262. TRACE("Iseventset end for rn");
  263. if (IsEventSet(m_hevDone))
  264. break;
  265. } // end for
  266. if (i != SubFilesList.size()) // fail
  267. {
  268. delete new CVal(pFileList);
  269. // clear not detached pathlist CVal;
  270. for (int j=0; j<SubFilesList.size(); j++)
  271. {
  272. if (SubFilesList[j].m_pPathList)
  273. delete SubFilesList[j].m_pPathList;
  274. }
  275. return 0;
  276. }
  277. if (lDone > 0)
  278. {
  279. sha.finish(sha1sum);
  280. memPieces.write((char*)sha1sum, 20);
  281. iPiecesCount++;
  282. }
  283. PVALMAP pRet = new VALMAP();
  284. if (memPieces.size() <= 0)
  285. (*pRet)["pieces"] = new CVal(0, 0);
  286. else
  287. (*pRet)["pieces"] = new CVal(memPieces, memPieces.size());
  288. (*pRet)["piece length"] = new CVal(lPieceLength);
  289. (*pRet)["files"] = new CVal(pFileList);
  290. (*pRet)["name"] = new CVal(string(pszFileName));
  291. return new CVal(pRet);
  292. }
  293. else
  294. {
  295. long lsize = GetFileSize(strFilePath);
  296. FILE* pfile = fopen(strFilePath.data(), "rb");
  297. if (!pfile) return 0;
  298. memstream memPieces;
  299. CSHA sha;
  300. sha.start();
  301. unsigned char sha1sum[20];
  302. long lLeftLen = 0;
  303. long lPos = 0;
  304. unsigned char* pszBuf = new unsigned char[lPieceLength];
  305. auto_ptr<unsigned char> aszBuf(pszBuf);
  306. while (lPos < lsize)
  307. {
  308. lLeftLen = min(lsize - lPos, lPieceLength);
  309. int iRead = fread(pszBuf, sizeof(char), lLeftLen, pfile);
  310. if (iRead != lLeftLen)
  311. {
  312. assert(false);
  313. fclose(pfile);
  314. break;
  315. }
  316. if (IsEventSet(m_hevDone))
  317. break;
  318. lPos += iRead;
  319. sha.update(pszBuf, lLeftLen);
  320. sha.finish(sha1sum);
  321. memPieces.write((char*)sha1sum, 20);
  322. sha.start();
  323. if (lsize> 0)
  324. ProgressInfo(float(lPos)/ lsize);
  325. else
  326. ProgressInfo(float(1));
  327. }
  328. if (lPos < lsize) // fail
  329. {
  330. // assert(false);
  331. return 0;
  332. }
  333. fclose(pfile);
  334. PVALMAP pRet = new VALMAP();
  335. // (*pRet)["pieces"] = new CVal(memPieces, memPieces.size());
  336. if (memPieces.size() <= 0)
  337. (*pRet)["pieces"] = new CVal(0, 0);
  338. else
  339. (*pRet)["pieces"] = new CVal(memPieces, memPieces.size());
  340. (*pRet)["piece length"] = new CVal(lPieceLength);
  341. (*pRet)["length"] = new CVal(lsize);
  342. (*pRet)["name"] = new CVal(string(pszFileName));
  343. return new CVal(pRet);
  344. }
  345. return 0;
  346. }
  347. bool CMakeMetaFile::SubFiles(string strPath, vector<string> vSubPaths, CSubFilesList& SubFilesList, HANDLE hevDone)
  348. {
  349. DWORD dwAttr = GetFileAttributes(strPath.data());
  350. if (dwAttr ==  0xffffffff)
  351. return false;
  352. WIN32_FIND_DATA FileData;
  353. BOOL fFinished = FALSE;
  354. if (strPath[strPath.size() - 1] != '\')
  355. strPath += '\';
  356. string strFind = strPath + "*.*";
  357. // TRACE("%srn", strPath.data());
  358. HANDLE hSearch = FindFirstFile(strFind.data(), &FileData); 
  359. if (hSearch == INVALID_HANDLE_VALUE) 
  360. return false;
  361. while (!fFinished) 
  362. {
  363. if (string(FileData.cFileName) != "." &&
  364. string(FileData.cFileName) != ".." )
  365. {
  366. if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  367. {
  368. vector<string> vChildPaths = vSubPaths;
  369. vChildPaths.push_back(FileData.cFileName);
  370. if (!SubFiles(strPath + FileData.cFileName, vChildPaths, SubFilesList, hevDone))
  371. {
  372. FindClose(hSearch);
  373. return false;
  374. }
  375. }
  376. else
  377. {
  378. PVALLIST pvFileSubPath = new VALLIST();
  379. for (int i=0; i<vSubPaths.size(); i++)
  380. {
  381. (*pvFileSubPath).push_back(new CVal(vSubPaths[i]));
  382. }
  383. (*pvFileSubPath).push_back(new CVal(FileData.cFileName));
  384. SubFilesList.push_back(CSubFilesItem(new CVal(pvFileSubPath), strPath + FileData.cFileName));
  385. // TRACE("(%s)rn", FileData.cFileName);
  386. }
  387. }
  388. if (IsEventSet(hevDone))
  389. return false;
  390. if (!FindNextFile(hSearch, &FileData)) 
  391. {
  392. fFinished = TRUE;
  393. if (GetLastError() == ERROR_NO_MORE_FILES) { } 
  394. else { } 
  395. }
  396. FindClose(hSearch);
  397. return true;
  398. }
  399. void CMakeMetaFile::ProgressInfo(float fPercent)
  400. {
  401. if (::IsWindow(m_hWnd))
  402. ::PostMessage(m_hWnd, MAKE_METAFILE_PROGRESS, fPercent*100, 0);
  403. }
  404. bool CMakeMetaFile::FormatSaveAS(string strFilePath, string& strToSavePath)
  405. {
  406. assert(!strToSavePath.empty() && !strFilePath.empty());
  407. string strName;
  408. if (!GetName(strFilePath, strName))
  409. return false;
  410. strToSavePath = formatDir(strToSavePath);
  411. strToSavePath += strName + ".torrent";
  412. return true;
  413. }
  414. bool CMakeMetaFile::GetName(string strFilePath, string& strName)
  415. {
  416. // get name map.
  417. if (strFilePath[strFilePath.size() - 1] == '\')
  418. strFilePath.erase(strFilePath.size() - 1);
  419. char *pszFileName = 0;
  420. char szPathName[MAX_PATH] = {0};
  421. if (!GetFullPathName(strFilePath.data(), MAX_PATH, szPathName, &pszFileName))
  422. {
  423. assert(false);
  424. return false;
  425. }
  426. if (pszFileName == 0) // strFilePath is the root driver.
  427. {
  428. assert(false);
  429. return 0;
  430. }
  431. strName = pszFileName;
  432. return true;
  433. }