mirror of
https://github.com/ProjectSWGCore/Holocore.git
synced 2026-07-14 00:03:01 -04:00
Basic HTTPS server
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user