com.github.netty.protocol.mqtt.interception.BrokerInterceptor Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package com.github.netty.protocol.mqtt.interception;
import com.github.netty.core.util.LoggerFactoryX;
import com.github.netty.core.util.LoggerX;
import com.github.netty.core.util.ThreadPoolX;
import com.github.netty.protocol.mqtt.subscriptions.Subscription;
import io.netty.handler.codec.mqtt.MqttConnectMessage;
import io.netty.handler.codec.mqtt.MqttPublishMessage;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
/**
* An interceptor that execute the interception tasks asynchronously.
*/
public final class BrokerInterceptor implements Interceptor {
private static final LoggerX LOG = LoggerFactoryX.getLogger(BrokerInterceptor.class);
private final Map, List> handlers;
private final ExecutorService executor;
public BrokerInterceptor(int poolSize, List handlers) {
this.handlers = new HashMap<>();
for (Class> messageType : InterceptHandler.ALL_MESSAGE_TYPES) {
this.handlers.put(messageType, new CopyOnWriteArrayList());
}
if (handlers != null) {
for (InterceptHandler handler : handlers) {
addInterceptHandler(handler);
}
}
executor = new ThreadPoolX("MQTT", poolSize);
}
public BrokerInterceptor(int poolSize) {
this(poolSize, null);
}
private static Class>[] getInterceptedMessageTypes(InterceptHandler interceptHandler) {
Class>[] interceptedMessageTypes = interceptHandler.getInterceptedMessageTypes();
if (interceptedMessageTypes == null) {
return InterceptHandler.ALL_MESSAGE_TYPES;
}
return interceptedMessageTypes;
}
/**
* Shutdown graciously the executor service
*/
public void stop() {
LOG.info("Shutting down interceptor thread pool...");
executor.shutdown();
try {
LOG.info("Waiting for thread pool tasks to terminate...");
executor.awaitTermination(10L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
}
if (!executor.isTerminated()) {
LOG.warn("Forcing shutdown of interceptor thread pool...");
executor.shutdownNow();
}
LOG.info("interceptors stopped");
}
@Override
public void notifyClientConnected(final MqttConnectMessage msg) {
for (final InterceptHandler handler : this.handlers.get(InterceptConnectMessage.class)) {
LOG.debug("Sending MQTT CONNECT message to interceptor. CId={}, interceptorId={}",
msg.payload().clientIdentifier(), handler.getID());
executor.execute(() -> handler.onConnect(new InterceptConnectMessage(msg)));
}
}
@Override
public void notifyClientDisconnected(final String clientID, final String username) {
for (final InterceptHandler handler : this.handlers.get(InterceptDisconnectMessage.class)) {
LOG.debug("Notifying MQTT client disconnection to interceptor. CId={}, username={}, interceptorId={}",
clientID, username, handler.getID());
executor.execute(() -> handler.onDisconnect(new InterceptDisconnectMessage(clientID, username)));
}
}
@Override
public void notifyClientConnectionLost(final String clientID, final String username) {
for (final InterceptHandler handler : this.handlers.get(InterceptConnectionLostMessage.class)) {
LOG.debug("Notifying unexpected MQTT client disconnection to interceptor CId={}, username={}, " +
"interceptorId={}", clientID, username, handler.getID());
executor.execute(() -> handler.onConnectionLost(new InterceptConnectionLostMessage(clientID, username)));
}
}
@Override
public void notifyTopicPublished(final MqttPublishMessage msg, final String clientID, final String username) {
msg.retain();
executor.execute(() -> {
try {
int messageId = msg.variableHeader().messageId();
String topic = msg.variableHeader().topicName();
for (InterceptHandler handler : handlers.get(InterceptPublishMessage.class)) {
LOG.debug("Notifying MQTT PUBLISH message to interceptor. CId={}, messageId={}, topic={}, "
+ "interceptorId={}", clientID, messageId, topic, handler.getID());
handler.onPublish(new InterceptPublishMessage(msg, clientID, username));
}
} finally {
msg.release();
}
});
}
@Override
public void notifyTopicSubscribed(final Subscription sub, final String username) {
for (final InterceptHandler handler : this.handlers.get(InterceptSubscribeMessage.class)) {
LOG.debug("Notifying MQTT SUBSCRIBE message to interceptor. CId={}, topicFilter={}, interceptorId={}",
sub.getClientId(), sub.getTopicFilter(), handler.getID());
executor.execute(() -> handler.onSubscribe(new InterceptSubscribeMessage(sub, username)));
}
}
@Override
public void notifyTopicUnsubscribed(final String topic, final String clientID, final String username) {
for (final InterceptHandler handler : this.handlers.get(InterceptUnsubscribeMessage.class)) {
LOG.debug("Notifying MQTT UNSUBSCRIBE message to interceptor. CId={}, topic={}, interceptorId={}", clientID,
topic, handler.getID());
executor.execute(() -> handler.onUnsubscribe(new InterceptUnsubscribeMessage(topic, clientID, username)));
}
}
@Override
public void notifyMessageAcknowledged(final InterceptAcknowledgedMessage msg) {
for (final InterceptHandler handler : this.handlers.get(InterceptAcknowledgedMessage.class)) {
LOG.debug("Notifying MQTT ACK message to interceptor. CId={}, messageId={}, topic={}, interceptorId={}",
msg.getMsg()/*.getClientID()*/, msg.getPacketID(), msg.getTopic(), handler.getID());
executor.execute(() -> handler.onMessageAcknowledged(msg));
}
}
@Override
public void addInterceptHandler(InterceptHandler interceptHandler) {
Class>[] interceptedMessageTypes = getInterceptedMessageTypes(interceptHandler);
LOG.info("Adding MQTT message interceptor. InterceptorId={}, handledMessageTypes={}",
interceptHandler.getID(), interceptedMessageTypes);
for (Class> interceptMessageType : interceptedMessageTypes) {
this.handlers.get(interceptMessageType).add(interceptHandler);
}
}
@Override
public void removeInterceptHandler(InterceptHandler interceptHandler) {
Class>[] interceptedMessageTypes = getInterceptedMessageTypes(interceptHandler);
LOG.info("Removing MQTT message interceptor. InterceptorId={}, handledMessageTypes={}",
interceptHandler.getID(), interceptedMessageTypes);
for (Class> interceptMessageType : interceptedMessageTypes) {
this.handlers.get(interceptMessageType).remove(interceptHandler);
}
}
}