mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-02-11 19:37:47 +07:00
Added support for multiple client connections to BNLS
Added support for multiple client connections to BNLS Added support for ConnectionClosed packet to politely close connection
This commit is contained in:
parent
3b24c3a58b
commit
7495aff11d
@ -1,8 +1,10 @@
|
|||||||
|
include "ConnectionClosed.fbs";
|
||||||
include "QueryRealms.fbs";
|
include "QueryRealms.fbs";
|
||||||
|
|
||||||
namespace com.riiablo.net.packet.bnls;
|
namespace com.riiablo.net.packet.bnls;
|
||||||
|
|
||||||
union BNLSData {
|
union BNLSData {
|
||||||
|
ConnectionClosed,
|
||||||
QueryRealms,
|
QueryRealms,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
core/src/com/riiablo/net/bnls/ConnectionClosed.fbs
Normal file
5
core/src/com/riiablo/net/bnls/ConnectionClosed.fbs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
namespace com.riiablo.net.packet.bnls;
|
||||||
|
|
||||||
|
table ConnectionClosed {
|
||||||
|
reason:string;
|
||||||
|
}
|
@ -7,10 +7,12 @@ import com.badlogic.gdx.Gdx;
|
|||||||
import com.badlogic.gdx.Net;
|
import com.badlogic.gdx.Net;
|
||||||
import com.badlogic.gdx.backends.headless.HeadlessApplication;
|
import com.badlogic.gdx.backends.headless.HeadlessApplication;
|
||||||
import com.badlogic.gdx.backends.headless.HeadlessApplicationConfiguration;
|
import com.badlogic.gdx.backends.headless.HeadlessApplicationConfiguration;
|
||||||
|
import com.badlogic.gdx.math.MathUtils;
|
||||||
import com.badlogic.gdx.net.ServerSocket;
|
import com.badlogic.gdx.net.ServerSocket;
|
||||||
import com.badlogic.gdx.net.Socket;
|
import com.badlogic.gdx.net.Socket;
|
||||||
import com.badlogic.gdx.utils.BufferUtils;
|
import com.badlogic.gdx.utils.BufferUtils;
|
||||||
import com.riiablo.net.packet.bnls.BNLSData;
|
import com.riiablo.net.packet.bnls.BNLSData;
|
||||||
|
import com.riiablo.net.packet.bnls.ConnectionClosed;
|
||||||
import com.riiablo.net.packet.bnls.QueryRealms;
|
import com.riiablo.net.packet.bnls.QueryRealms;
|
||||||
import com.riiablo.net.packet.bnls.Realm;
|
import com.riiablo.net.packet.bnls.Realm;
|
||||||
|
|
||||||
@ -26,12 +28,14 @@ import java.nio.channels.ReadableByteChannel;
|
|||||||
import java.nio.channels.WritableByteChannel;
|
import java.nio.channels.WritableByteChannel;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class BNLS extends ApplicationAdapter {
|
public class BNLS extends ApplicationAdapter {
|
||||||
private static final String TAG = "BNLS";
|
private static final String TAG = "BNLS";
|
||||||
|
|
||||||
private static final int PORT = 6110;
|
private static final int PORT = 6110;
|
||||||
|
private static final int MAX_CLIENTS = 32;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
HeadlessApplicationConfiguration config = new HeadlessApplicationConfiguration();
|
HeadlessApplicationConfiguration config = new HeadlessApplicationConfiguration();
|
||||||
@ -40,9 +44,11 @@ public class BNLS extends ApplicationAdapter {
|
|||||||
|
|
||||||
ServerSocket server;
|
ServerSocket server;
|
||||||
ByteBuffer buffer;
|
ByteBuffer buffer;
|
||||||
Thread thread;
|
Thread main;
|
||||||
AtomicBoolean kill;
|
AtomicBoolean kill;
|
||||||
Thread cli;
|
Thread cli;
|
||||||
|
ThreadGroup clientThreads;
|
||||||
|
CopyOnWriteArrayList<Client> CLIENTS = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
private static final String[][] REALMS = new String[][] {
|
private static final String[][] REALMS = new String[][] {
|
||||||
{"localhost", "U.S. West"},
|
{"localhost", "U.S. West"},
|
||||||
@ -65,42 +71,43 @@ public class BNLS extends ApplicationAdapter {
|
|||||||
Gdx.app.error(TAG, e.getMessage(), e);
|
Gdx.app.error(TAG, e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clientThreads = new ThreadGroup("BNLSClients");
|
||||||
|
|
||||||
Gdx.app.log(TAG, "Starting server...");
|
Gdx.app.log(TAG, "Starting server...");
|
||||||
server = Gdx.net.newServerSocket(Net.Protocol.TCP, PORT, null);
|
server = Gdx.net.newServerSocket(Net.Protocol.TCP, PORT, null);
|
||||||
buffer = BufferUtils.newByteBuffer(4096);
|
buffer = BufferUtils.newByteBuffer(4096);
|
||||||
kill = new AtomicBoolean(false);
|
kill = new AtomicBoolean(false);
|
||||||
thread = new Thread(new Runnable() {
|
main = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (!kill.get()) {
|
while (!kill.get()) {
|
||||||
Socket socket = null;
|
Gdx.app.log(TAG, "waiting...");
|
||||||
try {
|
Socket socket = server.accept(null);
|
||||||
Gdx.app.log(TAG, "waiting...");
|
Gdx.app.log(TAG, "connection from " + socket.getRemoteAddress());
|
||||||
socket = server.accept(null);
|
if (CLIENTS.size() >= MAX_CLIENTS) {
|
||||||
Gdx.app.log(TAG, "connection from " + socket.getRemoteAddress());
|
try {
|
||||||
|
ConnectionDenied(socket, "Server is Full");
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
} finally {
|
||||||
|
socket.dispose();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new Client(socket).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buffer.mark();
|
Gdx.app.log(TAG, "killing child threads...");
|
||||||
ReadableByteChannel in = Channels.newChannel(socket.getInputStream());
|
for (Client client : CLIENTS) {
|
||||||
in.read(buffer);
|
if (client != null) {
|
||||||
buffer.limit(buffer.position());
|
client.kill.set(true);
|
||||||
buffer.reset();
|
|
||||||
|
|
||||||
com.riiablo.net.packet.bnls.BNLS packet = com.riiablo.net.packet.bnls.BNLS.getRootAsBNLS(buffer);
|
|
||||||
Gdx.app.log(TAG, "packet type " + BNLSData.name(packet.dataType()));
|
|
||||||
process(socket, packet);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Gdx.app.log(TAG, t.getMessage());
|
|
||||||
} finally {
|
|
||||||
Gdx.app.log(TAG, "closing socket...");
|
|
||||||
if (socket != null) socket.dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Gdx.app.log(TAG, "killing thread...");
|
Gdx.app.log(TAG, "killing thread...");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
thread.setName("BNLS");
|
main.setName("BNLS");
|
||||||
thread.start();
|
main.start();
|
||||||
|
|
||||||
cli = new Thread(new Runnable() {
|
cli = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@ -134,7 +141,7 @@ public class BNLS extends ApplicationAdapter {
|
|||||||
kill.set(true);
|
kill.set(true);
|
||||||
server.dispose();
|
server.dispose();
|
||||||
try {
|
try {
|
||||||
thread.join();
|
main.join();
|
||||||
} catch (Throwable ignored) {}
|
} catch (Throwable ignored) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +155,21 @@ public class BNLS extends ApplicationAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void QueryRealms(Socket socket) throws IOException {
|
private boolean ConnectionDenied(Socket socket, String reason) throws IOException {
|
||||||
|
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||||
|
int reasonOffset = builder.createString(reason);
|
||||||
|
int connectionDeniedId = ConnectionClosed.createConnectionClosed(builder, reasonOffset);
|
||||||
|
int id = com.riiablo.net.packet.bnls.BNLS.createBNLS(builder, BNLSData.ConnectionClosed, connectionDeniedId);
|
||||||
|
builder.finish(id);
|
||||||
|
|
||||||
|
ByteBuffer data = builder.dataBuffer();
|
||||||
|
OutputStream out = socket.getOutputStream();
|
||||||
|
WritableByteChannel channel = Channels.newChannel(out);
|
||||||
|
channel.write(data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean QueryRealms(Socket socket) throws IOException {
|
||||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||||
|
|
||||||
int[] realms = new int[REALMS.length];
|
int[] realms = new int[REALMS.length];
|
||||||
@ -171,5 +192,42 @@ public class BNLS extends ApplicationAdapter {
|
|||||||
WritableByteChannel channel = Channels.newChannel(out);
|
WritableByteChannel channel = Channels.newChannel(out);
|
||||||
channel.write(data);
|
channel.write(data);
|
||||||
Gdx.app.log(TAG, "returning realms list...");
|
Gdx.app.log(TAG, "returning realms list...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String generateClientName() {
|
||||||
|
return String.format("Client-%08X", MathUtils.random(1, Integer.MAX_VALUE - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Client extends Thread {
|
||||||
|
Socket socket;
|
||||||
|
AtomicBoolean kill = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
Client(Socket socket) {
|
||||||
|
super(clientThreads, generateClientName());
|
||||||
|
this.socket = socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (!kill.get()) {
|
||||||
|
try {
|
||||||
|
buffer.mark();
|
||||||
|
ReadableByteChannel in = Channels.newChannel(socket.getInputStream());
|
||||||
|
in.read(buffer);
|
||||||
|
buffer.limit(buffer.position());
|
||||||
|
buffer.reset();
|
||||||
|
|
||||||
|
com.riiablo.net.packet.bnls.BNLS packet = com.riiablo.net.packet.bnls.BNLS.getRootAsBNLS(buffer);
|
||||||
|
Gdx.app.log(TAG, "packet type " + BNLSData.name(packet.dataType()));
|
||||||
|
process(socket, packet);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Gdx.app.log(TAG, t.getMessage());
|
||||||
|
} finally {
|
||||||
|
Gdx.app.log(TAG, "closing socket...");
|
||||||
|
if (socket != null) socket.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,12 @@ public class BNLSTest {
|
|||||||
buffer.rewind();
|
buffer.rewind();
|
||||||
|
|
||||||
com.riiablo.net.packet.bnls.BNLS packet = com.riiablo.net.packet.bnls.BNLS.getRootAsBNLS(buffer);
|
com.riiablo.net.packet.bnls.BNLS packet = com.riiablo.net.packet.bnls.BNLS.getRootAsBNLS(buffer);
|
||||||
Gdx.app.log(TAG, "packet " + packet.dataType());
|
Gdx.app.log(TAG, "packet " + BNLSData.name(packet.dataType()));
|
||||||
|
|
||||||
|
if (packet.dataType() == BNLSData.ConnectionClosed) {
|
||||||
|
Gdx.app.log(TAG, "connection closed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QueryRealms qr = (QueryRealms) packet.data(new QueryRealms());
|
QueryRealms qr = (QueryRealms) packet.data(new QueryRealms());
|
||||||
Gdx.app.log(TAG, "realms:");
|
Gdx.app.log(TAG, "realms:");
|
||||||
|
Loading…
Reference in New Issue
Block a user