Archived
0

MCSM: принимаем пинг-пакеты

This commit is contained in:
2017-05-01 12:28:53 +03:00
parent 49ae0220fe
commit 589df91151
6 changed files with 111 additions and 13 deletions

View File

@@ -1,5 +1,5 @@
group = 'asys' group = 'asys'
version = '0.7.1-SNAPSHOT' version = '0.8-SNAPSHOT'
apply plugin: 'osgi' apply plugin: 'osgi'

View File

@@ -29,6 +29,8 @@ public class Activator implements BundleActivator, ServiceListener {
Config config = serviceConfigTracker.getService(); Config config = serviceConfigTracker.getService();
if (config == null) throw new RuntimeException("Service 'Config' is not avalable!"); if (config == null) throw new RuntimeException("Service 'Config' is not avalable!");
Manager manager = new Manager();
module = new MCSM_WebModule(); module = new MCSM_WebModule();
logger.debug("Get service: {}", Webinterface.class); logger.debug("Get service: {}", Webinterface.class);
@@ -42,7 +44,7 @@ public class Activator implements BundleActivator, ServiceListener {
String passcode = config.getString("asys.mcsmanager.passcode", "testpasscode"); String passcode = config.getString("asys.mcsmanager.passcode", "testpasscode");
logger.debug("Start server manager: {}:{}", host, port); logger.debug("Start server manager: {}:{}", host, port);
serverManager = new Server(); serverManager = new Server();
serverManager.start(host, port, passcode); serverManager.start(host, port, passcode, manager);
serviceConfigTracker.close(); serviceConfigTracker.close();
} }

View File

@@ -0,0 +1,56 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2017-05-01
*/
package asys.mcsmanager;
import asys.mcsmanager.packets.CS_Ping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
public class Manager {
private Logger logger = LoggerFactory.getLogger(Manager.class);
private Map<String, Deque<CS_Ping>> serversMap = new HashMap<>();
/**
* Добавляем в список ClientID
* @param clientId id сервера. Чувствителен к регистру
* @return <code>false</code>, если сервер с таким id уже имеется
*/
public boolean addClientId(String clientId) {
if (serversMap.containsKey(clientId)) {
return false;
}
logger.debug("addClientId: {}", clientId);
serversMap.put(clientId, new LinkedList<>());
return true;
}
/**
* Дополнить информация о сервере.
* Если сервер отсутствует в списке, информация будет потеряна.
* @param clientId id сервера. Чувствителен к регистру
* @param pingPacket
*/
public void putInfo(String clientId, CS_Ping pingPacket) {
if (!serversMap.containsKey(clientId)) return;
Deque<CS_Ping> list = serversMap.get(clientId);
if (list.size() == 720) {
list.removeFirst();
}
list.addLast(pingPacket);
logger.debug("putInfo: {} [{}]", clientId, pingPacket.getTime());
}
public Set<String> getServerList() {
return serversMap.keySet();
}
public Deque<CS_Ping> getInfo(String clientId) {
return serversMap.get(clientId);
}
}

View File

@@ -9,4 +9,5 @@ import asys.mcsmanager.packets.SC_HandshakeResult;
abstract class HandshakeResult { abstract class HandshakeResult {
static final SC_HandshakeResult OK = new SC_HandshakeResult(0, "OK"); static final SC_HandshakeResult OK = new SC_HandshakeResult(0, "OK");
static final SC_HandshakeResult INVALID_PASSCODE = new SC_HandshakeResult(1, "Invalid passcode"); static final SC_HandshakeResult INVALID_PASSCODE = new SC_HandshakeResult(1, "Invalid passcode");
static final SC_HandshakeResult CLIENTID_EXISTS = new SC_HandshakeResult(2, "ClientID is already use");
} }

View File

@@ -4,6 +4,7 @@
*/ */
package asys.mcsmanager.server; package asys.mcsmanager.server;
import asys.mcsmanager.Manager;
import asys.mcsmanager.packets.CS_Ping; import asys.mcsmanager.packets.CS_Ping;
import asys.mcsmanager.packets.Packet; import asys.mcsmanager.packets.Packet;
import asys.mcsmanager.packets.codec.PacketDecoder; import asys.mcsmanager.packets.codec.PacketDecoder;
@@ -24,9 +25,11 @@ public class Server {
); );
private EventLoopGroup bossGroup, workerGroup; private EventLoopGroup bossGroup, workerGroup;
static String passcode; static String passcode;
static Manager manager;
public void start(String host, int port, String passcode) { public void start(String host, int port, String passcode, Manager manager) {
Server.passcode = passcode; Server.passcode = passcode;
Server.manager = manager;
bossGroup = new NioEventLoopGroup(1); bossGroup = new NioEventLoopGroup(1);
workerGroup = new NioEventLoopGroup(); workerGroup = new NioEventLoopGroup();

View File

@@ -4,19 +4,20 @@
*/ */
package asys.mcsmanager.server; package asys.mcsmanager.server;
import asys.mcsmanager.packets.CS_Handshake; import asys.mcsmanager.packets.*;
import asys.mcsmanager.packets.IPacketHandler;
import asys.mcsmanager.packets.Packet;
import asys.mcsmanager.packets.SC_HandshakeResult;
import asys.mcsmanager.packets.codec.Params;
import com.google.common.collect.BiMap; import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.AttributeKey;
import java.util.Map; import java.util.Map;
import static asys.mcsmanager.packets.codec.Params.KNOWN_HANDLERS;
import static asys.mcsmanager.packets.codec.Params.KNOWN_PACKETS;
import static asys.mcsmanager.server.Server.manager;
class ServerPacketHandler extends ChannelInboundHandlerAdapter implements IPacketHandler { class ServerPacketHandler extends ChannelInboundHandlerAdapter implements IPacketHandler {
private static final BiMap<Integer, Class<? extends Packet>> handshakePackets = ImmutableBiMap.of( private static final BiMap<Integer, Class<? extends Packet>> handshakePackets = ImmutableBiMap.of(
1, CS_Handshake.class, 1, CS_Handshake.class,
@@ -24,24 +25,41 @@ class ServerPacketHandler extends ChannelInboundHandlerAdapter implements IPacke
); );
private static Map<Class<? extends Packet>, IPacketHandler> handshakeHandlers; private static Map<Class<? extends Packet>, IPacketHandler> handshakeHandlers;
private static final BiMap<Integer, Class<? extends Packet>> pingPackets = ImmutableBiMap.of(
3, CS_Ping.class
);
private static Map<Class<? extends Packet>, IPacketHandler> pingHandlers;
private static final AttributeKey<String> CLIENTID = AttributeKey.valueOf("ClientId");
ServerPacketHandler() { ServerPacketHandler() {
if (handshakeHandlers == null) { if (handshakeHandlers == null) {
handshakeHandlers = ImmutableMap.of( handshakeHandlers = ImmutableMap.of(
CS_Handshake.class, this CS_Handshake.class, this
); );
} }
if (pingHandlers == null) {
pingHandlers = ImmutableMap.of(
CS_Ping.class, this
);
}
} }
@Override @Override
public void channelActive(ChannelHandlerContext context) throws Exception { public void channelActive(ChannelHandlerContext context) throws Exception {
context.channel().attr(Params.KNOWN_PACKETS).set(handshakePackets); context.channel().attr(KNOWN_PACKETS).set(handshakePackets);
context.channel().attr(Params.KNOWN_HANDLERS).set(handshakeHandlers); context.channel().attr(KNOWN_HANDLERS).set(handshakeHandlers);
super.channelActive(context); super.channelActive(context);
} }
@Override @Override
public void handle(Packet packet, ChannelHandlerContext context) { public void handle(Packet packet, ChannelHandlerContext context) {
if (packet.getClass() == CS_Handshake.class) handleCSHandshake((CS_Handshake) packet, context); if (packet.getClass() == CS_Handshake.class) {
handleCSHandshake((CS_Handshake) packet, context);
} else if (packet.getClass() == CS_Ping.class) {
handleCSPing((CS_Ping) packet, context);
}
} }
private void handleCSHandshake(CS_Handshake packet, ChannelHandlerContext context) { private void handleCSHandshake(CS_Handshake packet, ChannelHandlerContext context) {
@@ -51,8 +69,26 @@ class ServerPacketHandler extends ChannelInboundHandlerAdapter implements IPacke
} catch (InterruptedException ignore) { } catch (InterruptedException ignore) {
// ignore // ignore
} }
} else { return;
context.channel().writeAndFlush(HandshakeResult.OK);
} }
if (!manager.addClientId(packet.getClientId())) {
try {
context.channel().writeAndFlush(HandshakeResult.CLIENTID_EXISTS).sync().channel().close();
} catch (InterruptedException ignore) {
// ignore
}
return;
}
context.channel().write(HandshakeResult.OK);
context.channel().attr(CLIENTID).set(packet.getClientId());
context.channel().attr(KNOWN_PACKETS).set(pingPackets);
context.channel().attr(KNOWN_HANDLERS).set(pingHandlers);
context.channel().flush();
}
private void handleCSPing(CS_Ping packet, ChannelHandlerContext context) {
manager.putInfo(context.channel().attr(CLIENTID).get(), packet);
} }
} }