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

P2P编程

开发平台:

Visual C++

  1. // Rerequester.cpp: implementation of the CRerequester class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "testBT.h"
  6. #include "Rerequester.h"
  7. #include "bdecode.h"
  8. #include "BTFormat.h"
  9. #include "Download.h"
  10. #include "Connector.h"
  11. #include "Measure.h"
  12. #include "StorageWrapper.h"
  13. #ifdef _DEBUG
  14. #undef THIS_FILE
  15. static char THIS_FILE[]=__FILE__;
  16. #define new DEBUG_NEW
  17. #endif
  18. string quote(const char* pBuf, long length);
  19. // void OpenUrl(string strUrl, memstream& buf);
  20. //////////////////////////////////////////////////////////////////////
  21. // Construction/Destruction
  22. //////////////////////////////////////////////////////////////////////
  23. CRerequester::CRerequester(long lConnectErrorMax, long lConnectIntval, long minpeers, long maxpeers)
  24. {
  25. m_lConnectErrorMax = lConnectErrorMax;
  26. m_lConnectIntval = lConnectIntval;
  27. m_minpeers = minpeers;
  28. m_maxpeers = maxpeers;
  29. }
  30. void CRerequester::SetConnectErrorMax(long lConnectErrorMax, long lConnectIntval, long minpeers, long maxpeers)
  31. {
  32. m_lConnectErrorMax = lConnectErrorMax;
  33. m_lConnectIntval = lConnectIntval;
  34. m_minpeers = minpeers;
  35. m_maxpeers = maxpeers;
  36. }
  37. void CRerequester::Create(CDownloaderFeedback* pMain, CStorageWrapper* pStorageWrapper, CMeasure* pupmeasure,  
  38.   CMeasure* pdownmeasure, CConnector* pConnector,CEncrypter* pEncrypter, 
  39.   string strUrl, long port, string strIP, char* pMyId, char* pInfoHash,
  40.   long lInterval, 
  41.    long lTimeOut, HANDLE hevDone)
  42. {
  43. m_pMain = pMain;
  44. m_pConnector = pConnector;
  45. m_pEncrypter = pEncrypter;
  46. m_pStorageWrapper = pStorageWrapper;
  47. m_pupmeasure = pupmeasure;
  48. m_pdownmeasure = pdownmeasure;
  49. m_hevDone = hevDone;
  50. m_lTimeOut = lTimeOut;
  51. m_lInterval = lInterval;
  52. m_lAannounce_interval = lInterval; //60*30;
  53. m_strTrackerid = "";
  54. m_lLast = 0;
  55. m_lFileCount = 0;
  56. m_hHttpDone = CreateEvent(0, false, false, 0);
  57. m_tLast = 0;
  58. m_bCommand = false;
  59. m_bStarted = false;
  60. m_never_succeeded = true;
  61. m_pSingle = 0;
  62. // check to see if this is a reasonable URL
  63. CString strServerName;
  64. CString strObject;
  65. INTERNET_PORT nPort;
  66. DWORD dwServiceType;
  67. if (!AfxParseURL(strUrl.data(), dwServiceType, strServerName, strObject, nPort) ||
  68. dwServiceType != INTERNET_SERVICE_HTTP)
  69. {
  70. throw string("url is not correct");
  71. }
  72. char szport[100] = {0};
  73. sprintf(szport, "%d", port);
  74. m_strUrl = strUrl + "?info_hash=" + 
  75. quote(pInfoHash, 20) + "&peer_id=" + quote(pMyId, 20) + "&port=" + szport;
  76. if (!strIP.empty())
  77. m_strUrl += "&ip=" + quote(strIP.data(), strIP.size());
  78. // auto announce start.
  79. announce(REQ_STARTED);
  80. m_pMain->ShowSystemMessage("获取种子信息", CSystemMsg::eCmd);
  81. string strMsg = "开始连接服务器... : ";
  82. strMsg += m_strUrl;
  83. m_pMain->ShowSystemMessage(strMsg, CSystemMsg::eMsgOut);
  84. time(&m_tLast);
  85. time(&m_tStartLast);
  86. }
  87. CRerequester::~CRerequester()
  88. {
  89. assert(!m_pSingle);
  90. CloseHandle(m_hHttpDone);
  91. }
  92. void CRerequester::Close()
  93. {
  94. if (m_pSingle)
  95. {
  96. delete m_pSingle;
  97. m_pSingle = 0;
  98. }
  99. if (!m_never_succeeded)
  100. {
  101. bool bRet = false;
  102. int iCount = 20;
  103. HANDLE hSleep = CreateEvent(0, true, false, 0);
  104. while (iCount-- > 0)
  105. {
  106. announce(REQ_STOPPED);
  107. if (!m_pSingle)
  108. {
  109. CloseHandle(hSleep);
  110. assert(false);
  111. return;
  112. }
  113. string strErr;
  114. m_pSingle->WaitTerminate();
  115. bRet = m_pSingle->GetResult(strErr) != 0;
  116. delete m_pSingle;
  117. m_pSingle = 0;
  118. if (bRet) break;
  119. WaitForSingleObject(hSleep, m_lConnectIntval * CLOCKS_PER_SEC);
  120. }
  121. CloseHandle(hSleep);
  122. if (bRet)
  123. TRACE("***announce stop successedrn");
  124. else
  125. TRACE("***announce stop failedrn");
  126. }
  127. }
  128. HANDLE CRerequester::GetHttpEvent()
  129. {
  130. return m_hHttpDone;
  131. }
  132. void CRerequester::AnnounceEx(long lEvent)
  133. {
  134. assert(lEvent >= 0 && lEvent < 4);
  135. // cause memory leak.
  136. m_commands.push_back(lEvent);
  137. Excute();
  138. }
  139. void CRerequester::Excute()
  140. {
  141. if (m_pSingle) return;
  142. time_t ltime = 0;
  143. time(&ltime);
  144. if (ltime < m_tLast)
  145. {
  146. assert(false);
  147. m_tLast = ltime;
  148. }
  149. if (ltime < m_tStartLast)
  150. {
  151. m_tStartLast = ltime;
  152. m_tLast = ltime;
  153. }
  154. bool bRet = false;
  155. if (m_commands.size() > 0)
  156. {
  157. bRet = true;
  158. m_bCommand = true;
  159. announce((*m_commands.begin()));
  160. TRACE("rnrnhttp Command : %d rnrn", (*m_commands.begin()));
  161. }
  162. else
  163. {
  164. m_bCommand = false;
  165. int lAannounce_interval = m_never_succeeded ? m_lConnectIntval : m_lAannounce_interval;
  166. if ((ltime - m_tStartLast) >= lAannounce_interval)
  167. {
  168. bRet = true;
  169. m_tStartLast = ltime;
  170. announce(REQ_STARTED);
  171. TRACE("nrnhttp Command REQ_STARTEDrnrn ");
  172. }
  173. else
  174. {
  175. int interval = m_lInterval;
  176. if (!m_bStarted)
  177. {
  178. m_bStarted = true;
  179. interval /= 2;
  180. }
  181. if ((ltime - m_tLast) > interval)
  182. {
  183. if ((m_pConnector->how_many_connections() < m_minpeers))
  184. {
  185. bRet = true;
  186. announce();
  187. TRACE("nrnhttp Command REQ_QUERYrnrn ");
  188. }
  189. m_tLast = ltime;
  190. }
  191. }
  192. }
  193. if (bRet)
  194. {
  195. string strMsg = "开始连接服务器... : ";
  196. // strMsg += m_strUrl;
  197. m_pMain->ShowSystemMessage(strMsg, CSystemMsg::eMsgOut);
  198. }
  199. }
  200. void CRerequester::PostExcute()
  201. {
  202. assert(m_pSingle);
  203. string strErr;
  204. if (m_pSingle->GetResult(strErr))
  205. {
  206. if (m_bCommand)
  207. {
  208. assert(m_commands.size() > 0);
  209. m_commands.erase(m_commands.begin());
  210. }
  211. if (postrequest())
  212. m_never_succeeded = false;
  213. }
  214. else
  215. {
  216. char szText[1024] = {0};
  217. sprintf (szText, "连接服务器失败 : (%s) : (%d)秒后重试...", strErr.data(), 
  218. m_never_succeeded ? m_lConnectIntval : m_lAannounce_interval);
  219. m_pMain->ShowSystemMessage(szText, CSystemMsg::eBad);
  220. if (m_never_succeeded)
  221. {
  222. if (++m_lFileCount>= m_lConnectErrorMax)
  223. {
  224. m_pMain->SetBadMsg("超过失败次数, 下载/上传停止");
  225. }
  226. }
  227. }
  228. delete m_pSingle;
  229. m_pSingle = 0;
  230. time(&m_tLast);
  231. m_tStartLast = m_tLast;
  232. }
  233. void CRerequester::announce(long lEvent) //(HANDLE hHttpDone, long lEvent)
  234. {
  235. //
  236. // format url.
  237. //
  238. string strCurUrl = m_strUrl + "&uploaded=" + ltostring(m_pupmeasure->get_total()) + 
  239. "&downloaded=" + ltostring(m_pdownmeasure->get_total()) + 
  240. "&left=" + ltostring(m_pStorageWrapper->get_amount_left());
  241. if (m_lLast != 0)
  242. {
  243. char strLast[100] = {0};
  244. sprintf(strLast, "%d", m_lLast);
  245. strCurUrl += "&last=" + quote(strLast, strlen(strLast));
  246. }
  247. if (!m_strTrackerid.empty())
  248. strCurUrl += "&trackerid=" + quote(m_strTrackerid.data(), m_strTrackerid.size());
  249. if (m_pConnector->how_many_connections() >= m_maxpeers)
  250. strCurUrl += "&numwant=0";
  251. const string strEventArr[] = {"started", "completed", "stopped"};
  252. if (lEvent < 0 || lEvent > 3)
  253. throw string("announce() error: req event must be 0<x<3");
  254. if (lEvent != REQ_QUERY)
  255. strCurUrl += "&event=" + strEventArr[lEvent];
  256. TRACE("rnrnurl : %srnrn", strCurUrl.data());
  257. assert(!m_pSingle);
  258. m_pSingle = new CRerequesterSingle();
  259. m_pSingle->OpenUrlEx(strCurUrl, m_hHttpDone, lEvent);
  260. }
  261. bool CRerequester::postrequest()
  262. {
  263. assert(m_pSingle);
  264. assert(m_pSingle->m_RetStream.size() > 0);
  265. try
  266. {
  267. CVal* pResponse = 0;
  268. CBdecode dec;
  269. pResponse = dec.bdecode((char*)m_pSingle->m_RetStream, m_pSingle->m_RetStream.size());
  270. if (!pResponse)
  271. throw string("postrequest() error : decode resonse from http fail");
  272. auto_ptr<CVal> aResponse(pResponse);
  273. CBTFormat::check_peers(pResponse);
  274. if (HasKey(pResponse->pmapVal, "failure reason"))
  275. {
  276. // m_pMain->errorFunc(string("rejected by tracker - ") + (*pResponse)["failure reason"]->pstrVal);
  277. m_pMain->ShowSystemMessage(string("被服务器拒绝 - ") + (*pResponse)["failure reason"]->pstrVal, CSystemMsg::eBad);
  278. }
  279. else
  280. {
  281. if (HasKey(pResponse->pmapVal, "interval"))
  282. m_lAannounce_interval = (*pResponse)["interval"]->lVal;
  283. if (HasKey(pResponse->pmapVal, "min interval"))
  284. m_lInterval = (*pResponse)["min interval"]->lVal;
  285. if (HasKey(pResponse->pmapVal, "tracker id"))
  286. m_strTrackerid = (*pResponse)["tracker id"]->pstrVal;
  287. if (HasKey(pResponse->pmapVal, "last"))
  288. m_lLast = (*pResponse)["last"]->lVal;
  289. //*********************************
  290. // meaning of last unknown.wait ...
  291. //*********************************
  292. CVal* pPeers = (*pResponse)["peers"];
  293. long lps = pPeers->size() + m_pConnector->how_many_connections();
  294. if (lps < m_maxpeers)
  295. {
  296. long lNumPeers = 1000;
  297. if (HasKey(pResponse->pmapVal, "num peers"))
  298. lNumPeers = (*pResponse)["num peers"]->lVal;
  299. long lDonePeers = 0;
  300. if (HasKey(pResponse->pmapVal, "done peers"))
  301. lDonePeers = (*pResponse)["done peers"]->lVal;
  302. bool bDownloadDone = ( WaitForSingleObject(m_hevDone, 0) == WAIT_OBJECT_0);
  303. if (bDownloadDone)
  304. {
  305. if ((lNumPeers - lDonePeers) > (lps * 1.2))
  306. m_lLast = 0;
  307. }
  308. else
  309. {
  310. if (lNumPeers > (lps * 1.2) )
  311. m_lLast = 0;
  312. }
  313. }
  314. //
  315. // connect to peers.
  316. //
  317. TRACE("rnrnbegin...rn");
  318. for (int i=0; i<pPeers->size(); i++)
  319. {
  320. CVal* pPeer = (*pPeers)[i];
  321. string strIP = (*pPeer)["ip"]->pstrVal;
  322. long lPort = (*pPeer)["port"]->lVal;
  323. string strPeerId = (*pPeer)["peer id"]->pstrVal;
  324. // sprintf(strAll + strlen(strAll), "%s, %d, %srn", strIP.data(), lPort, quote(strPeerId.data(), (*pPeer)["peer id"]->lstrLen).data());
  325. char strAll[4096] = {0};
  326. // sprintf(strAll, "%s, %d, %srn", strIP.data(), lPort, quote(strPeerId.data(), (*pPeer)["peer id"]->lstrLen).data());
  327. sprintf(strAll, "%s, %d, %srn", strIP.data(), lPort, quote((*pPeer)["peer id"]->pstrVal, (*pPeer)["peer id"]->lstrLen).data());
  328. TRACE("%s", strAll);
  329. memstream memPeerID;
  330. memPeerID.write((*pPeer)["peer id"]->pstrVal, (*pPeer)["peer id"]->lstrLen);
  331. m_pEncrypter->start_connection(strIP, lPort, memPeerID);
  332. }
  333. TRACE("}rn");
  334. m_pMain->TrackerConnected();
  335. char strText[1024] = {0};
  336. sprintf(strText, "连接服务器成功, 返回(%d)条记录", pPeers->size());
  337. m_pMain->ShowSystemMessage(strText, CSystemMsg::eMsgIn);
  338. m_pMain->ShowSystemMessage("开始接收数据...", CSystemMsg::eCmd);
  339. }
  340. }
  341. catch (string& e)
  342. {
  343. e.data();
  344. m_pMain->ShowSystemMessage("连接服务器失败, 返回错误信息!等待重试...", CSystemMsg::eBad);
  345. return false;
  346. }
  347. return true;
  348. }
  349. /*
  350. Replace special characters in string using the "%xx" escape. Letters, digits, 
  351. and the characters "_,.-" are never quoted. The optional safe parameter 
  352. specifies additional characters that should not be quoted -- its default value is '/'. 
  353. Example: quote('/~connolly/') yields '/%7econnolly/'. 
  354. */
  355. string quote(const char* pBuf, long length)
  356. {
  357. string strRet;
  358. for (int i=0; i<length; i++)
  359. {
  360. unsigned char c = *(pBuf+i);
  361. if ((c > 64 && c<91) || (c > 96 && c < 123) || (c>47 && c<58) ||
  362. c== '_' || c == ',' || c=='.' || c=='-')
  363. {
  364. strRet += c;
  365. }
  366. else 
  367. {
  368. char temp[100] = {0};
  369. memset(temp, 0, sizeof(temp)/sizeof(char));
  370. if (c > 0xf)
  371. sprintf(temp, "%x", c);
  372. else
  373. sprintf(temp, "0%x", c);
  374. strRet += string("%") + temp;
  375. }
  376. }
  377. // Make the string upper case.
  378. // strRet = _strupr(_strdup(strRet.data()));
  379. return strRet;
  380. }
  381. /////////////////////////////////////////////////////////////////////////////////////////////
  382. // CRerequesterSingle.
  383. CRerequesterSingle::CRerequesterSingle()
  384. {
  385. m_hDone = CreateEvent(0, true, true, 0);
  386. m_hHttpDone = 0;
  387. m_iResult = false;
  388. }
  389. CRerequesterSingle::~CRerequesterSingle()
  390. {
  391. if (!IsEventSet(m_hDone))
  392. {
  393. // m_session.Close();
  394. WaitForSingleObject(m_hDone, INFINITE);
  395. }
  396. CloseHandle(m_hDone);
  397. }
  398. void CRerequesterSingle::WaitTerminate()
  399. {
  400. WaitForSingleObject(m_hDone, INFINITE);
  401. }
  402. bool CRerequesterSingle::OpenUrlEx(string strUrl, HANDLE hHttpDone, long lEvent)
  403. {
  404. m_lEvent = lEvent;
  405. m_hHttpDone = hHttpDone;
  406. ResetEvent(m_hHttpDone);
  407. ResetEvent(m_hDone);
  408. // check to see if this is a reasonable URL
  409. CString strServerName;
  410. CString strObject;
  411. INTERNET_PORT nPort;
  412. DWORD dwServiceType;
  413. if (!AfxParseURL(strUrl.data(), dwServiceType, strServerName, strObject, nPort) ||
  414. dwServiceType != INTERNET_SERVICE_HTTP)
  415. {
  416. return false;
  417. }
  418. m_strUrl = strUrl;
  419. DWORD dwThreadId = 0;
  420. ::CreateThread(0, 0, SendRequestProc, this, 0, &dwThreadId);
  421. TRACE("rnSendRequestProc thread = (%x)", dwThreadId);
  422. return true;
  423. }
  424. DWORD WINAPI CRerequesterSingle::SendRequestProc(void *pParam)
  425. {
  426. CRerequesterSingle* pRerequesterSingle = (CRerequesterSingle*) pParam;
  427. HANDLE m_hDone = pRerequesterSingle->m_hDone;
  428. HANDLE hHttpDone = pRerequesterSingle->m_hHttpDone;
  429. pRerequesterSingle->SendRequest();
  430. SetEvent(m_hDone);
  431. assert(hHttpDone);
  432. SetEvent(hHttpDone);
  433. return 0;
  434. }
  435. void CRerequesterSingle::SendRequest()
  436. {
  437. m_iResult = true;
  438. try
  439. {
  440. m_RetStream.clear();
  441. OpenUrl(m_strUrl, m_RetStream);
  442. }
  443. catch (string& e)
  444. {
  445. e;
  446. m_iResult = false;
  447. }
  448. /*
  449. assert(m_hHttpDone);
  450. SetEvent(m_hHttpDone);
  451. //*/
  452. }
  453. void CRerequesterSingle::OpenUrl(string strUrl, memstream& buf)
  454. {
  455. CStdioFile* pfile = 0;
  456. try
  457. {
  458. pfile = m_session.OpenURL(strUrl.data());
  459. if (!pfile)
  460. throw string("OpenURL() fail");
  461. auto_ptr<CStdioFile> af(pfile);
  462. char* pBuf = new char[1024];
  463. auto_ptr<char> ab(pBuf);
  464. DWORD dwRead = 0;
  465. do
  466. {
  467. dwRead = pfile->Read(pBuf, 1024);
  468. buf.write(pBuf, dwRead);
  469. }
  470. while (dwRead > 0);
  471. pfile->Close();
  472. }
  473. catch (CInternetException* pEx)
  474. {
  475. TCHAR szErr[1024];
  476. pEx->GetErrorMessage(szErr, 1024);
  477. pEx->Delete();
  478. m_strErr = szErr;
  479. if (pfile) 
  480. pfile->Close();
  481. throw string(szErr);
  482. }
  483. catch (string e)
  484. {
  485. throw e;
  486. }
  487. catch (...)
  488. {
  489. assert(false);
  490. }
  491. }
  492. int CRerequesterSingle::GetResult(string& strErr)
  493. {
  494. strErr = m_strErr;
  495. return m_iResult;
  496. }