Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import gama.core.messaging.GamaMessage;
import gama.core.messaging.MessagingSkill;
import gama.core.metamodel.agent.IAgent;
import gama.core.metamodel.population.IPopulation;
import gama.core.metamodel.population.IPopulation.Listener;
import gama.core.runtime.GAMA;
import gama.core.runtime.IScope;
import gama.core.runtime.exceptions.GamaRuntimeException;
Expand Down Expand Up @@ -78,6 +80,41 @@ public class NetworkSkill extends MessagingSkill {

/** The Constant REGISTRED_SERVER. */
final static String REGISTERED_SERVER = "registered_servers";


class NetworkListener implements Listener {

@Override
public void notifyPopulationCleared(IScope scope, IPopulation<? extends IAgent> pop) {
// do nothing
}

@Override
public void notifyAgentsRemoved(IScope sc, IPopulation<? extends IAgent> pop,
Collection<? extends IAgent> agents) {
// for(IAgent ag : agents) {
// disconnect(ag.getScope());
// }
}

@Override
public void notifyAgentsAdded(IScope scope, IPopulation<? extends IAgent> pop,
Collection<? extends IAgent> agents) {
// do nothing
}

@Override
public void notifyAgentRemoved(IScope sc, IPopulation<? extends IAgent> pop, IAgent agent) {
// do nothing
disconnect(agent.getScope());
}

@Override
public void notifyAgentAdded(IScope scope, IPopulation<? extends IAgent> pop, IAgent agent) {
// do nothing

}
}

/**
* System exec.
Expand Down Expand Up @@ -203,6 +240,11 @@ public boolean connectToServer(final IScope scope) throws GamaRuntimeException {

// Fix to Issue #2618
final String serverKey = createServerKey(serverURL, port);

if (scope.getAgent() != null) {
scope.getAgent().getPopulation().addListener(new NetworkListener());
Copy link

Copilot AI Jun 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registering a new listener on every connect causes multiple redundant listeners; ensure only one listener per population by tracking registration or moving it to initialization.

Suggested change
scope.getAgent().getPopulation().addListener(new NetworkListener());
IPopulation population = scope.getAgent().getPopulation();
if (!registeredPopulations.contains(population)) {
population.addListener(new NetworkListener());
registeredPopulations.add(population);
}

Copilot uses AI. Check for mistakes.
}


final Map<String, IConnector> myConnectors = this.getRegisteredServers(scope);
IConnector connector = myConnectors.get(serverKey);
Expand Down Expand Up @@ -324,21 +366,29 @@ public boolean connectToServer(final IScope scope) throws GamaRuntimeException {
doc = @doc (
value = "Disconnects from all the servers previously connected to. Will return true if everything went well, false in case of an error."))
public Boolean disconnect(final IScope scope) {
final Map<String, IConnector> connectors = this.getRegisteredServers(scope);
final Map<String, IConnector> connectors = getRegisteredServers(scope);
final IAgent agent = scope.getAgent();
List<String> serverList = (List<String>) agent.getAttribute(INetworkSkill.NET_AGENT_SERVER);
Copy link

Copilot AI Jun 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Directly casting and using serverList without checking for null can cause a NullPointerException if the attribute is missing; consider initializing or validating it first.

Suggested change
List<String> serverList = (List<String>) agent.getAttribute(INetworkSkill.NET_AGENT_SERVER);
List<String> serverList = (List<String>) agent.getAttribute(INetworkSkill.NET_AGENT_SERVER);
if (serverList == null) {
serverList = new ArrayList<>();
}

Copilot uses AI. Check for mistakes.

boolean no_problem = true;
var to_remove = new ArrayList<String>();
for (var entry : connectors.entrySet()) {
var connector_to_remove = new ArrayList<String>();
for (var server : serverList) {
try {
var connector = entry.getValue();
var connector = connectors.get(server);
connector.close(scope);
connector.leaveTheGroup(scope.getAgent(), REGISTERED_AGENTS);
to_remove.add(entry.getKey());
connector.leaveTheGroup(agent, REGISTERED_AGENTS);
connector_to_remove.add(server);
} catch (Exception ex) {
no_problem = false;
}
}

for (var connector : to_remove) { connectors.remove(connector); }
// removes all closed connections from the registered servers and NET_AGENT_SERVER list
for (var serverKey : connector_to_remove) {
connectors.remove(serverKey);
serverList.remove(serverKey);
}
agent.setAttribute(INetworkSkill.NET_AGENT_SERVER, serverList);

return no_problem;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ public void stopService() {
this.isAlive = false;
if (sender != null) { sender.close(); }
try {
if (receiver != null) { receiver.close(); }
if (socket != null) {
socket.close();
}
if (receiver != null) { receiver.close(); }
Comment on lines 112 to +115
Copy link

Copilot AI Jun 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closing the socket before closing the receiver stream can lead to resource leaks or exceptions; consider closing the receiver (input stream) before the socket.

Suggested change
if (socket != null) {
socket.close();
}
if (receiver != null) { receiver.close(); }
if (receiver != null) { receiver.close(); }
if (socket != null) {
socket.close();
}

Copilot uses AI. Check for mistakes.
} catch (final IOException e) {

e.printStackTrace();
Expand Down