WebSocket API
This commit is contained in:
29
pandalib-ws-server/pom.xml
Normal file
29
pandalib-ws-server/pom.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>pandalib-parent</artifactId>
|
||||
<groupId>fr.pandacube.lib</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>pandalib-ws-server</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>fr.pandacube.lib</groupId>
|
||||
<artifactId>pandalib-ws</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-jetty-api</artifactId>
|
||||
<version>10.0.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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);
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user