mirror of
				https://github.com/mochi-mqtt/server.git
				synced 2025-10-31 03:26:28 +08:00 
			
		
		
		
	 1574443981
			
		
	
	1574443981
	
	
	
		
			
			* Another code implementation for Inline Client Subscriptions. * Added a few test cases. * Changed the return value types of Server.Unsubscribe() and Subscribe() to boolean. * Implementing the delivery of retained messages and supporting multiple callbacks per topic using different inline client IDs. * Added validation checks for the legality of the inline client id during Subscribe and Unsubscribe. * Added validation checks for the legality of the client during Subscribe and Unsubscribe. * Fixed the TestServerSubscribe/invalid_client_id test case failure. * Add Server.inlineClient and Temporarily removing test cases for better code review readability. * Using server.inlineClient in server.InjectPacket(). * After unsubscribing, if there are other subscriptions in particle.inlineSubscriptions, particle cannot be deleted. * Add comments to particle.inlineSubscriptions and modify to return ErrTopicFilterInvalid when the topic is invalid during subscription. * Fixed some test case failures caused by adding inlineClient to the server. * More test cases have been added. * Optimization of test case code. * Modify server.go: When used as a publisher, treat the qos of inline client-published messages as 0. * Resolve conflict.
		
			
				
	
	
		
			150 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // SPDX-License-Identifier: MIT
 | |
| // SPDX-FileCopyrightText: 2022 mochi-mqtt, mochi-co
 | |
| // SPDX-FileContributor: mochi-co
 | |
| 
 | |
| package packets
 | |
| 
 | |
| // Code contains a reason code and reason string for a response.
 | |
| type Code struct {
 | |
| 	Reason string
 | |
| 	Code   byte
 | |
| }
 | |
| 
 | |
| // String returns the readable reason for a code.
 | |
| func (c Code) String() string {
 | |
| 	return c.Reason
 | |
| }
 | |
| 
 | |
| // Error returns the readable reason for a code.
 | |
| func (c Code) Error() string {
 | |
| 	return c.Reason
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	// QosCodes indicates the reason codes for each Qos byte.
 | |
| 	QosCodes = map[byte]Code{
 | |
| 		0: CodeGrantedQos0,
 | |
| 		1: CodeGrantedQos1,
 | |
| 		2: CodeGrantedQos2,
 | |
| 	}
 | |
| 
 | |
| 	CodeSuccessIgnore                         = Code{Code: 0x00, Reason: "ignore packet"}
 | |
| 	CodeSuccess                               = Code{Code: 0x00, Reason: "success"}
 | |
| 	CodeDisconnect                            = Code{Code: 0x00, Reason: "disconnected"}
 | |
| 	CodeGrantedQos0                           = Code{Code: 0x00, Reason: "granted qos 0"}
 | |
| 	CodeGrantedQos1                           = Code{Code: 0x01, Reason: "granted qos 1"}
 | |
| 	CodeGrantedQos2                           = Code{Code: 0x02, Reason: "granted qos 2"}
 | |
| 	CodeDisconnectWillMessage                 = Code{Code: 0x04, Reason: "disconnect with will message"}
 | |
| 	CodeNoMatchingSubscribers                 = Code{Code: 0x10, Reason: "no matching subscribers"}
 | |
| 	CodeNoSubscriptionExisted                 = Code{Code: 0x11, Reason: "no subscription existed"}
 | |
| 	CodeContinueAuthentication                = Code{Code: 0x18, Reason: "continue authentication"}
 | |
| 	CodeReAuthenticate                        = Code{Code: 0x19, Reason: "re-authenticate"}
 | |
| 	ErrUnspecifiedError                       = Code{Code: 0x80, Reason: "unspecified error"}
 | |
| 	ErrMalformedPacket                        = Code{Code: 0x81, Reason: "malformed packet"}
 | |
| 	ErrMalformedProtocolName                  = Code{Code: 0x81, Reason: "malformed packet: protocol name"}
 | |
| 	ErrMalformedProtocolVersion               = Code{Code: 0x81, Reason: "malformed packet: protocol version"}
 | |
| 	ErrMalformedFlags                         = Code{Code: 0x81, Reason: "malformed packet: flags"}
 | |
| 	ErrMalformedKeepalive                     = Code{Code: 0x81, Reason: "malformed packet: keepalive"}
 | |
| 	ErrMalformedPacketID                      = Code{Code: 0x81, Reason: "malformed packet: packet identifier"}
 | |
| 	ErrMalformedTopic                         = Code{Code: 0x81, Reason: "malformed packet: topic"}
 | |
| 	ErrMalformedWillTopic                     = Code{Code: 0x81, Reason: "malformed packet: will topic"}
 | |
| 	ErrMalformedWillPayload                   = Code{Code: 0x81, Reason: "malformed packet: will message"}
 | |
| 	ErrMalformedUsername                      = Code{Code: 0x81, Reason: "malformed packet: username"}
 | |
| 	ErrMalformedPassword                      = Code{Code: 0x81, Reason: "malformed packet: password"}
 | |
| 	ErrMalformedQos                           = Code{Code: 0x81, Reason: "malformed packet: qos"}
 | |
| 	ErrMalformedOffsetUintOutOfRange          = Code{Code: 0x81, Reason: "malformed packet: offset uint out of range"}
 | |
| 	ErrMalformedOffsetBytesOutOfRange         = Code{Code: 0x81, Reason: "malformed packet: offset bytes out of range"}
 | |
| 	ErrMalformedOffsetByteOutOfRange          = Code{Code: 0x81, Reason: "malformed packet: offset byte out of range"}
 | |
| 	ErrMalformedOffsetBoolOutOfRange          = Code{Code: 0x81, Reason: "malformed packet: offset boolean out of range"}
 | |
| 	ErrMalformedInvalidUTF8                   = Code{Code: 0x81, Reason: "malformed packet: invalid utf-8 string"}
 | |
| 	ErrMalformedVariableByteInteger           = Code{Code: 0x81, Reason: "malformed packet: variable byte integer out of range"}
 | |
| 	ErrMalformedBadProperty                   = Code{Code: 0x81, Reason: "malformed packet: unknown property"}
 | |
| 	ErrMalformedProperties                    = Code{Code: 0x81, Reason: "malformed packet: properties"}
 | |
| 	ErrMalformedWillProperties                = Code{Code: 0x81, Reason: "malformed packet: will properties"}
 | |
| 	ErrMalformedSessionPresent                = Code{Code: 0x81, Reason: "malformed packet: session present"}
 | |
| 	ErrMalformedReasonCode                    = Code{Code: 0x81, Reason: "malformed packet: reason code"}
 | |
| 	ErrProtocolViolation                      = Code{Code: 0x82, Reason: "protocol violation"}
 | |
| 	ErrProtocolViolationProtocolName          = Code{Code: 0x82, Reason: "protocol violation: protocol name"}
 | |
| 	ErrProtocolViolationProtocolVersion       = Code{Code: 0x82, Reason: "protocol violation: protocol version"}
 | |
| 	ErrProtocolViolationReservedBit           = Code{Code: 0x82, Reason: "protocol violation: reserved bit not 0"}
 | |
| 	ErrProtocolViolationFlagNoUsername        = Code{Code: 0x82, Reason: "protocol violation: username flag set but no value"}
 | |
| 	ErrProtocolViolationFlagNoPassword        = Code{Code: 0x82, Reason: "protocol violation: password flag set but no value"}
 | |
| 	ErrProtocolViolationUsernameNoFlag        = Code{Code: 0x82, Reason: "protocol violation: username set but no flag"}
 | |
| 	ErrProtocolViolationPasswordNoFlag        = Code{Code: 0x82, Reason: "protocol violation: username set but no flag"}
 | |
| 	ErrProtocolViolationPasswordTooLong       = Code{Code: 0x82, Reason: "protocol violation: password too long"}
 | |
| 	ErrProtocolViolationUsernameTooLong       = Code{Code: 0x82, Reason: "protocol violation: username too long"}
 | |
| 	ErrProtocolViolationNoPacketID            = Code{Code: 0x82, Reason: "protocol violation: missing packet id"}
 | |
| 	ErrProtocolViolationSurplusPacketID       = Code{Code: 0x82, Reason: "protocol violation: surplus packet id"}
 | |
| 	ErrProtocolViolationQosOutOfRange         = Code{Code: 0x82, Reason: "protocol violation: qos out of range"}
 | |
| 	ErrProtocolViolationSecondConnect         = Code{Code: 0x82, Reason: "protocol violation: second connect packet"}
 | |
| 	ErrProtocolViolationZeroNonZeroExpiry     = Code{Code: 0x82, Reason: "protocol violation: non-zero expiry"}
 | |
| 	ErrProtocolViolationRequireFirstConnect   = Code{Code: 0x82, Reason: "protocol violation: first packet must be connect"}
 | |
| 	ErrProtocolViolationWillFlagNoPayload     = Code{Code: 0x82, Reason: "protocol violation: will flag no payload"}
 | |
| 	ErrProtocolViolationWillFlagSurplusRetain = Code{Code: 0x82, Reason: "protocol violation: will flag surplus retain"}
 | |
| 	ErrProtocolViolationSurplusWildcard       = Code{Code: 0x82, Reason: "protocol violation: topic contains wildcards"}
 | |
| 	ErrProtocolViolationSurplusSubID          = Code{Code: 0x82, Reason: "protocol violation: contained subscription identifier"}
 | |
| 	ErrProtocolViolationInvalidTopic          = Code{Code: 0x82, Reason: "protocol violation: invalid topic"}
 | |
| 	ErrProtocolViolationInvalidSharedNoLocal  = Code{Code: 0x82, Reason: "protocol violation: invalid shared no local"}
 | |
| 	ErrProtocolViolationNoFilters             = Code{Code: 0x82, Reason: "protocol violation: must contain at least one filter"}
 | |
| 	ErrProtocolViolationInvalidReason         = Code{Code: 0x82, Reason: "protocol violation: invalid reason"}
 | |
| 	ErrProtocolViolationOversizeSubID         = Code{Code: 0x82, Reason: "protocol violation: oversize subscription id"}
 | |
| 	ErrProtocolViolationDupNoQos              = Code{Code: 0x82, Reason: "protocol violation: dup true with no qos"}
 | |
| 	ErrProtocolViolationUnsupportedProperty   = Code{Code: 0x82, Reason: "protocol violation: unsupported property"}
 | |
| 	ErrProtocolViolationNoTopic               = Code{Code: 0x82, Reason: "protocol violation: no topic or alias"}
 | |
| 	ErrImplementationSpecificError            = Code{Code: 0x83, Reason: "implementation specific error"}
 | |
| 	ErrRejectPacket                           = Code{Code: 0x83, Reason: "packet rejected"}
 | |
| 	ErrUnsupportedProtocolVersion             = Code{Code: 0x84, Reason: "unsupported protocol version"}
 | |
| 	ErrClientIdentifierNotValid               = Code{Code: 0x85, Reason: "client identifier not valid"}
 | |
| 	ErrClientIdentifierTooLong                = Code{Code: 0x85, Reason: "client identifier too long"}
 | |
| 	ErrBadUsernameOrPassword                  = Code{Code: 0x86, Reason: "bad username or password"}
 | |
| 	ErrNotAuthorized                          = Code{Code: 0x87, Reason: "not authorized"}
 | |
| 	ErrServerUnavailable                      = Code{Code: 0x88, Reason: "server unavailable"}
 | |
| 	ErrServerBusy                             = Code{Code: 0x89, Reason: "server busy"}
 | |
| 	ErrBanned                                 = Code{Code: 0x8A, Reason: "banned"}
 | |
| 	ErrServerShuttingDown                     = Code{Code: 0x8B, Reason: "server shutting down"}
 | |
| 	ErrBadAuthenticationMethod                = Code{Code: 0x8C, Reason: "bad authentication method"}
 | |
| 	ErrKeepAliveTimeout                       = Code{Code: 0x8D, Reason: "keep alive timeout"}
 | |
| 	ErrSessionTakenOver                       = Code{Code: 0x8E, Reason: "session takeover"}
 | |
| 	ErrTopicFilterInvalid                     = Code{Code: 0x8F, Reason: "topic filter invalid"}
 | |
| 	ErrTopicNameInvalid                       = Code{Code: 0x90, Reason: "topic name invalid"}
 | |
| 	ErrPacketIdentifierInUse                  = Code{Code: 0x91, Reason: "packet identifier in use"}
 | |
| 	ErrPacketIdentifierNotFound               = Code{Code: 0x92, Reason: "packet identifier not found"}
 | |
| 	ErrReceiveMaximum                         = Code{Code: 0x93, Reason: "receive maximum exceeded"}
 | |
| 	ErrTopicAliasInvalid                      = Code{Code: 0x94, Reason: "topic alias invalid"}
 | |
| 	ErrPacketTooLarge                         = Code{Code: 0x95, Reason: "packet too large"}
 | |
| 	ErrMessageRateTooHigh                     = Code{Code: 0x96, Reason: "message rate too high"}
 | |
| 	ErrQuotaExceeded                          = Code{Code: 0x97, Reason: "quota exceeded"}
 | |
| 	ErrPendingClientWritesExceeded            = Code{Code: 0x97, Reason: "too many pending writes"}
 | |
| 	ErrAdministrativeAction                   = Code{Code: 0x98, Reason: "administrative action"}
 | |
| 	ErrPayloadFormatInvalid                   = Code{Code: 0x99, Reason: "payload format invalid"}
 | |
| 	ErrRetainNotSupported                     = Code{Code: 0x9A, Reason: "retain not supported"}
 | |
| 	ErrQosNotSupported                        = Code{Code: 0x9B, Reason: "qos not supported"}
 | |
| 	ErrUseAnotherServer                       = Code{Code: 0x9C, Reason: "use another server"}
 | |
| 	ErrServerMoved                            = Code{Code: 0x9D, Reason: "server moved"}
 | |
| 	ErrSharedSubscriptionsNotSupported        = Code{Code: 0x9E, Reason: "shared subscriptions not supported"}
 | |
| 	ErrConnectionRateExceeded                 = Code{Code: 0x9F, Reason: "connection rate exceeded"}
 | |
| 	ErrMaxConnectTime                         = Code{Code: 0xA0, Reason: "maximum connect time"}
 | |
| 	ErrSubscriptionIdentifiersNotSupported    = Code{Code: 0xA1, Reason: "subscription identifiers not supported"}
 | |
| 	ErrWildcardSubscriptionsNotSupported      = Code{Code: 0xA2, Reason: "wildcard subscriptions not supported"}
 | |
| 	ErrInlineSubscriptionHandlerInvalid       = Code{Code: 0xA3, Reason: "inline subscription handler not valid."}
 | |
| 
 | |
| 	// MQTTv3 specific bytes.
 | |
| 	Err3UnsupportedProtocolVersion = Code{Code: 0x01}
 | |
| 	Err3ClientIdentifierNotValid   = Code{Code: 0x02}
 | |
| 	Err3ServerUnavailable          = Code{Code: 0x03}
 | |
| 	ErrMalformedUsernameOrPassword = Code{Code: 0x04}
 | |
| 	Err3NotAuthorized              = Code{Code: 0x05}
 | |
| 
 | |
| 	// V5CodesToV3 maps MQTTv5 Connack reason codes to MQTTv3 return codes.
 | |
| 	// This is required because MQTTv3 has different return byte specification.
 | |
| 	// See http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc385349257
 | |
| 	V5CodesToV3 = map[Code]Code{
 | |
| 		ErrUnsupportedProtocolVersion: Err3UnsupportedProtocolVersion,
 | |
| 		ErrClientIdentifierNotValid:   Err3ClientIdentifierNotValid,
 | |
| 		ErrServerUnavailable:          Err3ServerUnavailable,
 | |
| 		ErrMalformedUsername:          ErrMalformedUsernameOrPassword,
 | |
| 		ErrMalformedPassword:          ErrMalformedUsernameOrPassword,
 | |
| 		ErrBadUsernameOrPassword:      Err3NotAuthorized,
 | |
| 	}
 | |
| )
 |