ace-of-shades-2/server/src/main/java/nl/andrewl/aos2_server/ClientHandler.java

123 lines
3.2 KiB
Java

package nl.andrewl.aos2_server;
import nl.andrewl.aos_core.Net;
import nl.andrewl.aos_core.net.ConnectRejectMessage;
import nl.andrewl.aos_core.net.ConnectRequestMessage;
import nl.andrewl.record_net.Message;
import nl.andrewl.record_net.util.ExtendedDataInputStream;
import nl.andrewl.record_net.util.ExtendedDataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.*;
public class ClientHandler extends Thread {
private static int nextThreadId = 1;
private final Server server;
private final Socket socket;
private final DatagramSocket datagramSocket;
private final ExtendedDataInputStream in;
private final ExtendedDataOutputStream out;
private volatile boolean running;
private InetAddress clientAddress;
private int clientUdpPort;
public ClientHandler(Server server, Socket socket, DatagramSocket datagramSocket) throws IOException {
super("aos-client-handler-" + nextThreadId++);
this.server = server;
this.socket = socket;
this.datagramSocket = datagramSocket;
this.in = Net.getInputStream(socket.getInputStream());
this.out = Net.getOutputStream(socket.getOutputStream());
}
public void shutdown() {
running = false;
}
@Override
public void run() {
running = true;
establishConnection();
while (running) {
try {
Message msg = Net.read(in);
} catch (SocketException e) {
if (e.getMessage().equals("Socket closed") | e.getMessage().equals("Connection reset")) {
shutdown();
} else {
e.printStackTrace();
}
} catch (EOFException e) {
shutdown();
} catch (IOException e) {
e.printStackTrace();
shutdown();
}
}
}
private void establishConnection() {
try {
socket.setSoTimeout(1000);
} catch (SocketException e) {
throw new RuntimeException(e);
}
boolean connectionEstablished = false;
int attempts = 0;
while (!connectionEstablished && attempts < 100) {
try {
Message msg = Net.read(in);
if (msg instanceof ConnectRequestMessage connectMsg) {
this.clientAddress = socket.getInetAddress();
this.clientUdpPort = connectMsg.udpPort();
System.out.println("Player connected: " + connectMsg.username());
connectionEstablished = true;
try {
socket.setSoTimeout(0);
} catch (SocketException e) {
throw new RuntimeException(e);
}
}
} catch (IOException e) {
e.printStackTrace();
}
attempts++;
}
if (!connectionEstablished) {
try {
Net.write(new ConnectRejectMessage("Too many connect attempts failed."), out);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Player couldn't connect after " + attempts + " attempts. Aborting.");
shutdown();
}
}
private void sendDatagramPacket(Message msg) {
try {
sendDatagramPacket(Net.write(msg));
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendDatagramPacket(byte[] data) {
DatagramPacket packet = new DatagramPacket(data, data.length, clientAddress, clientUdpPort);
sendDatagramPacket(packet);
}
private void sendDatagramPacket(DatagramPacket packet) {
try {
packet.setAddress(clientAddress);
packet.setPort(clientUdpPort);
datagramSocket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}