This commit is contained in:
166
trunk/java/com/l2jserver/loginserver/FloodProtectedListener.java
Normal file
166
trunk/java/com/l2jserver/loginserver/FloodProtectedListener.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javolution.util.FastMap;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public abstract class FloodProtectedListener extends Thread
|
||||
{
|
||||
private final Logger _log = Logger.getLogger(FloodProtectedListener.class.getName());
|
||||
private final Map<String, ForeignConnection> _floodProtection = new FastMap<>();
|
||||
private ServerSocket _serverSocket;
|
||||
|
||||
public FloodProtectedListener(String listenIp, int port) throws IOException
|
||||
{
|
||||
if (listenIp.equals("*"))
|
||||
{
|
||||
_serverSocket = new ServerSocket(port);
|
||||
}
|
||||
else
|
||||
{
|
||||
_serverSocket = new ServerSocket(port, 50, InetAddress.getByName(listenIp));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Socket connection = null;
|
||||
while (!isInterrupted())
|
||||
{
|
||||
try
|
||||
{
|
||||
connection = _serverSocket.accept();
|
||||
if (Config.FLOOD_PROTECTION)
|
||||
{
|
||||
ForeignConnection fConnection = _floodProtection.get(connection.getInetAddress().getHostAddress());
|
||||
if (fConnection != null)
|
||||
{
|
||||
fConnection.connectionNumber += 1;
|
||||
if (((fConnection.connectionNumber > Config.FAST_CONNECTION_LIMIT) && ((System.currentTimeMillis() - fConnection.lastConnection) < Config.NORMAL_CONNECTION_TIME)) || ((System.currentTimeMillis() - fConnection.lastConnection) < Config.FAST_CONNECTION_TIME) || (fConnection.connectionNumber > Config.MAX_CONNECTION_PER_IP))
|
||||
{
|
||||
fConnection.lastConnection = System.currentTimeMillis();
|
||||
connection.close();
|
||||
fConnection.connectionNumber -= 1;
|
||||
if (!fConnection.isFlooding)
|
||||
{
|
||||
_log.warning("Potential Flood from " + connection.getInetAddress().getHostAddress());
|
||||
}
|
||||
fConnection.isFlooding = true;
|
||||
continue;
|
||||
}
|
||||
if (fConnection.isFlooding) // if connection was flooding server but now passed the check
|
||||
{
|
||||
fConnection.isFlooding = false;
|
||||
_log.info(connection.getInetAddress().getHostAddress() + " is not considered as flooding anymore.");
|
||||
}
|
||||
fConnection.lastConnection = System.currentTimeMillis();
|
||||
}
|
||||
else
|
||||
{
|
||||
fConnection = new ForeignConnection(System.currentTimeMillis());
|
||||
_floodProtection.put(connection.getInetAddress().getHostAddress(), fConnection);
|
||||
}
|
||||
}
|
||||
|
||||
addClient(connection);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (isInterrupted())
|
||||
{
|
||||
// shutdown?
|
||||
try
|
||||
{
|
||||
_serverSocket.close();
|
||||
}
|
||||
catch (IOException io)
|
||||
{
|
||||
_log.log(Level.INFO, "", io);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static class ForeignConnection
|
||||
{
|
||||
public int connectionNumber;
|
||||
public long lastConnection;
|
||||
public boolean isFlooding = false;
|
||||
|
||||
/**
|
||||
* @param time
|
||||
*/
|
||||
public ForeignConnection(long time)
|
||||
{
|
||||
lastConnection = time;
|
||||
connectionNumber = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void addClient(Socket s);
|
||||
|
||||
public void removeFloodProtection(String ip)
|
||||
{
|
||||
if (!Config.FLOOD_PROTECTION)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ForeignConnection fConnection = _floodProtection.get(ip);
|
||||
if (fConnection != null)
|
||||
{
|
||||
fConnection.connectionNumber -= 1;
|
||||
if (fConnection.connectionNumber == 0)
|
||||
{
|
||||
_floodProtection.remove(ip);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.warning("Removing a flood protection for a GameServer that was not in the connection map??? :" + ip);
|
||||
}
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
try
|
||||
{
|
||||
_serverSocket.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.warning(getClass().getSimpleName() + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
52
trunk/java/com/l2jserver/loginserver/GameServerListener.java
Normal file
52
trunk/java/com/l2jserver/loginserver/GameServerListener.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.util.List;
|
||||
|
||||
import javolution.util.FastList;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
|
||||
/**
|
||||
* @author KenM
|
||||
*/
|
||||
public class GameServerListener extends FloodProtectedListener
|
||||
{
|
||||
private static List<GameServerThread> _gameServers = new FastList<>();
|
||||
|
||||
public GameServerListener() throws IOException
|
||||
{
|
||||
super(Config.GAME_SERVER_LOGIN_HOST, Config.GAME_SERVER_LOGIN_PORT);
|
||||
setName(getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addClient(Socket s)
|
||||
{
|
||||
_gameServers.add(new GameServerThread(s));
|
||||
}
|
||||
|
||||
public void removeGameServer(GameServerThread gst)
|
||||
{
|
||||
_gameServers.remove(gst);
|
||||
}
|
||||
}
|
681
trunk/java/com/l2jserver/loginserver/GameServerTable.java
Normal file
681
trunk/java/com/l2jserver/loginserver/GameServerTable.java
Normal file
@@ -0,0 +1,681 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.spec.RSAKeyGenParameterSpec;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javolution.io.UTF8StreamReader;
|
||||
import javolution.xml.stream.XMLStreamConstants;
|
||||
import javolution.xml.stream.XMLStreamReaderImpl;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.L2DatabaseFactory;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.ServerStatus;
|
||||
import com.l2jserver.util.IPSubnet;
|
||||
import com.l2jserver.util.Rnd;
|
||||
|
||||
/**
|
||||
* The Class GameServerTable loads the game server names and initialize the game server tables.
|
||||
* @author KenM, Zoey76
|
||||
*/
|
||||
public final class GameServerTable
|
||||
{
|
||||
private static final Logger _log = Logger.getLogger(GameServerTable.class.getName());
|
||||
// Server Names Config
|
||||
private static final Map<Integer, String> _serverNames = new HashMap<>();
|
||||
// Game Server Table
|
||||
private static final Map<Integer, GameServerInfo> _gameServerTable = new HashMap<>();
|
||||
// RSA Config
|
||||
private static final int KEYS_SIZE = 10;
|
||||
private KeyPair[] _keyPairs;
|
||||
|
||||
/**
|
||||
* Instantiates a new game server table.
|
||||
*/
|
||||
public GameServerTable()
|
||||
{
|
||||
loadGameServerNames();
|
||||
_log.info(getClass().getSimpleName() + ": Loaded " + _serverNames.size() + " server names");
|
||||
|
||||
loadRegisteredGameServers();
|
||||
_log.info(getClass().getSimpleName() + ": Loaded " + _gameServerTable.size() + " registered Game Servers");
|
||||
|
||||
initRSAKeys();
|
||||
_log.info(getClass().getSimpleName() + ": Cached " + _keyPairs.length + " RSA keys for Game Server communication.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Load game server names.
|
||||
*/
|
||||
private void loadGameServerNames()
|
||||
{
|
||||
final File xml = new File(Config.DATAPACK_ROOT, "data/servername.xml");
|
||||
try (InputStream in = new FileInputStream(xml);
|
||||
UTF8StreamReader utf8 = new UTF8StreamReader())
|
||||
{
|
||||
final XMLStreamReaderImpl xpp = new XMLStreamReaderImpl();
|
||||
xpp.setInput(utf8.setInput(in));
|
||||
for (int e = xpp.getEventType(); e != XMLStreamConstants.END_DOCUMENT; e = xpp.next())
|
||||
{
|
||||
if (e == XMLStreamConstants.START_ELEMENT)
|
||||
{
|
||||
if (xpp.getLocalName().toString().equals("server"))
|
||||
{
|
||||
Integer id = Integer.valueOf(xpp.getAttributeValue(null, "id").toString());
|
||||
String name = xpp.getAttributeValue(null, "name").toString();
|
||||
_serverNames.put(id, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
xpp.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.info(getClass().getSimpleName() + ": Cannot load " + xml.getAbsolutePath() + "!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inits the RSA keys.
|
||||
*/
|
||||
private void initRSAKeys()
|
||||
{
|
||||
try
|
||||
{
|
||||
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
|
||||
keyGen.initialize(new RSAKeyGenParameterSpec(512, RSAKeyGenParameterSpec.F4));
|
||||
_keyPairs = new KeyPair[KEYS_SIZE];
|
||||
for (int i = 0; i < KEYS_SIZE; i++)
|
||||
{
|
||||
_keyPairs[i] = keyGen.genKeyPair();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.severe(getClass().getSimpleName() + ": Error loading RSA keys for Game Server communication!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load registered game servers.
|
||||
*/
|
||||
private void loadRegisteredGameServers()
|
||||
{
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
Statement ps = con.createStatement();
|
||||
ResultSet rs = ps.executeQuery("SELECT * FROM gameservers"))
|
||||
{
|
||||
int id;
|
||||
while (rs.next())
|
||||
{
|
||||
id = rs.getInt("server_id");
|
||||
_gameServerTable.put(id, new GameServerInfo(id, stringToHex(rs.getString("hexid"))));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.severe(getClass().getSimpleName() + ": Error loading registered game servers!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered game servers.
|
||||
* @return the registered game servers
|
||||
*/
|
||||
public Map<Integer, GameServerInfo> getRegisteredGameServers()
|
||||
{
|
||||
return _gameServerTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered game server by id.
|
||||
* @param id the game server Id
|
||||
* @return the registered game server by id
|
||||
*/
|
||||
public GameServerInfo getRegisteredGameServerById(int id)
|
||||
{
|
||||
return _gameServerTable.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for registered game server on id.
|
||||
* @param id the id
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean hasRegisteredGameServerOnId(int id)
|
||||
{
|
||||
return _gameServerTable.containsKey(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register with first available id.
|
||||
* @param gsi the game server information DTO
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean registerWithFirstAvaliableId(GameServerInfo gsi)
|
||||
{
|
||||
// avoid two servers registering with the same "free" id
|
||||
synchronized (_gameServerTable)
|
||||
{
|
||||
for (Entry<Integer, String> entry : _serverNames.entrySet())
|
||||
{
|
||||
if (!_gameServerTable.containsKey(entry.getKey()))
|
||||
{
|
||||
_gameServerTable.put(entry.getKey(), gsi);
|
||||
gsi.setId(entry.getKey());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a game server.
|
||||
* @param id the id
|
||||
* @param gsi the gsi
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean register(int id, GameServerInfo gsi)
|
||||
{
|
||||
// avoid two servers registering with the same id
|
||||
synchronized (_gameServerTable)
|
||||
{
|
||||
if (!_gameServerTable.containsKey(id))
|
||||
{
|
||||
_gameServerTable.put(id, gsi);
|
||||
gsi.setId(id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper method.
|
||||
* @param gsi the game server info DTO.
|
||||
*/
|
||||
public void registerServerOnDB(GameServerInfo gsi)
|
||||
{
|
||||
registerServerOnDB(gsi.getHexId(), gsi.getId(), gsi.getExternalHost());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register server on db.
|
||||
* @param hexId the hex id
|
||||
* @param id the id
|
||||
* @param externalHost the external host
|
||||
*/
|
||||
public void registerServerOnDB(byte[] hexId, int id, String externalHost)
|
||||
{
|
||||
register(id, new GameServerInfo(id, hexId));
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("INSERT INTO gameservers (hexid,server_id,host) values (?,?,?)"))
|
||||
{
|
||||
ps.setString(1, hexToString(hexId));
|
||||
ps.setInt(2, id);
|
||||
ps.setString(3, externalHost);
|
||||
ps.executeUpdate();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.severe(getClass().getSimpleName() + ": Error while saving gameserver!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server name by id.
|
||||
* @param id the id
|
||||
* @return the server name by id
|
||||
*/
|
||||
public String getServerNameById(int id)
|
||||
{
|
||||
return _serverNames.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server names.
|
||||
* @return the game server names map.
|
||||
*/
|
||||
public Map<Integer, String> getServerNames()
|
||||
{
|
||||
return _serverNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the key pair.
|
||||
* @return a random key pair.
|
||||
*/
|
||||
public KeyPair getKeyPair()
|
||||
{
|
||||
return _keyPairs[Rnd.nextInt(10)];
|
||||
}
|
||||
|
||||
/**
|
||||
* String to hex.
|
||||
* @param string the string to convert.
|
||||
* @return return the hex representation.
|
||||
*/
|
||||
private byte[] stringToHex(String string)
|
||||
{
|
||||
return new BigInteger(string, 16).toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hex to string.
|
||||
* @param hex the hex value to convert.
|
||||
* @return the string representation.
|
||||
*/
|
||||
private String hexToString(byte[] hex)
|
||||
{
|
||||
if (hex == null)
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
return new BigInteger(hex).toString(16);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Class GameServerInfo.
|
||||
*/
|
||||
public static class GameServerInfo
|
||||
{
|
||||
// auth
|
||||
private int _id;
|
||||
private final byte[] _hexId;
|
||||
private boolean _isAuthed;
|
||||
// status
|
||||
private GameServerThread _gst;
|
||||
private int _status;
|
||||
// network
|
||||
private final ArrayList<GameServerAddress> _addrs = new ArrayList<>(5);
|
||||
private int _port;
|
||||
// config
|
||||
private final boolean _isPvp = true;
|
||||
private int _serverType;
|
||||
private int _ageLimit;
|
||||
private boolean _isShowingBrackets;
|
||||
private int _maxPlayers;
|
||||
|
||||
/**
|
||||
* Instantiates a new game server info.
|
||||
* @param id the id
|
||||
* @param hexId the hex id
|
||||
* @param gst the gst
|
||||
*/
|
||||
public GameServerInfo(int id, byte[] hexId, GameServerThread gst)
|
||||
{
|
||||
_id = id;
|
||||
_hexId = hexId;
|
||||
_gst = gst;
|
||||
_status = ServerStatus.STATUS_DOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new game server info.
|
||||
* @param id the id
|
||||
* @param hexId the hex id
|
||||
*/
|
||||
public GameServerInfo(int id, byte[] hexId)
|
||||
{
|
||||
this(id, hexId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the id.
|
||||
* @param id the new id
|
||||
*/
|
||||
public void setId(int id)
|
||||
{
|
||||
_id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id.
|
||||
* @return the id
|
||||
*/
|
||||
public int getId()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hex id.
|
||||
* @return the hex id
|
||||
*/
|
||||
public byte[] getHexId()
|
||||
{
|
||||
return _hexId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the authed.
|
||||
* @param isAuthed the new authed
|
||||
*/
|
||||
public void setAuthed(boolean isAuthed)
|
||||
{
|
||||
_isAuthed = isAuthed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is authed.
|
||||
* @return true, if is authed
|
||||
*/
|
||||
public boolean isAuthed()
|
||||
{
|
||||
return _isAuthed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the game server thread.
|
||||
* @param gst the new game server thread
|
||||
*/
|
||||
public void setGameServerThread(GameServerThread gst)
|
||||
{
|
||||
_gst = gst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the game server thread.
|
||||
* @return the game server thread
|
||||
*/
|
||||
public GameServerThread getGameServerThread()
|
||||
{
|
||||
return _gst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status.
|
||||
* @param status the new status
|
||||
*/
|
||||
public void setStatus(int status)
|
||||
{
|
||||
_status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status.
|
||||
* @return the status
|
||||
*/
|
||||
public int getStatus()
|
||||
{
|
||||
return _status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current player count.
|
||||
* @return the current player count
|
||||
*/
|
||||
public int getCurrentPlayerCount()
|
||||
{
|
||||
if (_gst == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return _gst.getPlayerCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the external host.
|
||||
* @return the external host
|
||||
*/
|
||||
public String getExternalHost()
|
||||
{
|
||||
try
|
||||
{
|
||||
return getServerAddress(InetAddress.getByName("0.0.0.0"));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the port.
|
||||
* @return the port
|
||||
*/
|
||||
public int getPort()
|
||||
{
|
||||
return _port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the port.
|
||||
* @param port the new port
|
||||
*/
|
||||
public void setPort(int port)
|
||||
{
|
||||
_port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the max players.
|
||||
* @param maxPlayers the new max players
|
||||
*/
|
||||
public void setMaxPlayers(int maxPlayers)
|
||||
{
|
||||
_maxPlayers = maxPlayers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the max players.
|
||||
* @return the max players
|
||||
*/
|
||||
public int getMaxPlayers()
|
||||
{
|
||||
return _maxPlayers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is pvp.
|
||||
* @return true, if is pvp
|
||||
*/
|
||||
public boolean isPvp()
|
||||
{
|
||||
return _isPvp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the age limit.
|
||||
* @param val the new age limit
|
||||
*/
|
||||
public void setAgeLimit(int val)
|
||||
{
|
||||
_ageLimit = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the age limit.
|
||||
* @return the age limit
|
||||
*/
|
||||
public int getAgeLimit()
|
||||
{
|
||||
return _ageLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server type.
|
||||
* @param val the new server type
|
||||
*/
|
||||
public void setServerType(int val)
|
||||
{
|
||||
_serverType = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server type.
|
||||
* @return the server type
|
||||
*/
|
||||
public int getServerType()
|
||||
{
|
||||
return _serverType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the showing brackets.
|
||||
* @param val the new showing brackets
|
||||
*/
|
||||
public void setShowingBrackets(boolean val)
|
||||
{
|
||||
_isShowingBrackets = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is showing brackets.
|
||||
* @return true, if is showing brackets
|
||||
*/
|
||||
public boolean isShowingBrackets()
|
||||
{
|
||||
return _isShowingBrackets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the down.
|
||||
*/
|
||||
public void setDown()
|
||||
{
|
||||
setAuthed(false);
|
||||
setPort(0);
|
||||
setGameServerThread(null);
|
||||
setStatus(ServerStatus.STATUS_DOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the server address.
|
||||
* @param subnet the subnet
|
||||
* @param addr the addr
|
||||
* @throws UnknownHostException the unknown host exception
|
||||
*/
|
||||
public void addServerAddress(String subnet, String addr) throws UnknownHostException
|
||||
{
|
||||
_addrs.add(new GameServerAddress(subnet, addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server address.
|
||||
* @param addr the addr
|
||||
* @return the server address
|
||||
*/
|
||||
public String getServerAddress(InetAddress addr)
|
||||
{
|
||||
for (GameServerAddress a : _addrs)
|
||||
{
|
||||
if (a.equals(addr))
|
||||
{
|
||||
return a.getServerAddress();
|
||||
}
|
||||
}
|
||||
return null; // should not happens
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server addresses.
|
||||
* @return the server addresses
|
||||
*/
|
||||
public String[] getServerAddresses()
|
||||
{
|
||||
String[] result = new String[_addrs.size()];
|
||||
for (int i = 0; i < result.length; i++)
|
||||
{
|
||||
result[i] = _addrs.get(i).toString();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear server addresses.
|
||||
*/
|
||||
public void clearServerAddresses()
|
||||
{
|
||||
_addrs.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* The Class GameServerAddress.
|
||||
*/
|
||||
private class GameServerAddress extends IPSubnet
|
||||
{
|
||||
private final String _serverAddress;
|
||||
|
||||
/**
|
||||
* Instantiates a new game server address.
|
||||
* @param subnet the subnet
|
||||
* @param address the address
|
||||
* @throws UnknownHostException the unknown host exception
|
||||
*/
|
||||
public GameServerAddress(String subnet, String address) throws UnknownHostException
|
||||
{
|
||||
super(subnet);
|
||||
_serverAddress = address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server address.
|
||||
* @return the server address
|
||||
*/
|
||||
public String getServerAddress()
|
||||
{
|
||||
return _serverAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return _serverAddress + super.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the single instance of GameServerTable.
|
||||
* @return single instance of GameServerTable
|
||||
*/
|
||||
public static GameServerTable getInstance()
|
||||
{
|
||||
return SingletonHolder._instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Class SingletonHolder.
|
||||
*/
|
||||
private static class SingletonHolder
|
||||
{
|
||||
protected static final GameServerTable _instance = new GameServerTable();
|
||||
}
|
||||
}
|
380
trunk/java/com/l2jserver/loginserver/GameServerThread.java
Normal file
380
trunk/java/com/l2jserver/loginserver/GameServerThread.java
Normal file
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyPair;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javolution.util.FastSet;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.loginserver.GameServerTable.GameServerInfo;
|
||||
import com.l2jserver.loginserver.network.L2JGameServerPacketHandler;
|
||||
import com.l2jserver.loginserver.network.L2JGameServerPacketHandler.GameServerState;
|
||||
import com.l2jserver.loginserver.network.loginserverpackets.ChangePasswordResponse;
|
||||
import com.l2jserver.loginserver.network.loginserverpackets.InitLS;
|
||||
import com.l2jserver.loginserver.network.loginserverpackets.KickPlayer;
|
||||
import com.l2jserver.loginserver.network.loginserverpackets.LoginServerFail;
|
||||
import com.l2jserver.loginserver.network.loginserverpackets.RequestCharacters;
|
||||
import com.l2jserver.util.Util;
|
||||
import com.l2jserver.util.crypt.NewCrypt;
|
||||
import com.l2jserver.util.network.BaseSendablePacket;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
* @author KenM
|
||||
*/
|
||||
public class GameServerThread extends Thread
|
||||
{
|
||||
protected static final Logger _log = Logger.getLogger(GameServerThread.class.getName());
|
||||
private final Socket _connection;
|
||||
private InputStream _in;
|
||||
private OutputStream _out;
|
||||
private final RSAPublicKey _publicKey;
|
||||
private final RSAPrivateKey _privateKey;
|
||||
private NewCrypt _blowfish;
|
||||
private GameServerState _loginConnectionState = GameServerState.CONNECTED;
|
||||
|
||||
private final String _connectionIp;
|
||||
|
||||
private GameServerInfo _gsi;
|
||||
|
||||
/** Authed Clients on a GameServer */
|
||||
private final Set<String> _accountsOnGameServer = new FastSet<>();
|
||||
|
||||
private String _connectionIPAddress;
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
_connectionIPAddress = _connection.getInetAddress().getHostAddress();
|
||||
if (GameServerThread.isBannedGameserverIP(_connectionIPAddress))
|
||||
{
|
||||
_log.info("GameServerRegistration: IP Address " + _connectionIPAddress + " is on Banned IP list.");
|
||||
forceClose(LoginServerFail.REASON_IP_BANNED);
|
||||
// ensure no further processing for this connection
|
||||
return;
|
||||
}
|
||||
|
||||
InitLS startPacket = new InitLS(_publicKey.getModulus().toByteArray());
|
||||
try
|
||||
{
|
||||
sendPacket(startPacket);
|
||||
|
||||
int lengthHi = 0;
|
||||
int lengthLo = 0;
|
||||
int length = 0;
|
||||
boolean checksumOk = false;
|
||||
for (;;)
|
||||
{
|
||||
lengthLo = _in.read();
|
||||
lengthHi = _in.read();
|
||||
length = (lengthHi * 256) + lengthLo;
|
||||
|
||||
if ((lengthHi < 0) || _connection.isClosed())
|
||||
{
|
||||
_log.finer("LoginServerThread: Login terminated the connection.");
|
||||
break;
|
||||
}
|
||||
|
||||
byte[] data = new byte[length - 2];
|
||||
|
||||
int receivedBytes = 0;
|
||||
int newBytes = 0;
|
||||
int left = length - 2;
|
||||
while ((newBytes != -1) && (receivedBytes < (length - 2)))
|
||||
{
|
||||
newBytes = _in.read(data, receivedBytes, left);
|
||||
receivedBytes = receivedBytes + newBytes;
|
||||
left -= newBytes;
|
||||
}
|
||||
|
||||
if (receivedBytes != (length - 2))
|
||||
{
|
||||
_log.warning("Incomplete Packet is sent to the server, closing connection.(LS)");
|
||||
break;
|
||||
}
|
||||
|
||||
// decrypt if we have a key
|
||||
_blowfish.decrypt(data, 0, data.length);
|
||||
checksumOk = NewCrypt.verifyChecksum(data);
|
||||
if (!checksumOk)
|
||||
{
|
||||
_log.warning("Incorrect packet checksum, closing connection (LS)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.warning("[C]" + Config.EOL + Util.printData(data));
|
||||
}
|
||||
|
||||
L2JGameServerPacketHandler.handlePacket(data, this);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
String serverName = (getServerId() != -1 ? "[" + getServerId() + "] " + GameServerTable.getInstance().getServerNameById(getServerId()) : "(" + _connectionIPAddress + ")");
|
||||
String msg = "GameServer " + serverName + ": Connection lost: " + e.getMessage();
|
||||
_log.info(msg);
|
||||
broadcastToTelnet(msg);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (isAuthed())
|
||||
{
|
||||
_gsi.setDown();
|
||||
_log.info("Server [" + getServerId() + "] " + GameServerTable.getInstance().getServerNameById(getServerId()) + " is now set as disconnected");
|
||||
}
|
||||
L2LoginServer.getInstance().getGameServerListener().removeGameServer(this);
|
||||
L2LoginServer.getInstance().getGameServerListener().removeFloodProtection(_connectionIp);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasAccountOnGameServer(String account)
|
||||
{
|
||||
return _accountsOnGameServer.contains(account);
|
||||
}
|
||||
|
||||
public int getPlayerCount()
|
||||
{
|
||||
return _accountsOnGameServer.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attachs a GameServerInfo to this Thread<br>
|
||||
* <ul>
|
||||
* <li>Updates the GameServerInfo values based on GameServerAuth packet</li>
|
||||
* <li><b>Sets the GameServerInfo as Authed</b></li>
|
||||
* </ul>
|
||||
* @param gsi The GameServerInfo to be attached.
|
||||
* @param port
|
||||
* @param hosts
|
||||
* @param maxPlayers
|
||||
*/
|
||||
public void attachGameServerInfo(GameServerInfo gsi, int port, String[] hosts, int maxPlayers)
|
||||
{
|
||||
setGameServerInfo(gsi);
|
||||
gsi.setGameServerThread(this);
|
||||
gsi.setPort(port);
|
||||
setGameHosts(hosts);
|
||||
gsi.setMaxPlayers(maxPlayers);
|
||||
gsi.setAuthed(true);
|
||||
}
|
||||
|
||||
public void forceClose(int reason)
|
||||
{
|
||||
sendPacket(new LoginServerFail(reason));
|
||||
|
||||
try
|
||||
{
|
||||
_connection.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.finer("GameServerThread: Failed disconnecting banned server, server already disconnected.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ipAddress
|
||||
* @return
|
||||
*/
|
||||
public static boolean isBannedGameserverIP(String ipAddress)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public GameServerThread(Socket con)
|
||||
{
|
||||
_connection = con;
|
||||
_connectionIp = con.getInetAddress().getHostAddress();
|
||||
try
|
||||
{
|
||||
_in = _connection.getInputStream();
|
||||
_out = new BufferedOutputStream(_connection.getOutputStream());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.warning(getClass().getSimpleName() + ": " + e.getMessage());
|
||||
}
|
||||
KeyPair pair = GameServerTable.getInstance().getKeyPair();
|
||||
_privateKey = (RSAPrivateKey) pair.getPrivate();
|
||||
_publicKey = (RSAPublicKey) pair.getPublic();
|
||||
_blowfish = new NewCrypt("_;v.]05-31!|+-%xT!^[$\00");
|
||||
setName(getClass().getSimpleName() + "-" + getId() + "@" + _connectionIp);
|
||||
start();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sl
|
||||
*/
|
||||
public void sendPacket(BaseSendablePacket sl)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] data = sl.getContent();
|
||||
NewCrypt.appendChecksum(data);
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.finest("[S] " + sl.getClass().getSimpleName() + ":" + Config.EOL + Util.printData(data));
|
||||
}
|
||||
_blowfish.crypt(data, 0, data.length);
|
||||
|
||||
int len = data.length + 2;
|
||||
synchronized (_out)
|
||||
{
|
||||
_out.write(len & 0xff);
|
||||
_out.write((len >> 8) & 0xff);
|
||||
_out.write(data);
|
||||
_out.flush();
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.severe("IOException while sending packet " + sl.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcastToTelnet(String msg)
|
||||
{
|
||||
if (L2LoginServer.getInstance().getStatusServer() != null)
|
||||
{
|
||||
L2LoginServer.getInstance().getStatusServer().sendMessageToTelnets(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void kickPlayer(String account)
|
||||
{
|
||||
sendPacket(new KickPlayer(account));
|
||||
}
|
||||
|
||||
public void requestCharacters(String account)
|
||||
{
|
||||
sendPacket(new RequestCharacters(account));
|
||||
}
|
||||
|
||||
public void ChangePasswordResponse(byte successful, String characterName, String msgToSend)
|
||||
{
|
||||
sendPacket(new ChangePasswordResponse(successful, characterName, msgToSend));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hosts The gameHost to set.
|
||||
*/
|
||||
public void setGameHosts(String[] hosts)
|
||||
{
|
||||
_log.info("Updated Gameserver [" + getServerId() + "] " + GameServerTable.getInstance().getServerNameById(getServerId()) + " IP's:");
|
||||
|
||||
_gsi.clearServerAddresses();
|
||||
for (int i = 0; i < hosts.length; i += 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
_gsi.addServerAddress(hosts[i], hosts[i + 1]);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.warning("Couldn't resolve hostname \"" + e + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
for (String s : _gsi.getServerAddresses())
|
||||
{
|
||||
_log.info(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the isAuthed.
|
||||
*/
|
||||
public boolean isAuthed()
|
||||
{
|
||||
if (getGameServerInfo() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return getGameServerInfo().isAuthed();
|
||||
}
|
||||
|
||||
public void setGameServerInfo(GameServerInfo gsi)
|
||||
{
|
||||
_gsi = gsi;
|
||||
}
|
||||
|
||||
public GameServerInfo getGameServerInfo()
|
||||
{
|
||||
return _gsi;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the connectionIpAddress.
|
||||
*/
|
||||
public String getConnectionIpAddress()
|
||||
{
|
||||
return _connectionIPAddress;
|
||||
}
|
||||
|
||||
public int getServerId()
|
||||
{
|
||||
if (getGameServerInfo() != null)
|
||||
{
|
||||
return getGameServerInfo().getId();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public RSAPrivateKey getPrivateKey()
|
||||
{
|
||||
return _privateKey;
|
||||
}
|
||||
|
||||
public void SetBlowFish(NewCrypt blowfish)
|
||||
{
|
||||
_blowfish = blowfish;
|
||||
}
|
||||
|
||||
public void addAccountOnGameServer(String account)
|
||||
{
|
||||
_accountsOnGameServer.add(account);
|
||||
}
|
||||
|
||||
public void removeAccountOnGameServer(String account)
|
||||
{
|
||||
_accountsOnGameServer.remove(account);
|
||||
}
|
||||
|
||||
public GameServerState getLoginConnectionState()
|
||||
{
|
||||
return _loginConnectionState;
|
||||
}
|
||||
|
||||
public void setLoginConnectionState(GameServerState state)
|
||||
{
|
||||
_loginConnectionState = state;
|
||||
}
|
||||
}
|
54
trunk/java/com/l2jserver/loginserver/HackingException.java
Normal file
54
trunk/java/com/l2jserver/loginserver/HackingException.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver;
|
||||
|
||||
/**
|
||||
* This class ...
|
||||
* @version $Revision: 1.2.4.2 $ $Date: 2005/03/27 15:30:09 $
|
||||
*/
|
||||
|
||||
public class HackingException extends Exception
|
||||
{
|
||||
/**
|
||||
* Comment for <code>serialVersionUID</code>
|
||||
*/
|
||||
private static final long serialVersionUID = 4050762693478463029L;
|
||||
String _ip;
|
||||
private final int _connects;
|
||||
|
||||
public HackingException(String ip, int connects)
|
||||
{
|
||||
_ip = ip;
|
||||
_connects = connects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getIP()
|
||||
{
|
||||
return _ip;
|
||||
}
|
||||
|
||||
public int getConnects()
|
||||
{
|
||||
return _connects;
|
||||
}
|
||||
|
||||
}
|
306
trunk/java/com/l2jserver/loginserver/L2LoginServer.java
Normal file
306
trunk/java/com/l2jserver/loginserver/L2LoginServer.java
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.mmocore.network.SelectorConfig;
|
||||
import org.mmocore.network.SelectorThread;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.L2DatabaseFactory;
|
||||
import com.l2jserver.Server;
|
||||
import com.l2jserver.UPnPService;
|
||||
import com.l2jserver.loginserver.mail.MailSystem;
|
||||
import com.l2jserver.loginserver.network.L2LoginClient;
|
||||
import com.l2jserver.loginserver.network.L2LoginPacketHandler;
|
||||
import com.l2jserver.status.Status;
|
||||
|
||||
/**
|
||||
* @author KenM
|
||||
*/
|
||||
public final class L2LoginServer
|
||||
{
|
||||
private final Logger _log = Logger.getLogger(L2LoginServer.class.getName());
|
||||
|
||||
public static final int PROTOCOL_REV = 0x0106;
|
||||
private static L2LoginServer _instance;
|
||||
private GameServerListener _gameServerListener;
|
||||
private SelectorThread<L2LoginClient> _selectorThread;
|
||||
private Status _statusServer;
|
||||
private Thread _restartLoginServer;
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new L2LoginServer();
|
||||
}
|
||||
|
||||
public static L2LoginServer getInstance()
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
|
||||
private L2LoginServer()
|
||||
{
|
||||
_instance = this;
|
||||
Server.serverMode = Server.MODE_LOGINSERVER;
|
||||
// Local Constants
|
||||
final String LOG_FOLDER = "log"; // Name of folder for log file
|
||||
final String LOG_NAME = "./log.cfg"; // Name of log file
|
||||
|
||||
/*** Main ***/
|
||||
// Create log folder
|
||||
File logFolder = new File(Config.DATAPACK_ROOT, LOG_FOLDER);
|
||||
logFolder.mkdir();
|
||||
|
||||
// Create input stream for log file -- or store file data into memory
|
||||
|
||||
try (InputStream is = new FileInputStream(new File(LOG_NAME)))
|
||||
{
|
||||
LogManager.getLogManager().readConfiguration(is);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.warning(getClass().getSimpleName() + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
// Load Config
|
||||
Config.load();
|
||||
|
||||
// Prepare Database
|
||||
try
|
||||
{
|
||||
L2DatabaseFactory.getInstance();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
_log.log(Level.SEVERE, "FATAL: Failed initializing database. Reason: " + e.getMessage(), e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LoginController.load();
|
||||
}
|
||||
catch (GeneralSecurityException e)
|
||||
{
|
||||
_log.log(Level.SEVERE, "FATAL: Failed initializing LoginController. Reason: " + e.getMessage(), e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
GameServerTable.getInstance();
|
||||
|
||||
loadBanFile();
|
||||
|
||||
if (Config.EMAIL_SYS_ENABLED)
|
||||
{
|
||||
MailSystem.getInstance();
|
||||
}
|
||||
|
||||
InetAddress bindAddress = null;
|
||||
if (!Config.LOGIN_BIND_ADDRESS.equals("*"))
|
||||
{
|
||||
try
|
||||
{
|
||||
bindAddress = InetAddress.getByName(Config.LOGIN_BIND_ADDRESS);
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
_log.log(Level.WARNING, "WARNING: The LoginServer bind address is invalid, using all avaliable IPs. Reason: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
final SelectorConfig sc = new SelectorConfig();
|
||||
sc.MAX_READ_PER_PASS = Config.MMO_MAX_READ_PER_PASS;
|
||||
sc.MAX_SEND_PER_PASS = Config.MMO_MAX_SEND_PER_PASS;
|
||||
sc.SLEEP_TIME = Config.MMO_SELECTOR_SLEEP_TIME;
|
||||
sc.HELPER_BUFFER_COUNT = Config.MMO_HELPER_BUFFER_COUNT;
|
||||
|
||||
final L2LoginPacketHandler lph = new L2LoginPacketHandler();
|
||||
final SelectorHelper sh = new SelectorHelper();
|
||||
try
|
||||
{
|
||||
_selectorThread = new SelectorThread<>(sc, sh, lph, sh, sh);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.log(Level.SEVERE, "FATAL: Failed to open Selector. Reason: " + e.getMessage(), e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_gameServerListener = new GameServerListener();
|
||||
_gameServerListener.start();
|
||||
_log.info("Listening for GameServers on " + Config.GAME_SERVER_LOGIN_HOST + ":" + Config.GAME_SERVER_LOGIN_PORT);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.log(Level.SEVERE, "FATAL: Failed to start the Game Server Listener. Reason: " + e.getMessage(), e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
if (Config.IS_TELNET_ENABLED)
|
||||
{
|
||||
try
|
||||
{
|
||||
_statusServer = new Status(Server.serverMode);
|
||||
_statusServer.start();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.log(Level.WARNING, "Failed to start the Telnet Server. Reason: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.info("Telnet server is currently disabled.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_selectorThread.openServerSocket(bindAddress, Config.PORT_LOGIN);
|
||||
_selectorThread.start();
|
||||
_log.log(Level.INFO, getClass().getSimpleName() + ": is now listening on: " + Config.LOGIN_BIND_ADDRESS + ":" + Config.PORT_LOGIN);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.log(Level.SEVERE, "FATAL: Failed to open server socket. Reason: " + e.getMessage(), e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
UPnPService.getInstance();
|
||||
}
|
||||
|
||||
public Status getStatusServer()
|
||||
{
|
||||
return _statusServer;
|
||||
}
|
||||
|
||||
public GameServerListener getGameServerListener()
|
||||
{
|
||||
return _gameServerListener;
|
||||
}
|
||||
|
||||
private void loadBanFile()
|
||||
{
|
||||
final File bannedFile = new File("./banned_ip.cfg");
|
||||
if (bannedFile.exists() && bannedFile.isFile())
|
||||
{
|
||||
try (FileInputStream fis = new FileInputStream(bannedFile);
|
||||
InputStreamReader is = new InputStreamReader(fis);
|
||||
LineNumberReader lnr = new LineNumberReader(is))
|
||||
{
|
||||
//@formatter:off
|
||||
lnr.lines()
|
||||
.map(String::trim)
|
||||
.filter(l -> !l.isEmpty() && (l.charAt(0) != '#'))
|
||||
.forEach(line -> {
|
||||
String[] parts = line.split("#", 2); // address[ duration][ # comments]
|
||||
line = parts[0];
|
||||
parts = line.split("\\s+"); // durations might be aligned via multiple spaces
|
||||
String address = parts[0];
|
||||
long duration = 0;
|
||||
|
||||
if (parts.length > 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
duration = Long.parseLong(parts[1]);
|
||||
}
|
||||
catch (NumberFormatException nfe)
|
||||
{
|
||||
_log.warning("Skipped: Incorrect ban duration (" + parts[1] + ") on (" + bannedFile.getName() + "). Line: " + lnr.getLineNumber());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LoginController.getInstance().addBanForAddress(address, duration);
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
_log.warning("Skipped: Invalid address (" + address + ") on (" + bannedFile.getName() + "). Line: " + lnr.getLineNumber());
|
||||
}
|
||||
});
|
||||
//@formatter:on
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.log(Level.WARNING, "Error while reading the bans file (" + bannedFile.getName() + "). Details: " + e.getMessage(), e);
|
||||
}
|
||||
_log.info("Loaded " + LoginController.getInstance().getBannedIps().size() + " IP Bans.");
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.warning("IP Bans file (" + bannedFile.getName() + ") is missing or is a directory, skipped.");
|
||||
}
|
||||
|
||||
if (Config.LOGIN_SERVER_SCHEDULE_RESTART)
|
||||
{
|
||||
_log.info("Scheduled LS restart after " + Config.LOGIN_SERVER_SCHEDULE_RESTART_TIME + " hours");
|
||||
_restartLoginServer = new LoginServerRestart();
|
||||
_restartLoginServer.setDaemon(true);
|
||||
_restartLoginServer.start();
|
||||
}
|
||||
}
|
||||
|
||||
class LoginServerRestart extends Thread
|
||||
{
|
||||
public LoginServerRestart()
|
||||
{
|
||||
setName("LoginServerRestart");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while (!isInterrupted())
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(Config.LOGIN_SERVER_SCHEDULE_RESTART_TIME * 3600000);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
shutdown(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown(boolean restart)
|
||||
{
|
||||
Runtime.getRuntime().exit(restart ? 2 : 0);
|
||||
}
|
||||
}
|
698
trunk/java/com/l2jserver/loginserver/LoginController.java
Normal file
698
trunk/java/com/l2jserver/loginserver/LoginController.java
Normal file
@@ -0,0 +1,698 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.spec.RSAKeyGenParameterSpec;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import javolution.util.FastMap;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.L2DatabaseFactory;
|
||||
import com.l2jserver.loginserver.GameServerTable.GameServerInfo;
|
||||
import com.l2jserver.loginserver.model.data.AccountInfo;
|
||||
import com.l2jserver.loginserver.network.L2LoginClient;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.ServerStatus;
|
||||
import com.l2jserver.loginserver.network.serverpackets.LoginFail.LoginFailReason;
|
||||
import com.l2jserver.util.Rnd;
|
||||
import com.l2jserver.util.crypt.ScrambledKeyPair;
|
||||
|
||||
public class LoginController
|
||||
{
|
||||
protected static final Logger _log = Logger.getLogger(LoginController.class.getName());
|
||||
|
||||
private static LoginController _instance;
|
||||
|
||||
/** Time before kicking the client if he didn't logged yet */
|
||||
public static final int LOGIN_TIMEOUT = 60 * 1000;
|
||||
|
||||
/** Authed Clients on LoginServer */
|
||||
protected FastMap<String, L2LoginClient> _loginServerClients = new FastMap<String, L2LoginClient>().shared();
|
||||
|
||||
private final Map<InetAddress, Integer> _failedLoginAttemps = new HashMap<>();
|
||||
private final Map<InetAddress, Long> _bannedIps = new FastMap<InetAddress, Long>().shared();
|
||||
|
||||
protected ScrambledKeyPair[] _keyPairs;
|
||||
|
||||
protected byte[][] _blowfishKeys;
|
||||
private static final int BLOWFISH_KEYS = 20;
|
||||
|
||||
// SQL Queries
|
||||
private static final String USER_INFO_SELECT = "SELECT login, password, IF(? > value OR value IS NULL, accessLevel, -1) AS accessLevel, lastServer FROM accounts LEFT JOIN (account_data) ON (account_data.account_name=accounts.login AND account_data.var=\"ban_temp\") WHERE login=?";
|
||||
private static final String AUTOCREATE_ACCOUNTS_INSERT = "INSERT INTO accounts (login, password, lastactive, accessLevel, lastIP) values (?, ?, ?, ?, ?)";
|
||||
private static final String ACCOUNT_INFO_UPDATE = "UPDATE accounts SET lastactive = ?, lastIP = ? WHERE login = ?";
|
||||
private static final String ACCOUNT_LAST_SERVER_UPDATE = "UPDATE accounts SET lastServer = ? WHERE login = ?";
|
||||
private static final String ACCOUNT_ACCESS_LEVEL_UPDATE = "UPDATE accounts SET accessLevel = ? WHERE login = ?";
|
||||
private static final String ACCOUNT_IPS_UPDATE = "UPDATE accounts SET pcIp = ?, hop1 = ?, hop2 = ?, hop3 = ?, hop4 = ? WHERE login = ?";
|
||||
private static final String ACCOUNT_IPAUTH_SELECT = "SELECT * FROM accounts_ipauth WHERE login = ?";
|
||||
|
||||
private LoginController() throws GeneralSecurityException
|
||||
{
|
||||
_log.info("Loading LoginController...");
|
||||
|
||||
_keyPairs = new ScrambledKeyPair[10];
|
||||
|
||||
KeyPairGenerator keygen = null;
|
||||
|
||||
keygen = KeyPairGenerator.getInstance("RSA");
|
||||
RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(1024, RSAKeyGenParameterSpec.F4);
|
||||
keygen.initialize(spec);
|
||||
|
||||
// generate the initial set of keys
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
_keyPairs[i] = new ScrambledKeyPair(keygen.generateKeyPair());
|
||||
}
|
||||
_log.info("Cached 10 KeyPairs for RSA communication");
|
||||
|
||||
testCipher((RSAPrivateKey) _keyPairs[0]._pair.getPrivate());
|
||||
|
||||
// Store keys for blowfish communication
|
||||
generateBlowFishKeys();
|
||||
|
||||
Thread purge = new PurgeThread();
|
||||
purge.setDaemon(true);
|
||||
purge.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is mostly to force the initialization of the Crypto Implementation, avoiding it being done on runtime when its first needed.<BR>
|
||||
* In short it avoids the worst-case execution time on runtime by doing it on loading.
|
||||
* @param key Any private RSA Key just for testing purposes.
|
||||
* @throws GeneralSecurityException if a underlying exception was thrown by the Cipher
|
||||
*/
|
||||
private void testCipher(RSAPrivateKey key) throws GeneralSecurityException
|
||||
{
|
||||
// avoid worst-case execution, KenM
|
||||
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
|
||||
rsaCipher.init(Cipher.DECRYPT_MODE, key);
|
||||
}
|
||||
|
||||
private void generateBlowFishKeys()
|
||||
{
|
||||
_blowfishKeys = new byte[BLOWFISH_KEYS][16];
|
||||
|
||||
for (int i = 0; i < BLOWFISH_KEYS; i++)
|
||||
{
|
||||
for (int j = 0; j < _blowfishKeys[i].length; j++)
|
||||
{
|
||||
_blowfishKeys[i][j] = (byte) (Rnd.nextInt(255) + 1);
|
||||
}
|
||||
}
|
||||
_log.info("Stored " + _blowfishKeys.length + " keys for Blowfish communication");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns a random key
|
||||
*/
|
||||
public byte[] getBlowfishKey()
|
||||
{
|
||||
return _blowfishKeys[(int) (Math.random() * BLOWFISH_KEYS)];
|
||||
}
|
||||
|
||||
public SessionKey assignSessionKeyToClient(String account, L2LoginClient client)
|
||||
{
|
||||
SessionKey key;
|
||||
|
||||
key = new SessionKey(Rnd.nextInt(), Rnd.nextInt(), Rnd.nextInt(), Rnd.nextInt());
|
||||
_loginServerClients.put(account, client);
|
||||
return key;
|
||||
}
|
||||
|
||||
public void removeAuthedLoginClient(String account)
|
||||
{
|
||||
if (account == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_loginServerClients.remove(account);
|
||||
}
|
||||
|
||||
public L2LoginClient getAuthedClient(String account)
|
||||
{
|
||||
return _loginServerClients.get(account);
|
||||
}
|
||||
|
||||
public AccountInfo retriveAccountInfo(InetAddress clientAddr, String login, String password)
|
||||
{
|
||||
return retriveAccountInfo(clientAddr, login, password, true);
|
||||
}
|
||||
|
||||
private void recordFailedLoginAttemp(InetAddress addr)
|
||||
{
|
||||
// We need to synchronize this!
|
||||
// When multiple connections from the same address fail to login at the
|
||||
// same time, unexpected behavior can happen.
|
||||
Integer failedLoginAttemps;
|
||||
synchronized (_failedLoginAttemps)
|
||||
{
|
||||
failedLoginAttemps = _failedLoginAttemps.get(addr);
|
||||
if (failedLoginAttemps == null)
|
||||
{
|
||||
failedLoginAttemps = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++failedLoginAttemps;
|
||||
}
|
||||
|
||||
_failedLoginAttemps.put(addr, failedLoginAttemps);
|
||||
}
|
||||
|
||||
if (failedLoginAttemps >= Config.LOGIN_TRY_BEFORE_BAN)
|
||||
{
|
||||
addBanForAddress(addr, Config.LOGIN_BLOCK_AFTER_BAN * 1000);
|
||||
// we need to clear the failed login attempts here, so after the ip ban is over the client has another 5 attempts
|
||||
clearFailedLoginAttemps(addr);
|
||||
_log.warning("Added banned address " + addr.getHostAddress() + "! Too many login attemps.");
|
||||
}
|
||||
}
|
||||
|
||||
private void clearFailedLoginAttemps(InetAddress addr)
|
||||
{
|
||||
synchronized (_failedLoginAttemps)
|
||||
{
|
||||
_failedLoginAttemps.remove(addr);
|
||||
}
|
||||
}
|
||||
|
||||
private AccountInfo retriveAccountInfo(InetAddress addr, String login, String password, boolean autoCreateIfEnabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
MessageDigest md = MessageDigest.getInstance("SHA");
|
||||
byte[] raw = password.getBytes(StandardCharsets.UTF_8);
|
||||
String hashBase64 = Base64.getEncoder().encodeToString(md.digest(raw));
|
||||
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
PreparedStatement ps = con.prepareStatement(USER_INFO_SELECT))
|
||||
{
|
||||
ps.setString(1, Long.toString(System.currentTimeMillis()));
|
||||
ps.setString(2, login);
|
||||
try (ResultSet rset = ps.executeQuery())
|
||||
{
|
||||
if (rset.next())
|
||||
{
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.fine("Account '" + login + "' exists.");
|
||||
}
|
||||
|
||||
AccountInfo info = new AccountInfo(rset.getString("login"), rset.getString("password"), rset.getInt("accessLevel"), rset.getInt("lastServer"));
|
||||
if (!info.checkPassHash(hashBase64))
|
||||
{
|
||||
// wrong password
|
||||
recordFailedLoginAttemp(addr);
|
||||
return null;
|
||||
}
|
||||
|
||||
clearFailedLoginAttemps(addr);
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!autoCreateIfEnabled || !Config.AUTO_CREATE_ACCOUNTS)
|
||||
{
|
||||
// account does not exist and auto create account is not desired
|
||||
recordFailedLoginAttemp(addr);
|
||||
return null;
|
||||
}
|
||||
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
PreparedStatement ps = con.prepareStatement(AUTOCREATE_ACCOUNTS_INSERT))
|
||||
{
|
||||
ps.setString(1, login);
|
||||
ps.setString(2, hashBase64);
|
||||
ps.setLong(3, System.currentTimeMillis());
|
||||
ps.setInt(4, 0);
|
||||
ps.setString(5, addr.getHostAddress());
|
||||
ps.execute();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.log(Level.WARNING, "Exception while auto creating account for '" + login + "'!", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
_log.info("Auto created account '" + login + "'.");
|
||||
return retriveAccountInfo(addr, login, password, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.log(Level.WARNING, "Exception while retriving account info for '" + login + "'!", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public AuthLoginResult tryCheckinAccount(L2LoginClient client, InetAddress address, AccountInfo info)
|
||||
{
|
||||
if (info.getAccessLevel() < 0)
|
||||
{
|
||||
return AuthLoginResult.ACCOUNT_BANNED;
|
||||
}
|
||||
|
||||
AuthLoginResult ret = AuthLoginResult.INVALID_PASSWORD;
|
||||
// check auth
|
||||
if (canCheckin(client, address, info))
|
||||
{
|
||||
// login was successful, verify presence on Gameservers
|
||||
ret = AuthLoginResult.ALREADY_ON_GS;
|
||||
if (!isAccountInAnyGameServer(info.getLogin()))
|
||||
{
|
||||
// account isnt on any GS verify LS itself
|
||||
ret = AuthLoginResult.ALREADY_ON_LS;
|
||||
|
||||
if (_loginServerClients.putIfAbsent(info.getLogin(), client) == null)
|
||||
{
|
||||
ret = AuthLoginResult.AUTH_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the address to the ban list of the login server, with the given end time in milliseconds.
|
||||
* @param address The Address to be banned.
|
||||
* @param expiration Timestamp in milliseconds when this ban expires
|
||||
* @throws UnknownHostException if the address is invalid.
|
||||
*/
|
||||
public void addBanForAddress(String address, long expiration) throws UnknownHostException
|
||||
{
|
||||
_bannedIps.putIfAbsent(InetAddress.getByName(address), expiration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the address to the ban list of the login server, with the given duration.
|
||||
* @param address The Address to be banned.
|
||||
* @param duration is milliseconds
|
||||
*/
|
||||
public void addBanForAddress(InetAddress address, long duration)
|
||||
{
|
||||
_bannedIps.putIfAbsent(address, System.currentTimeMillis() + duration);
|
||||
}
|
||||
|
||||
public boolean isBannedAddress(InetAddress address)
|
||||
{
|
||||
String[] parts = address.getHostAddress().split("\\.");
|
||||
Long bi = _bannedIps.get(address);
|
||||
if (bi == null)
|
||||
{
|
||||
bi = _bannedIps.get(parts[0] + "." + parts[1] + "." + parts[2] + ".0");
|
||||
}
|
||||
if (bi == null)
|
||||
{
|
||||
bi = _bannedIps.get(parts[0] + "." + parts[1] + ".0.0");
|
||||
}
|
||||
if (bi == null)
|
||||
{
|
||||
bi = _bannedIps.get(parts[0] + ".0.0.0");
|
||||
}
|
||||
if (bi != null)
|
||||
{
|
||||
if ((bi > 0) && (bi < System.currentTimeMillis()))
|
||||
{
|
||||
_bannedIps.remove(address);
|
||||
_log.info("Removed expired ip address ban " + address.getHostAddress() + ".");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Map<InetAddress, Long> getBannedIps()
|
||||
{
|
||||
return _bannedIps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified address from the ban list
|
||||
* @param address The address to be removed from the ban list
|
||||
* @return true if the ban was removed, false if there was no ban for this ip
|
||||
*/
|
||||
public boolean removeBanForAddress(InetAddress address)
|
||||
{
|
||||
return _bannedIps.remove(address.getHostAddress()) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified address from the ban list
|
||||
* @param address The address to be removed from the ban list
|
||||
* @return true if the ban was removed, false if there was no ban for this ip or the address was invalid.
|
||||
*/
|
||||
public boolean removeBanForAddress(String address)
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.removeBanForAddress(InetAddress.getByName(address));
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public SessionKey getKeyForAccount(String account)
|
||||
{
|
||||
L2LoginClient client = _loginServerClients.get(account);
|
||||
if (client != null)
|
||||
{
|
||||
return client.getSessionKey();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isAccountInAnyGameServer(String account)
|
||||
{
|
||||
Collection<GameServerInfo> serverList = GameServerTable.getInstance().getRegisteredGameServers().values();
|
||||
for (GameServerInfo gsi : serverList)
|
||||
{
|
||||
GameServerThread gst = gsi.getGameServerThread();
|
||||
if ((gst != null) && gst.hasAccountOnGameServer(account))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public GameServerInfo getAccountOnGameServer(String account)
|
||||
{
|
||||
Collection<GameServerInfo> serverList = GameServerTable.getInstance().getRegisteredGameServers().values();
|
||||
for (GameServerInfo gsi : serverList)
|
||||
{
|
||||
GameServerThread gst = gsi.getGameServerThread();
|
||||
if ((gst != null) && gst.hasAccountOnGameServer(account))
|
||||
{
|
||||
return gsi;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void getCharactersOnAccount(String account)
|
||||
{
|
||||
Collection<GameServerInfo> serverList = GameServerTable.getInstance().getRegisteredGameServers().values();
|
||||
for (GameServerInfo gsi : serverList)
|
||||
{
|
||||
if (gsi.isAuthed())
|
||||
{
|
||||
gsi.getGameServerThread().requestCharacters(account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param client
|
||||
* @param serverId
|
||||
* @return
|
||||
*/
|
||||
public boolean isLoginPossible(L2LoginClient client, int serverId)
|
||||
{
|
||||
GameServerInfo gsi = GameServerTable.getInstance().getRegisteredGameServerById(serverId);
|
||||
int access = client.getAccessLevel();
|
||||
if ((gsi != null) && gsi.isAuthed())
|
||||
{
|
||||
boolean loginOk = ((gsi.getCurrentPlayerCount() < gsi.getMaxPlayers()) && (gsi.getStatus() != ServerStatus.STATUS_GM_ONLY)) || (access > 0);
|
||||
|
||||
if (loginOk && (client.getLastServer() != serverId))
|
||||
{
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
PreparedStatement ps = con.prepareStatement(ACCOUNT_LAST_SERVER_UPDATE))
|
||||
{
|
||||
ps.setInt(1, serverId);
|
||||
ps.setString(2, client.getAccount());
|
||||
ps.executeUpdate();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.log(Level.WARNING, "Could not set lastServer: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return loginOk;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setAccountAccessLevel(String account, int banLevel)
|
||||
{
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
PreparedStatement ps = con.prepareStatement(ACCOUNT_ACCESS_LEVEL_UPDATE))
|
||||
{
|
||||
ps.setInt(1, banLevel);
|
||||
ps.setString(2, account);
|
||||
ps.executeUpdate();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.log(Level.WARNING, "Could not set accessLevel: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAccountLastTracert(String account, String pcIp, String hop1, String hop2, String hop3, String hop4)
|
||||
{
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
PreparedStatement ps = con.prepareStatement(ACCOUNT_IPS_UPDATE))
|
||||
{
|
||||
ps.setString(1, pcIp);
|
||||
ps.setString(2, hop1);
|
||||
ps.setString(3, hop2);
|
||||
ps.setString(4, hop3);
|
||||
ps.setString(5, hop4);
|
||||
ps.setString(6, account);
|
||||
ps.executeUpdate();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.log(Level.WARNING, "Could not set last tracert: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCharactersOnServer(String account, int charsNum, long[] timeToDel, int serverId)
|
||||
{
|
||||
L2LoginClient client = _loginServerClients.get(account);
|
||||
|
||||
if (client == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (charsNum > 0)
|
||||
{
|
||||
client.setCharsOnServ(serverId, charsNum);
|
||||
}
|
||||
|
||||
if (timeToDel.length > 0)
|
||||
{
|
||||
client.serCharsWaitingDelOnServ(serverId, timeToDel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This method returns one of the cached {@link ScrambledKeyPair ScrambledKeyPairs} for communication with Login Clients.
|
||||
* </p>
|
||||
* @return a scrambled keypair
|
||||
*/
|
||||
public ScrambledKeyPair getScrambledRSAKeyPair()
|
||||
{
|
||||
return _keyPairs[Rnd.nextInt(10)];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param client the client
|
||||
* @param address client host address
|
||||
* @param info the account info to checkin
|
||||
* @return true when ok to checkin, false otherwise
|
||||
*/
|
||||
public boolean canCheckin(L2LoginClient client, InetAddress address, AccountInfo info)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<InetAddress> ipWhiteList = new ArrayList<>();
|
||||
List<InetAddress> ipBlackList = new ArrayList<>();
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
PreparedStatement ps = con.prepareStatement(ACCOUNT_IPAUTH_SELECT))
|
||||
{
|
||||
ps.setString(1, info.getLogin());
|
||||
try (ResultSet rset = ps.executeQuery())
|
||||
{
|
||||
String ip, type;
|
||||
while (rset.next())
|
||||
{
|
||||
ip = rset.getString("ip");
|
||||
type = rset.getString("type");
|
||||
|
||||
if (!isValidIPAddress(ip))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (type.equals("allow"))
|
||||
{
|
||||
ipWhiteList.add(InetAddress.getByName(ip));
|
||||
}
|
||||
else if (type.equals("deny"))
|
||||
{
|
||||
ipBlackList.add(InetAddress.getByName(ip));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check IP
|
||||
if (!ipWhiteList.isEmpty() || !ipBlackList.isEmpty())
|
||||
{
|
||||
if (!ipWhiteList.isEmpty() && !ipWhiteList.contains(address))
|
||||
{
|
||||
_log.warning("Account checkin attemp from address(" + address.getHostAddress() + ") not present on whitelist for account '" + info.getLogin() + "'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ipBlackList.isEmpty() && ipBlackList.contains(address))
|
||||
{
|
||||
_log.warning("Account checkin attemp from address(" + address.getHostAddress() + ") on blacklist for account '" + info.getLogin() + "'.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
client.setAccessLevel(info.getAccessLevel());
|
||||
client.setLastServer(info.getLastServer());
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
PreparedStatement ps = con.prepareStatement(ACCOUNT_INFO_UPDATE))
|
||||
{
|
||||
ps.setLong(1, System.currentTimeMillis());
|
||||
ps.setString(2, address.getHostAddress());
|
||||
ps.setString(3, info.getLogin());
|
||||
ps.execute();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.log(Level.WARNING, "Could not finish login process!", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isValidIPAddress(String ipAddress)
|
||||
{
|
||||
String[] parts = ipAddress.split("\\.");
|
||||
if (parts.length != 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String s : parts)
|
||||
{
|
||||
int i = Integer.parseInt(s);
|
||||
if ((i < 0) || (i > 255))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void load() throws GeneralSecurityException
|
||||
{
|
||||
synchronized (LoginController.class)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new LoginController();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("LoginController can only be loaded a single time.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static LoginController getInstance()
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
|
||||
class PurgeThread extends Thread
|
||||
{
|
||||
public PurgeThread()
|
||||
{
|
||||
setName("PurgeThread");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while (!isInterrupted())
|
||||
{
|
||||
for (L2LoginClient client : _loginServerClients.values())
|
||||
{
|
||||
if (client == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((client.getConnectionStartTime() + LOGIN_TIMEOUT) < System.currentTimeMillis())
|
||||
{
|
||||
client.close(LoginFailReason.REASON_ACCESS_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(LOGIN_TIMEOUT / 2);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static enum AuthLoginResult
|
||||
{
|
||||
INVALID_PASSWORD,
|
||||
ACCOUNT_BANNED,
|
||||
ALREADY_ON_LS,
|
||||
ALREADY_ON_GS,
|
||||
AUTH_SUCCESS
|
||||
}
|
||||
}
|
69
trunk/java/com/l2jserver/loginserver/SelectorHelper.java
Normal file
69
trunk/java/com/l2jserver/loginserver/SelectorHelper.java
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver;
|
||||
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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;
|
||||
|
||||
import com.l2jserver.loginserver.network.L2LoginClient;
|
||||
import com.l2jserver.loginserver.network.serverpackets.Init;
|
||||
import com.l2jserver.util.IPv4Filter;
|
||||
|
||||
/**
|
||||
* @author KenM
|
||||
*/
|
||||
public class SelectorHelper implements IMMOExecutor<L2LoginClient>, IClientFactory<L2LoginClient>, IAcceptFilter
|
||||
{
|
||||
private final ThreadPoolExecutor _generalPacketsThreadPool;
|
||||
private final IPv4Filter _ipv4filter;
|
||||
|
||||
public SelectorHelper()
|
||||
{
|
||||
_generalPacketsThreadPool = new ThreadPoolExecutor(4, 6, 15L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
|
||||
_ipv4filter = new IPv4Filter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ReceivablePacket<L2LoginClient> packet)
|
||||
{
|
||||
_generalPacketsThreadPool.execute(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public L2LoginClient create(MMOConnection<L2LoginClient> con)
|
||||
{
|
||||
L2LoginClient client = new L2LoginClient(con);
|
||||
client.sendPacket(new Init(client));
|
||||
return client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SocketChannel sc)
|
||||
{
|
||||
return _ipv4filter.accept(sc) && !LoginController.getInstance().isBannedAddress(sc.socket().getInetAddress());
|
||||
}
|
||||
}
|
82
trunk/java/com/l2jserver/loginserver/SessionKey.java
Normal file
82
trunk/java/com/l2jserver/loginserver/SessionKey.java
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class is used to represent session keys used by the client to authenticate in the gameserver
|
||||
* </p>
|
||||
* <p>
|
||||
* A SessionKey is made up of two 8 bytes keys. One is send in the {@link com.l2jserver.loginserver.network.serverpackets.LoginOk#LoginOk} packet and the other is sent in {@link com.l2jserver.loginserver.network.serverpackets.PlayOk#PlayOk}
|
||||
* </p>
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class SessionKey
|
||||
{
|
||||
public int playOkID1;
|
||||
public int playOkID2;
|
||||
public int loginOkID1;
|
||||
public int loginOkID2;
|
||||
|
||||
public SessionKey(int loginOK1, int loginOK2, int playOK1, int playOK2)
|
||||
{
|
||||
playOkID1 = playOK1;
|
||||
playOkID2 = playOK2;
|
||||
loginOkID1 = loginOK1;
|
||||
loginOkID2 = loginOK2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "PlayOk: " + playOkID1 + " " + playOkID2 + " LoginOk:" + loginOkID1 + " " + loginOkID2;
|
||||
}
|
||||
|
||||
public boolean checkLoginPair(int loginOk1, int loginOk2)
|
||||
{
|
||||
return (loginOkID1 == loginOk1) && (loginOkID2 == loginOk2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only checks the PlayOk part of the session key if server doesn't show the license when player logs in.
|
||||
* @param o
|
||||
* @return true if keys are equal.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof SessionKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final SessionKey key = (SessionKey) o;
|
||||
// when server doesn't show license it doesn't send the LoginOk packet, client doesn't have this part of the key then.
|
||||
if (Config.SHOW_LICENCE)
|
||||
{
|
||||
return ((playOkID1 == key.playOkID1) && (loginOkID1 == key.loginOkID1) && (playOkID2 == key.playOkID2) && (loginOkID2 == key.loginOkID2));
|
||||
}
|
||||
return ((playOkID1 == key.playOkID1) && (playOkID2 == key.playOkID2));
|
||||
}
|
||||
}
|
165
trunk/java/com/l2jserver/loginserver/mail/BaseMail.java
Normal file
165
trunk/java/com/l2jserver/loginserver/mail/BaseMail.java
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.mail;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.mail.Authenticator;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.PasswordAuthentication;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Transport;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.L2DatabaseFactory;
|
||||
import com.l2jserver.loginserver.mail.MailSystem.MailContent;
|
||||
|
||||
/**
|
||||
* @author mrTJO
|
||||
*/
|
||||
public class BaseMail implements Runnable
|
||||
{
|
||||
private static final Logger _log = Logger.getLogger(BaseMail.class.getName());
|
||||
|
||||
private MimeMessage _messageMime = null;
|
||||
|
||||
private class SmtpAuthenticator extends Authenticator
|
||||
{
|
||||
private final PasswordAuthentication _auth;
|
||||
|
||||
public SmtpAuthenticator()
|
||||
{
|
||||
_auth = new PasswordAuthentication(Config.EMAIL_SYS_USERNAME, Config.EMAIL_SYS_PASSWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PasswordAuthentication getPasswordAuthentication()
|
||||
{
|
||||
return _auth;
|
||||
}
|
||||
}
|
||||
|
||||
public BaseMail(String account, String mailId, String... args)
|
||||
{
|
||||
String mailAddr = getUserMail(account);
|
||||
|
||||
if (mailAddr == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MailContent content = MailSystem.getInstance().getMailContent(mailId);
|
||||
if (content == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String message = compileHtml(account, content.getText(), args);
|
||||
|
||||
final Properties mailProp = new Properties();
|
||||
mailProp.put("mail.smtp.host", Config.EMAIL_SYS_HOST);
|
||||
mailProp.put("mail.smtp.auth", Config.EMAIL_SYS_SMTP_AUTH);
|
||||
mailProp.put("mail.smtp.port", Config.EMAIL_SYS_PORT);
|
||||
mailProp.put("mail.smtp.socketFactory.port", Config.EMAIL_SYS_PORT);
|
||||
mailProp.put("mail.smtp.socketFactory.class", Config.EMAIL_SYS_FACTORY);
|
||||
mailProp.put("mail.smtp.socketFactory.fallback", Config.EMAIL_SYS_FACTORY_CALLBACK);
|
||||
final SmtpAuthenticator authenticator = (Config.EMAIL_SYS_SMTP_AUTH ? new SmtpAuthenticator() : null);
|
||||
|
||||
Session mailSession = Session.getDefaultInstance(mailProp, authenticator);
|
||||
|
||||
try
|
||||
{
|
||||
_messageMime = new MimeMessage(mailSession);
|
||||
_messageMime.setSubject(content.getSubject());
|
||||
try
|
||||
{
|
||||
_messageMime.setFrom(new InternetAddress(Config.EMAIL_SYS_ADDRESS, Config.EMAIL_SERVERINFO_NAME));
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
_log.warning("Sender Address not Valid!");
|
||||
}
|
||||
_messageMime.setContent(message, "text/html");
|
||||
_messageMime.setRecipient(Message.RecipientType.TO, new InternetAddress(mailAddr));
|
||||
}
|
||||
catch (MessagingException e)
|
||||
{
|
||||
_log.warning(getClass().getSimpleName() + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String compileHtml(String account, String html, String[] args)
|
||||
{
|
||||
if (args != null)
|
||||
{
|
||||
for (int i = 0; i < args.length; i++)
|
||||
{
|
||||
html = html.replace("%var" + i + "%", args[i]);
|
||||
}
|
||||
}
|
||||
html = html.replace("%accountname%", account);
|
||||
return html;
|
||||
}
|
||||
|
||||
private String getUserMail(String username)
|
||||
{
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
PreparedStatement statement = con.prepareStatement(Config.EMAIL_SYS_SELECTQUERY))
|
||||
{
|
||||
statement.setString(1, username);
|
||||
try (ResultSet rset = statement.executeQuery())
|
||||
{
|
||||
if (rset.next())
|
||||
{
|
||||
String mail = rset.getString(Config.EMAIL_SYS_DBFIELD);
|
||||
return mail;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.warning("Cannot select user mail: Exception");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_messageMime != null)
|
||||
{
|
||||
Transport.send(_messageMime);
|
||||
}
|
||||
}
|
||||
catch (MessagingException e)
|
||||
{
|
||||
_log.warning("Error encounterd while sending email");
|
||||
}
|
||||
}
|
||||
}
|
155
trunk/java/com/l2jserver/loginserver/mail/MailSystem.java
Normal file
155
trunk/java/com/l2jserver/loginserver/mail/MailSystem.java
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.mail;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import javolution.util.FastMap;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
|
||||
/**
|
||||
* @author mrTJO
|
||||
*/
|
||||
public class MailSystem
|
||||
{
|
||||
private static final Logger _log = Logger.getLogger(MailSystem.class.getName());
|
||||
private final Map<String, MailContent> _mailData = new FastMap<>();
|
||||
|
||||
public static MailSystem getInstance()
|
||||
{
|
||||
return SingletonHolder._instance;
|
||||
}
|
||||
|
||||
public MailSystem()
|
||||
{
|
||||
loadMails();
|
||||
}
|
||||
|
||||
public void sendMail(String account, String messageId, String... args)
|
||||
{
|
||||
BaseMail mail = new BaseMail(account, messageId, args);
|
||||
mail.run();
|
||||
}
|
||||
|
||||
private void loadMails()
|
||||
{
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setValidating(false);
|
||||
factory.setIgnoringComments(true);
|
||||
File file = new File(Config.DATAPACK_ROOT, "data/mail/MailList.xml");
|
||||
Document doc = null;
|
||||
if (file.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
doc = factory.newDocumentBuilder().parse(file);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.log(Level.WARNING, "Could not parse MailList.xml file: " + e.getMessage(), e);
|
||||
return;
|
||||
}
|
||||
|
||||
Node n = doc.getFirstChild();
|
||||
File mailFile;
|
||||
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
|
||||
{
|
||||
if (d.getNodeName().equals("mail"))
|
||||
{
|
||||
String mailId = d.getAttributes().getNamedItem("id").getNodeValue();
|
||||
String subject = d.getAttributes().getNamedItem("subject").getNodeValue();
|
||||
String maFile = d.getAttributes().getNamedItem("file").getNodeValue();
|
||||
|
||||
mailFile = new File(Config.DATAPACK_ROOT, "data/mail/" + maFile);
|
||||
try (FileInputStream fis = new FileInputStream(mailFile);
|
||||
BufferedInputStream bis = new BufferedInputStream(fis))
|
||||
{
|
||||
int bytes = bis.available();
|
||||
byte[] raw = new byte[bytes];
|
||||
|
||||
bis.read(raw);
|
||||
String html = new String(raw, "UTF-8");
|
||||
html = html.replaceAll(Config.EOL, "\n");
|
||||
html = html.replace("%servermail%", Config.EMAIL_SERVERINFO_ADDRESS);
|
||||
html = html.replace("%servername%", Config.EMAIL_SERVERINFO_NAME);
|
||||
|
||||
_mailData.put(mailId, new MailContent(subject, html));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.warning("IOException while reading " + maFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
_log.info("eMail System Loaded");
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.warning("Cannot load eMail System - Missing file MailList.xml");
|
||||
}
|
||||
}
|
||||
|
||||
public class MailContent
|
||||
{
|
||||
private final String _subject;
|
||||
private final String _text;
|
||||
|
||||
/**
|
||||
* @param subject
|
||||
* @param text
|
||||
*/
|
||||
public MailContent(String subject, String text)
|
||||
{
|
||||
_subject = subject;
|
||||
_text = text;
|
||||
}
|
||||
|
||||
public String getSubject()
|
||||
{
|
||||
return _subject;
|
||||
}
|
||||
|
||||
public String getText()
|
||||
{
|
||||
return _text;
|
||||
}
|
||||
}
|
||||
|
||||
public MailContent getMailContent(String mailId)
|
||||
{
|
||||
return _mailData.get(mailId);
|
||||
}
|
||||
|
||||
private static class SingletonHolder
|
||||
{
|
||||
protected static final MailSystem _instance = new MailSystem();
|
||||
}
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.model.data;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author HorridoJoho
|
||||
*/
|
||||
public final class AccountInfo
|
||||
{
|
||||
private final String _login;
|
||||
private final String _passHash;
|
||||
private final int _accessLevel;
|
||||
private final int _lastServer;
|
||||
|
||||
public AccountInfo(final String login, final String passHash, final int accessLevel, final int lastServer)
|
||||
{
|
||||
Objects.requireNonNull(login, "login");
|
||||
Objects.requireNonNull(passHash, "passHash");
|
||||
|
||||
if (login.isEmpty())
|
||||
{
|
||||
throw new IllegalArgumentException("login");
|
||||
}
|
||||
if (passHash.isEmpty())
|
||||
{
|
||||
throw new IllegalArgumentException("passHash");
|
||||
}
|
||||
|
||||
_login = login.toLowerCase();
|
||||
_passHash = passHash;
|
||||
_accessLevel = accessLevel;
|
||||
_lastServer = lastServer;
|
||||
}
|
||||
|
||||
public boolean checkPassHash(final String passHash)
|
||||
{
|
||||
return _passHash.equals(passHash);
|
||||
}
|
||||
|
||||
public String getLogin()
|
||||
{
|
||||
return _login;
|
||||
}
|
||||
|
||||
public int getAccessLevel()
|
||||
{
|
||||
return _accessLevel;
|
||||
}
|
||||
|
||||
public int getLastServer()
|
||||
{
|
||||
return _lastServer;
|
||||
}
|
||||
}
|
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.loginserver.GameServerThread;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.BlowFishKey;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.ChangeAccessLevel;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.ChangePassword;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.GameServerAuth;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.PlayerAuthRequest;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.PlayerInGame;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.PlayerLogout;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.PlayerTracert;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.ReplyCharacters;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.RequestSendMail;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.RequestTempBan;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.ServerStatus;
|
||||
import com.l2jserver.loginserver.network.loginserverpackets.LoginServerFail;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* @author mrTJO
|
||||
*/
|
||||
public class L2JGameServerPacketHandler
|
||||
{
|
||||
protected static Logger _log = Logger.getLogger(L2JGameServerPacketHandler.class.getName());
|
||||
|
||||
public static enum GameServerState
|
||||
{
|
||||
CONNECTED,
|
||||
BF_CONNECTED,
|
||||
AUTHED
|
||||
}
|
||||
|
||||
public static BaseRecievePacket handlePacket(byte[] data, GameServerThread server)
|
||||
{
|
||||
BaseRecievePacket msg = null;
|
||||
int opcode = data[0] & 0xff;
|
||||
GameServerState state = server.getLoginConnectionState();
|
||||
switch (state)
|
||||
{
|
||||
case CONNECTED:
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x00:
|
||||
msg = new BlowFishKey(data, server);
|
||||
break;
|
||||
default:
|
||||
_log.warning("Unknown Opcode (" + Integer.toHexString(opcode).toUpperCase() + ") in state " + state.name() + " from GameServer, closing connection.");
|
||||
server.forceClose(LoginServerFail.NOT_AUTHED);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BF_CONNECTED:
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x01:
|
||||
msg = new GameServerAuth(data, server);
|
||||
break;
|
||||
default:
|
||||
_log.warning("Unknown Opcode (" + Integer.toHexString(opcode).toUpperCase() + ") in state " + state.name() + " from GameServer, closing connection.");
|
||||
server.forceClose(LoginServerFail.NOT_AUTHED);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AUTHED:
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x02:
|
||||
msg = new PlayerInGame(data, server);
|
||||
break;
|
||||
case 0x03:
|
||||
msg = new PlayerLogout(data, server);
|
||||
break;
|
||||
case 0x04:
|
||||
msg = new ChangeAccessLevel(data, server);
|
||||
break;
|
||||
case 0x05:
|
||||
msg = new PlayerAuthRequest(data, server);
|
||||
break;
|
||||
case 0x06:
|
||||
msg = new ServerStatus(data, server);
|
||||
break;
|
||||
case 0x07:
|
||||
msg = new PlayerTracert(data);
|
||||
break;
|
||||
case 0x08:
|
||||
msg = new ReplyCharacters(data, server);
|
||||
break;
|
||||
case 0x09:
|
||||
if (Config.EMAIL_SYS_ENABLED)
|
||||
{
|
||||
msg = new RequestSendMail(data);
|
||||
}
|
||||
break;
|
||||
case 0x0A:
|
||||
msg = new RequestTempBan(data);
|
||||
break;
|
||||
case 0x0B:
|
||||
new ChangePassword(data);
|
||||
break;
|
||||
default:
|
||||
_log.warning("Unknown Opcode (" + Integer.toHexString(opcode).toUpperCase() + ") in state " + state.name() + " from GameServer, closing connection.");
|
||||
server.forceClose(LoginServerFail.NOT_AUTHED);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
}
|
296
trunk/java/com/l2jserver/loginserver/network/L2LoginClient.java
Normal file
296
trunk/java/com/l2jserver/loginserver/network/L2LoginClient.java
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.mmocore.network.MMOClient;
|
||||
import org.mmocore.network.MMOConnection;
|
||||
import org.mmocore.network.SendablePacket;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.loginserver.LoginController;
|
||||
import com.l2jserver.loginserver.SessionKey;
|
||||
import com.l2jserver.loginserver.network.serverpackets.L2LoginServerPacket;
|
||||
import com.l2jserver.loginserver.network.serverpackets.LoginFail;
|
||||
import com.l2jserver.loginserver.network.serverpackets.LoginFail.LoginFailReason;
|
||||
import com.l2jserver.loginserver.network.serverpackets.PlayFail;
|
||||
import com.l2jserver.loginserver.network.serverpackets.PlayFail.PlayFailReason;
|
||||
import com.l2jserver.util.Rnd;
|
||||
import com.l2jserver.util.crypt.LoginCrypt;
|
||||
import com.l2jserver.util.crypt.ScrambledKeyPair;
|
||||
|
||||
/**
|
||||
* Represents a client connected into the LoginServer
|
||||
* @author KenM
|
||||
*/
|
||||
public final class L2LoginClient extends MMOClient<MMOConnection<L2LoginClient>>
|
||||
{
|
||||
private static final Logger _log = Logger.getLogger(L2LoginClient.class.getName());
|
||||
|
||||
public static enum LoginClientState
|
||||
{
|
||||
CONNECTED,
|
||||
AUTHED_GG,
|
||||
AUTHED_LOGIN
|
||||
}
|
||||
|
||||
private LoginClientState _state;
|
||||
|
||||
// Crypt
|
||||
private final LoginCrypt _loginCrypt;
|
||||
private final ScrambledKeyPair _scrambledPair;
|
||||
private final byte[] _blowfishKey;
|
||||
|
||||
private String _account;
|
||||
private int _accessLevel;
|
||||
private int _lastServer;
|
||||
private SessionKey _sessionKey;
|
||||
private final int _sessionId;
|
||||
private boolean _joinedGS;
|
||||
private Map<Integer, Integer> _charsOnServers;
|
||||
private Map<Integer, long[]> _charsToDelete;
|
||||
|
||||
private final long _connectionStartTime;
|
||||
|
||||
/**
|
||||
* @param con
|
||||
*/
|
||||
public L2LoginClient(MMOConnection<L2LoginClient> con)
|
||||
{
|
||||
super(con);
|
||||
_state = LoginClientState.CONNECTED;
|
||||
_scrambledPair = LoginController.getInstance().getScrambledRSAKeyPair();
|
||||
_blowfishKey = LoginController.getInstance().getBlowfishKey();
|
||||
_sessionId = Rnd.nextInt();
|
||||
_connectionStartTime = System.currentTimeMillis();
|
||||
_loginCrypt = new LoginCrypt();
|
||||
_loginCrypt.setKey(_blowfishKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decrypt(ByteBuffer buf, int size)
|
||||
{
|
||||
boolean isChecksumValid = false;
|
||||
try
|
||||
{
|
||||
isChecksumValid = _loginCrypt.decrypt(buf.array(), buf.position(), size);
|
||||
if (!isChecksumValid)
|
||||
{
|
||||
_log.warning("Wrong checksum from client: " + toString());
|
||||
super.getConnection().close((SendablePacket<L2LoginClient>) null);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.warning(getClass().getSimpleName() + ": " + e.getMessage());
|
||||
super.getConnection().close((SendablePacket<L2LoginClient>) null);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean encrypt(ByteBuffer buf, int size)
|
||||
{
|
||||
final int offset = buf.position();
|
||||
try
|
||||
{
|
||||
size = _loginCrypt.encrypt(buf.array(), offset, size);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.warning(getClass().getSimpleName() + ": " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
buf.position(offset + size);
|
||||
return true;
|
||||
}
|
||||
|
||||
public LoginClientState getState()
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
|
||||
public void setState(LoginClientState state)
|
||||
{
|
||||
_state = state;
|
||||
}
|
||||
|
||||
public byte[] getBlowfishKey()
|
||||
{
|
||||
return _blowfishKey;
|
||||
}
|
||||
|
||||
public byte[] getScrambledModulus()
|
||||
{
|
||||
return _scrambledPair._scrambledModulus;
|
||||
}
|
||||
|
||||
public RSAPrivateKey getRSAPrivateKey()
|
||||
{
|
||||
return (RSAPrivateKey) _scrambledPair._pair.getPrivate();
|
||||
}
|
||||
|
||||
public String getAccount()
|
||||
{
|
||||
return _account;
|
||||
}
|
||||
|
||||
public void setAccount(String account)
|
||||
{
|
||||
_account = account;
|
||||
}
|
||||
|
||||
public void setAccessLevel(int accessLevel)
|
||||
{
|
||||
_accessLevel = accessLevel;
|
||||
}
|
||||
|
||||
public int getAccessLevel()
|
||||
{
|
||||
return _accessLevel;
|
||||
}
|
||||
|
||||
public void setLastServer(int lastServer)
|
||||
{
|
||||
_lastServer = lastServer;
|
||||
}
|
||||
|
||||
public int getLastServer()
|
||||
{
|
||||
return _lastServer;
|
||||
}
|
||||
|
||||
public int getSessionId()
|
||||
{
|
||||
return _sessionId;
|
||||
}
|
||||
|
||||
public boolean hasJoinedGS()
|
||||
{
|
||||
return _joinedGS;
|
||||
}
|
||||
|
||||
public void setJoinedGS(boolean val)
|
||||
{
|
||||
_joinedGS = val;
|
||||
}
|
||||
|
||||
public void setSessionKey(SessionKey sessionKey)
|
||||
{
|
||||
_sessionKey = sessionKey;
|
||||
}
|
||||
|
||||
public SessionKey getSessionKey()
|
||||
{
|
||||
return _sessionKey;
|
||||
}
|
||||
|
||||
public long getConnectionStartTime()
|
||||
{
|
||||
return _connectionStartTime;
|
||||
}
|
||||
|
||||
public void sendPacket(L2LoginServerPacket lsp)
|
||||
{
|
||||
getConnection().sendPacket(lsp);
|
||||
}
|
||||
|
||||
public void close(LoginFailReason reason)
|
||||
{
|
||||
getConnection().close(new LoginFail(reason));
|
||||
}
|
||||
|
||||
public void close(PlayFailReason reason)
|
||||
{
|
||||
getConnection().close(new PlayFail(reason));
|
||||
}
|
||||
|
||||
public void close(L2LoginServerPacket lsp)
|
||||
{
|
||||
getConnection().close(lsp);
|
||||
}
|
||||
|
||||
public void setCharsOnServ(int servId, int chars)
|
||||
{
|
||||
if (_charsOnServers == null)
|
||||
{
|
||||
_charsOnServers = new HashMap<>();
|
||||
}
|
||||
_charsOnServers.put(servId, chars);
|
||||
}
|
||||
|
||||
public Map<Integer, Integer> getCharsOnServ()
|
||||
{
|
||||
return _charsOnServers;
|
||||
}
|
||||
|
||||
public void serCharsWaitingDelOnServ(int servId, long[] charsToDel)
|
||||
{
|
||||
if (_charsToDelete == null)
|
||||
{
|
||||
_charsToDelete = new HashMap<>();
|
||||
}
|
||||
_charsToDelete.put(servId, charsToDel);
|
||||
}
|
||||
|
||||
public Map<Integer, long[]> getCharsWaitingDelOnServ()
|
||||
{
|
||||
return _charsToDelete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnection()
|
||||
{
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.info("DISCONNECTED: " + toString());
|
||||
}
|
||||
|
||||
if (!hasJoinedGS() || ((getConnectionStartTime() + LoginController.LOGIN_TIMEOUT) < System.currentTimeMillis()))
|
||||
{
|
||||
LoginController.getInstance().removeAuthedLoginClient(getAccount());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
InetAddress address = getConnection().getInetAddress();
|
||||
if (getState() == LoginClientState.AUTHED_LOGIN)
|
||||
{
|
||||
return "[" + getAccount() + " (" + (address == null ? "disconnected" : address.getHostAddress()) + ")]";
|
||||
}
|
||||
return "[" + (address == null ? "disconnected" : address.getHostAddress()) + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onForcedDisconnection()
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.mmocore.network.IPacketHandler;
|
||||
import org.mmocore.network.ReceivablePacket;
|
||||
|
||||
import com.l2jserver.loginserver.network.L2LoginClient.LoginClientState;
|
||||
import com.l2jserver.loginserver.network.clientpackets.AuthGameGuard;
|
||||
import com.l2jserver.loginserver.network.clientpackets.RequestAuthLogin;
|
||||
import com.l2jserver.loginserver.network.clientpackets.RequestServerList;
|
||||
import com.l2jserver.loginserver.network.clientpackets.RequestServerLogin;
|
||||
|
||||
/**
|
||||
* Handler for packets received by Login Server
|
||||
* @author KenM
|
||||
*/
|
||||
public final class L2LoginPacketHandler implements IPacketHandler<L2LoginClient>
|
||||
{
|
||||
protected static final Logger _log = Logger.getLogger(L2LoginPacketHandler.class.getName());
|
||||
|
||||
@Override
|
||||
public ReceivablePacket<L2LoginClient> handlePacket(ByteBuffer buf, L2LoginClient client)
|
||||
{
|
||||
int opcode = buf.get() & 0xFF;
|
||||
|
||||
ReceivablePacket<L2LoginClient> packet = null;
|
||||
LoginClientState state = client.getState();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case CONNECTED:
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x07:
|
||||
packet = new AuthGameGuard();
|
||||
break;
|
||||
default:
|
||||
debugOpcode(opcode, state);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AUTHED_GG:
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x00:
|
||||
packet = new RequestAuthLogin();
|
||||
break;
|
||||
default:
|
||||
debugOpcode(opcode, state);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AUTHED_LOGIN:
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x02:
|
||||
packet = new RequestServerLogin();
|
||||
break;
|
||||
case 0x05:
|
||||
packet = new RequestServerList();
|
||||
break;
|
||||
default:
|
||||
debugOpcode(opcode, state);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private void debugOpcode(int opcode, LoginClientState state)
|
||||
{
|
||||
_log.info("Unknown Opcode: " + opcode + " for state: " + state.name());
|
||||
}
|
||||
}
|
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.clientpackets;
|
||||
|
||||
import com.l2jserver.loginserver.network.L2LoginClient.LoginClientState;
|
||||
import com.l2jserver.loginserver.network.serverpackets.GGAuth;
|
||||
import com.l2jserver.loginserver.network.serverpackets.LoginFail.LoginFailReason;
|
||||
|
||||
/**
|
||||
* Format: ddddd
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class AuthGameGuard extends L2LoginClientPacket
|
||||
{
|
||||
private int _sessionId;
|
||||
private int _data1;
|
||||
private int _data2;
|
||||
private int _data3;
|
||||
private int _data4;
|
||||
|
||||
public int getSessionId()
|
||||
{
|
||||
return _sessionId;
|
||||
}
|
||||
|
||||
public int getData1()
|
||||
{
|
||||
return _data1;
|
||||
}
|
||||
|
||||
public int getData2()
|
||||
{
|
||||
return _data2;
|
||||
}
|
||||
|
||||
public int getData3()
|
||||
{
|
||||
return _data3;
|
||||
}
|
||||
|
||||
public int getData4()
|
||||
{
|
||||
return _data4;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readImpl()
|
||||
{
|
||||
if (super._buf.remaining() >= 20)
|
||||
{
|
||||
_sessionId = readD();
|
||||
_data1 = readD();
|
||||
_data2 = readD();
|
||||
_data3 = readD();
|
||||
_data4 = readD();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (_sessionId == getClient().getSessionId())
|
||||
{
|
||||
getClient().setState(LoginClientState.AUTHED_GG);
|
||||
getClient().sendPacket(new GGAuth(getClient().getSessionId()));
|
||||
}
|
||||
else
|
||||
{
|
||||
getClient().close(LoginFailReason.REASON_ACCESS_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.clientpackets;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.mmocore.network.ReceivablePacket;
|
||||
|
||||
import com.l2jserver.loginserver.network.L2LoginClient;
|
||||
|
||||
/**
|
||||
* @author KenM
|
||||
*/
|
||||
public abstract class L2LoginClientPacket extends ReceivablePacket<L2LoginClient>
|
||||
{
|
||||
private static Logger _log = Logger.getLogger(L2LoginClientPacket.class.getName());
|
||||
|
||||
@Override
|
||||
protected final boolean read()
|
||||
{
|
||||
try
|
||||
{
|
||||
return readImpl();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.log(Level.SEVERE, "ERROR READING: " + this.getClass().getSimpleName() + ": " + e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean readImpl();
|
||||
}
|
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.clientpackets;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.loginserver.GameServerTable.GameServerInfo;
|
||||
import com.l2jserver.loginserver.LoginController;
|
||||
import com.l2jserver.loginserver.LoginController.AuthLoginResult;
|
||||
import com.l2jserver.loginserver.model.data.AccountInfo;
|
||||
import com.l2jserver.loginserver.network.L2LoginClient;
|
||||
import com.l2jserver.loginserver.network.L2LoginClient.LoginClientState;
|
||||
import com.l2jserver.loginserver.network.serverpackets.AccountKicked;
|
||||
import com.l2jserver.loginserver.network.serverpackets.AccountKicked.AccountKickedReason;
|
||||
import com.l2jserver.loginserver.network.serverpackets.LoginFail.LoginFailReason;
|
||||
import com.l2jserver.loginserver.network.serverpackets.LoginOk;
|
||||
import com.l2jserver.loginserver.network.serverpackets.ServerList;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Format: x
|
||||
* 0 (a leading null)
|
||||
* x: the rsa encrypted block with the login an password.
|
||||
*
|
||||
* <pre>
|
||||
*/
|
||||
public class RequestAuthLogin extends L2LoginClientPacket
|
||||
{
|
||||
private static Logger _log = Logger.getLogger(RequestAuthLogin.class.getName());
|
||||
|
||||
private final byte[] _raw1 = new byte[128];
|
||||
private final byte[] _raw2 = new byte[128];
|
||||
private boolean _newAuthMethod = false;
|
||||
|
||||
private String _user;
|
||||
private String _password;
|
||||
private int _ncotp;
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getPassword()
|
||||
{
|
||||
return _password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getUser()
|
||||
{
|
||||
return _user;
|
||||
}
|
||||
|
||||
public int getOneTimePassword()
|
||||
{
|
||||
return _ncotp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readImpl()
|
||||
{
|
||||
if (super._buf.remaining() >= 256)
|
||||
{
|
||||
_newAuthMethod = true;
|
||||
readB(_raw1);
|
||||
readB(_raw2);
|
||||
return true;
|
||||
}
|
||||
else if (super._buf.remaining() >= 128)
|
||||
{
|
||||
readB(_raw1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
byte[] decUser = null;
|
||||
byte[] decPass = null;
|
||||
final L2LoginClient client = getClient();
|
||||
try
|
||||
{
|
||||
final Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
|
||||
rsaCipher.init(Cipher.DECRYPT_MODE, client.getRSAPrivateKey());
|
||||
decUser = rsaCipher.doFinal(_raw1, 0x00, 0x80);
|
||||
if (_newAuthMethod)
|
||||
{
|
||||
decPass = rsaCipher.doFinal(_raw2, 0x00, 0x80);
|
||||
}
|
||||
}
|
||||
catch (GeneralSecurityException e)
|
||||
{
|
||||
_log.log(Level.INFO, "", e);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (_newAuthMethod)
|
||||
{
|
||||
_user = new String(decUser, 0x4E, 0xE).trim().toLowerCase();
|
||||
_password = new String(decPass, 0x5C, 0x10).trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
_user = new String(decUser, 0x5E, 0xE).trim().toLowerCase();
|
||||
_password = new String(decUser, 0x6C, 0x10).trim();
|
||||
}
|
||||
_ncotp = decUser[0x7c];
|
||||
_ncotp |= decUser[0x7d] << 8;
|
||||
_ncotp |= decUser[0x7e] << 16;
|
||||
_ncotp |= decUser[0x7f] << 24;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.log(Level.WARNING, "", e);
|
||||
return;
|
||||
}
|
||||
|
||||
InetAddress clientAddr = getClient().getConnection().getInetAddress();
|
||||
|
||||
final LoginController lc = LoginController.getInstance();
|
||||
AccountInfo info = lc.retriveAccountInfo(clientAddr, _user, _password);
|
||||
if (info == null)
|
||||
{
|
||||
// user or pass wrong
|
||||
client.close(LoginFailReason.REASON_USER_OR_PASS_WRONG);
|
||||
return;
|
||||
}
|
||||
|
||||
AuthLoginResult result = lc.tryCheckinAccount(client, clientAddr, info);
|
||||
switch (result)
|
||||
{
|
||||
case AUTH_SUCCESS:
|
||||
client.setAccount(info.getLogin());
|
||||
client.setState(LoginClientState.AUTHED_LOGIN);
|
||||
client.setSessionKey(lc.assignSessionKeyToClient(info.getLogin(), client));
|
||||
lc.getCharactersOnAccount(info.getLogin());
|
||||
if (Config.SHOW_LICENCE)
|
||||
{
|
||||
client.sendPacket(new LoginOk(getClient().getSessionKey()));
|
||||
}
|
||||
else
|
||||
{
|
||||
getClient().sendPacket(new ServerList(getClient()));
|
||||
}
|
||||
break;
|
||||
case INVALID_PASSWORD:
|
||||
client.close(LoginFailReason.REASON_USER_OR_PASS_WRONG);
|
||||
break;
|
||||
case ACCOUNT_BANNED:
|
||||
client.close(new AccountKicked(AccountKickedReason.REASON_PERMANENTLY_BANNED));
|
||||
return;
|
||||
case ALREADY_ON_LS:
|
||||
L2LoginClient oldClient = lc.getAuthedClient(info.getLogin());
|
||||
if (oldClient != null)
|
||||
{
|
||||
// kick the other client
|
||||
oldClient.close(LoginFailReason.REASON_ACCOUNT_IN_USE);
|
||||
lc.removeAuthedLoginClient(info.getLogin());
|
||||
}
|
||||
// kick also current client
|
||||
client.close(LoginFailReason.REASON_ACCOUNT_IN_USE);
|
||||
break;
|
||||
case ALREADY_ON_GS:
|
||||
GameServerInfo gsi = lc.getAccountOnGameServer(info.getLogin());
|
||||
if (gsi != null)
|
||||
{
|
||||
client.close(LoginFailReason.REASON_ACCOUNT_IN_USE);
|
||||
|
||||
// kick from there
|
||||
if (gsi.isAuthed())
|
||||
{
|
||||
gsi.getGameServerThread().kickPlayer(info.getLogin());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.clientpackets;
|
||||
|
||||
import com.l2jserver.loginserver.network.serverpackets.LoginFail.LoginFailReason;
|
||||
import com.l2jserver.loginserver.network.serverpackets.ServerList;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Format: ddc
|
||||
* d: fist part of session id
|
||||
* d: second part of session id
|
||||
* c: ?
|
||||
* </pre>
|
||||
*/
|
||||
public class RequestServerList extends L2LoginClientPacket
|
||||
{
|
||||
private int _skey1;
|
||||
private int _skey2;
|
||||
private int _data3;
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getSessionKey1()
|
||||
{
|
||||
return _skey1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getSessionKey2()
|
||||
{
|
||||
return _skey2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getData3()
|
||||
{
|
||||
return _data3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readImpl()
|
||||
{
|
||||
if (super._buf.remaining() >= 8)
|
||||
{
|
||||
_skey1 = readD(); // loginOk 1
|
||||
_skey2 = readD(); // loginOk 2
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (getClient().getSessionKey().checkLoginPair(_skey1, _skey2))
|
||||
{
|
||||
getClient().sendPacket(new ServerList(getClient()));
|
||||
}
|
||||
else
|
||||
{
|
||||
getClient().close(LoginFailReason.REASON_ACCESS_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.clientpackets;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.loginserver.LoginController;
|
||||
import com.l2jserver.loginserver.SessionKey;
|
||||
import com.l2jserver.loginserver.network.serverpackets.LoginFail.LoginFailReason;
|
||||
import com.l2jserver.loginserver.network.serverpackets.PlayFail.PlayFailReason;
|
||||
import com.l2jserver.loginserver.network.serverpackets.PlayOk;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Format is ddc
|
||||
* d: first part of session id
|
||||
* d: second part of session id
|
||||
* c: server ID
|
||||
* </pre>
|
||||
*/
|
||||
public class RequestServerLogin extends L2LoginClientPacket
|
||||
{
|
||||
private int _skey1;
|
||||
private int _skey2;
|
||||
private int _serverId;
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getSessionKey1()
|
||||
{
|
||||
return _skey1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getSessionKey2()
|
||||
{
|
||||
return _skey2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getServerID()
|
||||
{
|
||||
return _serverId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readImpl()
|
||||
{
|
||||
if (super._buf.remaining() >= 9)
|
||||
{
|
||||
_skey1 = readD();
|
||||
_skey2 = readD();
|
||||
_serverId = readC();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
SessionKey sk = getClient().getSessionKey();
|
||||
|
||||
// if we didnt showed the license we cant check these values
|
||||
if (!Config.SHOW_LICENCE || sk.checkLoginPair(_skey1, _skey2))
|
||||
{
|
||||
if (LoginController.getInstance().isLoginPossible(getClient(), _serverId))
|
||||
{
|
||||
getClient().setJoinedGS(true);
|
||||
getClient().sendPacket(new PlayOk(sk));
|
||||
}
|
||||
else
|
||||
{
|
||||
getClient().close(PlayFailReason.REASON_SERVER_OVERLOADED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
getClient().close(LoginFailReason.REASON_ACCESS_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.gameserverpackets;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.loginserver.GameServerThread;
|
||||
import com.l2jserver.loginserver.network.L2JGameServerPacketHandler.GameServerState;
|
||||
import com.l2jserver.util.crypt.NewCrypt;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class BlowFishKey extends BaseRecievePacket
|
||||
{
|
||||
protected static final Logger _log = Logger.getLogger(BlowFishKey.class.getName());
|
||||
|
||||
/**
|
||||
* @param decrypt
|
||||
* @param server
|
||||
*/
|
||||
public BlowFishKey(byte[] decrypt, GameServerThread server)
|
||||
{
|
||||
super(decrypt);
|
||||
int size = readD();
|
||||
byte[] tempKey = readB(size);
|
||||
try
|
||||
{
|
||||
byte[] tempDecryptKey;
|
||||
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
|
||||
rsaCipher.init(Cipher.DECRYPT_MODE, server.getPrivateKey());
|
||||
tempDecryptKey = rsaCipher.doFinal(tempKey);
|
||||
// there are nulls before the key we must remove them
|
||||
int i = 0;
|
||||
int len = tempDecryptKey.length;
|
||||
for (; i < len; i++)
|
||||
{
|
||||
if (tempDecryptKey[i] != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
byte[] key = new byte[len - i];
|
||||
System.arraycopy(tempDecryptKey, i, key, 0, len - i);
|
||||
|
||||
server.SetBlowFish(new NewCrypt(key));
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.info("New BlowFish key received, Blowfih Engine initialized:");
|
||||
}
|
||||
server.setLoginConnectionState(GameServerState.BF_CONNECTED);
|
||||
}
|
||||
catch (GeneralSecurityException e)
|
||||
{
|
||||
_log.log(Level.SEVERE, "Error While decrypting blowfish key (RSA): " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.gameserverpackets;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jserver.loginserver.GameServerThread;
|
||||
import com.l2jserver.loginserver.LoginController;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class ChangeAccessLevel extends BaseRecievePacket
|
||||
{
|
||||
protected static Logger _log = Logger.getLogger(ChangeAccessLevel.class.getName());
|
||||
|
||||
/**
|
||||
* @param decrypt
|
||||
* @param server
|
||||
*/
|
||||
public ChangeAccessLevel(byte[] decrypt, GameServerThread server)
|
||||
{
|
||||
super(decrypt);
|
||||
int level = readD();
|
||||
String account = readS();
|
||||
|
||||
LoginController.getInstance().setAccountAccessLevel(account, level);
|
||||
_log.info("Changed " + account + " access level to " + level);
|
||||
}
|
||||
}
|
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.gameserverpackets;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Base64;
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jserver.L2DatabaseFactory;
|
||||
import com.l2jserver.loginserver.GameServerTable;
|
||||
import com.l2jserver.loginserver.GameServerTable.GameServerInfo;
|
||||
import com.l2jserver.loginserver.GameServerThread;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* @author Nik
|
||||
*/
|
||||
public class ChangePassword extends BaseRecievePacket
|
||||
{
|
||||
protected static Logger _log = Logger.getLogger(ChangePassword.class.getName());
|
||||
private static GameServerThread gst = null;
|
||||
|
||||
public ChangePassword(byte[] decrypt)
|
||||
{
|
||||
super(decrypt);
|
||||
|
||||
String accountName = readS();
|
||||
String characterName = readS();
|
||||
String curpass = readS();
|
||||
String newpass = readS();
|
||||
|
||||
// get the GameServerThread
|
||||
Collection<GameServerInfo> serverList = GameServerTable.getInstance().getRegisteredGameServers().values();
|
||||
for (GameServerInfo gsi : serverList)
|
||||
{
|
||||
if ((gsi.getGameServerThread() != null) && gsi.getGameServerThread().hasAccountOnGameServer(accountName))
|
||||
{
|
||||
gst = gsi.getGameServerThread();
|
||||
}
|
||||
}
|
||||
|
||||
if (gst == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((curpass == null) || (newpass == null))
|
||||
{
|
||||
gst.ChangePasswordResponse((byte) 0, characterName, "Invalid password data! Try again.");
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
MessageDigest md = MessageDigest.getInstance("SHA");
|
||||
|
||||
byte[] raw = curpass.getBytes("UTF-8");
|
||||
raw = md.digest(raw);
|
||||
String curpassEnc = Base64.getEncoder().encodeToString(raw);
|
||||
String pass = null;
|
||||
int passUpdated = 0;
|
||||
|
||||
// SQL connection
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT password FROM accounts WHERE login=?"))
|
||||
{
|
||||
ps.setString(1, accountName);
|
||||
try (ResultSet rs = ps.executeQuery())
|
||||
{
|
||||
if (rs.next())
|
||||
{
|
||||
pass = rs.getString("password");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (curpassEnc.equals(pass))
|
||||
{
|
||||
byte[] password = newpass.getBytes("UTF-8");
|
||||
password = md.digest(password);
|
||||
|
||||
// SQL connection
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("UPDATE accounts SET password=? WHERE login=?"))
|
||||
{
|
||||
ps.setString(1, Base64.getEncoder().encodeToString(password));
|
||||
ps.setString(2, accountName);
|
||||
passUpdated = ps.executeUpdate();
|
||||
}
|
||||
|
||||
_log.log(Level.INFO, "The password for account " + accountName + " has been changed from " + curpassEnc + " to " + Base64.getEncoder().encodeToString(password));
|
||||
if (passUpdated > 0)
|
||||
{
|
||||
gst.ChangePasswordResponse((byte) 1, characterName, "You have successfully changed your password!");
|
||||
}
|
||||
else
|
||||
{
|
||||
gst.ChangePasswordResponse((byte) 0, characterName, "The password change was unsuccessful!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gst.ChangePasswordResponse((byte) 0, characterName, "The typed current password doesn't match with your current one.");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.warning("Error while changing password for account " + accountName + " requested by player " + characterName + "! " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.gameserverpackets;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.loginserver.GameServerTable;
|
||||
import com.l2jserver.loginserver.GameServerTable.GameServerInfo;
|
||||
import com.l2jserver.loginserver.GameServerThread;
|
||||
import com.l2jserver.loginserver.network.L2JGameServerPacketHandler.GameServerState;
|
||||
import com.l2jserver.loginserver.network.loginserverpackets.AuthResponse;
|
||||
import com.l2jserver.loginserver.network.loginserverpackets.LoginServerFail;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Format: cccddb
|
||||
* c desired ID
|
||||
* c accept alternative ID
|
||||
* c reserve Host
|
||||
* s ExternalHostName
|
||||
* s InetranlHostName
|
||||
* d max players
|
||||
* d hexid size
|
||||
* b hexid
|
||||
* </pre>
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class GameServerAuth extends BaseRecievePacket
|
||||
{
|
||||
protected static Logger _log = Logger.getLogger(GameServerAuth.class.getName());
|
||||
GameServerThread _server;
|
||||
private final byte[] _hexId;
|
||||
private final int _desiredId;
|
||||
@SuppressWarnings("unused")
|
||||
private final boolean _hostReserved;
|
||||
private final boolean _acceptAlternativeId;
|
||||
private final int _maxPlayers;
|
||||
private final int _port;
|
||||
private final String[] _hosts;
|
||||
|
||||
/**
|
||||
* @param decrypt
|
||||
* @param server
|
||||
*/
|
||||
public GameServerAuth(byte[] decrypt, GameServerThread server)
|
||||
{
|
||||
super(decrypt);
|
||||
_server = server;
|
||||
_desiredId = readC();
|
||||
_acceptAlternativeId = (readC() == 0 ? false : true);
|
||||
_hostReserved = (readC() == 0 ? false : true);
|
||||
_port = readH();
|
||||
_maxPlayers = readD();
|
||||
int size = readD();
|
||||
_hexId = readB(size);
|
||||
size = 2 * readD();
|
||||
_hosts = new String[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
_hosts[i] = readS();
|
||||
}
|
||||
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.info("Auth request received");
|
||||
}
|
||||
|
||||
if (handleRegProcess())
|
||||
{
|
||||
AuthResponse ar = new AuthResponse(server.getGameServerInfo().getId());
|
||||
server.sendPacket(ar);
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.info("Authed: id: " + server.getGameServerInfo().getId());
|
||||
}
|
||||
server.broadcastToTelnet("GameServer [" + server.getServerId() + "] " + GameServerTable.getInstance().getServerNameById(server.getServerId()) + " is connected");
|
||||
server.setLoginConnectionState(GameServerState.AUTHED);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleRegProcess()
|
||||
{
|
||||
GameServerTable gameServerTable = GameServerTable.getInstance();
|
||||
|
||||
int id = _desiredId;
|
||||
byte[] hexId = _hexId;
|
||||
|
||||
GameServerInfo gsi = gameServerTable.getRegisteredGameServerById(id);
|
||||
// is there a gameserver registered with this id?
|
||||
if (gsi != null)
|
||||
{
|
||||
// does the hex id match?
|
||||
if (Arrays.equals(gsi.getHexId(), hexId))
|
||||
{
|
||||
// check to see if this GS is already connected
|
||||
synchronized (gsi)
|
||||
{
|
||||
if (gsi.isAuthed())
|
||||
{
|
||||
_server.forceClose(LoginServerFail.REASON_ALREADY_LOGGED8IN);
|
||||
return false;
|
||||
}
|
||||
_server.attachGameServerInfo(gsi, _port, _hosts, _maxPlayers);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// there is already a server registered with the desired id and different hex id
|
||||
// try to register this one with an alternative id
|
||||
if (Config.ACCEPT_NEW_GAMESERVER && _acceptAlternativeId)
|
||||
{
|
||||
gsi = new GameServerInfo(id, hexId, _server);
|
||||
if (gameServerTable.registerWithFirstAvaliableId(gsi))
|
||||
{
|
||||
_server.attachGameServerInfo(gsi, _port, _hosts, _maxPlayers);
|
||||
gameServerTable.registerServerOnDB(gsi);
|
||||
}
|
||||
else
|
||||
{
|
||||
_server.forceClose(LoginServerFail.REASON_NO_FREE_ID);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// server id is already taken, and we cant get a new one for you
|
||||
_server.forceClose(LoginServerFail.REASON_WRONG_HEXID);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// can we register on this id?
|
||||
if (Config.ACCEPT_NEW_GAMESERVER)
|
||||
{
|
||||
gsi = new GameServerInfo(id, hexId, _server);
|
||||
if (gameServerTable.register(id, gsi))
|
||||
{
|
||||
_server.attachGameServerInfo(gsi, _port, _hosts, _maxPlayers);
|
||||
gameServerTable.registerServerOnDB(gsi);
|
||||
}
|
||||
else
|
||||
{
|
||||
// some one took this ID meanwhile
|
||||
_server.forceClose(LoginServerFail.REASON_ID_RESERVED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_server.forceClose(LoginServerFail.REASON_WRONG_HEXID);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.gameserverpackets;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.loginserver.GameServerThread;
|
||||
import com.l2jserver.loginserver.LoginController;
|
||||
import com.l2jserver.loginserver.SessionKey;
|
||||
import com.l2jserver.loginserver.network.loginserverpackets.PlayerAuthResponse;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class PlayerAuthRequest extends BaseRecievePacket
|
||||
{
|
||||
private static Logger _log = Logger.getLogger(PlayerAuthRequest.class.getName());
|
||||
|
||||
/**
|
||||
* @param decrypt
|
||||
* @param server
|
||||
*/
|
||||
public PlayerAuthRequest(byte[] decrypt, GameServerThread server)
|
||||
{
|
||||
super(decrypt);
|
||||
String account = readS();
|
||||
int playKey1 = readD();
|
||||
int playKey2 = readD();
|
||||
int loginKey1 = readD();
|
||||
int loginKey2 = readD();
|
||||
SessionKey sessionKey = new SessionKey(loginKey1, loginKey2, playKey1, playKey2);
|
||||
|
||||
PlayerAuthResponse authResponse;
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.info("auth request received for Player " + account);
|
||||
}
|
||||
SessionKey key = LoginController.getInstance().getKeyForAccount(account);
|
||||
if ((key != null) && key.equals(sessionKey))
|
||||
{
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.info("auth request: OK");
|
||||
}
|
||||
LoginController.getInstance().removeAuthedLoginClient(account);
|
||||
authResponse = new PlayerAuthResponse(account, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.info("auth request: NO");
|
||||
_log.info("session key from self: " + key);
|
||||
_log.info("session key sent: " + sessionKey);
|
||||
}
|
||||
authResponse = new PlayerAuthResponse(account, false);
|
||||
}
|
||||
server.sendPacket(authResponse);
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.gameserverpackets;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.loginserver.GameServerTable;
|
||||
import com.l2jserver.loginserver.GameServerThread;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class PlayerInGame extends BaseRecievePacket
|
||||
{
|
||||
private static Logger _log = Logger.getLogger(PlayerInGame.class.getName());
|
||||
|
||||
/**
|
||||
* @param decrypt
|
||||
* @param server
|
||||
*/
|
||||
public PlayerInGame(byte[] decrypt, GameServerThread server)
|
||||
{
|
||||
super(decrypt);
|
||||
int size = readH();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
String account = readS();
|
||||
server.addAccountOnGameServer(account);
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.info("Account " + account + " logged in GameServer: [" + server.getServerId() + "] " + GameServerTable.getInstance().getServerNameById(server.getServerId()));
|
||||
}
|
||||
server.broadcastToTelnet("Account " + account + " logged in GameServer " + server.getServerId());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.gameserverpackets;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.loginserver.GameServerTable;
|
||||
import com.l2jserver.loginserver.GameServerThread;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class PlayerLogout extends BaseRecievePacket
|
||||
{
|
||||
protected static Logger _log = Logger.getLogger(PlayerLogout.class.getName());
|
||||
|
||||
/**
|
||||
* @param decrypt
|
||||
* @param server
|
||||
*/
|
||||
public PlayerLogout(byte[] decrypt, GameServerThread server)
|
||||
{
|
||||
super(decrypt);
|
||||
String account = readS();
|
||||
|
||||
server.removeAccountOnGameServer(account);
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.info("Player " + account + " logged out from gameserver [" + server.getServerId() + "] " + GameServerTable.getInstance().getServerNameById(server.getServerId()));
|
||||
}
|
||||
|
||||
server.broadcastToTelnet("Player " + account + " disconnected from GameServer " + server.getServerId());
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.gameserverpackets;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.loginserver.LoginController;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* @author mrTJO
|
||||
*/
|
||||
public class PlayerTracert extends BaseRecievePacket
|
||||
{
|
||||
protected static Logger _log = Logger.getLogger(PlayerTracert.class.getName());
|
||||
|
||||
/**
|
||||
* @param decrypt
|
||||
*/
|
||||
public PlayerTracert(byte[] decrypt)
|
||||
{
|
||||
super(decrypt);
|
||||
String account = readS();
|
||||
String pcIp = readS();
|
||||
String hop1 = readS();
|
||||
String hop2 = readS();
|
||||
String hop3 = readS();
|
||||
String hop4 = readS();
|
||||
|
||||
LoginController.getInstance().setAccountLastTracert(account, pcIp, hop1, hop2, hop3, hop4);
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.info("Saved " + account + " last tracert");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.gameserverpackets;
|
||||
|
||||
import com.l2jserver.loginserver.GameServerThread;
|
||||
import com.l2jserver.loginserver.LoginController;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* Thanks to mochitto.
|
||||
* @author mrTJO
|
||||
*/
|
||||
public class ReplyCharacters extends BaseRecievePacket
|
||||
{
|
||||
/**
|
||||
* @param decrypt
|
||||
* @param server
|
||||
*/
|
||||
public ReplyCharacters(byte[] decrypt, GameServerThread server)
|
||||
{
|
||||
super(decrypt);
|
||||
String account = readS();
|
||||
int chars = readC();
|
||||
int charsToDel = readC();
|
||||
long[] charsList = new long[charsToDel];
|
||||
for (int i = 0; i < charsToDel; i++)
|
||||
{
|
||||
charsList[i] = readQ();
|
||||
}
|
||||
LoginController.getInstance().setCharactersOnServer(account, chars, charsList, server.getServerId());
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.gameserverpackets;
|
||||
|
||||
import com.l2jserver.loginserver.mail.MailSystem;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* @author mrTJO
|
||||
*/
|
||||
public class RequestSendMail extends BaseRecievePacket
|
||||
{
|
||||
String _accountName, _mailId;
|
||||
String[] _args;
|
||||
|
||||
/**
|
||||
* @param decrypt
|
||||
*/
|
||||
public RequestSendMail(byte[] decrypt)
|
||||
{
|
||||
super(decrypt);
|
||||
_accountName = readS();
|
||||
_mailId = readS();
|
||||
int argNum = readC();
|
||||
_args = new String[argNum];
|
||||
for (int i = 0; i < argNum; i++)
|
||||
{
|
||||
_args[i] = readS();
|
||||
}
|
||||
|
||||
MailSystem.getInstance().sendMail(_accountName, _mailId, _args);
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.gameserverpackets;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jserver.L2DatabaseFactory;
|
||||
import com.l2jserver.loginserver.LoginController;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* @author mrTJO
|
||||
*/
|
||||
public class RequestTempBan extends BaseRecievePacket
|
||||
{
|
||||
private static final Logger _log = Logger.getLogger(RequestTempBan.class.getName());
|
||||
|
||||
private final String _accountName;
|
||||
@SuppressWarnings("unused")
|
||||
private String _banReason;
|
||||
private final String _ip;
|
||||
long _banTime;
|
||||
|
||||
/**
|
||||
* @param decrypt
|
||||
*/
|
||||
public RequestTempBan(byte[] decrypt)
|
||||
{
|
||||
super(decrypt);
|
||||
_accountName = readS();
|
||||
_ip = readS();
|
||||
_banTime = readQ();
|
||||
boolean haveReason = readC() == 0 ? false : true;
|
||||
if (haveReason)
|
||||
{
|
||||
_banReason = readS();
|
||||
}
|
||||
banUser();
|
||||
}
|
||||
|
||||
private void banUser()
|
||||
{
|
||||
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("INSERT INTO account_data VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE value=?"))
|
||||
{
|
||||
ps.setString(1, _accountName);
|
||||
ps.setString(2, "ban_temp");
|
||||
ps.setString(3, Long.toString(_banTime));
|
||||
ps.setString(4, Long.toString(_banTime));
|
||||
ps.execute();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
_log.warning(getClass().getSimpleName() + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LoginController.getInstance().addBanForAddress(_ip, _banTime);
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.gameserverpackets;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jserver.loginserver.GameServerTable;
|
||||
import com.l2jserver.loginserver.GameServerTable.GameServerInfo;
|
||||
import com.l2jserver.loginserver.GameServerThread;
|
||||
import com.l2jserver.util.network.BaseRecievePacket;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class ServerStatus extends BaseRecievePacket
|
||||
{
|
||||
protected static Logger _log = Logger.getLogger(ServerStatus.class.getName());
|
||||
|
||||
public static final String[] STATUS_STRING =
|
||||
{
|
||||
"Auto",
|
||||
"Good",
|
||||
"Normal",
|
||||
"Full",
|
||||
"Down",
|
||||
"Gm Only"
|
||||
};
|
||||
|
||||
public static final int SERVER_LIST_STATUS = 0x01;
|
||||
public static final int SERVER_TYPE = 0x02;
|
||||
public static final int SERVER_LIST_SQUARE_BRACKET = 0x03;
|
||||
public static final int MAX_PLAYERS = 0x04;
|
||||
public static final int TEST_SERVER = 0x05;
|
||||
public static final int SERVER_AGE = 0x06;
|
||||
|
||||
// Server Status
|
||||
public static final int STATUS_AUTO = 0x00;
|
||||
public static final int STATUS_GOOD = 0x01;
|
||||
public static final int STATUS_NORMAL = 0x02;
|
||||
public static final int STATUS_FULL = 0x03;
|
||||
public static final int STATUS_DOWN = 0x04;
|
||||
public static final int STATUS_GM_ONLY = 0x05;
|
||||
|
||||
// Server Types
|
||||
public static final int SERVER_NORMAL = 0x01;
|
||||
public static final int SERVER_RELAX = 0x02;
|
||||
public static final int SERVER_TEST = 0x04;
|
||||
public static final int SERVER_NOLABEL = 0x08;
|
||||
public static final int SERVER_CREATION_RESTRICTED = 0x10;
|
||||
public static final int SERVER_EVENT = 0x20;
|
||||
public static final int SERVER_FREE = 0x40;
|
||||
|
||||
// Server Ages
|
||||
public static final int SERVER_AGE_ALL = 0x00;
|
||||
public static final int SERVER_AGE_15 = 0x0F;
|
||||
public static final int SERVER_AGE_18 = 0x12;
|
||||
|
||||
public static final int ON = 0x01;
|
||||
public static final int OFF = 0x00;
|
||||
|
||||
/**
|
||||
* @param decrypt
|
||||
* @param server
|
||||
*/
|
||||
public ServerStatus(byte[] decrypt, GameServerThread server)
|
||||
{
|
||||
super(decrypt);
|
||||
|
||||
GameServerInfo gsi = GameServerTable.getInstance().getRegisteredGameServerById(server.getServerId());
|
||||
if (gsi != null)
|
||||
{
|
||||
int size = readD();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
int type = readD();
|
||||
int value = readD();
|
||||
switch (type)
|
||||
{
|
||||
case SERVER_LIST_STATUS:
|
||||
gsi.setStatus(value);
|
||||
break;
|
||||
case SERVER_LIST_SQUARE_BRACKET:
|
||||
gsi.setShowingBrackets(value == ON);
|
||||
break;
|
||||
case MAX_PLAYERS:
|
||||
gsi.setMaxPlayers(value);
|
||||
break;
|
||||
case SERVER_TYPE:
|
||||
gsi.setServerType(value);
|
||||
break;
|
||||
case SERVER_AGE:
|
||||
gsi.setAgeLimit(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.loginserverpackets;
|
||||
|
||||
import com.l2jserver.loginserver.GameServerTable;
|
||||
import com.l2jserver.util.network.BaseSendablePacket;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class AuthResponse extends BaseSendablePacket
|
||||
{
|
||||
/**
|
||||
* @param serverId
|
||||
*/
|
||||
public AuthResponse(int serverId)
|
||||
{
|
||||
writeC(0x02);
|
||||
writeC(serverId);
|
||||
writeS(GameServerTable.getInstance().getServerNameById(serverId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getContent()
|
||||
{
|
||||
return getBytes();
|
||||
}
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.loginserverpackets;
|
||||
|
||||
import com.l2jserver.util.network.BaseSendablePacket;
|
||||
|
||||
/**
|
||||
* @author Nik
|
||||
*/
|
||||
public class ChangePasswordResponse extends BaseSendablePacket
|
||||
{
|
||||
public ChangePasswordResponse(byte successful, String characterName, String msgToSend)
|
||||
{
|
||||
writeC(0x06);
|
||||
// writeC(successful); //0 false, 1 true
|
||||
writeS(characterName);
|
||||
writeS(msgToSend);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getContent()
|
||||
{
|
||||
return getBytes();
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.loginserverpackets;
|
||||
|
||||
import com.l2jserver.loginserver.L2LoginServer;
|
||||
import com.l2jserver.util.network.BaseSendablePacket;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class InitLS extends BaseSendablePacket
|
||||
{
|
||||
// ID 0x00
|
||||
// format
|
||||
// d proto rev
|
||||
// d key size
|
||||
// b key
|
||||
|
||||
public InitLS(byte[] publickey)
|
||||
{
|
||||
writeC(0x00);
|
||||
writeD(L2LoginServer.PROTOCOL_REV);
|
||||
writeD(publickey.length);
|
||||
writeB(publickey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getContent()
|
||||
{
|
||||
return getBytes();
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.loginserverpackets;
|
||||
|
||||
import com.l2jserver.util.network.BaseSendablePacket;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class KickPlayer extends BaseSendablePacket
|
||||
{
|
||||
public KickPlayer(String account)
|
||||
{
|
||||
writeC(0x04);
|
||||
writeS(account);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getContent()
|
||||
{
|
||||
return getBytes();
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.loginserverpackets;
|
||||
|
||||
import com.l2jserver.util.network.BaseSendablePacket;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class LoginServerFail extends BaseSendablePacket
|
||||
{
|
||||
|
||||
/**
|
||||
* @param reason
|
||||
*/
|
||||
public LoginServerFail(int reason)
|
||||
{
|
||||
writeC(0x01);
|
||||
writeC(reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getContent()
|
||||
{
|
||||
return getBytes();
|
||||
}
|
||||
|
||||
public static final int REASON_IP_BANNED = 1;
|
||||
public static final int REASON_IP_RESERVED = 2;
|
||||
public static final int REASON_WRONG_HEXID = 3;
|
||||
public static final int REASON_ID_RESERVED = 4;
|
||||
public static final int REASON_NO_FREE_ID = 5;
|
||||
public static final int NOT_AUTHED = 6;
|
||||
public static final int REASON_ALREADY_LOGGED8IN = 7;
|
||||
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.loginserverpackets;
|
||||
|
||||
import com.l2jserver.util.network.BaseSendablePacket;
|
||||
|
||||
/**
|
||||
* @author -Wooden-
|
||||
*/
|
||||
public class PlayerAuthResponse extends BaseSendablePacket
|
||||
{
|
||||
public PlayerAuthResponse(String account, boolean response)
|
||||
{
|
||||
writeC(0x03);
|
||||
writeS(account);
|
||||
writeC(response ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getContent()
|
||||
{
|
||||
return getBytes();
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.loginserverpackets;
|
||||
|
||||
import com.l2jserver.util.network.BaseSendablePacket;
|
||||
|
||||
/**
|
||||
* @author mrTJO
|
||||
*/
|
||||
public class RequestCharacters extends BaseSendablePacket
|
||||
{
|
||||
public RequestCharacters(String account)
|
||||
{
|
||||
writeC(0x05);
|
||||
writeS(account);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getContent()
|
||||
{
|
||||
return getBytes();
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.serverpackets;
|
||||
|
||||
/**
|
||||
* @author KenM
|
||||
*/
|
||||
public final class AccountKicked extends L2LoginServerPacket
|
||||
{
|
||||
public static enum AccountKickedReason
|
||||
{
|
||||
REASON_DATA_STEALER(0x01),
|
||||
REASON_GENERIC_VIOLATION(0x08),
|
||||
REASON_7_DAYS_SUSPENDED(0x10),
|
||||
REASON_PERMANENTLY_BANNED(0x20);
|
||||
|
||||
private final int _code;
|
||||
|
||||
AccountKickedReason(int code)
|
||||
{
|
||||
_code = code;
|
||||
}
|
||||
|
||||
public final int getCode()
|
||||
{
|
||||
return _code;
|
||||
}
|
||||
}
|
||||
|
||||
private final AccountKickedReason _reason;
|
||||
|
||||
/**
|
||||
* @param reason
|
||||
*/
|
||||
public AccountKicked(AccountKickedReason reason)
|
||||
{
|
||||
_reason = reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write()
|
||||
{
|
||||
writeC(0x02);
|
||||
writeD(_reason.getCode());
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.serverpackets;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
|
||||
/**
|
||||
* Fromat: d d: response
|
||||
*/
|
||||
public final class GGAuth extends L2LoginServerPacket
|
||||
{
|
||||
static final Logger _log = Logger.getLogger(GGAuth.class.getName());
|
||||
public static final int SKIP_GG_AUTH_REQUEST = 0x0b;
|
||||
|
||||
private final int _response;
|
||||
|
||||
public GGAuth(int response)
|
||||
{
|
||||
_response = response;
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.warning("Reason Hex: " + (Integer.toHexString(response)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write()
|
||||
{
|
||||
writeC(0x0b);
|
||||
writeD(_response);
|
||||
writeD(0x00);
|
||||
writeD(0x00);
|
||||
writeD(0x00);
|
||||
writeD(0x00);
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.serverpackets;
|
||||
|
||||
import com.l2jserver.loginserver.network.L2LoginClient;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Format: dd b dddd s
|
||||
* d: session id
|
||||
* d: protocol revision
|
||||
* b: 0x90 bytes : 0x80 bytes for the scrambled RSA public key
|
||||
* 0x10 bytes at 0x00
|
||||
* d: unknow
|
||||
* d: unknow
|
||||
* d: unknow
|
||||
* d: unknow
|
||||
* s: blowfish key
|
||||
* </pre>
|
||||
*/
|
||||
public final class Init extends L2LoginServerPacket
|
||||
{
|
||||
private final int _sessionId;
|
||||
|
||||
private final byte[] _publicKey;
|
||||
private final byte[] _blowfishKey;
|
||||
|
||||
public Init(L2LoginClient client)
|
||||
{
|
||||
this(client.getScrambledModulus(), client.getBlowfishKey(), client.getSessionId());
|
||||
}
|
||||
|
||||
public Init(byte[] publickey, byte[] blowfishkey, int sessionId)
|
||||
{
|
||||
_sessionId = sessionId;
|
||||
_publicKey = publickey;
|
||||
_blowfishKey = blowfishkey;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write()
|
||||
{
|
||||
writeC(0x00); // init packet id
|
||||
|
||||
writeD(_sessionId); // session id
|
||||
writeD(0x0000c621); // protocol revision
|
||||
|
||||
writeB(_publicKey); // RSA Public Key
|
||||
|
||||
// unk GG related?
|
||||
writeD(0x29DD954E);
|
||||
writeD(0x77C39CFC);
|
||||
writeD(0x97ADB620);
|
||||
writeD(0x07BDE0F7);
|
||||
|
||||
writeB(_blowfishKey); // BlowFish key
|
||||
writeC(0x00); // null termination ;)
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.serverpackets;
|
||||
|
||||
import org.mmocore.network.SendablePacket;
|
||||
|
||||
import com.l2jserver.loginserver.network.L2LoginClient;
|
||||
|
||||
/**
|
||||
* @author KenM
|
||||
*/
|
||||
public abstract class L2LoginServerPacket extends SendablePacket<L2LoginClient>
|
||||
{
|
||||
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.serverpackets;
|
||||
|
||||
/**
|
||||
* Fromat: d d: the failure reason
|
||||
*/
|
||||
public final class LoginFail extends L2LoginServerPacket
|
||||
{
|
||||
public static enum LoginFailReason
|
||||
{
|
||||
REASON_NO_MESSAGE(0x00),
|
||||
REASON_SYSTEM_ERROR_LOGIN_LATER(0x01),
|
||||
REASON_USER_OR_PASS_WRONG(0x02),
|
||||
REASON_ACCESS_FAILED_TRY_AGAIN_LATER(0x04),
|
||||
REASON_ACCOUNT_INFO_INCORRECT_CONTACT_SUPPORT(0x05),
|
||||
REASON_ACCOUNT_IN_USE(0x07),
|
||||
REASON_UNDER_18_YEARS_KR(0x0C),
|
||||
REASON_SERVER_OVERLOADED(0x0F),
|
||||
REASON_SERVER_MAINTENANCE(0x10),
|
||||
REASON_TEMP_PASS_EXPIRED(0x11),
|
||||
REASON_GAME_TIME_EXPIRED(0x12),
|
||||
REASON_NO_TIME_LEFT(0x13),
|
||||
REASON_SYSTEM_ERROR(0x14),
|
||||
REASON_ACCESS_FAILED(0x15),
|
||||
REASON_RESTRICTED_IP(0x16),
|
||||
REASON_WEEK_USAGE_FINISHED(0x1E),
|
||||
REASON_SECURITY_CARD_NUMBER_INVALID(0x1F),
|
||||
REASON_AGE_NOT_VERIFIED_CANT_LOG_BEETWEEN_10PM_6AM(0x20),
|
||||
REASON_SERVER_CANNOT_BE_ACCESSED_BY_YOUR_COUPON(0x21),
|
||||
REASON_DUAL_BOX(0x23),
|
||||
REASON_INACTIVE(0x24),
|
||||
REASON_USER_AGREEMENT_REJECTED_ON_WEBSITE(0x25),
|
||||
REASON_GUARDIAN_CONSENT_REQUIRED(0x26),
|
||||
REASON_USER_AGREEMENT_DECLINED_OR_WITHDRAWL_REQUEST(0x27),
|
||||
REASON_ACCOUNT_SUSPENDED_CALL(0x28),
|
||||
REASON_CHANGE_PASSWORD_AND_QUIZ_ON_WEBSITE(0x29),
|
||||
REASON_ALREADY_LOGGED_INTO_10_ACCOUNTS(0x2A),
|
||||
REASON_MASTER_ACCOUNT_RESTRICTED(0x2B),
|
||||
REASON_CERTIFICATION_FAILED(0x2E),
|
||||
REASON_TELEPHONE_CERTIFICATION_UNAVAILABLE(0x2F),
|
||||
REASON_TELEPHONE_SIGNALS_DELAYED(0x30),
|
||||
REASON_CERTIFICATION_FAILED_LINE_BUSY(0x31),
|
||||
REASON_CERTIFICATION_SERVICE_NUMBER_EXPIRED_OR_INCORRECT(0x32),
|
||||
REASON_CERTIFICATION_SERVICE_CURRENTLY_BEING_CHECKED(0x33),
|
||||
REASON_CERTIFICATION_SERVICE_CANT_BE_USED_HEAVY_VOLUME(0x34),
|
||||
REASON_CERTIFICATION_SERVICE_EXPIRED_GAMEPLAY_BLOCKED(0x35),
|
||||
REASON_CERTIFICATION_FAILED_3_TIMES_GAMEPLAY_BLOCKED_30_MIN(0x36),
|
||||
REASON_CERTIFICATION_DAILY_USE_EXCEEDED(0x37),
|
||||
REASON_CERTIFICATION_UNDERWAY_TRY_AGAIN_LATER(0x38);
|
||||
|
||||
private final int _code;
|
||||
|
||||
LoginFailReason(int code)
|
||||
{
|
||||
_code = code;
|
||||
}
|
||||
|
||||
public final int getCode()
|
||||
{
|
||||
return _code;
|
||||
}
|
||||
}
|
||||
|
||||
private final LoginFailReason _reason;
|
||||
|
||||
public LoginFail(LoginFailReason reason)
|
||||
{
|
||||
_reason = reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write()
|
||||
{
|
||||
writeC(0x01);
|
||||
writeC(_reason.getCode());
|
||||
}
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.serverpackets;
|
||||
|
||||
import com.l2jserver.loginserver.SessionKey;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Format: dddddddd
|
||||
* f: the session key
|
||||
* d: ?
|
||||
* d: ?
|
||||
* d: ?
|
||||
* d: ?
|
||||
* d: ?
|
||||
* d: ?
|
||||
* b: 16 bytes - unknown
|
||||
* </pre>
|
||||
*/
|
||||
public final class LoginOk extends L2LoginServerPacket
|
||||
{
|
||||
private final int _loginOk1, _loginOk2;
|
||||
|
||||
public LoginOk(SessionKey sessionKey)
|
||||
{
|
||||
_loginOk1 = sessionKey.loginOkID1;
|
||||
_loginOk2 = sessionKey.loginOkID2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write()
|
||||
{
|
||||
writeC(0x03);
|
||||
writeD(_loginOk1);
|
||||
writeD(_loginOk2);
|
||||
writeD(0x00);
|
||||
writeD(0x00);
|
||||
writeD(0x000003ea);
|
||||
writeD(0x00);
|
||||
writeD(0x00);
|
||||
writeD(0x00);
|
||||
writeB(new byte[16]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.serverpackets;
|
||||
|
||||
/**
|
||||
* This class ...
|
||||
* @version $Revision: 1.2.4.1 $ $Date: 2005/03/27 15:30:11 $
|
||||
*/
|
||||
public final class PlayFail extends L2LoginServerPacket
|
||||
{
|
||||
public static enum PlayFailReason
|
||||
{
|
||||
REASON_NO_MESSAGE(0x00),
|
||||
REASON_SYSTEM_ERROR_LOGIN_LATER(0x01),
|
||||
REASON_USER_OR_PASS_WRONG(0x02),
|
||||
REASON_ACCESS_FAILED_TRY_AGAIN_LATER(0x04),
|
||||
REASON_ACCOUNT_INFO_INCORRECT_CONTACT_SUPPORT(0x05),
|
||||
REASON_ACCOUNT_IN_USE(0x07),
|
||||
REASON_UNDER_18_YEARS_KR(0x0C),
|
||||
REASON_SERVER_OVERLOADED(0x0F),
|
||||
REASON_SERVER_MAINTENANCE(0x10),
|
||||
REASON_TEMP_PASS_EXPIRED(0x11),
|
||||
REASON_GAME_TIME_EXPIRED(0x12),
|
||||
REASON_NO_TIME_LEFT(0x13),
|
||||
REASON_SYSTEM_ERROR(0x14),
|
||||
REASON_ACCESS_FAILED(0x15),
|
||||
REASON_RESTRICTED_IP(0x16),
|
||||
REASON_WEEK_USAGE_FINISHED(0x1E),
|
||||
REASON_SECURITY_CARD_NUMBER_INVALID(0x1F),
|
||||
REASON_AGE_NOT_VERIFIED_CANT_LOG_BEETWEEN_10PM_6AM(0x20),
|
||||
REASON_SERVER_CANNOT_BE_ACCESSED_BY_YOUR_COUPON(0x21),
|
||||
REASON_DUAL_BOX(0x23),
|
||||
REASON_INACTIVE(0x24),
|
||||
REASON_USER_AGREEMENT_REJECTED_ON_WEBSITE(0x25),
|
||||
REASON_GUARDIAN_CONSENT_REQUIRED(0x26),
|
||||
REASON_USER_AGREEMENT_DECLINED_OR_WITHDRAWL_REQUEST(0x27),
|
||||
REASON_ACCOUNT_SUSPENDED_CALL(0x28),
|
||||
REASON_CHANGE_PASSWORD_AND_QUIZ_ON_WEBSITE(0x29),
|
||||
REASON_ALREADY_LOGGED_INTO_10_ACCOUNTS(0x2A),
|
||||
REASON_MASTER_ACCOUNT_RESTRICTED(0x2B),
|
||||
REASON_CERTIFICATION_FAILED(0x2E),
|
||||
REASON_TELEPHONE_CERTIFICATION_UNAVAILABLE(0x2F),
|
||||
REASON_TELEPHONE_SIGNALS_DELAYED(0x30),
|
||||
REASON_CERTIFICATION_FAILED_LINE_BUSY(0x31),
|
||||
REASON_CERTIFICATION_SERVICE_NUMBER_EXPIRED_OR_INCORRECT(0x32),
|
||||
REASON_CERTIFICATION_SERVICE_CURRENTLY_BEING_CHECKED(0x33),
|
||||
REASON_CERTIFICATION_SERVICE_CANT_BE_USED_HEAVY_VOLUME(0x34),
|
||||
REASON_CERTIFICATION_SERVICE_EXPIRED_GAMEPLAY_BLOCKED(0x35),
|
||||
REASON_CERTIFICATION_FAILED_3_TIMES_GAMEPLAY_BLOCKED_30_MIN(0x36),
|
||||
REASON_CERTIFICATION_DAILY_USE_EXCEEDED(0x37),
|
||||
REASON_CERTIFICATION_UNDERWAY_TRY_AGAIN_LATER(0x38);
|
||||
|
||||
private final int _code;
|
||||
|
||||
PlayFailReason(int code)
|
||||
{
|
||||
_code = code;
|
||||
}
|
||||
|
||||
public final int getCode()
|
||||
{
|
||||
return _code;
|
||||
}
|
||||
}
|
||||
|
||||
private final PlayFailReason _reason;
|
||||
|
||||
public PlayFail(PlayFailReason reason)
|
||||
{
|
||||
_reason = reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write()
|
||||
{
|
||||
writeC(0x06);
|
||||
writeC(_reason.getCode());
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.serverpackets;
|
||||
|
||||
import com.l2jserver.loginserver.SessionKey;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public final class PlayOk extends L2LoginServerPacket
|
||||
{
|
||||
private final int _playOk1, _playOk2;
|
||||
|
||||
public PlayOk(SessionKey sessionKey)
|
||||
{
|
||||
_playOk1 = sessionKey.playOkID1;
|
||||
_playOk2 = sessionKey.playOkID2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write()
|
||||
{
|
||||
writeC(0x07);
|
||||
writeD(_playOk1);
|
||||
writeD(_playOk2);
|
||||
}
|
||||
}
|
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2014 L2J Server
|
||||
*
|
||||
* This file is part of L2J Server.
|
||||
*
|
||||
* L2J Server 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.
|
||||
*
|
||||
* L2J Server 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.loginserver.network.serverpackets;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jserver.loginserver.GameServerTable;
|
||||
import com.l2jserver.loginserver.GameServerTable.GameServerInfo;
|
||||
import com.l2jserver.loginserver.network.L2LoginClient;
|
||||
import com.l2jserver.loginserver.network.gameserverpackets.ServerStatus;
|
||||
|
||||
/**
|
||||
* ServerList
|
||||
*
|
||||
* <pre>
|
||||
* Format: cc [cddcchhcdc]
|
||||
*
|
||||
* c: server list size (number of servers)
|
||||
* c: ?
|
||||
* [ (repeat for each servers)
|
||||
* c: server id (ignored by client?)
|
||||
* d: server ip
|
||||
* d: server port
|
||||
* c: age limit (used by client?)
|
||||
* c: pvp or not (used by client?)
|
||||
* h: current number of players
|
||||
* h: max number of players
|
||||
* c: 0 if server is down
|
||||
* d: 2nd bit: clock
|
||||
* 3rd bit: won't display server name
|
||||
* 4th bit: test server (used by client?)
|
||||
* c: 0 if you don't want to display brackets in front of sever name
|
||||
* ]
|
||||
* </pre>
|
||||
*
|
||||
* Server will be considered as Good when the number of online players<br>
|
||||
* is less than half the maximum. as Normal between half and 4/5<br>
|
||||
* and Full when there's more than 4/5 of the maximum number of players.
|
||||
*/
|
||||
public final class ServerList extends L2LoginServerPacket
|
||||
{
|
||||
protected static final Logger _log = Logger.getLogger(ServerList.class.getName());
|
||||
|
||||
private final List<ServerData> _servers;
|
||||
private final int _lastServer;
|
||||
private final Map<Integer, Integer> _charsOnServers;
|
||||
private final Map<Integer, long[]> _charsToDelete;
|
||||
|
||||
class ServerData
|
||||
{
|
||||
protected byte[] _ip;
|
||||
protected int _port;
|
||||
protected int _ageLimit;
|
||||
protected boolean _pvp;
|
||||
protected int _currentPlayers;
|
||||
protected int _maxPlayers;
|
||||
protected boolean _brackets;
|
||||
protected boolean _clock;
|
||||
protected int _status;
|
||||
protected int _serverId;
|
||||
protected int _serverType;
|
||||
|
||||
ServerData(L2LoginClient client, GameServerInfo gsi)
|
||||
{
|
||||
try
|
||||
{
|
||||
_ip = InetAddress.getByName(gsi.getServerAddress(client.getConnection().getInetAddress())).getAddress();
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
_log.warning(getClass().getSimpleName() + ": " + e.getMessage());
|
||||
_ip = new byte[4];
|
||||
_ip[0] = 127;
|
||||
_ip[1] = 0;
|
||||
_ip[2] = 0;
|
||||
_ip[3] = 1;
|
||||
}
|
||||
|
||||
_port = gsi.getPort();
|
||||
_pvp = gsi.isPvp();
|
||||
_serverType = gsi.getServerType();
|
||||
_currentPlayers = gsi.getCurrentPlayerCount();
|
||||
_maxPlayers = gsi.getMaxPlayers();
|
||||
_ageLimit = 0;
|
||||
_brackets = gsi.isShowingBrackets();
|
||||
// If server GM-only - show status only to GMs
|
||||
_status = gsi.getStatus() != ServerStatus.STATUS_GM_ONLY ? gsi.getStatus() : client.getAccessLevel() > 0 ? gsi.getStatus() : ServerStatus.STATUS_DOWN;
|
||||
_serverId = gsi.getId();
|
||||
}
|
||||
}
|
||||
|
||||
public ServerList(L2LoginClient client)
|
||||
{
|
||||
_servers = new ArrayList<>(GameServerTable.getInstance().getRegisteredGameServers().size());
|
||||
_lastServer = client.getLastServer();
|
||||
for (GameServerInfo gsi : GameServerTable.getInstance().getRegisteredGameServers().values())
|
||||
{
|
||||
_servers.add(new ServerData(client, gsi));
|
||||
}
|
||||
_charsOnServers = client.getCharsOnServ();
|
||||
_charsToDelete = client.getCharsWaitingDelOnServ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write()
|
||||
{
|
||||
writeC(0x04);
|
||||
writeC(_servers.size());
|
||||
writeC(_lastServer);
|
||||
for (ServerData server : _servers)
|
||||
{
|
||||
writeC(server._serverId); // server id
|
||||
|
||||
writeC(server._ip[0] & 0xff);
|
||||
writeC(server._ip[1] & 0xff);
|
||||
writeC(server._ip[2] & 0xff);
|
||||
writeC(server._ip[3] & 0xff);
|
||||
|
||||
writeD(server._port);
|
||||
writeC(server._ageLimit); // Age Limit 0, 15, 18
|
||||
writeC(server._pvp ? 0x01 : 0x00);
|
||||
writeH(server._currentPlayers);
|
||||
writeH(server._maxPlayers);
|
||||
writeC(server._status == ServerStatus.STATUS_DOWN ? 0x00 : 0x01);
|
||||
writeD(server._serverType); // 1: Normal, 2: Relax, 4: Public Test, 8: No Label, 16: Character Creation Restricted, 32: Event, 64: Free
|
||||
writeC(server._brackets ? 0x01 : 0x00);
|
||||
}
|
||||
writeH(0x00); // unknown
|
||||
if (_charsOnServers != null)
|
||||
{
|
||||
writeC(_charsOnServers.size());
|
||||
for (int servId : _charsOnServers.keySet())
|
||||
{
|
||||
writeC(servId);
|
||||
writeC(_charsOnServers.get(servId));
|
||||
if ((_charsToDelete == null) || !_charsToDelete.containsKey(servId))
|
||||
{
|
||||
writeC(0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
writeC(_charsToDelete.get(servId).length);
|
||||
for (long deleteTime : _charsToDelete.get(servId))
|
||||
{
|
||||
writeD((int) ((deleteTime - System.currentTimeMillis()) / 1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writeC(0x00);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user