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          } else if (mqttVersion == MqttVersion.MQTT_3_1_1) {
46              // In 3.1.3.1 Client Identifier of MQTT 3.1.1 specification, The Server MAY allow ClientId’s
47              // that contain more than 23 encoded bytes. And, The Server MAY allow zero-length ClientId.
48              return clientId != null;
49          }
50          throw new IllegalArgumentException(mqttVersion + " is unknown mqtt version");
51      }
52  
53      static MqttFixedHeader validateFixedHeader(MqttFixedHeader mqttFixedHeader) {
54          switch (mqttFixedHeader.messageType()) {
55              case PUBREL:
56              case SUBSCRIBE:
57              case UNSUBSCRIBE:
58                  if (mqttFixedHeader.qosLevel() != MqttQoS.AT_LEAST_ONCE) {
59                      throw new DecoderException(mqttFixedHeader.messageType().name() + " message must have QoS 1");
60                  }
61              default:
62                  return mqttFixedHeader;
63          }
64      }
65  
66      static MqttFixedHeader resetUnusedFields(MqttFixedHeader mqttFixedHeader) {
67          switch (mqttFixedHeader.messageType()) {
68              case CONNECT:
69              case CONNACK:
70              case PUBACK:
71              case PUBREC:
72              case PUBCOMP:
73              case SUBACK:
74              case UNSUBACK:
75              case PINGREQ:
76              case PINGRESP:
77              case DISCONNECT:
78                  if (mqttFixedHeader.isDup() ||
79                          mqttFixedHeader.qosLevel() != MqttQoS.AT_MOST_ONCE ||
80                          mqttFixedHeader.isRetain()) {
81                      return new MqttFixedHeader(
82                              mqttFixedHeader.messageType(),
83                              false,
84                              MqttQoS.AT_MOST_ONCE,
85                              false,
86                              mqttFixedHeader.remainingLength());
87                  }
88                  return mqttFixedHeader;
89              case PUBREL:
90              case SUBSCRIBE:
91              case UNSUBSCRIBE:
92                  if (mqttFixedHeader.isRetain()) {
93                      return new MqttFixedHeader(
94                              mqttFixedHeader.messageType(),
95                              mqttFixedHeader.isDup(),
96                              mqttFixedHeader.qosLevel(),
97                              false,
98                              mqttFixedHeader.remainingLength());
99                  }
100                 return mqttFixedHeader;
101             default:
102                 return mqttFixedHeader;
103         }
104     }
105 
106     private MqttCodecUtil() { }
107 }