Package org.moparscape.msc.gs.connection.filter

Source Code of org.moparscape.msc.gs.connection.filter.PacketThrottler

package org.moparscape.msc.gs.connection.filter;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import net.jcip.annotations.ThreadSafe;

import org.apache.mina.common.IoFilterAdapter;
import org.apache.mina.common.IoSession;
import org.moparscape.msc.gs.Instance;
import org.moparscape.msc.gs.alert.AlertHandler;
import org.moparscape.msc.gs.config.Config;
import org.moparscape.msc.gs.event.DelayedEvent;
import org.moparscape.msc.gs.model.Player;
import org.moparscape.msc.gs.util.annotation.Singleton;

/**
*
* This filter will disconnect players that have exceeded the packet per second
* threshold, and if configured, send an alert.
*
* @author CodeForFame
*
*/
@ThreadSafe
@Singleton
public class PacketThrottler extends IoFilterAdapter {

  // ///////////////////////////////////////
  // /////// Singleton Boilerplate /////////
  // ///////////////////////////////////////

  private static final PacketThrottler instance = new PacketThrottler();

  public static PacketThrottler getInstance() {
    return instance;
  }

  // ///////////////////////////////////////
  // ///// Singleton Boilerplate End ///////
  // ///////////////////////////////////////

  /**
   * The map of username hashes to packet per second.
   */
  private Map<Long, Integer> playerToPacketCount = new HashMap<Long, Integer>();
    private final Lock lock = new ReentrantLock();

  private PacketThrottler() {
    // Clears the count every second, so we can check the packets per
    // second.
    Instance.getDelayedEventHandler().add(new DelayedEvent(null, 1000) {

      @Override
      public void run() {
//        playerToPacketCount.clear();
                try {
                    lock.lock();
                    playerToPacketCount.clear();
                }
                finally {
                    lock.unlock();
                }
      }

    });
  }

  @Override
  public void messageReceived(NextFilter nextFilter, IoSession session,
      Object message) {

        // TODO: FIX ME.

    Player player = (Player) session.getAttachment();
    if (session.isClosing() || player.destroyed()) {
      return;
    }

    int count = incrementAndGet(player.getUsernameHash());
    //System.out.println(count);
    if (count > Config.PACKET_PER_SECOND_THRESHOLD) {

      if (Config.PACKET_PER_SECOND_ALERT) {
        // If the player is initialized, then use the username,
        // otherwise use the IP.
        String s = (player.isInitialized() ? player.getUsername()
            : player.getCurrentIP())
            + " has exceeded the packet per second threshold";
        // Sends an alert with a priority of 2.
        AlertHandler.sendAlert(s, 2);
      }

      // Destroys the user and discards the packet.
      player.destroy(true);
      return;
    }

    nextFilter.messageReceived(session, message);
  }

  /**
   * Increments and returns the current count.
   *
   * @param hash
   *            - The hash of the player.
   */
  private int incrementAndGet(long hash) {
    final int count;

    // Even though operations are atomic, there are multiple, therefore it
    // needs to be synchronized.
        try {
            lock.lock();

            // If it is null, default to 0
      Integer i = playerToPacketCount.get(hash);
      if (i == null) {
        count = 1;
      } else {
        count = i + 1;
      }

      // Update/Create entry
      playerToPacketCount.put(hash, count);
        }
        finally {
            lock.unlock();
        }

    return count;
  }
}
TOP

Related Classes of org.moparscape.msc.gs.connection.filter.PacketThrottler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.