|
|
@ -1,12 +1,12 @@ |
|
|
/** |
|
|
/** |
|
|
* Copyright © 2016-2018 The Thingsboard Authors |
|
|
* Copyright © 2016-2018 The Thingsboard Authors |
|
|
* |
|
|
* <p> |
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
* you may not use this file except in compliance with the License. |
|
|
* you may not use this file except in compliance with the License. |
|
|
* You may obtain a copy of the License at |
|
|
* You may obtain a copy of the License at |
|
|
* |
|
|
* <p> |
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
* |
|
|
* <p> |
|
|
* Unless required by applicable law or agreed to in writing, software |
|
|
* Unless required by applicable law or agreed to in writing, software |
|
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
|
@ -18,9 +18,21 @@ package org.thingsboard.server.transport.mqtt; |
|
|
import com.fasterxml.jackson.databind.JsonNode; |
|
|
import com.fasterxml.jackson.databind.JsonNode; |
|
|
import io.netty.channel.ChannelHandlerContext; |
|
|
import io.netty.channel.ChannelHandlerContext; |
|
|
import io.netty.channel.ChannelInboundHandlerAdapter; |
|
|
import io.netty.channel.ChannelInboundHandlerAdapter; |
|
|
import io.netty.handler.codec.mqtt.*; |
|
|
import io.netty.handler.codec.mqtt.MqttConnAckMessage; |
|
|
|
|
|
import io.netty.handler.codec.mqtt.MqttConnAckVariableHeader; |
|
|
|
|
|
import io.netty.handler.codec.mqtt.MqttConnectMessage; |
|
|
import io.netty.handler.codec.mqtt.MqttConnectReturnCode; |
|
|
import io.netty.handler.codec.mqtt.MqttConnectReturnCode; |
|
|
|
|
|
import io.netty.handler.codec.mqtt.MqttFixedHeader; |
|
|
|
|
|
import io.netty.handler.codec.mqtt.MqttMessage; |
|
|
|
|
|
import io.netty.handler.codec.mqtt.MqttMessageIdVariableHeader; |
|
|
|
|
|
import io.netty.handler.codec.mqtt.MqttPubAckMessage; |
|
|
|
|
|
import io.netty.handler.codec.mqtt.MqttPublishMessage; |
|
|
import io.netty.handler.codec.mqtt.MqttQoS; |
|
|
import io.netty.handler.codec.mqtt.MqttQoS; |
|
|
|
|
|
import io.netty.handler.codec.mqtt.MqttSubAckMessage; |
|
|
|
|
|
import io.netty.handler.codec.mqtt.MqttSubAckPayload; |
|
|
|
|
|
import io.netty.handler.codec.mqtt.MqttSubscribeMessage; |
|
|
|
|
|
import io.netty.handler.codec.mqtt.MqttTopicSubscription; |
|
|
|
|
|
import io.netty.handler.codec.mqtt.MqttUnsubscribeMessage; |
|
|
import io.netty.handler.ssl.SslHandler; |
|
|
import io.netty.handler.ssl.SslHandler; |
|
|
import io.netty.util.concurrent.Future; |
|
|
import io.netty.util.concurrent.Future; |
|
|
import io.netty.util.concurrent.GenericFutureListener; |
|
|
import io.netty.util.concurrent.GenericFutureListener; |
|
|
@ -34,13 +46,12 @@ import org.thingsboard.server.common.msg.session.AdaptorToSessionActorMsg; |
|
|
import org.thingsboard.server.common.msg.session.BasicAdaptorToSessionActorMsg; |
|
|
import org.thingsboard.server.common.msg.session.BasicAdaptorToSessionActorMsg; |
|
|
import org.thingsboard.server.common.msg.session.BasicTransportToDeviceSessionActorMsg; |
|
|
import org.thingsboard.server.common.msg.session.BasicTransportToDeviceSessionActorMsg; |
|
|
import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg; |
|
|
import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg; |
|
|
import org.thingsboard.server.common.transport.SessionMsgProcessor; |
|
|
import org.thingsboard.server.common.transport.TransportService; |
|
|
|
|
|
import org.thingsboard.server.common.transport.TransportServiceCallback; |
|
|
import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
|
|
import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
|
|
import org.thingsboard.server.common.transport.auth.DeviceAuthService; |
|
|
|
|
|
import org.thingsboard.server.common.transport.quota.QuotaService; |
|
|
import org.thingsboard.server.common.transport.quota.QuotaService; |
|
|
import org.thingsboard.server.dao.EncryptionUtil; |
|
|
import org.thingsboard.server.dao.EncryptionUtil; |
|
|
import org.thingsboard.server.dao.device.DeviceService; |
|
|
import org.thingsboard.server.gen.transport.TransportProtos; |
|
|
import org.thingsboard.server.dao.relation.RelationService; |
|
|
|
|
|
import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor; |
|
|
import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor; |
|
|
import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx; |
|
|
import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx; |
|
|
import org.thingsboard.server.transport.mqtt.session.GatewaySessionCtx; |
|
|
import org.thingsboard.server.transport.mqtt.session.GatewaySessionCtx; |
|
|
@ -48,18 +59,51 @@ import org.thingsboard.server.transport.mqtt.util.SslUtil; |
|
|
|
|
|
|
|
|
import javax.net.ssl.SSLPeerUnverifiedException; |
|
|
import javax.net.ssl.SSLPeerUnverifiedException; |
|
|
import javax.security.cert.X509Certificate; |
|
|
import javax.security.cert.X509Certificate; |
|
|
|
|
|
import java.io.IOException; |
|
|
import java.net.InetSocketAddress; |
|
|
import java.net.InetSocketAddress; |
|
|
import java.util.ArrayList; |
|
|
import java.util.ArrayList; |
|
|
import java.util.List; |
|
|
import java.util.List; |
|
|
import java.util.Map; |
|
|
import java.util.UUID; |
|
|
import java.util.concurrent.ConcurrentHashMap; |
|
|
import java.util.concurrent.ConcurrentHashMap; |
|
|
import java.util.concurrent.ConcurrentMap; |
|
|
import java.util.concurrent.ConcurrentMap; |
|
|
|
|
|
|
|
|
import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.*; |
|
|
import org.thingsboard.server.gen.transport.TransportProtos.*; |
|
|
import static io.netty.handler.codec.mqtt.MqttMessageType.*; |
|
|
|
|
|
import static io.netty.handler.codec.mqtt.MqttQoS.*; |
|
|
import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEPTED; |
|
|
import static org.thingsboard.server.common.msg.session.SessionMsgType.*; |
|
|
import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD; |
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.*; |
|
|
import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED; |
|
|
|
|
|
import static io.netty.handler.codec.mqtt.MqttMessageType.CONNACK; |
|
|
|
|
|
import static io.netty.handler.codec.mqtt.MqttMessageType.PINGRESP; |
|
|
|
|
|
import static io.netty.handler.codec.mqtt.MqttMessageType.PUBACK; |
|
|
|
|
|
import static io.netty.handler.codec.mqtt.MqttMessageType.SUBACK; |
|
|
|
|
|
import static io.netty.handler.codec.mqtt.MqttMessageType.UNSUBACK; |
|
|
|
|
|
import static io.netty.handler.codec.mqtt.MqttQoS.AT_LEAST_ONCE; |
|
|
|
|
|
import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE; |
|
|
|
|
|
import static io.netty.handler.codec.mqtt.MqttQoS.FAILURE; |
|
|
|
|
|
import static org.thingsboard.server.common.msg.session.SessionMsgType.GET_ATTRIBUTES_REQUEST; |
|
|
|
|
|
import static org.thingsboard.server.common.msg.session.SessionMsgType.POST_ATTRIBUTES_REQUEST; |
|
|
|
|
|
import static org.thingsboard.server.common.msg.session.SessionMsgType.POST_TELEMETRY_REQUEST; |
|
|
|
|
|
import static org.thingsboard.server.common.msg.session.SessionMsgType.SUBSCRIBE_ATTRIBUTES_REQUEST; |
|
|
|
|
|
import static org.thingsboard.server.common.msg.session.SessionMsgType.SUBSCRIBE_RPC_COMMANDS_REQUEST; |
|
|
|
|
|
import static org.thingsboard.server.common.msg.session.SessionMsgType.TO_DEVICE_RPC_RESPONSE; |
|
|
|
|
|
import static org.thingsboard.server.common.msg.session.SessionMsgType.TO_SERVER_RPC_REQUEST; |
|
|
|
|
|
import static org.thingsboard.server.common.msg.session.SessionMsgType.UNSUBSCRIBE_ATTRIBUTES_REQUEST; |
|
|
|
|
|
import static org.thingsboard.server.common.msg.session.SessionMsgType.UNSUBSCRIBE_RPC_COMMANDS_REQUEST; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.BASE_GATEWAY_API_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.DEVICE_ATTRIBUTES_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.DEVICE_RPC_REQUESTS_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.DEVICE_RPC_RESPONSE_SUB_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.DEVICE_RPC_RESPONSE_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.DEVICE_TELEMETRY_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.GATEWAY_ATTRIBUTES_REQUEST_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.GATEWAY_ATTRIBUTES_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.GATEWAY_CONNECT_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.GATEWAY_DISCONNECT_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.GATEWAY_RPC_TOPIC; |
|
|
|
|
|
import static org.thingsboard.server.transport.mqtt.MqttTopics.GATEWAY_TELEMETRY_TOPIC; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @author Andrew Shvayka |
|
|
* @author Andrew Shvayka |
|
|
@ -69,33 +113,34 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
|
|
|
|
|
|
|
|
public static final MqttQoS MAX_SUPPORTED_QOS_LVL = AT_LEAST_ONCE; |
|
|
public static final MqttQoS MAX_SUPPORTED_QOS_LVL = AT_LEAST_ONCE; |
|
|
|
|
|
|
|
|
private final DeviceSessionCtx deviceSessionCtx; |
|
|
private final UUID sessionId; |
|
|
private final String sessionId; |
|
|
private final MqttTransportContext context; |
|
|
private final MqttTransportAdaptor adaptor; |
|
|
private final MqttTransportAdaptor adaptor; |
|
|
private final SessionMsgProcessor processor; |
|
|
private final TransportService transportService; |
|
|
private final DeviceService deviceService; |
|
|
|
|
|
private final DeviceAuthService authService; |
|
|
|
|
|
private final RelationService relationService; |
|
|
|
|
|
private final QuotaService quotaService; |
|
|
private final QuotaService quotaService; |
|
|
private final SslHandler sslHandler; |
|
|
private final SslHandler sslHandler; |
|
|
private final ConcurrentMap<String, Integer> mqttQoSMap; |
|
|
private final ConcurrentMap<String, Integer> mqttQoSMap; |
|
|
|
|
|
|
|
|
private volatile boolean connected; |
|
|
private final SessionInfoProto sessionInfo; |
|
|
|
|
|
|
|
|
private volatile InetSocketAddress address; |
|
|
private volatile InetSocketAddress address; |
|
|
|
|
|
private volatile DeviceSessionCtx deviceSessionCtx; |
|
|
private volatile GatewaySessionCtx gatewaySessionCtx; |
|
|
private volatile GatewaySessionCtx gatewaySessionCtx; |
|
|
|
|
|
|
|
|
public MqttTransportHandler(SessionMsgProcessor processor, DeviceService deviceService, DeviceAuthService authService, RelationService relationService, |
|
|
public MqttTransportHandler(MqttTransportContext context) { |
|
|
MqttTransportAdaptor adaptor, SslHandler sslHandler, QuotaService quotaService) { |
|
|
this.sessionId = UUID.randomUUID(); |
|
|
this.processor = processor; |
|
|
this.context = context; |
|
|
this.deviceService = deviceService; |
|
|
this.transportService = context.getTransportService(); |
|
|
this.relationService = relationService; |
|
|
this.adaptor = context.getAdaptor(); |
|
|
this.authService = authService; |
|
|
this.quotaService = context.getQuotaService(); |
|
|
this.adaptor = adaptor; |
|
|
this.sslHandler = context.getSslHandler(); |
|
|
this.mqttQoSMap = new ConcurrentHashMap<>(); |
|
|
this.mqttQoSMap = new ConcurrentHashMap<>(); |
|
|
this.deviceSessionCtx = new DeviceSessionCtx(processor, authService, adaptor, mqttQoSMap); |
|
|
this.sessionInfo = SessionInfoProto.newBuilder() |
|
|
this.sessionId = deviceSessionCtx.getSessionId().toUidStr(); |
|
|
.setNodeId(context.getNodeId()) |
|
|
this.sslHandler = sslHandler; |
|
|
.setSessionIdMSB(sessionId.getMostSignificantBits()) |
|
|
this.quotaService = quotaService; |
|
|
.setSessionIdLSB(sessionId.getLeastSignificantBits()) |
|
|
|
|
|
.build(); |
|
|
|
|
|
this.deviceSessionCtx = new DeviceSessionCtx(mqttQoSMap); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
@ -127,196 +172,196 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
|
|
case CONNECT: |
|
|
case CONNECT: |
|
|
processConnect(ctx, (MqttConnectMessage) msg); |
|
|
processConnect(ctx, (MqttConnectMessage) msg); |
|
|
break; |
|
|
break; |
|
|
case PUBLISH: |
|
|
// case PUBLISH:
|
|
|
processPublish(ctx, (MqttPublishMessage) msg); |
|
|
// processPublish(ctx, (MqttPublishMessage) msg);
|
|
|
break; |
|
|
// break;
|
|
|
case SUBSCRIBE: |
|
|
// case SUBSCRIBE:
|
|
|
processSubscribe(ctx, (MqttSubscribeMessage) msg); |
|
|
// processSubscribe(ctx, (MqttSubscribeMessage) msg);
|
|
|
break; |
|
|
// break;
|
|
|
case UNSUBSCRIBE: |
|
|
// case UNSUBSCRIBE:
|
|
|
processUnsubscribe(ctx, (MqttUnsubscribeMessage) msg); |
|
|
// processUnsubscribe(ctx, (MqttUnsubscribeMessage) msg);
|
|
|
break; |
|
|
// break;
|
|
|
case PINGREQ: |
|
|
// case PINGREQ:
|
|
|
if (checkConnected(ctx)) { |
|
|
// if (checkConnected(ctx)) {
|
|
|
ctx.writeAndFlush(new MqttMessage(new MqttFixedHeader(PINGRESP, false, AT_MOST_ONCE, false, 0))); |
|
|
// ctx.writeAndFlush(new MqttMessage(new MqttFixedHeader(PINGRESP, false, AT_MOST_ONCE, false, 0)));
|
|
|
} |
|
|
// }
|
|
|
break; |
|
|
// break;
|
|
|
case DISCONNECT: |
|
|
// case DISCONNECT:
|
|
|
if (checkConnected(ctx)) { |
|
|
// if (checkConnected(ctx)) {
|
|
|
processDisconnect(ctx); |
|
|
// processDisconnect(ctx);
|
|
|
} |
|
|
// }
|
|
|
break; |
|
|
// break;
|
|
|
default: |
|
|
default: |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private void processPublish(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg) { |
|
|
// private void processPublish(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg) {
|
|
|
if (!checkConnected(ctx)) { |
|
|
// if (!checkConnected(ctx)) {
|
|
|
return; |
|
|
// return;
|
|
|
} |
|
|
// }
|
|
|
String topicName = mqttMsg.variableHeader().topicName(); |
|
|
// String topicName = mqttMsg.variableHeader().topicName();
|
|
|
int msgId = mqttMsg.variableHeader().messageId(); |
|
|
// int msgId = mqttMsg.variableHeader().packetId();
|
|
|
log.trace("[{}] Processing publish msg [{}][{}]!", sessionId, topicName, msgId); |
|
|
// log.trace("[{}] Processing publish msg [{}][{}]!", sessionId, topicName, msgId);
|
|
|
|
|
|
//
|
|
|
if (topicName.startsWith(BASE_GATEWAY_API_TOPIC)) { |
|
|
// if (topicName.startsWith(BASE_GATEWAY_API_TOPIC)) {
|
|
|
if (gatewaySessionCtx != null) { |
|
|
// if (gatewaySessionCtx != null) {
|
|
|
gatewaySessionCtx.setChannel(ctx); |
|
|
// gatewaySessionCtx.setChannel(ctx);
|
|
|
handleMqttPublishMsg(topicName, msgId, mqttMsg); |
|
|
// handleMqttPublishMsg(topicName, msgId, mqttMsg);
|
|
|
} |
|
|
// }
|
|
|
} else { |
|
|
// } else {
|
|
|
processDevicePublish(ctx, mqttMsg, topicName, msgId); |
|
|
// processDevicePublish(ctx, mqttMsg, topicName, msgId);
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
private void handleMqttPublishMsg(String topicName, int msgId, MqttPublishMessage mqttMsg) { |
|
|
// private void handleMqttPublishMsg(String topicName, int msgId, MqttPublishMessage mqttMsg) {
|
|
|
try { |
|
|
// try {
|
|
|
switch (topicName) { |
|
|
// switch (topicName) {
|
|
|
case GATEWAY_TELEMETRY_TOPIC: |
|
|
// case GATEWAY_TELEMETRY_TOPIC:
|
|
|
gatewaySessionCtx.onDeviceTelemetry(mqttMsg); |
|
|
// gatewaySessionCtx.onDeviceTelemetry(mqttMsg);
|
|
|
break; |
|
|
// break;
|
|
|
case GATEWAY_ATTRIBUTES_TOPIC: |
|
|
// case GATEWAY_ATTRIBUTES_TOPIC:
|
|
|
gatewaySessionCtx.onDeviceAttributes(mqttMsg); |
|
|
// gatewaySessionCtx.onDeviceAttributes(mqttMsg);
|
|
|
break; |
|
|
// break;
|
|
|
case GATEWAY_ATTRIBUTES_REQUEST_TOPIC: |
|
|
// case GATEWAY_ATTRIBUTES_REQUEST_TOPIC:
|
|
|
gatewaySessionCtx.onDeviceAttributesRequest(mqttMsg); |
|
|
// gatewaySessionCtx.onDeviceAttributesRequest(mqttMsg);
|
|
|
break; |
|
|
// break;
|
|
|
case GATEWAY_RPC_TOPIC: |
|
|
// case GATEWAY_RPC_TOPIC:
|
|
|
gatewaySessionCtx.onDeviceRpcResponse(mqttMsg); |
|
|
// gatewaySessionCtx.onDeviceRpcResponse(mqttMsg);
|
|
|
break; |
|
|
// break;
|
|
|
case GATEWAY_CONNECT_TOPIC: |
|
|
// case GATEWAY_CONNECT_TOPIC:
|
|
|
gatewaySessionCtx.onDeviceConnect(mqttMsg); |
|
|
// gatewaySessionCtx.onDeviceConnect(mqttMsg);
|
|
|
break; |
|
|
// break;
|
|
|
case GATEWAY_DISCONNECT_TOPIC: |
|
|
// case GATEWAY_DISCONNECT_TOPIC:
|
|
|
gatewaySessionCtx.onDeviceDisconnect(mqttMsg); |
|
|
// gatewaySessionCtx.onDeviceDisconnect(mqttMsg);
|
|
|
break; |
|
|
// break;
|
|
|
} |
|
|
// }
|
|
|
} catch (RuntimeException | AdaptorException e) { |
|
|
// } catch (RuntimeException | AdaptorException e) {
|
|
|
log.warn("[{}] Failed to process publish msg [{}][{}]", sessionId, topicName, msgId, e); |
|
|
// log.warn("[{}] Failed to process publish msg [{}][{}]", sessionId, topicName, msgId, e);
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
private void processDevicePublish(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg, String topicName, int msgId) { |
|
|
// private void processDevicePublish(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg, String topicName, int msgId) {
|
|
|
AdaptorToSessionActorMsg msg = null; |
|
|
// AdaptorToSessionActorMsg msg = null;
|
|
|
try { |
|
|
// try {
|
|
|
if (topicName.equals(DEVICE_TELEMETRY_TOPIC)) { |
|
|
// if (topicName.equals(DEVICE_TELEMETRY_TOPIC)) {
|
|
|
msg = adaptor.convertToActorMsg(deviceSessionCtx, POST_TELEMETRY_REQUEST, mqttMsg); |
|
|
// msg = adaptor.convertToActorMsg(deviceSessionCtx, POST_TELEMETRY_REQUEST, mqttMsg);
|
|
|
} else if (topicName.equals(DEVICE_ATTRIBUTES_TOPIC)) { |
|
|
// } else if (topicName.equals(DEVICE_ATTRIBUTES_TOPIC)) {
|
|
|
msg = adaptor.convertToActorMsg(deviceSessionCtx, POST_ATTRIBUTES_REQUEST, mqttMsg); |
|
|
// msg = adaptor.convertToActorMsg(deviceSessionCtx, POST_ATTRIBUTES_REQUEST, mqttMsg);
|
|
|
} else if (topicName.startsWith(DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX)) { |
|
|
// } else if (topicName.startsWith(DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX)) {
|
|
|
msg = adaptor.convertToActorMsg(deviceSessionCtx, GET_ATTRIBUTES_REQUEST, mqttMsg); |
|
|
// msg = adaptor.convertToActorMsg(deviceSessionCtx, GET_ATTRIBUTES_REQUEST, mqttMsg);
|
|
|
if (msgId >= 0) { |
|
|
// if (msgId >= 0) {
|
|
|
ctx.writeAndFlush(createMqttPubAckMsg(msgId)); |
|
|
// ctx.writeAndFlush(createMqttPubAckMsg(msgId));
|
|
|
} |
|
|
// }
|
|
|
} else if (topicName.startsWith(DEVICE_RPC_RESPONSE_TOPIC)) { |
|
|
// } else if (topicName.startsWith(DEVICE_RPC_RESPONSE_TOPIC)) {
|
|
|
msg = adaptor.convertToActorMsg(deviceSessionCtx, TO_DEVICE_RPC_RESPONSE, mqttMsg); |
|
|
// msg = adaptor.convertToActorMsg(deviceSessionCtx, TO_DEVICE_RPC_RESPONSE, mqttMsg);
|
|
|
if (msgId >= 0) { |
|
|
// if (msgId >= 0) {
|
|
|
ctx.writeAndFlush(createMqttPubAckMsg(msgId)); |
|
|
// ctx.writeAndFlush(createMqttPubAckMsg(msgId));
|
|
|
} |
|
|
// }
|
|
|
} else if (topicName.startsWith(DEVICE_RPC_REQUESTS_TOPIC)) { |
|
|
// } else if (topicName.startsWith(DEVICE_RPC_REQUESTS_TOPIC)) {
|
|
|
msg = adaptor.convertToActorMsg(deviceSessionCtx, TO_SERVER_RPC_REQUEST, mqttMsg); |
|
|
// msg = adaptor.convertToActorMsg(deviceSessionCtx, TO_SERVER_RPC_REQUEST, mqttMsg);
|
|
|
if (msgId >= 0) { |
|
|
// if (msgId >= 0) {
|
|
|
ctx.writeAndFlush(createMqttPubAckMsg(msgId)); |
|
|
// ctx.writeAndFlush(createMqttPubAckMsg(msgId));
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
} catch (AdaptorException e) { |
|
|
// } catch (AdaptorException e) {
|
|
|
log.warn("[{}] Failed to process publish msg [{}][{}]", sessionId, topicName, msgId, e); |
|
|
// log.warn("[{}] Failed to process publish msg [{}][{}]", sessionId, topicName, msgId, e);
|
|
|
} |
|
|
// }
|
|
|
if (msg != null) { |
|
|
// if (msg != null) {
|
|
|
processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg)); |
|
|
// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
|
|
} else { |
|
|
// } else {
|
|
|
log.info("[{}] Closing current session due to invalid publish msg [{}][{}]", sessionId, topicName, msgId); |
|
|
// log.info("[{}] Closing current session due to invalid publish msg [{}][{}]", sessionId, topicName, msgId);
|
|
|
ctx.close(); |
|
|
// ctx.close();
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
private void processSubscribe(ChannelHandlerContext ctx, MqttSubscribeMessage mqttMsg) { |
|
|
// private void processSubscribe(ChannelHandlerContext ctx, MqttSubscribeMessage mqttMsg) {
|
|
|
if (!checkConnected(ctx)) { |
|
|
// if (!checkConnected(ctx)) {
|
|
|
return; |
|
|
// return;
|
|
|
} |
|
|
// }
|
|
|
log.trace("[{}] Processing subscription [{}]!", sessionId, mqttMsg.variableHeader().messageId()); |
|
|
// log.trace("[{}] Processing subscription [{}]!", sessionId, mqttMsg.variableHeader().messageId());
|
|
|
List<Integer> grantedQoSList = new ArrayList<>(); |
|
|
// List<Integer> grantedQoSList = new ArrayList<>();
|
|
|
for (MqttTopicSubscription subscription : mqttMsg.payload().topicSubscriptions()) { |
|
|
// for (MqttTopicSubscription subscription : mqttMsg.payload().topicSubscriptions()) {
|
|
|
String topic = subscription.topicName(); |
|
|
// String topic = subscription.topicName();
|
|
|
MqttQoS reqQoS = subscription.qualityOfService(); |
|
|
// MqttQoS reqQoS = subscription.qualityOfService();
|
|
|
try { |
|
|
// try {
|
|
|
switch (topic) { |
|
|
// switch (topic) {
|
|
|
case DEVICE_ATTRIBUTES_TOPIC: { |
|
|
// case DEVICE_ATTRIBUTES_TOPIC: {
|
|
|
AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, SUBSCRIBE_ATTRIBUTES_REQUEST, mqttMsg); |
|
|
// AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, SUBSCRIBE_ATTRIBUTES_REQUEST, mqttMsg);
|
|
|
processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg)); |
|
|
// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
|
|
registerSubQoS(topic, grantedQoSList, reqQoS); |
|
|
// registerSubQoS(topic, grantedQoSList, reqQoS);
|
|
|
break; |
|
|
// break;
|
|
|
} |
|
|
// }
|
|
|
case DEVICE_RPC_REQUESTS_SUB_TOPIC: { |
|
|
// case DEVICE_RPC_REQUESTS_SUB_TOPIC: {
|
|
|
AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, SUBSCRIBE_RPC_COMMANDS_REQUEST, mqttMsg); |
|
|
// AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, SUBSCRIBE_RPC_COMMANDS_REQUEST, mqttMsg);
|
|
|
processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg)); |
|
|
// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
|
|
registerSubQoS(topic, grantedQoSList, reqQoS); |
|
|
// registerSubQoS(topic, grantedQoSList, reqQoS);
|
|
|
break; |
|
|
// break;
|
|
|
} |
|
|
// }
|
|
|
case DEVICE_RPC_RESPONSE_SUB_TOPIC: |
|
|
// case DEVICE_RPC_RESPONSE_SUB_TOPIC:
|
|
|
case GATEWAY_ATTRIBUTES_TOPIC: |
|
|
// case GATEWAY_ATTRIBUTES_TOPIC:
|
|
|
case GATEWAY_RPC_TOPIC: |
|
|
// case GATEWAY_RPC_TOPIC:
|
|
|
registerSubQoS(topic, grantedQoSList, reqQoS); |
|
|
// registerSubQoS(topic, grantedQoSList, reqQoS);
|
|
|
break; |
|
|
// break;
|
|
|
case DEVICE_ATTRIBUTES_RESPONSES_TOPIC: |
|
|
// case DEVICE_ATTRIBUTES_RESPONSES_TOPIC:
|
|
|
deviceSessionCtx.setAllowAttributeResponses(); |
|
|
// deviceSessionCtx.setAllowAttributeResponses();
|
|
|
registerSubQoS(topic, grantedQoSList, reqQoS); |
|
|
// registerSubQoS(topic, grantedQoSList, reqQoS);
|
|
|
break; |
|
|
// break;
|
|
|
default: |
|
|
// default:
|
|
|
log.warn("[{}] Failed to subscribe to [{}][{}]", sessionId, topic, reqQoS); |
|
|
// log.warn("[{}] Failed to subscribe to [{}][{}]", sessionId, topic, reqQoS);
|
|
|
grantedQoSList.add(FAILURE.value()); |
|
|
// grantedQoSList.add(FAILURE.value());
|
|
|
break; |
|
|
// break;
|
|
|
} |
|
|
// }
|
|
|
} catch (AdaptorException e) { |
|
|
// } catch (AdaptorException e) {
|
|
|
log.warn("[{}] Failed to subscribe to [{}][{}]", sessionId, topic, reqQoS); |
|
|
// log.warn("[{}] Failed to subscribe to [{}][{}]", sessionId, topic, reqQoS);
|
|
|
grantedQoSList.add(FAILURE.value()); |
|
|
// grantedQoSList.add(FAILURE.value());
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
ctx.writeAndFlush(createSubAckMessage(mqttMsg.variableHeader().messageId(), grantedQoSList)); |
|
|
// ctx.writeAndFlush(createSubAckMessage(mqttMsg.variableHeader().messageId(), grantedQoSList));
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
private void registerSubQoS(String topic, List<Integer> grantedQoSList, MqttQoS reqQoS) { |
|
|
// private void registerSubQoS(String topic, List<Integer> grantedQoSList, MqttQoS reqQoS) {
|
|
|
grantedQoSList.add(getMinSupportedQos(reqQoS)); |
|
|
// grantedQoSList.add(getMinSupportedQos(reqQoS));
|
|
|
mqttQoSMap.put(topic, getMinSupportedQos(reqQoS)); |
|
|
// mqttQoSMap.put(topic, getMinSupportedQos(reqQoS));
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
private void processUnsubscribe(ChannelHandlerContext ctx, MqttUnsubscribeMessage mqttMsg) { |
|
|
// private void processUnsubscribe(ChannelHandlerContext ctx, MqttUnsubscribeMessage mqttMsg) {
|
|
|
if (!checkConnected(ctx)) { |
|
|
// if (!checkConnected(ctx)) {
|
|
|
return; |
|
|
// return;
|
|
|
} |
|
|
// }
|
|
|
log.trace("[{}] Processing subscription [{}]!", sessionId, mqttMsg.variableHeader().messageId()); |
|
|
// log.trace("[{}] Processing subscription [{}]!", sessionId, mqttMsg.variableHeader().messageId());
|
|
|
for (String topicName : mqttMsg.payload().topics()) { |
|
|
// for (String topicName : mqttMsg.payload().topics()) {
|
|
|
mqttQoSMap.remove(topicName); |
|
|
// mqttQoSMap.remove(topicName);
|
|
|
try { |
|
|
// try {
|
|
|
switch (topicName) { |
|
|
// switch (topicName) {
|
|
|
case DEVICE_ATTRIBUTES_TOPIC: { |
|
|
// case DEVICE_ATTRIBUTES_TOPIC: {
|
|
|
AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, UNSUBSCRIBE_ATTRIBUTES_REQUEST, mqttMsg); |
|
|
// AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, UNSUBSCRIBE_ATTRIBUTES_REQUEST, mqttMsg);
|
|
|
processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg)); |
|
|
// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
|
|
break; |
|
|
// break;
|
|
|
} |
|
|
// }
|
|
|
case DEVICE_RPC_REQUESTS_SUB_TOPIC: { |
|
|
// case DEVICE_RPC_REQUESTS_SUB_TOPIC: {
|
|
|
AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, UNSUBSCRIBE_RPC_COMMANDS_REQUEST, mqttMsg); |
|
|
// AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, UNSUBSCRIBE_RPC_COMMANDS_REQUEST, mqttMsg);
|
|
|
processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg)); |
|
|
// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
|
|
break; |
|
|
// break;
|
|
|
} |
|
|
// }
|
|
|
case DEVICE_ATTRIBUTES_RESPONSES_TOPIC: |
|
|
// case DEVICE_ATTRIBUTES_RESPONSES_TOPIC:
|
|
|
deviceSessionCtx.setDisallowAttributeResponses(); |
|
|
// deviceSessionCtx.setDisallowAttributeResponses();
|
|
|
break; |
|
|
// break;
|
|
|
} |
|
|
// }
|
|
|
} catch (AdaptorException e) { |
|
|
// } catch (AdaptorException e) {
|
|
|
log.warn("[{}] Failed to process unsubscription [{}] to [{}]", sessionId, mqttMsg.variableHeader().messageId(), topicName); |
|
|
// log.warn("[{}] Failed to process unsubscription [{}] to [{}]", sessionId, mqttMsg.variableHeader().messageId(), topicName);
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
ctx.writeAndFlush(createUnSubAckMessage(mqttMsg.variableHeader().messageId())); |
|
|
// ctx.writeAndFlush(createUnSubAckMessage(mqttMsg.variableHeader().messageId()));
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
private MqttMessage createUnSubAckMessage(int msgId) { |
|
|
// private MqttMessage createUnSubAckMessage(int msgId) {
|
|
|
MqttFixedHeader mqttFixedHeader = |
|
|
// MqttFixedHeader mqttFixedHeader =
|
|
|
new MqttFixedHeader(UNSUBACK, false, AT_LEAST_ONCE, false, 0); |
|
|
// new MqttFixedHeader(UNSUBACK, false, AT_LEAST_ONCE, false, 0);
|
|
|
MqttMessageIdVariableHeader mqttMessageIdVariableHeader = MqttMessageIdVariableHeader.from(msgId); |
|
|
// MqttMessageIdVariableHeader mqttMessageIdVariableHeader = MqttMessageIdVariableHeader.from(msgId);
|
|
|
return new MqttMessage(mqttFixedHeader, mqttMessageIdVariableHeader); |
|
|
// return new MqttMessage(mqttFixedHeader, mqttMessageIdVariableHeader);
|
|
|
} |
|
|
// }
|
|
|
|
|
|
|
|
|
private void processConnect(ChannelHandlerContext ctx, MqttConnectMessage msg) { |
|
|
private void processConnect(ChannelHandlerContext ctx, MqttConnectMessage msg) { |
|
|
log.info("[{}] Processing connect msg for client: {}!", sessionId, msg.payload().clientIdentifier()); |
|
|
log.info("[{}] Processing connect msg for client: {}!", sessionId, msg.payload().clientIdentifier()); |
|
|
@ -333,36 +378,58 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
|
|
if (StringUtils.isEmpty(userName)) { |
|
|
if (StringUtils.isEmpty(userName)) { |
|
|
ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD)); |
|
|
ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD)); |
|
|
ctx.close(); |
|
|
ctx.close(); |
|
|
} else if (!deviceSessionCtx.login(new DeviceTokenCredentials(msg.payload().userName()))) { |
|
|
|
|
|
ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_REFUSED_NOT_AUTHORIZED)); |
|
|
|
|
|
ctx.close(); |
|
|
|
|
|
} else { |
|
|
} else { |
|
|
ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_ACCEPTED)); |
|
|
transportService.process(ValidateDeviceTokenRequestMsg.newBuilder().setToken(userName).build(), |
|
|
connected = true; |
|
|
new TransportServiceCallback<ValidateDeviceTokenResponseMsg>() { |
|
|
processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), |
|
|
@Override |
|
|
new BasicAdaptorToSessionActorMsg(deviceSessionCtx, new SessionOpenMsg()))); |
|
|
public void onSuccess(ValidateDeviceTokenResponseMsg msg) { |
|
|
checkGatewaySession(); |
|
|
if (!msg.hasDeviceInfo()) { |
|
|
|
|
|
ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_REFUSED_NOT_AUTHORIZED)); |
|
|
|
|
|
ctx.close(); |
|
|
|
|
|
} else { |
|
|
|
|
|
ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_ACCEPTED)); |
|
|
|
|
|
deviceSessionCtx.setDeviceInfo(deviceSessionCtx.getDeviceInfo()); |
|
|
|
|
|
transportService.process(getSessionEventMsg(SessionEvent.OPEN), null); |
|
|
|
|
|
checkGatewaySession(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
public void onError(Exception e) { |
|
|
|
|
|
log.trace("[{}] Failed to process credentials: {}", address, userName, e); |
|
|
|
|
|
ctx.writeAndFlush(createMqttConnAckMsg(MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE)); |
|
|
|
|
|
ctx.close(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected SessionEventMsg getSessionEventMsg(SessionEvent event) { |
|
|
|
|
|
return SessionEventMsg.newBuilder() |
|
|
|
|
|
.setSessionInfo(sessionInfo) |
|
|
|
|
|
.setDeviceIdMSB(deviceSessionCtx.getDeviceIdMSB()) |
|
|
|
|
|
.setDeviceIdLSB(deviceSessionCtx.getDeviceIdLSB()) |
|
|
|
|
|
.setEvent(event).build(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private void processX509CertConnect(ChannelHandlerContext ctx, X509Certificate cert) { |
|
|
private void processX509CertConnect(ChannelHandlerContext ctx, X509Certificate cert) { |
|
|
try { |
|
|
// try {
|
|
|
String strCert = SslUtil.getX509CertificateString(cert); |
|
|
// String strCert = SslUtil.getX509CertificateString(cert);
|
|
|
String sha3Hash = EncryptionUtil.getSha3Hash(strCert); |
|
|
// String sha3Hash = EncryptionUtil.getSha3Hash(strCert);
|
|
|
if (deviceSessionCtx.login(new DeviceX509Credentials(sha3Hash))) { |
|
|
// if (deviceSessionCtx.login(new DeviceX509Credentials(sha3Hash))) {
|
|
|
ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_ACCEPTED)); |
|
|
// ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_ACCEPTED));
|
|
|
connected = true; |
|
|
// connected = true;
|
|
|
processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), |
|
|
// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(),
|
|
|
new BasicAdaptorToSessionActorMsg(deviceSessionCtx, new SessionOpenMsg()))); |
|
|
// new BasicAdaptorToSessionActorMsg(deviceSessionCtx, new SessionOpenMsg())));
|
|
|
checkGatewaySession(); |
|
|
// checkGatewaySession();
|
|
|
} else { |
|
|
// } else {
|
|
|
ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_REFUSED_NOT_AUTHORIZED)); |
|
|
// ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_REFUSED_NOT_AUTHORIZED));
|
|
|
ctx.close(); |
|
|
// ctx.close();
|
|
|
} |
|
|
// }
|
|
|
} catch (Exception e) { |
|
|
// } catch (Exception e) {
|
|
|
ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_REFUSED_NOT_AUTHORIZED)); |
|
|
// ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_REFUSED_NOT_AUTHORIZED));
|
|
|
ctx.close(); |
|
|
// ctx.close();
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private X509Certificate getX509Certificate() { |
|
|
private X509Certificate getX509Certificate() { |
|
|
@ -380,8 +447,8 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
|
|
|
|
|
|
|
|
private void processDisconnect(ChannelHandlerContext ctx) { |
|
|
private void processDisconnect(ChannelHandlerContext ctx) { |
|
|
ctx.close(); |
|
|
ctx.close(); |
|
|
if (connected) { |
|
|
if (deviceSessionCtx.isConnected()) { |
|
|
processor.process(SessionCloseMsg.onDisconnect(deviceSessionCtx.getSessionId())); |
|
|
transportService.process(getSessionEventMsg(SessionEvent.CLOSED), null); |
|
|
if (gatewaySessionCtx != null) { |
|
|
if (gatewaySessionCtx != null) { |
|
|
gatewaySessionCtx.onGatewayDisconnect(); |
|
|
gatewaySessionCtx.onGatewayDisconnect(); |
|
|
} |
|
|
} |
|
|
@ -428,7 +495,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private boolean checkConnected(ChannelHandlerContext ctx) { |
|
|
private boolean checkConnected(ChannelHandlerContext ctx) { |
|
|
if (connected) { |
|
|
if (deviceSessionCtx.isConnected()) { |
|
|
return true; |
|
|
return true; |
|
|
} else { |
|
|
} else { |
|
|
log.info("[{}] Closing current session due to invalid msg order [{}][{}]", sessionId); |
|
|
log.info("[{}] Closing current session due to invalid msg order [{}][{}]", sessionId); |
|
|
@ -438,18 +505,22 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private void checkGatewaySession() { |
|
|
private void checkGatewaySession() { |
|
|
Device device = deviceSessionCtx.getDevice(); |
|
|
DeviceInfoProto device = deviceSessionCtx.getDeviceInfo(); |
|
|
JsonNode infoNode = device.getAdditionalInfo(); |
|
|
try { |
|
|
if (infoNode != null) { |
|
|
JsonNode infoNode = context.getMapper().readTree(device.getAdditionalInfo()); |
|
|
JsonNode gatewayNode = infoNode.get("gateway"); |
|
|
if (infoNode != null) { |
|
|
if (gatewayNode != null && gatewayNode.asBoolean()) { |
|
|
JsonNode gatewayNode = infoNode.get("gateway"); |
|
|
gatewaySessionCtx = new GatewaySessionCtx(processor, deviceService, authService, relationService, deviceSessionCtx); |
|
|
if (gatewayNode != null && gatewayNode.asBoolean()) { |
|
|
|
|
|
gatewaySessionCtx = new GatewaySessionCtx(deviceSessionCtx); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} catch (IOException e) { |
|
|
|
|
|
log.trace("[{}][{}] Failed to fetch device additional info", sessionId, device.getDeviceName(), e); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public void operationComplete(Future<? super Void> future) throws Exception { |
|
|
public void operationComplete(Future<? super Void> future) throws Exception { |
|
|
processor.process(SessionCloseMsg.onError(deviceSessionCtx.getSessionId())); |
|
|
transportService.process(getSessionEventMsg(SessionEvent.CLOSED), null); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|