WebsocketAPI,WebsocketConnection: Convert to Kotlin

This commit is contained in:
Sapphire
2026-03-13 19:27:42 -05:00
parent c57701d8ff
commit 4a449faa40
4 changed files with 94 additions and 155 deletions

View File

@@ -1,111 +0,0 @@
package dev.slimevr.websocketapi;
import dev.slimevr.VRServer;
import dev.slimevr.protocol.GenericConnection;
import dev.slimevr.protocol.ProtocolAPI;
import dev.slimevr.protocol.ProtocolAPIServer;
import io.eiren.util.logging.LogManager;
import org.java_websocket.WebSocket;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import org.jetbrains.annotations.NotNull;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Objects;
import java.util.stream.Stream;
public class WebsocketAPI extends WebSocketServer implements ProtocolAPIServer {
public final VRServer server;
public final ProtocolAPI protocolAPI;
public WebsocketAPI(VRServer server, ProtocolAPI protocolAPI) {
super(new InetSocketAddress(21110), Collections.singletonList(new Draft_6455()));
this.server = server;
this.protocolAPI = protocolAPI;
this.protocolAPI.registerAPIServer(this);
setReuseAddr(true);
}
@Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
LogManager
.info(
"[WebSocketAPI] New connection from: "
+ conn.getRemoteSocketAddress().getAddress().getHostAddress()
);
conn.setAttachment(new WebsocketConnection(conn));
}
/**
* Helper function to get the string of the `conn` while handling `null`
*/
protected static String connAddr(WebSocket conn) {
if (conn == null) {
return "null";
}
var remote = conn.getRemoteSocketAddress();
if (remote == null) {
return conn.toString();
}
var addr = remote.getAddress();
if (addr == null) {
return remote.toString();
}
return addr.getHostAddress();
}
@Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
LogManager
.info(
"[WebSocketAPI] Disconnected: "
+ connAddr(conn)
+ ", ("
+ code
+ ") "
+ reason
+ ". Remote: "
+ remote
);
}
@Override
public void onMessage(WebSocket conn, String message) {
}
@Override
public void onMessage(WebSocket conn, ByteBuffer message) {
var connection = conn.<WebsocketConnection>getAttachment();
if (connection != null)
this.protocolAPI.onMessage(connection, message);
}
@Override
public void onError(WebSocket conn, Exception ex) {
LogManager
.severe(
"[WebSocket] Exception on connection " + connAddr(conn),
ex
);
}
@Override
public void onStart() {
LogManager.info("[WebSocketAPI] Web Socket API started on port " + getPort());
setConnectionLostTimeout(0);
}
@Override
public @NotNull Stream<GenericConnection> getApiConnections() {
return this.getConnections().stream().map(conn -> {
var c = conn.<WebsocketConnection>getAttachment();
return (GenericConnection) c;
}).filter(Objects::nonNull);
}
}

View File

@@ -0,0 +1,71 @@
package dev.slimevr.websocketapi
import dev.slimevr.VRServer
import dev.slimevr.protocol.GenericConnection
import dev.slimevr.protocol.ProtocolAPI
import dev.slimevr.protocol.ProtocolAPIServer
import io.eiren.util.logging.LogManager
import org.java_websocket.WebSocket
import org.java_websocket.drafts.Draft_6455
import org.java_websocket.handshake.ClientHandshake
import org.java_websocket.server.WebSocketServer
import java.net.InetSocketAddress
import java.nio.ByteBuffer
import java.util.stream.Stream
open class WebsocketAPI(val server: VRServer, val protocolAPI: ProtocolAPI) :
WebSocketServer(InetSocketAddress(21110), mutableListOf(Draft_6455())),
ProtocolAPIServer {
init {
protocolAPI.registerAPIServer(this)
isReuseAddr = true
}
override fun onOpen(conn: WebSocket, handshake: ClientHandshake) {
LogManager.info("[WebSocketAPI] New connection from ${conn.remoteSocketAddress.address.hostAddress}")
conn.setAttachment(WebsocketConnection(conn))
}
override fun onClose(conn: WebSocket, code: Int, reason: String, remote: Boolean) {
LogManager.info("[WebSocketAPI] Disconnected: ${connAddr(conn)}, ($code) $reason. Remote: $remote")
}
override fun onMessage(conn: WebSocket, message: String) {
}
override fun onMessage(conn: WebSocket, message: ByteBuffer) {
val connection = conn.getAttachment<WebsocketConnection?>() ?: return
protocolAPI.onMessage(connection, message)
}
override fun onError(conn: WebSocket, ex: Exception) {
LogManager
.severe("[WebSocket] Exception on connection ${connAddr(conn)}", ex)
}
override fun onStart() {
LogManager.info("[WebSocketAPI] Started on port ${getPort()}")
connectionLostTimeout = 0
}
override val apiConnections: Stream<GenericConnection>
get() = connections
.stream()
.map { conn: WebSocket ->
conn.getAttachment<WebsocketConnection?>() as GenericConnection?
}
.filter { it != null }
.map { it!! }
companion object {
/**
* Helper function to get the string of the `conn` while handling `null`
*/
protected fun connAddr(conn: WebSocket?): String {
if (conn == null) return "null"
val remote = conn.remoteSocketAddress ?: return conn.toString()
return remote.address?.hostAddress ?: return remote.toString()
}
}
}

View File

@@ -1,44 +0,0 @@
package dev.slimevr.websocketapi;
import dev.slimevr.protocol.ConnectionContext;
import dev.slimevr.protocol.GenericConnection;
import org.java_websocket.WebSocket;
import org.java_websocket.exceptions.WebsocketNotConnectedException;
import java.nio.ByteBuffer;
import java.util.UUID;
public class WebsocketConnection implements GenericConnection {
public final ConnectionContext context;
public final WebSocket conn;
public UUID id;
public WebsocketConnection(WebSocket conn) {
this.context = new ConnectionContext();
this.conn = conn;
this.id = UUID.randomUUID();
}
@Override
public ConnectionContext getContext() {
return this.context;
}
@Override
public void send(ByteBuffer bytes) {
if (this.conn.isOpen()) {
try {
this.conn.send(bytes.slice());
} catch (WebsocketNotConnectedException ignored) {
// Race condition if it closes between our check and sending
}
}
}
@Override
public UUID getConnectionId() {
return id;
}
}

View File

@@ -0,0 +1,23 @@
package dev.slimevr.websocketapi
import dev.slimevr.protocol.ConnectionContext
import dev.slimevr.protocol.GenericConnection
import org.java_websocket.WebSocket
import org.java_websocket.exceptions.WebsocketNotConnectedException
import java.nio.ByteBuffer
import java.util.*
class WebsocketConnection(val conn: WebSocket) : GenericConnection {
override val context = ConnectionContext()
override val connectionId: UUID = UUID.randomUUID()
override fun send(bytes: ByteBuffer) {
if (this.conn.isOpen) {
try {
this.conn.send(bytes.slice())
} catch (ignored: WebsocketNotConnectedException) {
// Race condition if it closes between our check and sending
}
}
}
}