Launcher/LaunchServer/src/main/java/ru/gravit/launchserver/socket/ServerSocketHandler.java

125 lines
4.2 KiB
Java
Raw Normal View History

2018-09-17 10:07:32 +03:00
package ru.gravit.launchserver.socket;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
2018-12-26 15:33:49 +03:00
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
2018-09-17 10:07:32 +03:00
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
2018-12-26 15:33:49 +03:00
import ru.gravit.launcher.managers.GarbageManager;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.manangers.SessionManager;
import ru.gravit.utils.helper.CommonHelper;
import ru.gravit.utils.helper.LogHelper;
2018-09-17 10:07:32 +03:00
public final class ServerSocketHandler implements Runnable, AutoCloseable {
public interface Listener {
2018-10-13 11:01:10 +03:00
2018-09-17 10:07:32 +03:00
boolean onConnect(InetAddress address);
2018-10-13 11:01:10 +03:00
2018-09-17 10:07:32 +03:00
void onDisconnect(Exception e);
2018-10-13 11:01:10 +03:00
2018-09-17 10:07:32 +03:00
boolean onHandshake(long session, Integer type);
}
2018-09-22 17:33:00 +03:00
2018-09-17 10:07:32 +03:00
private static final ThreadFactory THREAD_FACTORY = r -> CommonHelper.newThread("Network Thread", true, r);
2018-10-13 11:01:10 +03:00
2018-09-17 10:07:32 +03:00
public volatile boolean logConnections = Boolean.getBoolean("launcher.logConnections");
// Instance
private final LaunchServer server;
private final AtomicReference<ServerSocket> serverSocket = new AtomicReference<>();
private final ExecutorService threadPool;
2018-09-17 10:07:32 +03:00
public final SessionManager sessionManager;
private final AtomicLong idCounter = new AtomicLong(0L);
private volatile Listener listener;
public ServerSocketHandler(LaunchServer server) {
this(server, new SessionManager());
2018-09-17 10:07:32 +03:00
GarbageManager.registerNeedGC(sessionManager);
}
public ServerSocketHandler(LaunchServer server, SessionManager sessionManager) {
this.server = server;
threadPool = new ThreadPoolExecutor(server.config.threadCoreCount, Integer.MAX_VALUE,
2018-12-20 18:45:01 +03:00
server.config.threadCount, TimeUnit.SECONDS,
2018-12-20 18:52:09 +03:00
new SynchronousQueue<>(),
THREAD_FACTORY);
2018-09-17 10:07:32 +03:00
this.sessionManager = sessionManager;
}
@Override
public void close() {
ServerSocket socket = serverSocket.getAndSet(null);
if (socket != null) {
LogHelper.info("Closing server socket listener");
try {
socket.close();
} catch (IOException e) {
LogHelper.error(e);
}
}
}
/*package*/ void onDisconnect(Exception e) {
if (listener != null)
2018-09-22 17:33:00 +03:00
listener.onDisconnect(e);
2018-09-17 10:07:32 +03:00
}
/*package*/ boolean onHandshake(long session, Integer type) {
return listener == null || listener.onHandshake(session, type);
}
@Override
public void run() {
LogHelper.info("Starting server socket thread");
try (ServerSocket serverSocket = new ServerSocket()) {
if (!this.serverSocket.compareAndSet(null, serverSocket))
2018-09-22 17:33:00 +03:00
throw new IllegalStateException("Previous socket wasn't closed");
2018-09-17 10:07:32 +03:00
// Set socket params
serverSocket.setReuseAddress(true);
serverSocket.setPerformancePreferences(1, 0, 2);
//serverSocket.setReceiveBufferSize(0x10000);
serverSocket.bind(server.config.getSocketAddress());
LogHelper.info("Server socket thread successfully started");
// Listen for incoming connections
while (serverSocket.isBound()) {
Socket socket = serverSocket.accept();
// Invoke pre-connect listener
long id = idCounter.incrementAndGet();
if (listener != null && !listener.onConnect(socket.getInetAddress()))
2019-01-02 14:11:01 +03:00
{
socket.close();
2018-09-22 17:33:00 +03:00
continue; // Listener didn't accepted this connection
2019-01-02 14:11:01 +03:00
}
2018-09-17 10:07:32 +03:00
// Reply in separate thread
2018-12-29 13:00:50 +03:00
threadPool.execute(new ResponseThread(server, id, socket, sessionManager, server.socketHookManager));
2018-09-17 10:07:32 +03:00
}
} catch (IOException e) {
// Ignore error after close/rebind
if (serverSocket.get() != null)
2018-09-22 17:33:00 +03:00
LogHelper.error(e);
2018-09-17 10:07:32 +03:00
}
}
2018-10-13 11:01:10 +03:00
2018-09-17 10:07:32 +03:00
public void setListener(Listener listener) {
this.listener = listener;
}
}