Add WebSocket support with routing, origin validation, session management, and broadcasting
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package dev.coph.nextusweb.server.websocket;
|
||||
|
||||
import dev.coph.nextusweb.server.json.JsonMapper;
|
||||
import io.netty.channel.group.ChannelGroup;
|
||||
import io.netty.channel.group.DefaultChannelGroup;
|
||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import io.netty.util.concurrent.GlobalEventExecutor;
|
||||
import tools.jackson.core.JacksonException;
|
||||
|
||||
public final class WebSocketGroup {
|
||||
|
||||
private final ChannelGroup channels;
|
||||
private final String name;
|
||||
|
||||
public WebSocketGroup() {
|
||||
this("anonymous");
|
||||
}
|
||||
|
||||
public WebSocketGroup(String name) {
|
||||
this.name = name;
|
||||
this.channels = new DefaultChannelGroup(name, GlobalEventExecutor.INSTANCE);
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public WebSocketGroup add(WebSocketSession session) {
|
||||
channels.add(session.channel());
|
||||
return this;
|
||||
}
|
||||
|
||||
public WebSocketGroup remove(WebSocketSession session) {
|
||||
channels.remove(session.channel());
|
||||
return this;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return channels.size();
|
||||
}
|
||||
|
||||
public WebSocketGroup broadcast(String text) {
|
||||
channels.writeAndFlush(new TextWebSocketFrame(text));
|
||||
return this;
|
||||
}
|
||||
|
||||
public WebSocketGroup broadcastJson(Object value) {
|
||||
try {
|
||||
byte[] bytes = JsonMapper.MAPPER.writeValueAsBytes(value);
|
||||
String text = new String(bytes, java.nio.charset.StandardCharsets.UTF_8);
|
||||
channels.writeAndFlush(new TextWebSocketFrame(text));
|
||||
} catch (JacksonException e) {
|
||||
throw new RuntimeException("JSON serialization failed", e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public WebSocketGroup broadcastBinary(byte[] data) {
|
||||
for (var ch : channels) {
|
||||
if (ch.isActive()) {
|
||||
var buf = ch.alloc().buffer(data.length).writeBytes(data);
|
||||
ch.writeAndFlush(new BinaryWebSocketFrame(buf));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public WebSocketGroup broadcastExcept(WebSocketSession exclude, String text) {
|
||||
var excludeCh = exclude == null ? null : exclude.channel();
|
||||
for (var ch : channels) {
|
||||
if (ch.isActive() && ch != excludeCh) {
|
||||
ch.writeAndFlush(new TextWebSocketFrame(text));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public WebSocketGroup closeAll() {
|
||||
channels.close();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user