| 288 | TimeSinceLastRecv = 1e6f; |
| 289 | } |
| 290 | bool UpdateAlive(const TUdpAddress& toAddress, float deltaT, float timeout, float* resMaxWaitTime) { |
| 291 | if (!FullSpeed) { |
| 292 | // create virtual packets during idle to avoid burst on transmit start |
| 293 | if (AvrgRTT > CONG_CTRL_MIN_RTT_FOR_BURST_REDUCTION) { |
| 294 | VirtualPackets = Max(VirtualPackets, Window - PacketsInFly - CONG_CTRL_ALLOWED_BURST_SIZE); |
| 295 | } |
| 296 | } else { |
| 297 | if (VirtualPackets > 0) { |
| 298 | if (Window <= CONG_CTRL_ALLOWED_BURST_SIZE) { |
| 299 | VirtualPackets = 0; |
| 300 | } |
| 301 | float xRTT = AvrgRTT == 0 ? CONG_CTRL_INITIAL_RTT : AvrgRTT; |
| 302 | float virtualPktsPerSecond = Window / xRTT; |
| 303 | VirtualPackets = Max(0.f, VirtualPackets - deltaT * virtualPktsPerSecond); |
| 304 | *resMaxWaitTime = Min(*resMaxWaitTime, 0.001f); // need to update virtual packets counter regularly |
| 305 | } |
| 306 | } |
| 307 | float currentRTT = GetRTT(); |
| 308 | FractionRecalc += deltaT; |
| 309 | if (FractionRecalc > currentRTT) { |
| 310 | int cycleCount = (int)(FractionRecalc / currentRTT); |
| 311 | FractionRecalc -= currentRTT * cycleCount; |
| 312 | WindowFraction = (NetAckRnd() & 1023) * (1 / 1023.0f) / cycleCount; |
| 313 | } |
| 314 | |
| 315 | if (MaxPacketRate > 0 && AvrgRTT > 0) { |
| 316 | float maxTimeWindow = CONG_CTRL_TIME_WINDOW_LIMIT_PERIOD * MaxPacketRate; |
| 317 | TimeWindow = Min(maxTimeWindow, TimeWindow + MaxPacketRate * deltaT); |
| 318 | } else |
| 319 | TimeWindow = CONG_CTRL_LARGE_TIME_WINDOW; |
| 320 | |
| 321 | // guarantee minimal send rate |
| 322 | if (currentRTT > CONG_CTRL_MINIMAL_SEND_INTERVAL * Window) { |
| 323 | Window = Max(CONG_CTRL_MIN_WINDOW, currentRTT / CONG_CTRL_MINIMAL_SEND_INTERVAL); |
| 324 | VirtualPackets = 0; |
| 325 | } |
| 326 | |
| 327 | TimeSinceLastFail += deltaT; |
| 328 | |
| 329 | //static int n; |
| 330 | //if ((++n & 127) == 0) |
| 331 | // printf("window = %g, fly = %g, VirtualPkts = %g, deltaT = %g, FailRate = %g FullSpeed = %d AvrgRTT = %g\n", |
| 332 | // Window, PacketsInFly, VirtualPackets, deltaT * 1000, FailRate, (int)FullSpeed, AvrgRTT * 1000); |
| 333 | |
| 334 | if (PacketsInFly > 0 || FullSpeed || DoCountTime) { |
| 335 | // считаем время только когда есть пакеты в полете |
| 336 | TimeSinceLastRecv += deltaT; |
| 337 | if (TimeSinceLastRecv > START_CHECK_PORT_DELAY) { |
| 338 | if (TimeSinceLastRecv < FINISH_CHECK_PORT_DELAY) { |
| 339 | TIntrusivePtr<TPortUnreachableTester> portTester; |
| 340 | with_lock (PortTesterLock) { |
| 341 | portTester = PortTester; |
| 342 | } |
| 343 | |
| 344 | if (!portTester && AtomicGet(ActivePortTestersCount) < N_PORT_TEST_COUNT_LIMIT) { |
| 345 | portTester = new TPortUnreachableTester(); |
| 346 | with_lock (PortTesterLock) { |
| 347 | PortTester = portTester; |