|
|
@@ -1,13 +1,9 @@
|
|
|
package org.jetlinks.community.network.mqtt.server.vertx;
|
|
|
|
|
|
-import cn.hutool.core.lang.tree.Tree;
|
|
|
-import cn.hutool.core.lang.tree.TreeUtil;
|
|
|
-import cn.hutool.extra.spring.SpringUtil;
|
|
|
import io.netty.buffer.ByteBuf;
|
|
|
import io.netty.buffer.Unpooled;
|
|
|
-import io.netty.channel.nio.NioEventLoopGroup;
|
|
|
-import io.netty.handler.codec.http2.Http2Connection;
|
|
|
-import io.netty.handler.codec.mqtt.*;
|
|
|
+import io.netty.handler.codec.mqtt.MqttConnectReturnCode;
|
|
|
+import io.netty.handler.codec.mqtt.MqttQoS;
|
|
|
import io.vertx.core.buffer.Buffer;
|
|
|
import io.vertx.core.net.SocketAddress;
|
|
|
import io.vertx.mqtt.MqttEndpoint;
|
|
|
@@ -18,17 +14,13 @@ import io.vertx.mqtt.messages.MqttUnsubscribeMessage;
|
|
|
import lombok.AllArgsConstructor;
|
|
|
import lombok.Getter;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.jetlinks.community.network.mqtt.server.*;
|
|
|
-import org.jetlinks.core.event.EventBus;
|
|
|
-import org.jetlinks.core.message.DeviceOnlineMessage;
|
|
|
-import org.jetlinks.core.message.MessageType;
|
|
|
+import org.jetlinks.community.network.mqtt.server.MqttConnection;
|
|
|
+import org.jetlinks.community.network.mqtt.server.MqttPublishing;
|
|
|
+import org.jetlinks.community.network.mqtt.server.MqttSubscription;
|
|
|
+import org.jetlinks.community.network.mqtt.server.MqttUnSubscription;
|
|
|
import org.jetlinks.core.message.codec.MqttMessage;
|
|
|
import org.jetlinks.core.message.codec.SimpleMqttMessage;
|
|
|
import org.jetlinks.core.server.mqtt.MqttAuth;
|
|
|
-import org.jetlinks.core.server.session.DeviceSessionManager;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
-import org.springframework.util.StringUtils;
|
|
|
import reactor.core.publisher.EmitterProcessor;
|
|
|
import reactor.core.publisher.Flux;
|
|
|
import reactor.core.publisher.FluxSink;
|
|
|
@@ -37,15 +29,14 @@ import reactor.core.publisher.Mono;
|
|
|
import javax.annotation.Nonnull;
|
|
|
import java.net.InetSocketAddress;
|
|
|
import java.time.Duration;
|
|
|
-import java.util.*;
|
|
|
-import java.util.concurrent.ScheduledFuture;
|
|
|
-import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.Optional;
|
|
|
import java.util.function.Consumer;
|
|
|
import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
@Slf4j
|
|
|
class VertxMqttConnection implements MqttConnection {
|
|
|
+
|
|
|
private final MqttEndpoint endpoint;
|
|
|
private long keepAliveTimeoutMs;
|
|
|
@Getter
|
|
|
@@ -54,15 +45,12 @@ class VertxMqttConnection implements MqttConnection {
|
|
|
|
|
|
private final EmitterProcessor<MqttPublishing> messageProcessor = EmitterProcessor.create(false);
|
|
|
|
|
|
- private ScheduledFuture<?> pingRespTimeout;
|
|
|
-
|
|
|
private final FluxSink<MqttPublishing> publishingFluxSink = messageProcessor.sink(FluxSink.OverflowStrategy.BUFFER);
|
|
|
|
|
|
- private final EmitterProcessor<MqttSubscription> subscriptionProcessor = EmitterProcessor.create(false);
|
|
|
+ private final EmitterProcessor<MqttSubscription> subscription = EmitterProcessor.create(false);
|
|
|
private final EmitterProcessor<MqttUnSubscription> unsubscription = EmitterProcessor.create(false);
|
|
|
|
|
|
private static final MqttAuth emptyAuth = new MqttAuth() {
|
|
|
-
|
|
|
@Override
|
|
|
public String getUsername() {
|
|
|
return "";
|
|
|
@@ -81,9 +69,10 @@ class VertxMqttConnection implements MqttConnection {
|
|
|
|
|
|
private final Consumer<MqttConnection> defaultListener = mqttConnection -> {
|
|
|
log.debug("mqtt client [{}] disconnected", getClientId());
|
|
|
- subscriptionProcessor.onComplete();
|
|
|
+ subscription.onComplete();
|
|
|
unsubscription.onComplete();
|
|
|
messageProcessor.onComplete();
|
|
|
+
|
|
|
};
|
|
|
|
|
|
private Consumer<MqttConnection> disconnectConsumer = defaultListener;
|
|
|
@@ -124,70 +113,21 @@ class VertxMqttConnection implements MqttConnection {
|
|
|
if (accepted) {
|
|
|
return this;
|
|
|
}
|
|
|
- accepted = true;
|
|
|
- //todo 需要验证密码
|
|
|
log.debug("mqtt client [{}] connected", getClientId());
|
|
|
- ping();
|
|
|
+ accepted = true;
|
|
|
try {
|
|
|
if (!endpoint.isConnected()) {
|
|
|
-
|
|
|
+ endpoint.accept();
|
|
|
}
|
|
|
- //心跳检测 todo 改为配置文件配置
|
|
|
- heartIdleHandler(endpoint,keepAliveTimeoutMs,TimeUnit.SECONDS);
|
|
|
} catch (Exception e) {
|
|
|
close().subscribe();
|
|
|
log.warn(e.getMessage(), e);
|
|
|
return this;
|
|
|
}
|
|
|
-// initSubscript();
|
|
|
init();
|
|
|
- endpoint.accept();
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- private static final Map<String, List<MqttEndpoint>> map = new HashMap<>();
|
|
|
-// /**
|
|
|
-// * 初始化监听器
|
|
|
-// */
|
|
|
-// private void initSubscript() {
|
|
|
-//
|
|
|
-// //todo 订阅处理
|
|
|
-// subscriptionProcessor.subscribe(mqttSubscription -> {
|
|
|
-// MqttSubscribeMessage message = mqttSubscription.getMessage();
|
|
|
-// List<MqttTopicSubscription> mqttTopicSubscriptions = message.topicSubscriptions();
|
|
|
-// for (MqttTopicSubscription subscription : mqttTopicSubscriptions) {
|
|
|
-// TopicHelper.addTopic(subscription.topicName(),endpoint);
|
|
|
-// }
|
|
|
-// });
|
|
|
-// //取消订阅处理 todo
|
|
|
-// unsubscription.subscribe(mqttUnSubscription -> {
|
|
|
-// List<String> topics = mqttUnSubscription.getMessage().topics();
|
|
|
-// for (String topic : topics) {
|
|
|
-// TopicHelper.deleteNodeEndPoint(topic,endpoint);
|
|
|
-// }
|
|
|
-// });
|
|
|
-//
|
|
|
-// //发布处理 todo
|
|
|
-// messageProcessor.subscribe(publishing -> {
|
|
|
-// // /tuoren/yanjiuyuan
|
|
|
-// String publishTopic = publishing.getMessage().getTopic();
|
|
|
-// Set<MqttEndpoint> mqttEndpoints = TopicHelper.findMatchNodes(publishTopic);
|
|
|
-// // /tuoren/yanjiuyuan /tuoren/#
|
|
|
-// mqttEndpoints.parallelStream().forEach(mqttEndpoint ->{
|
|
|
-// mqttEndpoint.publish(publishTopic,Buffer.buffer(publishing.getMessage().payloadAsString(),"utf-8"),MqttQoS.AT_MOST_ONCE,false,false);
|
|
|
-// });
|
|
|
-// });
|
|
|
-// }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void heartIdleHandler(MqttEndpoint endpoint, long delay, TimeUnit unit) {
|
|
|
- this.pingRespTimeout= new NioEventLoopGroup(1).schedule(()->{
|
|
|
- log.warn("通道关闭了:{}",endpoint.remoteAddress());
|
|
|
- endpoint.close();
|
|
|
- },delay,unit);
|
|
|
- }
|
|
|
-
|
|
|
@Override
|
|
|
public void keepAlive() {
|
|
|
ping();
|
|
|
@@ -195,22 +135,15 @@ class VertxMqttConnection implements MqttConnection {
|
|
|
|
|
|
void ping() {
|
|
|
lastPingTime = System.currentTimeMillis();
|
|
|
- if (this.pingRespTimeout != null && !this.pingRespTimeout.isCancelled() && !this.pingRespTimeout.isDone()) {
|
|
|
- this.pingRespTimeout.cancel(true);
|
|
|
- this.pingRespTimeout = null;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
void init() {
|
|
|
this.endpoint
|
|
|
- .exceptionHandler(event -> {
|
|
|
-
|
|
|
- })
|
|
|
.disconnectHandler(ignore -> this.complete())
|
|
|
.closeHandler(ignore -> this.complete())
|
|
|
.pingHandler(ignore -> {
|
|
|
this.ping();
|
|
|
- if (endpoint.isAutoKeepAlive()) {
|
|
|
+ if (!endpoint.isAutoKeepAlive()) {
|
|
|
endpoint.pong();
|
|
|
}
|
|
|
})
|
|
|
@@ -249,27 +182,25 @@ class VertxMqttConnection implements MqttConnection {
|
|
|
})
|
|
|
.subscribeHandler(msg -> {
|
|
|
ping();
|
|
|
- VertxMqttSubscription subscription = new VertxMqttSubscription( msg,false);
|
|
|
- boolean hasDownstream = this.subscriptionProcessor.hasDownstreams();
|
|
|
+ VertxMqttSubscription subscription = new VertxMqttSubscription(msg, false);
|
|
|
+ boolean hasDownstream = this.subscription.hasDownstreams();
|
|
|
if (autoAckSub || !hasDownstream) {
|
|
|
subscription.acknowledge();
|
|
|
}
|
|
|
- this.subscriptionProcessor.onNext(subscription);
|
|
|
if (hasDownstream) {
|
|
|
- this.subscriptionProcessor.onNext(subscription);
|
|
|
+ this.subscription.onNext(subscription);
|
|
|
}
|
|
|
})
|
|
|
.unsubscribeHandler(msg -> {
|
|
|
ping();
|
|
|
- VertxMqttMqttUnSubscription unSubscription = new VertxMqttMqttUnSubscription(msg,false);
|
|
|
+ VertxMqttMqttUnSubscription unSubscription = new VertxMqttMqttUnSubscription(msg, false);
|
|
|
boolean hasDownstream = this.unsubscription.hasDownstreams();
|
|
|
if (autoAckUnSub || !hasDownstream) {
|
|
|
unSubscription.acknowledge();
|
|
|
}
|
|
|
- this.unsubscription.onNext(unSubscription);
|
|
|
-// if (hasDownstream) {
|
|
|
-// this.unsubscription.onNext(unSubscription);
|
|
|
-// }
|
|
|
+ if (hasDownstream) {
|
|
|
+ this.unsubscription.onNext(unSubscription);
|
|
|
+ }
|
|
|
});
|
|
|
}
|
|
|
|
|
|
@@ -329,8 +260,9 @@ class VertxMqttConnection implements MqttConnection {
|
|
|
|
|
|
@Override
|
|
|
public Flux<MqttSubscription> handleSubscribe(boolean autoAck) {
|
|
|
+
|
|
|
autoAckSub = autoAck;
|
|
|
- return subscriptionProcessor.map(Function.identity());
|
|
|
+ return subscription.map(Function.identity());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -422,11 +354,6 @@ class VertxMqttConnection implements MqttConnection {
|
|
|
|
|
|
private volatile boolean acknowledged;
|
|
|
|
|
|
-
|
|
|
- public void setAcknowledged(boolean acknowledged) {
|
|
|
- this.acknowledged = acknowledged;
|
|
|
- }
|
|
|
-
|
|
|
@Override
|
|
|
public MqttMessage getMessage() {
|
|
|
return new VertxMqttMessage(message);
|
|
|
@@ -453,7 +380,6 @@ class VertxMqttConnection implements MqttConnection {
|
|
|
|
|
|
private final MqttSubscribeMessage message;
|
|
|
|
|
|
-
|
|
|
private volatile boolean acknowledged;
|
|
|
|
|
|
@Override
|