WebSocket API

This commit is contained in:
2023-03-14 16:22:50 +01:00
parent b6dba62fa4
commit fd828d600e
16 changed files with 910 additions and 3 deletions

View File

@@ -0,0 +1,60 @@
package fr.pandacube.lib.ws.server;
import fr.pandacube.lib.ws.AbstractWS;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
import java.io.IOException;
/**
* Minimal implementation of a Websocket server endpoint using the Jetty Websocket API.
*/
public abstract class AbstractServerWS extends WebSocketAdapter implements AbstractWS {
@Override
public final void onWebSocketConnect(Session sess)
{
super.onWebSocketConnect(sess);
onConnect();
}
@Override
public final void onWebSocketBinary(byte[] payload, int offset, int len) {
handleReceivedBinary();
}
@Override
public final void onWebSocketText(String message) {
handleReceivedMessage(message);
}
@Override
public final void onWebSocketClose(int statusCode, String reason) {
onClose(statusCode, reason);
}
@Override
public final void onWebSocketError(Throwable cause) {
onError(cause);
}
public final void sendString(String message) throws IOException {
getSession().getRemote().sendString(message);
}
@Override
public final void sendClose(int code, String reason) throws IOException {
getSession().close(code, reason);
}
@Override
public String getRemoteIdentifier() {
return getSession().getRemoteAddress().toString();
}
}

View File

@@ -0,0 +1,95 @@
package fr.pandacube.lib.ws.server;
import fr.pandacube.lib.ws.payloads.ErrorPayload;
import fr.pandacube.lib.ws.payloads.LoginPayload;
import fr.pandacube.lib.ws.payloads.LoginSucceedPayload;
import fr.pandacube.lib.ws.payloads.Payload;
import java.util.function.Supplier;
/**
* Websocket server endpoint that is protected with a key.
*/
public abstract class KeyProtectedServerWS extends AbstractServerWS {
private boolean loginSucceed = false;
private final Supplier<String> keySupplier;
/**
* Creates a websocket server endpoint protected by the key given by the provided {@link Supplier}.
* @param keySupplier a {@link Supplier} for the key.
*/
public KeyProtectedServerWS(Supplier<String> keySupplier) {
this.keySupplier = keySupplier;
}
@Override
public final void onConnect() {
// nothing, just wait for the client to login
}
@Override
public final void onReceivePayload(Payload payload) {
if (loginSucceed) {
onReceivePayloadLoggedIn(payload);
}
else if (payload instanceof LoginPayload login) {
if (keySupplier.get().equals(login.key)) {
loginSucceed = true;
trySendAsJson(new LoginSucceedPayload());
onLoginSucceed();
}
else {
logAndTrySendError(new ErrorPayload("Bad key"));
trySendClose();
}
}
else {
logAndTrySendError(new ErrorPayload("Please use the login packet first. Received " + payload.getClass().getSimpleName() + " instead."));
trySendClose();
}
}
@Override
public final void onClose(int code, String reason) {
if (loginSucceed) {
onCloseLoggedIn(code, reason);
}
}
@Override
public final void onError(Throwable cause) {
if (loginSucceed) {
onErrorLoggedIn(cause);
}
}
/**
* Called when the client endpoint is succesfully logged in.
*/
public abstract void onLoginSucceed();
/**
* Called on reception of a valid payload from the already logged in client.
* @param payload the received payload.
*/
public abstract void onReceivePayloadLoggedIn(Payload payload);
/**
* Called on reception of a websocket Close packet, only if the client endpoint is already logged in.
* The connection is closed after this method call.
* @param code the close code. 1000 for a normal closure.
* @param reason the close reason.
*/
public abstract void onCloseLoggedIn(int code, String reason);
/**
* Called when an error occurs with the websocket API, only if the client endpoint is already logged in.
* The connection is already closed when this method is called.
* @param cause the error cause.
*/
public abstract void onErrorLoggedIn(Throwable cause);
}