Beispiel #1
0
        void HandleTimeSyncResponse(TimeSyncResponse timeSyncResponse)
        {
            if (!_pendingTimeSyncRequests.ContainsKey(timeSyncResponse.SequenceIndex))
            {
                return;
            }

            uint serverTimeAtSent = _pendingTimeSyncRequests.LookupByKey(timeSyncResponse.SequenceIndex);

            _pendingTimeSyncRequests.Remove(timeSyncResponse.SequenceIndex);

            // time it took for the request to travel to the client, for the client to process it and reply and for response to travel back to the server.
            // we are going to make 2 assumptions:
            // 1) we assume that the request processing time equals 0.
            // 2) we assume that the packet took as much time to travel from server to client than it took to travel from client to server.
            uint roundTripDuration = Time.GetMSTimeDiff(serverTimeAtSent, timeSyncResponse.GetReceivedTime());
            uint lagDelay          = roundTripDuration / 2;

            /*
             * clockDelta = serverTime - clientTime
             * where
             * serverTime: time that was displayed on the clock of the SERVER at the moment when the client processed the SMSG_TIME_SYNC_REQUEST packet.
             * clientTime:  time that was displayed on the clock of the CLIENT at the moment when the client processed the SMSG_TIME_SYNC_REQUEST packet.
             *
             * Once clockDelta has been computed, we can compute the time of an event on server clock when we know the time of that same event on the client clock,
             * using the following relation:
             * serverTime = clockDelta + clientTime
             */
            long clockDelta = (long)(serverTimeAtSent + lagDelay) - (long)timeSyncResponse.ClientTime;

            _timeSyncClockDeltaQueue.PushFront(Tuple.Create(clockDelta, roundTripDuration));
            ComputeNewClockDelta();
        }
Beispiel #2
0
        private void HandleErroneousTimeSyncRequest(IBeaconSendingContext context, TimeSyncResponse response)
        {
            // if this is the initial sync try, we have to initialize the time provider
            // in every other case we keep the previous setting
            if (IsInitialTimeSync)
            {
                context.InitializeTimeSync(0, context.IsTimeSyncSupported);
            }

            if (BeaconSendingResponseUtil.IsTooManyRequestsResponse(response))
            {
                // server is currently overloaded, change to CaptureOff state temporarily
                context.NextState = new BeaconSendingCaptureOffState(response.GetRetryAfterInMilliseconds());
            }
            else if (context.IsTimeSyncSupported)
            {
                // in case of time sync failure when it's supported, go to capture off state
                context.NextState = new BeaconSendingCaptureOffState();
            }
            else
            {
                // otherwise set the next state based on the configuration
                SetNextState(context);
            }
        }
        public void StateTransitionToCaptureOffIsMadeIfTooManyRequestsResponseIsReceived()
        {
            // given
            var responseHeaders = new Dictionary <string, List <string> >
            {
                { Response.ResponseKeyRetryAfter, new List <string> {
                      "456"
                  } }
            };
            var response = new TimeSyncResponse(Substitute.For <ILogger>(), string.Empty, Response.HttpTooManyRequests, responseHeaders);

            httpClient.SendTimeSyncRequest().Returns(response);

            context.IsTimeSyncSupported.Returns(true);
            context.IsCaptureOn.Returns(true);

            AbstractBeaconSendingState capturedState = null;

            context.NextState = Arg.Do <AbstractBeaconSendingState>(x => capturedState = x);

            var target = new BeaconSendingTimeSyncState(true);

            // when
            target.Execute(context);

            // then
            context.ReceivedWithAnyArgs(1).NextState = null;
            Assert.That(capturedState, Is.Not.Null);
            Assert.That(capturedState, Is.InstanceOf <BeaconSendingCaptureOffState>());
            Assert.That(((BeaconSendingCaptureOffState)capturedState).sleepTimeInMilliseconds, Is.EqualTo(456 * 1000));
        }
        public void TimeSyncRequetsAreRetried()
        {
            // given
            var erroneousResponse = new TimeSyncResponse(Substitute.For <ILogger>(), string.Empty, Response.HttpBadRequest, new Dictionary <string, List <string> >());

            httpClient.SendTimeSyncRequest().Returns(
                // request 1 fails 2 times
                x => erroneousResponse,
                x => erroneousResponse,
                x => CreateValidTimeResponse(currentTime, 10),
                // request 2 fails 1 time
                x => erroneousResponse,
                x => CreateValidTimeResponse(currentTime, 10),
                // request 3 fails 4 times
                x => erroneousResponse,
                x => erroneousResponse,
                x => erroneousResponse,
                x => erroneousResponse,
                x => CreateValidTimeResponse(currentTime, 10),
                // request 4 fails 0 times
                x => CreateValidTimeResponse(currentTime, 10),
                // request 5 fails 1 time
                x => erroneousResponse,
                x => CreateValidTimeResponse(currentTime, 10)
                );

            // when
            var target = new BeaconSendingTimeSyncState();

            target.Execute(context);

            // then
            httpClient.Received(13).SendTimeSyncRequest();
        }
        public void InitCompleteIsNotCalledForNonInitialRequest()
        {
            // given
            var erroneousResponse = new TimeSyncResponse(Substitute.For <ILogger>(), string.Empty, Response.HttpBadRequest, new Dictionary <string, List <string> >());

            httpClient.SendTimeSyncRequest().Returns(erroneousResponse); // alwasys return invalid response

            // when
            var target = new BeaconSendingTimeSyncState();

            target.Execute(context);

            // then
            context.DidNotReceive().InitCompleted(Arg.Any <bool>());
        }
Beispiel #6
0
        void HandleTimeSyncResponse(TimeSyncResponse packet)
        {
            Log.outDebug(LogFilter.Network, "CMSG_TIME_SYNC_RESP");

            if (packet.SequenceIndex != _player.m_timeSyncQueue.FirstOrDefault())
            {
                Log.outError(LogFilter.Network, "Wrong time sync counter from player {0} (cheater?)", _player.GetName());
            }

            Log.outDebug(LogFilter.Network, "Time sync received: counter {0}, client ticks {1}, time since last sync {2}", packet.SequenceIndex, packet.ClientTime, packet.ClientTime - _player.m_timeSyncClient);

            uint ourTicks = packet.ClientTime + (Time.GetMSTime() - _player.m_timeSyncServer);

            // diff should be small
            Log.outDebug(LogFilter.Network, "Our ticks: {0}, diff {1}, latency {2}", ourTicks, ourTicks - packet.ClientTime, GetLatency());

            _player.m_timeSyncClient = packet.ClientTime;
            _player.m_timeSyncQueue.Pop();
        }
        public void SleepTimeIsDoubledAndResetAfterSuccess()
        {
            // given
            var erroneousResponse = new TimeSyncResponse(Substitute.For <ILogger>(), string.Empty, Response.HttpBadRequest, new Dictionary <string, List <string> >());

            httpClient.SendTimeSyncRequest().Returns(
                // request 1 fails 2 times
                x => erroneousResponse,
                x => erroneousResponse,
                x => erroneousResponse,
                x => erroneousResponse,
                x => erroneousResponse,
                x => CreateValidTimeResponse(currentTime, 10),
                // request 2 fails 1 time
                x => erroneousResponse,
                // other requets do not fail
                x => CreateValidTimeResponse(currentTime, 10),
                x => CreateValidTimeResponse(currentTime, 10),
                x => CreateValidTimeResponse(currentTime, 10),
                x => CreateValidTimeResponse(currentTime, 10)
                );

            // when
            var target = new BeaconSendingTimeSyncState();

            target.Execute(context);

            // then
            httpClient.Received(11).SendTimeSyncRequest();
            context.Received(6).Sleep(Arg.Any <int>());
            Received.InOrder(() =>
            {
                // sleeps for first request
                context.Sleep(1000);  // start with 1 sec
                context.Sleep(2000);  // double
                context.Sleep(4000);  // double
                context.Sleep(8000);  // double
                context.Sleep(16000); // double
                // sleeps for second request
                context.Sleep(1000);  // start with 1 sec again
            });
        }