PSYNCSvr.cpp
上传用户:woshihumen
上传日期:2013-07-18
资源大小:484k
文件大小:15k
源码类别:

Email服务器

开发平台:

Visual C++

  1. /*
  2.  *  XMail by Davide Libenzi ( Intranet and Internet mail server )
  3.  *  Copyright (C) 1999,..,2004  Davide Libenzi
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  *  Davide Libenzi <davidel@xmailserver.org>
  20.  *
  21.  */
  22. #include "SysInclude.h"
  23. #include "SysDep.h"
  24. #include "SvrDefines.h"
  25. #include "ShBlocks.h"
  26. #include "SList.h"
  27. #include "BuffSock.h"
  28. #include "ResLocks.h"
  29. #include "MiscUtils.h"
  30. #include "MailConfig.h"
  31. #include "SvrUtils.h"
  32. #include "UsrUtils.h"
  33. #include "POP3Svr.h"
  34. #include "POP3Utils.h"
  35. #include "MessQueue.h"
  36. #include "AppDefines.h"
  37. #include "MailSvr.h"
  38. #include "POP3GwLink.h"
  39. #include "PSYNCSvr.h"
  40. #define PSYNC_LOG_FILE              "psync"
  41. #define PSYNC_TRIGGER_FILE          ".psync-trigger"
  42. #define PSYNC_WAIT_SLEEP            2
  43. #define MAX_CLIENTS_WAIT            300
  44. #define PSYNC_WAKEUP_TIME           2
  45. #define PSYNC_SERVER_NAME           "[" APP_NAME_VERSION_STR " PSYNC Server]"
  46. struct PSYNCThreadData {
  47. PSYNCConfig *pPSYNCCfg;
  48. POP3Link *pPopLnk;
  49. };
  50. static bool PSYNCNeedSync(void);
  51. static PSYNCConfig *PSYNCGetConfigCopy(SHB_HANDLE hShbPSYNC);
  52. static int PSYNCThreadCountAdd(long lCount, SHB_HANDLE hShbPSYNC, PSYNCConfig * pPSYNCCfg = NULL);
  53. static int PSYNCTimeToStop(SHB_HANDLE hShbPSYNC);
  54. static SYS_THREAD PSYNCCreateSyncThread(SHB_HANDLE hShbPSYNC, POP3Link * pPopLnk);
  55. static int PSYNCStartTransfer(SHB_HANDLE hShbPSYNC, PSYNCConfig * pPSYNCCfg);
  56. unsigned int PSYNCThreadSyncProc(void *pThreadData);
  57. static int PSYNCThreadNotifyExit(void);
  58. static int PSYNCLogEnabled(PSYNCConfig * pPSYNCCfg);
  59. static int PSYNCLogSession(POP3Link const *pPopLnk, PopSyncReport const *pSRep,
  60.    char const *pszStatus);
  61. static bool PSYNCNeedSync(void)
  62. {
  63. char szTriggerPath[SYS_MAX_PATH] = "";
  64. CfgGetRootPath(szTriggerPath, sizeof(szTriggerPath));
  65. StrNCat(szTriggerPath, PSYNC_TRIGGER_FILE, sizeof(szTriggerPath));
  66. ///////////////////////////////////////////////////////////////////////////////
  67. //  Check for the presence of the trigger file
  68. ///////////////////////////////////////////////////////////////////////////////
  69. if (!SysExistFile(szTriggerPath))
  70. return (false);
  71. SysRemove(szTriggerPath);
  72. return (true);
  73. }
  74. static PSYNCConfig *PSYNCGetConfigCopy(SHB_HANDLE hShbPSYNC)
  75. {
  76. PSYNCConfig *pPSYNCCfg = (PSYNCConfig *) ShbLock(hShbPSYNC);
  77. if (pPSYNCCfg == NULL)
  78. return (NULL);
  79. PSYNCConfig *pNewPSYNCCfg = (PSYNCConfig *) SysAlloc(sizeof(PSYNCConfig));
  80. if (pNewPSYNCCfg != NULL)
  81. memcpy(pNewPSYNCCfg, pPSYNCCfg, sizeof(PSYNCConfig));
  82. ShbUnlock(hShbPSYNC);
  83. return (pNewPSYNCCfg);
  84. }
  85. static int PSYNCThreadCountAdd(long lCount, SHB_HANDLE hShbPSYNC, PSYNCConfig * pPSYNCCfg)
  86. {
  87. int iDoUnlock = 0;
  88. if (pPSYNCCfg == NULL) {
  89. if ((pPSYNCCfg = (PSYNCConfig *) ShbLock(hShbPSYNC)) == NULL)
  90. return (ErrGetErrorCode());
  91. ++iDoUnlock;
  92. }
  93. pPSYNCCfg->lThreadCount += lCount;
  94. if (iDoUnlock)
  95. ShbUnlock(hShbPSYNC);
  96. return (0);
  97. }
  98. static int PSYNCTimeToStop(SHB_HANDLE hShbPSYNC)
  99. {
  100. PSYNCConfig *pPSYNCCfg = (PSYNCConfig *) ShbLock(hShbPSYNC);
  101. if (pPSYNCCfg == NULL)
  102. return (1);
  103. int iTimeToStop = (pPSYNCCfg->ulFlags & PSYNCF_STOP_SERVER) ? 1 : 0;
  104. ShbUnlock(hShbPSYNC);
  105. return (iTimeToStop);
  106. }
  107. unsigned int PSYNCThreadProc(void *pThreadData)
  108. {
  109. SysLogMessage(LOG_LEV_MESSAGE, "%s startedn", PSYNC_SERVER_NAME);
  110. int iElapsedTime = 0;
  111. for (;;) {
  112. SysSleep(PSYNC_WAKEUP_TIME);
  113. iElapsedTime += PSYNC_WAKEUP_TIME;
  114. PSYNCConfig *pPSYNCCfg = PSYNCGetConfigCopy(hShbPSYNC);
  115. if (pPSYNCCfg == NULL)
  116. break;
  117. if (pPSYNCCfg->ulFlags & PSYNCF_STOP_SERVER) {
  118. SysFree(pPSYNCCfg);
  119. break;
  120. }
  121. if (((pPSYNCCfg->iSyncInterval == 0) || (iElapsedTime < pPSYNCCfg->iSyncInterval))
  122.     && !PSYNCNeedSync()) {
  123. SysFree(pPSYNCCfg);
  124. continue;
  125. }
  126. iElapsedTime = 0;
  127. PSYNCStartTransfer(hShbPSYNC, pPSYNCCfg);
  128. SysFree(pPSYNCCfg);
  129. }
  130. ///////////////////////////////////////////////////////////////////////////////
  131. //  Wait for client completion
  132. ///////////////////////////////////////////////////////////////////////////////
  133. for (int iTotalWait = 0; (iTotalWait < MAX_CLIENTS_WAIT); iTotalWait += PSYNC_WAIT_SLEEP) {
  134. PSYNCConfig *pPSYNCCfg = (PSYNCConfig *) ShbLock(hShbPSYNC);
  135. if (pPSYNCCfg == NULL)
  136. break;
  137. long lThreadCount = pPSYNCCfg->lThreadCount;
  138. ShbUnlock(hShbPSYNC);
  139. if (lThreadCount == 0)
  140. break;
  141. SysSleep(PSYNC_WAIT_SLEEP);
  142. }
  143. SysLogMessage(LOG_LEV_MESSAGE, "%s stoppedn", PSYNC_SERVER_NAME);
  144. return (0);
  145. }
  146. static SYS_THREAD PSYNCCreateSyncThread(SHB_HANDLE hShbPSYNC, POP3Link * pPopLnk)
  147. {
  148. PSYNCThreadData *pSTD = (PSYNCThreadData *) SysAlloc(sizeof(PSYNCThreadData));
  149. if (pSTD == NULL)
  150. return (SYS_INVALID_THREAD);
  151. if ((pSTD->pPSYNCCfg = PSYNCGetConfigCopy(hShbPSYNC)) == NULL) {
  152. SysFree(pSTD);
  153. return (SYS_INVALID_THREAD);
  154. }
  155. pSTD->pPopLnk = pPopLnk;
  156. SYS_THREAD hThread = SysCreateThread(PSYNCThreadSyncProc, pSTD);
  157. if (hThread == SYS_INVALID_THREAD) {
  158. SysFree(pSTD->pPSYNCCfg);
  159. SysFree(pSTD);
  160. return (SYS_INVALID_THREAD);
  161. }
  162. return (hThread);
  163. }
  164. static int PSYNCStartTransfer(SHB_HANDLE hShbPSYNC, PSYNCConfig * pPSYNCCfg)
  165. {
  166. GWLKF_HANDLE hLinksDB = GwLkOpenDB();
  167. if (hLinksDB == INVALID_GWLKF_HANDLE) {
  168. ErrorPush();
  169. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString(ErrorFetch()));
  170. return (ErrorPop());
  171. }
  172. POP3Link *pPopLnk = GwLkGetFirstUser(hLinksDB);
  173. for (; pPopLnk != NULL; pPopLnk = GwLkGetNextUser(hLinksDB)) {
  174. ///////////////////////////////////////////////////////////////////////////////
  175. //  Check if link is enabled
  176. ///////////////////////////////////////////////////////////////////////////////
  177. if (GwLkCheckEnabled(pPopLnk) < 0) {
  178. GwLkFreePOP3Link(pPopLnk);
  179. continue;
  180. }
  181. if ((SysWaitSemaphore(hSyncSem, SYS_INFINITE_TIMEOUT) < 0) ||
  182.     PSYNCTimeToStop(hShbPSYNC)) {
  183. GwLkFreePOP3Link(pPopLnk);
  184. break;
  185. }
  186. SYS_THREAD hClientThread = PSYNCCreateSyncThread(hShbPSYNC, pPopLnk);
  187. if (hClientThread == SYS_INVALID_THREAD) {
  188. ErrorPush();
  189. GwLkFreePOP3Link(pPopLnk);
  190. SysReleaseSemaphore(hSyncSem, 1);
  191. GwLkCloseDB(hLinksDB);
  192. return (ErrorPop());
  193. }
  194. SysCloseThread(hClientThread, 0);
  195. }
  196. GwLkCloseDB(hLinksDB);
  197. return (0);
  198. }
  199. static int PSYNCThreadNotifyExit(void)
  200. {
  201. SysReleaseSemaphore(hSyncSem, 1);
  202. return (0);
  203. }
  204. unsigned int PSYNCThreadSyncProc(void *pThreadData)
  205. {
  206. PSYNCThreadData *pSTD = (PSYNCThreadData *) pThreadData;
  207. POP3Link *pPopLnk = pSTD->pPopLnk;
  208. PSYNCConfig *pPSYNCCfg = pSTD->pPSYNCCfg;
  209. SysFree(pSTD);
  210. SysLogMessage(LOG_LEV_MESSAGE, "[PSYNC] entryn");
  211. ///////////////////////////////////////////////////////////////////////////////
  212. //  Get configuration handle
  213. ///////////////////////////////////////////////////////////////////////////////
  214. SVRCFG_HANDLE hSvrConfig = SvrGetConfigHandle();
  215. if (hSvrConfig == INVALID_SVRCFG_HANDLE) {
  216. ErrorPush();
  217. SysLogMessage(LOG_LEV_MESSAGE, "%sn", ErrGetErrorString(ErrorFetch()));
  218. GwLkFreePOP3Link(pPopLnk);
  219. SysFree(pPSYNCCfg);
  220. ///////////////////////////////////////////////////////////////////////////////
  221. //  Notify thread exit semaphore
  222. ///////////////////////////////////////////////////////////////////////////////
  223. PSYNCThreadNotifyExit();
  224. return (ErrorPop());
  225. }
  226. ///////////////////////////////////////////////////////////////////////////////
  227. //  Get the error account for email that the server is not able to deliver coz
  228. //  it does not find information about where it has to deliver
  229. ///////////////////////////////////////////////////////////////////////////////
  230. char szErrorAccount[MAX_ADDR_NAME] = "";
  231. SvrConfigVar("Pop3SyncErrorAccount", szErrorAccount, sizeof(szErrorAccount) - 1,
  232.      hSvrConfig, "");
  233. char const *pszErrorAccount = (IsEmptyString(szErrorAccount)) ? NULL : szErrorAccount;
  234. ///////////////////////////////////////////////////////////////////////////////
  235. //  Get headers tags that must be checked to extract recipients
  236. ///////////////////////////////////////////////////////////////////////////////
  237. char szFetchHdrTags[256] = "";
  238. SvrConfigVar("FetchHdrTags", szFetchHdrTags, sizeof(szFetchHdrTags) - 1,
  239.      hSvrConfig, "+X-Deliver-To,+Received,To,Cc");
  240. ///////////////////////////////////////////////////////////////////////////////
  241. //  Lock the link
  242. ///////////////////////////////////////////////////////////////////////////////
  243. if (GwLkLinkLock(pPopLnk) < 0) {
  244. ErrorPush();
  245. SysLogMessage(LOG_LEV_MESSAGE, "%sn", ErrGetErrorString(ErrorFetch()));
  246. SvrReleaseConfigHandle(hSvrConfig);
  247. GwLkFreePOP3Link(pPopLnk);
  248. SysFree(pPSYNCCfg);
  249. ///////////////////////////////////////////////////////////////////////////////
  250. //  Notify thread exit semaphore
  251. ///////////////////////////////////////////////////////////////////////////////
  252. PSYNCThreadNotifyExit();
  253. return (ErrorPop());
  254. }
  255. ///////////////////////////////////////////////////////////////////////////////
  256. //  Increase threads count
  257. ///////////////////////////////////////////////////////////////////////////////
  258. PSYNCThreadCountAdd(+1, hShbPSYNC);
  259. ///////////////////////////////////////////////////////////////////////////////
  260. //  Sync for real internal account ?
  261. ///////////////////////////////////////////////////////////////////////////////
  262. PopSyncReport SRep;
  263. if (GwLkLocalDomain(pPopLnk)) {
  264. ///////////////////////////////////////////////////////////////////////////////
  265. //  Verify user credentials
  266. ///////////////////////////////////////////////////////////////////////////////
  267. UserInfo *pUI = UsrGetUserByName(pPopLnk->pszDomain, pPopLnk->pszName);
  268. if (pUI != NULL) {
  269. SysLogMessage(LOG_LEV_MESSAGE,
  270.       "[PSYNC] User = "%s" - Domain = "%s"n",
  271.       pPopLnk->pszName, pPopLnk->pszDomain);
  272. ///////////////////////////////////////////////////////////////////////////////
  273. //  Sync
  274. ///////////////////////////////////////////////////////////////////////////////
  275. char szUserAddress[MAX_ADDR_NAME] = "";
  276. UsrGetAddress(pUI, szUserAddress);
  277. if (UPopSyncRemoteLink
  278.     (szUserAddress, pPopLnk->pszRmtDomain, pPopLnk->pszRmtName,
  279.      pPopLnk->pszRmtPassword, &SRep, szFetchHdrTags, pPopLnk->pszAuthType,
  280.      pszErrorAccount) < 0) {
  281. ErrLogMessage(LOG_LEV_MESSAGE,
  282.       "[PSYNC] User = "%s" - Domain = "%s" Failed !n",
  283.       pPopLnk->pszName, pPopLnk->pszDomain);
  284. ZeroData(SRep);
  285. if (PSYNCLogEnabled(pPSYNCCfg))
  286. PSYNCLogSession(pPopLnk, &SRep, "SYNC=EFAIL");
  287. } else {
  288. if (PSYNCLogEnabled(pPSYNCCfg))
  289. PSYNCLogSession(pPopLnk, &SRep, "SYNC=OK");
  290. }
  291. UsrFreeUserInfo(pUI);
  292. } else {
  293. SysLogMessage(LOG_LEV_MESSAGE,
  294.       "[PSYNC] User = "%s" - Domain = "%s" Failed !n"
  295.       "Error = %sn", pPopLnk->pszName, pPopLnk->pszDomain,
  296.       ErrGetErrorString());
  297. ZeroData(SRep);
  298. if (PSYNCLogEnabled(pPSYNCCfg))
  299. PSYNCLogSession(pPopLnk, &SRep, "SYNC=ENOUSER");
  300. }
  301. } else if (GwLkMasqueradeDomain(pPopLnk)) {
  302. SysLogMessage(LOG_LEV_MESSAGE,
  303.       "[PSYNC/MASQ] MasqDomain = "%s" - RmtDomain = "%s" - RmtName = "%s"n",
  304.       pPopLnk->pszDomain + 1, pPopLnk->pszRmtDomain, pPopLnk->pszRmtName);
  305. ///////////////////////////////////////////////////////////////////////////////
  306. //  Sync ( "pszDomain" == "?" + masq-domain or "pszDomain" == "&" + add-domain )
  307. ///////////////////////////////////////////////////////////////////////////////
  308. if (UPopSyncRemoteLink
  309.     (pPopLnk->pszDomain, pPopLnk->pszRmtDomain, pPopLnk->pszRmtName,
  310.      pPopLnk->pszRmtPassword, &SRep, szFetchHdrTags, pPopLnk->pszAuthType,
  311.      pszErrorAccount) < 0) {
  312. ErrLogMessage(LOG_LEV_MESSAGE,
  313.       "[PSYNC/MASQ] MasqDomain = "%s" - RmtDomain = "%s" - RmtName = "%s" Failed !n",
  314.       pPopLnk->pszDomain + 1, pPopLnk->pszRmtDomain,
  315.       pPopLnk->pszRmtName);
  316. ZeroData(SRep);
  317. if (PSYNCLogEnabled(pPSYNCCfg))
  318. PSYNCLogSession(pPopLnk, &SRep, "SYNC=EFAIL");
  319. } else {
  320. if (PSYNCLogEnabled(pPSYNCCfg))
  321. PSYNCLogSession(pPopLnk, &SRep, "SYNC=OK");
  322. }
  323. } else {
  324. char szSyncAddress[MAX_ADDR_NAME] = "";
  325. SysSNPrintf(szSyncAddress, sizeof(szSyncAddress) - 1, "%s%s", pPopLnk->pszName,
  326.     pPopLnk->pszDomain);
  327. SysLogMessage(LOG_LEV_MESSAGE,
  328.       "[PSYNC/EXT] Acount = "%s" - RmtDomain = "%s" - RmtName = "%s"n",
  329.       szSyncAddress, pPopLnk->pszRmtDomain, pPopLnk->pszRmtName);
  330. ///////////////////////////////////////////////////////////////////////////////
  331. //  Sync ( "pszDomain" == "@" + domain )
  332. ///////////////////////////////////////////////////////////////////////////////
  333. if (UPopSyncRemoteLink(szSyncAddress, pPopLnk->pszRmtDomain, pPopLnk->pszRmtName,
  334.        pPopLnk->pszRmtPassword, &SRep, szFetchHdrTags,
  335.        pPopLnk->pszAuthType, pszErrorAccount) < 0) {
  336. ErrLogMessage(LOG_LEV_MESSAGE,
  337.       "[PSYNC/EXT] Acount = "%s" - RmtDomain = "%s" - RmtName = "%s" Failed !n",
  338.       szSyncAddress, pPopLnk->pszRmtDomain, pPopLnk->pszRmtName);
  339. ZeroData(SRep);
  340. if (PSYNCLogEnabled(pPSYNCCfg))
  341. PSYNCLogSession(pPopLnk, &SRep, "SYNC=EFAIL");
  342. } else {
  343. if (PSYNCLogEnabled(pPSYNCCfg))
  344. PSYNCLogSession(pPopLnk, &SRep, "SYNC=OK");
  345. }
  346. }
  347. ///////////////////////////////////////////////////////////////////////////////
  348. //  Decrease threads count
  349. ///////////////////////////////////////////////////////////////////////////////
  350. PSYNCThreadCountAdd(-1, hShbPSYNC);
  351. GwLkLinkUnlock(pPopLnk);
  352. SvrReleaseConfigHandle(hSvrConfig);
  353. GwLkFreePOP3Link(pPopLnk);
  354. SysFree(pPSYNCCfg);
  355. ///////////////////////////////////////////////////////////////////////////////
  356. //  Notify thread exit semaphore
  357. ///////////////////////////////////////////////////////////////////////////////
  358. PSYNCThreadNotifyExit();
  359. SysLogMessage(LOG_LEV_MESSAGE, "[PSYNC] exitn");
  360. return (0);
  361. }
  362. static int PSYNCLogEnabled(PSYNCConfig * pPSYNCCfg)
  363. {
  364. return ((pPSYNCCfg->ulFlags & PSYNCF_LOG_ENABLED) ? 1 : 0);
  365. }
  366. static int PSYNCLogSession(POP3Link const *pPopLnk, PopSyncReport const *pSRep,
  367.    char const *pszStatus)
  368. {
  369. char szTime[256] = "";
  370. MscGetTimeNbrString(szTime, sizeof(szTime) - 1);
  371. RLCK_HANDLE hResLock = RLckLockEX(SVR_LOGS_DIR SYS_SLASH_STR PSYNC_LOG_FILE);
  372. if (hResLock == INVALID_RLCK_HANDLE)
  373. return (ErrGetErrorCode());
  374. MscFileLog(PSYNC_LOG_FILE,
  375.    ""%s""
  376.    "t"%s""
  377.    "t"%s""
  378.    "t"%s""
  379.    "t"%s""
  380.    "t"%s""
  381.    "t"%s""
  382.    "t"%d""
  383.    "t"%lu""
  384.    "t"%d""
  385.    "t"%lu""
  386.    "n", szTime, pPopLnk->pszDomain, pPopLnk->pszName,
  387.    pPopLnk->pszRmtDomain, pPopLnk->pszRmtName, pPopLnk->pszAuthType, pszStatus,
  388.    pSRep->iMsgSync, pSRep->ulSizeSync, pSRep->iMsgErr, pSRep->ulSizeErr);
  389. RLckUnlockEX(hResLock);
  390. return (0);
  391. }