/*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If
* not, see .
*/
package net.sf.l2j.loginserver;
import java.net.InetAddress;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import net.sf.l2j.loginserver.serverpackets.Init;
import org.mmocore.network.IAcceptFilter;
import org.mmocore.network.IClientFactory;
import org.mmocore.network.IMMOExecutor;
import org.mmocore.network.MMOConnection;
import org.mmocore.network.ReceivablePacket;
/**
*
* @author KenM
*/
public class SelectorHelper extends Thread implements IMMOExecutor,
IClientFactory, IAcceptFilter
{
private HashMap _ipFloodMap;
private ThreadPoolExecutor _generalPacketsThreadPool;
public SelectorHelper()
{
_generalPacketsThreadPool = new ThreadPoolExecutor(4, 6, 15L, TimeUnit.SECONDS, new LinkedBlockingQueue());
_ipFloodMap = new HashMap();
super.setDaemon(true);
super.start();
}
/**
*
* @see org.mmocore.network.IMMOExecutor#execute(org.mmocore.network.ReceivablePacket)
*/
public void execute(ReceivablePacket packet)
{
_generalPacketsThreadPool.execute(packet);
}
/**
*
* @see org.mmocore.network.IClientFactory#create(org.mmocore.network.MMOConnection)
*/
public L2LoginClient create(MMOConnection con)
{
L2LoginClient client = new L2LoginClient(con);
client.sendPacket(new Init(client));
return client;
}
/**
*
* @see org.mmocore.network.IAcceptFilter#accept(java.nio.channels.SocketChannel)
*/
public boolean accept(SocketChannel sc)
{
InetAddress addr = sc.socket().getInetAddress();
int h = hash(addr.getAddress());
long current = System.currentTimeMillis();
Flood f;
synchronized (_ipFloodMap)
{
f = _ipFloodMap.get(h);
}
if (f != null)
{
if (f.trys == -1)
{
f.lastAccess = current;
return false;
}
if (f.lastAccess + 1000 > current)
{
f.lastAccess = current;
if (f.trys >= 3)
{
f.trys = -1;
return false;
}
f.trys++;
}
else
{
f.lastAccess = current;
}
}
else
{
synchronized (_ipFloodMap)
{
_ipFloodMap.put(h, new Flood());
}
}
return !LoginController.getInstance().isBannedAddress(addr);
}
/**
*
* @param ip
* @return
*/
private int hash(byte[] ip)
{
return ip[0] & 0xFF | ip[1] << 8 & 0xFF00 | ip[2] << 16 & 0xFF0000 | ip[3] << 24
& 0xFF000000;
}
private class Flood
{
long lastAccess;
int trys;
Flood()
{
lastAccess = System.currentTimeMillis();
trys = 0;
}
}
/**
*
* @see java.lang.Thread#run()
*/
@Override
public void run()
{
while (true)
{
long reference = System.currentTimeMillis() - (1000 * 300);
ArrayList toRemove = new ArrayList(50);
synchronized (_ipFloodMap)
{
for (Entry e : _ipFloodMap.entrySet())
{
Flood f = e.getValue();
if (f.lastAccess < reference)
toRemove.add(e.getKey());
}
}
synchronized (_ipFloodMap)
{
for (Integer i : toRemove)
{
_ipFloodMap.remove(i);
}
}
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
}
}
}
}