/*
|
* Copyright 2014 The Netty Project
|
*
|
* The Netty Project licenses this file to you under the Apache License,
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
* with the License. You may obtain a copy of the License at:
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
* License for the specific language governing permissions and limitations
|
* under the License.
|
*/
|
|
package chat.server.moquette;
|
|
import chat.server.moquette.message.MqttFixedHeader;
|
import chat.server.moquette.message.MqttQoS;
|
import io.netty.handler.codec.DecoderException;
|
|
final class MqttCodecUtil {
|
|
private static final char[] TOPIC_WILDCARDS = {'#', '+'};
|
private static final int MIN_CLIENT_ID_LENGTH = 1;
|
private static final int MAX_CLIENT_ID_LENGTH = 23;
|
|
static boolean isValidPublishTopicName(String topicName) {
|
// publish topic name must not contain any wildcard
|
for (char c : TOPIC_WILDCARDS) {
|
if (topicName.indexOf(c) >= 0) {
|
return false;
|
}
|
}
|
return true;
|
}
|
|
static boolean isValidMessageId(int messageId) {
|
return messageId != 0;
|
}
|
|
public static boolean isValidClientId(MqttVersion mqttVersion, String clientId) {
|
if (mqttVersion == MqttVersion.MQTT_3_1) {
|
return clientId != null && clientId.length() >= MIN_CLIENT_ID_LENGTH &&
|
clientId.length() <= MAX_CLIENT_ID_LENGTH;
|
}
|
if (mqttVersion.protocolLevel() >= MqttVersion.MQTT_3_1_1.protocolLevel()) {
|
// In 3.1.3.1 Client Identifier of MQTT 3.1.1 specification, The Server MAY allow ClientId’s
|
// that contain more than 23 encoded bytes. And, The Server MAY allow zero-length ClientId.
|
return clientId != null;
|
}
|
throw new IllegalArgumentException(mqttVersion + " is unknown mqtt version");
|
}
|
|
static MqttFixedHeader validateFixedHeader(MqttFixedHeader mqttFixedHeader) {
|
switch (mqttFixedHeader.messageType()) {
|
case PUBREL:
|
case SUBSCRIBE:
|
case UNSUBSCRIBE:
|
if (mqttFixedHeader.qosLevel() != MqttQoS.AT_LEAST_ONCE) {
|
throw new DecoderException(mqttFixedHeader.messageType().name() + " message must have QoS 1");
|
}
|
default:
|
return mqttFixedHeader;
|
}
|
}
|
|
static MqttFixedHeader resetUnusedFields(MqttFixedHeader mqttFixedHeader) {
|
switch (mqttFixedHeader.messageType()) {
|
case CONNECT:
|
case CONNACK:
|
case PUBACK:
|
case PUBREC:
|
case PUBCOMP:
|
case SUBACK:
|
case UNSUBACK:
|
case PINGREQ:
|
case PINGRESP:
|
//case DISCONNECT:
|
if (mqttFixedHeader.isDup() ||
|
mqttFixedHeader.qosLevel() != MqttQoS.AT_MOST_ONCE ||
|
mqttFixedHeader.isRetain()) {
|
return new MqttFixedHeader(
|
mqttFixedHeader.messageType(),
|
false,
|
MqttQoS.AT_MOST_ONCE,
|
false,
|
mqttFixedHeader.remainingLength());
|
}
|
return mqttFixedHeader;
|
case PUBREL:
|
case SUBSCRIBE:
|
case UNSUBSCRIBE:
|
if (mqttFixedHeader.isRetain()) {
|
return new MqttFixedHeader(
|
mqttFixedHeader.messageType(),
|
mqttFixedHeader.isDup(),
|
mqttFixedHeader.qosLevel(),
|
false,
|
mqttFixedHeader.remainingLength());
|
}
|
return mqttFixedHeader;
|
default:
|
return mqttFixedHeader;
|
}
|
}
|
|
private MqttCodecUtil() { }
|
}
|