mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-02-11 11:27:16 +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";
|
||||
|
||||
namespace com.riiablo.net.packet.bnls;
|
||||
|
||||
union BNLSData {
|
||||
ConnectionClosed,
|
||||
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.backends.headless.HeadlessApplication;
|
||||
import com.badlogic.gdx.backends.headless.HeadlessApplicationConfiguration;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.net.ServerSocket;
|
||||
import com.badlogic.gdx.net.Socket;
|
||||
import com.badlogic.gdx.utils.BufferUtils;
|
||||
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.Realm;
|
||||
|
||||
@ -26,12 +28,14 @@ import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class BNLS extends ApplicationAdapter {
|
||||
private static final String TAG = "BNLS";
|
||||
|
||||
private static final int PORT = 6110;
|
||||
private static final int MAX_CLIENTS = 32;
|
||||
|
||||
public static void main(String[] args) {
|
||||
HeadlessApplicationConfiguration config = new HeadlessApplicationConfiguration();
|
||||
@ -40,9 +44,11 @@ public class BNLS extends ApplicationAdapter {
|
||||
|
||||
ServerSocket server;
|
||||
ByteBuffer buffer;
|
||||
Thread thread;
|
||||
Thread main;
|
||||
AtomicBoolean kill;
|
||||
Thread cli;
|
||||
ThreadGroup clientThreads;
|
||||
CopyOnWriteArrayList<Client> CLIENTS = new CopyOnWriteArrayList<>();
|
||||
|
||||
private static final String[][] REALMS = new String[][] {
|
||||
{"localhost", "U.S. West"},
|
||||
@ -65,42 +71,43 @@ public class BNLS extends ApplicationAdapter {
|
||||
Gdx.app.error(TAG, e.getMessage(), e);
|
||||
}
|
||||
|
||||
clientThreads = new ThreadGroup("BNLSClients");
|
||||
|
||||
Gdx.app.log(TAG, "Starting server...");
|
||||
server = Gdx.net.newServerSocket(Net.Protocol.TCP, PORT, null);
|
||||
buffer = BufferUtils.newByteBuffer(4096);
|
||||
kill = new AtomicBoolean(false);
|
||||
thread = new Thread(new Runnable() {
|
||||
main = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (!kill.get()) {
|
||||
Socket socket = null;
|
||||
try {
|
||||
Gdx.app.log(TAG, "waiting...");
|
||||
socket = server.accept(null);
|
||||
Gdx.app.log(TAG, "connection from " + socket.getRemoteAddress());
|
||||
Gdx.app.log(TAG, "waiting...");
|
||||
Socket socket = server.accept(null);
|
||||
Gdx.app.log(TAG, "connection from " + socket.getRemoteAddress());
|
||||
if (CLIENTS.size() >= MAX_CLIENTS) {
|
||||
try {
|
||||
ConnectionDenied(socket, "Server is Full");
|
||||
} catch (Throwable ignored) {
|
||||
} finally {
|
||||
socket.dispose();
|
||||
}
|
||||
} else {
|
||||
new Client(socket).start();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
Gdx.app.log(TAG, "killing child threads...");
|
||||
for (Client client : CLIENTS) {
|
||||
if (client != null) {
|
||||
client.kill.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
Gdx.app.log(TAG, "killing thread...");
|
||||
}
|
||||
});
|
||||
thread.setName("BNLS");
|
||||
thread.start();
|
||||
main.setName("BNLS");
|
||||
main.start();
|
||||
|
||||
cli = new Thread(new Runnable() {
|
||||
@Override
|
||||
@ -134,7 +141,7 @@ public class BNLS extends ApplicationAdapter {
|
||||
kill.set(true);
|
||||
server.dispose();
|
||||
try {
|
||||
thread.join();
|
||||
main.join();
|
||||
} 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();
|
||||
|
||||
int[] realms = new int[REALMS.length];
|
||||
@ -171,5 +192,42 @@ public class BNLS extends ApplicationAdapter {
|
||||
WritableByteChannel channel = Channels.newChannel(out);
|
||||
channel.write(data);
|
||||
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();
|
||||
|
||||
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());
|
||||
Gdx.app.log(TAG, "realms:");
|
||||
|
Loading…
Reference in New Issue
Block a user