LYFZIPReceive.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /****************************************************************/
  2. /* */
  3. /* LYFZIPReceive.cpp */
  4. /* */
  5. /* Implementation of the CLYFZIPReceive class. */
  6. /* This class is a part of the FTP Server Application */
  7. /* */
  8. /* Programmed by LYFZ van der Meer */
  9. /* Copyright LYFZ Software Solutions 2002 */
  10. /* http://www.LYFZvandermeer.nl */
  11. /* */
  12. /* Last updated: 10 july 2002 */
  13. /* */
  14. /****************************************************************/
  15. #include "stdafx.h"
  16. #include "LYFZIPReceive.h"
  17. extern int g_port;
  18. CLYFZIPReceive *g_pWndServer=NULL;
  19. CLYFZIPReceive::CLYFZIPReceive()
  20. {
  21. m_nPort = g_port;
  22. m_nMaxUsers = 500;
  23. m_strWelcomeMessage = "Welcome to LYFZ FTP Server";
  24. m_strGoodbyeMessage = "Bye";
  25. m_nTimeout = 10;
  26. m_bRunning = FALSE;
  27. m_hWnd = NULL;
  28. m_nConnectionCount = 0;
  29. // intialize statistics
  30. m_dwTotalSentBytes = 0;
  31. m_dwTotalReceivedBytes = 0;
  32. m_nTotalConnections = 0;
  33. m_nFilesDownloaded = 0;
  34. m_nFilesUploaded = 0;
  35. m_nFailedDownloads = 0;
  36. m_nFailedUploads = 0;
  37. m_nSecurityMode = 0;
  38. m_nStatisticsInterval = 0;
  39. // load users
  40. m_UserManager.Serialize(FALSE);
  41. // load security
  42. m_SecurityManager.Serialize(FALSE);
  43. }
  44. CLYFZIPReceive::~CLYFZIPReceive()
  45. {
  46. Stop();
  47. }
  48. BEGIN_MESSAGE_MAP(CLYFZIPReceive, CWnd)
  49. //{{AFX_MSG_MAP(CLYFZIPReceive)
  50. ON_WM_TIMER()
  51. //}}AFX_MSG_MAP
  52. ON_MESSAGE(WM_THREADSTART, OnThreadStart)
  53. ON_MESSAGE(WM_THREADCLOSE, OnThreadClose)
  54. ON_MESSAGE(WM_THREADMSG, OnThreadMessage)
  55. END_MESSAGE_MAP()
  56. /********************************************************************/
  57. /* */
  58. /* Function name : Start */
  59. /* Description : Start listining on port 21 and accept new */
  60. /* connections. */
  61. /* */
  62. /********************************************************************/
  63. //在21号端口启动侦听并准备接受新的连接
  64. BOOL CLYFZIPReceive::Start()
  65. {
  66. if (m_bRunning)
  67. return FALSE;
  68. // 为消息发送创建一个新的窗口
  69. if (!CWnd::CreateEx(0, AfxRegisterWndClass(0), "FTP Server Notification Sink", WS_POPUP, 0,0,0,0, NULL, 0))
  70. {
  71. AddTraceLine(0, "Failed to create notification window.");
  72. return FALSE;
  73. }
  74. // 创建一个新的套接字
  75. if (m_ListenSocket.Create(g_port))
  76. {
  77. // 启动侦听
  78. if (m_ListenSocket.Listen())
  79. {
  80. g_pWndServer=this;
  81. // m_ListenSocket.m_pWndServer = this;
  82. m_bRunning = TRUE;
  83. SetTimer(1, m_nStatisticsInterval, NULL);
  84. AddTraceLine(0, "FTP Server started on port %d.", g_port);
  85. return TRUE;
  86. }
  87. }
  88. AddTraceLine(0, "FTP Server failed to listen on port %d.", g_port);
  89. // 销毁通知窗口
  90. if (IsWindow(m_hWnd))
  91. DestroyWindow();
  92. m_hWnd = NULL;
  93. return FALSE;
  94. }
  95. /********************************************************************/
  96. /* */
  97. /* Function name : Stop */
  98. /* Description : Stop FTP server. */
  99. /* */
  100. /********************************************************************/
  101. //停止FTP服务器
  102. void CLYFZIPReceive::Stop()
  103. {
  104. if (!m_bRunning)
  105. return;
  106. // 停止统计计时器
  107. KillTimer(1);
  108. m_bRunning = FALSE;
  109. m_ListenSocket.Close();
  110. CConnectThread* pThread = NULL;
  111. //关闭所有线程
  112. do
  113. {
  114. m_CriticalSection.Lock();
  115. POSITION pos = m_ThreadList.GetHeadPosition();
  116. if (pos != NULL)
  117. {
  118. pThread = (CConnectThread *)m_ThreadList.GetAt(pos);
  119. m_CriticalSection.Unlock();
  120. // 保存线程
  121. int nThreadID = pThread->m_nThreadID;
  122. HANDLE hThread = pThread->m_hThread;
  123. AddTraceLine(0, "[%d] Shutting down thread...", nThreadID);
  124. // 通知线程停止
  125. pThread->SetThreadPriority(THREAD_PRIORITY_HIGHEST);
  126. pThread->PostThreadMessage(WM_QUIT,0,0);
  127. //等待线程终止
  128. if (WaitWithMessageLoop(hThread, 5000) == FALSE)
  129. {
  130. // 线程不能终止
  131. AddTraceLine(0, "[%d] Problem while killing thread.", nThreadID);
  132. //清除线程
  133. m_CriticalSection.Lock();
  134. POSITION rmPos = m_ThreadList.Find(pThread);
  135. if (rmPos != NULL)
  136. m_ThreadList.RemoveAt(rmPos);
  137. m_CriticalSection.Unlock();
  138. }
  139. else
  140. {
  141. AddTraceLine(0, "[%d] Thread successfully stopped.", nThreadID);
  142. }
  143. }
  144. else
  145. {
  146. m_CriticalSection.Unlock();
  147. pThread = NULL;
  148. }
  149. }
  150. while (pThread != NULL);
  151. //更新服务器状态
  152. AddTraceLine(0, "FTP Server stopped.");
  153. if (IsWindow(m_hWnd))
  154. DestroyWindow();
  155. m_hWnd = NULL;
  156. }
  157. /********************************************************************/
  158. /* */
  159. /* Function name : IsActive */
  160. /* Description : Is FTP server active? */
  161. /* */
  162. /********************************************************************/
  163. BOOL CLYFZIPReceive::IsActive()
  164. {
  165. return m_bRunning;
  166. }
  167. /********************************************************************/
  168. /* */
  169. /* Function name : SetMaxUsers */
  170. /* Description : Set maximum number of users */
  171. /* */
  172. /********************************************************************/
  173. void CLYFZIPReceive::SetMaxUsers(int nValue)
  174. {
  175. m_nMaxUsers = nValue;
  176. }
  177. /********************************************************************/
  178. /* */
  179. /* Function name : SetPort */
  180. /* Description : Set listening port for new connections */
  181. /* */
  182. /********************************************************************/
  183. void CLYFZIPReceive::SetPort(int nValue)
  184. {
  185. m_nPort = nValue;
  186. }
  187. /********************************************************************/
  188. /* */
  189. /* Function name : SetTimeout */
  190. /* Description : Set connection timeout */
  191. /* */
  192. /********************************************************************/
  193. void CLYFZIPReceive::SetTimeout(int nValue)
  194. {
  195. m_nTimeout = nValue;
  196. }
  197. /********************************************************************/
  198. /* */
  199. /* Function name : SetTimeout */
  200. /* Description : Set connection timeout */
  201. /* */
  202. /********************************************************************/
  203. void CLYFZIPReceive::SetStatisticsInterval(int nValue)
  204. {
  205. m_nStatisticsInterval = nValue;
  206. if (m_nStatisticsInterval != 0)
  207. {
  208. KillTimer(1);
  209. SetTimer(1, nValue, NULL);
  210. }
  211. else
  212. {
  213. KillTimer(1);
  214. }
  215. }
  216. /********************************************************************/
  217. /* */
  218. /* Function name : SetWelcomeMessage */
  219. /* Description : Set welcome message */
  220. /* */
  221. /********************************************************************/
  222. void CLYFZIPReceive::SetWelcomeMessage(LPCTSTR lpszText)
  223. {
  224. m_strWelcomeMessage = lpszText;
  225. }
  226. /********************************************************************/
  227. /* */
  228. /* Function name : SetGoodbyeMessage */
  229. /* Description : Set goodbye message */
  230. /* */
  231. /********************************************************************/
  232. void CLYFZIPReceive::SetGoodbyeMessage(LPCTSTR lpszText)
  233. {
  234. m_strGoodbyeMessage = lpszText;
  235. }
  236. /********************************************************************/
  237. /* */
  238. /* Function name : Initialize */
  239. /* Description : Initialize event sink. */
  240. /* */
  241. /********************************************************************/
  242. void CLYFZIPReceive::Initialize(CFTPEventSink *pEventSink)
  243. {
  244. m_pEventSink = pEventSink;
  245. }
  246. /********************************************************************/
  247. /* */
  248. /* Function name : AddTraceLine */
  249. /* Description : FTP status change. */
  250. /* */
  251. /********************************************************************/
  252. void CLYFZIPReceive::AddTraceLine(int nType, LPCTSTR pstrFormat, ...)
  253. {
  254. CString str;
  255. // format and write the data we were given
  256. va_list args;
  257. va_start(args, pstrFormat);
  258. str.FormatV(pstrFormat, args);
  259. m_pEventSink->OnFTPStatusChange(nType, str);
  260. }
  261. /********************************************************************/
  262. /* */
  263. /* Function name : OnThreadStart */
  264. /* Description : Called when a new thread has started. */
  265. /* */
  266. /********************************************************************/
  267. LRESULT CLYFZIPReceive::OnThreadStart(WPARAM wParam, LPARAM)
  268. {
  269. m_nConnectionCount++;
  270. m_nTotalConnections++;
  271. CConnectThread *pThread = (CConnectThread *)wParam;
  272. // pThread->m_ConnectSocket.GetPeerName(pThread->m_strRemoteHost, port);
  273. AddTraceLine(0, "[%d] Client connected from %s.", pThread->m_nThreadID, pThread->m_strRemoteHost);
  274. AfxGetMainWnd()->KillTimer (1);
  275. AfxGetMainWnd()->SetTimer(1, 5*60*1000, NULL);
  276. return TRUE;
  277. }
  278. /********************************************************************/
  279. /* */
  280. /* Function name : OnThreadClose */
  281. /* Description : Called when a thread is about to stop. */
  282. /* */
  283. /********************************************************************/
  284. LRESULT CLYFZIPReceive::OnThreadClose(WPARAM wParam, LPARAM lParam)
  285. {
  286. m_nConnectionCount--;
  287. CConnectThread *pThread = (CConnectThread *)wParam;
  288. AddTraceLine(0, "[%d] Client disconnected from %s.", pThread->m_nThreadID, pThread->m_strRemoteHost);
  289. m_pEventSink->OnFTPUserDisconnected(pThread->m_nThreadID, pThread->m_ConnectSocket.m_strUserName);
  290. return TRUE;
  291. }
  292. /********************************************************************/
  293. /* */
  294. /* Function name : OnThreadMessage */
  295. /* Description : Message sent from connect connection. */
  296. /* */
  297. /********************************************************************/
  298. LRESULT CLYFZIPReceive::OnThreadMessage(WPARAM wParam, LPARAM lParam)
  299. {
  300. switch(wParam)
  301. {
  302. case 0:
  303. m_dwTotalSentBytes += (int)lParam;
  304. break;
  305. case 1:
  306. m_dwTotalReceivedBytes += (int)lParam;
  307. break;
  308. case 2:
  309. switch(lParam)
  310. {
  311. case FTPSTAT_DOWNLOADSUCCEEDED:
  312. m_nFilesDownloaded++;
  313. break;
  314. case FTPSTAT_UPLOADSUCCEEDED:
  315. m_nFilesUploaded++;
  316. break;
  317. case FTPSTAT_DOWNLOADFAILED:
  318. m_nFailedDownloads++;
  319. break;
  320. case FTPSTAT_UPLOADFAILED:
  321. m_nFailedUploads++;
  322. break;
  323. }
  324. break;
  325. default:
  326. break;
  327. }
  328. return TRUE;
  329. }
  330. /********************************************************************/
  331. /* */
  332. /* Function name : CheckMaxUsers */
  333. /* Description : Reached maximum number of connections? */
  334. /* */
  335. /********************************************************************/
  336. BOOL CLYFZIPReceive::CheckMaxUsers()
  337. {
  338. if (m_nConnectionCount > 100)
  339. return TRUE;
  340. else
  341. return FALSE;
  342. }
  343. /********************************************************************/
  344. /* */
  345. /* Function name : OnTimer */
  346. /* Description : Update statictics. */
  347. /* */
  348. /********************************************************************/
  349. void CLYFZIPReceive::OnTimer(UINT nIDEvent)
  350. {
  351. // update statictics ?
  352. if (nIDEvent == 1)
  353. {
  354. m_pEventSink->OnFTPSentBytesChange(m_dwTotalSentBytes);
  355. m_pEventSink->OnFTPReceivedBytesChange(m_dwTotalReceivedBytes);
  356. m_pEventSink->OnFTPStatisticChange(0, m_nTotalConnections);
  357. m_pEventSink->OnFTPStatisticChange(1, m_nConnectionCount);
  358. m_pEventSink->OnFTPStatisticChange(2, m_nFilesDownloaded);
  359. m_pEventSink->OnFTPStatisticChange(3, m_nFilesUploaded);
  360. m_pEventSink->OnFTPStatisticChange(4, m_nFailedDownloads);
  361. m_pEventSink->OnFTPStatisticChange(5, m_nFailedUploads);
  362. }
  363. CWnd::OnTimer(nIDEvent);
  364. }
  365. /********************************************************************/
  366. /* */
  367. /* Function name : SetSecurityMode */
  368. /* Description : Set security mode. */
  369. /* */
  370. /********************************************************************/
  371. void CLYFZIPReceive::SetSecurityMode(BOOL bBlockSpecific)
  372. {
  373. m_nSecurityMode = bBlockSpecific ? 0 : 1;
  374. }
  375. /********************************************************************/
  376. /* */
  377. /* Function name : IsIPAddressAllowed */
  378. /* Description : Check (based on blockmode) if IP is allowed. */
  379. /* */
  380. /********************************************************************/
  381. BOOL CLYFZIPReceive::IsIPAddressAllowed(LPCTSTR lpszIPAddress)
  382. {
  383. if (m_nSecurityMode == 0)
  384. {
  385. return !m_SecurityManager.IsIPAddressBlocked(lpszIPAddress);
  386. }
  387. else
  388. {
  389. return m_SecurityManager.IsIPAddressNonBlocked(lpszIPAddress);
  390. }
  391. }