⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sntp.cxx

📁 Windows CE 6.0 Server 源码
💻 CXX
📖 第 1 页 / 共 4 页
字号:
        } else {
            iErr = ERROR_SUCCESS;
            fSystemTimeCorrect = TRUE;
        }

        DWORD dw;
        DWORD dwType = 0;
        DWORD dwSize = sizeof(dw);

        if ((iErr == ERROR_SUCCESS) && (ERROR_SUCCESS == RegQueryValueEx (hk, L"ServerRole", NULL, &dwType, (LPBYTE)&dw, &dwSize)) &&
                            (dwType == REG_DWORD) && (dwSize == sizeof(dw)) && dw)
            fHaveServer = TRUE;

        dwType = 0;
        dwSize = sizeof(dw);

        if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"trustlocalclock", NULL, &dwType, (LPBYTE)&dw, &dwSize)) &&
                            (dwType == REG_DWORD) && (dwSize == sizeof(dw)) && dw)
            fSystemTimeCorrect = TRUE;

        if (fHaveServer) {
            iErr = GetAddressList (hk, L"multicast", (char *)sntp_mcasts, SVSUTIL_ARRLEN(sntp_mcasts), SVSUTIL_ARRLEN(sntp_mcasts[0]), &cMcasts);
            if ((iErr == ERROR_SUCCESS) && cMcasts) {
                if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"multicastperiod", NULL, &dwType, (LPBYTE)&dw, &dwSize)) &&
                            (dwType == REG_DWORD) && (dwSize == sizeof(dw)) && (dw > MIN_MULTICAST))
                    dwMulticastPeriodMS = dw;
                else {
                    iErr = ERROR_BAD_CONFIGURATION;
                    RETAILMSG(1, (L"[TIMESVC] Configuration error: Multicast period required. Aborting.\r\n"));
                }
            }
        }
        RegCloseKey (hk);
    } else {
        fHaveClient = TRUE;
        fHaveServer = TRUE;

        iErr = ERROR_SUCCESS;
        strcpy ((char *)sntp_servers[0], "time.windows.com");
        cServers = 1;

        sntp_mcasts[0][0] = '\0';
        cMcasts  = 0;        // No multicasts

        dwRefreshMS = 14*24*60*60*1000;            // Synchronize clock every two weeks
        dwRecoveryRefreshMS = 30*60*1000;         // Try every half hour if it fails
        dwAdjustThreshMS = 24*60*60*1000;                // Allow one day

        fSystemTimeCorrect = TRUE;                // Server provides time even if time synch failed
    }

    if (fHaveServer) {
    }
    for (int i = 0 ; i < cServers ; ++i) {
        DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Configuration: sntp server           : %a\r\n", sntp_servers[i]));
    }

    DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Configuration: client                : %s\r\n", fHaveClient ? L"enabled" : L"disabled"));
    DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Configuration: server                : %s\r\n", fHaveServer ? L"enabled" : L"disabled"));
    DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Configuration: regular refresh       : %d ms (%d day(s))\r\n", dwRefreshMS, dwRefreshMS/(24*60*60*1000)));
    DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Configuration: accelerated refresh   : %d ms (%d day(s))\r\n", dwRecoveryRefreshMS, dwRecoveryRefreshMS/(24*60*60*1000)));
    DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Configuration: adjustment threshold  : %d ms\r\n", dwAdjustThreshMS));

    if (fHaveServer) {
        DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Configuration: system clock          : %s\r\n", fSystemTimeCorrect ? L"presumed correct" : L"presumed wrong if not updates"));
        for (int i = 0 ; i < cMcasts ; ++i) {
            DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Configuration: multicast address     : %a\r\n", sntp_mcasts[i]));
        }
        DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Configuration: multicast period      : %d ms\r\n", dwMulticastPeriodMS));
    }

    return iErr;
}

int TimeState::ForcedUpdate (void) {
    fRefreshRequired = TRUE;

    DEBUGMSG(ZONE_CLIENT, (L"[TIMESVC] Client: updating time NOW\r\n"));

    if (ckNextRefresh)
        pEvents->UnScheduleEvent (ckNextRefresh);

    if (! fSystemTimeCorrect)
        fForceTimeToServer = TRUE;

    if (! (ckNextRefresh = pEvents->ScheduleEvent (TimeRefreshThread, NULL, 0)))
        return ERROR_OUTOFMEMORY;

    return ERROR_SUCCESS;
}

int TimeState::UpdateNowOrLater (enum When when, int fForceTime) {
    if (! fHaveClient) {
        DEBUGMSG(ZONE_CLIENT, (L"[TIMESVC] Client: not enabled; update request ignored\r\n"));
        return ERROR_SUCCESS;
    }

    DWORD dwTimeout;
    if (when == Now) {
        fRefreshRequired = TRUE;
        dwTimeout = NULL;
    } else if (when == Shortly) {
        SVSUTIL_ASSERT (fRefreshRequired);
        dwTimeout = dwRecoveryRefreshMS;
    } else
        dwTimeout = dwRefreshMS;

    DEBUGMSG(ZONE_CLIENT, (L"[TIMESVC] Client: schedule time update in %d ms %s\r\n", dwTimeout, fForceTime ? L"(require refresh)" : L""));

    if (ckNextRefresh)
        pEvents->UnScheduleEvent (ckNextRefresh);

    if (fForceTime || (! fSystemTimeCorrect))
        fForceTimeToServer = TRUE;

    if (! (ckNextRefresh = pEvents->ScheduleEvent (TimeRefreshThread, NULL, dwTimeout)))
        return ERROR_OUTOFMEMORY;

    return ERROR_SUCCESS;
}

int TimeState::TimeChanged (void) {
    DEBUGMSG(ZONE_TRACE, (L"[TIMESVC] Server: Time changed - multicast now?\r\n"));
    if (cMcasts == 0)
        return 0;

    if (ckNextMulticast)
        pEvents->UnScheduleEvent (ckNextMulticast);

    if (! (ckNextMulticast = pEvents->ScheduleEvent (MulticastThread, NULL, 0)))
        return ERROR_OUTOFMEMORY;

    return ERROR_SUCCESS;
}

int TimeState::Start (void) {
    DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Service starting\r\n"));

    pEvents = new SVSThreadPool (5);
    if (! pEvents) {
        DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Start error: Out of memory allocating threads\r\n"));
        return ERROR_OUTOFMEMORY;
    }

    if (fHaveServer) {
        ADDRINFO aiHints;
        ADDRINFO *paiLocal = NULL;

        memset(&aiHints, 0, sizeof(aiHints));
        aiHints.ai_family = PF_UNSPEC;
        aiHints.ai_socktype = SOCK_DGRAM;
        aiHints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;

        iSock = 0;

        int iErr = ERROR_SUCCESS;

        if (0 != getaddrinfo(NULL, NTP_PORT_A, &aiHints, &paiLocal)) {
            iErr = GetLastError ();
            DEBUGMSG(ZONE_ERROR,(L"[TIMESVC] Start error: getaddrinfo() fails, GLE=0x%08x\r\n",iErr));
        } else {
            for (ADDRINFO *paiTrav = paiLocal; paiTrav && (iSock < SVSUTIL_ARRLEN(saServer)) ; paiTrav = paiTrav->ai_next) {
                if (INVALID_SOCKET == (saServer[iSock] = socket(paiTrav->ai_family, paiTrav->ai_socktype, paiTrav->ai_protocol)))
                    continue;

                if (SOCKET_ERROR == bind(saServer[iSock], paiTrav->ai_addr, paiTrav->ai_addrlen)) {
                    iErr = GetLastError ();
                    DEBUGMSG(ZONE_ERROR,(L"[TIMESVC] Start error: failed to bind socket, GLE=0x%08x\r\n",iErr));
                    closesocket (saServer[iSock]);
                    continue;
                }

                ++iSock;
            }
        }

        if (paiLocal)
            freeaddrinfo(paiLocal);

        if (iSock == 0) {
            DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Start error: failure to register time server (error %d)\r\n", iErr));

            delete pEvents;
            ReInit ();

            return iErr;
        }


        if ( ! pEvents->ScheduleEvent (RxThread, NULL)) {
            for (int i = 0 ; i < iSock ; ++i)
                closesocket (saServer[i]);

            SVSThreadPool *pp = pEvents;
            ReInit ();

            DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Start error: Out of memory scheduling server thread\r\n"));

            Unlock ();
            delete pp;
            Lock ();

            return ERROR_OUTOFMEMORY;
        }
    }

    if (ERROR_SUCCESS != UpdateNowOrLater (Now)) {
        for (int i = 0 ; i < iSock ; ++i)
            closesocket (saServer[i]);

        SVSThreadPool *pp = pEvents;

        DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Start error: Out of memory scheduling time update\r\n"));

        ReInit ();

        Unlock ();
        delete pp;
        Lock ();

        return ERROR_OUTOFMEMORY;
    }

    fStarted = TRUE;

    DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Service started successfully\r\n"));

    return ERROR_SUCCESS;
}

SVSThreadPool *TimeState::Stop (void) {
    DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Stopping service\r\n"));
    fStarted = FALSE;

    for (int i = 0 ; i < iSock ; ++i) {
        closesocket (saServer[i]);
        saServer[i] = INVALID_SOCKET;
    }

    iSock = 0;

    SVSThreadPool *pp = pEvents;
    pEvents = NULL;
    return pp;
}

///////////////////////////////////////////////////////////////////////
//
//        Globals
//
//
static TimeState *gpTS = NULL;

///////////////////////////////////////////////////////////////////////
//
//        Service functions
//
//    Note: NTP time conversion functions derived from XP's NTP sources (ntpbase.*)
//
static inline unsigned char EndianSwap (unsigned char x) {
    return x;
}

static inline unsigned short EndianSwap (unsigned short x) {
    return (EndianSwap ((unsigned char)x) << 8) | EndianSwap ((unsigned char)(x >> 8));
}

static inline unsigned int EndianSwap (unsigned int x) {
    return (EndianSwap ((unsigned short)x) << 16) | EndianSwap ((unsigned short)(x >> 16));
}

static inline unsigned __int64 EndianSwap (unsigned __int64 x) {
    return (((unsigned __int64)EndianSwap ((unsigned int)x)) << 32) | EndianSwap ((unsigned int)(x >> 32));
}

static unsigned __int64 NtTimeEpochFromNtpTimeEpoch(unsigned __int64 te) {
    //return (qwNtpTime*(10**7)/(2**32))+NTPTIMEOFFSET
    // ==>
    //return (qwNtpTime*( 5**7)/(2**25))+NTPTIMEOFFSET
    // ==>
    //return ((qwNTPtime*FIVETOTHESEVETH)>>25)+NTPTIMEOFFSET;  
    // ==>
    // Note: 'After' division, we round (instead of truncate) the result for better precision
    unsigned __int64 qwNtpTime=EndianSwap(te);
    unsigned __int64 qwTemp=((qwNtpTime&0x00000000FFFFFFFF)*FIVETOTHESEVETH)+0x0000000001000000; //rounding step: if 25th bit is set, round up;

    return (qwTemp>>25) + ((qwNtpTime&0xFFFFFFFF00000000)>>25)*FIVETOTHESEVETH + NTPTIMEOFFSET;
}

static unsigned __int64 NtpTimeEpochFromNtTimeEpoch(unsigned __int64 te) {
    //return (qwNtTime-NTPTIMEOFFSET)*(2**32)/(10**7);
    // ==>
    //return (qwNtTime-NTPTIMEOFFSET)*(2**25)/(5**7);
    // ==>
    //return ((qwNtTime-NTPTIMEOFFSET)<<25)/FIVETOTHESEVETH);
    // ==>
    // Note: The high bit is lost (and assumed to be zero) but 
    //       it will not be set for another 29,000 years (around year 31587). No big loss.
    // Note: 'After' division, we truncate the result because the precision of NTP already excessive
    unsigned __int64 qwTemp=(te-NTPTIMEOFFSET)<<1; 
    unsigned __int64 qwHigh=qwTemp>>8;
    unsigned __int64 qwLow=(qwHigh%FIVETOTHESEVETH)<<32 | (qwTemp&0x00000000000000FF)<<24;

    return EndianSwap(((qwHigh/FIVETOTHESEVETH)<<32) | (qwLow/FIVETOTHESEVETH));
}

static void GetCurrTimeNtp (unsigned __int64 *ptimeXX) {
    SYSTEMTIME st;
    GetSystemTime (&st);

    union {
        FILETIME ft;
        unsigned __int64 ui64ft;
    };

    SystemTimeToFileTime (&st, &ft);

    *ptimeXX = NtpTimeEpochFromNtTimeEpoch (ui64ft);
}

static int Exec (LPTHREAD_START_ROUTINE pfunc, void *pvControlBlock = NULL) {
    HANDLE h = CreateThread (NULL, 0, pfunc, pvControlBlock, 0, NULL);
    if (! h)
        return GetLastError ();

    WaitForSingleObject (h, INFINITE);

    DWORD dw = ERROR_INTERNAL_ERROR;
    GetExitCodeThread (h, &dw);
    CloseHandle (h);

    return (int)dw;
}

#if defined (DEBUG) || defined (_DEBUG)
static void DumpPacket (NTP_REQUEST *pPacket) {
    unsigned int li = pPacket->li ();
    unsigned int vn = pPacket->vn ();
    unsigned int mode = pPacket->mode ();
    unsigned int poll = pPacket->poll ();
    unsigned int stratum = pPacket->stratum ();
    unsigned int precision = pPacket->precision ();
    unsigned int root_delay = pPacket->root_delay ();
    unsigned int root_dispersion = pPacket->root_dispersion ();
    unsigned int ref_id = pPacket->ref_id ();
    unsigned __int64 ref_stamp = pPacket->ref_stamp ();
    unsigned __int64 orig_stamp = pPacket->orig_stamp ();
    unsigned __int64 recv_stamp = pPacket->recv_stamp ();
    unsigned __int64 trans_stamp = pPacket->trans_stamp ();

    DEBUGMSG(ZONE_PACKETS, (L"\r\nSNTP Packet:\r\n"));

    WCHAR *pText = L"";

    switch (li) {
        case 0:
            pText = L"No warning";
            break;
        case 1:
            pText = L"Last minute has 61 seconds";
            break;
        case 2:
            pText = L"Last minute has 59 seconds";
            break;
        case 3:
            pText = L"Alarm condition (clock not synchronized)";
            break;
        default:
            pText = L"Illegal or reserved code";
            break;
    }

    DEBUGMSG(ZONE_PACKETS, (L"Leap      : %d (%s)\r\n", li, pText));
    DEBUGMSG(ZONE_PACKETS, (L"Version   : %d\r\n", vn));

    pText = L"";
    switch (mode) {
        case 1:
            pText = L"symmetric active";
            break;
        case 2:
            pText = L"symmetric passive";
            break;
        case 3:
            pText = L"client";
            break;
        case 4:
            pText = L"server";
            break;
        case 5:
            pText = L"broadcast";
            break;
        case 6:
            pText = L"NTP control";
            break;
        case 7:
            pText = L"private use";
            break;
        default:
            pText = L"illegal or reserved code";
            break;
    }

    DEBUGMSG(ZONE_PACKETS, (L"Mode      : %d (%s)\r\n", mode, pText));
    DEBUGMSG(ZONE_PACKETS, (L"Stratum   : %d\r\n", stratum));
    DEBUGMSG(ZONE_PACKETS, (L"Poll      : %d\r\n", poll));
    DEBUGMSG(ZONE_PACKETS, (L"Precision : %d\r\n", poll));
    DEBUGMSG(ZONE_PACKETS, (L"Root delay: 0x%08x (%d sec)\r\n", root_delay, ((int)root_delay)/4));
    DEBUGMSG(ZONE_PACKETS, (L"Root disp : 0x%08x (%d sec)\r\n", root_dispersion, ((int)root_dispersion)/4));
    in_addr ia;
    ia.S_un.S_addr = ref_id;
    DEBUGMSG(ZONE_PACKETS, (L"Refid     : %08x (or %a)\r\n", ref_id, inet_ntoa (ia)));

    union {
        unsigned __int64 ui64;
        FILETIME ft;
    };

    SYSTEMTIME xst;

    ui64 = NtTimeEpochFromNtpTimeEpoch (ref_stamp);
    FileTimeToSystemTime ((FILETIME *)&ui64, &xst);
    DEBUGMSG(ZONE_PACKETS, (L"Reference time: %02d/%02d/%d %02d:%02d:%02d.%03d\n", xst.wMonth, xst.wDay, xst.wYear, xst.wHour, xst.wMinute, xst.wSecond, xst.wMilliseconds));

    ui64 = NtTimeEpochFromNtpTimeEpoch (orig_stamp);
    FileTimeToSystemTime ((FILETIME *)&ui64, &xst);
    DEBUGMSG(ZONE_PACKETS, (L"Origination time: %02d/%02d/%d %02d:%02d:%02d.%03d\n", xst.wMonth, xst.wDay, xst.wYear, xst.wHour, xst.wMinute, xst.wSecond, xst.wMilliseconds));

    ui64 = NtTimeEpochFromNtpTimeEpoch (recv_stamp);
    FileTimeToSystemTime ((FILETIME *)&ui64, &xst);
    DEBUGMSG(ZONE_PACKETS, (L"Received time: %02d/%02d/%d %02d:%02d:%02d.%03d\n", xst.wMonth, xst.wDay, xst.wYear, xst.wHour, xst.wMinute, xst.wSecond, xst.wMilliseconds));

    ui64 = NtTimeEpochFromNtpTimeEpoch (trans_stamp);
    FileTimeToSystemTime ((FILETIME *)&ui64, &xst);
    DEBUGMSG(ZONE_PACKETS, (L"Transmitted time: %02d/%02d/%d %02d:%02d:%02d.%03d\n", xst.wMonth, xst.wDay, xst.wYear, xst.wHour, xst.wMinute, xst.wSecond, xst.wMilliseconds));
    DEBUGMSG(ZONE_PACKETS, (L"\r\n\r\n"));
}
#endif

///////////////////////////////////////////////////////////////////////
//
//        Threads
//
//
static DWORD WINAPI MulticastThread (LPVOID lpUnused) {
    DEBUGMSG(ZONE_SERVER, (L"[TIMESVC] Multicast Event\r\n"));
    int fSuccess = FALSE;

    if (! gpTS) {
        DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Multicast: service not initialized!\r\n"));
        return 0;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -