1
0

MainThread.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. //---------------------------------------------------------------------------
  2. #include "stdafx.h"
  3. #include "MainThread.h"
  4. #define ECS m_CriticalSection.Lock()
  5. #define LCS m_CriticalSection.Unlock()
  6. /////////////////////////////////////////////////////////////////////////////
  7. // CMainThread
  8. CMainThread::CMainThread()
  9. {
  10. m_pTools = NULL;
  11. m_nInternalMessageID = 0;
  12. m_pPostKeepAliveCommand = 0;
  13. m_nTimerID = 0;
  14. m_pControlSocket = NULL;
  15. m_bBusy = FALSE;
  16. m_bConnected = FALSE;
  17. m_pWorkingDir = 0;
  18. m_nAsyncRequestID = 0;
  19. m_bQuit = FALSE;
  20. m_hThread = 0;
  21. m_dwThreadId = 0;
  22. }
  23. CMainThread::~CMainThread()
  24. {
  25. delete m_pWorkingDir;
  26. CloseHandle(m_hThread);
  27. }
  28. BOOL CMainThread::InitInstance()
  29. {
  30. m_nTimerID=SetTimer(0,1,1000,0);
  31. m_pPostKeepAliveCommand=0;
  32. // initialize Winsock library
  33. BOOL res=TRUE;
  34. WSADATA wsaData;
  35. WORD wVersionRequested = MAKEWORD(1, 1);
  36. int nResult = WSAStartup(wVersionRequested, &wsaData);
  37. if (nResult != 0)
  38. res=FALSE;
  39. else if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
  40. {
  41. WSACleanup();
  42. res=FALSE;
  43. }
  44. m_pControlSocket=new CFtpControlSocket(this, m_pTools);
  45. m_pControlSocket->InitIntern(GetIntern());
  46. return TRUE;
  47. }
  48. DWORD CMainThread::ExitInstance()
  49. {
  50. KillTimer(0,m_nTimerID);
  51. if (m_pControlSocket)
  52. delete m_pControlSocket;
  53. return 1;
  54. }
  55. BOOL CMainThread::IsConnected()
  56. {
  57. BOOL bConnected;
  58. ECS;
  59. bConnected=m_bConnected;
  60. LCS;
  61. return bConnected;
  62. }
  63. void CMainThread::OnTimer(WPARAM wParam, LPARAM lParam)
  64. {
  65. if (!m_pControlSocket)
  66. return;
  67. if (wParam==m_nTimerID)
  68. m_pControlSocket->OnTimer();
  69. return;
  70. }
  71. BOOL CMainThread::OnThreadMessage(UINT Msg, WPARAM wParam, LPARAM lParam)
  72. {
  73. if (Msg==m_nInternalMessageID)
  74. {
  75. if (wParam==FZAPI_THREADMSG_COMMAND)
  76. {
  77. if (m_pControlSocket && !m_pControlSocket->IsReady())
  78. m_pPostKeepAliveCommand=(t_command *)lParam;
  79. else
  80. {
  81. t_command *pCommand=(t_command *)lParam;
  82. switch(pCommand->id)
  83. {
  84. case FZ_COMMAND_CONNECT:
  85. DebugAssert(!IsConnected());
  86. SetCurrentPath(CServerPath());
  87. m_pControlSocket->Connect(pCommand->server);
  88. break;
  89. case FZ_COMMAND_LIST:
  90. DebugAssert(m_pControlSocket);
  91. m_pControlSocket->List(FALSE, 0, pCommand->path, pCommand->param1);
  92. break;
  93. case FZ_COMMAND_LISTFILE:
  94. DebugAssert(m_pControlSocket);
  95. m_pControlSocket->ListFile(pCommand->param1, pCommand->path);
  96. break;
  97. case FZ_COMMAND_FILETRANSFER:
  98. DebugAssert(m_pControlSocket);
  99. m_pControlSocket->FileTransfer(&pCommand->transferfile);
  100. break;
  101. case FZ_COMMAND_CUSTOMCOMMAND:
  102. DebugAssert(m_pControlSocket);
  103. m_pControlSocket->FtpCommand(pCommand->param1);
  104. break;
  105. case FZ_COMMAND_DELETE:
  106. DebugAssert(m_pControlSocket);
  107. m_pControlSocket->Delete(pCommand->param1, pCommand->path);
  108. break;
  109. case FZ_COMMAND_REMOVEDIR:
  110. DebugAssert(m_pControlSocket);
  111. m_pControlSocket->RemoveDir(pCommand->param1, pCommand->path);
  112. break;
  113. case FZ_COMMAND_MAKEDIR:
  114. DebugAssert(m_pControlSocket);
  115. m_pControlSocket->MakeDir(pCommand->path);
  116. break;
  117. case FZ_COMMAND_RENAME:
  118. DebugAssert(m_pControlSocket);
  119. m_pControlSocket->Rename(pCommand->param1, pCommand->param2, pCommand->path, pCommand->newPath);
  120. break;
  121. case FZ_COMMAND_CHMOD:
  122. DebugAssert(m_pControlSocket);
  123. m_pControlSocket->Chmod(pCommand->param1, pCommand->path, pCommand->param4);
  124. break;
  125. }
  126. delete pCommand;
  127. }
  128. }
  129. else if (wParam==FZAPI_THREADMSG_PROCESSREPLY)
  130. m_pControlSocket->ProcessReply();
  131. else if (wParam==FZAPI_THREADMSG_TRANSFEREND)
  132. m_pControlSocket->TransferEnd(lParam);
  133. else if (wParam==FZAPI_THREADMSG_CANCEL)
  134. m_pControlSocket->Cancel(lParam);
  135. else if (wParam==FZAPI_THREADMSG_DISCONNECT)
  136. m_pControlSocket->Disconnect();
  137. else if (wParam==FZAPI_THREADMSG_POSTKEEPALIVE)
  138. {
  139. if (m_pPostKeepAliveCommand)
  140. {
  141. PostThreadMessage(m_nInternalMessageID,FZAPI_THREADMSG_COMMAND,(LPARAM)m_pPostKeepAliveCommand);
  142. m_pPostKeepAliveCommand=0;
  143. }
  144. }
  145. else if (wParam==FZAPI_THREADMSG_ASYNCREQUESTREPLY)
  146. {
  147. CAsyncRequestData *pData=(CAsyncRequestData *)lParam;
  148. if (pData)
  149. {
  150. if (pData->nRequestID!=GetAsyncRequestID())
  151. LogMessage(FZ_LOG_INFO, L"Ignoring old request ID");
  152. else
  153. m_pControlSocket->SetAsyncRequestResult(pData->nRequestResult, pData);
  154. delete pData;
  155. }
  156. else
  157. LogMessage(FZ_LOG_WARNING, L"Request reply without data");
  158. }
  159. return TRUE;
  160. }
  161. else if (Msg==WM_TIMER)
  162. {
  163. OnTimer(wParam, lParam);
  164. }
  165. return TRUE;
  166. }
  167. BOOL CMainThread::IsBusy()
  168. {
  169. BOOL bBusy;
  170. ECS;
  171. bBusy=m_bBusy;
  172. LCS;
  173. return bBusy;
  174. }
  175. void CMainThread::Command(const t_command &command)
  176. {
  177. DebugAssert(!IsBusy());
  178. ECS;
  179. if (m_bQuit)
  180. {
  181. LCS;
  182. return;
  183. }
  184. m_bBusy=TRUE;
  185. t_command *pCommand=new t_command;
  186. *pCommand=command;
  187. DebugCheck(PostThreadMessage(m_nInternalMessageID,FZAPI_THREADMSG_COMMAND,(LPARAM)pCommand));
  188. m_LastCommand=command;
  189. LCS;
  190. }
  191. BOOL CMainThread::LastOperationSuccessful()
  192. {
  193. return TRUE;
  194. }
  195. void CMainThread::SetBusy(BOOL bBusy)
  196. {
  197. ECS;
  198. m_bBusy=bBusy;
  199. LCS;
  200. }
  201. void CMainThread::SetConnected(BOOL bConnected /*=TRUE*/)
  202. {
  203. ECS;
  204. m_bConnected=bConnected;
  205. if (!bConnected)
  206. {
  207. // when we loose connection
  208. // reset pending commands as we cannot fulfill them anyway
  209. m_pPostKeepAliveCommand = 0;
  210. }
  211. LCS;
  212. }
  213. bool CMainThread::GetCurrentPath(CServerPath &dir)
  214. {
  215. if (!IsConnected())
  216. return false;
  217. ECS;
  218. dir=m_CurrentPath;
  219. LCS;
  220. return true;
  221. }
  222. CServerPath CMainThread::GetCurrentPath()
  223. {
  224. CServerPath path;
  225. bool res = GetCurrentPath(path);
  226. if (!res)
  227. return CServerPath();
  228. return path;
  229. }
  230. BOOL CMainThread::GetCurrentServer(t_server &server)
  231. {
  232. if (!IsConnected())
  233. return FALSE;
  234. ECS;
  235. server=m_pControlSocket->GetCurrentServer();
  236. LCS;
  237. return TRUE;
  238. }
  239. void CMainThread::Quit()
  240. {
  241. ECS;
  242. m_bQuit=TRUE;
  243. LCS;
  244. if (IsBusy())
  245. PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_CANCEL, 1);
  246. PostThreadMessage(WM_QUIT, 0, 0);
  247. }
  248. void CMainThread::SetCurrentPath(CServerPath path)
  249. {
  250. ECS;
  251. m_CurrentPath=path;
  252. LCS;
  253. return;
  254. }
  255. bool CMainThread::UsingMlsd()
  256. {
  257. if (!IsConnected())
  258. return false;
  259. return m_pControlSocket->UsingMlsd();
  260. }
  261. bool CMainThread::UsingUtf8()
  262. {
  263. if (!IsConnected())
  264. return false;
  265. return m_pControlSocket->UsingUtf8();
  266. }
  267. std::string CMainThread::GetTlsVersionStr()
  268. {
  269. if (!IsConnected())
  270. return std::string();
  271. return m_pControlSocket->GetTlsVersionStr();
  272. }
  273. std::string CMainThread::GetCipherName()
  274. {
  275. if (!IsConnected())
  276. return std::string();
  277. return m_pControlSocket->GetCipherName();
  278. }
  279. BOOL CMainThread::GetWorkingDir(t_directory *pWorkingDir)
  280. {
  281. ECS;
  282. if (m_pWorkingDir)
  283. {
  284. *pWorkingDir=*m_pWorkingDir;
  285. LCS;
  286. return TRUE;
  287. }
  288. LCS;
  289. return FALSE;
  290. }
  291. void CMainThread::SetWorkingDir(t_directory *pWorkingDir)
  292. {
  293. if (!pWorkingDir)
  294. {
  295. ECS;
  296. delete m_pWorkingDir;
  297. m_pWorkingDir=0;
  298. LCS;
  299. }
  300. else
  301. {
  302. ECS;
  303. if (!m_pWorkingDir)
  304. m_pWorkingDir=new t_directory;
  305. *m_pWorkingDir=*pWorkingDir;
  306. LCS;
  307. }
  308. if (pWorkingDir)
  309. {
  310. t_directory *pDirectoryToSend=new t_directory;
  311. *pDirectoryToSend=*pWorkingDir;
  312. SendDirectoryListing(pDirectoryToSend);
  313. }
  314. return;
  315. }
  316. void CMainThread::SendDirectoryListing(t_directory * pDirectoryToSend)
  317. {
  318. if (!GetIntern()->PostMessage(FZ_MSG_MAKEMSG(FZ_MSG_LISTDATA, 0), (LPARAM)pDirectoryToSend))
  319. {
  320. delete pDirectoryToSend;
  321. }
  322. }
  323. __int64 CMainThread::GetAsyncRequestID() const
  324. {
  325. return m_nAsyncRequestID;
  326. }
  327. __int64 CMainThread::GetNextAsyncRequestID()
  328. {
  329. return ++m_nAsyncRequestID;
  330. }
  331. CMainThread* CMainThread::Create(int nPriority /*=THREAD_PRIORITY_NORMAL*/, DWORD dwCreateFlags /*=0*/)
  332. {
  333. CMainThread *pMainThread=new CMainThread();
  334. pMainThread->m_hThread=CreateThread(0, 0, ThreadProc, pMainThread, dwCreateFlags, &pMainThread->m_dwThreadId);
  335. if (!pMainThread->m_hThread)
  336. {
  337. delete pMainThread;
  338. return NULL;
  339. }
  340. ::SetThreadPriority(pMainThread->m_hThread, nPriority);
  341. return pMainThread;
  342. }
  343. BOOL CMainThread::PostThreadMessage(UINT message, WPARAM wParam, LPARAM lParam)
  344. {
  345. return ::PostThreadMessage(m_dwThreadId, message, wParam, lParam);
  346. }
  347. DWORD CMainThread::ResumeThread()
  348. {
  349. BOOL res=::ResumeThread(m_hThread);
  350. if (res)
  351. {
  352. m_EventStarted.Lock();
  353. m_EventStarted.Unlock();
  354. }
  355. return res;
  356. }
  357. DWORD WINAPI CMainThread::ThreadProc(LPVOID lpParameter)
  358. {
  359. return ((CMainThread *)lpParameter)->Run();
  360. }
  361. DWORD CMainThread::Run()
  362. {
  363. ECS;
  364. InitInstance();
  365. m_EventStarted.SetEvent();
  366. LCS;
  367. MSG msg;
  368. while (GetMessage(&msg, 0, 0, 0))
  369. {
  370. TranslateMessage(&msg);
  371. if (!msg.hwnd)
  372. {
  373. OnThreadMessage(msg.message, msg.wParam, msg.lParam);
  374. }
  375. DispatchMessage(&msg);
  376. }
  377. DWORD res = ExitInstance();
  378. delete this;
  379. return res;
  380. }