119 lines
3.1 KiB
Java
119 lines
3.1 KiB
Java
package ms.net;
|
|
|
|
import ms.world.WorldDatabase;
|
|
import ms09.MSLogger;
|
|
|
|
import java.io.IOException;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.channels.ClosedChannelException;
|
|
import java.nio.channels.ReadableByteChannel;
|
|
import java.nio.channels.SelectionKey;
|
|
import java.nio.channels.Selector;
|
|
import java.nio.channels.ServerSocketChannel;
|
|
import java.nio.channels.SocketChannel;
|
|
import java.util.Arrays;
|
|
import java.util.concurrent.ExecutorService;
|
|
|
|
/**
|
|
* I/O event handling.
|
|
* @author Emperor
|
|
*
|
|
*/
|
|
public final class IoEventHandler {
|
|
|
|
/**
|
|
* The executor service.
|
|
*/
|
|
private final ExecutorService service;
|
|
|
|
/**
|
|
* Constructs a new {@code IoEventHandler}.
|
|
* @param service The executor service used for handling events.
|
|
*/
|
|
public IoEventHandler(ExecutorService service) {
|
|
this.service = service;
|
|
}
|
|
|
|
/**
|
|
* Called when making a new connection.
|
|
* @param key The selection key.
|
|
*/
|
|
public void connect(SelectionKey key) {
|
|
/*
|
|
* empty.
|
|
*/
|
|
}
|
|
|
|
/**
|
|
* Used for accepting a new connection.
|
|
* @param key The selection key.
|
|
* @param selector The selector.
|
|
* @throws IOException When an I/O exception occurs.
|
|
*/
|
|
public void accept(SelectionKey key, Selector selector) throws IOException {
|
|
SocketChannel sc = ((ServerSocketChannel) key.channel()).accept();
|
|
sc.configureBlocking(false);
|
|
sc.socket().setTcpNoDelay(true);
|
|
sc.register(selector, SelectionKey.OP_READ);
|
|
}
|
|
|
|
/**
|
|
* Reads the incoming packet data.
|
|
* @param key The selection key.
|
|
* @throws IOException When an I/O exception occurs.
|
|
*/
|
|
public void read(SelectionKey key) throws IOException {
|
|
ReadableByteChannel channel = (ReadableByteChannel) key.channel();
|
|
ByteBuffer buffer = ByteBuffer.allocate(100_000);
|
|
IoSession session = (IoSession) key.attachment();
|
|
if (channel.read(buffer) == -1) {
|
|
if(session == null){
|
|
key.cancel();
|
|
return;
|
|
}
|
|
if(session.getGameServer() != null){
|
|
WorldDatabase.unRegister(session.getGameServer());
|
|
}
|
|
session.disconnect();
|
|
key.cancel();
|
|
return;
|
|
}
|
|
buffer.flip();
|
|
if (session == null) {
|
|
key.attach(session = new IoSession(key, service));
|
|
}
|
|
service.execute(session.getProducer().produceReader(session, buffer));
|
|
}
|
|
|
|
/**
|
|
* Writes the outgoing packet data.
|
|
* @param key The selection key.
|
|
*/
|
|
public void write(SelectionKey key) {
|
|
IoSession session = (IoSession) key.attachment();
|
|
if(session != null) {
|
|
key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
|
|
session.write();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disconnects a connection.
|
|
* @param key The selection key.
|
|
* @param t The occurred exception (if any).
|
|
*/
|
|
public void disconnect(SelectionKey key, Throwable t) {
|
|
try {
|
|
IoSession session = (IoSession) key.attachment();
|
|
String cause = "" + t;
|
|
if (t != null && !(t instanceof ClosedChannelException || cause.contains("De externe host") || cause.contains("De software op uw") || cause.contains("An established connection was aborted") || cause.contains("An existing connection") || cause.contains("AsynchronousClose"))) {
|
|
t.printStackTrace();
|
|
}
|
|
if (session != null) {
|
|
session.disconnect();
|
|
}
|
|
} catch (Throwable e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
} |