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

org.kurento.jsonrpc.internal.server.PingWatchdogManager Maven / Gradle / Ivy

/*
 * (C) Copyright 2016 Kurento (http://kurento.org/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.kurento.jsonrpc.internal.server;

import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.TaskScheduler;

public class PingWatchdogManager {

  private static final Logger log = LoggerFactory.getLogger(PingWatchdogManager.class);

  public interface NativeSessionCloser {
    public void closeSession(String transportId);
  }

  private static final long NUM_NO_PINGS_TO_CLOSE = 3;

  public class PingWatchdogSession {

    private static final long MAX_PING_INTERVAL = 20000;

    private String transportId;
    private String sessionId;

    private long pingInterval = -1;

    private volatile ScheduledFuture lastTask;

    private Runnable closeSessionTask = new Runnable() {
      @Override
      public void run() {
        log.debug("Closing session with sessionId={} and transportId={} for not receiving ping in {}"
            + " millis", sessionId, transportId, pingInterval * NUM_NO_PINGS_TO_CLOSE);
        closer.closeSession(transportId);
      }
    };

    public PingWatchdogSession(String transportId) {
      this.transportId = transportId;
    }

    public void pingReceived(long interval) {

      if (pingInterval == -1) {

        if (interval == -1) {
          pingInterval = MAX_PING_INTERVAL;
          log.warn("Received first ping request without 'interval'");
        } else {
          pingInterval = interval;
        }

        log.debug(
            "Setting ping interval to {}" + " millis in session with transportId={}. "
                + "Connection is closed if a ping is not received in {}x{}={} millis",
            pingInterval, this.transportId, pingInterval, NUM_NO_PINGS_TO_CLOSE,
            NUM_NO_PINGS_TO_CLOSE * pingInterval);
      }

      activateSessionCloser();
    }

    private void activateSessionCloser() {

      disablePingWatchdog();

      lastTask = taskScheduler.schedule(closeSessionTask,
          new Date(System.currentTimeMillis() + NUM_NO_PINGS_TO_CLOSE * pingInterval));
    }

    public void setSessionId(String sessionId) {
      this.sessionId = sessionId;
    }

    public void setTransportId(String transportId) {
      this.transportId = transportId;
      disablePingWatchdog();

      if (pingWachdog) {
        if (pingInterval != -1) {
          log.debug("Setting new transportId={} for sessionId={}. "
              + "Restarting timer to consider disconnected client if pings are not received in {}"
              + " millis", transportId, sessionId, NUM_NO_PINGS_TO_CLOSE * pingInterval);
          activateSessionCloser();
        }
      }
    }

    public void disablePingWatchdog() {
      if (lastTask != null) {
        lastTask.cancel(false);
      }
    }
  }

  private ConcurrentHashMap sessions = new ConcurrentHashMap<>();
  private boolean pingWachdog = false;
  private TaskScheduler taskScheduler;
  private NativeSessionCloser closer;

  public PingWatchdogManager(TaskScheduler taskScheduler, NativeSessionCloser closer) {
    this.taskScheduler = taskScheduler;
    this.closer = closer;
  }

  public void associateSessionId(String transportId, String sessionId) {
    if (pingWachdog) {
      PingWatchdogSession session = getOrCreatePingSession(transportId);
      session.setSessionId(sessionId);
    }
  }

  public void pingReceived(String transportId, long interval) {
    if (pingWachdog) {
      PingWatchdogSession session = getOrCreatePingSession(transportId);
      session.pingReceived(interval);
    }
  }

  // TODO Improve concurrency
  private synchronized PingWatchdogSession getOrCreatePingSession(String transportId) {
    PingWatchdogSession session = sessions.get(transportId);
    if (session == null) {
      log.debug("Created PingWatchdogSession for transportId {}", transportId);
      session = new PingWatchdogSession(transportId);
      sessions.put(transportId, session);
    }
    return session;
  }

  public void setPingWatchdog(boolean pingWachdog) {
    this.pingWachdog = pingWachdog;
  }

  public void removeSession(ServerSession session) {
    log.debug("Removed PingWatchdogSession for transportId {}", session.getTransportId());
    PingWatchdogSession pingSession = sessions.remove(session.getTransportId());
    if (pingSession != null) {
      pingSession.disablePingWatchdog();
    }
  }

  public synchronized void updateTransportId(String transportId, String oldTransportId) {
    PingWatchdogSession session = sessions.remove(oldTransportId);
    if (session != null) {
      log.debug("Updated with new transportId {} the session with old transportId {}", transportId,
          oldTransportId);
      session.setTransportId(transportId);
      sessions.put(transportId, session);
    } else {
      if (pingWachdog) {
        log.warn("Trying to update transport for unexisting session with oldTransportId {}",
            oldTransportId);
      }
    }
  }

  public void disablePingWatchdogForSession(String transportId) {
    PingWatchdogSession session = sessions.get(transportId);
    if (session != null) {
      log.debug("Disabling PingWatchdog for session with transportId {}", transportId);
      session.disablePingWatchdog();
    } else {
      if (pingWachdog) {
        log.warn("Trying to disable PingWatchdog for unexisting session with transportId {}",
            transportId);
      }
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy