View Javadoc
1   /*
2    * Copyright 2014 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  
17  package io.netty.handler.codec.mqtt;
18  
19  import io.netty.handler.codec.DecoderException;
20  
21  final class MqttCodecUtil {
22  
23      private static final char[] TOPIC_WILDCARDS = {'#', '+'};
24      private static final int MIN_CLIENT_ID_LENGTH = 1;
25      private static final int MAX_CLIENT_ID_LENGTH = 23;
26  
27      static boolean isValidPublishTopicName(String topicName) {
28          // publish topic name must not contain any wildcard
29          for (char c : TOPIC_WILDCARDS) {
30              if (topicName.indexOf(c) >= 0) {
31                  return false;
32              }
33          }
34          return true;
35      }
36  
37      static boolean isValidMessageId(int messageId) {
38          return messageId != 0;
39      }
40  
41      static boolean isValidClientId(MqttVersion mqttVersion, String clientId) {
42          if (mqttVersion == MqttVersion.MQTT_3_1) {
43              return clientId != null && clientId.length() >= MIN_CLIENT_ID_LENGTH &&
44                  clientId.length() <= MAX_CLIENT_ID_LENGTH;
45          }
46          if (mqttVersion == MqttVersion.MQTT_3_1_1) {
47              // In 3.1.3.1 Client Identifier of MQTT 3.1.1 specification, The Server MAY allow ClientId’s
48              // that contain more than 23 encoded bytes. And, The Server MAY allow zero-length ClientId.
49              return clientId != null;
50          }
51          throw new IllegalArgumentException(mqttVersion + " is unknown mqtt version");
52      }
53  
54      static MqttFixedHeader validateFixedHeader(MqttFixedHeader mqttFixedHeader) {
55          switch (mqttFixedHeader.messageType()) {
56              case PUBREL:
57              case SUBSCRIBE:
58              case UNSUBSCRIBE:
59                  if (mqttFixedHeader.qosLevel() != MqttQoS.AT_LEAST_ONCE) {
60                      throw new DecoderException(mqttFixedHeader.messageType().name() + " message must have QoS 1");
61                  }
62              default:
63                  return mqttFixedHeader;
64          }
65      }
66  
67      static MqttFixedHeader resetUnusedFields(MqttFixedHeader mqttFixedHeader) {
68          switch (mqttFixedHeader.messageType()) {
69              case CONNECT:
70              case CONNACK:
71              case PUBACK:
72              case PUBREC:
73              case PUBCOMP:
74              case SUBACK:
75              case UNSUBACK:
76              case PINGREQ:
77              case PINGRESP:
78              case DISCONNECT:
79                  if (mqttFixedHeader.isDup() ||
80                          mqttFixedHeader.qosLevel() != MqttQoS.AT_MOST_ONCE ||
81                          mqttFixedHeader.isRetain()) {
82                      return new MqttFixedHeader(
83                              mqttFixedHeader.messageType(),
84                              false,
85                              MqttQoS.AT_MOST_ONCE,
86                              false,
87                              mqttFixedHeader.remainingLength());
88                  }
89                  return mqttFixedHeader;
90              case PUBREL:
91              case SUBSCRIBE:
92              case UNSUBSCRIBE:
93                  if (mqttFixedHeader.isRetain()) {
94                      return new MqttFixedHeader(
95                              mqttFixedHeader.messageType(),
96                              mqttFixedHeader.isDup(),
97                              mqttFixedHeader.qosLevel(),
98                              false,
99                              mqttFixedHeader.remainingLength());
100                 }
101                 return mqttFixedHeader;
102             default:
103                 return mqttFixedHeader;
104         }
105     }
106 
107     private MqttCodecUtil() { }
108 }