-
Notifications
You must be signed in to change notification settings - Fork 534
/
topic.go
90 lines (78 loc) · 2.78 KB
/
topic.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
* Copyright (c) 2021 IBM Corp and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Seth Hoenig
* Allan Stockdill-Mander
* Mike Robertson
*/
package mqtt
import (
"errors"
"strings"
)
// ErrInvalidQos is the error returned when an packet is to be sent
// with an invalid Qos value
var ErrInvalidQos = errors.New("invalid QoS")
// ErrInvalidTopicEmptyString is the error returned when a topic string
// is passed in that is 0 length
var ErrInvalidTopicEmptyString = errors.New("invalid Topic; empty string")
// ErrInvalidTopicMultilevel is the error returned when a topic string
// is passed in that has the multi level wildcard in any position but
// the last
var ErrInvalidTopicMultilevel = errors.New("invalid Topic; multi-level wildcard must be last level")
// Topic Names and Topic Filters
// The MQTT v3.1.1 spec clarifies a number of ambiguities with regard
// to the validity of Topic strings.
// - A Topic must be between 1 and 65535 bytes.
// - A Topic is case sensitive.
// - A Topic may contain whitespace.
// - A Topic containing a leading forward slash is different than a Topic without.
// - A Topic may be "/" (two levels, both empty string).
// - A Topic must be UTF-8 encoded.
// - A Topic may contain any number of levels.
// - A Topic may contain an empty level (two forward slashes in a row).
// - A TopicName may not contain a wildcard.
// - A TopicFilter may only have a # (multi-level) wildcard as the last level.
// - A TopicFilter may contain any number of + (single-level) wildcards.
// - A TopicFilter with a # will match the absence of a level
// Example: a subscription to "foo/#" will match messages published to "foo".
func validateSubscribeMap(subs map[string]byte) ([]string, []byte, error) {
if len(subs) == 0 {
return nil, nil, errors.New("invalid subscription; subscribe map must not be empty")
}
var topics []string
var qoss []byte
for topic, qos := range subs {
if err := validateTopicAndQos(topic, qos); err != nil {
return nil, nil, err
}
topics = append(topics, topic)
qoss = append(qoss, qos)
}
return topics, qoss, nil
}
func validateTopicAndQos(topic string, qos byte) error {
if len(topic) == 0 {
return ErrInvalidTopicEmptyString
}
levels := strings.Split(topic, "/")
for i, level := range levels {
if level == "#" && i != len(levels)-1 {
return ErrInvalidTopicMultilevel
}
}
if qos > 2 {
return ErrInvalidQos
}
return nil
}