FileTorrent.cpp
资源名称:GGBT.rar [点击查看]
上传用户:lds876
上传日期:2013-05-25
资源大小:567k
文件大小:12k
源码类别:
P2P编程
开发平台:
Visual C++
- // FileTorrent.cpp: implementation of the CFileTorrent class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "testbt.h"
- #include "FileTorrent.h"
- #include <direct.h>
- #include "bdecode.h"
- #include "BTFormat.h"
- #include "sha.h"
- #include "filebase.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CFileTorrent::CFileTorrent()
- {
- m_pResponse = 0;
- m_lSize = 0;
- m_bDirectory = false;
- m_bOpened = false;
- m_bBad = false;
- m_hFileOpenDone = CreateEvent(0, true, true, 0);
- m_hCancel = CreateEvent(0, true, false, 0);
- m_hWnd = 0;
- m_lOpenIndex = 0;
- }
- CFileTorrent::~CFileTorrent()
- {
- Close();
- CloseHandle(m_hFileOpenDone);
- CloseHandle(m_hCancel);
- }
- memstream& CFileTorrent::GetMyId()
- {
- assert(m_memMyid.size() == 20);
- return m_memMyid;
- }
- string CFileTorrent::GetInfohashString()
- {
- assert(m_memInfohash.size() == 20);
- char infohash[20] = {0};
- memcpy(infohash, m_memInfohash, 20);
- string strRet;
- for (int i=0; i<20; i++)
- {
- char szText[20] = {0};
- if ((unsigned char) infohash[i] < 0x10)
- sprintf(szText, "0%x", (unsigned char) infohash[i]);
- else
- sprintf(szText, "%x", (unsigned char) infohash[i]);
- strRet += szText;
- }
- return strRet;
- }
- memstream& CFileTorrent::GetInfohash()
- {
- assert(m_memInfohash.size() == 20);
- return m_memInfohash;
- }
- CVal* CFileTorrent::GetInfo()
- {
- assert(m_pResponse);
- CVal* pInfo = (*m_pResponse->pmapVal)["info"];
- return pInfo;
- }
- CVal* CFileTorrent::GetResponse()
- {
- return m_pResponse;
- }
- string CFileTorrent::GetUrl()
- {
- assert(m_pResponse);
- return (*m_pResponse)[string("announce")]->pstrVal;
- }
- string CFileTorrent::GetComment()
- {
- assert(m_pResponse);
- string strComment;
- if (HasKey(m_pResponse->pmapVal, "comment"))
- strComment = (*m_pResponse)[string("comment")]->pstrVal;
- return strComment;
- }
- vector<CFileInfo>& CFileTorrent::GetFileInfo()
- {
- return m_vFiles;
- }
- vector<char*>& CFileTorrent::GetPieces()
- {
- return m_vPieces;
- }
- string CFileTorrent::GetTorrentFileName()
- {
- assert(!m_strTorrentFileName.empty());
- return m_strTorrentFileName;
- }
- string CFileTorrent::GetSaveName()
- {
- assert(!m_strSaveName.empty());
- return m_strSaveName;
- }
- BLONG CFileTorrent::GetFileLength()
- {
- return m_lSize;
- }
- void CFileTorrent::Close()
- {
- if (!IsEventSet(m_hFileOpenDone))
- {
- SetEvent(m_hCancel);
- WaitForSingleObject(m_hFileOpenDone, INFINITE);
- }
- m_bOpened = false;
- m_bBad = false;
- m_strBad = "";
- if (m_pResponse)
- delete m_pResponse;
- m_pResponse = 0;
- m_vPieces.clear();
- m_vFiles.clear();
- m_memMyid.clear();
- m_memInfohash.clear();
- m_strTorrentFileName = "";
- m_strSaveName = "";
- m_lSize = 0;
- }
- bool CFileTorrent::IsOpen()
- {
- if (!IsEventSet(m_hFileOpenDone))
- return false;
- return m_bOpened;
- }
- bool CFileTorrent::IsBad()
- {
- return m_bBad;
- }
- string CFileTorrent::GetBadMsg()
- {
- return m_strBad;
- }
- long CFileTorrent::GetOpenIndex()
- {
- return m_lOpenIndex;
- }
- bool CFileTorrent::OpenFileEx(string strFileName, string strSaveAs, HWND hWnd)
- {
- if (IsOpen() || !IsEventSet(m_hFileOpenDone))
- {
- assert(false);
- return false;
- }
- //
- // read data from *.torrent
- //
- if (strFileName.empty() || !hWnd)
- {
- assert(false);
- return false;
- }
- if (m_lOpenIndex ++ > 10000)
- m_lOpenIndex = 0;
- m_strTorrentFileName = strFileName;
- m_hWnd = hWnd;
- ResetEvent(m_hFileOpenDone);
- ResetEvent(m_hCancel);
- DWORD dwThreadId = 0;
- ::CreateThread(0, 0, OpenFileExProc, (void*)new CSize((long)this, m_lOpenIndex), 0, &dwThreadId);
- TRACE("rnopen file thread = (%x)", dwThreadId);
- return true;
- }
- DWORD WINAPI CFileTorrent::OpenFileExProc(void *pParam)
- {
- CSize* p = (CSize*) pParam;
- auto_ptr<CSize> a(p);
- CFileTorrent* pFileTorrent = (CFileTorrent*) p->cx;
- long lOpenIndex = p->cy;
- HWND hWnd = pFileTorrent->m_hWnd;
- pFileTorrent->ExtractFile(lOpenIndex);
- PostMessage(hWnd, WM_FILE_TORRENT_OPENED, lOpenIndex, 0);
- return 0;
- }
- void CFileTorrent::ExtractFile(long lOpenIndex)
- {
- ExtractFileData();
- assert(m_hWnd);
- if (m_bOpened) m_bBad = true;
- SetEvent(m_hFileOpenDone);
- }
- void CFileTorrent::ExtractFileData()
- {
- //
- // open file and read data
- //
- assert(!m_strTorrentFileName.empty());
- FILE* pfile = 0;
- pfile = fopen(m_strTorrentFileName.data(), "rb");
- if (!pfile)
- {
- m_strBad = string("file (") + m_strTorrentFileName + ") can't find";
- return;
- }
- fseek(pfile, 0, SEEK_END);
- unsigned long lsize = ftell(pfile);
- char * pBuf = new char[lsize];
- auto_ptr<char> autoBuf(pBuf);
- fseek(pfile, 0, SEEK_SET);
- int iRet = fread(pBuf, 1, lsize, pfile);
- if (iRet != lsize)
- {
- fclose(pfile);
- m_strBad = string("read file ") + m_strTorrentFileName + " fail";
- return;
- }
- fclose(pfile);
- //
- // extract info from buffer.
- //
- CBdecode dec;
- m_pResponse = dec.bdecode(pBuf, lsize);
- if (!m_pResponse)
- {
- m_strBad = string("File(" + m_strTorrentFileName + ") -- bdecode error");
- return;
- }
- //
- // check info extracted.
- //
- try
- {
- CBTFormat btformat;
- btformat.CheckMessage(m_pResponse);
- }
- catch (string& e)
- {
- delete m_pResponse;
- m_pResponse = 0;
- e.data();
- m_strBad = string("File(" + m_strTorrentFileName + ") CheckMessage error");
- return;
- }
- //
- // Format data.
- //
- MakeMyid();
- MakeInfohash();
- MakePieces();
- m_bOpened = true;
- }
- bool CFileTorrent::OpenFile(string strFileName, string strSaveAs)
- {
- assert(!m_pResponse);
- // read data from *.torrent
- if (strFileName.empty())
- {
- assert(false);
- throw string("CFileTorrent::OpenFile() file name can't be empty");
- }
- m_strTorrentFileName = strFileName;
- ExtractFileData();
- return m_bOpened;
- }
- bool CFileTorrent::QueryDir()
- {
- assert(m_pResponse);
- CVal* pInfo = (*m_pResponse->pmapVal)["info"];
- if (HasKey(pInfo->pmapVal, "length"))
- {
- CVal* pLength = (*pInfo->pmapVal)["length"];
- BLONG lfilelen = pLength->lVal;
- m_strSaveName = (*pInfo->pmapVal)["name"]->pstrVal;
- m_lSize = lfilelen;
- m_bDirectory = false;
- }
- else
- {
- CVal* pFiles = (*pInfo->pmapVal)["files"];
- BLONG lfilelen = 0;
- for (VALLIST::iterator iter = pFiles->plistVal->begin(); iter!= pFiles->plistVal->end(); iter++)
- {
- lfilelen += (*(*iter)->pmapVal)["length"]->lVal;
- }
- m_lSize = lfilelen;
- m_strSaveName = (*pInfo->pmapVal)["name"]->pstrVal;
- m_bDirectory = true;
- }
- return true;
- }
- bool CFileTorrent::QuerySubFiles(vector<CFileInfo>& vFiles, bool& bDir, BLONG & lTotalSize)
- {
- if (!m_pResponse)
- {
- assert(m_pResponse);
- return false;
- }
- // Create the dir and vector files.
- CVal* pInfo = (*m_pResponse->pmapVal)["info"];
- if (HasKey(pInfo->pmapVal, "length"))
- {
- CVal* pLength = (*pInfo->pmapVal)["length"];
- BLONG lfilelen = pLength->lVal;
- string strFile = (*pInfo->pmapVal)["name"]->pstrVal;
- vFiles.push_back(CFileInfo(strFile, lfilelen));
- lTotalSize = lfilelen;
- }
- else
- {
- string strSaveName = (*pInfo->pmapVal)["name"]->pstrVal;
- CVal* pFiles = (*pInfo->pmapVal)["files"];
- for (VALLIST::iterator iter = pFiles->plistVal->begin();
- iter!= pFiles->plistVal->end(); iter++)
- {
- CVal* pLength = (*(*iter)->pmapVal)["length"];
- CVal* pPath = (*(*iter)->pmapVal)["path"];
- string strPath = strSaveName;
- for (int j=0; j<pPath->size(); j++)
- {
- if (strPath[strPath.size() - 1] != '\')
- strPath += "\";
- strPath += (*pPath)[j]->pstrVal;
- }
- vFiles.push_back(CFileInfo(strPath, pLength->lVal));
- lTotalSize += pLength->lVal;
- }
- } // end elseif
- return true;
- }
- bool CFileTorrent::CreateDir(string strSaveAs)
- {
- assert(m_pResponse);
- // Create the dir and vector files.
- CVal* pInfo = (*m_pResponse->pmapVal)["info"];
- if (HasKey(pInfo->pmapVal, "length"))
- {
- CVal* pLength = (*pInfo->pmapVal)["length"];
- BLONG lfilelen = pLength->lVal;
- string strFile = strSaveAs;
- if (strFile.empty())
- {
- assert(false);
- return false;
- }
- m_strSaveName = strFile;
- m_lSize = lfilelen;
- MakeDir(strFile);
- m_vFiles.push_back(CFileInfo(strFile, lfilelen));
- }
- else
- {
- CVal* pFiles = (*pInfo->pmapVal)["files"];
- BLONG lfilelen = 0;
- for (VALLIST::iterator iter = pFiles->plistVal->begin(); iter!= pFiles->plistVal->end(); iter++)
- {
- lfilelen += (*(*iter)->pmapVal)["length"]->lVal;
- }
- string strFile = formatDir(strSaveAs);
- if (strFile.empty())
- {
- assert(false);
- return false;
- }
- m_lSize = lfilelen;
- m_strSaveName = strFile;
- bool bRet = MakeDir(strFile, true);
- assert(bRet);
- for (iter = pFiles->plistVal->begin(); iter!= pFiles->plistVal->end(); iter++)
- {
- CVal* pLength = (*(*iter)->pmapVal)["length"];
- CVal* pPath = (*(*iter)->pmapVal)["path"];
- string strPath = strFile;
- for (int j=0; j<pPath->size(); j++)
- {
- if (strPath[strPath.size() - 1] != '\')
- strPath += "\";
- strPath += (*pPath)[j]->pstrVal;
- bRet = MakeDir(strPath);
- assert(bRet);
- }
- m_vFiles.push_back(CFileInfo(strPath, pLength->lVal));
- }
- } // end elseif
- return true;
- }
- string CFileTorrent::ChooseFile(string strDefaultName, unsigned long lsize, string strSaveas, bool bDir)
- {
- ASSERT(FALSE);
- if (bDir)
- {
- CString strDef, strFolder;
- if (!SelectFolder(strDef, strFolder))
- return "";
- string strSelected = strFolder.GetBuffer(0);
- if (strSelected[strSelected.size() - 1] != '\')
- strSelected += '\';
- return strSelected + strDefaultName;
- }
- else
- {
- CFileDialog fileDialog(FALSE, 0, strDefaultName.data());
- int iRet = fileDialog.DoModal();
- if (iRet != IDOK)
- return "";
- return fileDialog.GetPathName(); // + fileDialog.GetFileName();
- // return string("d:\") + strDefaultName;
- }
- }
- bool CFileTorrent::MakeDir(string strFileName, bool bForceDir)
- {
- if (!bForceDir)
- {
- char path_buffer[_MAX_PATH];
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
- char fname[_MAX_FNAME];
- char ext[_MAX_EXT];
- _splitpath(strFileName.data(), drive, dir, fname, ext );
- _makepath( path_buffer, drive, dir, 0, 0);
- strFileName = path_buffer;
- }
- if (!_access(strFileName.data(), 0))
- return true;
- if (strFileName.empty())
- return false;
- // if (_mkdir(strFileName.data()))
- if (!MakeDirecotry(strFileName.data()))
- {
- long l= errno;
- throw string("makedir error : directory (") + strFileName + ")";
- }
- return true;
- }
- void CFileTorrent::MakeMyid()
- {
- string szMyId;
- char strBuf[100] = {0};
- long ltime;
- time(<ime);
- sprintf(strBuf, "%d", ltime);
- szMyId = strBuf; // szMyId = "1064570069.875";
- szMyId += " ";
- sprintf(strBuf, "%d", getpid());
- szMyId += strBuf; // szMyId += "1848";
- unsigned char sha1sum[20] = {0};
- CSHA sha;
- sha.start();
- sha.update((unsigned char*)szMyId.data(), szMyId.size());
- sha.finish(sha1sum);
- char myId[20] = {0};
- memset(myId, 0, 20);
- memcpy(myId+12, (char*)sha1sum + 12, 8);
- m_memMyid.clear();
- m_memMyid.write(myId, 20);
- // 'D(wxadx18xd1Omxccx07xa0xd7xfaxa6xcbpxfbtOr'
- // 'xfaxa6xcbpxfbtOr'
- // for (int z =0; z<20; z++)
- // TRACE("%x,", (unsigned char)pMyId[z]);
- }
- void CFileTorrent::MakeInfohash()
- {
- assert(m_pResponse);
- CVal* pInfo = (*m_pResponse->pmapVal)["info"];
- memstream strInfohash;
- CBdecode::bencode(pInfo, strInfohash);
- unsigned char sha1sum[20] = {0};
- CSHA sha;
- sha.start();
- sha.update((unsigned char*)(char*)strInfohash, strInfohash.size());
- sha.finish(sha1sum);
- // memcpy(pInfohash, (char*)sha1sum, 20);
- m_memInfohash.clear();
- m_memInfohash.write((char*)sha1sum, 20);
- }
- long CFileTorrent::getpid()
- {
- return GetCurrentProcessId();
- }
- void CFileTorrent::MakePieces()
- {
- assert(m_pResponse);
- CVal* pInfo = (*m_pResponse->pmapVal)["info"];
- char* pPieces = (*pInfo)[string("pieces")]->pstrVal;
- long lPiecesSize = (*pInfo)[string("pieces")]->lstrLen;
- long lNumPieces = lPiecesSize/20;
- for (int i=0; i<lPiecesSize/20; i++)
- {
- m_vPieces.push_back(pPieces + i*20);
- }
- }