All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.luminis.quic.core.KeepAliveActor Maven / Gradle / Ivy

/*
 * Copyright © 2019, 2020, 2021, 2022, 2023 Peter Doornbosch
 *
 * This file is part of Kwik, an implementation of the QUIC protocol in Java.
 *
 * Kwik is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * Kwik 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 Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see .
 */
package net.luminis.quic.core;

import net.luminis.quic.frame.PingFrame;
import net.luminis.quic.send.Sender;

import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;

import static java.time.temporal.ChronoUnit.SECONDS;
import static net.luminis.quic.core.EncryptionLevel.App;


public class KeepAliveActor {

    private Clock clock;
    private final VersionHolder quicVersion;
    private final int keepAliveTime;
    private final Sender sender;
    private final Instant started;
    private final ScheduledExecutorService scheduler;
    private final int pingInterval;
    private volatile ScheduledFuture scheduledTask;

    /**
     * @param quicVersion
     * @param keepAliveTime       the time the connection should be kept alive in seconds
     * @param peerIdleTimeout     the idle timeout of the peer, in milliseconds
     * @param sender
     */
    public KeepAliveActor(VersionHolder quicVersion, int keepAliveTime, int peerIdleTimeout, Sender sender) {
        this(Clock.systemUTC(), quicVersion, keepAliveTime, peerIdleTimeout, sender, Executors.newScheduledThreadPool(1));
    }

    KeepAliveActor(Clock clock, VersionHolder quicVersion, int keepAliveTime, int peerIdleTimeout, Sender sender, ScheduledExecutorService scheduler) {
        this.clock = clock;
        this.quicVersion = quicVersion;
        this.keepAliveTime = keepAliveTime;
        this.sender = sender;
        this.scheduler = scheduler;

        started = clock.instant();
        pingInterval = peerIdleTimeout / 1000 / 2;

        scheduleNextPing();
    }

    private void ping() {
        sender.send(new PingFrame(quicVersion.getVersion()), App);
        sender.flush();

        scheduleNextPing();
    }

    private void scheduleNextPing() {
        Instant now = clock.instant();
        if (Duration.between(started, now).compareTo(Duration.of(keepAliveTime - pingInterval, SECONDS)) < 0) {
            scheduledTask = scheduler.schedule(() -> ping(), pingInterval, java.util.concurrent.TimeUnit.SECONDS);
        }
    }

    public void shutdown() {
        scheduler.shutdown();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy