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

📄 sntp.cxx

📁 Windows CE 6.0 Server 源码
💻 CXX
📖 第 1 页 / 共 4 页
字号:
    gpTS->Lock ();

    if (! gpTS->IsStarted ()) {
        DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Time Refresh: service not active!\r\n"));
        gpTS->Unlock ();

        return 0;
    }

    int fTimeAccurate = gpTS->IsTimeAccurate();

    unsigned int uiPollInterval = gpTS->dwMulticastPeriodMS / 1000;
    unsigned int poll = 1;

    while (poll < uiPollInterval)
        poll <<= 1;
    poll >>= 1;

    unsigned int ref = (unsigned int)gpTS->llLastSyncTimeXX & 0xffffffff;
    unsigned __int64 ref_ts = gpTS->llLastSyncTimeXX;

    gpTS->Unlock ();

    if (! fTimeAccurate) {
        DEBUGMSG(ZONE_SERVER, (L"[TIMESVC] Multicast server does not have accurate time\r\n"));
        return 0;
    }

    NTP_REQUEST dg;
    memset (&dg, 0, sizeof(dg));
    dg.set_vn (4);
    dg.set_mode (5);
    dg.set_stratum (2);
    dg.set_poll (poll);
    dg.set_precision((unsigned int)-7);
    dg.set_ref_id (ref);
    dg.set_ref_stamp (ref_ts);

    int icast = 0;

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

        gpTS->Lock ();

        if (! gpTS->IsStarted ()) {
            DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Multicast: service not active!\r\n"));
            gpTS->Unlock ();

            return 0;
        }

        if (icast >= gpTS->cMcasts)
            break;

        char hostname[DNS_MAX_NAME_BUFFER_LENGTH];
        strcpy (hostname, gpTS->sntp_mcasts[icast++]);

        gpTS->Unlock ();

        DEBUGMSG(ZONE_SERVER, (L"[TIMESVC] Multicast: multicasting to %a\r\n", hostname));

        ADDRINFO aiHints;
        ADDRINFO *paiLocal = NULL;

        memset(&aiHints, 0, sizeof(aiHints));
        aiHints.ai_family = PF_UNSPEC;
        aiHints.ai_socktype = SOCK_DGRAM;
        aiHints.ai_flags = 0; // Or AI_NUMERICHOST; ?

        if (0 != getaddrinfo(hostname, NTP_PORT_A, &aiHints, &paiLocal)) {
            DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Multicast: host %a is not reachable\r\n", hostname));
            continue;
        }

        for (ADDRINFO *paiTrav = paiLocal; paiTrav ; paiTrav = paiTrav->ai_next) {
            SOCKET s;
            if (INVALID_SOCKET == (s = socket(paiTrav->ai_family, paiTrav->ai_socktype, paiTrav->ai_protocol)))
                continue;

            int on = 1;
            if (0 != setsockopt (s, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on))) {
                DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Multicast: could not set broadcast option, error %d\n", GetLastError ()));
            }

            unsigned __int64 llTXX;
            GetCurrTimeNtp (&llTXX);

            dg.set_trans_stamp (llTXX);

            int iRet = sendto (s, (char *)&dg, sizeof(dg), 0, paiTrav->ai_addr, paiTrav->ai_addrlen);

            closesocket (s);

            if (sizeof(dg) == iRet)
                break;

            DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Multicast failed: error %d; retrying different address family\n", GetLastError ()));
        }

        if (paiLocal)
            freeaddrinfo(paiLocal);
    }

    if (gpTS->dwMulticastPeriodMS > 1000)
        gpTS->ckNextMulticast = gpTS->pEvents->ScheduleEvent (MulticastThread, NULL, gpTS->dwMulticastPeriodMS);

    gpTS->Unlock ();

    DEBUGMSG(ZONE_SERVER, (L"[TIMESVC] Multicast event processing completed\r\n"));
    return 0;
}

static int GetOffsetFromServer (char *hostname, __int64 *pllOffset) {
    ADDRINFO aiHints;
    ADDRINFO *paiLocal = NULL;

    memset(&aiHints, 0, sizeof(aiHints));
    aiHints.ai_family = PF_UNSPEC;
    aiHints.ai_socktype = SOCK_DGRAM;
    aiHints.ai_flags = 0; // Or AI_NUMERICHOST; ?

    if (0 != getaddrinfo(hostname, NTP_PORT_A, &aiHints, &paiLocal)) {
        DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Time Refresh: host %a is not reachable\r\n", hostname));
        return FALSE;
    }

    for (ADDRINFO *paiTrav = paiLocal; paiTrav ; paiTrav = paiTrav->ai_next) {
        SOCKET s;
        if (INVALID_SOCKET == (s = socket(paiTrav->ai_family, paiTrav->ai_socktype, paiTrav->ai_protocol)))
            continue;

        for (int i = 0 ; i < 3 ; ++i) {
            DEBUGMSG(ZONE_CLIENT, (L"[TIMESVC] Time Refresh: querying server %a\r\n", hostname));

            NTP_REQUEST dg;
            memset (&dg, 0, sizeof(dg));
            dg.set_vn (4);
            dg.set_mode (3);

            unsigned __int64 llT1XX;
            GetCurrTimeNtp (&llT1XX);

            dg.set_trans_stamp (llT1XX);

#if defined (DEBUG) || defined (_DEBUG)
            DEBUGMSG (ZONE_PACKETS, (L"[TIMESVC] Sending SNTP request\r\n"));
            DumpPacket (&dg);
#endif

            if (sizeof (dg) == sendto (s, (char *)&dg, sizeof(dg), 0, paiTrav->ai_addr, paiTrav->ai_addrlen)) {
                DEBUGMSG(ZONE_CLIENT, (L"[TIMESVC] Time Refresh: sent request, awaiting response\r\n"));
                fd_set f;
                FD_ZERO (&f);
                FD_SET (s, &f);

                timeval tv;
                tv.tv_sec  = 3;
                tv.tv_usec = 0;

                if (select (0, &f, NULL, NULL, &tv) > 0) {
                    SOCKADDR_STORAGE sa;
                    int salen = sizeof(sa);
                    if (sizeof(dg) == recvfrom (s, (char *)&dg, sizeof(dg), 0, (sockaddr *)&sa, &salen)) {
                        unsigned __int64 llT4XX;
                        GetCurrTimeNtp (&llT4XX);

#if defined (DEBUG) || defined (_DEBUG)
                        DEBUGMSG (ZONE_PACKETS, (L"[TIMESVC] Received SNTP response\r\n"));
                        DumpPacket (&dg);
#endif

                        int fSuccess = FALSE;

                        if ((dg.li () != 3) && (llT1XX == dg.orig_stamp ())) {
                            unsigned __int64 llT2XX = dg.recv_stamp ();
                            unsigned __int64 llT3XX = dg.trans_stamp ();

                            unsigned __int64 llT1 = NtTimeEpochFromNtpTimeEpoch (llT1XX);
                            unsigned __int64 llT2 = NtTimeEpochFromNtpTimeEpoch (llT2XX);
                            unsigned __int64 llT3 = NtTimeEpochFromNtpTimeEpoch (llT3XX);
                            unsigned __int64 llT4 = NtTimeEpochFromNtpTimeEpoch (llT4XX);

                            *pllOffset = ((__int64)((llT2 - llT1) + (llT3 - llT4))) / 2;

                            fSuccess = TRUE;
                        } else {
                            DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Time Refresh: sntp server not synchronized\r\n"));
                        }

                        closesocket (s);

                        if (paiLocal)
                            freeaddrinfo(paiLocal);

                        return fSuccess;
                    } else {
                        DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Time Refresh: sntp server datagram size incorrect (or authentication requested)\r\n"));
                    }
                } else {
                    DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Time Refresh: sntp server response timeout (no SNTP on server?)\r\n"));
                }
            } else {
                DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Time Refresh: host %a unreachable\r\n", hostname));
            }

            closesocket (s);
        }
    }

    if (paiLocal)
        freeaddrinfo(paiLocal);

    return FALSE;
}

static int RefreshTimeFromServer (char *hostname, int fForceTime, DWORD dwMaxAdjustS, int *pfTimeChanged) {
    *pfTimeChanged = FALSE;

    __int64 llOffset;

    if (GetOffsetFromServer (hostname, &llOffset)) {
        int iOffsetSec = (int)(llOffset / 10000000);
        if (fForceTime || ((DWORD)abs (iOffsetSec) < dwMaxAdjustS)) {
            SYSTEMTIME st, st2;
            unsigned __int64 llTime;

            GetSystemTime (&st);
            SystemTimeToFileTime (&st, (FILETIME *)&llTime);
            llTime += llOffset;
            FileTimeToSystemTime ((FILETIME *)&llTime, &st2);

            // The system must be updated with whether we're DST or STD
            // before we update the system clock.  We're updating in UTC
            // but system clock will convert and save this as local time,
            // which means it will apply the DST/STD bias first.
            SetDaylightOrStandardTimeDST(&st2);
            SetSystemTime (&st2);

            DEBUGMSG(ZONE_CLIENT, (L"[TIMESVC] Time Refresh: time accepted. offset = %d s.\r\n", iOffsetSec));
            DEBUGMSG(ZONE_CLIENT, (L"[TIMESVC] Time Refresh: old time: %02d/%02d/%d %02d:%02d:%02d.%03d\r\n", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds));
            DEBUGMSG(ZONE_CLIENT, (L"[TIMESVC] Time Refresh: new time: %02d/%02d/%d %02d:%02d:%02d.%03d\r\n", st2.wMonth, st2.wDay, st2.wYear, st2.wHour, st2.wMinute, st2.wSecond, st2.wMilliseconds));

            if ((DWORD)abs (iOffsetSec) > MIN_TIMEUPDATE)
                *pfTimeChanged = TRUE;

            return TRUE;
        } else {
            DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Time Refresh: time indicated by server is not within allowed adjustment boundaries (offset = %d s)\r\n", iOffsetSec));
        }
    }

    return FALSE;
}

static DWORD WINAPI TimeRefreshThread (LPVOID lpUnused) {
    DEBUGMSG(ZONE_CLIENT, (L"[TIMESVC] Refresh Event\r\n"));

    int fSuccess = FALSE;
    int fTimeChanged = FALSE;
    int iSrv = 0;

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

        gpTS->Lock ();

        if (! gpTS->IsStarted ()) {
            DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Time Refresh: service not active!\r\n"));
            gpTS->Unlock ();

            return 0;
        }

        if (iSrv >= gpTS->cServers) {
            DEBUGMSG(ZONE_WARNING, (L"[TIMESVC] Time Refresh: all servers queried, but time not updated.\r\n"));
            gpTS->Unlock ();

            break;
        }

        int fForceTime = gpTS->fForceTimeToServer;
        DWORD dwMaxAdjustS = gpTS->dwAdjustThreshMS / 1000;

        char hostname[DNS_MAX_NAME_BUFFER_LENGTH];
        memcpy (hostname, gpTS->sntp_servers[iSrv++], sizeof(hostname));

        gpTS->Unlock ();

        fSuccess = RefreshTimeFromServer (hostname, fForceTime, dwMaxAdjustS, &fTimeChanged);
    }

    if (gpTS) {
        gpTS->Lock ();

        if (gpTS->IsStarted ()) {
            if (fSuccess) {
                GetCurrTimeNtp (&gpTS->llLastSyncTimeXX);
                gpTS->fRefreshRequired = FALSE;

                gpTS->UpdateNowOrLater (Later);

                gpTS->fForceTimeToServer = FALSE;

                DEBUGMSG(ZONE_CLIENT, (L"[TIMESVC] Time successfully refreshed\r\n"));

                if (fTimeChanged || (gpTS->ckNextMulticast == 0))
                    gpTS->TimeChanged ();
            } else {
                DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Time Refresh failed, rescheduling\r\n"));
                gpTS->fRefreshRequired = TRUE;
                gpTS->UpdateNowOrLater (Shortly);

				if(gpTS->ckNextMulticast == 0) 
					gpTS->TimeChanged();
            }
        }

        gpTS->Unlock ();
    }

    DEBUGMSG(ZONE_CLIENT, (L"[TIMESVC] Time Refresh event processing completed\r\n"));

    return 0;
}

static DWORD WINAPI RxThread (LPVOID lpUnused) {
    DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Server thread started\r\n"));

    for ( ; ; ) {
        if (! gpTS) {
            DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Server: Not initialized, quitting\r\n"));
            return 0;
        }

        gpTS->Lock ();

        if (! gpTS->IsStarted ()) {
            DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Server: Not active, quitting\r\n"));
            gpTS->Unlock ();

            return 0;
        }



        fd_set sockSet;
        FD_ZERO(&sockSet);
        for (int i = 0; i < gpTS->iSock; ++i)
            FD_SET(gpTS->saServer[i], &sockSet);

        gpTS->Unlock ();


        int iSockReady = select (0,&sockSet,NULL,NULL,NULL);
        if (iSockReady == 0 || iSockReady == SOCKET_ERROR) {
            DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Server: select failed, error=%d\r\n", GetLastError ()));
            break;
        }

        for (i = 0; i < iSockReady; ++i) {
            NTP_REQUEST    dg;

            SOCKADDR_STORAGE sa;
            int salen = sizeof(sa);
            int iRecv = recvfrom (sockSet.fd_array[i], (char *)&dg, sizeof(dg), 0, (sockaddr *)&sa, &salen);

            if (iRecv <= 0) {
                DEBUGMSG(ZONE_ERROR, (L"[TIMESVC] Server: receive failed, error=%d\r\n", GetLastError ()));
                break;
            }

            if (iRecv != sizeof(dg)) {
                DEBUGMSG(ZONE_SERVER, (L"[TIMESVC] Server: size mismatch, packet ignored\r\n"));
                continue;
            }

#if defined (DEBUG) || defined (_DEBUG)
            DEBUGMSG(ZONE_PACKETS, (L"[TIMESVC] Received SNTP request\r\n"));
            DumpPacket (&dg);
#endif

            if (dg.mode () == 3) {    //client
                dg.set_mode (4);    //server
            } else if (dg.mode () == 1) {    // symmetric, active
                dg.set_mode(1);                // symmetric, passive
            } else {
                DEBUGMSG(ZONE_SERVER, (L"[TIMESVC] Server: Not a request, aborting\r\n"));
                continue;
            }

            dg.set_root_delay (0);
            dg.set_root_dispersion (0);
            dg.set_precision((unsigned int)-7);

            unsigned __int64 llOrigTimeXX = dg.trans_stamp ();
            dg.set_orig_stamp (llOrigTimeXX);

            unsigned __int64 llRecvTimeXX;
            GetCurrTimeNtp (&llRecvTimeXX);

            dg.set_recv_stamp (llRecvTimeXX);
            dg.set_trans_stamp (llRecvTimeXX);

            if (! gpTS)
                break;

            gpTS->Lock ();
            dg.set_ref_stamp (gpTS->llLastSyncTimeXX);
            dg.set_ref_id ((unsigned int)gpTS->llLastSyncTimeXX);

            if (gpTS->IsTimeAccurate()) {
                dg.set_li (0);
                dg.set_stratum (2);
            } else {
                dg.set_li (3);
                dg.set_stratum (15);
            }
            gpTS->Unlock ();

            sendto (sockSet.fd_array[i], (char *)&dg, sizeof(dg), 0, (sockaddr *)&sa, salen);

#if defined (DEBUG) || defined (_DEBUG)
            DEBUGMSG(ZONE_PACKETS, (L"[TIMESVC] Sent SNTP response\r\n"));
            DumpPacket (&dg);
#endif
        }
    }

    DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Server Thread exited\r\n"));
    return 0;
}

///////////////////////////////////////////////////////////////////////
//
//        Interface, initialization, management
//
//
static DWORD WINAPI SyncTime (LPVOID dwUnused) {
    DEBUGMSG(ZONE_TRACE, (L"[TIMESVC] Time update request from OS\r\n"));

    int iErr = ERROR_SERVICE_DOES_NOT_EXIST;
    if (gpTS) {
        gpTS->Lock ();
        iErr = ERROR_SUCCESS;

        if (! gpTS->IsStarted())

⌨️ 快捷键说明

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