123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- /*
- * 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
- }
|