// Make a very quick test to verify the agent's remote endpoint can be connected to.
// If not, no point in continuing - the server won't be able to talk to the agent anyway.
pingEndpoint(request.getRemoteEndpoint());
Agent agentByName = getAgentManager().getAgentByName(request.getName());
/*
* As part of the registration request, a previously registered agent should send its current token (aka the
* original token). We will check this original token in the database and see what agent name is associated with
* it. If it is different than the name of the agent that is asking for this registration, we abort. In effect,
* we are telling the agent "you are already registered under the name "A" - you cannot change your name to
* something else".
*
* If there is no original token with the request, this is either a brand new agent never before registered, or it
* is an agent that has been registered before but for some reason lost its token.
* In this case, if there is no agent with the name being requested, we register this as a new agent.
* If, however, the agent name is already in use, we abort the request. An agent cannot register with an
* existing agent without sending that agent's security token.
*/
if (request.getOriginalToken() != null) {
Agent agentByToken = getAgentManager().getAgentByAgentToken(request.getOriginalToken());
if (agentByToken != null) {
if (!agentByToken.getName().equals(request.getName())) {
String msg = "The agent asking for registration is already registered with the name ["
+ agentByToken.getName() + "], it cannot change its name to [" + request.getName() + "]";
throw new AgentRegistrationException(msg);
} else {
Agent agentByAddressPort = getAgentManager().getAgentByAddressAndPort(request.getAddress(),
request.getPort());
if (agentByAddressPort != null && !agentByAddressPort.getName().equals(request.getName())) {
// the agent request provided information about an authentic agent but it is trying to
// steal another agent's host/port. Thus, we will abort this request.
String msg = "The agent asking for registration [" + request.getName()
+ "] is trying to register the same address/port [" + request.getAddress() + ":"
+ request.getPort() + "] that is already registered under a different name ["
+ agentByAddressPort.getName() + "]";
throw new AgentRegistrationException(msg);
}
}
} else {
if (agentByName != null) {
// the agent request provided a name that already is in use by an agent. However, the request
// provided a security token that was not assigned to any agent! How can this be? Something is fishy.
String msg = "The agent asking for registration under the name [" + request.getName()
+ "] provided an invalid security token. This request will fail. " + securityTokenMessage();
throw new AgentRegistrationException(msg);
}
Agent agentByAddressPort = getAgentManager().getAgentByAddressAndPort(request.getAddress(),
request.getPort());
if (agentByAddressPort != null) {
// The agent is requesting to register an unused agent name - so this is considered a new agent.
// It provided a security token but it is an unknown/obsolete/bogus token (usually due to the
// fact that someone purged the platform/agent from the server database but the old agent is
// still around with its old token).
// However, the IP/port it wants to use is already in-use. This sounds fishy. If we let this
// go through, this agent with an unknown/bogus token will essentially hijack this IP/port
// belonging to an existing agent. If the agent wants to reuse an IP/port already in existence, it should
// already know its security token associated with that IP/port. Thus, we will abort this request.
String msg = "The agent asking for registration under the name [" + request.getName()
+ "] is attempting to take another agent's address/port [" + request.getAddress() + ":"
+ request.getPort() + "] with an unknown security token. This request will fail.";
throw new AgentRegistrationException(msg);
}
}
} else {
Agent agentByAddressPort = getAgentManager().getAgentByAddressAndPort(request.getAddress(),
request.getPort());
if (agentByAddressPort != null) {
if (!agentByAddressPort.getName().equals(request.getName())) {
String msg = "The agent asking for registration is trying to register the same address/port ["
+ request.getAddress()
+ ":"
+ request.getPort()
+ "] that is already registered under a different name ["
+ agentByAddressPort.getName()
+ "]. If this new agent is actually the same as the original, then re-register with the same name"
+ " and same security token. Otherwise, you should uninventory the Platform resource for agent ["
+ agentByAddressPort.getName() + "] and re-register this new agent.";
throw new AgentRegistrationException(msg);
} else {
String msg = "The agent [" + request.getName()
+ "] is attempting to re-register without a security token. " + securityTokenMessage();
throw new AgentRegistrationException(msg);
}
} else {
if (agentByName != null) {
// the name being registered already exists - but there is no security token to authenticate this request!
// Therefore, because this agent name is already registered and because this current request
// cannot authenticate itself with the proper security token, we fail.
String msg = "An agent is trying to register with an existing agent name ["
+ request.getName()
+ "] without providing a valid security token. If you are attempting to re-register this agent, "
+ "you will need the agent's security token. " + securityTokenMessage();
throw new AgentRegistrationException(msg);
}
}
}
Server registeringServer = getServerManager().getServer();
// if the agent is registering with a loopback address, log a warning since you probably do not want this in production
try {
String address = request.getAddress();
String fullEndpoint = request.getRemoteEndpoint();
boolean loopbackRegistration = false;
if (address.equals("127.0.0.1") || address.equalsIgnoreCase("localhost")) {
loopbackRegistration = true;
} else {
// jboss/remoting transport params might be telling us to have our client connect to a different address
if (fullEndpoint != null) {
if (fullEndpoint.contains("127.0.0.1") || fullEndpoint.contains("localhost")) {
loopbackRegistration = true;
}
}
}
if (loopbackRegistration) {
log.warn("An agent [" + request.getName()
+ "] has registered with a loopback address. This should only be done "
+ "for testing or demo purposes - this agent can only ever interact with this server. " + request);
}
} catch (Exception ignore) {
}
if (agentByName != null) {
log.info("Got agent registration request for existing agent: " + agentByName.getName() + "["
+ agentByName.getAddress() + ":" + agentByName.getPort() + "][" + request.getAgentVersion()
+ "] - Will " + (request.getRegenerateToken() ? "" : "not") + " regenerate a new token");
final String oldAddress = agentByName.getAddress();
final int oldPort = agentByName.getPort();
final String oldRemoteEndpoint = agentByName.getRemoteEndpoint();
agentByName.setServer(registeringServer);
agentByName.setAddress(request.getAddress());
agentByName.setPort(request.getPort());
agentByName.setRemoteEndpoint(request.getRemoteEndpoint());
if (request.getRegenerateToken()) {
agentByName.setAgentToken(generateAgentToken());
}
try {
agentManager.updateAgent(agentByName);
} catch (Exception e) {
log.warn("Could not update the agent in database", e);
throw new AgentRegistrationException(new WrappedRemotingException(e));
}
// if agent is re-registering in order to change its remote endpoint, destroy our old client.
if (!oldAddress.equals(request.getAddress()) || oldPort != request.getPort()
|| !oldRemoteEndpoint.equals(request.getRemoteEndpoint())) {
try {
final Agent oldAgent = new Agent();
oldAgent.setName(agentByName.getName());
oldAgent.setAddress(oldAddress);
oldAgent.setPort(oldPort);
oldAgent.setRemoteEndpoint(oldRemoteEndpoint);
agentManager.destroyAgentClient(oldAgent);
} catch (Exception e) {
log.warn("Could not destroy the agent client - will continue but agent comm may be broken", e);
}
}
} else {
log.info("Got agent registration request for new agent: " + request.getName() + "[" + request.getAddress()
+ ":" + request.getPort() + "][" + request.getAgentVersion() + "]");
// the agent does not yet exist, we need to create it
try {
agentByName = new Agent(request.getName(), request.getAddress(), request.getPort(),
request.getRemoteEndpoint(), generateAgentToken());
agentByName.setServer(registeringServer);
agentManager.createAgent(agentByName);
} catch (Exception e) {