PSYNCSvr.cpp
上传用户:woshihumen
上传日期:2013-07-18
资源大小:484k
文件大小:15k
- /*
- * XMail by Davide Libenzi ( Intranet and Internet mail server )
- * Copyright (C) 1999,..,2004 Davide Libenzi
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Davide Libenzi <davidel@xmailserver.org>
- *
- */
- #include "SysInclude.h"
- #include "SysDep.h"
- #include "SvrDefines.h"
- #include "ShBlocks.h"
- #include "SList.h"
- #include "BuffSock.h"
- #include "ResLocks.h"
- #include "MiscUtils.h"
- #include "MailConfig.h"
- #include "SvrUtils.h"
- #include "UsrUtils.h"
- #include "POP3Svr.h"
- #include "POP3Utils.h"
- #include "MessQueue.h"
- #include "AppDefines.h"
- #include "MailSvr.h"
- #include "POP3GwLink.h"
- #include "PSYNCSvr.h"
- #define PSYNC_LOG_FILE "psync"
- #define PSYNC_TRIGGER_FILE ".psync-trigger"
- #define PSYNC_WAIT_SLEEP 2
- #define MAX_CLIENTS_WAIT 300
- #define PSYNC_WAKEUP_TIME 2
- #define PSYNC_SERVER_NAME "[" APP_NAME_VERSION_STR " PSYNC Server]"
- struct PSYNCThreadData {
- PSYNCConfig *pPSYNCCfg;
- POP3Link *pPopLnk;
- };
- static bool PSYNCNeedSync(void);
- static PSYNCConfig *PSYNCGetConfigCopy(SHB_HANDLE hShbPSYNC);
- static int PSYNCThreadCountAdd(long lCount, SHB_HANDLE hShbPSYNC, PSYNCConfig * pPSYNCCfg = NULL);
- static int PSYNCTimeToStop(SHB_HANDLE hShbPSYNC);
- static SYS_THREAD PSYNCCreateSyncThread(SHB_HANDLE hShbPSYNC, POP3Link * pPopLnk);
- static int PSYNCStartTransfer(SHB_HANDLE hShbPSYNC, PSYNCConfig * pPSYNCCfg);
- unsigned int PSYNCThreadSyncProc(void *pThreadData);
- static int PSYNCThreadNotifyExit(void);
- static int PSYNCLogEnabled(PSYNCConfig * pPSYNCCfg);
- static int PSYNCLogSession(POP3Link const *pPopLnk, PopSyncReport const *pSRep,
- char const *pszStatus);
- static bool PSYNCNeedSync(void)
- {
- char szTriggerPath[SYS_MAX_PATH] = "";
- CfgGetRootPath(szTriggerPath, sizeof(szTriggerPath));
- StrNCat(szTriggerPath, PSYNC_TRIGGER_FILE, sizeof(szTriggerPath));
- ///////////////////////////////////////////////////////////////////////////////
- // Check for the presence of the trigger file
- ///////////////////////////////////////////////////////////////////////////////
- if (!SysExistFile(szTriggerPath))
- return (false);
- SysRemove(szTriggerPath);
- return (true);
- }
- static PSYNCConfig *PSYNCGetConfigCopy(SHB_HANDLE hShbPSYNC)
- {
- PSYNCConfig *pPSYNCCfg = (PSYNCConfig *) ShbLock(hShbPSYNC);
- if (pPSYNCCfg == NULL)
- return (NULL);
- PSYNCConfig *pNewPSYNCCfg = (PSYNCConfig *) SysAlloc(sizeof(PSYNCConfig));
- if (pNewPSYNCCfg != NULL)
- memcpy(pNewPSYNCCfg, pPSYNCCfg, sizeof(PSYNCConfig));
- ShbUnlock(hShbPSYNC);
- return (pNewPSYNCCfg);
- }
- static int PSYNCThreadCountAdd(long lCount, SHB_HANDLE hShbPSYNC, PSYNCConfig * pPSYNCCfg)
- {
- int iDoUnlock = 0;
- if (pPSYNCCfg == NULL) {
- if ((pPSYNCCfg = (PSYNCConfig *) ShbLock(hShbPSYNC)) == NULL)
- return (ErrGetErrorCode());
- ++iDoUnlock;
- }
- pPSYNCCfg->lThreadCount += lCount;
- if (iDoUnlock)
- ShbUnlock(hShbPSYNC);
- return (0);
- }
- static int PSYNCTimeToStop(SHB_HANDLE hShbPSYNC)
- {
- PSYNCConfig *pPSYNCCfg = (PSYNCConfig *) ShbLock(hShbPSYNC);
- if (pPSYNCCfg == NULL)
- return (1);
- int iTimeToStop = (pPSYNCCfg->ulFlags & PSYNCF_STOP_SERVER) ? 1 : 0;
- ShbUnlock(hShbPSYNC);
- return (iTimeToStop);
- }
- unsigned int PSYNCThreadProc(void *pThreadData)
- {
- SysLogMessage(LOG_LEV_MESSAGE, "%s startedn", PSYNC_SERVER_NAME);
- int iElapsedTime = 0;
- for (;;) {
- SysSleep(PSYNC_WAKEUP_TIME);
- iElapsedTime += PSYNC_WAKEUP_TIME;
- PSYNCConfig *pPSYNCCfg = PSYNCGetConfigCopy(hShbPSYNC);
- if (pPSYNCCfg == NULL)
- break;
- if (pPSYNCCfg->ulFlags & PSYNCF_STOP_SERVER) {
- SysFree(pPSYNCCfg);
- break;
- }
- if (((pPSYNCCfg->iSyncInterval == 0) || (iElapsedTime < pPSYNCCfg->iSyncInterval))
- && !PSYNCNeedSync()) {
- SysFree(pPSYNCCfg);
- continue;
- }
- iElapsedTime = 0;
- PSYNCStartTransfer(hShbPSYNC, pPSYNCCfg);
- SysFree(pPSYNCCfg);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Wait for client completion
- ///////////////////////////////////////////////////////////////////////////////
- for (int iTotalWait = 0; (iTotalWait < MAX_CLIENTS_WAIT); iTotalWait += PSYNC_WAIT_SLEEP) {
- PSYNCConfig *pPSYNCCfg = (PSYNCConfig *) ShbLock(hShbPSYNC);
- if (pPSYNCCfg == NULL)
- break;
- long lThreadCount = pPSYNCCfg->lThreadCount;
- ShbUnlock(hShbPSYNC);
- if (lThreadCount == 0)
- break;
- SysSleep(PSYNC_WAIT_SLEEP);
- }
- SysLogMessage(LOG_LEV_MESSAGE, "%s stoppedn", PSYNC_SERVER_NAME);
- return (0);
- }
- static SYS_THREAD PSYNCCreateSyncThread(SHB_HANDLE hShbPSYNC, POP3Link * pPopLnk)
- {
- PSYNCThreadData *pSTD = (PSYNCThreadData *) SysAlloc(sizeof(PSYNCThreadData));
- if (pSTD == NULL)
- return (SYS_INVALID_THREAD);
- if ((pSTD->pPSYNCCfg = PSYNCGetConfigCopy(hShbPSYNC)) == NULL) {
- SysFree(pSTD);
- return (SYS_INVALID_THREAD);
- }
- pSTD->pPopLnk = pPopLnk;
- SYS_THREAD hThread = SysCreateThread(PSYNCThreadSyncProc, pSTD);
- if (hThread == SYS_INVALID_THREAD) {
- SysFree(pSTD->pPSYNCCfg);
- SysFree(pSTD);
- return (SYS_INVALID_THREAD);
- }
- return (hThread);
- }
- static int PSYNCStartTransfer(SHB_HANDLE hShbPSYNC, PSYNCConfig * pPSYNCCfg)
- {
- GWLKF_HANDLE hLinksDB = GwLkOpenDB();
- if (hLinksDB == INVALID_GWLKF_HANDLE) {
- ErrorPush();
- SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString(ErrorFetch()));
- return (ErrorPop());
- }
- POP3Link *pPopLnk = GwLkGetFirstUser(hLinksDB);
- for (; pPopLnk != NULL; pPopLnk = GwLkGetNextUser(hLinksDB)) {
- ///////////////////////////////////////////////////////////////////////////////
- // Check if link is enabled
- ///////////////////////////////////////////////////////////////////////////////
- if (GwLkCheckEnabled(pPopLnk) < 0) {
- GwLkFreePOP3Link(pPopLnk);
- continue;
- }
- if ((SysWaitSemaphore(hSyncSem, SYS_INFINITE_TIMEOUT) < 0) ||
- PSYNCTimeToStop(hShbPSYNC)) {
- GwLkFreePOP3Link(pPopLnk);
- break;
- }
- SYS_THREAD hClientThread = PSYNCCreateSyncThread(hShbPSYNC, pPopLnk);
- if (hClientThread == SYS_INVALID_THREAD) {
- ErrorPush();
- GwLkFreePOP3Link(pPopLnk);
- SysReleaseSemaphore(hSyncSem, 1);
- GwLkCloseDB(hLinksDB);
- return (ErrorPop());
- }
- SysCloseThread(hClientThread, 0);
- }
- GwLkCloseDB(hLinksDB);
- return (0);
- }
- static int PSYNCThreadNotifyExit(void)
- {
- SysReleaseSemaphore(hSyncSem, 1);
- return (0);
- }
- unsigned int PSYNCThreadSyncProc(void *pThreadData)
- {
- PSYNCThreadData *pSTD = (PSYNCThreadData *) pThreadData;
- POP3Link *pPopLnk = pSTD->pPopLnk;
- PSYNCConfig *pPSYNCCfg = pSTD->pPSYNCCfg;
- SysFree(pSTD);
- SysLogMessage(LOG_LEV_MESSAGE, "[PSYNC] entryn");
- ///////////////////////////////////////////////////////////////////////////////
- // Get configuration handle
- ///////////////////////////////////////////////////////////////////////////////
- SVRCFG_HANDLE hSvrConfig = SvrGetConfigHandle();
- if (hSvrConfig == INVALID_SVRCFG_HANDLE) {
- ErrorPush();
- SysLogMessage(LOG_LEV_MESSAGE, "%sn", ErrGetErrorString(ErrorFetch()));
- GwLkFreePOP3Link(pPopLnk);
- SysFree(pPSYNCCfg);
- ///////////////////////////////////////////////////////////////////////////////
- // Notify thread exit semaphore
- ///////////////////////////////////////////////////////////////////////////////
- PSYNCThreadNotifyExit();
- return (ErrorPop());
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Get the error account for email that the server is not able to deliver coz
- // it does not find information about where it has to deliver
- ///////////////////////////////////////////////////////////////////////////////
- char szErrorAccount[MAX_ADDR_NAME] = "";
- SvrConfigVar("Pop3SyncErrorAccount", szErrorAccount, sizeof(szErrorAccount) - 1,
- hSvrConfig, "");
- char const *pszErrorAccount = (IsEmptyString(szErrorAccount)) ? NULL : szErrorAccount;
- ///////////////////////////////////////////////////////////////////////////////
- // Get headers tags that must be checked to extract recipients
- ///////////////////////////////////////////////////////////////////////////////
- char szFetchHdrTags[256] = "";
- SvrConfigVar("FetchHdrTags", szFetchHdrTags, sizeof(szFetchHdrTags) - 1,
- hSvrConfig, "+X-Deliver-To,+Received,To,Cc");
- ///////////////////////////////////////////////////////////////////////////////
- // Lock the link
- ///////////////////////////////////////////////////////////////////////////////
- if (GwLkLinkLock(pPopLnk) < 0) {
- ErrorPush();
- SysLogMessage(LOG_LEV_MESSAGE, "%sn", ErrGetErrorString(ErrorFetch()));
- SvrReleaseConfigHandle(hSvrConfig);
- GwLkFreePOP3Link(pPopLnk);
- SysFree(pPSYNCCfg);
- ///////////////////////////////////////////////////////////////////////////////
- // Notify thread exit semaphore
- ///////////////////////////////////////////////////////////////////////////////
- PSYNCThreadNotifyExit();
- return (ErrorPop());
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Increase threads count
- ///////////////////////////////////////////////////////////////////////////////
- PSYNCThreadCountAdd(+1, hShbPSYNC);
- ///////////////////////////////////////////////////////////////////////////////
- // Sync for real internal account ?
- ///////////////////////////////////////////////////////////////////////////////
- PopSyncReport SRep;
- if (GwLkLocalDomain(pPopLnk)) {
- ///////////////////////////////////////////////////////////////////////////////
- // Verify user credentials
- ///////////////////////////////////////////////////////////////////////////////
- UserInfo *pUI = UsrGetUserByName(pPopLnk->pszDomain, pPopLnk->pszName);
- if (pUI != NULL) {
- SysLogMessage(LOG_LEV_MESSAGE,
- "[PSYNC] User = "%s" - Domain = "%s"n",
- pPopLnk->pszName, pPopLnk->pszDomain);
- ///////////////////////////////////////////////////////////////////////////////
- // Sync
- ///////////////////////////////////////////////////////////////////////////////
- char szUserAddress[MAX_ADDR_NAME] = "";
- UsrGetAddress(pUI, szUserAddress);
- if (UPopSyncRemoteLink
- (szUserAddress, pPopLnk->pszRmtDomain, pPopLnk->pszRmtName,
- pPopLnk->pszRmtPassword, &SRep, szFetchHdrTags, pPopLnk->pszAuthType,
- pszErrorAccount) < 0) {
- ErrLogMessage(LOG_LEV_MESSAGE,
- "[PSYNC] User = "%s" - Domain = "%s" Failed !n",
- pPopLnk->pszName, pPopLnk->pszDomain);
- ZeroData(SRep);
- if (PSYNCLogEnabled(pPSYNCCfg))
- PSYNCLogSession(pPopLnk, &SRep, "SYNC=EFAIL");
- } else {
- if (PSYNCLogEnabled(pPSYNCCfg))
- PSYNCLogSession(pPopLnk, &SRep, "SYNC=OK");
- }
- UsrFreeUserInfo(pUI);
- } else {
- SysLogMessage(LOG_LEV_MESSAGE,
- "[PSYNC] User = "%s" - Domain = "%s" Failed !n"
- "Error = %sn", pPopLnk->pszName, pPopLnk->pszDomain,
- ErrGetErrorString());
- ZeroData(SRep);
- if (PSYNCLogEnabled(pPSYNCCfg))
- PSYNCLogSession(pPopLnk, &SRep, "SYNC=ENOUSER");
- }
- } else if (GwLkMasqueradeDomain(pPopLnk)) {
- SysLogMessage(LOG_LEV_MESSAGE,
- "[PSYNC/MASQ] MasqDomain = "%s" - RmtDomain = "%s" - RmtName = "%s"n",
- pPopLnk->pszDomain + 1, pPopLnk->pszRmtDomain, pPopLnk->pszRmtName);
- ///////////////////////////////////////////////////////////////////////////////
- // Sync ( "pszDomain" == "?" + masq-domain or "pszDomain" == "&" + add-domain )
- ///////////////////////////////////////////////////////////////////////////////
- if (UPopSyncRemoteLink
- (pPopLnk->pszDomain, pPopLnk->pszRmtDomain, pPopLnk->pszRmtName,
- pPopLnk->pszRmtPassword, &SRep, szFetchHdrTags, pPopLnk->pszAuthType,
- pszErrorAccount) < 0) {
- ErrLogMessage(LOG_LEV_MESSAGE,
- "[PSYNC/MASQ] MasqDomain = "%s" - RmtDomain = "%s" - RmtName = "%s" Failed !n",
- pPopLnk->pszDomain + 1, pPopLnk->pszRmtDomain,
- pPopLnk->pszRmtName);
- ZeroData(SRep);
- if (PSYNCLogEnabled(pPSYNCCfg))
- PSYNCLogSession(pPopLnk, &SRep, "SYNC=EFAIL");
- } else {
- if (PSYNCLogEnabled(pPSYNCCfg))
- PSYNCLogSession(pPopLnk, &SRep, "SYNC=OK");
- }
- } else {
- char szSyncAddress[MAX_ADDR_NAME] = "";
- SysSNPrintf(szSyncAddress, sizeof(szSyncAddress) - 1, "%s%s", pPopLnk->pszName,
- pPopLnk->pszDomain);
- SysLogMessage(LOG_LEV_MESSAGE,
- "[PSYNC/EXT] Acount = "%s" - RmtDomain = "%s" - RmtName = "%s"n",
- szSyncAddress, pPopLnk->pszRmtDomain, pPopLnk->pszRmtName);
- ///////////////////////////////////////////////////////////////////////////////
- // Sync ( "pszDomain" == "@" + domain )
- ///////////////////////////////////////////////////////////////////////////////
- if (UPopSyncRemoteLink(szSyncAddress, pPopLnk->pszRmtDomain, pPopLnk->pszRmtName,
- pPopLnk->pszRmtPassword, &SRep, szFetchHdrTags,
- pPopLnk->pszAuthType, pszErrorAccount) < 0) {
- ErrLogMessage(LOG_LEV_MESSAGE,
- "[PSYNC/EXT] Acount = "%s" - RmtDomain = "%s" - RmtName = "%s" Failed !n",
- szSyncAddress, pPopLnk->pszRmtDomain, pPopLnk->pszRmtName);
- ZeroData(SRep);
- if (PSYNCLogEnabled(pPSYNCCfg))
- PSYNCLogSession(pPopLnk, &SRep, "SYNC=EFAIL");
- } else {
- if (PSYNCLogEnabled(pPSYNCCfg))
- PSYNCLogSession(pPopLnk, &SRep, "SYNC=OK");
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Decrease threads count
- ///////////////////////////////////////////////////////////////////////////////
- PSYNCThreadCountAdd(-1, hShbPSYNC);
- GwLkLinkUnlock(pPopLnk);
- SvrReleaseConfigHandle(hSvrConfig);
- GwLkFreePOP3Link(pPopLnk);
- SysFree(pPSYNCCfg);
- ///////////////////////////////////////////////////////////////////////////////
- // Notify thread exit semaphore
- ///////////////////////////////////////////////////////////////////////////////
- PSYNCThreadNotifyExit();
- SysLogMessage(LOG_LEV_MESSAGE, "[PSYNC] exitn");
- return (0);
- }
- static int PSYNCLogEnabled(PSYNCConfig * pPSYNCCfg)
- {
- return ((pPSYNCCfg->ulFlags & PSYNCF_LOG_ENABLED) ? 1 : 0);
- }
- static int PSYNCLogSession(POP3Link const *pPopLnk, PopSyncReport const *pSRep,
- char const *pszStatus)
- {
- char szTime[256] = "";
- MscGetTimeNbrString(szTime, sizeof(szTime) - 1);
- RLCK_HANDLE hResLock = RLckLockEX(SVR_LOGS_DIR SYS_SLASH_STR PSYNC_LOG_FILE);
- if (hResLock == INVALID_RLCK_HANDLE)
- return (ErrGetErrorCode());
- MscFileLog(PSYNC_LOG_FILE,
- ""%s""
- "t"%s""
- "t"%s""
- "t"%s""
- "t"%s""
- "t"%s""
- "t"%s""
- "t"%d""
- "t"%lu""
- "t"%d""
- "t"%lu""
- "n", szTime, pPopLnk->pszDomain, pPopLnk->pszName,
- pPopLnk->pszRmtDomain, pPopLnk->pszRmtName, pPopLnk->pszAuthType, pszStatus,
- pSRep->iMsgSync, pSRep->ulSizeSync, pSRep->iMsgErr, pSRep->ulSizeErr);
- RLckUnlockEX(hResLock);
- return (0);
- }