mirror of
https://github.com/ProjectSWGCore/Holocore.git
synced 2026-01-15 23:05:45 -05:00
197 lines
4.8 KiB
Java
197 lines
4.8 KiB
Java
package services.admin.http;
|
|
|
|
import java.io.IOException;
|
|
import java.net.InetAddress;
|
|
import java.net.ServerSocket;
|
|
import java.net.Socket;
|
|
import java.net.SocketException;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
import resources.server_info.Log;
|
|
import services.admin.http.HttpSocket.HttpRequest;
|
|
import utilities.ThreadUtilities;
|
|
|
|
public class HttpServer {
|
|
|
|
private static final String TAG = "HttpServer";
|
|
|
|
private final InetAddress addr;
|
|
private final int port;
|
|
|
|
private ExecutorService executor;
|
|
private ServerSocket serverSocket;
|
|
private AtomicInteger currentConnections;
|
|
private HttpServerCallback callback;
|
|
private int maxConnections;
|
|
private boolean secure;
|
|
|
|
protected HttpServer(InetAddress addr, int port, boolean secure) {
|
|
this.addr = addr;
|
|
this.port = port;
|
|
this.currentConnections = new AtomicInteger(0);
|
|
this.callback = null;
|
|
this.maxConnections = 2;
|
|
this.secure = secure;
|
|
}
|
|
|
|
public HttpServer(InetAddress addr, int port) {
|
|
this(addr, port, false);
|
|
}
|
|
|
|
public void start() {
|
|
executor = Executors.newCachedThreadPool(ThreadUtilities.newThreadFactory(getThreadFactoryName()));
|
|
try {
|
|
serverSocket = createSocket();
|
|
startAcceptThread(serverSocket, secure);
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
public void stop() {
|
|
if (serverSocket != null) {
|
|
try {
|
|
serverSocket.close();
|
|
} catch (IOException e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
if (executor != null) {
|
|
executor.shutdownNow();
|
|
try {
|
|
executor.awaitTermination(1, TimeUnit.SECONDS);
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void setServerCallback(HttpServerCallback callback) {
|
|
this.callback = callback;
|
|
}
|
|
|
|
public void setMaxConnections(int maxConnections) {
|
|
this.maxConnections = maxConnections;
|
|
}
|
|
|
|
public final InetAddress getBindAddress() {
|
|
return addr;
|
|
}
|
|
|
|
public final int getBindPort() {
|
|
return port;
|
|
}
|
|
|
|
protected String getThreadFactoryName() {
|
|
return "HttpServer-%d";
|
|
}
|
|
|
|
protected ServerSocket createSocket() throws IOException {
|
|
return new ServerSocket(port, 0, addr);
|
|
}
|
|
|
|
private void startAcceptThread(ServerSocket serverSocket, boolean secure) {
|
|
executor.submit(() -> {
|
|
try {
|
|
acceptThread(serverSocket, secure);
|
|
} catch (Throwable t) {
|
|
t.printStackTrace();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void startSocketThread(HttpSocket socket) {
|
|
executor.submit(() -> {
|
|
try {
|
|
socketThread(socket);
|
|
} catch (Throwable t) {
|
|
t.printStackTrace();
|
|
}
|
|
try {
|
|
socket.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
synchronized (currentConnections) {
|
|
currentConnections.decrementAndGet();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void acceptThread(ServerSocket serverSocket, boolean secure) {
|
|
Log.i(TAG, "Now listening over HTTP%s. Address: %s:%d", secure?"S":"", serverSocket.getInetAddress(), serverSocket.getLocalPort());
|
|
while (serverSocket.isBound() && !serverSocket.isClosed()) {
|
|
try {
|
|
Socket socket = serverSocket.accept();
|
|
HttpSocket httpSocket = new HttpSocket(socket, secure);
|
|
if (!httpSocket.isOpened()) {
|
|
httpSocket.close();
|
|
continue;
|
|
}
|
|
if (currentConnections.get() >= maxConnections) {
|
|
httpSocket.send(HttpStatusCode.SERVICE_UNAVAILABLE, "The server has reached it's maximum connection limit: " + maxConnections);
|
|
socket.close();
|
|
} else {
|
|
if (currentConnections.incrementAndGet() > maxConnections) {
|
|
socket.close();
|
|
currentConnections.decrementAndGet();
|
|
} else {
|
|
startSocketThread(httpSocket);
|
|
}
|
|
}
|
|
} catch (SocketException e) {
|
|
if (serverSocket.isClosed())
|
|
break;
|
|
e.printStackTrace();
|
|
} catch (Throwable t) {
|
|
t.printStackTrace();
|
|
}
|
|
}
|
|
Log.i(TAG, "No longer listening over HTTP%s!", secure?"S":"");
|
|
}
|
|
|
|
private void socketThread(HttpSocket socket) throws IOException {
|
|
onSocketCreated(socket);
|
|
HttpRequest request;
|
|
while (socket.isOpened() && !socket.isClosed()) {
|
|
request = socket.waitForRequest();
|
|
if (request == null)
|
|
break;
|
|
if (request.getType() == null || request.getURI() == null || request.getHttpVersion() == null) {
|
|
socket.send(HttpStatusCode.BAD_REQUEST);
|
|
continue;
|
|
}
|
|
onRequestReceived(socket, request);
|
|
}
|
|
}
|
|
|
|
private void onSocketCreated(HttpSocket socket) {
|
|
if (callback == null)
|
|
return;
|
|
try {
|
|
callback.onSocketCreated(socket);
|
|
} catch (Throwable t) {
|
|
t.printStackTrace();
|
|
}
|
|
}
|
|
|
|
private void onRequestReceived(HttpSocket socket, HttpRequest request) {
|
|
if (callback == null)
|
|
return;
|
|
try {
|
|
callback.onRequestReceived(socket, request);
|
|
} catch (Throwable t) {
|
|
t.printStackTrace();
|
|
}
|
|
}
|
|
|
|
public interface HttpServerCallback {
|
|
void onSocketCreated(HttpSocket socket);
|
|
void onRequestReceived(HttpSocket socket, HttpRequest request);
|
|
}
|
|
|
|
}
|