use of org.forgerock.openam.radius.server.events.PacketReceivedEvent in project OpenAM by OpenRock.
the class RadiusRequestListener method run.
/**
* Where the work gets done. :-) Blocks until packets are received, validates the source IP against configured
* clients and drops packets accordingly, then spools valid ones to the thread pool for handling and goes back to
* listening.
*/
@Override
public void run() {
// Flag to hold interrupted state for returning after cleanup.
boolean interrupted = false;
dumpBannerToLog();
while (!terminated && !interrupted) {
try {
// assure big-endian (network) byte order for our buffer
final ByteBuffer bfr = ByteBuffer.allocate(RadiusServerConstants.MAX_PACKET_SIZE);
bfr.order(ByteOrder.BIG_ENDIAN);
InetSocketAddress iAddr = null;
// see if we have a datagram packet waiting for us
try {
iAddr = (InetSocketAddress) channel.receive(bfr);
if (iAddr == null) {
// no datagram was available, it happens, just go back to listening
LOG.message("DatagramChannel receive returned null. No datagram available.");
continue;
} else {
eventBus.post(new PacketReceivedEvent());
}
} catch (final ClosedByInterruptException c) {
interrupted = true;
continue;
} catch (final IOException e) {
LOG.warning("Exception Receiving RADIUS packet. Ignoring.", e);
continue;
} catch (final SecurityException e) {
LOG.error("a security manager has been installed and it does not permit datagrams to be " + " accepted from the datagram's sender. Ignoring", e);
continue;
}
// see if it is for a registered client
final String ipAddr = iAddr.getAddress().toString();
final ClientConfig clientConfig = config.findClient(ipAddr);
if (clientConfig == null) {
LOG.warning("No Defined RADIUS Client matches IP address " + ipAddr + ". Dropping request.");
continue;
}
if (!clientConfig.isClassIsValid()) {
LOG.warning("Declared Handler Class for Client '" + clientConfig.getName() + "' is not valid. See earlier loading exception. Dropping request.");
continue;
}
// prepare buffer for draining and queue up a handler
bfr.flip();
final RadiusRequestContext reqCtx = new RadiusRequestContext(clientConfig, channel, iAddr);
final PromiseImpl<RadiusResponse, RadiusProcessingException> promise = PromiseImpl.create();
final RadiusRequestHandler requestHandler = new RadiusRequestHandler(accessRequestHandlerFactory, reqCtx, bfr, promise, promise, eventBus);
executorService.execute(requestHandler);
try {
final RadiusResponse result = promise.getOrThrow();
eventBus.post(new PacketProcessedEvent());
} catch (final RadiusProcessingException e) {
final RadiusProcessingExceptionNature nature = e.getNature();
switch(nature) {
case CATASTROPHIC:
LOG.error("Catestrophic error processing a RADIUS request.", e);
terminated = true;
break;
case INVALID_RESPONSE:
LOG.error("Failed to handle request. This request will be ignored.", e);
break;
case TEMPORARY_FAILURE:
final String errStr = "Failed to handle request. This request could be retried, but that is" + " currently not implemented.";
LOG.error(errStr, e);
break;
default:
break;
}
}
} catch (final Exception t) {
LOG.error("Error receiving request.", t);
}
}
// re-assert interrupted state if it occurred
if (interrupted) {
Thread.currentThread().interrupt();
}
try {
// be sure that channel is closed
channel.close();
} catch (final Exception e) {
LOG.error("Failed to close the Listener's UDP channel", e);
}
LOG.message("RADIUS Listener Exited.");
this.listenerThread = null;
}
Aggregations