/*
OrpheusMS: MapleStory Private Server based on OdinMS
Copyright (C) 2012 Aaron Weiss <aaron@deviant-core.net>
Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net;
import client.MapleClient;
import constants.ServerConstants;
import net.server.Server;
import tools.MapleAESOFB;
import tools.MaplePacketCreator;
import tools.Output;
import tools.data.input.ByteArrayByteStream;
import tools.data.input.GenericSeekableLittleEndianAccessor;
import tools.data.input.SeekableLittleEndianAccessor;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import tools.MapleLogger;
public class MapleServerHandler extends IoHandlerAdapter {
private PacketProcessor processor;
private byte world = -1, channel = -1;
public MapleServerHandler(PacketProcessor processor) {
this.processor = processor;
}
public MapleServerHandler(PacketProcessor processor, byte channel, byte world) {
this.processor = processor;
this.channel = channel;
this.world = world;
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
Runnable r = ((MaplePacket) message).getOnSend();
if (r != null) {
r.run();
}
super.messageSent(session, message);
}
@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
/*
* synchronized (session) { MapleClient client = ((MapleClient)
* session.getAttribute(MapleClient.CLIENT_KEY)); if (client != null) {
* client.disconnect(); } }
*/
session.close(true);
MapleLogger.print(MapleLogger.EXCEPTION_CAUGHT, cause);
// sessionClosed should be called
}
@Override
public void sessionOpened(IoSession session) {
if (!Server.getInstance().isOnline()) {
session.close(true);
return;
}
if (channel > -1 && world > -1) {
if (Server.getInstance().getChannel(world, channel) == null) {
session.close(true);
return;
}
} else {
Output.print("IoSession with " + session.getRemoteAddress() + " opened.");
}
byte key[] = {0x13, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, (byte) 0xB4, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00};
byte ivRecv[] = {70, 114, 122, 82};
byte ivSend[] = {82, 48, 120, 115};
ivRecv[3] = (byte) (Math.random() * 255);
ivSend[3] = (byte) (Math.random() * 255);
MapleAESOFB sendCypher = new MapleAESOFB(key, ivSend, (short) (0xFFFF - ServerConstants.VERSION));
MapleAESOFB recvCypher = new MapleAESOFB(key, ivRecv, (short) ServerConstants.VERSION);
MapleClient client = new MapleClient(sendCypher, recvCypher, session);
client.setWorld(world);
client.setChannel(channel);
session.write(MaplePacketCreator.getHello(ServerConstants.VERSION, ivSend, ivRecv));
session.setAttribute(MapleClient.CLIENT_KEY, client);
}
@Override
public void sessionClosed(IoSession session) throws Exception {
synchronized (session) {
MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
if (client != null) {
try {
client.disconnect();
} finally {
session.removeAttribute(MapleClient.CLIENT_KEY);
client.empty();
}
}
}
super.sessionClosed(session);
}
@Override
public void messageReceived(IoSession session, Object message) {
byte[] content = (byte[]) message;
SeekableLittleEndianAccessor slea = new GenericSeekableLittleEndianAccessor(new ByteArrayByteStream(content));
short packetId = slea.readShort();
MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
MaplePacketHandler packetHandler = processor.getHandler(packetId);
if (packetHandler != null && packetHandler.validateState(client)) {
try {
packetHandler.handlePacket(slea, client);
} catch (Throwable t) {
}
}
}
@Override
public void sessionIdle(final IoSession session, final IdleStatus status) throws Exception {
MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
if (client != null) {
client.sendPing();
}
super.sessionIdle(session, status);
}
}