Merge remote-tracking branch 'origin/dev-webconsole' into local-merge
# Conflicts: # bridge-protocol/build.gradle # bridge/src/main/java/asys/bridge/bukkit/BridgePlugin.java # bridge/src/main/java/asys/bridge/client/ClientPacketHandler.java # mcserver-manager/build.gradle # mcserver-manager/src/main/java/asys/mcsmanager/server/ServerPacketHandler.java
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
package asys.mcsmanager;
|
||||
|
||||
import asys.api.Config;
|
||||
import asys.mcsmanager.server.Server;
|
||||
import asys.webinterface.api.Webinterface;
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
@@ -20,7 +19,8 @@ public class Activator implements BundleActivator, ServiceListener {
|
||||
private ServiceTracker<?, Webinterface> serviceTracker;
|
||||
private MCSM_WebModule module;
|
||||
private Webinterface webinterface;
|
||||
private Server serverManager;
|
||||
private asys.mcsmanager.server.Server serverManager;
|
||||
private asys.mcsmanager.websocket.Server webconsoleServer;
|
||||
|
||||
@Override
|
||||
public void start(BundleContext context) throws Exception {
|
||||
@@ -43,13 +43,21 @@ public class Activator implements BundleActivator, ServiceListener {
|
||||
int port = config.getInt("asys.mcsmanager.port", 8779);
|
||||
String passcode = config.getString("asys.mcsmanager.passcode", "testpasscode");
|
||||
logger.debug("Start server manager: {}:{}", host, port);
|
||||
serverManager = new Server();
|
||||
serverManager = new asys.mcsmanager.server.Server();
|
||||
serverManager.start(host, port, passcode, manager);
|
||||
|
||||
host = config.getString("asys.mcsmanager.webconsole.host", "127.0.0.1");
|
||||
port = config.getInt("asys.mcsmanager.webconsole.port", 8770);
|
||||
logger.debug("Start webconsole server: {}:{}", host, port);
|
||||
webconsoleServer = new asys.mcsmanager.websocket.Server();
|
||||
webconsoleServer.start(host, port, manager);
|
||||
|
||||
serviceConfigTracker.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
webconsoleServer.shutdown();
|
||||
serverManager.shutdown();
|
||||
|
||||
if (webinterface != null) {
|
||||
|
||||
@@ -26,6 +26,7 @@ public class MCSM_WebModule extends WebModule {
|
||||
private final String MODULE_NAME = "mcsmanager";
|
||||
private final String MODULE_URL = "/"+MODULE_NAME;
|
||||
private final Pattern URL_PATTERN_JS = Pattern.compile(MODULE_URL+"/(\\w+)\\.js");
|
||||
private final Pattern URL_PATTERN_CSS = Pattern.compile(MODULE_URL+"/(\\w+)\\.css");
|
||||
private Manager manager;
|
||||
|
||||
MCSM_WebModule(Manager manager) {
|
||||
@@ -66,6 +67,19 @@ public class MCSM_WebModule extends WebModule {
|
||||
this.sendContent(httpExchange, 0, stream);
|
||||
return true;
|
||||
}
|
||||
|
||||
//FIXME дублирование кода
|
||||
matcher = URL_PATTERN_CSS.matcher(urlPath);
|
||||
if (matcher.find()) {
|
||||
InputStream stream = getClass().getResourceAsStream("/" + matcher.group(1) + ".css");
|
||||
if (stream == null) {
|
||||
this.sendHttpCode(httpExchange, 404, "not found");
|
||||
return true;
|
||||
}
|
||||
httpExchange.getResponseHeaders().add("Content-Type", "text/css;charset=utf-8");
|
||||
this.sendContent(httpExchange, 0, stream);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
*/
|
||||
package asys.mcsmanager;
|
||||
|
||||
import asys.mcsmanager.packets.CS_ConsoleMessage;
|
||||
import asys.mcsmanager.packets.CS_Ping;
|
||||
import asys.mcsmanager.packets.SC_Command;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -13,19 +17,43 @@ import java.util.*;
|
||||
public class Manager {
|
||||
private Logger logger = LoggerFactory.getLogger(Manager.class);
|
||||
private Map<String, ServerInfo> serversMap = new HashMap<>();
|
||||
private Map<String, Channel> serverChannels = new HashMap<>();
|
||||
private List<Channel> webconsoleListener = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Добавляем в список ClientID
|
||||
* @param clientId id сервера. Чувствителен к регистру
|
||||
* @return <code>false</code>, если сервер с таким id уже имеется
|
||||
*/
|
||||
public boolean addClientId(String clientId) {
|
||||
public boolean addClientId(String clientId, Channel channel) {
|
||||
if (serversMap.containsKey(clientId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.debug("addClientId: {}", clientId);
|
||||
serversMap.put(clientId, new ServerInfo(clientId));
|
||||
serverChannels.put(clientId, channel);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void removeClientId(String clientId) {
|
||||
if (clientId != null) {
|
||||
serverChannels.remove(clientId);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean sendCommand(String clientId, String command) {
|
||||
/*
|
||||
if (serverChannels.containsKey(clientId)) {
|
||||
serverChannels.get(clientId).writeAndFlush(new SC_Command(command));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
//FIXME временный костыль
|
||||
Channel channel = serverChannels.entrySet().iterator().next().getValue();
|
||||
channel.writeAndFlush(new SC_Command(command));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -47,4 +75,22 @@ public class Manager {
|
||||
public ServerInfo getInfo(String clientId) {
|
||||
return serversMap.get(clientId);
|
||||
}
|
||||
|
||||
public void addWebConsoleListener(Channel channel) {
|
||||
this.webconsoleListener.add(channel);
|
||||
}
|
||||
|
||||
public void removeWebConsoleListener(Channel channel) {
|
||||
this.webconsoleListener.remove(channel);
|
||||
}
|
||||
|
||||
public void sendBroadcastToWebConsoleListeners(CS_ConsoleMessage message) {
|
||||
for (Channel channel : this.webconsoleListener) {
|
||||
channel.writeAndFlush(new TextWebSocketFrame(String.format(
|
||||
"[L:%d] %s",
|
||||
message.getLevel(),
|
||||
message.getMessage()
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ class ServerPacketHandler extends ChannelInboundHandlerAdapter implements IPacke
|
||||
|
||||
private static final BiMap<Integer, Class<? extends Packet>> pingPackets = ImmutableBiMap.of(
|
||||
3, CS_Ping.class,
|
||||
4, CS_ConsoleMessage.class
|
||||
4, CS_ConsoleMessage.class,
|
||||
5, SC_Command.class
|
||||
);
|
||||
private static Map<Class<? extends Packet>, IPacketHandler> pingHandlers;
|
||||
|
||||
@@ -56,6 +57,12 @@ class ServerPacketHandler extends ChannelInboundHandlerAdapter implements IPacke
|
||||
super.channelActive(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext context) throws Exception {
|
||||
manager.removeClientId(context.channel().attr(CLIENTID).get());
|
||||
super.channelInactive(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Packet packet, ChannelHandlerContext context) {
|
||||
if (packet.getClass() == CS_Handshake.class) {
|
||||
@@ -77,7 +84,7 @@ class ServerPacketHandler extends ChannelInboundHandlerAdapter implements IPacke
|
||||
return;
|
||||
}
|
||||
|
||||
if (!manager.addClientId(packet.getClientId())) {
|
||||
if (!manager.addClientId(packet.getClientId(), context.channel())) {
|
||||
try {
|
||||
context.channel().writeAndFlush(HandshakeResult.CLIENTID_EXISTS).sync().channel().close();
|
||||
} catch (InterruptedException ignore) {
|
||||
@@ -98,6 +105,6 @@ class ServerPacketHandler extends ChannelInboundHandlerAdapter implements IPacke
|
||||
}
|
||||
|
||||
private void handleCSConsoleMessage(CS_ConsoleMessage packet) {
|
||||
LoggerFactory.getLogger(getClass()).debug("[L:{}] {}", packet.getLevel(), packet.getMessage());
|
||||
manager.sendBroadcastToWebConsoleListeners(packet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2017-05-09
|
||||
*/
|
||||
package asys.mcsmanager.websocket;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static asys.mcsmanager.websocket.Server.manager;
|
||||
|
||||
public class FrameHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
|
||||
private final Logger logger = LoggerFactory.getLogger(FrameHandler.class);
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
manager.addWebConsoleListener(ctx.channel());
|
||||
super.channelActive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
manager.removeWebConsoleListener(ctx.channel());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {
|
||||
if (frame instanceof TextWebSocketFrame) {
|
||||
String requestText = ((TextWebSocketFrame)frame).text();
|
||||
if (requestText.startsWith(":")) {
|
||||
//FIXME убрать костыли
|
||||
manager.sendCommand(null, requestText.substring(1));
|
||||
}
|
||||
} else {
|
||||
logger.warn("unsupport frame type: {}", frame.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2017-05-08
|
||||
*/
|
||||
package asys.mcsmanager.websocket;
|
||||
|
||||
import asys.mcsmanager.Manager;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.codec.http.HttpServerCodec;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
|
||||
|
||||
public class Server {
|
||||
static Manager manager;
|
||||
private EventLoopGroup bossGroup, workerGroup;
|
||||
|
||||
public void start(String host, int port, Manager manager) {
|
||||
Server.manager = manager;
|
||||
bossGroup = new NioEventLoopGroup(1);
|
||||
workerGroup = new NioEventLoopGroup();
|
||||
|
||||
ServerBootstrap serverBootstrap = createServerBootstrap();
|
||||
serverBootstrap.bind(host, port);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
workerGroup.shutdownGracefully();
|
||||
bossGroup.shutdownGracefully();
|
||||
}
|
||||
|
||||
private ServerBootstrap createServerBootstrap() {
|
||||
ServerBootstrap bootstrap = new ServerBootstrap();
|
||||
|
||||
bootstrap.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(createChannelInitializer());
|
||||
|
||||
return bootstrap;
|
||||
}
|
||||
|
||||
private ChannelInitializer createChannelInitializer() {
|
||||
return new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
||||
socketChannel.pipeline().addLast(
|
||||
new HttpServerCodec(),
|
||||
new HttpObjectAggregator(65536),
|
||||
new WebSocketServerProtocolHandler("/", null, true),
|
||||
new FrameHandler()
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user