mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 10:54:51 +00:00
Added exceptions. Added reconnect attempts and changeable address
This commit is contained in:
2
.idea/inspectionProfiles/Project_Default.xml
generated
2
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -2,7 +2,7 @@
|
|||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
<inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
|
<inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
<option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.lang.foreign.Arena,ofAuto,java.lang.foreign.Arena,global,org.toop.framework.audio.AudioPlayer,play,java.util.Map,remove" />
|
<option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.lang.foreign.Arena,ofAuto,java.lang.foreign.Arena,global,org.toop.framework.audio.AudioPlayer,play,java.util.Map,remove,java.util.concurrent.Executors,newSingleThreadScheduledExecutor" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="WriteOnlyObject" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="WriteOnlyObject" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
</profile>
|
</profile>
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ package org.toop.framework.networking;
|
|||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.toop.framework.SnowflakeGenerator;
|
||||||
import org.toop.framework.eventbus.EventFlow;
|
import org.toop.framework.eventbus.EventFlow;
|
||||||
import org.toop.framework.networking.interfaces.NetworkingClient;
|
|
||||||
import org.toop.framework.networking.events.NetworkEvents;
|
import org.toop.framework.networking.events.NetworkEvents;
|
||||||
|
import org.toop.framework.networking.exceptions.ClientNotFoundException;
|
||||||
import org.toop.framework.networking.interfaces.NetworkingClientManager;
|
import org.toop.framework.networking.interfaces.NetworkingClientManager;
|
||||||
|
|
||||||
public class NetworkingClientEventListener {
|
public class NetworkingClientEventListener {
|
||||||
@@ -31,93 +32,111 @@ public class NetworkingClientEventListener {
|
|||||||
.listen(this::handleSendHelp)
|
.listen(this::handleSendHelp)
|
||||||
.listen(this::handleSendHelpForCommand)
|
.listen(this::handleSendHelpForCommand)
|
||||||
.listen(this::handleCloseClient)
|
.listen(this::handleCloseClient)
|
||||||
.listen(this::handleChangeClientHost)
|
.listen(this::handleReconnect)
|
||||||
|
.listen(this::handleChangeAddress)
|
||||||
.listen(this::handleGetAllConnections)
|
.listen(this::handleGetAllConnections)
|
||||||
.listen(this::handleShutdownAll);
|
.listen(this::handleShutdownAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleStartClient(NetworkEvents.StartClient event) {
|
void handleStartClient(NetworkEvents.StartClient event) {
|
||||||
long clientId = clientManager.startClient(SnowflakeGenerator.nextId(), event.networkingClientClass(), event.host(), event.port()).orElse(-1);
|
clientManager.startClient(
|
||||||
logger.info("Client {} started", clientId);
|
event.identifier(),
|
||||||
|
event.networkingClientClass(),
|
||||||
|
event.host(),
|
||||||
|
event.port(),
|
||||||
|
event.networkingReconnect()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendCommand(long clientId, String command) {
|
||||||
try {
|
try {
|
||||||
new EventFlow()
|
clientManager.sendCommand(clientId, command);
|
||||||
.addPostEvent(new NetworkEvents.StartClientResponse(clientId, event.getIdentifier()))
|
} catch (ClientNotFoundException e) {
|
||||||
.asyncPostEvent();
|
logger.error(e);
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCommand(NetworkEvents.SendCommand event) {
|
private void handleCommand(NetworkEvents.SendCommand event) {
|
||||||
String args = String.join(" ", event.args());
|
String args = String.join(" ", event.args());
|
||||||
logger.error(args);
|
sendCommand(event.clientId(), args);
|
||||||
clientManager.sendCommand(event.clientId(), args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSendLogin(NetworkEvents.SendLogin event) {
|
private void handleSendLogin(NetworkEvents.SendLogin event) {
|
||||||
logger.error("{}", event.username());
|
sendCommand(event.clientId(), String.format("LOGIN %s", event.username()));
|
||||||
clientManager.sendCommand(event.clientId(), String.format("LOGIN %s", event.username()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSendLogout(NetworkEvents.SendLogout event) {
|
private void handleSendLogout(NetworkEvents.SendLogout event) {
|
||||||
clientManager.sendCommand(event.clientId(), "LOGOUT");
|
sendCommand(event.clientId(), "LOGOUT");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSendGetPlayerlist(NetworkEvents.SendGetPlayerlist event) {
|
private void handleSendGetPlayerlist(NetworkEvents.SendGetPlayerlist event) {
|
||||||
clientManager.sendCommand(event.clientId(), "GET PLAYERLIST");
|
sendCommand(event.clientId(), "GET PLAYERLIST");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSendGetGamelist(NetworkEvents.SendGetGamelist event) {
|
private void handleSendGetGamelist(NetworkEvents.SendGetGamelist event) {
|
||||||
clientManager.sendCommand(event.clientId(), "GET GAMELIST");
|
sendCommand(event.clientId(), "GET GAMELIST");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSendSubscribe(NetworkEvents.SendSubscribe event) {
|
private void handleSendSubscribe(NetworkEvents.SendSubscribe event) {
|
||||||
clientManager.sendCommand(event.clientId(), String.format("SUBSCRIBE %s", event.gameType()));
|
sendCommand(event.clientId(), String.format("SUBSCRIBE %s", event.gameType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSendMove(NetworkEvents.SendMove event) {
|
private void handleSendMove(NetworkEvents.SendMove event) {
|
||||||
clientManager.sendCommand(event.clientId(), String.format("MOVE %d", event.moveNumber()));
|
sendCommand(event.clientId(), String.format("MOVE %d", event.moveNumber()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSendChallenge(NetworkEvents.SendChallenge event) {
|
private void handleSendChallenge(NetworkEvents.SendChallenge event) {
|
||||||
clientManager.sendCommand(
|
sendCommand(event.clientId(), String.format("CHALLENGE %s %s", event.usernameToChallenge(), event.gameType()));
|
||||||
event.clientId(),
|
|
||||||
String.format("CHALLENGE %s %s", event.usernameToChallenge(), event.gameType()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSendAcceptChallenge(NetworkEvents.SendAcceptChallenge event) {
|
private void handleSendAcceptChallenge(NetworkEvents.SendAcceptChallenge event) {
|
||||||
clientManager.sendCommand(event.clientId(), String.format("CHALLENGE ACCEPT %d", event.challengeId()));
|
sendCommand(event.clientId(), String.format("CHALLENGE ACCEPT %d", event.challengeId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSendForfeit(NetworkEvents.SendForfeit event) {
|
private void handleSendForfeit(NetworkEvents.SendForfeit event) {
|
||||||
clientManager.sendCommand(event.clientId(), "FORFEIT");
|
sendCommand(event.clientId(), "FORFEIT");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSendMessage(NetworkEvents.SendMessage event) {
|
private void handleSendMessage(NetworkEvents.SendMessage event) {
|
||||||
clientManager.sendCommand(event.clientId(), String.format("MESSAGE %s", event.message()));
|
sendCommand(event.clientId(), String.format("MESSAGE %s", event.message()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSendHelp(NetworkEvents.SendHelp event) {
|
private void handleSendHelp(NetworkEvents.SendHelp event) {
|
||||||
clientManager.sendCommand(event.clientId(), "HELP");
|
sendCommand(event.clientId(), "HELP");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSendHelpForCommand(NetworkEvents.SendHelpForCommand event) {
|
private void handleSendHelpForCommand(NetworkEvents.SendHelpForCommand event) {
|
||||||
clientManager.sendCommand(event.clientId(), String.format("HELP %s", event.command()));
|
sendCommand(event.clientId(), String.format("HELP %s", event.command()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleChangeClientHost(NetworkEvents.ChangeClientHost event) {
|
private void handleReconnect(NetworkEvents.Reconnect event) {
|
||||||
// NetworkingClient client = this.networkClients.get(event.clientId());
|
try {
|
||||||
// client.closeConnection();
|
clientManager.reconnect(event.clientId(), event.networkingReconnect());
|
||||||
// startClientRequest(event.ip(), event.port(), event.clientId());
|
} catch (ClientNotFoundException e) {
|
||||||
|
logger.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleChangeAddress(NetworkEvents.ChangeAddress event) {
|
||||||
|
try {
|
||||||
|
clientManager.changeAddress(event.clientId(), event.ip(), event.port(), event.networkingReconnect());
|
||||||
|
} catch (ClientNotFoundException e) {
|
||||||
|
logger.error(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCloseClient(NetworkEvents.CloseClient event) {
|
void handleCloseClient(NetworkEvents.CloseClient event) {
|
||||||
this.clientManager.closeClient(event.clientId());
|
try {
|
||||||
|
this.clientManager.closeClient(event.clientId());
|
||||||
|
} catch (ClientNotFoundException e) {
|
||||||
|
logger.error(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleGetAllConnections(NetworkEvents.RequestsAllClients request) {
|
void handleGetAllConnections(NetworkEvents.RequestsAllClients request) {
|
||||||
// List<NetworkingClient> a = new ArrayList<>(this.networkClients.values());
|
// List<NetworkingClient> a = new ArrayList<>(this.networkClients.values());
|
||||||
// request.future().complete(a);
|
// request.future().complete(a);
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleShutdownAll(NetworkEvents.ForceCloseAllClients request) {
|
public void handleShutdownAll(NetworkEvents.ForceCloseAllClients request) {
|
||||||
|
|||||||
@@ -1,10 +1,20 @@
|
|||||||
package org.toop.framework.networking;
|
package org.toop.framework.networking;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.toop.framework.eventbus.EventFlow;
|
||||||
|
import org.toop.framework.networking.events.NetworkEvents;
|
||||||
|
import org.toop.framework.networking.exceptions.ClientNotFoundException;
|
||||||
|
import org.toop.framework.networking.exceptions.CouldNotConnectException;
|
||||||
import org.toop.framework.networking.interfaces.NetworkingClient;
|
import org.toop.framework.networking.interfaces.NetworkingClient;
|
||||||
|
import org.toop.framework.networking.types.NetworkingReconnect;
|
||||||
|
|
||||||
public class NetworkingClientManager implements org.toop.framework.networking.interfaces.NetworkingClientManager {
|
public class NetworkingClientManager implements org.toop.framework.networking.interfaces.NetworkingClientManager {
|
||||||
private static final Logger logger = LogManager.getLogger(NetworkingClientManager.class);
|
private static final Logger logger = LogManager.getLogger(NetworkingClientManager.class);
|
||||||
@@ -13,46 +23,169 @@ public class NetworkingClientManager implements org.toop.framework.networking.in
|
|||||||
public NetworkingClientManager() {}
|
public NetworkingClientManager() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OptionalLong startClient(long id, NetworkingClient networkingClient, String host, int port) {
|
public void startClient(
|
||||||
try {
|
long id,
|
||||||
networkingClient.connect(id, host, port);
|
NetworkingClient networkingClient,
|
||||||
this.networkClients.put(id, networkingClient);
|
String host, int port,
|
||||||
logger.info("New client started successfully for {}:{}", host, port);
|
NetworkingReconnect networkingReconnect) {
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e); // TODO Better error handling
|
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
|
||||||
return OptionalLong.empty();
|
|
||||||
}
|
Runnable connectTask = new Runnable() {
|
||||||
return OptionalLong.of(id);
|
int attempts = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
networkingClient.connect(id, host, port);
|
||||||
|
networkClients.put(id, networkingClient);
|
||||||
|
logger.info("New client started successfully for {}:{}", host, port);
|
||||||
|
new EventFlow().addPostEvent(new NetworkEvents.StartClientResponse(id, id)).postEvent();
|
||||||
|
scheduler.shutdown();
|
||||||
|
} catch (CouldNotConnectException e) {
|
||||||
|
attempts++;
|
||||||
|
if (attempts < networkingReconnect.reconnectAttempts()) {
|
||||||
|
logger.warn("Could not connect to {}:{}. Retrying in {} {}",
|
||||||
|
host, port, networkingReconnect.timeout(), networkingReconnect.timeUnit());
|
||||||
|
scheduler.schedule(this, networkingReconnect.timeout(), networkingReconnect.timeUnit());
|
||||||
|
} else {
|
||||||
|
logger.error("Failed to start client for {}:{} after {} attempts", host, port, attempts);
|
||||||
|
new EventFlow().addPostEvent(new NetworkEvents.StartClientResponse(-1, id)).postEvent();
|
||||||
|
scheduler.shutdown();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Unexpected exception during startClient", e);
|
||||||
|
scheduler.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
scheduler.schedule(connectTask, 0, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sendCommand(long id, String command) {
|
public void sendCommand(long id, String command) throws ClientNotFoundException {
|
||||||
logger.info("Sending command to client for {}:{}", id, command);
|
logger.info("Sending command to client for {}:{}", id, command);
|
||||||
if (command.isEmpty()) { return false; }
|
if (command.isEmpty()) {
|
||||||
|
IllegalArgumentException e = new IllegalArgumentException("command is empty");
|
||||||
|
logger.error("Invalid command received", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NetworkingClient client = this.networkClients.get(id);
|
NetworkingClient client = this.networkClients.get(id);
|
||||||
if (client == null) { return false; } // TODO: Create client not found exceptions.
|
if (client == null) {
|
||||||
|
throw new ClientNotFoundException(id);
|
||||||
|
}
|
||||||
|
|
||||||
String toSend = command.trim();
|
String toSend = command.trim();
|
||||||
|
|
||||||
if (toSend.endsWith("\n")) { client.writeAndFlush(toSend); }
|
if (toSend.endsWith("\n")) { client.writeAndFlush(toSend); }
|
||||||
else { client.writeAndFlush(toSend + "\n"); }
|
else { client.writeAndFlush(toSend + "\n"); }
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean reconnect(long id) {
|
public void reconnect(long id, NetworkingReconnect networkingReconnect) throws ClientNotFoundException {
|
||||||
return false; // TODO
|
NetworkingClient client = this.networkClients.get(id);
|
||||||
|
if (client == null) {
|
||||||
|
throw new ClientNotFoundException(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
InetSocketAddress address = client.getAddress();
|
||||||
|
|
||||||
|
if (client.isActive()) {
|
||||||
|
client.closeConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
|
||||||
|
Runnable connectTask = new Runnable() {
|
||||||
|
int attempts = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
client.connect(id, address.getHostName(), address.getPort());
|
||||||
|
networkClients.put(id, client);
|
||||||
|
logger.info("Client {} reconnected to {}:{}", id, address.getHostName(), address.getPort());
|
||||||
|
new EventFlow().addPostEvent(new NetworkEvents.ReconnectResponse(true, id)).postEvent().postEvent();
|
||||||
|
scheduler.shutdown();
|
||||||
|
} catch (CouldNotConnectException e) {
|
||||||
|
attempts++;
|
||||||
|
if (attempts < networkingReconnect.reconnectAttempts()) {
|
||||||
|
logger.warn("Could not reconnect client {} to {}:{}. Retrying in {} {}",
|
||||||
|
id, address.getHostName(), address.getPort(), networkingReconnect.timeout(), networkingReconnect.timeUnit());
|
||||||
|
scheduler.schedule(this, networkingReconnect.timeout(), networkingReconnect.timeUnit());
|
||||||
|
} else {
|
||||||
|
logger.error("Failed to reconnect client {} to {}:{} after {} attempts", id, address.getHostName(), address.getPort(), attempts);
|
||||||
|
new EventFlow().addPostEvent(new NetworkEvents.ReconnectResponse(false, id)).postEvent().postEvent();
|
||||||
|
scheduler.shutdown();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Unexpected exception during reconnect for client {}", id, e);
|
||||||
|
new EventFlow().addPostEvent(new NetworkEvents.ReconnectResponse(false, id)).postEvent().postEvent();
|
||||||
|
scheduler.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
scheduler.schedule(connectTask, 0, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean changeAddress(long id, String host, int port) {
|
public void changeAddress(long id, String host, int port, NetworkingReconnect networkingReconnect) throws ClientNotFoundException {
|
||||||
return false; // TODO
|
NetworkingClient client = this.networkClients.get(id);
|
||||||
|
if (client == null) {
|
||||||
|
throw new ClientNotFoundException(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client.isActive()) {
|
||||||
|
client.closeConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
|
||||||
|
Runnable connectTask = new Runnable() {
|
||||||
|
int attempts = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
client.connect(id, host, port);
|
||||||
|
networkClients.put(id, client);
|
||||||
|
logger.info("Client {} changed address to {}:{}", id, host, port);
|
||||||
|
new EventFlow().addPostEvent(new NetworkEvents.ChangeAddressResponse(true, id)).postEvent().postEvent();
|
||||||
|
scheduler.shutdown();
|
||||||
|
} catch (CouldNotConnectException e) {
|
||||||
|
attempts++;
|
||||||
|
if (attempts < networkingReconnect.reconnectAttempts()) {
|
||||||
|
logger.warn("Could not connect client {} to {}:{}. Retrying in {} {}",
|
||||||
|
id, host, port, networkingReconnect.timeout(), networkingReconnect.timeUnit());
|
||||||
|
scheduler.schedule(this, networkingReconnect.timeout(), networkingReconnect.timeUnit());
|
||||||
|
} else {
|
||||||
|
logger.error("Failed to connect client {} to {}:{} after {} attempts", id, host, port, attempts);
|
||||||
|
new EventFlow().addPostEvent(new NetworkEvents.ChangeAddressResponse(false, id)).postEvent().postEvent();
|
||||||
|
scheduler.shutdown();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Unexpected exception during changeAddress for client {}", id, e);
|
||||||
|
new EventFlow().addPostEvent(new NetworkEvents.ChangeAddressResponse(false, id)).postEvent().postEvent();
|
||||||
|
scheduler.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
scheduler.schedule(connectTask, 0, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean closeClient(long id) {
|
public void closeClient(long id) throws ClientNotFoundException {
|
||||||
return false; // TODO
|
NetworkingClient client = this.networkClients.get(id);
|
||||||
|
if (client == null) {
|
||||||
|
throw new ClientNotFoundException(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
client.closeConnection();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,12 @@ import io.netty.handler.codec.string.StringEncoder;
|
|||||||
import io.netty.util.CharsetUtil;
|
import io.netty.util.CharsetUtil;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.toop.framework.networking.exceptions.CouldNotConnectException;
|
||||||
import org.toop.framework.networking.handlers.NetworkingGameClientHandler;
|
import org.toop.framework.networking.handlers.NetworkingGameClientHandler;
|
||||||
import org.toop.framework.networking.interfaces.NetworkingClient;
|
import org.toop.framework.networking.interfaces.NetworkingClient;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
public class TournamentNetworkingClient implements NetworkingClient {
|
public class TournamentNetworkingClient implements NetworkingClient {
|
||||||
private static final Logger logger = LogManager.getLogger(TournamentNetworkingClient.class);
|
private static final Logger logger = LogManager.getLogger(TournamentNetworkingClient.class);
|
||||||
private Channel channel;
|
private Channel channel;
|
||||||
@@ -21,7 +24,12 @@ public class TournamentNetworkingClient implements NetworkingClient {
|
|||||||
public TournamentNetworkingClient() {}
|
public TournamentNetworkingClient() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean connect(long clientId, String host, int port) {
|
public InetSocketAddress getAddress() {
|
||||||
|
return (InetSocketAddress) channel.remoteAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect(long clientId, String host, int port) throws CouldNotConnectException {
|
||||||
try {
|
try {
|
||||||
Bootstrap bootstrap = new Bootstrap();
|
Bootstrap bootstrap = new Bootstrap();
|
||||||
EventLoopGroup workerGroup = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory());
|
EventLoopGroup workerGroup = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory());
|
||||||
@@ -44,11 +52,9 @@ public class TournamentNetworkingClient implements NetworkingClient {
|
|||||||
});
|
});
|
||||||
ChannelFuture channelFuture = bootstrap.connect(host, port).sync();
|
ChannelFuture channelFuture = bootstrap.connect(host, port).sync();
|
||||||
this.channel = channelFuture.channel();
|
this.channel = channelFuture.channel();
|
||||||
} catch (Exception e) {
|
} catch (Exception _) {
|
||||||
logger.error("Failed to create networking client instance", e);
|
throw new CouldNotConnectException(clientId);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.toop.framework.eventbus.events.UniqueEvent;
|
|||||||
import org.toop.framework.eventbus.events.EventsBase;
|
import org.toop.framework.eventbus.events.EventsBase;
|
||||||
import org.toop.annotations.AutoResponseResult;
|
import org.toop.annotations.AutoResponseResult;
|
||||||
import org.toop.framework.networking.interfaces.NetworkingClient;
|
import org.toop.framework.networking.interfaces.NetworkingClient;
|
||||||
|
import org.toop.framework.networking.types.NetworkingReconnect;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A collection of networking-related event records for use with the {@link
|
* A collection of networking-related event records for use with the {@link
|
||||||
@@ -101,31 +102,6 @@ public class NetworkEvents extends EventsBase {
|
|||||||
/** Request to close a specific client connection. */
|
/** Request to close a specific client connection. */
|
||||||
public record CloseClient(long clientId) implements GenericEvent {}
|
public record CloseClient(long clientId) implements GenericEvent {}
|
||||||
|
|
||||||
/**
|
|
||||||
* Event to start a new client connection.
|
|
||||||
*
|
|
||||||
* <p>Carries IP, port, and a unique event ID for correlation with responses.
|
|
||||||
*
|
|
||||||
* @param networkingClientClass The type of networking client to create.
|
|
||||||
* @param host Server IP address.
|
|
||||||
* @param port Server port.
|
|
||||||
* @param eventSnowflake Unique event identifier for correlation.
|
|
||||||
*/
|
|
||||||
public record StartClient(
|
|
||||||
NetworkingClient networkingClientClass,
|
|
||||||
String host,
|
|
||||||
int port,
|
|
||||||
long identifier) implements UniqueEvent {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Response confirming a client was started.
|
|
||||||
*
|
|
||||||
* @param clientId The client ID assigned to the new connection.
|
|
||||||
* @param identifier Event ID used for correlation.
|
|
||||||
*/
|
|
||||||
@AutoResponseResult
|
|
||||||
public record StartClientResponse(long clientId, long identifier) implements ResponseToUniqueEvent {}
|
|
||||||
|
|
||||||
/** Generic server response. */
|
/** Generic server response. */
|
||||||
public record ServerResponse(long clientId) implements GenericEvent {}
|
public record ServerResponse(long clientId) implements GenericEvent {}
|
||||||
|
|
||||||
@@ -137,8 +113,49 @@ public class NetworkEvents extends EventsBase {
|
|||||||
*/
|
*/
|
||||||
public record SendCommand(long clientId, String... args) implements GenericEvent {}
|
public record SendCommand(long clientId, String... args) implements GenericEvent {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event to start a new client connection.
|
||||||
|
*
|
||||||
|
* <p>Carries IP, port, and a unique event ID for correlation with responses.
|
||||||
|
*
|
||||||
|
* @param networkingClientClass The type of networking client to create.
|
||||||
|
* @param host Server IP address.
|
||||||
|
* @param port Server port.
|
||||||
|
* @param identifier Unique event identifier for correlation.
|
||||||
|
*/
|
||||||
|
public record StartClient(
|
||||||
|
NetworkingClient networkingClientClass,
|
||||||
|
String host,
|
||||||
|
int port,
|
||||||
|
NetworkingReconnect networkingReconnect,
|
||||||
|
long identifier) implements UniqueEvent {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response confirming a client was started.
|
||||||
|
*
|
||||||
|
* @param clientId The client ID assigned to the new connection.
|
||||||
|
* @param identifier Event ID used for correlation.
|
||||||
|
*/
|
||||||
|
@AutoResponseResult
|
||||||
|
public record StartClientResponse(long clientId, long identifier) implements ResponseToUniqueEvent {}
|
||||||
|
|
||||||
/** WIP (Not working) Request to reconnect a client to a previous address. */
|
/** WIP (Not working) Request to reconnect a client to a previous address. */
|
||||||
public record Reconnect(long clientId) implements GenericEvent {}
|
public record Reconnect(long clientId, NetworkingReconnect networkingReconnect, long identifier)
|
||||||
|
implements UniqueEvent {}
|
||||||
|
|
||||||
|
public record ReconnectResponse(boolean successful, long identifier) implements ResponseToUniqueEvent {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request to change a client connection to a new server.
|
||||||
|
*
|
||||||
|
* @param clientId The client connection ID.
|
||||||
|
* @param ip The new server IP.
|
||||||
|
* @param port The new server port.
|
||||||
|
*/
|
||||||
|
public record ChangeAddress(long clientId, String ip, int port, NetworkingReconnect networkingReconnect, long identifier)
|
||||||
|
implements UniqueEvent {}
|
||||||
|
|
||||||
|
public record ChangeAddressResponse(boolean successful, long identifier) implements ResponseToUniqueEvent {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response triggered when a message is received from a server.
|
* Response triggered when a message is received from a server.
|
||||||
@@ -148,18 +165,6 @@ public class NetworkEvents extends EventsBase {
|
|||||||
*/
|
*/
|
||||||
public record ReceivedMessage(long clientId, String message) implements GenericEvent {}
|
public record ReceivedMessage(long clientId, String message) implements GenericEvent {}
|
||||||
|
|
||||||
/**
|
|
||||||
* Request to change a client connection to a new server.
|
|
||||||
*
|
|
||||||
* @param clientId The client connection ID.
|
|
||||||
* @param ip The new server IP.
|
|
||||||
* @param port The new server port.
|
|
||||||
*/
|
|
||||||
public record ChangeClientHost(long clientId, String ip, int port) implements GenericEvent {}
|
|
||||||
|
|
||||||
/** WIP (Not working) Response indicating that the client could not connect. */
|
|
||||||
public record CouldNotConnect(long clientId) implements GenericEvent {}
|
|
||||||
|
|
||||||
/** Event indicating a client connection was closed. */
|
/** Event indicating a client connection was closed. */
|
||||||
public record ClosedConnection(long clientId) implements GenericEvent {}
|
public record ClosedConnection(long clientId) implements GenericEvent {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package org.toop.framework.networking.exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when an operation is attempted on a networking client
|
||||||
|
* that does not exist or has already been closed.
|
||||||
|
*/
|
||||||
|
public class ClientNotFoundException extends RuntimeException {
|
||||||
|
|
||||||
|
private final long clientId;
|
||||||
|
|
||||||
|
public ClientNotFoundException(long clientId) {
|
||||||
|
super("Networking client with ID " + clientId + " was not found.");
|
||||||
|
this.clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientNotFoundException(long clientId, Throwable cause) {
|
||||||
|
super("Networking client with ID " + clientId + " was not found.", cause);
|
||||||
|
this.clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getClientId() {
|
||||||
|
return clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package org.toop.framework.networking.exceptions;
|
||||||
|
|
||||||
|
public class CouldNotConnectException extends RuntimeException {
|
||||||
|
|
||||||
|
private final long clientId;
|
||||||
|
|
||||||
|
public CouldNotConnectException(long clientId) {
|
||||||
|
super("Networking client with ID " + clientId + " could not connect.");
|
||||||
|
this.clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CouldNotConnectException(long clientId, Throwable cause) {
|
||||||
|
super("Networking client with ID " + clientId + " could not connect.", cause);
|
||||||
|
this.clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getClientId() {
|
||||||
|
return clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.toop.framework.networking;
|
package org.toop.framework.networking.exceptions;
|
||||||
|
|
||||||
public class NetworkingInitializationException extends RuntimeException {
|
public class NetworkingInitializationException extends RuntimeException {
|
||||||
public NetworkingInitializationException(String message, Throwable cause) {
|
public NetworkingInitializationException(String message, Throwable cause) {
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
package org.toop.framework.networking.interfaces;
|
package org.toop.framework.networking.interfaces;
|
||||||
|
|
||||||
|
import org.toop.framework.networking.exceptions.CouldNotConnectException;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
public interface NetworkingClient {
|
public interface NetworkingClient {
|
||||||
boolean connect(long clientId, String host, int port);
|
InetSocketAddress getAddress();
|
||||||
|
void connect(long clientId, String host, int port) throws CouldNotConnectException;
|
||||||
boolean isActive();
|
boolean isActive();
|
||||||
void writeAndFlush(String msg);
|
void writeAndFlush(String msg);
|
||||||
void closeConnection();
|
void closeConnection();
|
||||||
|
|||||||
@@ -1,11 +1,20 @@
|
|||||||
package org.toop.framework.networking.interfaces;
|
package org.toop.framework.networking.interfaces;
|
||||||
|
|
||||||
import java.util.OptionalLong;
|
import org.toop.framework.networking.exceptions.ClientNotFoundException;
|
||||||
|
import org.toop.framework.networking.exceptions.CouldNotConnectException;
|
||||||
|
import org.toop.framework.networking.types.NetworkingReconnect;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface NetworkingClientManager {
|
public interface NetworkingClientManager {
|
||||||
OptionalLong startClient(long id, NetworkingClient networkingClientClass, String host, int port);
|
void startClient(
|
||||||
boolean sendCommand(long id, String command);
|
long id,
|
||||||
boolean reconnect(long id);
|
NetworkingClient networkingClientClass,
|
||||||
boolean changeAddress(long id, String host, int port);
|
String host,
|
||||||
boolean closeClient(long id);
|
int port,
|
||||||
|
NetworkingReconnect networkingReconnect) throws CouldNotConnectException;
|
||||||
|
void sendCommand(long id, String command) throws ClientNotFoundException;
|
||||||
|
void reconnect(long id, NetworkingReconnect networkingReconnect) throws ClientNotFoundException;
|
||||||
|
void changeAddress(long id, String host, int port, NetworkingReconnect networkingReconnect) throws ClientNotFoundException;
|
||||||
|
void closeClient(long id) throws ClientNotFoundException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package org.toop.framework.networking.types;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public record NetworkingReconnect(int reconnectAttempts, long timeout, TimeUnit timeUnit) {}
|
||||||
Reference in New Issue
Block a user