/** * This file is part of aion-emu <aion-emu.com>. * * aion-emu 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. * * aion-emu 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 aion-emu. If not, see <http://www.gnu.org/licenses/>. */ package com.aionemu.gameserver.network.loginserver; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.ArrayDeque; import java.util.Deque; import org.apache.log4j.Logger; import com.aionemu.commons.network.AConnection; import com.aionemu.commons.network.Dispatcher; import com.aionemu.gameserver.network.loginserver.serverpackets.SM_GS_AUTH; import com.aionemu.gameserver.utils.ThreadPoolManager; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; /** * Object representing connection between LoginServer and GameServer. * * @author -Nemesiss- * */ public class LoginServerConnection extends AConnection { /** * Logger for this class. */ private static final Logger log = Logger.getLogger(LoginServerConnection.class); /** * Possible states of GsConnection */ public static enum State { /** * game server just connect */ CONNECTED, /** * game server is authenticated */ AUTHED } /** * Server Packet "to send" Queue */ private final Deque<LsServerPacket> sendMsgQueue = new ArrayDeque<LsServerPacket>(); /** * Current state of this connection */ private State state; private LoginServer loginServer; private LsPacketHandler lsPacketHandler; /** * Constructor. * * @param sc * @param d * @throws IOException */ @Inject public LoginServerConnection(@Assisted SocketChannel sc,@Assisted Dispatcher d, LoginServer loginServer, LsPacketHandler lsPacketHandler) throws IOException { super(sc, d); this.loginServer = loginServer; this.lsPacketHandler = lsPacketHandler; state = State.CONNECTED; log.info("Connected to LoginServer!"); /** * send first packet - authentication. */ this.sendPacket(new SM_GS_AUTH()); } /** * Called by Dispatcher. ByteBuffer data contains one packet that should be processed. * * @param data * @return True if data was processed correctly, False if some error occurred and connection should be closed NOW. */ @Override public boolean processData(ByteBuffer data) { LsClientPacket pck = lsPacketHandler.handle(data, this); log.info("recived packet: " + pck); /** * Execute packet only if packet exist (!= null) and read was ok. */ if(pck != null && pck.read()) ThreadPoolManager.getInstance().executeLsPacket(pck); return true; } /** * This method will be called by Dispatcher, and will be repeated till return false. * * @param data * @return True if data was written to buffer, False indicating that there are not any more data to write. */ @Override protected final boolean writeData(ByteBuffer data) { synchronized(guard) { LsServerPacket packet = sendMsgQueue.pollFirst(); if(packet == null) return false; packet.write(this, data); return true; } } /** * This method is called by Dispatcher when connection is ready to be closed. * * @return time in ms after witch onDisconnect() method will be called. Always return 0. */ @Override protected final long getDisconnectionDelay() { return 0; } /** * {@inheritDoc} */ @Override protected final void onDisconnect() { loginServer.loginServerDown(); } /** * {@inheritDoc} */ @Override protected final void onServerClose() { // TODO mb some packet should be send to loginserver before closing? close(/* packet, */true); } /** * Sends GsServerPacket to this client. * * @param bp * GsServerPacket to be sent. */ public final void sendPacket(LsServerPacket bp) { synchronized(guard) { /** * Connection is already closed or waiting for last (close packet) to be sent */ if(isWriteDisabled()) return; log.info("sending packet: " + bp); sendMsgQueue.addLast(bp); enableWriteInterest(); } } /** * Its guaranted that closePacket will be sent before closing connection, but all past and future packets wont. * Connection will be closed [by Dispatcher Thread], and onDisconnect() method will be called to clear all other * things. forced means that server shouldn't wait with removing this connection. * * @param closePacket * Packet that will be send before closing. * @param forced * have no effect in this implementation. */ public final void close(LsServerPacket closePacket, boolean forced) { synchronized(guard) { if(isWriteDisabled()) return; log.info("sending packet: " + closePacket + " and closing connection after that."); pendingClose = true; isForcedClosing = forced; sendMsgQueue.clear(); sendMsgQueue.addLast(closePacket); enableWriteInterest(); } } /** * @return Current state of this connection. */ public State getState() { return state; } /** * @param state * Set current state of this connection. */ public void setState(State state) { this.state = state; } /** * @return String info about this connection */ @Override public String toString() { return "LoginServer " + getIP(); } }