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

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. #include "stdafx.h"
  20. #include "Communicator.h"
  21. #include "ConfigFile.h"
  22. namespace NPLayer1 {
  23. Communicator::Communicator() : currRes(NULL), //logFile("#Layer1"), 
  24. csClient(this), tryClient(this), p2pMgr(this), localPeerFinder(this)
  25. {
  26. cfgData.COMMUNICATOR_VERSION = 0.152f;
  27. cfgData.ADD_PROGNAME_VERSION = 0.150f;
  28. cfgData.ADD_PROGTIME_VERSION = 0.152f;
  29. cfgData.ACCEPT_VERSION = 0.135f;
  30. cfgData.OUTGOING_NUM = 30;
  31. cfgData.INCOMING_NUM = 30;
  32. cfgData.OUT_4FREE_NUM = 5;
  33. cfgData.IN_4FREE_NUM = 5;
  34. cfgData.allow_post = 0;
  35. noitfyWindow = NULL;
  36. notifyCode = 0;
  37. userID = 0;
  38. userPass[MD5_LEN] = 0;
  39. // 初始化随机数生成器
  40. ctx.randa=ctx.randb=ctx.randc=(ub4)0;
  41. // 设置随机种子
  42. for (int i = 0; i < RANDSIZ; ++i) 
  43. ctx.randrsl[i] = (ub4)i;
  44. ctx.randrsl[0] = GetTickCount();
  45. ctx.randrsl[1] = time(NULL);
  46. std::random_shuffle(ctx.randrsl, ctx.randrsl+RANDSIZ);
  47. randinit(&ctx, TRUE);
  48. }
  49. Communicator::~Communicator() {
  50. logFile.StatusOut("P2PMgr Uninit()...");
  51. p2pMgr.Uninit();
  52. logFile.StatusOut("CSClient SendLogout()...");
  53. csClient.SendLogout();
  54. StopCurrentRes();
  55. TE_CleanupLibrary();
  56. //MessageBox(NULL, logFile.file_name().c_str(), allow_post==1? "1": "0", MB_OK);
  57. if(cfgData.allow_post) {
  58. STARTUPINFO si;
  59. PROCESS_INFORMATION pi;
  60. ZeroMemory( &si, sizeof(si) );
  61. si.cb = sizeof(si);
  62. ZeroMemory( &pi, sizeof(pi) );
  63. //发送log文件
  64. TCHAR exename[MAX_PATH_EX] = _T("");
  65. if(cfgData.module_base.size() + 20 <= MAX_PATH_EX)
  66. _stprintf(exename, "%sPostLog.exe", cfgData.module_base.data());
  67. TCHAR cmdarg[MAX_PATH_EX] = _T("");
  68. if(cfgData.post_log_url.size() + logFile.file_name().size() + 20 <= MAX_PATH_EX)
  69. _stprintf(cmdarg, _T(" %s %s "), cfgData.post_log_url.data(), logFile.file_name().data());
  70. if( CreateProcess(  // No module name (use command line). 
  71. exename, 
  72. cmdarg,
  73. NULL,             // Process handle not inheritable. 
  74. NULL,             // Thread handle not inheritable. 
  75. FALSE,            // Set handle inheritance to FALSE. 
  76. 0,                // No creation flags. 
  77. NULL,             // Use parent's environment block. 
  78. NULL,             // Use parent's starting directory. 
  79. &si,              // Pointer to STARTUPINFO structure.
  80. &pi )             // Pointer to PROCESS_INFORMATION structure.
  81. {
  82. // Close process and thread handles. 
  83. CloseHandle( pi.hProcess );
  84. CloseHandle( pi.hThread );
  85. }
  86. }
  87. // delete log file
  88. logFile.Uninit();
  89. }
  90. P2P_RETURN_TYPE Communicator::Init(string trackerURL) {
  91. if(trackerIP.sin_addr.s_addr != 0)
  92. return PRT_DUP_INIT;
  93. TCHAR buf[MAX_PATH_EX] = _T("");
  94. if(!BufferMgr::GetSelfModulePath(buf, MAX_PATH_EX)) {
  95. assert(0);
  96. return PRT_SYS;
  97. }
  98. cfgData.module_base = buf;
  99. // 读取配置文件
  100. ConfigFile config(cfgData.module_base+"config.ini");
  101. cfgData.allow_post = atoi(config.Value("postlog", "allowpost").c_str());
  102. cfgData.post_log_url = config.Value("postlog", "posturl");
  103. // 初始化日志文件
  104. P2P_RETURN_TYPE ret = logFile.Init(cfgData.module_base);
  105. //MessageBox(NULL, module_base.c_str(), "Communicator::Init", MB_OK);
  106. if(ret < PRT_OK)
  107. return ret;
  108. // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
  109. // If that fails, try using the OSVERSIONINFO structure.
  110. ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
  111. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  112. if(!GetVersionEx ((OSVERSIONINFO *) &osvi)) {
  113. osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  114. if(!GetVersionEx ((OSVERSIONINFO*) &osvi)) {
  115. logFile.StatusErr("无法检测Windows版本,程序必须结束.", GetLastError());
  116. return PRT_SYS;
  117. }
  118. }
  119. // 初始化Windows Socket
  120. logFile.StatusOut("Initializing Windows Socket...");
  121. if(TE_InitLibrary() != SOCKET_SUCCESS)
  122. return PRT_INIT_SOCK;
  123. // 取得TrackServer的IP和Port
  124. int index = trackerURL.find(':');
  125. if(index != -1) {
  126. trackerIP.sin_addr.s_addr = TE_GetIP(trackerURL.substr(0, index).data(), TRUE);
  127. if(trackerIP.sin_addr.s_addr == INADDR_NONE)
  128. return PRT_TRACKER_IP;
  129. int port = atoi(trackerURL.substr(index+1, trackerURL.length()-index-1).data());
  130. if(port == 0)
  131. return PRT_TRACKER_IP;
  132. trackerIP.sin_port = htons(port);
  133. }
  134. else {
  135. return PRT_TRACKER_IP;
  136. }
  137. logFile.StatusOut("TrackServer %s", trackerURL.data());
  138. // 删除原来的缓冲文件和日志文件
  139. LogMgr::RemoveOldTmpFile("GB", cfgData.module_base.data());
  140. LogMgr::RemoveOldTmpFile("2006", cfgData.module_base.data());
  141. // 建立新的缓冲文件
  142. logFile.StatusOut("Initialize Default BufferMgr...");
  143. bool bFileModified = false;
  144. ret = g_bufferMgr.Init("", bFileModified, rand(&ctx));
  145. if(ret < PRT_OK)
  146. return ret;
  147. logFile.StatusOut("CSClient Init & SendLogin...");
  148. ret = csClient.Init();
  149. if(ret < PRT_OK)
  150. return ret;
  151. // 初始化P2P连接,同时也启动了主线程
  152. logFile.StatusOut("P2PMgr Init...");
  153. ret = p2pMgr.Init();
  154. if(ret < PRT_OK)
  155. return ret;
  156. // 登陆TrackerServer
  157. csClient.SendLogin();
  158. // 初始化Peer发现模块
  159. localPeerFinder.Init();
  160. return PRT_OK;
  161. }
  162. P2P_RETURN_TYPE Communicator::Request(
  163.    const char* resname, // 资源名
  164.    const char* hashcode, // 资源的Hash码
  165.    const char* strSPList, // SuperPeer列表的IP地址
  166.    float bitRate // 频道的码率
  167.    )
  168. {
  169. if(!resname || !hashcode)
  170. return PRT_WRONG_ARG;
  171. CriticalSection::Owner lock(mainThreadLock);
  172. logFile.StatusOut("Request Resource %s, name %s, bitrate %.2f, SP List %s", hashcode, resname, bitRate, strSPList);
  173. // 停止当前下载的资源
  174. StopCurrentRes();
  175. LiveResource* res = new LiveResource(this);
  176. if(!res)
  177. return PRT_ALLOC;
  178. // 使用参数初始化资源
  179. P2P_RETURN_TYPE ret = res->Init(resname, hashcode, strSPList?strSPList:"", bitRate);
  180. if(ret < PRT_OK) {
  181. // 初始化失败
  182. logFile.StatusErr("Init exist Res", GetLastError());
  183. assert(0);
  184. // 删除未使用的资源
  185. delete res;
  186. return ret;
  187. }
  188. // 初始化成功, 设置当前资源
  189. currRes = res;
  190. // 向TS请求资源
  191. csClient.SendReqRes();
  192. return PRT_OK;
  193. }
  194. void Communicator::StopCurrentRes() {
  195. CriticalSection::Owner lock(mainThreadLock);
  196. // 如果存在当前下载文件, 停止当前文件的下载
  197. if(currRes) {
  198. logFile.StatusOut("Stopping connections on current resource...");
  199. p2pMgr.StopAll();
  200. /// 在这里停止主线程的话,会需要几秒钟时间,不想让stop太慢,所以不在这里执行
  201. //p2pMgr.Uninit();
  202. localPeerFinder.Uninit();
  203. logFile.StatusOut("CSClient SendDelRes()...");
  204. csClient.SendDelRes(currRes);
  205. delete currRes;
  206. // Log out
  207. csClient.SendLogout();
  208. currRes = NULL;
  209. }
  210. }
  211. // 发送错误消息给外部程序
  212. void Communicator::PostErrMessage(P2P_NOTIFY_TYPE type, LPARAM lParam, bool shouldStop) {
  213. if(noitfyWindow) {
  214. WPARAM wparam = MAKEWPARAM((UINT16) type, channelID);
  215. PostMessage(noitfyWindow, notifyCode, wparam, lParam);
  216. }
  217. if(shouldStop) {
  218. logFile.StatusOut("Post Err Message with code %d.", type);
  219. StopCurrentRes();
  220. }
  221. }
  222. }