github.com/nats-io/nats-server/v2@v2.11.0-preview.2/server/mqtt.go (about) 1 // Copyright 2020-2023 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package server 15 16 import ( 17 "bytes" 18 "crypto/tls" 19 "encoding/binary" 20 "encoding/json" 21 "errors" 22 "fmt" 23 "io" 24 "net" 25 "net/http" 26 "sort" 27 "strconv" 28 "strings" 29 "sync" 30 "time" 31 "unicode/utf8" 32 33 "github.com/nats-io/nuid" 34 ) 35 36 // References to "spec" here is from https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf 37 38 const ( 39 mqttPacketConnect = byte(0x10) 40 mqttPacketConnectAck = byte(0x20) 41 mqttPacketPub = byte(0x30) 42 mqttPacketPubAck = byte(0x40) 43 mqttPacketPubRec = byte(0x50) 44 mqttPacketPubRel = byte(0x60) 45 mqttPacketPubComp = byte(0x70) 46 mqttPacketSub = byte(0x80) 47 mqttPacketSubAck = byte(0x90) 48 mqttPacketUnsub = byte(0xa0) 49 mqttPacketUnsubAck = byte(0xb0) 50 mqttPacketPing = byte(0xc0) 51 mqttPacketPingResp = byte(0xd0) 52 mqttPacketDisconnect = byte(0xe0) 53 mqttPacketMask = byte(0xf0) 54 mqttPacketFlagMask = byte(0x0f) 55 56 mqttProtoLevel = byte(0x4) 57 58 // Connect flags 59 mqttConnFlagReserved = byte(0x1) 60 mqttConnFlagCleanSession = byte(0x2) 61 mqttConnFlagWillFlag = byte(0x04) 62 mqttConnFlagWillQoS = byte(0x18) 63 mqttConnFlagWillRetain = byte(0x20) 64 mqttConnFlagPasswordFlag = byte(0x40) 65 mqttConnFlagUsernameFlag = byte(0x80) 66 67 // Publish flags 68 mqttPubFlagRetain = byte(0x01) 69 mqttPubFlagQoS = byte(0x06) 70 mqttPubFlagDup = byte(0x08) 71 mqttPubQos1 = byte(0x1 << 1) 72 mqttPubQoS2 = byte(0x2 << 1) 73 74 // Subscribe flags 75 mqttSubscribeFlags = byte(0x2) 76 mqttSubAckFailure = byte(0x80) 77 78 // Unsubscribe flags 79 mqttUnsubscribeFlags = byte(0x2) 80 81 // ConnAck returned codes 82 mqttConnAckRCConnectionAccepted = byte(0x0) 83 mqttConnAckRCUnacceptableProtocolVersion = byte(0x1) 84 mqttConnAckRCIdentifierRejected = byte(0x2) 85 mqttConnAckRCServerUnavailable = byte(0x3) 86 mqttConnAckRCBadUserOrPassword = byte(0x4) 87 mqttConnAckRCNotAuthorized = byte(0x5) 88 mqttConnAckRCQoS2WillRejected = byte(0x10) 89 90 // Maximum payload size of a control packet 91 mqttMaxPayloadSize = 0xFFFFFFF 92 93 // Topic/Filter characters 94 mqttTopicLevelSep = '/' 95 mqttSingleLevelWC = '+' 96 mqttMultiLevelWC = '#' 97 mqttReservedPre = '$' 98 99 // This is appended to the sid of a subscription that is 100 // created on the upper level subject because of the MQTT 101 // wildcard '#' semantic. 102 mqttMultiLevelSidSuffix = " fwc" 103 104 // This is the prefix for NATS subscriptions subjects associated as delivery 105 // subject of JS consumer. We want to make them unique so will prevent users 106 // MQTT subscriptions to start with this. 107 mqttSubPrefix = "$MQTT.sub." 108 109 // Stream name for MQTT messages on a given account 110 mqttStreamName = "$MQTT_msgs" 111 mqttStreamSubjectPrefix = "$MQTT.msgs." 112 113 // Stream name for MQTT retained messages on a given account 114 mqttRetainedMsgsStreamName = "$MQTT_rmsgs" 115 mqttRetainedMsgsStreamSubject = "$MQTT.rmsgs." 116 117 // Stream name for MQTT sessions on a given account 118 mqttSessStreamName = "$MQTT_sess" 119 mqttSessStreamSubjectPrefix = "$MQTT.sess." 120 121 // Stream name prefix for MQTT sessions on a given account 122 mqttSessionsStreamNamePrefix = "$MQTT_sess_" 123 124 // Stream name and subject for incoming MQTT QoS2 messages 125 mqttQoS2IncomingMsgsStreamName = "$MQTT_qos2in" 126 mqttQoS2IncomingMsgsStreamSubjectPrefix = "$MQTT.qos2.in." 127 128 // Stream name and subjects for outgoing MQTT QoS (PUBREL) messages 129 mqttOutStreamName = "$MQTT_out" 130 mqttOutSubjectPrefix = "$MQTT.out." 131 mqttPubRelSubjectPrefix = "$MQTT.out.pubrel." 132 mqttPubRelDeliverySubjectPrefix = "$MQTT.deliver.pubrel." 133 mqttPubRelConsumerDurablePrefix = "$MQTT_PUBREL_" 134 135 // As per spec, MQTT server may not redeliver QoS 1 and 2 messages to 136 // clients, except after client reconnects. However, NATS Server will 137 // redeliver unacknowledged messages after this default interval. This can 138 // be changed with the server.Options.MQTT.AckWait option. 139 mqttDefaultAckWait = 30 * time.Second 140 141 // This is the default for the outstanding number of pending QoS 1 142 // messages sent to a session with QoS 1 subscriptions. 143 mqttDefaultMaxAckPending = 1024 144 145 // A session's list of subscriptions cannot have a cumulative MaxAckPending 146 // of more than this limit. 147 mqttMaxAckTotalLimit = 0xFFFF 148 149 // Prefix of the reply subject for JS API requests. 150 mqttJSARepliesPrefix = "$MQTT.JSA." 151 152 // Those are tokens that are used for the reply subject of JS API requests. 153 // For instance "$MQTT.JSA.<node id>.SC.<number>" is the reply subject 154 // for a request to create a stream (where <node id> is the server name hash), 155 // while "$MQTT.JSA.<node id>.SL.<number>" is for a stream lookup, etc... 156 mqttJSAIdTokenPos = 3 157 mqttJSATokenPos = 4 158 mqttJSAClientIDPos = 5 159 mqttJSAStreamCreate = "SC" 160 mqttJSAStreamUpdate = "SU" 161 mqttJSAStreamLookup = "SL" 162 mqttJSAStreamDel = "SD" 163 mqttJSAConsumerCreate = "CC" 164 mqttJSAConsumerLookup = "CL" 165 mqttJSAConsumerDel = "CD" 166 mqttJSAMsgStore = "MS" 167 mqttJSAMsgLoad = "ML" 168 mqttJSAMsgDelete = "MD" 169 mqttJSASessPersist = "SP" 170 mqttJSARetainedMsgDel = "RD" 171 mqttJSAStreamNames = "SN" 172 173 // This is how long to keep a client in the flappers map before closing the 174 // connection. This prevent quick reconnect from those clients that keep 175 // wanting to connect with a client ID already in use. 176 mqttSessFlappingJailDur = time.Second 177 178 // This is how frequently the timer to cleanup the sessions flappers map is firing. 179 mqttSessFlappingCleanupInterval = 5 * time.Second 180 181 // Default retry delay if transfer of old session streams to new one fails 182 mqttDefaultTransferRetry = 5 * time.Second 183 184 // For Websocket URLs 185 mqttWSPath = "/mqtt" 186 187 mqttInitialPubHeader = 16 // An overkill, should need 7 bytes max 188 mqttProcessSubTooLong = 100 * time.Millisecond 189 mqttDefaultRetainedCacheTTL = 2 * time.Minute 190 mqttRetainedTransferTimeout = 10 * time.Second 191 ) 192 193 const ( 194 sparkbNBIRTH = "NBIRTH" 195 sparkbDBIRTH = "DBIRTH" 196 sparkbNDEATH = "NDEATH" 197 sparkbDDEATH = "DDEATH" 198 ) 199 200 var ( 201 sparkbNamespaceTopicPrefix = []byte("spBv1.0/") 202 sparkbCertificatesTopicPrefix = []byte("$sparkplug/certificates/") 203 ) 204 205 var ( 206 mqttPingResponse = []byte{mqttPacketPingResp, 0x0} 207 mqttProtoName = []byte("MQTT") 208 mqttOldProtoName = []byte("MQIsdp") 209 mqttSessJailDur = mqttSessFlappingJailDur 210 mqttFlapCleanItvl = mqttSessFlappingCleanupInterval 211 mqttJSAPITimeout = 4 * time.Second 212 mqttRetainedCacheTTL = mqttDefaultRetainedCacheTTL 213 ) 214 215 var ( 216 errMQTTNotWebsocketPort = errors.New("MQTT clients over websocket must connect to the Websocket port, not the MQTT port") 217 errMQTTTopicFilterCannotBeEmpty = errors.New("topic filter cannot be empty") 218 errMQTTMalformedVarInt = errors.New("malformed variable int") 219 errMQTTSecondConnectPacket = errors.New("received a second CONNECT packet") 220 errMQTTServerNameMustBeSet = errors.New("mqtt requires server name to be explicitly set") 221 errMQTTUserMixWithUsersNKeys = errors.New("mqtt authentication username not compatible with presence of users/nkeys") 222 errMQTTTokenMixWIthUsersNKeys = errors.New("mqtt authentication token not compatible with presence of users/nkeys") 223 errMQTTAckWaitMustBePositive = errors.New("ack wait must be a positive value") 224 errMQTTStandaloneNeedsJetStream = errors.New("mqtt requires JetStream to be enabled if running in standalone mode") 225 errMQTTConnFlagReserved = errors.New("connect flags reserved bit not set to 0") 226 errMQTTWillAndRetainFlag = errors.New("if Will flag is set to 0, Will Retain flag must be 0 too") 227 errMQTTPasswordFlagAndNoUser = errors.New("password flag set but username flag is not") 228 errMQTTCIDEmptyNeedsCleanFlag = errors.New("when client ID is empty, clean session flag must be set to 1") 229 errMQTTEmptyWillTopic = errors.New("empty Will topic not allowed") 230 errMQTTEmptyUsername = errors.New("empty user name not allowed") 231 errMQTTTopicIsEmpty = errors.New("topic cannot be empty") 232 errMQTTPacketIdentifierIsZero = errors.New("packet identifier cannot be 0") 233 errMQTTUnsupportedCharacters = errors.New("character ' ' not supported for MQTT topics") 234 errMQTTInvalidSession = errors.New("invalid MQTT session") 235 ) 236 237 type srvMQTT struct { 238 listener net.Listener 239 listenerErr error 240 authOverride bool 241 sessmgr mqttSessionManager 242 } 243 244 type mqttSessionManager struct { 245 mu sync.RWMutex 246 sessions map[string]*mqttAccountSessionManager // key is account name 247 } 248 249 var testDisableRMSCache = false 250 251 type mqttAccountSessionManager struct { 252 mu sync.RWMutex 253 sessions map[string]*mqttSession // key is MQTT client ID 254 sessByHash map[string]*mqttSession // key is MQTT client ID hash 255 sessLocked map[string]struct{} // key is MQTT client ID and indicate that a session can not be taken by a new client at this time 256 flappers map[string]int64 // When connection connects with client ID already in use 257 flapTimer *time.Timer // Timer to perform some cleanup of the flappers map 258 sl *Sublist // sublist allowing to find retained messages for given subscription 259 retmsgs map[string]*mqttRetainedMsgRef // retained messages 260 rmsCache *sync.Map // map[subject]mqttRetainedMsg 261 jsa mqttJSA 262 rrmLastSeq uint64 // Restore retained messages expected last sequence 263 rrmDoneCh chan struct{} // To notify the caller that all retained messages have been loaded 264 domainTk string // Domain (with trailing "."), or possibly empty. This is added to session subject. 265 } 266 267 type mqttJSAResponse struct { 268 reply string // will be used to map to the original request in jsa.NewRequestExMulti 269 value any 270 } 271 272 type mqttJSA struct { 273 mu sync.Mutex 274 id string 275 c *client 276 sendq *ipQueue[*mqttJSPubMsg] 277 rplyr string 278 replies sync.Map // [string]chan *mqttJSAResponse 279 nuid *nuid.NUID 280 quitCh chan struct{} 281 domain string // Domain or possibly empty. This is added to session subject. 282 domainSet bool // covers if domain was set, even to empty 283 } 284 285 type mqttJSPubMsg struct { 286 subj string 287 reply string 288 hdr int 289 msg []byte 290 } 291 292 type mqttRetMsgDel struct { 293 Subject string `json:"subject"` 294 Seq uint64 `json:"seq"` 295 } 296 297 type mqttSession struct { 298 // subsMu is a "quick" version of the session lock, sufficient for the QoS0 299 // callback. It only guarantees that a new subscription is initialized, and 300 // its retained messages if any have been queued up for delivery. The QoS12 301 // callback uses the session lock. 302 mu sync.Mutex 303 subsMu sync.RWMutex 304 305 id string // client ID 306 idHash string // client ID hash 307 c *client 308 jsa *mqttJSA 309 subs map[string]byte // Key is MQTT SUBSCRIBE filter, value is the subscription QoS 310 cons map[string]*ConsumerConfig 311 pubRelConsumer *ConsumerConfig 312 pubRelSubscribed bool 313 pubRelDeliverySubject string 314 pubRelDeliverySubjectB []byte 315 pubRelSubject string 316 seq uint64 317 318 // pendingPublish maps packet identifiers (PI) to JetStream ACK subjects for 319 // QoS1 and 2 PUBLISH messages pending delivery to the session's client. 320 pendingPublish map[uint16]*mqttPending 321 322 // pendingPubRel maps PIs to JetStream ACK subjects for QoS2 PUBREL 323 // messages pending delivery to the session's client. 324 pendingPubRel map[uint16]*mqttPending 325 326 // cpending maps delivery attempts (that come with a JS ACK subject) to 327 // existing PIs. 328 cpending map[string]map[uint64]uint16 // composite key: jsDur, sseq 329 330 // "Last used" publish packet identifier (PI). starting point searching for the next available. 331 last_pi uint16 332 333 // Maximum number of pending acks for this session. 334 maxp uint16 335 tmaxack int 336 clean bool 337 domainTk string 338 } 339 340 type mqttPersistedSession struct { 341 Origin string `json:"origin,omitempty"` 342 ID string `json:"id,omitempty"` 343 Clean bool `json:"clean,omitempty"` 344 Subs map[string]byte `json:"subs,omitempty"` 345 Cons map[string]*ConsumerConfig `json:"cons,omitempty"` 346 PubRel *ConsumerConfig `json:"pubrel,omitempty"` 347 } 348 349 type mqttRetainedMsg struct { 350 Origin string `json:"origin,omitempty"` 351 Subject string `json:"subject,omitempty"` 352 Topic string `json:"topic,omitempty"` 353 Msg []byte `json:"msg,omitempty"` 354 Flags byte `json:"flags,omitempty"` 355 Source string `json:"source,omitempty"` 356 357 expiresFromCache time.Time 358 } 359 360 type mqttRetainedMsgRef struct { 361 sseq uint64 362 floor uint64 363 sub *subscription 364 } 365 366 // mqttSub contains fields associated with a MQTT subscription, and is added to 367 // the main subscription struct for MQTT message delivery subscriptions. The 368 // delivery callbacks may get invoked before sub.mqtt is set up, so they should 369 // acquire either sess.mu or sess.subsMu before accessing it. 370 type mqttSub struct { 371 // The sub's QOS and the JS durable name. They can change when 372 // re-subscribing, and are used in the delivery callbacks. They can be 373 // quickly accessed using sess.subsMu.RLock, or under the main session lock. 374 qos byte 375 jsDur string 376 377 // Pending serialization of retained messages to be sent when subscription 378 // is registered. The sub's delivery callbacks must wait until `prm` is 379 // ready (can block on sess.mu for that, too). 380 prm [][]byte 381 382 // If this subscription needs to be checked for being reserved. E.g. '#' or 383 // '*' or '*/'. It is set up at the time of subscription and is immutable 384 // after that. 385 reserved bool 386 } 387 388 type mqtt struct { 389 r *mqttReader 390 cp *mqttConnectProto 391 pp *mqttPublish 392 asm *mqttAccountSessionManager // quick reference to account session manager, immutable after processConnect() 393 sess *mqttSession // quick reference to session, immutable after processConnect() 394 cid string // client ID 395 396 // rejectQoS2Pub tells the MQTT client to not accept QoS2 PUBLISH, instead 397 // error and terminate the connection. 398 rejectQoS2Pub bool 399 400 // downgradeQOS2Sub tells the MQTT client to downgrade QoS2 SUBSCRIBE 401 // requests to QoS1. 402 downgradeQoS2Sub bool 403 } 404 405 type mqttPending struct { 406 sseq uint64 // stream sequence 407 jsAckSubject string // the ACK subject to send the ack to 408 jsDur string // JS durable name 409 } 410 411 type mqttConnectProto struct { 412 rd time.Duration 413 will *mqttWill 414 flags byte 415 } 416 417 type mqttIOReader interface { 418 io.Reader 419 SetReadDeadline(time.Time) error 420 } 421 422 type mqttReader struct { 423 reader mqttIOReader 424 buf []byte 425 pos int 426 pstart int 427 pbuf []byte 428 } 429 430 type mqttWriter struct { 431 bytes.Buffer 432 } 433 434 type mqttWill struct { 435 topic []byte 436 subject []byte 437 mapped []byte 438 message []byte 439 qos byte 440 retain bool 441 } 442 443 type mqttFilter struct { 444 filter string 445 qos byte 446 // Used only for tracing and should not be used after parsing of (un)sub protocols. 447 ttopic []byte 448 } 449 450 type mqttPublish struct { 451 topic []byte 452 subject []byte 453 mapped []byte 454 msg []byte 455 sz int 456 pi uint16 457 flags byte 458 } 459 460 // When we re-encode incoming MQTT PUBLISH messages for NATS delivery, we add 461 // the following headers: 462 // - "Nmqtt-Pub" (*always) indicates that the message originated from MQTT, and 463 // contains the original message QoS. 464 // - "Nmqtt-Subject" contains the original MQTT subject from mqttParsePub. 465 // - "Nmqtt-Mapped" contains the mapping during mqttParsePub. 466 // 467 // When we submit a PUBREL for delivery, we add a "Nmqtt-PubRel" header that 468 // contains the PI. 469 const ( 470 // NATS header that indicates that the message originated from MQTT and 471 // stores the published message QOS. 472 mqttNatsHeader = "Nmqtt-Pub" 473 474 // NATS headers to store retained message metadata (along with the original 475 // message as binary). 476 mqttNatsRetainedMessageTopic = "Nmqtt-RTopic" 477 mqttNatsRetainedMessageOrigin = "Nmqtt-ROrigin" 478 mqttNatsRetainedMessageFlags = "Nmqtt-RFlags" 479 mqttNatsRetainedMessageSource = "Nmqtt-RSource" 480 481 // NATS header that indicates that the message is an MQTT PubRel and stores 482 // the PI. 483 mqttNatsPubRelHeader = "Nmqtt-PubRel" 484 485 // NATS headers to store the original MQTT subject and the subject mapping. 486 mqttNatsHeaderSubject = "Nmqtt-Subject" 487 mqttNatsHeaderMapped = "Nmqtt-Mapped" 488 ) 489 490 type mqttParsedPublishNATSHeader struct { 491 qos byte 492 subject []byte 493 mapped []byte 494 } 495 496 func (s *Server) startMQTT() { 497 if s.isShuttingDown() { 498 return 499 } 500 501 sopts := s.getOpts() 502 o := &sopts.MQTT 503 504 var hl net.Listener 505 var err error 506 507 port := o.Port 508 if port == -1 { 509 port = 0 510 } 511 hp := net.JoinHostPort(o.Host, strconv.Itoa(port)) 512 s.mu.Lock() 513 s.mqtt.sessmgr.sessions = make(map[string]*mqttAccountSessionManager) 514 hl, err = net.Listen("tcp", hp) 515 s.mqtt.listenerErr = err 516 if err != nil { 517 s.mu.Unlock() 518 s.Fatalf("Unable to listen for MQTT connections: %v", err) 519 return 520 } 521 if port == 0 { 522 o.Port = hl.Addr().(*net.TCPAddr).Port 523 } 524 s.mqtt.listener = hl 525 scheme := "mqtt" 526 if o.TLSConfig != nil { 527 scheme = "tls" 528 } 529 s.Noticef("Listening for MQTT clients on %s://%s:%d", scheme, o.Host, o.Port) 530 go s.acceptConnections(hl, "MQTT", func(conn net.Conn) { s.createMQTTClient(conn, nil) }, nil) 531 s.mu.Unlock() 532 } 533 534 // This is similar to createClient() but has some modifications specifi to MQTT clients. 535 // The comments have been kept to minimum to reduce code size. Check createClient() for 536 // more details. 537 func (s *Server) createMQTTClient(conn net.Conn, ws *websocket) *client { 538 opts := s.getOpts() 539 540 maxPay := int32(opts.MaxPayload) 541 maxSubs := int32(opts.MaxSubs) 542 if maxSubs == 0 { 543 maxSubs = -1 544 } 545 now := time.Now() 546 547 mqtt := &mqtt{ 548 rejectQoS2Pub: opts.MQTT.rejectQoS2Pub, 549 downgradeQoS2Sub: opts.MQTT.downgradeQoS2Sub, 550 } 551 c := &client{srv: s, nc: conn, mpay: maxPay, msubs: maxSubs, start: now, last: now, mqtt: mqtt, ws: ws} 552 c.headers = true 553 c.mqtt.pp = &mqttPublish{} 554 // MQTT clients don't send NATS CONNECT protocols. So make it an "echo" 555 // client, but disable verbose and pedantic (by not setting them). 556 c.opts.Echo = true 557 558 c.registerWithAccount(s.globalAccount()) 559 560 s.mu.Lock() 561 // Check auth, override if applicable. 562 authRequired := s.info.AuthRequired || s.mqtt.authOverride 563 s.totalClients++ 564 s.mu.Unlock() 565 566 c.mu.Lock() 567 if authRequired { 568 c.flags.set(expectConnect) 569 } 570 c.initClient() 571 c.Debugf("Client connection created") 572 c.mu.Unlock() 573 574 s.mu.Lock() 575 if !s.isRunning() || s.ldm { 576 if s.isShuttingDown() { 577 conn.Close() 578 } 579 s.mu.Unlock() 580 return c 581 } 582 583 if opts.MaxConn > 0 && len(s.clients) >= opts.MaxConn { 584 s.mu.Unlock() 585 c.maxConnExceeded() 586 return nil 587 } 588 s.clients[c.cid] = c 589 590 // Websocket TLS handshake is already done when getting to this function. 591 tlsRequired := opts.MQTT.TLSConfig != nil && ws == nil 592 s.mu.Unlock() 593 594 c.mu.Lock() 595 596 // In case connection has already been closed 597 if c.isClosed() { 598 c.mu.Unlock() 599 c.closeConnection(WriteError) 600 return nil 601 } 602 603 var pre []byte 604 if tlsRequired && opts.AllowNonTLS { 605 pre = make([]byte, 4) 606 c.nc.SetReadDeadline(time.Now().Add(secondsToDuration(opts.MQTT.TLSTimeout))) 607 n, _ := io.ReadFull(c.nc, pre[:]) 608 c.nc.SetReadDeadline(time.Time{}) 609 pre = pre[:n] 610 if n > 0 && pre[0] == 0x16 { 611 tlsRequired = true 612 } else { 613 tlsRequired = false 614 } 615 } 616 617 if tlsRequired { 618 if len(pre) > 0 { 619 c.nc = &tlsMixConn{c.nc, bytes.NewBuffer(pre)} 620 pre = nil 621 } 622 623 // Perform server-side TLS handshake. 624 if err := c.doTLSServerHandshake(tlsHandshakeMQTT, opts.MQTT.TLSConfig, opts.MQTT.TLSTimeout, opts.MQTT.TLSPinnedCerts); err != nil { 625 c.mu.Unlock() 626 return nil 627 } 628 } 629 630 if authRequired { 631 timeout := opts.AuthTimeout 632 // Possibly override with MQTT specific value. 633 if opts.MQTT.AuthTimeout != 0 { 634 timeout = opts.MQTT.AuthTimeout 635 } 636 c.setAuthTimer(secondsToDuration(timeout)) 637 } 638 639 // No Ping timer for MQTT clients... 640 641 s.startGoRoutine(func() { c.readLoop(pre) }) 642 s.startGoRoutine(func() { c.writeLoop() }) 643 644 if tlsRequired { 645 c.Debugf("TLS handshake complete") 646 cs := c.nc.(*tls.Conn).ConnectionState() 647 c.Debugf("TLS version %s, cipher suite %s", tlsVersion(cs.Version), tlsCipher(cs.CipherSuite)) 648 } 649 650 c.mu.Unlock() 651 652 return c 653 } 654 655 // Given the mqtt options, we check if any auth configuration 656 // has been provided. If so, possibly create users/nkey users and 657 // store them in s.mqtt.users/nkeys. 658 // Also update a boolean that indicates if auth is required for 659 // mqtt clients. 660 // Server lock is held on entry. 661 func (s *Server) mqttConfigAuth(opts *MQTTOpts) { 662 mqtt := &s.mqtt 663 // If any of those is specified, we consider that there is an override. 664 mqtt.authOverride = opts.Username != _EMPTY_ || opts.Token != _EMPTY_ || opts.NoAuthUser != _EMPTY_ 665 } 666 667 // Validate the mqtt related options. 668 func validateMQTTOptions(o *Options) error { 669 mo := &o.MQTT 670 // If no port is defined, we don't care about other options 671 if mo.Port == 0 { 672 return nil 673 } 674 // We have to force the server name to be explicitly set and be unique when 675 // in cluster mode. 676 if o.ServerName == _EMPTY_ && (o.Cluster.Port != 0 || o.Gateway.Port != 0) { 677 return errMQTTServerNameMustBeSet 678 } 679 // If there is a NoAuthUser, we need to have Users defined and 680 // the user to be present. 681 if mo.NoAuthUser != _EMPTY_ { 682 if err := validateNoAuthUser(o, mo.NoAuthUser); err != nil { 683 return err 684 } 685 } 686 // Token/Username not possible if there are users/nkeys 687 if len(o.Users) > 0 || len(o.Nkeys) > 0 { 688 if mo.Username != _EMPTY_ { 689 return errMQTTUserMixWithUsersNKeys 690 } 691 if mo.Token != _EMPTY_ { 692 return errMQTTTokenMixWIthUsersNKeys 693 } 694 } 695 if mo.AckWait < 0 { 696 return errMQTTAckWaitMustBePositive 697 } 698 // If strictly standalone and there is no JS enabled, then it won't work... 699 // For leafnodes, we could either have remote(s) and it would be ok, or no 700 // remote but accept from a remote side that has "hub" property set, which 701 // then would ok too. So we fail only if we have no leafnode config at all. 702 if !o.JetStream && o.Cluster.Port == 0 && o.Gateway.Port == 0 && 703 o.LeafNode.Port == 0 && len(o.LeafNode.Remotes) == 0 { 704 return errMQTTStandaloneNeedsJetStream 705 } 706 if err := validatePinnedCerts(mo.TLSPinnedCerts); err != nil { 707 return fmt.Errorf("mqtt: %v", err) 708 } 709 if mo.ConsumerReplicas > 0 && mo.StreamReplicas > 0 && mo.ConsumerReplicas > mo.StreamReplicas { 710 return fmt.Errorf("mqtt: consumer_replicas (%v) cannot be higher than stream_replicas (%v)", 711 mo.ConsumerReplicas, mo.StreamReplicas) 712 } 713 return nil 714 } 715 716 // Returns true if this connection is from a MQTT client. 717 // Lock held on entry. 718 func (c *client) isMqtt() bool { 719 return c.mqtt != nil 720 } 721 722 // If this is an MQTT client, returns the session client ID, 723 // otherwise returns the empty string. 724 // Lock held on entry 725 func (c *client) getMQTTClientID() string { 726 if !c.isMqtt() { 727 return _EMPTY_ 728 } 729 return c.mqtt.cid 730 } 731 732 // Parse protocols inside the given buffer. 733 // This is invoked from the readLoop. 734 func (c *client) mqttParse(buf []byte) error { 735 c.mu.Lock() 736 s := c.srv 737 trace := c.trace 738 connected := c.flags.isSet(connectReceived) 739 mqtt := c.mqtt 740 r := mqtt.r 741 var rd time.Duration 742 if mqtt.cp != nil { 743 rd = mqtt.cp.rd 744 if rd > 0 { 745 r.reader.SetReadDeadline(time.Time{}) 746 } 747 } 748 hasMappings := c.in.flags.isSet(hasMappings) 749 c.mu.Unlock() 750 751 r.reset(buf) 752 753 var err error 754 var b byte 755 var pl int 756 var complete bool 757 758 for err == nil && r.hasMore() { 759 760 // Keep track of the starting of the packet, in case we have a partial 761 r.pstart = r.pos 762 763 // Read packet type and flags 764 if b, err = r.readByte("packet type"); err != nil { 765 break 766 } 767 768 // Packet type 769 pt := b & mqttPacketMask 770 771 // If client was not connected yet, the first packet must be 772 // a mqttPacketConnect otherwise we fail the connection. 773 if !connected && pt != mqttPacketConnect { 774 // If the buffer indicates that it may be a websocket handshake 775 // but the client is not websocket, it means that the client 776 // connected to the MQTT port instead of the Websocket port. 777 if bytes.HasPrefix(buf, []byte("GET ")) && !c.isWebsocket() { 778 err = errMQTTNotWebsocketPort 779 } else { 780 err = fmt.Errorf("the first packet should be a CONNECT (%v), got %v", mqttPacketConnect, pt) 781 } 782 break 783 } 784 785 pl, complete, err = r.readPacketLen() 786 if err != nil || !complete { 787 break 788 } 789 790 switch pt { 791 // Packets that we receive back when we act as the "sender": PUBACK, 792 // PUBREC, PUBCOMP. 793 case mqttPacketPubAck: 794 var pi uint16 795 pi, err = mqttParsePIPacket(r) 796 if trace { 797 c.traceInOp("PUBACK", errOrTrace(err, fmt.Sprintf("pi=%v", pi))) 798 } 799 if err == nil { 800 err = c.mqttProcessPubAck(pi) 801 } 802 803 case mqttPacketPubRec: 804 var pi uint16 805 pi, err = mqttParsePIPacket(r) 806 if trace { 807 c.traceInOp("PUBREC", errOrTrace(err, fmt.Sprintf("pi=%v", pi))) 808 } 809 if err == nil { 810 err = c.mqttProcessPubRec(pi) 811 } 812 813 case mqttPacketPubComp: 814 var pi uint16 815 pi, err = mqttParsePIPacket(r) 816 if trace { 817 c.traceInOp("PUBCOMP", errOrTrace(err, fmt.Sprintf("pi=%v", pi))) 818 } 819 if err == nil { 820 c.mqttProcessPubComp(pi) 821 } 822 823 // Packets where we act as the "receiver": PUBLISH, PUBREL, SUBSCRIBE, UNSUBSCRIBE. 824 case mqttPacketPub: 825 pp := c.mqtt.pp 826 pp.flags = b & mqttPacketFlagMask 827 err = c.mqttParsePub(r, pl, pp, hasMappings) 828 if trace { 829 c.traceInOp("PUBLISH", errOrTrace(err, mqttPubTrace(pp))) 830 if err == nil { 831 c.mqttTraceMsg(pp.msg) 832 } 833 } 834 if err == nil { 835 err = s.mqttProcessPub(c, pp, trace) 836 } 837 838 case mqttPacketPubRel: 839 var pi uint16 840 pi, err = mqttParsePIPacket(r) 841 if trace { 842 c.traceInOp("PUBREL", errOrTrace(err, fmt.Sprintf("pi=%v", pi))) 843 } 844 if err == nil { 845 err = s.mqttProcessPubRel(c, pi, trace) 846 } 847 848 case mqttPacketSub: 849 var pi uint16 // packet identifier 850 var filters []*mqttFilter 851 var subs []*subscription 852 pi, filters, err = c.mqttParseSubs(r, b, pl) 853 if trace { 854 c.traceInOp("SUBSCRIBE", errOrTrace(err, mqttSubscribeTrace(pi, filters))) 855 } 856 if err == nil { 857 subs, err = c.mqttProcessSubs(filters) 858 if err == nil && trace { 859 c.traceOutOp("SUBACK", []byte(fmt.Sprintf("pi=%v", pi))) 860 } 861 } 862 if err == nil { 863 c.mqttEnqueueSubAck(pi, filters) 864 c.mqttSendRetainedMsgsToNewSubs(subs) 865 } 866 867 case mqttPacketUnsub: 868 var pi uint16 // packet identifier 869 var filters []*mqttFilter 870 pi, filters, err = c.mqttParseUnsubs(r, b, pl) 871 if trace { 872 c.traceInOp("UNSUBSCRIBE", errOrTrace(err, mqttUnsubscribeTrace(pi, filters))) 873 } 874 if err == nil { 875 err = c.mqttProcessUnsubs(filters) 876 if err == nil && trace { 877 c.traceOutOp("UNSUBACK", []byte(fmt.Sprintf("pi=%v", pi))) 878 } 879 } 880 if err == nil { 881 c.mqttEnqueueUnsubAck(pi) 882 } 883 884 // Packets that we get both as a receiver and sender: PING, CONNECT, DISCONNECT 885 case mqttPacketPing: 886 if trace { 887 c.traceInOp("PINGREQ", nil) 888 } 889 c.mqttEnqueuePingResp() 890 if trace { 891 c.traceOutOp("PINGRESP", nil) 892 } 893 894 case mqttPacketConnect: 895 // It is an error to receive a second connect packet 896 if connected { 897 err = errMQTTSecondConnectPacket 898 break 899 } 900 var rc byte 901 var cp *mqttConnectProto 902 var sessp bool 903 rc, cp, err = c.mqttParseConnect(r, hasMappings) 904 // Add the client id to the client's string, regardless of error. 905 // We may still get the client_id if the call above fails somewhere 906 // after parsing the client ID itself. 907 c.ncs.Store(fmt.Sprintf("%s - %q", c, c.mqtt.cid)) 908 if trace && cp != nil { 909 c.traceInOp("CONNECT", errOrTrace(err, c.mqttConnectTrace(cp))) 910 } 911 if rc != 0 { 912 c.mqttEnqueueConnAck(rc, sessp) 913 if trace { 914 c.traceOutOp("CONNACK", []byte(fmt.Sprintf("sp=%v rc=%v", sessp, rc))) 915 } 916 } else if err == nil { 917 if err = s.mqttProcessConnect(c, cp, trace); err != nil { 918 err = fmt.Errorf("unable to connect: %v", err) 919 } else { 920 // Add this debug statement so users running in Debug mode 921 // will have the client id printed here for the first time. 922 c.Debugf("Client connected") 923 connected = true 924 rd = cp.rd 925 } 926 } 927 928 case mqttPacketDisconnect: 929 if trace { 930 c.traceInOp("DISCONNECT", nil) 931 } 932 // Normal disconnect, we need to discard the will. 933 // Spec [MQTT-3.1.2-8] 934 c.mu.Lock() 935 if c.mqtt.cp != nil { 936 c.mqtt.cp.will = nil 937 } 938 c.mu.Unlock() 939 s.mqttHandleClosedClient(c) 940 c.closeConnection(ClientClosed) 941 return nil 942 943 default: 944 err = fmt.Errorf("received unknown packet type %d", pt>>4) 945 } 946 } 947 if err == nil && rd > 0 { 948 r.reader.SetReadDeadline(time.Now().Add(rd)) 949 } 950 return err 951 } 952 953 func (c *client) mqttTraceMsg(msg []byte) { 954 maxTrace := c.srv.getOpts().MaxTracedMsgLen 955 if maxTrace > 0 && len(msg) > maxTrace { 956 c.Tracef("<<- MSG_PAYLOAD: [\"%s...\"]", msg[:maxTrace]) 957 } else { 958 c.Tracef("<<- MSG_PAYLOAD: [%q]", msg) 959 } 960 } 961 962 // The MQTT client connection has been closed, or the DISCONNECT packet was received. 963 // For a "clean" session, we will delete the session, otherwise, simply removing 964 // the binding. We will also send the "will" message if applicable. 965 // 966 // Runs from the client's readLoop. 967 // No lock held on entry. 968 func (s *Server) mqttHandleClosedClient(c *client) { 969 c.mu.Lock() 970 asm := c.mqtt.asm 971 sess := c.mqtt.sess 972 c.mu.Unlock() 973 974 // If asm or sess are nil, it means that we have failed a client 975 // before it was associated with a session, so nothing more to do. 976 if asm == nil || sess == nil { 977 return 978 } 979 980 // Add this session to the locked map for the rest of the execution. 981 if err := asm.lockSession(sess, c); err != nil { 982 return 983 } 984 defer asm.unlockSession(sess) 985 986 asm.mu.Lock() 987 // Clear the client from the session, but session may stay. 988 sess.mu.Lock() 989 sess.c = nil 990 doClean := sess.clean 991 sess.mu.Unlock() 992 // If it was a clean session, then we remove from the account manager, 993 // and we will call clear() outside of any lock. 994 if doClean { 995 asm.removeSession(sess, false) 996 } 997 // Remove in case it was in the flappers map. 998 asm.removeSessFromFlappers(sess.id) 999 asm.mu.Unlock() 1000 1001 // This needs to be done outside of any lock. 1002 if doClean { 1003 if err := sess.clear(); err != nil { 1004 c.Errorf(err.Error()) 1005 } 1006 } 1007 1008 // Now handle the "will". This function will be a no-op if there is no "will" to send. 1009 s.mqttHandleWill(c) 1010 } 1011 1012 // Updates the MaxAckPending for all MQTT sessions, updating the 1013 // JetStream consumers and updating their max ack pending and forcing 1014 // a expiration of pending messages. 1015 // 1016 // Runs from a server configuration reload routine. 1017 // No lock held on entry. 1018 func (s *Server) mqttUpdateMaxAckPending(newmaxp uint16) { 1019 msm := &s.mqtt.sessmgr 1020 s.accounts.Range(func(k, _ any) bool { 1021 accName := k.(string) 1022 msm.mu.RLock() 1023 asm := msm.sessions[accName] 1024 msm.mu.RUnlock() 1025 if asm == nil { 1026 // Move to next account 1027 return true 1028 } 1029 asm.mu.RLock() 1030 for _, sess := range asm.sessions { 1031 sess.mu.Lock() 1032 sess.maxp = newmaxp 1033 sess.mu.Unlock() 1034 } 1035 asm.mu.RUnlock() 1036 return true 1037 }) 1038 } 1039 1040 func (s *Server) mqttGetJSAForAccount(acc string) *mqttJSA { 1041 sm := &s.mqtt.sessmgr 1042 1043 sm.mu.RLock() 1044 asm := sm.sessions[acc] 1045 sm.mu.RUnlock() 1046 1047 if asm == nil { 1048 return nil 1049 } 1050 1051 asm.mu.RLock() 1052 jsa := &asm.jsa 1053 asm.mu.RUnlock() 1054 return jsa 1055 } 1056 1057 func (s *Server) mqttStoreQoSMsgForAccountOnNewSubject(hdr int, msg []byte, acc, subject string) { 1058 if s == nil || hdr <= 0 { 1059 return 1060 } 1061 h := mqttParsePublishNATSHeader(msg[:hdr]) 1062 if h == nil || h.qos == 0 { 1063 return 1064 } 1065 jsa := s.mqttGetJSAForAccount(acc) 1066 if jsa == nil { 1067 return 1068 } 1069 jsa.storeMsg(mqttStreamSubjectPrefix+subject, hdr, msg) 1070 } 1071 1072 func mqttParsePublishNATSHeader(headerBytes []byte) *mqttParsedPublishNATSHeader { 1073 if len(headerBytes) == 0 { 1074 return nil 1075 } 1076 1077 pubValue := getHeader(mqttNatsHeader, headerBytes) 1078 if len(pubValue) == 0 { 1079 return nil 1080 } 1081 return &mqttParsedPublishNATSHeader{ 1082 qos: pubValue[0] - '0', 1083 subject: getHeader(mqttNatsHeaderSubject, headerBytes), 1084 mapped: getHeader(mqttNatsHeaderMapped, headerBytes), 1085 } 1086 } 1087 1088 func mqttParsePubRelNATSHeader(headerBytes []byte) uint16 { 1089 if len(headerBytes) == 0 { 1090 return 0 1091 } 1092 1093 pubrelValue := getHeader(mqttNatsPubRelHeader, headerBytes) 1094 if len(pubrelValue) == 0 { 1095 return 0 1096 } 1097 pi, _ := strconv.Atoi(string(pubrelValue)) 1098 return uint16(pi) 1099 } 1100 1101 // Returns the MQTT sessions manager for a given account. 1102 // If new, creates the required JetStream streams/consumers 1103 // for handling of sessions and messages. 1104 func (s *Server) getOrCreateMQTTAccountSessionManager(c *client) (*mqttAccountSessionManager, error) { 1105 sm := &s.mqtt.sessmgr 1106 1107 c.mu.Lock() 1108 acc := c.acc 1109 c.mu.Unlock() 1110 accName := acc.GetName() 1111 1112 sm.mu.RLock() 1113 asm, ok := sm.sessions[accName] 1114 sm.mu.RUnlock() 1115 1116 if ok { 1117 return asm, nil 1118 } 1119 1120 // We will pass the quitCh to the account session manager if we happen to create it. 1121 s.mu.Lock() 1122 quitCh := s.quitCh 1123 s.mu.Unlock() 1124 1125 // Not found, now take the write lock and check again 1126 sm.mu.Lock() 1127 defer sm.mu.Unlock() 1128 asm, ok = sm.sessions[accName] 1129 if ok { 1130 return asm, nil 1131 } 1132 // Need to create one here. 1133 asm, err := s.mqttCreateAccountSessionManager(acc, quitCh) 1134 if err != nil { 1135 return nil, err 1136 } 1137 sm.sessions[accName] = asm 1138 return asm, nil 1139 } 1140 1141 // Creates JS streams/consumers for handling of sessions and messages for this account. 1142 // 1143 // Global session manager lock is held on entry. 1144 func (s *Server) mqttCreateAccountSessionManager(acc *Account, quitCh chan struct{}) (*mqttAccountSessionManager, error) { 1145 var err error 1146 1147 accName := acc.GetName() 1148 1149 opts := s.getOpts() 1150 c := s.createInternalAccountClient() 1151 c.acc = acc 1152 1153 id := s.NodeName() 1154 replicas := opts.MQTT.StreamReplicas 1155 if replicas <= 0 { 1156 replicas = s.mqttDetermineReplicas() 1157 } 1158 qname := fmt.Sprintf("[ACC:%s] MQTT ", accName) 1159 as := &mqttAccountSessionManager{ 1160 sessions: make(map[string]*mqttSession), 1161 sessByHash: make(map[string]*mqttSession), 1162 sessLocked: make(map[string]struct{}), 1163 flappers: make(map[string]int64), 1164 jsa: mqttJSA{ 1165 id: id, 1166 c: c, 1167 rplyr: mqttJSARepliesPrefix + id + ".", 1168 sendq: newIPQueue[*mqttJSPubMsg](s, qname+"send"), 1169 nuid: nuid.New(), 1170 quitCh: quitCh, 1171 }, 1172 } 1173 if !testDisableRMSCache { 1174 as.rmsCache = &sync.Map{} 1175 } 1176 // TODO record domain name in as here 1177 1178 // The domain to communicate with may be required for JS calls. 1179 // Search from specific (per account setting) to generic (mqtt setting) 1180 if opts.JsAccDefaultDomain != nil { 1181 if d, ok := opts.JsAccDefaultDomain[accName]; ok { 1182 if d != _EMPTY_ { 1183 as.jsa.domain = d 1184 } 1185 as.jsa.domainSet = true 1186 } 1187 // in case domain was set to empty, check if there are more generic domain overwrites 1188 } 1189 if as.jsa.domain == _EMPTY_ { 1190 if d := opts.MQTT.JsDomain; d != _EMPTY_ { 1191 as.jsa.domain = d 1192 as.jsa.domainSet = true 1193 } 1194 } 1195 // We need to include the domain in the subject prefix used to store sessions in the $MQTT_sess stream. 1196 if as.jsa.domainSet { 1197 if as.jsa.domain != _EMPTY_ { 1198 as.domainTk = as.jsa.domain + "." 1199 } 1200 } else if d := s.getOpts().JetStreamDomain; d != _EMPTY_ { 1201 as.domainTk = d + "." 1202 } 1203 if as.jsa.domainSet { 1204 s.Noticef("Creating MQTT streams/consumers with replicas %v for account %q in domain %q", replicas, accName, as.jsa.domain) 1205 } else { 1206 s.Noticef("Creating MQTT streams/consumers with replicas %v for account %q", replicas, accName) 1207 } 1208 1209 var subs []*subscription 1210 var success bool 1211 closeCh := make(chan struct{}) 1212 1213 defer func() { 1214 if success { 1215 return 1216 } 1217 for _, sub := range subs { 1218 c.processUnsub(sub.sid) 1219 } 1220 close(closeCh) 1221 }() 1222 1223 // We create all subscriptions before starting the go routine that will do 1224 // sends otherwise we could get races. 1225 // Note that using two different clients (one for the subs, one for the 1226 // sends) would cause other issues such as registration of recent subs in 1227 // the "sub" client would be invisible to the check for GW routed replies 1228 // (shouldMapReplyForGatewaySend) since the client there would be the "sender". 1229 1230 jsa := &as.jsa 1231 sid := int64(1) 1232 // This is a subscription that will process all JS API replies. We could split to 1233 // individual subscriptions if needed, but since there is a bit of common code, 1234 // that seemed like a good idea to be all in one place. 1235 if err := as.createSubscription(jsa.rplyr+">", 1236 as.processJSAPIReplies, &sid, &subs); err != nil { 1237 return nil, err 1238 } 1239 1240 // We will listen for replies to session persist requests so that we can 1241 // detect the use of a session with the same client ID anywhere in the cluster. 1242 // `$MQTT.JSA.{js-id}.SP.{client-id-hash}.{uuid}` 1243 if err := as.createSubscription(mqttJSARepliesPrefix+"*."+mqttJSASessPersist+".*.*", 1244 as.processSessionPersist, &sid, &subs); err != nil { 1245 return nil, err 1246 } 1247 1248 // We create the subscription on "$MQTT.sub.<nuid>" to limit the subjects 1249 // that a user would allow permissions on. 1250 rmsubj := mqttSubPrefix + nuid.Next() 1251 if err := as.createSubscription(rmsubj, as.processRetainedMsg, &sid, &subs); err != nil { 1252 return nil, err 1253 } 1254 1255 // Create a subscription to be notified of retained messages delete requests. 1256 rmdelsubj := mqttJSARepliesPrefix + "*." + mqttJSARetainedMsgDel 1257 if err := as.createSubscription(rmdelsubj, as.processRetainedMsgDel, &sid, &subs); err != nil { 1258 return nil, err 1259 } 1260 1261 // No more creation of subscriptions past this point otherwise RACEs may happen. 1262 1263 // Start the go routine that will send JS API requests. 1264 s.startGoRoutine(func() { 1265 defer s.grWG.Done() 1266 as.sendJSAPIrequests(s, c, accName, closeCh) 1267 }) 1268 1269 // Start the go routine that will clean up cached retained messages that expired. 1270 if as.rmsCache != nil { 1271 s.startGoRoutine(func() { 1272 defer s.grWG.Done() 1273 as.cleanupRetainedMessageCache(s, closeCh) 1274 }) 1275 } 1276 1277 lookupStream := func(stream, txt string) (*StreamInfo, error) { 1278 si, err := jsa.lookupStream(stream) 1279 if err != nil { 1280 if IsNatsErr(err, JSStreamNotFoundErr) { 1281 return nil, nil 1282 } 1283 return nil, fmt.Errorf("lookup %s stream for account %q: %v", txt, accName, err) 1284 } 1285 if opts.MQTT.StreamReplicas == 0 { 1286 return si, nil 1287 } 1288 sr := 1 1289 if si.Cluster != nil { 1290 sr += len(si.Cluster.Replicas) 1291 } 1292 if replicas != sr { 1293 s.Warnf("MQTT %s stream replicas mismatch: current is %v but configuration is %v for '%s > %s'", 1294 txt, sr, replicas, accName, stream) 1295 } 1296 return si, nil 1297 } 1298 1299 if si, err := lookupStream(mqttSessStreamName, "sessions"); err != nil { 1300 return nil, err 1301 } else if si == nil { 1302 // Create the stream for the sessions. 1303 cfg := &StreamConfig{ 1304 Name: mqttSessStreamName, 1305 Subjects: []string{mqttSessStreamSubjectPrefix + as.domainTk + ">"}, 1306 Storage: FileStorage, 1307 Retention: LimitsPolicy, 1308 Replicas: replicas, 1309 MaxMsgsPer: 1, 1310 } 1311 if _, created, err := jsa.createStream(cfg); err == nil && created { 1312 as.transferUniqueSessStreamsToMuxed(s) 1313 } else if isErrorOtherThan(err, JSStreamNameExistErr) { 1314 return nil, fmt.Errorf("create sessions stream for account %q: %v", accName, err) 1315 } 1316 } 1317 1318 if si, err := lookupStream(mqttStreamName, "messages"); err != nil { 1319 return nil, err 1320 } else if si == nil { 1321 // Create the stream for the messages. 1322 cfg := &StreamConfig{ 1323 Name: mqttStreamName, 1324 Subjects: []string{mqttStreamSubjectPrefix + ">"}, 1325 Storage: FileStorage, 1326 Retention: InterestPolicy, 1327 Replicas: replicas, 1328 } 1329 if _, _, err := jsa.createStream(cfg); isErrorOtherThan(err, JSStreamNameExistErr) { 1330 return nil, fmt.Errorf("create messages stream for account %q: %v", accName, err) 1331 } 1332 } 1333 1334 if si, err := lookupStream(mqttQoS2IncomingMsgsStreamName, "QoS2 incoming messages"); err != nil { 1335 return nil, err 1336 } else if si == nil { 1337 // Create the stream for the incoming QoS2 messages that have not been 1338 // PUBREL-ed by the sender. Subject is 1339 // "$MQTT.qos2.<session>.<PI>", the .PI is to achieve exactly 1340 // once for each PI. 1341 cfg := &StreamConfig{ 1342 Name: mqttQoS2IncomingMsgsStreamName, 1343 Subjects: []string{mqttQoS2IncomingMsgsStreamSubjectPrefix + ">"}, 1344 Storage: FileStorage, 1345 Retention: LimitsPolicy, 1346 Discard: DiscardNew, 1347 MaxMsgsPer: 1, 1348 DiscardNewPer: true, 1349 Replicas: replicas, 1350 } 1351 if _, _, err := jsa.createStream(cfg); isErrorOtherThan(err, JSStreamNameExistErr) { 1352 return nil, fmt.Errorf("create QoS2 incoming messages stream for account %q: %v", accName, err) 1353 } 1354 } 1355 1356 if si, err := lookupStream(mqttOutStreamName, "QoS2 outgoing PUBREL"); err != nil { 1357 return nil, err 1358 } else if si == nil { 1359 // Create the stream for the incoming QoS2 messages that have not been 1360 // PUBREL-ed by the sender. NATS messages are submitted as 1361 // "$MQTT.pubrel.<session hash>" 1362 cfg := &StreamConfig{ 1363 Name: mqttOutStreamName, 1364 Subjects: []string{mqttOutSubjectPrefix + ">"}, 1365 Storage: FileStorage, 1366 Retention: InterestPolicy, 1367 Replicas: replicas, 1368 } 1369 if _, _, err := jsa.createStream(cfg); isErrorOtherThan(err, JSStreamNameExistErr) { 1370 return nil, fmt.Errorf("create QoS2 outgoing PUBREL stream for account %q: %v", accName, err) 1371 } 1372 } 1373 1374 // This is the only case where we need "si" after lookup/create 1375 needToTransfer := true 1376 si, err := lookupStream(mqttRetainedMsgsStreamName, "retained messages") 1377 switch { 1378 case err != nil: 1379 return nil, err 1380 1381 case si == nil: 1382 // Create the stream for retained messages. 1383 cfg := &StreamConfig{ 1384 Name: mqttRetainedMsgsStreamName, 1385 Subjects: []string{mqttRetainedMsgsStreamSubject + ">"}, 1386 Storage: FileStorage, 1387 Retention: LimitsPolicy, 1388 Replicas: replicas, 1389 MaxMsgsPer: 1, 1390 } 1391 // We will need "si" outside of this block. 1392 si, _, err = jsa.createStream(cfg) 1393 if err != nil { 1394 if isErrorOtherThan(err, JSStreamNameExistErr) { 1395 return nil, fmt.Errorf("create retained messages stream for account %q: %v", accName, err) 1396 } 1397 // Suppose we had a race and the stream was actually created by another 1398 // node, we really need "si" after that, so lookup the stream again here. 1399 si, err = lookupStream(mqttRetainedMsgsStreamName, "retained messages") 1400 if err != nil { 1401 return nil, err 1402 } 1403 } 1404 needToTransfer = false 1405 1406 default: 1407 needToTransfer = si.Config.MaxMsgsPer != 1 1408 } 1409 1410 // Doing this check outside of above if/else due to possible race when 1411 // creating the stream. 1412 wantedSubj := mqttRetainedMsgsStreamSubject + ">" 1413 if len(si.Config.Subjects) != 1 || si.Config.Subjects[0] != wantedSubj { 1414 // Update only the Subjects at this stage, not MaxMsgsPer yet. 1415 si.Config.Subjects = []string{wantedSubj} 1416 if si, err = jsa.updateStream(&si.Config); err != nil { 1417 return nil, fmt.Errorf("failed to update stream config: %w", err) 1418 } 1419 } 1420 1421 transferRMS := func() error { 1422 if !needToTransfer { 1423 return nil 1424 } 1425 1426 as.transferRetainedToPerKeySubjectStream(s) 1427 1428 // We need another lookup to have up-to-date si.State values in order 1429 // to load all retained messages. 1430 si, err = lookupStream(mqttRetainedMsgsStreamName, "retained messages") 1431 if err != nil { 1432 return err 1433 } 1434 needToTransfer = false 1435 return nil 1436 } 1437 1438 // Attempt to transfer all "single subject" retained messages to new 1439 // subjects. It may fail, will log its own error; ignore it the first time 1440 // and proceed to updating MaxMsgsPer. Then we invoke transferRMS() again, 1441 // which will get another chance to resolve the error; if not we bail there. 1442 if err = transferRMS(); err != nil { 1443 return nil, err 1444 } 1445 1446 // Now, if the stream does not have MaxMsgsPer set to 1, and there are no 1447 // more messages on the single $MQTT.rmsgs subject, update the stream again. 1448 if si.Config.MaxMsgsPer != 1 { 1449 si.Config.MaxMsgsPer = 1 1450 // We will need an up-to-date si, so don't use local variable here. 1451 if si, err = jsa.updateStream(&si.Config); err != nil { 1452 return nil, fmt.Errorf("failed to update stream config: %w", err) 1453 } 1454 } 1455 1456 // If we failed the first time, there is now at most one lingering message 1457 // in the old subject. Try again (it will be a NO-OP if succeeded the first 1458 // time). 1459 if err = transferRMS(); err != nil { 1460 return nil, err 1461 } 1462 1463 var lastSeq uint64 1464 var rmDoneCh chan struct{} 1465 st := si.State 1466 if st.Msgs > 0 { 1467 lastSeq = st.LastSeq 1468 if lastSeq > 0 { 1469 rmDoneCh = make(chan struct{}) 1470 as.rrmLastSeq = lastSeq 1471 as.rrmDoneCh = rmDoneCh 1472 } 1473 } 1474 1475 // Opportunistically delete the old (legacy) consumer, from v2.10.10 and 1476 // before. Ignore any errors that might arise. 1477 rmLegacyDurName := mqttRetainedMsgsStreamName + "_" + jsa.id 1478 jsa.deleteConsumer(mqttRetainedMsgsStreamName, rmLegacyDurName) 1479 1480 // Create a new, uniquely names consumer for retained messages for this 1481 // server. The prior one will expire eventually. 1482 ccfg := &CreateConsumerRequest{ 1483 Stream: mqttRetainedMsgsStreamName, 1484 Config: ConsumerConfig{ 1485 Name: mqttRetainedMsgsStreamName + "_" + nuid.Next(), 1486 FilterSubject: mqttRetainedMsgsStreamSubject + ">", 1487 DeliverSubject: rmsubj, 1488 ReplayPolicy: ReplayInstant, 1489 AckPolicy: AckNone, 1490 InactiveThreshold: 5 * time.Minute, 1491 }, 1492 } 1493 if _, err := jsa.createEphemeralConsumer(ccfg); err != nil { 1494 return nil, fmt.Errorf("create retained messages consumer for account %q: %v", accName, err) 1495 } 1496 1497 if lastSeq > 0 { 1498 ttl := time.NewTimer(mqttJSAPITimeout) 1499 defer ttl.Stop() 1500 1501 select { 1502 case <-rmDoneCh: 1503 case <-ttl.C: 1504 s.Warnf("Timing out waiting to load %v retained messages", st.Msgs) 1505 case <-quitCh: 1506 return nil, ErrServerNotRunning 1507 } 1508 } 1509 1510 // Set this so that on defer we don't cleanup. 1511 success = true 1512 1513 return as, nil 1514 } 1515 1516 func (s *Server) mqttDetermineReplicas() int { 1517 // If not clustered, then replica will be 1. 1518 if !s.JetStreamIsClustered() { 1519 return 1 1520 } 1521 opts := s.getOpts() 1522 replicas := 0 1523 for _, u := range opts.Routes { 1524 host := u.Hostname() 1525 // If this is an IP just add one. 1526 if net.ParseIP(host) != nil { 1527 replicas++ 1528 } else { 1529 addrs, _ := net.LookupHost(host) 1530 replicas += len(addrs) 1531 } 1532 } 1533 if replicas < 1 { 1534 replicas = 1 1535 } else if replicas > 3 { 1536 replicas = 3 1537 } 1538 return replicas 1539 } 1540 1541 ////////////////////////////////////////////////////////////////////////////// 1542 // 1543 // JS APIs related functions 1544 // 1545 ////////////////////////////////////////////////////////////////////////////// 1546 1547 func (jsa *mqttJSA) newRequest(kind, subject string, hdr int, msg []byte) (any, error) { 1548 return jsa.newRequestEx(kind, subject, _EMPTY_, hdr, msg, mqttJSAPITimeout) 1549 } 1550 1551 func (jsa *mqttJSA) prefixDomain(subject string) string { 1552 if jsa.domain != _EMPTY_ { 1553 // rewrite js api prefix with domain 1554 if sub := strings.TrimPrefix(subject, JSApiPrefix+"."); sub != subject { 1555 subject = fmt.Sprintf("$JS.%s.API.%s", jsa.domain, sub) 1556 } 1557 } 1558 return subject 1559 } 1560 1561 func (jsa *mqttJSA) newRequestEx(kind, subject, cidHash string, hdr int, msg []byte, timeout time.Duration) (any, error) { 1562 responses, err := jsa.newRequestExMulti(kind, subject, cidHash, []int{hdr}, [][]byte{msg}, timeout) 1563 if err != nil { 1564 return nil, err 1565 } 1566 if len(responses) != 1 { 1567 return nil, fmt.Errorf("unreachable: invalid number of responses (%d)", len(responses)) 1568 } 1569 return responses[0].value, nil 1570 } 1571 1572 // newRequestExMulti sends multiple messages on the same subject and waits for 1573 // all responses. It returns the same number of responses in the same order as 1574 // msgs parameter. In case of a timeout it returns an error as well as all 1575 // responses received as a sparsely populated array, matching msgs, with nils 1576 // for the values that have not yet been received. 1577 // 1578 // Note that each response may represent an error and should be inspected as 1579 // such by the caller. 1580 func (jsa *mqttJSA) newRequestExMulti(kind, subject, cidHash string, hdrs []int, msgs [][]byte, timeout time.Duration) ([]*mqttJSAResponse, error) { 1581 if len(hdrs) != len(msgs) { 1582 return nil, fmt.Errorf("unreachable: invalid number of messages (%d) or header offsets (%d)", len(msgs), len(hdrs)) 1583 } 1584 responseCh := make(chan *mqttJSAResponse, len(msgs)) 1585 1586 // Generate and queue all outgoing requests, have all results reported to 1587 // responseCh, and store a map of reply subjects to the original subjects' 1588 // indices. 1589 r2i := map[string]int{} 1590 for i, msg := range msgs { 1591 hdr := hdrs[i] 1592 var sb strings.Builder 1593 // Either we use nuid.Next() which uses a global lock, or our own nuid object, but 1594 // then it needs to be "write" protected. This approach will reduce across account 1595 // contention since we won't use the global nuid's lock. 1596 jsa.mu.Lock() 1597 uid := jsa.nuid.Next() 1598 sb.WriteString(jsa.rplyr) 1599 jsa.mu.Unlock() 1600 1601 sb.WriteString(kind) 1602 sb.WriteByte(btsep) 1603 if cidHash != _EMPTY_ { 1604 sb.WriteString(cidHash) 1605 sb.WriteByte(btsep) 1606 } 1607 sb.WriteString(uid) 1608 reply := sb.String() 1609 1610 // Add responseCh to the reply channel map. It will be cleaned out on 1611 // timeout (see below), or in processJSAPIReplies upon receiving the 1612 // response. 1613 jsa.replies.Store(reply, responseCh) 1614 1615 subject = jsa.prefixDomain(subject) 1616 jsa.sendq.push(&mqttJSPubMsg{ 1617 subj: subject, 1618 reply: reply, 1619 hdr: hdr, 1620 msg: msg, 1621 }) 1622 r2i[reply] = i 1623 } 1624 1625 // Wait for all responses to come back, or for the timeout to expire. We 1626 // don't want to use time.After() which causes memory growth because the 1627 // timer can't be stopped and will need to expire to then be garbage 1628 // collected. 1629 c := 0 1630 responses := make([]*mqttJSAResponse, len(msgs)) 1631 start := time.Now() 1632 t := time.NewTimer(timeout) 1633 defer t.Stop() 1634 for { 1635 select { 1636 case r := <-responseCh: 1637 i := r2i[r.reply] 1638 responses[i] = r 1639 c++ 1640 if c == len(msgs) { 1641 return responses, nil 1642 } 1643 1644 case <-jsa.quitCh: 1645 return nil, ErrServerNotRunning 1646 1647 case <-t.C: 1648 var reply string 1649 now := time.Now() 1650 for reply = range r2i { // preserve the last value for Errorf 1651 jsa.replies.Delete(reply) 1652 } 1653 1654 if len(msgs) == 1 { 1655 return responses, fmt.Errorf("timeout after %v: request type %q on %q (reply=%q)", now.Sub(start), kind, subject, reply) 1656 } else { 1657 return responses, fmt.Errorf("timeout after %v: request type %q on %q: got %d out of %d", now.Sub(start), kind, subject, c, len(msgs)) 1658 } 1659 } 1660 } 1661 } 1662 1663 func (jsa *mqttJSA) sendAck(ackSubject string) { 1664 // We pass -1 for the hdr so that the send loop does not need to 1665 // add the "client info" header. This is not a JS API request per se. 1666 jsa.sendMsg(ackSubject, nil) 1667 } 1668 1669 func (jsa *mqttJSA) sendMsg(subj string, msg []byte) { 1670 if subj == _EMPTY_ { 1671 return 1672 } 1673 jsa.sendq.push(&mqttJSPubMsg{subj: subj, msg: msg, hdr: -1}) 1674 } 1675 1676 func (jsa *mqttJSA) createEphemeralConsumer(cfg *CreateConsumerRequest) (*JSApiConsumerCreateResponse, error) { 1677 cfgb, err := json.Marshal(cfg) 1678 if err != nil { 1679 return nil, err 1680 } 1681 subj := fmt.Sprintf(JSApiConsumerCreateT, cfg.Stream) 1682 ccri, err := jsa.newRequest(mqttJSAConsumerCreate, subj, 0, cfgb) 1683 if err != nil { 1684 return nil, err 1685 } 1686 ccr := ccri.(*JSApiConsumerCreateResponse) 1687 return ccr, ccr.ToError() 1688 } 1689 1690 func (jsa *mqttJSA) createDurableConsumer(cfg *CreateConsumerRequest) (*JSApiConsumerCreateResponse, error) { 1691 cfgb, err := json.Marshal(cfg) 1692 if err != nil { 1693 return nil, err 1694 } 1695 subj := fmt.Sprintf(JSApiDurableCreateT, cfg.Stream, cfg.Config.Durable) 1696 ccri, err := jsa.newRequest(mqttJSAConsumerCreate, subj, 0, cfgb) 1697 if err != nil { 1698 return nil, err 1699 } 1700 ccr := ccri.(*JSApiConsumerCreateResponse) 1701 return ccr, ccr.ToError() 1702 } 1703 1704 func (jsa *mqttJSA) deleteConsumer(streamName, consName string) (*JSApiConsumerDeleteResponse, error) { 1705 subj := fmt.Sprintf(JSApiConsumerDeleteT, streamName, consName) 1706 cdri, err := jsa.newRequest(mqttJSAConsumerDel, subj, 0, nil) 1707 if err != nil { 1708 return nil, err 1709 } 1710 cdr := cdri.(*JSApiConsumerDeleteResponse) 1711 return cdr, cdr.ToError() 1712 } 1713 1714 func (jsa *mqttJSA) createStream(cfg *StreamConfig) (*StreamInfo, bool, error) { 1715 cfgb, err := json.Marshal(cfg) 1716 if err != nil { 1717 return nil, false, err 1718 } 1719 scri, err := jsa.newRequest(mqttJSAStreamCreate, fmt.Sprintf(JSApiStreamCreateT, cfg.Name), 0, cfgb) 1720 if err != nil { 1721 return nil, false, err 1722 } 1723 scr := scri.(*JSApiStreamCreateResponse) 1724 return scr.StreamInfo, scr.DidCreate, scr.ToError() 1725 } 1726 1727 func (jsa *mqttJSA) updateStream(cfg *StreamConfig) (*StreamInfo, error) { 1728 cfgb, err := json.Marshal(cfg) 1729 if err != nil { 1730 return nil, err 1731 } 1732 scri, err := jsa.newRequest(mqttJSAStreamUpdate, fmt.Sprintf(JSApiStreamUpdateT, cfg.Name), 0, cfgb) 1733 if err != nil { 1734 return nil, err 1735 } 1736 scr := scri.(*JSApiStreamUpdateResponse) 1737 return scr.StreamInfo, scr.ToError() 1738 } 1739 1740 func (jsa *mqttJSA) lookupStream(name string) (*StreamInfo, error) { 1741 slri, err := jsa.newRequest(mqttJSAStreamLookup, fmt.Sprintf(JSApiStreamInfoT, name), 0, nil) 1742 if err != nil { 1743 return nil, err 1744 } 1745 slr := slri.(*JSApiStreamInfoResponse) 1746 return slr.StreamInfo, slr.ToError() 1747 } 1748 1749 func (jsa *mqttJSA) deleteStream(name string) (bool, error) { 1750 sdri, err := jsa.newRequest(mqttJSAStreamDel, fmt.Sprintf(JSApiStreamDeleteT, name), 0, nil) 1751 if err != nil { 1752 return false, err 1753 } 1754 sdr := sdri.(*JSApiStreamDeleteResponse) 1755 return sdr.Success, sdr.ToError() 1756 } 1757 1758 func (jsa *mqttJSA) loadLastMsgFor(streamName string, subject string) (*StoredMsg, error) { 1759 mreq := &JSApiMsgGetRequest{LastFor: subject} 1760 req, err := json.Marshal(mreq) 1761 if err != nil { 1762 return nil, err 1763 } 1764 lmri, err := jsa.newRequest(mqttJSAMsgLoad, fmt.Sprintf(JSApiMsgGetT, streamName), 0, req) 1765 if err != nil { 1766 return nil, err 1767 } 1768 lmr := lmri.(*JSApiMsgGetResponse) 1769 return lmr.Message, lmr.ToError() 1770 } 1771 1772 func (jsa *mqttJSA) loadLastMsgForMulti(streamName string, subjects []string) ([]*JSApiMsgGetResponse, error) { 1773 marshaled := make([][]byte, 0, len(subjects)) 1774 headerBytes := make([]int, 0, len(subjects)) 1775 for _, subject := range subjects { 1776 mreq := &JSApiMsgGetRequest{LastFor: subject} 1777 bb, err := json.Marshal(mreq) 1778 if err != nil { 1779 return nil, err 1780 } 1781 marshaled = append(marshaled, bb) 1782 headerBytes = append(headerBytes, 0) 1783 } 1784 1785 all, err := jsa.newRequestExMulti(mqttJSAMsgLoad, fmt.Sprintf(JSApiMsgGetT, streamName), _EMPTY_, headerBytes, marshaled, mqttJSAPITimeout) 1786 // all has the same order as subjects, preserve it as we unmarshal 1787 responses := make([]*JSApiMsgGetResponse, len(all)) 1788 for i, v := range all { 1789 if v != nil { 1790 responses[i] = v.value.(*JSApiMsgGetResponse) 1791 } 1792 } 1793 return responses, err 1794 } 1795 1796 func (jsa *mqttJSA) loadNextMsgFor(streamName string, subject string) (*StoredMsg, error) { 1797 mreq := &JSApiMsgGetRequest{NextFor: subject} 1798 req, err := json.Marshal(mreq) 1799 if err != nil { 1800 return nil, err 1801 } 1802 lmri, err := jsa.newRequest(mqttJSAMsgLoad, fmt.Sprintf(JSApiMsgGetT, streamName), 0, req) 1803 if err != nil { 1804 return nil, err 1805 } 1806 lmr := lmri.(*JSApiMsgGetResponse) 1807 return lmr.Message, lmr.ToError() 1808 } 1809 1810 func (jsa *mqttJSA) loadMsg(streamName string, seq uint64) (*StoredMsg, error) { 1811 mreq := &JSApiMsgGetRequest{Seq: seq} 1812 req, err := json.Marshal(mreq) 1813 if err != nil { 1814 return nil, err 1815 } 1816 lmri, err := jsa.newRequest(mqttJSAMsgLoad, fmt.Sprintf(JSApiMsgGetT, streamName), 0, req) 1817 if err != nil { 1818 return nil, err 1819 } 1820 lmr := lmri.(*JSApiMsgGetResponse) 1821 return lmr.Message, lmr.ToError() 1822 } 1823 1824 func (jsa *mqttJSA) storeMsg(subject string, headers int, msg []byte) (*JSPubAckResponse, error) { 1825 return jsa.storeMsgWithKind(mqttJSAMsgStore, subject, headers, msg) 1826 } 1827 1828 func (jsa *mqttJSA) storeMsgWithKind(kind, subject string, headers int, msg []byte) (*JSPubAckResponse, error) { 1829 smri, err := jsa.newRequest(kind, subject, headers, msg) 1830 if err != nil { 1831 return nil, err 1832 } 1833 smr := smri.(*JSPubAckResponse) 1834 return smr, smr.ToError() 1835 } 1836 1837 func (jsa *mqttJSA) storeSessionMsg(domainTk, cidHash string, hdr int, msg []byte) (*JSPubAckResponse, error) { 1838 // Compute subject where the session is being stored 1839 subject := mqttSessStreamSubjectPrefix + domainTk + cidHash 1840 1841 // Passing cidHash will add it to the JS reply subject, so that we can use 1842 // it in processSessionPersist. 1843 smri, err := jsa.newRequestEx(mqttJSASessPersist, subject, cidHash, hdr, msg, mqttJSAPITimeout) 1844 if err != nil { 1845 return nil, err 1846 } 1847 smr := smri.(*JSPubAckResponse) 1848 return smr, smr.ToError() 1849 } 1850 1851 func (jsa *mqttJSA) loadSessionMsg(domainTk, cidHash string) (*StoredMsg, error) { 1852 subject := mqttSessStreamSubjectPrefix + domainTk + cidHash 1853 return jsa.loadLastMsgFor(mqttSessStreamName, subject) 1854 } 1855 1856 func (jsa *mqttJSA) deleteMsg(stream string, seq uint64, wait bool) error { 1857 dreq := JSApiMsgDeleteRequest{Seq: seq, NoErase: true} 1858 req, _ := json.Marshal(dreq) 1859 subj := jsa.prefixDomain(fmt.Sprintf(JSApiMsgDeleteT, stream)) 1860 if !wait { 1861 jsa.sendq.push(&mqttJSPubMsg{ 1862 subj: subj, 1863 msg: req, 1864 }) 1865 return nil 1866 } 1867 dmi, err := jsa.newRequest(mqttJSAMsgDelete, subj, 0, req) 1868 if err != nil { 1869 return err 1870 } 1871 dm := dmi.(*JSApiMsgDeleteResponse) 1872 return dm.ToError() 1873 } 1874 1875 ////////////////////////////////////////////////////////////////////////////// 1876 // 1877 // Account Sessions Manager related functions 1878 // 1879 ////////////////////////////////////////////////////////////////////////////// 1880 1881 // Returns true if `err` is not nil and does not match the api error with ErrorIdentifier id 1882 func isErrorOtherThan(err error, id ErrorIdentifier) bool { 1883 return err != nil && !IsNatsErr(err, id) 1884 } 1885 1886 // Process JS API replies. 1887 // 1888 // Can run from various go routines (consumer's loop, system send loop, etc..). 1889 func (as *mqttAccountSessionManager) processJSAPIReplies(_ *subscription, pc *client, _ *Account, subject, _ string, msg []byte) { 1890 token := tokenAt(subject, mqttJSATokenPos) 1891 if token == _EMPTY_ { 1892 return 1893 } 1894 jsa := &as.jsa 1895 chi, ok := jsa.replies.Load(subject) 1896 if !ok { 1897 return 1898 } 1899 jsa.replies.Delete(subject) 1900 ch := chi.(chan *mqttJSAResponse) 1901 out := func(value any) { 1902 ch <- &mqttJSAResponse{reply: subject, value: value} 1903 } 1904 switch token { 1905 case mqttJSAStreamCreate: 1906 var resp = &JSApiStreamCreateResponse{} 1907 if err := json.Unmarshal(msg, resp); err != nil { 1908 resp.Error = NewJSInvalidJSONError() 1909 } 1910 out(resp) 1911 case mqttJSAStreamUpdate: 1912 var resp = &JSApiStreamUpdateResponse{} 1913 if err := json.Unmarshal(msg, resp); err != nil { 1914 resp.Error = NewJSInvalidJSONError() 1915 } 1916 out(resp) 1917 case mqttJSAStreamLookup: 1918 var resp = &JSApiStreamInfoResponse{} 1919 if err := json.Unmarshal(msg, &resp); err != nil { 1920 resp.Error = NewJSInvalidJSONError() 1921 } 1922 out(resp) 1923 case mqttJSAStreamDel: 1924 var resp = &JSApiStreamDeleteResponse{} 1925 if err := json.Unmarshal(msg, &resp); err != nil { 1926 resp.Error = NewJSInvalidJSONError() 1927 } 1928 out(resp) 1929 case mqttJSAConsumerCreate: 1930 var resp = &JSApiConsumerCreateResponse{} 1931 if err := json.Unmarshal(msg, resp); err != nil { 1932 resp.Error = NewJSInvalidJSONError() 1933 } 1934 out(resp) 1935 case mqttJSAConsumerDel: 1936 var resp = &JSApiConsumerDeleteResponse{} 1937 if err := json.Unmarshal(msg, resp); err != nil { 1938 resp.Error = NewJSInvalidJSONError() 1939 } 1940 out(resp) 1941 case mqttJSAMsgStore, mqttJSASessPersist: 1942 var resp = &JSPubAckResponse{} 1943 if err := json.Unmarshal(msg, resp); err != nil { 1944 resp.Error = NewJSInvalidJSONError() 1945 } 1946 out(resp) 1947 case mqttJSAMsgLoad: 1948 var resp = &JSApiMsgGetResponse{} 1949 if err := json.Unmarshal(msg, &resp); err != nil { 1950 resp.Error = NewJSInvalidJSONError() 1951 } 1952 out(resp) 1953 case mqttJSAStreamNames: 1954 var resp = &JSApiStreamNamesResponse{} 1955 if err := json.Unmarshal(msg, resp); err != nil { 1956 resp.Error = NewJSInvalidJSONError() 1957 } 1958 out(resp) 1959 case mqttJSAMsgDelete: 1960 var resp = &JSApiMsgDeleteResponse{} 1961 if err := json.Unmarshal(msg, resp); err != nil { 1962 resp.Error = NewJSInvalidJSONError() 1963 } 1964 out(resp) 1965 default: 1966 pc.Warnf("Unknown reply code %q", token) 1967 } 1968 } 1969 1970 // This will both load all retained messages and process updates from the cluster. 1971 // 1972 // Run from various go routines (JS consumer, etc..). 1973 // No lock held on entry. 1974 func (as *mqttAccountSessionManager) processRetainedMsg(_ *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { 1975 h, m := c.msgParts(rmsg) 1976 rm, err := mqttDecodeRetainedMessage(h, m) 1977 if err != nil { 1978 return 1979 } 1980 // If lastSeq is 0 (nothing to recover, or done doing it) and this is 1981 // from our own server, ignore. 1982 if as.rrmLastSeq == 0 && rm.Origin == as.jsa.id { 1983 return 1984 } 1985 // At this point we either recover from our own server, or process a remote retained message. 1986 seq, _, _ := ackReplyInfo(reply) 1987 1988 // Handle this retained message, no need to copy the bytes. 1989 as.handleRetainedMsg(rm.Subject, &mqttRetainedMsgRef{sseq: seq}, rm, false) 1990 1991 // If we were recovering (lastSeq > 0), then check if we are done. 1992 if as.rrmLastSeq > 0 && seq >= as.rrmLastSeq { 1993 as.rrmLastSeq = 0 1994 close(as.rrmDoneCh) 1995 as.rrmDoneCh = nil 1996 } 1997 } 1998 1999 func (as *mqttAccountSessionManager) processRetainedMsgDel(_ *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { 2000 idHash := tokenAt(subject, 3) 2001 if idHash == _EMPTY_ || idHash == as.jsa.id { 2002 return 2003 } 2004 _, msg := c.msgParts(rmsg) 2005 if len(msg) < LEN_CR_LF { 2006 return 2007 } 2008 var drm mqttRetMsgDel 2009 if err := json.Unmarshal(msg, &drm); err != nil { 2010 return 2011 } 2012 as.handleRetainedMsgDel(drm.Subject, drm.Seq) 2013 } 2014 2015 // This will receive all JS API replies for a request to store a session record, 2016 // including the reply for our own server, which we will ignore. 2017 // This allows us to detect that some application somewhere else in the cluster 2018 // is connecting with the same client ID, and therefore we need to close the 2019 // connection that is currently using this client ID. 2020 // 2021 // Can run from various go routines (system send loop, etc..). 2022 // No lock held on entry. 2023 func (as *mqttAccountSessionManager) processSessionPersist(_ *subscription, pc *client, _ *Account, subject, _ string, rmsg []byte) { 2024 // Ignore our own responses here (they are handled elsewhere) 2025 if tokenAt(subject, mqttJSAIdTokenPos) == as.jsa.id { 2026 return 2027 } 2028 cIDHash := tokenAt(subject, mqttJSAClientIDPos) 2029 _, msg := pc.msgParts(rmsg) 2030 if len(msg) < LEN_CR_LF { 2031 return 2032 } 2033 var par = &JSPubAckResponse{} 2034 if err := json.Unmarshal(msg, par); err != nil { 2035 return 2036 } 2037 if err := par.Error; err != nil { 2038 return 2039 } 2040 as.mu.RLock() 2041 // Note that as.domainTk includes a terminal '.', so strip to compare to PubAck.Domain. 2042 dl := len(as.domainTk) 2043 if dl > 0 { 2044 dl-- 2045 } 2046 ignore := par.Domain != as.domainTk[:dl] 2047 as.mu.RUnlock() 2048 if ignore { 2049 return 2050 } 2051 2052 as.mu.Lock() 2053 defer as.mu.Unlock() 2054 sess, ok := as.sessByHash[cIDHash] 2055 if !ok { 2056 return 2057 } 2058 // If our current session's stream sequence is higher, it means that this 2059 // update is stale, so we don't do anything here. 2060 sess.mu.Lock() 2061 ignore = par.Sequence < sess.seq 2062 sess.mu.Unlock() 2063 if ignore { 2064 return 2065 } 2066 as.removeSession(sess, false) 2067 sess.mu.Lock() 2068 if ec := sess.c; ec != nil { 2069 as.addSessToFlappers(sess.id) 2070 ec.Warnf("Closing because a remote connection has started with the same client ID: %q", sess.id) 2071 // Disassociate the client from the session so that on client close, 2072 // nothing will be done with regards to cleaning up the session, 2073 // such as deleting stream, etc.. 2074 sess.c = nil 2075 // Remove in separate go routine. 2076 go ec.closeConnection(DuplicateClientID) 2077 } 2078 sess.mu.Unlock() 2079 } 2080 2081 // Adds this client ID to the flappers map, and if needed start the timer 2082 // for map cleanup. 2083 // 2084 // Lock held on entry. 2085 func (as *mqttAccountSessionManager) addSessToFlappers(clientID string) { 2086 as.flappers[clientID] = time.Now().UnixNano() 2087 if as.flapTimer == nil { 2088 as.flapTimer = time.AfterFunc(mqttFlapCleanItvl, func() { 2089 as.mu.Lock() 2090 defer as.mu.Unlock() 2091 // In case of shutdown, this will be nil 2092 if as.flapTimer == nil { 2093 return 2094 } 2095 now := time.Now().UnixNano() 2096 for cID, tm := range as.flappers { 2097 if now-tm > int64(mqttSessJailDur) { 2098 delete(as.flappers, cID) 2099 } 2100 } 2101 as.flapTimer.Reset(mqttFlapCleanItvl) 2102 }) 2103 } 2104 } 2105 2106 // Remove this client ID from the flappers map. 2107 // 2108 // Lock held on entry. 2109 func (as *mqttAccountSessionManager) removeSessFromFlappers(clientID string) { 2110 delete(as.flappers, clientID) 2111 // Do not stop/set timer to nil here. Better leave the timer run at its 2112 // regular interval and detect that there is nothing to do. The timer 2113 // will be stopped on shutdown. 2114 } 2115 2116 // Helper to create a subscription. It updates the sid and array of subscriptions. 2117 func (as *mqttAccountSessionManager) createSubscription(subject string, cb msgHandler, sid *int64, subs *[]*subscription) error { 2118 sub, err := as.jsa.c.processSub([]byte(subject), nil, []byte(strconv.FormatInt(*sid, 10)), cb, false) 2119 if err != nil { 2120 return err 2121 } 2122 *sid++ 2123 *subs = append(*subs, sub) 2124 return nil 2125 } 2126 2127 // A timer loop to cleanup up expired cached retained messages for a given MQTT account. 2128 // The closeCh is used by the caller to be able to interrupt this routine 2129 // if the rest of the initialization fails, since the quitCh is really 2130 // only used when the server shutdown. 2131 // 2132 // No lock held on entry. 2133 func (as *mqttAccountSessionManager) cleanupRetainedMessageCache(s *Server, closeCh chan struct{}) { 2134 tt := time.NewTicker(mqttRetainedCacheTTL) 2135 defer tt.Stop() 2136 for { 2137 select { 2138 case <-tt.C: 2139 // Set a limit to the number of retained messages to scan since we 2140 // lock as for it. Since the map enumeration gives random order we 2141 // should eventually clean up everything. 2142 i, maxScan := 0, 10*1000 2143 now := time.Now() 2144 as.rmsCache.Range(func(key, value any) bool { 2145 rm := value.(*mqttRetainedMsg) 2146 if now.After(rm.expiresFromCache) { 2147 as.rmsCache.Delete(key) 2148 } 2149 i++ 2150 return i < maxScan 2151 }) 2152 2153 case <-closeCh: 2154 return 2155 case <-s.quitCh: 2156 return 2157 } 2158 } 2159 } 2160 2161 // Loop to send JS API requests for a given MQTT account. 2162 // The closeCh is used by the caller to be able to interrupt this routine 2163 // if the rest of the initialization fails, since the quitCh is really 2164 // only used when the server shutdown. 2165 // 2166 // No lock held on entry. 2167 func (as *mqttAccountSessionManager) sendJSAPIrequests(s *Server, c *client, accName string, closeCh chan struct{}) { 2168 var cluster string 2169 if s.JetStreamEnabled() && !as.jsa.domainSet { 2170 // Only request the own cluster when it is clear that 2171 cluster = s.cachedClusterName() 2172 } 2173 as.mu.RLock() 2174 sendq := as.jsa.sendq 2175 quitCh := as.jsa.quitCh 2176 ci := ClientInfo{Account: accName, Cluster: cluster} 2177 as.mu.RUnlock() 2178 2179 // The account session manager does not have a suhtdown API per-se, instead, 2180 // we will cleanup things when this go routine exits after detecting that the 2181 // server is shutdown or the initialization of the account manager failed. 2182 defer func() { 2183 as.mu.Lock() 2184 if as.flapTimer != nil { 2185 as.flapTimer.Stop() 2186 as.flapTimer = nil 2187 } 2188 as.mu.Unlock() 2189 }() 2190 2191 b, _ := json.Marshal(ci) 2192 hdrStart := bytes.Buffer{} 2193 hdrStart.WriteString(hdrLine) 2194 http.Header{ClientInfoHdr: []string{string(b)}}.Write(&hdrStart) 2195 hdrStart.WriteString(CR_LF) 2196 hdrStart.WriteString(CR_LF) 2197 hdrb := hdrStart.Bytes() 2198 2199 for { 2200 select { 2201 case <-sendq.ch: 2202 pmis := sendq.pop() 2203 for _, r := range pmis { 2204 var nsize int 2205 2206 msg := r.msg 2207 // If r.hdr is set to -1, it means that there is no need for any header. 2208 if r.hdr != -1 { 2209 bb := bytes.Buffer{} 2210 if r.hdr > 0 { 2211 // This means that the header has been set by the caller and is 2212 // already part of `msg`, so simply set c.pa.hdr to the given value. 2213 c.pa.hdr = r.hdr 2214 nsize = len(msg) 2215 msg = append(msg, _CRLF_...) 2216 } else { 2217 // We need the ClientInfo header, so add it here. 2218 bb.Write(hdrb) 2219 c.pa.hdr = bb.Len() 2220 bb.Write(r.msg) 2221 nsize = bb.Len() 2222 bb.WriteString(_CRLF_) 2223 msg = bb.Bytes() 2224 } 2225 c.pa.hdb = []byte(strconv.Itoa(c.pa.hdr)) 2226 } else { 2227 c.pa.hdr = -1 2228 c.pa.hdb = nil 2229 nsize = len(msg) 2230 msg = append(msg, _CRLF_...) 2231 } 2232 2233 c.pa.subject = []byte(r.subj) 2234 c.pa.reply = []byte(r.reply) 2235 c.pa.size = nsize 2236 c.pa.szb = []byte(strconv.Itoa(nsize)) 2237 2238 c.processInboundClientMsg(msg) 2239 c.flushClients(0) 2240 } 2241 sendq.recycle(&pmis) 2242 2243 case <-closeCh: 2244 return 2245 case <-quitCh: 2246 return 2247 } 2248 } 2249 } 2250 2251 // Add/Replace this message from the retained messages map. 2252 // If a message for this topic already existed, the existing record is updated 2253 // with the provided information. 2254 // Lock not held on entry. 2255 func (as *mqttAccountSessionManager) handleRetainedMsg(key string, rf *mqttRetainedMsgRef, rm *mqttRetainedMsg, copyBytesToCache bool) { 2256 as.mu.Lock() 2257 defer as.mu.Unlock() 2258 if as.retmsgs == nil { 2259 as.retmsgs = make(map[string]*mqttRetainedMsgRef) 2260 as.sl = NewSublistWithCache() 2261 } else { 2262 // Check if we already had one retained message. If so, update the existing one. 2263 if erm, exists := as.retmsgs[key]; exists { 2264 // If the new sequence is below the floor or the existing one, 2265 // then ignore the new one. 2266 if rf.sseq <= erm.sseq || rf.sseq <= erm.floor { 2267 return 2268 } 2269 // Capture existing sequence number so we can return it as the old sequence. 2270 erm.sseq = rf.sseq 2271 // Clear the floor 2272 erm.floor = 0 2273 // If sub is nil, it means that it was removed from sublist following a 2274 // network delete. So need to add it now. 2275 if erm.sub == nil { 2276 erm.sub = &subscription{subject: []byte(key)} 2277 as.sl.Insert(erm.sub) 2278 } 2279 2280 // Update the in-memory retained message cache but only for messages 2281 // that are already in the cache, i.e. have been (recently) used. 2282 as.setCachedRetainedMsg(key, rm, true, copyBytesToCache) 2283 return 2284 } 2285 } 2286 2287 rf.sub = &subscription{subject: []byte(key)} 2288 as.retmsgs[key] = rf 2289 as.sl.Insert(rf.sub) 2290 } 2291 2292 // Removes the retained message for the given `subject` if present, and returns the 2293 // stream sequence it was stored at. It will be 0 if no retained message was removed. 2294 // If a sequence is passed and not 0, then the retained message will be removed only 2295 // if the given sequence is equal or higher to what is stored. 2296 // 2297 // No lock held on entry. 2298 func (as *mqttAccountSessionManager) handleRetainedMsgDel(subject string, seq uint64) uint64 { 2299 var seqToRemove uint64 2300 as.mu.Lock() 2301 if as.retmsgs == nil { 2302 as.retmsgs = make(map[string]*mqttRetainedMsgRef) 2303 as.sl = NewSublistWithCache() 2304 } 2305 if erm, ok := as.retmsgs[subject]; ok { 2306 if as.rmsCache != nil { 2307 as.rmsCache.Delete(subject) 2308 } 2309 if erm.sub != nil { 2310 as.sl.Remove(erm.sub) 2311 erm.sub = nil 2312 } 2313 // If processing a delete request from the network, then seq will be > 0. 2314 // If that is the case and it is greater or equal to what we have, we need 2315 // to record the floor for this subject. 2316 if seq != 0 && seq >= erm.sseq { 2317 erm.sseq = 0 2318 erm.floor = seq 2319 } else if seq == 0 { 2320 delete(as.retmsgs, subject) 2321 seqToRemove = erm.sseq 2322 } 2323 } else if seq != 0 { 2324 rf := &mqttRetainedMsgRef{floor: seq} 2325 as.retmsgs[subject] = rf 2326 } 2327 as.mu.Unlock() 2328 return seqToRemove 2329 } 2330 2331 // First check if this session's client ID is already in the "locked" map, 2332 // which if it is the case means that another client is now bound to this 2333 // session and this should return an error. 2334 // If not in the "locked" map, but the client is not bound with this session, 2335 // then same error is returned. 2336 // Finally, if all checks ok, then the session's ID is added to the "locked" map. 2337 // 2338 // No lock held on entry. 2339 func (as *mqttAccountSessionManager) lockSession(sess *mqttSession, c *client) error { 2340 as.mu.Lock() 2341 defer as.mu.Unlock() 2342 var fail bool 2343 if _, fail = as.sessLocked[sess.id]; !fail { 2344 sess.mu.Lock() 2345 fail = sess.c != c 2346 sess.mu.Unlock() 2347 } 2348 if fail { 2349 return fmt.Errorf("another session is in use with client ID %q", sess.id) 2350 } 2351 as.sessLocked[sess.id] = struct{}{} 2352 return nil 2353 } 2354 2355 // Remove the session from the "locked" map. 2356 // 2357 // No lock held on entry. 2358 func (as *mqttAccountSessionManager) unlockSession(sess *mqttSession) { 2359 as.mu.Lock() 2360 delete(as.sessLocked, sess.id) 2361 as.mu.Unlock() 2362 } 2363 2364 // Simply adds the session to the various sessions maps. 2365 // The boolean `lock` indicates if this function should acquire the lock 2366 // prior to adding to the maps. 2367 // 2368 // No lock held on entry. 2369 func (as *mqttAccountSessionManager) addSession(sess *mqttSession, lock bool) { 2370 if lock { 2371 as.mu.Lock() 2372 } 2373 as.sessions[sess.id] = sess 2374 as.sessByHash[sess.idHash] = sess 2375 if lock { 2376 as.mu.Unlock() 2377 } 2378 } 2379 2380 // Simply removes the session from the various sessions maps. 2381 // The boolean `lock` indicates if this function should acquire the lock 2382 // prior to removing from the maps. 2383 // 2384 // No lock held on entry. 2385 func (as *mqttAccountSessionManager) removeSession(sess *mqttSession, lock bool) { 2386 if lock { 2387 as.mu.Lock() 2388 } 2389 delete(as.sessions, sess.id) 2390 delete(as.sessByHash, sess.idHash) 2391 if lock { 2392 as.mu.Unlock() 2393 } 2394 } 2395 2396 // Helper to set the sub's mqtt fields and possibly serialize (pre-loaded) 2397 // retained messages. 2398 // 2399 // Session lock held on entry. Acquires the subs lock and holds it for 2400 // the duration. Non-MQTT messages coming into mqttDeliverMsgCbQoS0 will be 2401 // waiting. 2402 func (sess *mqttSession) processQOS12Sub( 2403 c *client, // subscribing client. 2404 subject, sid []byte, isReserved bool, qos byte, jsDurName string, h msgHandler, // subscription parameters. 2405 ) (*subscription, error) { 2406 return sess.processSub(c, subject, sid, isReserved, qos, jsDurName, h, false, nil, false, nil) 2407 } 2408 2409 func (sess *mqttSession) processSub( 2410 c *client, // subscribing client. 2411 subject, sid []byte, isReserved bool, qos byte, jsDurName string, h msgHandler, // subscription parameters. 2412 initShadow bool, // do we need to scan for shadow subscriptions? (not for QOS1+) 2413 rms map[string]*mqttRetainedMsg, // preloaded rms (can be empty, or missing items if errors) 2414 trace bool, // trace serialized retained messages in the log? 2415 as *mqttAccountSessionManager, // needed only for rms serialization. 2416 ) (*subscription, error) { 2417 start := time.Now() 2418 defer func() { 2419 elapsed := time.Since(start) 2420 if elapsed > mqttProcessSubTooLong { 2421 c.Warnf("Took too long to process subscription for %q: %v", subject, elapsed) 2422 } 2423 }() 2424 2425 // Hold subsMu to prevent QOS0 messages callback from doing anything until 2426 // the (MQTT) sub is initialized. 2427 sess.subsMu.Lock() 2428 defer sess.subsMu.Unlock() 2429 2430 sub, err := c.processSub(subject, nil, sid, h, false) 2431 if err != nil { 2432 // c.processSub already called c.Errorf(), so no need here. 2433 return nil, err 2434 } 2435 subs := []*subscription{sub} 2436 if initShadow { 2437 subs = append(subs, sub.shadow...) 2438 } 2439 for _, ss := range subs { 2440 if ss.mqtt == nil { 2441 // reserved is set only once and once the subscription has been 2442 // created it can be considered immutable. 2443 ss.mqtt = &mqttSub{ 2444 reserved: isReserved, 2445 } 2446 } 2447 // QOS and jsDurName can be changed on an existing subscription, so 2448 // accessing it later requires a lock. 2449 ss.mqtt.qos = qos 2450 ss.mqtt.jsDur = jsDurName 2451 } 2452 2453 if len(rms) > 0 { 2454 for _, ss := range subs { 2455 as.serializeRetainedMsgsForSub(rms, sess, c, ss, trace) 2456 } 2457 } 2458 2459 return sub, nil 2460 } 2461 2462 // Process subscriptions for the given session/client. 2463 // 2464 // When `fromSubProto` is false, it means that this is invoked from the CONNECT 2465 // protocol, when restoring subscriptions that were saved for this session. 2466 // In that case, there is no need to update the session record. 2467 // 2468 // When `fromSubProto` is true, it means that this call is invoked from the 2469 // processing of the SUBSCRIBE protocol, which means that the session needs to 2470 // be updated. It also means that if a subscription on same subject with same 2471 // QoS already exist, we should not be recreating the subscription/JS durable, 2472 // since it was already done when processing the CONNECT protocol. 2473 // 2474 // Runs from the client's readLoop. 2475 // Lock not held on entry, but session is in the locked map. 2476 func (as *mqttAccountSessionManager) processSubs(sess *mqttSession, c *client, 2477 filters []*mqttFilter, fromSubProto, trace bool) ([]*subscription, error) { 2478 2479 c.mu.Lock() 2480 acc := c.acc 2481 c.mu.Unlock() 2482 2483 // Helper to determine if we need to create a separate top-level 2484 // subscription for a wildcard. 2485 fwc := func(subject string) (bool, string, string) { 2486 if !mqttNeedSubForLevelUp(subject) { 2487 return false, _EMPTY_, _EMPTY_ 2488 } 2489 // Say subject is "foo.>", remove the ".>" so that it becomes "foo" 2490 fwcsubject := subject[:len(subject)-2] 2491 // Change the sid to "foo fwc" 2492 fwcsid := fwcsubject + mqttMultiLevelSidSuffix 2493 2494 return true, fwcsubject, fwcsid 2495 } 2496 2497 rmSubjects := map[string]struct{}{} 2498 // Preload retained messages for all requested subscriptions. Also, since 2499 // it's the first iteration over the filter list, do some cleanup. 2500 for _, f := range filters { 2501 if f.qos > 2 { 2502 f.qos = 2 2503 } 2504 if c.mqtt.downgradeQoS2Sub && f.qos == 2 { 2505 c.Warnf("Downgrading subscription QoS2 to QoS1 for %q, as configured", f.filter) 2506 f.qos = 1 2507 } 2508 2509 // Do not allow subscribing to our internal subjects. 2510 // 2511 // TODO: (levb: not sure why since one can subscribe to `#` and it'll 2512 // include everything; I guess this would discourage? Otherwise another 2513 // candidate for DO NOT DELIVER prefix list). 2514 if strings.HasPrefix(f.filter, mqttSubPrefix) { 2515 f.qos = mqttSubAckFailure 2516 continue 2517 } 2518 2519 if f.qos == 2 { 2520 if err := sess.ensurePubRelConsumerSubscription(c); err != nil { 2521 c.Errorf("failed to initialize PUBREL processing: %v", err) 2522 f.qos = mqttSubAckFailure 2523 continue 2524 } 2525 } 2526 2527 // Find retained messages. 2528 if fromSubProto { 2529 addRMSubjects := func(subject string) error { 2530 sub := &subscription{ 2531 client: c, 2532 subject: []byte(subject), 2533 sid: []byte(subject), 2534 } 2535 if err := c.addShadowSubscriptions(acc, sub, false); err != nil { 2536 return err 2537 } 2538 2539 for _, sub := range append([]*subscription{sub}, sub.shadow...) { 2540 as.addRetainedSubjectsForSubject(rmSubjects, bytesToString(sub.subject)) 2541 for _, ss := range sub.shadow { 2542 as.addRetainedSubjectsForSubject(rmSubjects, bytesToString(ss.subject)) 2543 } 2544 } 2545 return nil 2546 } 2547 2548 if err := addRMSubjects(f.filter); err != nil { 2549 f.qos = mqttSubAckFailure 2550 continue 2551 } 2552 if need, subject, _ := fwc(f.filter); need { 2553 if err := addRMSubjects(subject); err != nil { 2554 f.qos = mqttSubAckFailure 2555 continue 2556 } 2557 } 2558 } 2559 } 2560 2561 serializeRMS := len(rmSubjects) > 0 2562 var rms map[string]*mqttRetainedMsg 2563 if serializeRMS { 2564 // Make the best effort to load retained messages. We will identify 2565 // errors in the next pass. 2566 rms = as.loadRetainedMessages(rmSubjects, c) 2567 } 2568 2569 // Small helper to add the consumer config to the session. 2570 addJSConsToSess := func(sid string, cc *ConsumerConfig) { 2571 if cc == nil { 2572 return 2573 } 2574 if sess.cons == nil { 2575 sess.cons = make(map[string]*ConsumerConfig) 2576 } 2577 sess.cons[sid] = cc 2578 } 2579 2580 var err error 2581 subs := make([]*subscription, 0, len(filters)) 2582 for _, f := range filters { 2583 // Skip what's already been identified as a failure. 2584 if f.qos == mqttSubAckFailure { 2585 continue 2586 } 2587 subject := f.filter 2588 bsubject := []byte(subject) 2589 sid := subject 2590 bsid := bsubject 2591 isReserved := isMQTTReservedSubscription(subject) 2592 2593 var jscons *ConsumerConfig 2594 var jssub *subscription 2595 2596 // Note that if a subscription already exists on this subject, the 2597 // existing sub is returned. Need to update the qos. 2598 var sub *subscription 2599 var err error 2600 2601 const processShadowSubs = true 2602 2603 as.mu.Lock() 2604 sess.mu.Lock() 2605 sub, err = sess.processSub(c, 2606 bsubject, bsid, isReserved, f.qos, // main subject 2607 _EMPTY_, mqttDeliverMsgCbQoS0, // no jsDur for QOS0 2608 processShadowSubs, 2609 rms, trace, as) 2610 sess.mu.Unlock() 2611 as.mu.Unlock() 2612 2613 if err != nil { 2614 f.qos = mqttSubAckFailure 2615 sess.cleanupFailedSub(c, sub, jscons, jssub) 2616 continue 2617 } 2618 2619 // This will create (if not already exist) a JS consumer for 2620 // subscriptions of QoS >= 1. But if a JS consumer already exists and 2621 // the subscription for same subject is now a QoS==0, then the JS 2622 // consumer will be deleted. 2623 jscons, jssub, err = sess.processJSConsumer(c, subject, sid, f.qos, fromSubProto) 2624 if err != nil { 2625 f.qos = mqttSubAckFailure 2626 sess.cleanupFailedSub(c, sub, jscons, jssub) 2627 continue 2628 } 2629 2630 // Process the wildcard subject if needed. 2631 if need, fwcsubject, fwcsid := fwc(subject); need { 2632 var fwjscons *ConsumerConfig 2633 var fwjssub *subscription 2634 var fwcsub *subscription 2635 2636 // See note above about existing subscription. 2637 as.mu.Lock() 2638 sess.mu.Lock() 2639 fwcsub, err = sess.processSub(c, 2640 []byte(fwcsubject), []byte(fwcsid), isReserved, f.qos, // FWC (top-level wildcard) subject 2641 _EMPTY_, mqttDeliverMsgCbQoS0, // no jsDur for QOS0 2642 processShadowSubs, 2643 rms, trace, as) 2644 sess.mu.Unlock() 2645 as.mu.Unlock() 2646 if err != nil { 2647 // c.processSub already called c.Errorf(), so no need here. 2648 f.qos = mqttSubAckFailure 2649 sess.cleanupFailedSub(c, sub, jscons, jssub) 2650 continue 2651 } 2652 2653 fwjscons, fwjssub, err = sess.processJSConsumer(c, fwcsubject, fwcsid, f.qos, fromSubProto) 2654 if err != nil { 2655 // c.processSub already called c.Errorf(), so no need here. 2656 f.qos = mqttSubAckFailure 2657 sess.cleanupFailedSub(c, sub, jscons, jssub) 2658 sess.cleanupFailedSub(c, fwcsub, fwjscons, fwjssub) 2659 continue 2660 } 2661 2662 subs = append(subs, fwcsub) 2663 addJSConsToSess(fwcsid, fwjscons) 2664 } 2665 2666 subs = append(subs, sub) 2667 addJSConsToSess(sid, jscons) 2668 } 2669 2670 if fromSubProto { 2671 err = sess.update(filters, true) 2672 } 2673 2674 return subs, err 2675 } 2676 2677 // Retained publish messages matching this subscription are serialized in the 2678 // subscription's `prm` mqtt writer. This buffer will be queued for outbound 2679 // after the subscription is processed and SUBACK is sent or possibly when 2680 // server processes an incoming published message matching the newly 2681 // registered subscription. 2682 // 2683 // Runs from the client's readLoop. 2684 // Account session manager lock held on entry. 2685 // Session lock held on entry. 2686 func (as *mqttAccountSessionManager) serializeRetainedMsgsForSub(rms map[string]*mqttRetainedMsg, sess *mqttSession, c *client, sub *subscription, trace bool) error { 2687 if len(as.retmsgs) == 0 || len(rms) == 0 { 2688 return nil 2689 } 2690 result := as.sl.ReverseMatch(string(sub.subject)) 2691 if len(result.psubs) == 0 { 2692 return nil 2693 } 2694 toTrace := []mqttPublish{} 2695 for _, psub := range result.psubs { 2696 2697 rm := rms[string(psub.subject)] 2698 if rm == nil { 2699 // This should not happen since we pre-load messages into rms before 2700 // calling serialize. 2701 continue 2702 } 2703 var pi uint16 2704 qos := mqttGetQoS(rm.Flags) 2705 if qos > sub.mqtt.qos { 2706 qos = sub.mqtt.qos 2707 } 2708 if c.mqtt.rejectQoS2Pub && qos == 2 { 2709 c.Warnf("Rejecting retained message with QoS2 for subscription %q, as configured", sub.subject) 2710 continue 2711 } 2712 if qos > 0 { 2713 pi = sess.trackPublishRetained() 2714 2715 // If we failed to get a PI for this message, send it as a QoS0, the 2716 // best we can do? 2717 if pi == 0 { 2718 qos = 0 2719 } 2720 } 2721 2722 // Need to use the subject for the retained message, not the `sub` subject. 2723 // We can find the published retained message in rm.sub.subject. 2724 // Set the RETAIN flag: [MQTT-3.3.1-8]. 2725 flags, headerBytes := mqttMakePublishHeader(pi, qos, false, true, []byte(rm.Topic), len(rm.Msg)) 2726 c.mu.Lock() 2727 sub.mqtt.prm = append(sub.mqtt.prm, headerBytes, rm.Msg) 2728 c.mu.Unlock() 2729 if trace { 2730 toTrace = append(toTrace, mqttPublish{ 2731 topic: []byte(rm.Topic), 2732 flags: flags, 2733 pi: pi, 2734 sz: len(rm.Msg), 2735 }) 2736 } 2737 } 2738 for _, pp := range toTrace { 2739 c.traceOutOp("PUBLISH", []byte(mqttPubTrace(&pp))) 2740 } 2741 return nil 2742 } 2743 2744 // Appends the stored message subjects for all retained message records that 2745 // match the given subscription's `subject` (which could have wildcards). 2746 // 2747 // Account session manager NOT lock held on entry. 2748 func (as *mqttAccountSessionManager) addRetainedSubjectsForSubject(list map[string]struct{}, topSubject string) bool { 2749 as.mu.RLock() 2750 if len(as.retmsgs) == 0 { 2751 as.mu.RUnlock() 2752 return false 2753 } 2754 result := as.sl.ReverseMatch(topSubject) 2755 as.mu.RUnlock() 2756 2757 added := false 2758 for _, sub := range result.psubs { 2759 subject := string(sub.subject) 2760 if _, ok := list[subject]; ok { 2761 continue 2762 } 2763 list[subject] = struct{}{} 2764 added = true 2765 } 2766 2767 return added 2768 } 2769 2770 type warner interface { 2771 Warnf(format string, v ...any) 2772 } 2773 2774 // Loads a list of retained messages given a list of stored message subjects. 2775 func (as *mqttAccountSessionManager) loadRetainedMessages(subjects map[string]struct{}, w warner) map[string]*mqttRetainedMsg { 2776 rms := make(map[string]*mqttRetainedMsg, len(subjects)) 2777 ss := []string{} 2778 for s := range subjects { 2779 if rm := as.getCachedRetainedMsg(s); rm != nil { 2780 rms[s] = rm 2781 } else { 2782 ss = append(ss, mqttRetainedMsgsStreamSubject+s) 2783 } 2784 } 2785 2786 if len(ss) == 0 { 2787 return rms 2788 } 2789 2790 results, err := as.jsa.loadLastMsgForMulti(mqttRetainedMsgsStreamName, ss) 2791 // If an error occurred, warn, but then proceed with what we got. 2792 if err != nil { 2793 w.Warnf("error loading retained messages: %v", err) 2794 } 2795 for i, result := range results { 2796 if result == nil { 2797 continue // skip requests that timed out 2798 } 2799 if result.ToError() != nil { 2800 w.Warnf("failed to load retained message for subject %q: %v", ss[i], err) 2801 continue 2802 } 2803 rm, err := mqttDecodeRetainedMessage(result.Message.Header, result.Message.Data) 2804 if err != nil { 2805 w.Warnf("failed to decode retained message for subject %q: %v", ss[i], err) 2806 continue 2807 } 2808 2809 // Add the loaded retained message to the cache, and to the results map. 2810 key := ss[i][len(mqttRetainedMsgsStreamSubject):] 2811 as.setCachedRetainedMsg(key, rm, false, false) 2812 rms[key] = rm 2813 } 2814 return rms 2815 } 2816 2817 // Composes a NATS message for a storeable mqttRetainedMsg. 2818 func mqttEncodeRetainedMessage(rm *mqttRetainedMsg) (natsMsg []byte, headerLen int) { 2819 // No need to encode the subject, we can restore it from topic. 2820 l := len(hdrLine) 2821 l += len(mqttNatsRetainedMessageTopic) + 1 + len(rm.Topic) + 2 // 1 byte for ':', 2 bytes for CRLF 2822 if rm.Origin != _EMPTY_ { 2823 l += len(mqttNatsRetainedMessageOrigin) + 1 + len(rm.Origin) + 2 // 1 byte for ':', 2 bytes for CRLF 2824 } 2825 if rm.Source != _EMPTY_ { 2826 l += len(mqttNatsRetainedMessageSource) + 1 + len(rm.Source) + 2 // 1 byte for ':', 2 bytes for CRLF 2827 } 2828 l += len(mqttNatsRetainedMessageFlags) + 1 + 2 + 2 // 1 byte for ':', 2 bytes for the flags, 2 bytes for CRLF 2829 l += 2 // 2 bytes for the extra CRLF after the header 2830 l += len(rm.Msg) 2831 2832 buf := bytes.NewBuffer(make([]byte, 0, l)) 2833 2834 buf.WriteString(hdrLine) 2835 2836 buf.WriteString(mqttNatsRetainedMessageTopic) 2837 buf.WriteByte(':') 2838 buf.WriteString(rm.Topic) 2839 buf.WriteString(_CRLF_) 2840 2841 buf.WriteString(mqttNatsRetainedMessageFlags) 2842 buf.WriteByte(':') 2843 buf.WriteString(strconv.FormatUint(uint64(rm.Flags), 16)) 2844 buf.WriteString(_CRLF_) 2845 2846 if rm.Origin != _EMPTY_ { 2847 buf.WriteString(mqttNatsRetainedMessageOrigin) 2848 buf.WriteByte(':') 2849 buf.WriteString(rm.Origin) 2850 buf.WriteString(_CRLF_) 2851 } 2852 if rm.Source != _EMPTY_ { 2853 buf.WriteString(mqttNatsRetainedMessageSource) 2854 buf.WriteByte(':') 2855 buf.WriteString(rm.Source) 2856 buf.WriteString(_CRLF_) 2857 } 2858 2859 // End of header, finalize 2860 buf.WriteString(_CRLF_) 2861 headerLen = buf.Len() 2862 buf.Write(rm.Msg) 2863 return buf.Bytes(), headerLen 2864 } 2865 2866 func mqttDecodeRetainedMessage(h, m []byte) (*mqttRetainedMsg, error) { 2867 fHeader := getHeader(mqttNatsRetainedMessageFlags, h) 2868 if len(fHeader) > 0 { 2869 flags, err := strconv.ParseUint(string(fHeader), 16, 8) 2870 if err != nil { 2871 return nil, fmt.Errorf("invalid retained message flags: %v", err) 2872 } 2873 topic := getHeader(mqttNatsRetainedMessageTopic, h) 2874 subj, _ := mqttToNATSSubjectConversion(topic, false) 2875 return &mqttRetainedMsg{ 2876 Flags: byte(flags), 2877 Subject: string(subj), 2878 Topic: string(topic), 2879 Origin: string(getHeader(mqttNatsRetainedMessageOrigin, h)), 2880 Source: string(getHeader(mqttNatsRetainedMessageSource, h)), 2881 Msg: m, 2882 }, nil 2883 } else { 2884 var rm mqttRetainedMsg 2885 if err := json.Unmarshal(m, &rm); err != nil { 2886 return nil, err 2887 } 2888 return &rm, nil 2889 } 2890 } 2891 2892 // Creates the session stream (limit msgs of 1) for this client ID if it does 2893 // not already exist. If it exists, recover the single record to rebuild the 2894 // state of the session. If there is a session record but this session is not 2895 // registered in the runtime of this server, then a request is made to the 2896 // owner to close the client associated with this session since specification 2897 // [MQTT-3.1.4-2] specifies that if the ClientId represents a Client already 2898 // connected to the Server then the Server MUST disconnect the existing client. 2899 // 2900 // Runs from the client's readLoop. 2901 // Lock not held on entry, but session is in the locked map. 2902 func (as *mqttAccountSessionManager) createOrRestoreSession(clientID string, opts *Options) (*mqttSession, bool, error) { 2903 jsa := &as.jsa 2904 formatError := func(errTxt string, err error) (*mqttSession, bool, error) { 2905 accName := jsa.c.acc.GetName() 2906 return nil, false, fmt.Errorf("%s for account %q, session %q: %v", errTxt, accName, clientID, err) 2907 } 2908 2909 hash := getHash(clientID) 2910 smsg, err := jsa.loadSessionMsg(as.domainTk, hash) 2911 if err != nil { 2912 if isErrorOtherThan(err, JSNoMessageFoundErr) { 2913 return formatError("loading session record", err) 2914 } 2915 // Message not found, so reate the session... 2916 // Create a session and indicate that this session did not exist. 2917 sess := mqttSessionCreate(jsa, clientID, hash, 0, opts) 2918 sess.domainTk = as.domainTk 2919 return sess, false, nil 2920 } 2921 // We need to recover the existing record now. 2922 ps := &mqttPersistedSession{} 2923 if err := json.Unmarshal(smsg.Data, ps); err != nil { 2924 return formatError(fmt.Sprintf("unmarshal of session record at sequence %v", smsg.Sequence), err) 2925 } 2926 2927 // Restore this session (even if we don't own it), the caller will do the right thing. 2928 sess := mqttSessionCreate(jsa, clientID, hash, smsg.Sequence, opts) 2929 sess.domainTk = as.domainTk 2930 sess.clean = ps.Clean 2931 sess.subs = ps.Subs 2932 sess.cons = ps.Cons 2933 sess.pubRelConsumer = ps.PubRel 2934 as.addSession(sess, true) 2935 return sess, true, nil 2936 } 2937 2938 // Sends a request to delete a message, but does not wait for the response. 2939 // 2940 // No lock held on entry. 2941 func (as *mqttAccountSessionManager) deleteRetainedMsg(seq uint64) { 2942 as.jsa.deleteMsg(mqttRetainedMsgsStreamName, seq, false) 2943 } 2944 2945 // Sends a message indicating that a retained message on a given subject and stream sequence 2946 // is being removed. 2947 func (as *mqttAccountSessionManager) notifyRetainedMsgDeleted(subject string, seq uint64) { 2948 req := mqttRetMsgDel{ 2949 Subject: subject, 2950 Seq: seq, 2951 } 2952 b, _ := json.Marshal(&req) 2953 jsa := &as.jsa 2954 jsa.sendq.push(&mqttJSPubMsg{ 2955 subj: jsa.rplyr + mqttJSARetainedMsgDel, 2956 msg: b, 2957 }) 2958 } 2959 2960 func (as *mqttAccountSessionManager) transferUniqueSessStreamsToMuxed(log *Server) { 2961 // Set retry to true, will be set to false on success. 2962 retry := true 2963 defer func() { 2964 if retry { 2965 next := mqttDefaultTransferRetry 2966 log.Warnf("Failed to transfer all MQTT session streams, will try again in %v", next) 2967 time.AfterFunc(next, func() { as.transferUniqueSessStreamsToMuxed(log) }) 2968 } 2969 }() 2970 2971 jsa := &as.jsa 2972 sni, err := jsa.newRequestEx(mqttJSAStreamNames, JSApiStreams, _EMPTY_, 0, nil, 5*time.Second) 2973 if err != nil { 2974 log.Errorf("Unable to transfer MQTT session streams: %v", err) 2975 return 2976 } 2977 snames := sni.(*JSApiStreamNamesResponse) 2978 if snames.Error != nil { 2979 log.Errorf("Unable to transfer MQTT session streams: %v", snames.ToError()) 2980 return 2981 } 2982 var oldMQTTSessStreams []string 2983 for _, sn := range snames.Streams { 2984 if strings.HasPrefix(sn, mqttSessionsStreamNamePrefix) { 2985 oldMQTTSessStreams = append(oldMQTTSessStreams, sn) 2986 } 2987 } 2988 ns := len(oldMQTTSessStreams) 2989 if ns == 0 { 2990 // Nothing to do 2991 retry = false 2992 return 2993 } 2994 log.Noticef("Transferring %v MQTT session streams...", ns) 2995 for _, sn := range oldMQTTSessStreams { 2996 log.Noticef(" Transferring stream %q to %q", sn, mqttSessStreamName) 2997 smsg, err := jsa.loadLastMsgFor(sn, sn) 2998 if err != nil { 2999 log.Errorf(" Unable to load session record: %v", err) 3000 return 3001 } 3002 ps := &mqttPersistedSession{} 3003 if err := json.Unmarshal(smsg.Data, ps); err != nil { 3004 log.Warnf(" Unable to unmarshal the content of this stream, may not be a legitimate MQTT session stream, skipping") 3005 continue 3006 } 3007 // Store record to MQTT session stream 3008 if _, err := jsa.storeSessionMsg(as.domainTk, getHash(ps.ID), 0, smsg.Data); err != nil { 3009 log.Errorf(" Unable to transfer the session record: %v", err) 3010 return 3011 } 3012 jsa.deleteStream(sn) 3013 } 3014 log.Noticef("Transfer of %v MQTT session streams done!", ns) 3015 retry = false 3016 } 3017 3018 func (as *mqttAccountSessionManager) transferRetainedToPerKeySubjectStream(log *Server) error { 3019 jsa := &as.jsa 3020 var processed int 3021 var transferred int 3022 3023 start := time.Now() 3024 deadline := start.Add(mqttRetainedTransferTimeout) 3025 for { 3026 // Try and look up messages on the original undivided "$MQTT.rmsgs" subject. 3027 // If nothing is returned here, we assume to have migrated all old messages. 3028 smsg, err := jsa.loadNextMsgFor(mqttRetainedMsgsStreamName, "$MQTT.rmsgs") 3029 if IsNatsErr(err, JSNoMessageFoundErr) { 3030 // We've ran out of messages to transfer, done. 3031 break 3032 } 3033 if err != nil { 3034 log.Warnf(" Unable to transfer a retained message: failed to load from '$MQTT.rmsgs': %s", err) 3035 return err 3036 } 3037 3038 // Unmarshal the message so that we can obtain the subject name. Do not 3039 // use mqttDecodeRetainedMessage() here because these messages are from 3040 // older versions, and contain the full JSON encoding in payload. 3041 var rmsg mqttRetainedMsg 3042 if err = json.Unmarshal(smsg.Data, &rmsg); err == nil { 3043 // Store the message again, this time with the new per-key subject. 3044 subject := mqttRetainedMsgsStreamSubject + rmsg.Subject 3045 if _, err = jsa.storeMsg(subject, 0, smsg.Data); err != nil { 3046 log.Errorf(" Unable to transfer the retained message with sequence %d: %v", smsg.Sequence, err) 3047 } 3048 transferred++ 3049 } else { 3050 log.Warnf(" Unable to unmarshal retained message with sequence %d, skipping", smsg.Sequence) 3051 } 3052 3053 // Delete the original message. 3054 if err := jsa.deleteMsg(mqttRetainedMsgsStreamName, smsg.Sequence, true); err != nil { 3055 log.Errorf(" Unable to clean up the retained message with sequence %d: %v", smsg.Sequence, err) 3056 return err 3057 } 3058 processed++ 3059 3060 now := time.Now() 3061 if now.After(deadline) { 3062 err := fmt.Errorf("timed out while transferring retained messages from '$MQTT.rmsgs' after %v, %d processed, %d successfully transferred", now.Sub(start), processed, transferred) 3063 log.Noticef(err.Error()) 3064 return err 3065 } 3066 } 3067 if processed > 0 { 3068 log.Noticef("Processed %d messages from '$MQTT.rmsgs', successfully transferred %d in %v", processed, transferred, time.Since(start)) 3069 } else { 3070 log.Debugf("No messages found to transfer from '$MQTT.rmsgs'") 3071 } 3072 return nil 3073 } 3074 3075 func (as *mqttAccountSessionManager) getCachedRetainedMsg(subject string) *mqttRetainedMsg { 3076 if as.rmsCache == nil { 3077 return nil 3078 } 3079 v, ok := as.rmsCache.Load(subject) 3080 if !ok { 3081 return nil 3082 } 3083 rm := v.(*mqttRetainedMsg) 3084 if rm.expiresFromCache.Before(time.Now()) { 3085 as.rmsCache.Delete(subject) 3086 return nil 3087 } 3088 return rm 3089 } 3090 3091 func (as *mqttAccountSessionManager) setCachedRetainedMsg(subject string, rm *mqttRetainedMsg, onlyReplace bool, copyBytesToCache bool) { 3092 if as.rmsCache == nil || rm == nil { 3093 return 3094 } 3095 rm.expiresFromCache = time.Now().Add(mqttRetainedCacheTTL) 3096 if onlyReplace { 3097 if _, ok := as.rmsCache.Load(subject); !ok { 3098 return 3099 } 3100 } 3101 if copyBytesToCache { 3102 rm.Msg = copyBytes(rm.Msg) 3103 } 3104 as.rmsCache.Store(subject, rm) 3105 } 3106 3107 ////////////////////////////////////////////////////////////////////////////// 3108 // 3109 // MQTT session related functions 3110 // 3111 ////////////////////////////////////////////////////////////////////////////// 3112 3113 // Returns a new mqttSession object with max ack pending set based on 3114 // option or use mqttDefaultMaxAckPending if no option set. 3115 func mqttSessionCreate(jsa *mqttJSA, id, idHash string, seq uint64, opts *Options) *mqttSession { 3116 maxp := opts.MQTT.MaxAckPending 3117 if maxp == 0 { 3118 maxp = mqttDefaultMaxAckPending 3119 } 3120 3121 return &mqttSession{ 3122 jsa: jsa, 3123 id: id, 3124 idHash: idHash, 3125 seq: seq, 3126 maxp: maxp, 3127 pubRelSubject: mqttPubRelSubjectPrefix + idHash, 3128 pubRelDeliverySubject: mqttPubRelDeliverySubjectPrefix + idHash, 3129 pubRelDeliverySubjectB: []byte(mqttPubRelDeliverySubjectPrefix + idHash), 3130 } 3131 } 3132 3133 // Persists a session. Note that if the session's current client does not match 3134 // the given client, nothing is done. 3135 // 3136 // Lock not held on entry. 3137 func (sess *mqttSession) save() error { 3138 sess.mu.Lock() 3139 ps := mqttPersistedSession{ 3140 Origin: sess.jsa.id, 3141 ID: sess.id, 3142 Clean: sess.clean, 3143 Subs: sess.subs, 3144 Cons: sess.cons, 3145 PubRel: sess.pubRelConsumer, 3146 } 3147 b, _ := json.Marshal(&ps) 3148 3149 domainTk, cidHash := sess.domainTk, sess.idHash 3150 seq := sess.seq 3151 sess.mu.Unlock() 3152 3153 var hdr int 3154 if seq != 0 { 3155 bb := bytes.Buffer{} 3156 bb.WriteString(hdrLine) 3157 bb.WriteString(JSExpectedLastSubjSeq) 3158 bb.WriteString(":") 3159 bb.WriteString(strconv.FormatInt(int64(seq), 10)) 3160 bb.WriteString(CR_LF) 3161 bb.WriteString(CR_LF) 3162 hdr = bb.Len() 3163 bb.Write(b) 3164 b = bb.Bytes() 3165 } 3166 3167 resp, err := sess.jsa.storeSessionMsg(domainTk, cidHash, hdr, b) 3168 if err != nil { 3169 return fmt.Errorf("unable to persist session %q (seq=%v): %v", ps.ID, seq, err) 3170 } 3171 sess.mu.Lock() 3172 sess.seq = resp.Sequence 3173 sess.mu.Unlock() 3174 return nil 3175 } 3176 3177 // Clear the session. 3178 // 3179 // Runs from the client's readLoop. 3180 // Lock not held on entry, but session is in the locked map. 3181 func (sess *mqttSession) clear() error { 3182 var durs []string 3183 var pubRelDur string 3184 3185 sess.mu.Lock() 3186 id := sess.id 3187 seq := sess.seq 3188 if l := len(sess.cons); l > 0 { 3189 durs = make([]string, 0, l) 3190 } 3191 for sid, cc := range sess.cons { 3192 delete(sess.cons, sid) 3193 durs = append(durs, cc.Durable) 3194 } 3195 if sess.pubRelConsumer != nil { 3196 pubRelDur = sess.pubRelConsumer.Durable 3197 } 3198 3199 sess.subs = nil 3200 sess.pendingPublish = nil 3201 sess.pendingPubRel = nil 3202 sess.cpending = nil 3203 sess.pubRelConsumer = nil 3204 sess.seq = 0 3205 sess.tmaxack = 0 3206 sess.mu.Unlock() 3207 3208 for _, dur := range durs { 3209 if _, err := sess.jsa.deleteConsumer(mqttStreamName, dur); isErrorOtherThan(err, JSConsumerNotFoundErr) { 3210 return fmt.Errorf("unable to delete consumer %q for session %q: %v", dur, sess.id, err) 3211 } 3212 } 3213 if pubRelDur != _EMPTY_ { 3214 _, err := sess.jsa.deleteConsumer(mqttOutStreamName, pubRelDur) 3215 if isErrorOtherThan(err, JSConsumerNotFoundErr) { 3216 return fmt.Errorf("unable to delete consumer %q for session %q: %v", pubRelDur, sess.id, err) 3217 } 3218 } 3219 3220 if seq > 0 { 3221 err := sess.jsa.deleteMsg(mqttSessStreamName, seq, true) 3222 // Ignore the various errors indicating that the message (or sequence) 3223 // is already deleted, can happen in a cluster. 3224 if isErrorOtherThan(err, JSSequenceNotFoundErrF) { 3225 if isErrorOtherThan(err, JSStreamMsgDeleteFailedF) || !strings.Contains(err.Error(), ErrStoreMsgNotFound.Error()) { 3226 return fmt.Errorf("unable to delete session %q record at sequence %v: %v", id, seq, err) 3227 } 3228 } 3229 } 3230 return nil 3231 } 3232 3233 // This will update the session record for this client in the account's MQTT 3234 // sessions stream if the session had any change in the subscriptions. 3235 // 3236 // Runs from the client's readLoop. 3237 // Lock not held on entry, but session is in the locked map. 3238 func (sess *mqttSession) update(filters []*mqttFilter, add bool) error { 3239 // Evaluate if we need to persist anything. 3240 var needUpdate bool 3241 for _, f := range filters { 3242 if add { 3243 if f.qos == mqttSubAckFailure { 3244 continue 3245 } 3246 if qos, ok := sess.subs[f.filter]; !ok || qos != f.qos { 3247 if sess.subs == nil { 3248 sess.subs = make(map[string]byte) 3249 } 3250 sess.subs[f.filter] = f.qos 3251 needUpdate = true 3252 } 3253 } else { 3254 if _, ok := sess.subs[f.filter]; ok { 3255 delete(sess.subs, f.filter) 3256 needUpdate = true 3257 } 3258 } 3259 } 3260 var err error 3261 if needUpdate { 3262 err = sess.save() 3263 } 3264 return err 3265 } 3266 3267 func (sess *mqttSession) bumpPI() uint16 { 3268 var avail bool 3269 next := sess.last_pi 3270 for i := 0; i < 0xFFFF; i++ { 3271 next++ 3272 if next == 0 { 3273 next = 1 3274 } 3275 3276 _, usedInPublish := sess.pendingPublish[next] 3277 _, usedInPubRel := sess.pendingPubRel[next] 3278 if !usedInPublish && !usedInPubRel { 3279 sess.last_pi = next 3280 avail = true 3281 break 3282 } 3283 } 3284 if !avail { 3285 return 0 3286 } 3287 return sess.last_pi 3288 } 3289 3290 // trackPublishRetained is invoked when a retained (QoS) message is published. 3291 // It need a new PI to be allocated, so we add it to the pendingPublish map, 3292 // with an empty value. Since cpending (not pending) is used to serialize the PI 3293 // mappings, we need to add this PI there as well. Make a unique key by using 3294 // mqttRetainedMsgsStreamName for the durable name, and PI for sseq. 3295 // 3296 // Lock held on entry 3297 func (sess *mqttSession) trackPublishRetained() uint16 { 3298 // Make sure we initialize the tracking maps. 3299 if sess.pendingPublish == nil { 3300 sess.pendingPublish = make(map[uint16]*mqttPending) 3301 } 3302 if sess.cpending == nil { 3303 sess.cpending = make(map[string]map[uint64]uint16) 3304 } 3305 3306 pi := sess.bumpPI() 3307 if pi == 0 { 3308 return 0 3309 } 3310 sess.pendingPublish[pi] = &mqttPending{} 3311 3312 return pi 3313 } 3314 3315 // trackPublish is invoked when a (QoS) PUBLISH message is to be delivered. It 3316 // detects an untracked (new) message based on its sequence extracted from its 3317 // delivery-time jsAckSubject, and adds it to the tracking maps. Returns a PI to 3318 // use for the message (new, or previously used), and whether this is a 3319 // duplicate delivery attempt. 3320 // 3321 // Lock held on entry 3322 func (sess *mqttSession) trackPublish(jsDur, jsAckSubject string) (uint16, bool) { 3323 var dup bool 3324 var pi uint16 3325 3326 if jsAckSubject == _EMPTY_ || jsDur == _EMPTY_ { 3327 return 0, false 3328 } 3329 3330 // Make sure we initialize the tracking maps. 3331 if sess.pendingPublish == nil { 3332 sess.pendingPublish = make(map[uint16]*mqttPending) 3333 } 3334 if sess.cpending == nil { 3335 sess.cpending = make(map[string]map[uint64]uint16) 3336 } 3337 3338 // Get the stream sequence and duplicate flag from the ack reply subject. 3339 sseq, _, dcount := ackReplyInfo(jsAckSubject) 3340 if dcount > 1 { 3341 dup = true 3342 } 3343 3344 var ack *mqttPending 3345 sseqToPi, ok := sess.cpending[jsDur] 3346 if !ok { 3347 sseqToPi = make(map[uint64]uint16) 3348 sess.cpending[jsDur] = sseqToPi 3349 } else { 3350 pi = sseqToPi[sseq] 3351 } 3352 3353 if pi != 0 { 3354 // There is a possible race between a PUBLISH re-delivery calling us, 3355 // and a PUBREC received already having submitting a PUBREL into JS . If 3356 // so, indicate no need for (re-)delivery by returning a PI of 0. 3357 _, usedForPubRel := sess.pendingPubRel[pi] 3358 if /*dup && */ usedForPubRel { 3359 return 0, false 3360 } 3361 3362 // We should have a pending JS ACK for this PI. 3363 ack = sess.pendingPublish[pi] 3364 } else { 3365 // sess.maxp will always have a value > 0. 3366 if len(sess.pendingPublish) >= int(sess.maxp) { 3367 // Indicate that we did not assign a packet identifier. 3368 // The caller will not send the message to the subscription 3369 // and JS will redeliver later, based on consumer's AckWait. 3370 return 0, false 3371 } 3372 3373 pi = sess.bumpPI() 3374 if pi == 0 { 3375 return 0, false 3376 } 3377 3378 sseqToPi[sseq] = pi 3379 } 3380 3381 if ack == nil { 3382 sess.pendingPublish[pi] = &mqttPending{ 3383 jsDur: jsDur, 3384 sseq: sseq, 3385 jsAckSubject: jsAckSubject, 3386 } 3387 } else { 3388 ack.jsAckSubject = jsAckSubject 3389 ack.sseq = sseq 3390 ack.jsDur = jsDur 3391 } 3392 3393 return pi, dup 3394 } 3395 3396 // Stops a PI from being tracked as a PUBLISH. It can still be in use for a 3397 // pending PUBREL. 3398 // 3399 // Lock held on entry 3400 func (sess *mqttSession) untrackPublish(pi uint16) (jsAckSubject string) { 3401 ack, ok := sess.pendingPublish[pi] 3402 if !ok { 3403 return _EMPTY_ 3404 } 3405 3406 delete(sess.pendingPublish, pi) 3407 if len(sess.pendingPublish) == 0 { 3408 sess.last_pi = 0 3409 } 3410 3411 if len(sess.cpending) != 0 && ack.jsDur != _EMPTY_ { 3412 if sseqToPi := sess.cpending[ack.jsDur]; sseqToPi != nil { 3413 delete(sseqToPi, ack.sseq) 3414 } 3415 } 3416 3417 return ack.jsAckSubject 3418 } 3419 3420 // trackAsPubRel is invoked in 2 cases: (a) when we receive a PUBREC and we need 3421 // to change from tracking the PI as a PUBLISH to a PUBREL; and (b) when we 3422 // attempt to deliver the PUBREL to record the JS ack subject for it. 3423 // 3424 // Lock held on entry 3425 func (sess *mqttSession) trackAsPubRel(pi uint16, jsAckSubject string) { 3426 if sess.pubRelConsumer == nil { 3427 // The cosumer MUST be set up already. 3428 return 3429 } 3430 jsDur := sess.pubRelConsumer.Durable 3431 3432 if sess.pendingPubRel == nil { 3433 sess.pendingPubRel = make(map[uint16]*mqttPending) 3434 } 3435 3436 if jsAckSubject == _EMPTY_ { 3437 sess.pendingPubRel[pi] = &mqttPending{ 3438 jsDur: jsDur, 3439 } 3440 return 3441 } 3442 3443 sseq, _, _ := ackReplyInfo(jsAckSubject) 3444 3445 if sess.cpending == nil { 3446 sess.cpending = make(map[string]map[uint64]uint16) 3447 } 3448 sseqToPi := sess.cpending[jsDur] 3449 if sseqToPi == nil { 3450 sseqToPi = make(map[uint64]uint16) 3451 sess.cpending[jsDur] = sseqToPi 3452 } 3453 sseqToPi[sseq] = pi 3454 sess.pendingPubRel[pi] = &mqttPending{ 3455 jsDur: sess.pubRelConsumer.Durable, 3456 sseq: sseq, 3457 jsAckSubject: jsAckSubject, 3458 } 3459 } 3460 3461 // Stops a PI from being tracked as a PUBREL. 3462 // 3463 // Lock held on entry 3464 func (sess *mqttSession) untrackPubRel(pi uint16) (jsAckSubject string) { 3465 ack, ok := sess.pendingPubRel[pi] 3466 if !ok { 3467 return _EMPTY_ 3468 } 3469 3470 delete(sess.pendingPubRel, pi) 3471 3472 if sess.pubRelConsumer != nil && len(sess.cpending) > 0 { 3473 if sseqToPi := sess.cpending[ack.jsDur]; sseqToPi != nil { 3474 delete(sseqToPi, ack.sseq) 3475 } 3476 } 3477 3478 return ack.jsAckSubject 3479 } 3480 3481 // Sends a consumer delete request, but does not wait for response. 3482 // 3483 // Lock not held on entry. 3484 func (sess *mqttSession) deleteConsumer(cc *ConsumerConfig) { 3485 sess.mu.Lock() 3486 sess.tmaxack -= cc.MaxAckPending 3487 sess.jsa.sendq.push(&mqttJSPubMsg{subj: sess.jsa.prefixDomain(fmt.Sprintf(JSApiConsumerDeleteT, mqttStreamName, cc.Durable))}) 3488 sess.mu.Unlock() 3489 } 3490 3491 ////////////////////////////////////////////////////////////////////////////// 3492 // 3493 // CONNECT protocol related functions 3494 // 3495 ////////////////////////////////////////////////////////////////////////////// 3496 3497 // Parse the MQTT connect protocol 3498 func (c *client) mqttParseConnect(r *mqttReader, hasMappings bool) (byte, *mqttConnectProto, error) { 3499 // Protocol name 3500 proto, err := r.readBytes("protocol name", false) 3501 if err != nil { 3502 return 0, nil, err 3503 } 3504 3505 // Spec [MQTT-3.1.2-1] 3506 if !bytes.Equal(proto, mqttProtoName) { 3507 // Check proto name against v3.1 to report better error 3508 if bytes.Equal(proto, mqttOldProtoName) { 3509 return 0, nil, fmt.Errorf("older protocol %q not supported", proto) 3510 } 3511 return 0, nil, fmt.Errorf("expected connect packet with protocol name %q, got %q", mqttProtoName, proto) 3512 } 3513 3514 // Protocol level 3515 level, err := r.readByte("protocol level") 3516 if err != nil { 3517 return 0, nil, err 3518 } 3519 // Spec [MQTT-3.1.2-2] 3520 if level != mqttProtoLevel { 3521 return mqttConnAckRCUnacceptableProtocolVersion, nil, fmt.Errorf("unacceptable protocol version of %v", level) 3522 } 3523 3524 cp := &mqttConnectProto{} 3525 // Connect flags 3526 cp.flags, err = r.readByte("flags") 3527 if err != nil { 3528 return 0, nil, err 3529 } 3530 3531 // Spec [MQTT-3.1.2-3] 3532 if cp.flags&mqttConnFlagReserved != 0 { 3533 return 0, nil, errMQTTConnFlagReserved 3534 } 3535 3536 var hasWill bool 3537 wqos := (cp.flags & mqttConnFlagWillQoS) >> 3 3538 wretain := cp.flags&mqttConnFlagWillRetain != 0 3539 // Spec [MQTT-3.1.2-11] 3540 if cp.flags&mqttConnFlagWillFlag == 0 { 3541 // Spec [MQTT-3.1.2-13] 3542 if wqos != 0 { 3543 return 0, nil, fmt.Errorf("if Will flag is set to 0, Will QoS must be 0 too, got %v", wqos) 3544 } 3545 // Spec [MQTT-3.1.2-15] 3546 if wretain { 3547 return 0, nil, errMQTTWillAndRetainFlag 3548 } 3549 } else { 3550 // Spec [MQTT-3.1.2-14] 3551 if wqos == 3 { 3552 return 0, nil, fmt.Errorf("if Will flag is set to 1, Will QoS can be 0, 1 or 2, got %v", wqos) 3553 } 3554 hasWill = true 3555 } 3556 3557 if c.mqtt.rejectQoS2Pub && hasWill && wqos == 2 { 3558 return mqttConnAckRCQoS2WillRejected, nil, fmt.Errorf("server does not accept QoS2 for Will messages") 3559 } 3560 3561 // Spec [MQTT-3.1.2-19] 3562 hasUser := cp.flags&mqttConnFlagUsernameFlag != 0 3563 // Spec [MQTT-3.1.2-21] 3564 hasPassword := cp.flags&mqttConnFlagPasswordFlag != 0 3565 // Spec [MQTT-3.1.2-22] 3566 if !hasUser && hasPassword { 3567 return 0, nil, errMQTTPasswordFlagAndNoUser 3568 } 3569 3570 // Keep alive 3571 var ka uint16 3572 ka, err = r.readUint16("keep alive") 3573 if err != nil { 3574 return 0, nil, err 3575 } 3576 // Spec [MQTT-3.1.2-24] 3577 if ka > 0 { 3578 cp.rd = time.Duration(float64(ka)*1.5) * time.Second 3579 } 3580 3581 // Payload starts here and order is mandated by: 3582 // Spec [MQTT-3.1.3-1]: client ID, will topic, will message, username, password 3583 3584 // Client ID 3585 c.mqtt.cid, err = r.readString("client ID") 3586 if err != nil { 3587 return 0, nil, err 3588 } 3589 // Spec [MQTT-3.1.3-7] 3590 if c.mqtt.cid == _EMPTY_ { 3591 if cp.flags&mqttConnFlagCleanSession == 0 { 3592 return mqttConnAckRCIdentifierRejected, nil, errMQTTCIDEmptyNeedsCleanFlag 3593 } 3594 // Spec [MQTT-3.1.3-6] 3595 c.mqtt.cid = nuid.Next() 3596 } 3597 // Spec [MQTT-3.1.3-4] and [MQTT-3.1.3-9] 3598 if !utf8.ValidString(c.mqtt.cid) { 3599 return mqttConnAckRCIdentifierRejected, nil, fmt.Errorf("invalid utf8 for client ID: %q", c.mqtt.cid) 3600 } 3601 3602 if hasWill { 3603 cp.will = &mqttWill{ 3604 qos: wqos, 3605 retain: wretain, 3606 } 3607 var topic []byte 3608 // Need to make a copy since we need to hold to this topic after the 3609 // parsing of this protocol. 3610 topic, err = r.readBytes("Will topic", true) 3611 if err != nil { 3612 return 0, nil, err 3613 } 3614 if len(topic) == 0 { 3615 return 0, nil, errMQTTEmptyWillTopic 3616 } 3617 if !utf8.Valid(topic) { 3618 return 0, nil, fmt.Errorf("invalid utf8 for Will topic %q", topic) 3619 } 3620 // Convert MQTT topic to NATS subject 3621 cp.will.subject, err = mqttTopicToNATSPubSubject(topic) 3622 if err != nil { 3623 return 0, nil, err 3624 } 3625 // Check for subject mapping. 3626 if hasMappings { 3627 // For selectMappedSubject to work, we need to have c.pa.subject set. 3628 // If there is a change, c.pa.mapped will be set after the call. 3629 c.pa.subject = cp.will.subject 3630 if changed := c.selectMappedSubject(); changed { 3631 // We need to keep track of the NATS subject/mapped in the `cp` structure. 3632 cp.will.subject = c.pa.subject 3633 cp.will.mapped = c.pa.mapped 3634 // We also now need to map the original MQTT topic to the new topic 3635 // based on the new subject. 3636 topic = natsSubjectToMQTTTopic(cp.will.subject) 3637 } 3638 // Reset those now. 3639 c.pa.subject, c.pa.mapped = nil, nil 3640 } 3641 cp.will.topic = topic 3642 // Now "will" message. 3643 // Ask for a copy since we need to hold to this after parsing of this protocol. 3644 cp.will.message, err = r.readBytes("Will message", true) 3645 if err != nil { 3646 return 0, nil, err 3647 } 3648 } 3649 3650 if hasUser { 3651 c.opts.Username, err = r.readString("user name") 3652 if err != nil { 3653 return 0, nil, err 3654 } 3655 if c.opts.Username == _EMPTY_ { 3656 return mqttConnAckRCBadUserOrPassword, nil, errMQTTEmptyUsername 3657 } 3658 // Spec [MQTT-3.1.3-11] 3659 if !utf8.ValidString(c.opts.Username) { 3660 return mqttConnAckRCBadUserOrPassword, nil, fmt.Errorf("invalid utf8 for user name %q", c.opts.Username) 3661 } 3662 } 3663 3664 if hasPassword { 3665 c.opts.Password, err = r.readString("password") 3666 if err != nil { 3667 return 0, nil, err 3668 } 3669 c.opts.Token = c.opts.Password 3670 c.opts.JWT = c.opts.Password 3671 } 3672 return 0, cp, nil 3673 } 3674 3675 func (c *client) mqttConnectTrace(cp *mqttConnectProto) string { 3676 trace := fmt.Sprintf("clientID=%s", c.mqtt.cid) 3677 if cp.rd > 0 { 3678 trace += fmt.Sprintf(" keepAlive=%v", cp.rd) 3679 } 3680 if cp.will != nil { 3681 trace += fmt.Sprintf(" will=(topic=%s QoS=%v retain=%v)", 3682 cp.will.topic, cp.will.qos, cp.will.retain) 3683 } 3684 if cp.flags&mqttConnFlagCleanSession != 0 { 3685 trace += " clean" 3686 } 3687 if c.opts.Username != _EMPTY_ { 3688 trace += fmt.Sprintf(" username=%s", c.opts.Username) 3689 } 3690 if c.opts.Password != _EMPTY_ { 3691 trace += " password=****" 3692 } 3693 return trace 3694 } 3695 3696 // Process the CONNECT packet. 3697 // 3698 // For the first session on the account, an account session manager will be created, 3699 // along with the JetStream streams/consumer necessary for the working of MQTT. 3700 // 3701 // The session, identified by a client ID, will be registered, or if already existing, 3702 // will be resumed. If the session exists but is associated with an existing client, 3703 // the old client is evicted, as per the specifications. 3704 // 3705 // Due to specific locking requirements around JS API requests, we cannot hold some 3706 // locks for the entire duration of processing of some protocols, therefore, we use 3707 // a map that registers the client ID in a "locked" state. If a different client tries 3708 // to connect and the server detects that the client ID is in that map, it will try 3709 // a little bit until it is not, or fail the new client, since we can't protect 3710 // processing of protocols in the original client. This is not expected to happen often. 3711 // 3712 // Runs from the client's readLoop. 3713 // No lock held on entry. 3714 func (s *Server) mqttProcessConnect(c *client, cp *mqttConnectProto, trace bool) error { 3715 sendConnAck := func(rc byte, sessp bool) { 3716 c.mqttEnqueueConnAck(rc, sessp) 3717 if trace { 3718 c.traceOutOp("CONNACK", []byte(fmt.Sprintf("sp=%v rc=%v", sessp, rc))) 3719 } 3720 } 3721 3722 c.mu.Lock() 3723 cid := c.mqtt.cid 3724 c.clearAuthTimer() 3725 c.mu.Unlock() 3726 if !s.isClientAuthorized(c) { 3727 if trace { 3728 c.traceOutOp("CONNACK", []byte(fmt.Sprintf("sp=%v rc=%v", false, mqttConnAckRCNotAuthorized))) 3729 } 3730 c.authViolation() 3731 return ErrAuthentication 3732 } 3733 // Now that we are authenticated, we have the client bound to the account. 3734 // Get the account's level MQTT sessions manager. If it does not exists yet, 3735 // this will create it along with the streams where sessions and messages 3736 // are stored. 3737 asm, err := s.getOrCreateMQTTAccountSessionManager(c) 3738 if err != nil { 3739 return err 3740 } 3741 3742 // Most of the session state is altered only in the readLoop so does not 3743 // need locking. For things that can be access in the readLoop and in 3744 // callbacks, we will use explicit locking. 3745 // To prevent other clients to connect with the same client ID, we will 3746 // add the client ID to a "locked" map so that the connect somewhere else 3747 // is put on hold. 3748 // This keep track of how many times this client is detecting that its 3749 // client ID is in the locked map. After a short amount, the server will 3750 // fail this inbound client. 3751 locked := 0 3752 3753 CHECK: 3754 asm.mu.Lock() 3755 // Check if different applications keep trying to connect with the same 3756 // client ID at the same time. 3757 if tm, ok := asm.flappers[cid]; ok { 3758 // If the last time it tried to connect was more than 1 sec ago, 3759 // then accept and remove from flappers map. 3760 if time.Now().UnixNano()-tm > int64(mqttSessJailDur) { 3761 asm.removeSessFromFlappers(cid) 3762 } else { 3763 // Will hold this client for a second and then close it. We 3764 // do this so that if the client has a reconnect feature we 3765 // don't end-up with very rapid flapping between apps. 3766 // We need to wait in place and not schedule the connection 3767 // close because if this is a misbehaved client that does 3768 // not wait for the CONNACK and sends other protocols, the 3769 // server would not have a fully setup client and may panic. 3770 asm.mu.Unlock() 3771 select { 3772 case <-s.quitCh: 3773 case <-time.After(mqttSessJailDur): 3774 } 3775 c.closeConnection(DuplicateClientID) 3776 return ErrConnectionClosed 3777 } 3778 } 3779 // If an existing session is in the process of processing some packet, we can't 3780 // evict the old client just yet. So try again to see if the state clears, but 3781 // if it does not, then we have no choice but to fail the new client instead of 3782 // the old one. 3783 if _, ok := asm.sessLocked[cid]; ok { 3784 asm.mu.Unlock() 3785 if locked++; locked == 10 { 3786 return fmt.Errorf("other session with client ID %q is in the process of connecting", cid) 3787 } 3788 time.Sleep(100 * time.Millisecond) 3789 goto CHECK 3790 } 3791 3792 // Register this client ID the "locked" map for the duration if this function. 3793 asm.sessLocked[cid] = struct{}{} 3794 // And remove it on exit, regardless of error or not. 3795 defer func() { 3796 asm.mu.Lock() 3797 delete(asm.sessLocked, cid) 3798 asm.mu.Unlock() 3799 }() 3800 3801 // Is the client requesting a clean session or not. 3802 cleanSess := cp.flags&mqttConnFlagCleanSession != 0 3803 // Session present? Assume false, will be set to true only when applicable. 3804 sessp := false 3805 // Do we have an existing session for this client ID 3806 es, exists := asm.sessions[cid] 3807 asm.mu.Unlock() 3808 3809 // The session is not in the map, but may be on disk, so try to recover 3810 // or create the stream if not. 3811 if !exists { 3812 es, exists, err = asm.createOrRestoreSession(cid, s.getOpts()) 3813 if err != nil { 3814 return err 3815 } 3816 } 3817 if exists { 3818 // Clear the session if client wants a clean session. 3819 // Also, Spec [MQTT-3.2.2-1]: don't report session present 3820 if cleanSess || es.clean { 3821 // Spec [MQTT-3.1.2-6]: If CleanSession is set to 1, the Client and 3822 // Server MUST discard any previous Session and start a new one. 3823 // This Session lasts as long as the Network Connection. State data 3824 // associated with this Session MUST NOT be reused in any subsequent 3825 // Session. 3826 if err := es.clear(); err != nil { 3827 asm.removeSession(es, true) 3828 return err 3829 } 3830 } else { 3831 // Report to the client that the session was present 3832 sessp = true 3833 } 3834 // Spec [MQTT-3.1.4-2]. If the ClientId represents a Client already 3835 // connected to the Server then the Server MUST disconnect the existing 3836 // client. 3837 // Bind with the new client. This needs to be protected because can be 3838 // accessed outside of the readLoop. 3839 es.mu.Lock() 3840 ec := es.c 3841 es.c = c 3842 es.clean = cleanSess 3843 es.mu.Unlock() 3844 if ec != nil { 3845 // Remove "will" of existing client before closing 3846 ec.mu.Lock() 3847 ec.mqtt.cp.will = nil 3848 ec.mu.Unlock() 3849 // Add to the map of the flappers 3850 asm.mu.Lock() 3851 asm.addSessToFlappers(cid) 3852 asm.mu.Unlock() 3853 c.Warnf("Replacing old client %q since both have the same client ID %q", ec, cid) 3854 // Close old client in separate go routine 3855 go ec.closeConnection(DuplicateClientID) 3856 } 3857 } else { 3858 // Spec [MQTT-3.2.2-3]: if the Server does not have stored Session state, 3859 // it MUST set Session Present to 0 in the CONNACK packet. 3860 es.mu.Lock() 3861 es.c, es.clean = c, cleanSess 3862 es.mu.Unlock() 3863 // Now add this new session into the account sessions 3864 asm.addSession(es, true) 3865 } 3866 // We would need to save only if it did not exist previously, but we save 3867 // always in case we are running in cluster mode. This will notify other 3868 // running servers that this session is being used. 3869 if err := es.save(); err != nil { 3870 asm.removeSession(es, true) 3871 return err 3872 } 3873 c.mu.Lock() 3874 c.flags.set(connectReceived) 3875 c.mqtt.cp = cp 3876 c.mqtt.asm = asm 3877 c.mqtt.sess = es 3878 c.mu.Unlock() 3879 3880 // Spec [MQTT-3.2.0-1]: CONNACK must be the first protocol sent to the session. 3881 sendConnAck(mqttConnAckRCConnectionAccepted, sessp) 3882 3883 // Process possible saved subscriptions. 3884 if l := len(es.subs); l > 0 { 3885 filters := make([]*mqttFilter, 0, l) 3886 for subject, qos := range es.subs { 3887 filters = append(filters, &mqttFilter{filter: subject, qos: qos}) 3888 } 3889 if _, err := asm.processSubs(es, c, filters, false, trace); err != nil { 3890 return err 3891 } 3892 } 3893 return nil 3894 } 3895 3896 func (c *client) mqttEnqueueConnAck(rc byte, sessionPresent bool) { 3897 proto := [4]byte{mqttPacketConnectAck, 2, 0, rc} 3898 c.mu.Lock() 3899 // Spec [MQTT-3.2.2-4]. If return code is different from 0, then 3900 // session present flag must be set to 0. 3901 if rc == 0 { 3902 if sessionPresent { 3903 proto[2] = 1 3904 } 3905 } 3906 c.enqueueProto(proto[:]) 3907 c.mu.Unlock() 3908 } 3909 3910 func (s *Server) mqttHandleWill(c *client) { 3911 c.mu.Lock() 3912 if c.mqtt.cp == nil { 3913 c.mu.Unlock() 3914 return 3915 } 3916 will := c.mqtt.cp.will 3917 if will == nil { 3918 c.mu.Unlock() 3919 return 3920 } 3921 pp := c.mqtt.pp 3922 pp.topic = will.topic 3923 pp.subject = will.subject 3924 pp.mapped = will.mapped 3925 pp.msg = will.message 3926 pp.sz = len(will.message) 3927 pp.pi = 0 3928 pp.flags = will.qos << 1 3929 if will.retain { 3930 pp.flags |= mqttPubFlagRetain 3931 } 3932 c.mu.Unlock() 3933 s.mqttInitiateMsgDelivery(c, pp) 3934 c.flushClients(0) 3935 } 3936 3937 ////////////////////////////////////////////////////////////////////////////// 3938 // 3939 // PUBLISH protocol related functions 3940 // 3941 ////////////////////////////////////////////////////////////////////////////// 3942 3943 func (c *client) mqttParsePub(r *mqttReader, pl int, pp *mqttPublish, hasMappings bool) error { 3944 qos := mqttGetQoS(pp.flags) 3945 if qos > 2 { 3946 return fmt.Errorf("QoS=%v is invalid in MQTT", qos) 3947 } 3948 3949 if c.mqtt.rejectQoS2Pub && qos == 2 { 3950 return fmt.Errorf("QoS=2 is disabled for PUBLISH messages") 3951 } 3952 3953 // Keep track of where we are when starting to read the variable header 3954 start := r.pos 3955 3956 var err error 3957 pp.topic, err = r.readBytes("topic", false) 3958 if err != nil { 3959 return err 3960 } 3961 if len(pp.topic) == 0 { 3962 return errMQTTTopicIsEmpty 3963 } 3964 // Convert the topic to a NATS subject. This call will also check that 3965 // there is no MQTT wildcards (Spec [MQTT-3.3.2-2] and [MQTT-4.7.1-1]) 3966 // Note that this may not result in a copy if there is no conversion. 3967 // It is good because after the message is processed we won't have a 3968 // reference to the buffer and we save a copy. 3969 pp.subject, err = mqttTopicToNATSPubSubject(pp.topic) 3970 if err != nil { 3971 return err 3972 } 3973 3974 // Check for subject mapping. 3975 if hasMappings { 3976 // For selectMappedSubject to work, we need to have c.pa.subject set. 3977 // If there is a change, c.pa.mapped will be set after the call. 3978 c.pa.subject = pp.subject 3979 if changed := c.selectMappedSubject(); changed { 3980 // We need to keep track of the NATS subject/mapped in the `pp` structure. 3981 pp.subject = c.pa.subject 3982 pp.mapped = c.pa.mapped 3983 // We also now need to map the original MQTT topic to the new topic 3984 // based on the new subject. 3985 pp.topic = natsSubjectToMQTTTopic(pp.subject) 3986 } 3987 // Reset those now. 3988 c.pa.subject, c.pa.mapped = nil, nil 3989 } 3990 3991 if qos > 0 { 3992 pp.pi, err = r.readUint16("packet identifier") 3993 if err != nil { 3994 return err 3995 } 3996 if pp.pi == 0 { 3997 return fmt.Errorf("with QoS=%v, packet identifier cannot be 0", qos) 3998 } 3999 } else { 4000 pp.pi = 0 4001 } 4002 4003 // The message payload will be the total packet length minus 4004 // what we have consumed for the variable header 4005 pp.sz = pl - (r.pos - start) 4006 if pp.sz > 0 { 4007 start = r.pos 4008 r.pos += pp.sz 4009 pp.msg = r.buf[start:r.pos] 4010 } else { 4011 pp.msg = nil 4012 } 4013 return nil 4014 } 4015 4016 func mqttPubTrace(pp *mqttPublish) string { 4017 dup := pp.flags&mqttPubFlagDup != 0 4018 qos := mqttGetQoS(pp.flags) 4019 retain := mqttIsRetained(pp.flags) 4020 var piStr string 4021 if pp.pi > 0 { 4022 piStr = fmt.Sprintf(" pi=%v", pp.pi) 4023 } 4024 return fmt.Sprintf("%s dup=%v QoS=%v retain=%v size=%v%s", 4025 pp.topic, dup, qos, retain, pp.sz, piStr) 4026 } 4027 4028 // Composes a NATS message from a MQTT PUBLISH packet. The message includes an 4029 // internal header containint the original packet's QoS, and for QoS2 packets 4030 // the original subject. 4031 // 4032 // Example (QoS2, subject: "foo.bar"): 4033 // 4034 // NATS/1.0\r\n 4035 // Nmqtt-Pub:2foo.bar\r\n 4036 // \r\n 4037 func mqttNewDeliverableMessage(pp *mqttPublish, encodePP bool) (natsMsg []byte, headerLen int) { 4038 size := len(hdrLine) + 4039 len(mqttNatsHeader) + 2 + 2 + // 2 for ':<qos>', and 2 for CRLF 4040 2 + // end-of-header CRLF 4041 pp.sz 4042 if encodePP { 4043 size += len(mqttNatsHeaderSubject) + 1 + // +1 for ':' 4044 len(pp.subject) + 2 // 2 for CRLF 4045 4046 if len(pp.mapped) > 0 { 4047 size += len(mqttNatsHeaderMapped) + 1 + // +1 for ':' 4048 len(pp.mapped) + 2 // 2 for CRLF 4049 } 4050 } 4051 buf := bytes.NewBuffer(make([]byte, 0, size)) 4052 4053 qos := mqttGetQoS(pp.flags) 4054 4055 buf.WriteString(hdrLine) 4056 buf.WriteString(mqttNatsHeader) 4057 buf.WriteByte(':') 4058 buf.WriteByte(qos + '0') 4059 buf.WriteString(_CRLF_) 4060 4061 if encodePP { 4062 buf.WriteString(mqttNatsHeaderSubject) 4063 buf.WriteByte(':') 4064 buf.Write(pp.subject) 4065 buf.WriteString(_CRLF_) 4066 4067 if len(pp.mapped) > 0 { 4068 buf.WriteString(mqttNatsHeaderMapped) 4069 buf.WriteByte(':') 4070 buf.Write(pp.mapped) 4071 buf.WriteString(_CRLF_) 4072 } 4073 } 4074 4075 // End of header 4076 buf.WriteString(_CRLF_) 4077 4078 headerLen = buf.Len() 4079 4080 buf.Write(pp.msg) 4081 return buf.Bytes(), headerLen 4082 } 4083 4084 // Composes a NATS message for a pending PUBREL packet. The message includes an 4085 // internal header containing the PI for PUBREL/PUBCOMP. 4086 // 4087 // Example (PI:123): 4088 // 4089 // NATS/1.0\r\n 4090 // Nmqtt-PubRel:123\r\n 4091 // \r\n 4092 func mqttNewDeliverablePubRel(pi uint16) (natsMsg []byte, headerLen int) { 4093 size := len(hdrLine) + 4094 len(mqttNatsPubRelHeader) + 6 + 2 + // 6 for ':65535', and 2 for CRLF 4095 2 // end-of-header CRLF 4096 buf := bytes.NewBuffer(make([]byte, 0, size)) 4097 buf.WriteString(hdrLine) 4098 buf.WriteString(mqttNatsPubRelHeader) 4099 buf.WriteByte(':') 4100 buf.WriteString(strconv.FormatInt(int64(pi), 10)) 4101 buf.WriteString(_CRLF_) 4102 buf.WriteString(_CRLF_) 4103 return buf.Bytes(), buf.Len() 4104 } 4105 4106 // Process the PUBLISH packet. 4107 // 4108 // Runs from the client's readLoop. 4109 // No lock held on entry. 4110 func (s *Server) mqttProcessPub(c *client, pp *mqttPublish, trace bool) error { 4111 qos := mqttGetQoS(pp.flags) 4112 4113 switch qos { 4114 case 0: 4115 return s.mqttInitiateMsgDelivery(c, pp) 4116 4117 case 1: 4118 // [MQTT-4.3.2-2]. Initiate onward delivery of the Application Message, 4119 // Send PUBACK. 4120 // 4121 // The receiver is not required to complete delivery of the Application 4122 // Message before sending the PUBACK. When its original sender receives 4123 // the PUBACK packet, ownership of the Application Message is 4124 // transferred to the receiver. 4125 err := s.mqttInitiateMsgDelivery(c, pp) 4126 if err == nil { 4127 c.mqttEnqueuePubResponse(mqttPacketPubAck, pp.pi, trace) 4128 } 4129 return err 4130 4131 case 2: 4132 // [MQTT-4.3.3-2]. Method A, Store message, send PUBREC. 4133 // 4134 // The receiver is not required to complete delivery of the Application 4135 // Message before sending the PUBREC or PUBCOMP. When its original 4136 // sender receives the PUBREC packet, ownership of the Application 4137 // Message is transferred to the receiver. 4138 err := s.mqttStoreQoS2MsgOnce(c, pp) 4139 if err == nil { 4140 c.mqttEnqueuePubResponse(mqttPacketPubRec, pp.pi, trace) 4141 } 4142 return err 4143 4144 default: 4145 return fmt.Errorf("unreachable: invalid QoS in mqttProcessPub: %v", qos) 4146 } 4147 } 4148 4149 func (s *Server) mqttInitiateMsgDelivery(c *client, pp *mqttPublish) error { 4150 natsMsg, headerLen := mqttNewDeliverableMessage(pp, false) 4151 4152 // Set the client's pubarg for processing. 4153 c.pa.subject = pp.subject 4154 c.pa.mapped = pp.mapped 4155 c.pa.reply = nil 4156 c.pa.hdr = headerLen 4157 c.pa.hdb = []byte(strconv.FormatInt(int64(c.pa.hdr), 10)) 4158 c.pa.size = len(natsMsg) 4159 c.pa.szb = []byte(strconv.FormatInt(int64(c.pa.size), 10)) 4160 defer func() { 4161 c.pa.subject = nil 4162 c.pa.mapped = nil 4163 c.pa.reply = nil 4164 c.pa.hdr = -1 4165 c.pa.hdb = nil 4166 c.pa.size = 0 4167 c.pa.szb = nil 4168 }() 4169 4170 _, permIssue := c.processInboundClientMsg(natsMsg) 4171 if permIssue { 4172 return nil 4173 } 4174 4175 // If QoS 0 messages don't need to be stored, other (1 and 2) do. Store them 4176 // JetStream under "$MQTT.msgs.<delivery-subject>" 4177 if qos := mqttGetQoS(pp.flags); qos == 0 { 4178 return nil 4179 } 4180 4181 // We need to call flushClients now since this we may have called c.addToPCD 4182 // with destination clients (possibly a route). Without calling flushClients 4183 // the following call may then be stuck waiting for a reply that may never 4184 // come because the destination is not flushed (due to c.out.fsp > 0, 4185 // see addToPCD and writeLoop for details). 4186 c.flushClients(0) 4187 4188 _, err := c.mqtt.sess.jsa.storeMsg(mqttStreamSubjectPrefix+string(c.pa.subject), headerLen, natsMsg) 4189 4190 return err 4191 } 4192 4193 var mqttMaxMsgErrPattern = fmt.Sprintf("%s (%v)", ErrMaxMsgsPerSubject.Error(), JSStreamStoreFailedF) 4194 4195 func (s *Server) mqttStoreQoS2MsgOnce(c *client, pp *mqttPublish) error { 4196 // `true` means encode the MQTT PUBLISH packet in the NATS message header. 4197 natsMsg, headerLen := mqttNewDeliverableMessage(pp, true) 4198 4199 // Do not broadcast the message until it has been deduplicated and released 4200 // by the sender. Instead store this QoS2 message as 4201 // "$MQTT.qos2.<client-id>.<PI>". If the message is a duplicate, we get back 4202 // a ErrMaxMsgsPerSubject, otherwise it does not change the flow, still need 4203 // to send a PUBREC back to the client. The original subject (translated 4204 // from MQTT topic) is included in the NATS header of the stored message to 4205 // use for latter delivery. 4206 _, err := c.mqtt.sess.jsa.storeMsg(c.mqttQoS2InternalSubject(pp.pi), headerLen, natsMsg) 4207 4208 // TODO: would prefer a more robust and performant way of checking the 4209 // error, but it comes back wrapped as an API result. 4210 if err != nil && 4211 (isErrorOtherThan(err, JSStreamStoreFailedF) || err.Error() != mqttMaxMsgErrPattern) { 4212 return err 4213 } 4214 4215 return nil 4216 } 4217 4218 func (c *client) mqttQoS2InternalSubject(pi uint16) string { 4219 return mqttQoS2IncomingMsgsStreamSubjectPrefix + c.mqtt.cid + "." + strconv.FormatUint(uint64(pi), 10) 4220 } 4221 4222 // Process a PUBREL packet (QoS2, acting as Receiver). 4223 // 4224 // Runs from the client's readLoop. 4225 // No lock held on entry. 4226 func (s *Server) mqttProcessPubRel(c *client, pi uint16, trace bool) error { 4227 // Once done with the processing, send a PUBCOMP back to the client. 4228 defer c.mqttEnqueuePubResponse(mqttPacketPubComp, pi, trace) 4229 4230 // See if there is a message pending for this pi. All failures are treated 4231 // as "not found". 4232 asm := c.mqtt.asm 4233 stored, _ := asm.jsa.loadLastMsgFor(mqttQoS2IncomingMsgsStreamName, c.mqttQoS2InternalSubject(pi)) 4234 4235 if stored == nil { 4236 // No message found, nothing to do. 4237 return nil 4238 } 4239 // Best attempt to delete the message from the QoS2 stream. 4240 asm.jsa.deleteMsg(mqttQoS2IncomingMsgsStreamName, stored.Sequence, true) 4241 4242 // only MQTT QoS2 messages should be here, and they must have a subject. 4243 h := mqttParsePublishNATSHeader(stored.Header) 4244 if h == nil || h.qos != 2 || len(h.subject) == 0 { 4245 return errors.New("invalid message in QoS2 PUBREL stream") 4246 } 4247 4248 pp := &mqttPublish{ 4249 topic: natsSubjectToMQTTTopic(h.subject), 4250 subject: h.subject, 4251 mapped: h.mapped, 4252 msg: stored.Data, 4253 sz: len(stored.Data), 4254 pi: pi, 4255 flags: h.qos << 1, 4256 } 4257 4258 return s.mqttInitiateMsgDelivery(c, pp) 4259 } 4260 4261 // Invoked when processing an inbound client message. If the "retain" flag is 4262 // set, the message is stored so it can be later resent to (re)starting 4263 // subscriptions that match the subject. 4264 // 4265 // Invoked from the MQTT publisher's readLoop. No client lock is held on entry. 4266 func (c *client) mqttHandlePubRetain() { 4267 pp := c.mqtt.pp 4268 retainMQTT := mqttIsRetained(pp.flags) 4269 isBirth, _, isCertificate := sparkbParseBirthDeathTopic(pp.topic) 4270 retainSparkbBirth := isBirth && !isCertificate 4271 4272 // [tck-id-topics-nbirth-mqtt] NBIRTH messages MUST be published with MQTT 4273 // QoS equal to 0 and retain equal to false. 4274 // 4275 // [tck-id-conformance-mqtt-aware-nbirth-mqtt-retain] A Sparkplug Aware MQTT 4276 // Server MUST make NBIRTH messages available on the topic: 4277 // $sparkplug/certificates/namespace/group_id/NBIRTH/edge_node_id with the 4278 // MQTT retain flag set to true. 4279 if retainMQTT == retainSparkbBirth { 4280 // (retainSparkbBirth && retainMQTT) : not valid, so ignore altogether. 4281 // (!retainSparkbBirth && !retainMQTT) : nothing to do. 4282 return 4283 } 4284 4285 asm := c.mqtt.asm 4286 key := string(pp.subject) 4287 4288 // Always clear the retain flag to deliver a normal published message. 4289 defer func() { 4290 pp.flags &= ^mqttPubFlagRetain 4291 }() 4292 4293 // Spec [MQTT-3.3.1-11]. Payload of size 0 removes the retained message, but 4294 // should still be delivered as a normal message. 4295 if pp.sz == 0 { 4296 if seqToRemove := asm.handleRetainedMsgDel(key, 0); seqToRemove > 0 { 4297 asm.deleteRetainedMsg(seqToRemove) 4298 asm.notifyRetainedMsgDeleted(key, seqToRemove) 4299 } 4300 return 4301 } 4302 4303 rm := &mqttRetainedMsg{ 4304 Origin: asm.jsa.id, 4305 Msg: pp.msg, // will copy these bytes later as we process rm. 4306 Flags: pp.flags, 4307 Source: c.opts.Username, 4308 } 4309 4310 if retainSparkbBirth { 4311 // [tck-id-conformance-mqtt-aware-store] A Sparkplug Aware MQTT Server 4312 // MUST store NBIRTH and DBIRTH messages as they pass through the MQTT 4313 // Server. 4314 // 4315 // [tck-id-conformance-mqtt-aware-nbirth-mqtt-topic]. A Sparkplug Aware 4316 // MQTT Server MUST make NBIRTH messages available on a topic of the 4317 // form: $sparkplug/certificates/namespace/group_id/NBIRTH/edge_node_id 4318 // 4319 // [tck-id-conformance-mqtt-aware-dbirth-mqtt-topic] A Sparkplug Aware 4320 // MQTT Server MUST make DBIRTH messages available on a topic of the 4321 // form: 4322 // $sparkplug/certificates/namespace/group_id/DBIRTH/edge_node_id/device_id 4323 topic := append(sparkbCertificatesTopicPrefix, pp.topic...) 4324 subject, _ := mqttTopicToNATSPubSubject(topic) 4325 rm.Topic = string(topic) 4326 rm.Subject = string(subject) 4327 4328 // will use to save the retained message. 4329 key = string(subject) 4330 4331 // Store the retained message with the RETAIN flag set. 4332 rm.Flags |= mqttPubFlagRetain 4333 4334 // Copy the payload out of pp since we will be sending the message 4335 // asynchronously. 4336 msg := make([]byte, pp.sz) 4337 copy(msg, pp.msg[:pp.sz]) 4338 asm.jsa.sendMsg(key, msg) 4339 4340 } else { // isRetained 4341 // Spec [MQTT-3.3.1-5]. Store the retained message with its QoS. 4342 // 4343 // When coming from a publish protocol, `pp` is referencing a stack 4344 // variable that itself possibly references the read buffer. 4345 rm.Topic = string(pp.topic) 4346 } 4347 4348 // Set the key to the subject of the message for retained, or the composed 4349 // $sparkplug subject for sparkB. 4350 rm.Subject = key 4351 rmBytes, hdr := mqttEncodeRetainedMessage(rm) // will copy the payload bytes 4352 smr, err := asm.jsa.storeMsg(mqttRetainedMsgsStreamSubject+key, hdr, rmBytes) 4353 if err == nil { 4354 // Update the new sequence. 4355 rf := &mqttRetainedMsgRef{ 4356 sseq: smr.Sequence, 4357 } 4358 // Add/update the map. `true` to copy the payload bytes if needs to 4359 // update rmsCache. 4360 asm.handleRetainedMsg(key, rf, rm, true) 4361 } else { 4362 c.mu.Lock() 4363 acc := c.acc 4364 c.mu.Unlock() 4365 c.Errorf("unable to store retained message for account %q, subject %q: %v", 4366 acc.GetName(), key, err) 4367 } 4368 } 4369 4370 // After a config reload, it is possible that the source of a publish retained 4371 // message is no longer allowed to publish on the given topic. If that is the 4372 // case, the retained message is removed from the map and will no longer be 4373 // sent to (re)starting subscriptions. 4374 // 4375 // Server lock MUST NOT be held on entry. 4376 func (s *Server) mqttCheckPubRetainedPerms() { 4377 sm := &s.mqtt.sessmgr 4378 sm.mu.RLock() 4379 done := len(sm.sessions) == 0 4380 sm.mu.RUnlock() 4381 4382 if done { 4383 return 4384 } 4385 4386 s.mu.Lock() 4387 users := make(map[string]*User, len(s.users)) 4388 for un, u := range s.users { 4389 users[un] = u 4390 } 4391 s.mu.Unlock() 4392 4393 // First get a list of all of the sessions. 4394 sm.mu.RLock() 4395 asms := make([]*mqttAccountSessionManager, 0, len(sm.sessions)) 4396 for _, asm := range sm.sessions { 4397 asms = append(asms, asm) 4398 } 4399 sm.mu.RUnlock() 4400 4401 type retainedMsg struct { 4402 subj string 4403 rmsg *mqttRetainedMsgRef 4404 } 4405 4406 // For each session we will obtain a list of retained messages. 4407 var _rms [128]retainedMsg 4408 rms := _rms[:0] 4409 for _, asm := range asms { 4410 // Get all of the retained messages. Then we will sort them so 4411 // that they are in sequence order, which should help the file 4412 // store to not have to load out-of-order blocks so often. 4413 asm.mu.RLock() 4414 rms = rms[:0] // reuse slice 4415 for subj, rf := range asm.retmsgs { 4416 rms = append(rms, retainedMsg{ 4417 subj: subj, 4418 rmsg: rf, 4419 }) 4420 } 4421 asm.mu.RUnlock() 4422 sort.Slice(rms, func(i, j int) bool { 4423 return rms[i].rmsg.sseq < rms[j].rmsg.sseq 4424 }) 4425 4426 perms := map[string]*perm{} 4427 deletes := map[string]uint64{} 4428 for _, rf := range rms { 4429 jsm, err := asm.jsa.loadMsg(mqttRetainedMsgsStreamName, rf.rmsg.sseq) 4430 if err != nil || jsm == nil { 4431 continue 4432 } 4433 rm, err := mqttDecodeRetainedMessage(jsm.Header, jsm.Data) 4434 if err != nil { 4435 continue 4436 } 4437 if rm.Source == _EMPTY_ { 4438 continue 4439 } 4440 // Lookup source from global users. 4441 u := users[rm.Source] 4442 if u != nil { 4443 p, ok := perms[rm.Source] 4444 if !ok { 4445 p = generatePubPerms(u.Permissions) 4446 perms[rm.Source] = p 4447 } 4448 // If there is permission and no longer allowed to publish in 4449 // the subject, remove the publish retained message from the map. 4450 if p != nil && !pubAllowed(p, rf.subj) { 4451 u = nil 4452 } 4453 } 4454 4455 // Not present or permissions have changed such that the source can't 4456 // publish on that subject anymore: remove it from the map. 4457 if u == nil { 4458 asm.mu.Lock() 4459 delete(asm.retmsgs, rf.subj) 4460 asm.sl.Remove(rf.rmsg.sub) 4461 asm.mu.Unlock() 4462 deletes[rf.subj] = rf.rmsg.sseq 4463 } 4464 } 4465 4466 for subject, seq := range deletes { 4467 asm.deleteRetainedMsg(seq) 4468 asm.notifyRetainedMsgDeleted(subject, seq) 4469 } 4470 } 4471 } 4472 4473 // Helper to generate only pub permissions from a Permissions object 4474 func generatePubPerms(perms *Permissions) *perm { 4475 var p *perm 4476 if perms.Publish.Allow != nil { 4477 p = &perm{} 4478 p.allow = NewSublistWithCache() 4479 for _, pubSubject := range perms.Publish.Allow { 4480 sub := &subscription{subject: []byte(pubSubject)} 4481 p.allow.Insert(sub) 4482 } 4483 } 4484 if len(perms.Publish.Deny) > 0 { 4485 if p == nil { 4486 p = &perm{} 4487 } 4488 p.deny = NewSublistWithCache() 4489 for _, pubSubject := range perms.Publish.Deny { 4490 sub := &subscription{subject: []byte(pubSubject)} 4491 p.deny.Insert(sub) 4492 } 4493 } 4494 return p 4495 } 4496 4497 // Helper that checks if given `perms` allow to publish on the given `subject` 4498 func pubAllowed(perms *perm, subject string) bool { 4499 allowed := true 4500 if perms.allow != nil { 4501 r := perms.allow.Match(subject) 4502 allowed = len(r.psubs) != 0 4503 } 4504 // If we have a deny list and are currently allowed, check that as well. 4505 if allowed && perms.deny != nil { 4506 r := perms.deny.Match(subject) 4507 allowed = len(r.psubs) == 0 4508 } 4509 return allowed 4510 } 4511 4512 func (c *client) mqttEnqueuePubResponse(packetType byte, pi uint16, trace bool) { 4513 proto := [4]byte{packetType, 0x2, 0, 0} 4514 proto[2] = byte(pi >> 8) 4515 proto[3] = byte(pi) 4516 4517 // Bits 3,2,1 and 0 of the fixed header in the PUBREL Control Packet are 4518 // reserved and MUST be set to 0,0,1 and 0 respectively. The Server MUST treat 4519 // any other value as malformed and close the Network Connection [MQTT-3.6.1-1]. 4520 if packetType == mqttPacketPubRel { 4521 proto[0] |= 0x2 4522 } 4523 4524 c.mu.Lock() 4525 c.enqueueProto(proto[:4]) 4526 c.mu.Unlock() 4527 4528 if trace { 4529 name := "(???)" 4530 switch packetType { 4531 case mqttPacketPubAck: 4532 name = "PUBACK" 4533 case mqttPacketPubRec: 4534 name = "PUBREC" 4535 case mqttPacketPubRel: 4536 name = "PUBREL" 4537 case mqttPacketPubComp: 4538 name = "PUBCOMP" 4539 } 4540 c.traceOutOp(name, []byte(fmt.Sprintf("pi=%v", pi))) 4541 } 4542 } 4543 4544 func mqttParsePIPacket(r *mqttReader) (uint16, error) { 4545 pi, err := r.readUint16("packet identifier") 4546 if err != nil { 4547 return 0, err 4548 } 4549 if pi == 0 { 4550 return 0, errMQTTPacketIdentifierIsZero 4551 } 4552 return pi, nil 4553 } 4554 4555 // Process a PUBACK (QoS1) or a PUBREC (QoS2) packet, acting as Sender. Set 4556 // isPubRec to false to process as a PUBACK. 4557 // 4558 // Runs from the client's readLoop. No lock held on entry. 4559 func (c *client) mqttProcessPublishReceived(pi uint16, isPubRec bool) (err error) { 4560 sess := c.mqtt.sess 4561 if sess == nil { 4562 return errMQTTInvalidSession 4563 } 4564 4565 var jsAckSubject string 4566 sess.mu.Lock() 4567 // Must be the same client, and the session must have been setup for QoS2. 4568 if sess.c != c { 4569 sess.mu.Unlock() 4570 return errMQTTInvalidSession 4571 } 4572 if isPubRec { 4573 // The JS ACK subject for the PUBREL will be filled in at the delivery 4574 // attempt. 4575 sess.trackAsPubRel(pi, _EMPTY_) 4576 } 4577 jsAckSubject = sess.untrackPublish(pi) 4578 sess.mu.Unlock() 4579 4580 if isPubRec { 4581 natsMsg, headerLen := mqttNewDeliverablePubRel(pi) 4582 _, err = sess.jsa.storeMsg(sess.pubRelSubject, headerLen, natsMsg) 4583 if err != nil { 4584 // Failure to send out PUBREL will terminate the connection. 4585 return err 4586 } 4587 } 4588 4589 // Send the ack to JS to remove the pending message from the consumer. 4590 sess.jsa.sendAck(jsAckSubject) 4591 return nil 4592 } 4593 4594 func (c *client) mqttProcessPubAck(pi uint16) error { 4595 return c.mqttProcessPublishReceived(pi, false) 4596 } 4597 4598 func (c *client) mqttProcessPubRec(pi uint16) error { 4599 return c.mqttProcessPublishReceived(pi, true) 4600 } 4601 4602 // Runs from the client's readLoop. No lock held on entry. 4603 func (c *client) mqttProcessPubComp(pi uint16) { 4604 sess := c.mqtt.sess 4605 if sess == nil { 4606 return 4607 } 4608 4609 var jsAckSubject string 4610 sess.mu.Lock() 4611 if sess.c != c { 4612 sess.mu.Unlock() 4613 return 4614 } 4615 jsAckSubject = sess.untrackPubRel(pi) 4616 sess.mu.Unlock() 4617 4618 // Send the ack to JS to remove the pending message from the consumer. 4619 sess.jsa.sendAck(jsAckSubject) 4620 } 4621 4622 // Return the QoS from the given PUBLISH protocol's flags 4623 func mqttGetQoS(flags byte) byte { 4624 return flags & mqttPubFlagQoS >> 1 4625 } 4626 4627 func mqttIsRetained(flags byte) bool { 4628 return flags&mqttPubFlagRetain != 0 4629 } 4630 4631 func sparkbParseBirthDeathTopic(topic []byte) (isBirth, isDeath, isCertificate bool) { 4632 if bytes.HasPrefix(topic, sparkbCertificatesTopicPrefix) { 4633 isCertificate = true 4634 topic = topic[len(sparkbCertificatesTopicPrefix):] 4635 } 4636 if !bytes.HasPrefix(topic, sparkbNamespaceTopicPrefix) { 4637 return false, false, false 4638 } 4639 topic = topic[len(sparkbNamespaceTopicPrefix):] 4640 4641 parts := bytes.Split(topic, []byte{'/'}) 4642 if len(parts) < 3 || len(parts) > 4 { 4643 return false, false, false 4644 } 4645 typ := bytesToString(parts[1]) 4646 switch typ { 4647 case sparkbNBIRTH, sparkbDBIRTH: 4648 isBirth = true 4649 case sparkbNDEATH, sparkbDDEATH: 4650 isDeath = true 4651 default: 4652 return false, false, false 4653 } 4654 return isBirth, isDeath, isCertificate 4655 } 4656 4657 ////////////////////////////////////////////////////////////////////////////// 4658 // 4659 // SUBSCRIBE related functions 4660 // 4661 ////////////////////////////////////////////////////////////////////////////// 4662 4663 func (c *client) mqttParseSubs(r *mqttReader, b byte, pl int) (uint16, []*mqttFilter, error) { 4664 return c.mqttParseSubsOrUnsubs(r, b, pl, true) 4665 } 4666 4667 func (c *client) mqttParseSubsOrUnsubs(r *mqttReader, b byte, pl int, sub bool) (uint16, []*mqttFilter, error) { 4668 var expectedFlag byte 4669 var action string 4670 if sub { 4671 expectedFlag = mqttSubscribeFlags 4672 } else { 4673 expectedFlag = mqttUnsubscribeFlags 4674 action = "un" 4675 } 4676 // Spec [MQTT-3.8.1-1], [MQTT-3.10.1-1] 4677 if rf := b & 0xf; rf != expectedFlag { 4678 return 0, nil, fmt.Errorf("wrong %ssubscribe reserved flags: %x", action, rf) 4679 } 4680 pi, err := r.readUint16("packet identifier") 4681 if err != nil { 4682 return 0, nil, fmt.Errorf("reading packet identifier: %v", err) 4683 } 4684 end := r.pos + (pl - 2) 4685 var filters []*mqttFilter 4686 for r.pos < end { 4687 // Don't make a copy now because, this will happen during conversion 4688 // or when processing the sub. 4689 topic, err := r.readBytes("topic filter", false) 4690 if err != nil { 4691 return 0, nil, err 4692 } 4693 if len(topic) == 0 { 4694 return 0, nil, errMQTTTopicFilterCannotBeEmpty 4695 } 4696 // Spec [MQTT-3.8.3-1], [MQTT-3.10.3-1] 4697 if !utf8.Valid(topic) { 4698 return 0, nil, fmt.Errorf("invalid utf8 for topic filter %q", topic) 4699 } 4700 var qos byte 4701 // We are going to report if we had an error during the conversion, 4702 // but we don't fail the parsing. When processing the sub, we will 4703 // have an error then, and the processing of subs code will send 4704 // the proper mqttSubAckFailure flag for this given subscription. 4705 filter, err := mqttFilterToNATSSubject(topic) 4706 if err != nil { 4707 c.Errorf("invalid topic %q: %v", topic, err) 4708 } 4709 if sub { 4710 qos, err = r.readByte("QoS") 4711 if err != nil { 4712 return 0, nil, err 4713 } 4714 // Spec [MQTT-3-8.3-4]. 4715 if qos > 2 { 4716 return 0, nil, fmt.Errorf("subscribe QoS value must be 0, 1 or 2, got %v", qos) 4717 } 4718 } 4719 f := &mqttFilter{ttopic: topic, filter: string(filter), qos: qos} 4720 filters = append(filters, f) 4721 } 4722 // Spec [MQTT-3.8.3-3], [MQTT-3.10.3-2] 4723 if len(filters) == 0 { 4724 return 0, nil, fmt.Errorf("%ssubscribe protocol must contain at least 1 topic filter", action) 4725 } 4726 return pi, filters, nil 4727 } 4728 4729 func mqttSubscribeTrace(pi uint16, filters []*mqttFilter) string { 4730 var sep string 4731 sb := &strings.Builder{} 4732 sb.WriteString("[") 4733 for i, f := range filters { 4734 sb.WriteString(sep) 4735 sb.Write(f.ttopic) 4736 sb.WriteString(" (") 4737 sb.WriteString(f.filter) 4738 sb.WriteString(") QoS=") 4739 sb.WriteString(fmt.Sprintf("%v", f.qos)) 4740 if i == 0 { 4741 sep = ", " 4742 } 4743 } 4744 sb.WriteString(fmt.Sprintf("] pi=%v", pi)) 4745 return sb.String() 4746 } 4747 4748 // For a MQTT QoS0 subscription, we create a single NATS subscription on the 4749 // actual subject, for instance "foo.bar". 4750 // 4751 // For a MQTT QoS1+ subscription, we create 2 subscriptions, one on "foo.bar" 4752 // (as for QoS0, but sub.mqtt.qos will be 1 or 2), and one on the subject 4753 // "$MQTT.sub.<uid>" which is the delivery subject of the JS durable consumer 4754 // with the filter subject "$MQTT.msgs.foo.bar". 4755 // 4756 // This callback delivers messages to the client as QoS0 messages, either 4757 // because: (a) they have been produced as MQTT QoS0 messages (and therefore 4758 // only this callback can receive them); (b) they are MQTT QoS1+ published 4759 // messages but this callback is for a subscription that is QoS0; or (c) the 4760 // published messages come from (other) NATS publishers on the subject. 4761 // 4762 // This callback must reject a message if it is known to be a QoS1+ published 4763 // message and this is the callback for a QoS1+ subscription because in that 4764 // case, it will be handled by the other callback. This avoid getting duplicate 4765 // deliveries. 4766 func mqttDeliverMsgCbQoS0(sub *subscription, pc *client, _ *Account, subject, reply string, rmsg []byte) { 4767 if pc.kind == JETSTREAM && len(reply) > 0 && strings.HasPrefix(reply, jsAckPre) { 4768 return 4769 } 4770 4771 // This is the client associated with the subscription. 4772 cc := sub.client 4773 4774 // This is immutable 4775 sess := cc.mqtt.sess 4776 4777 // Lock here, otherwise we may be called with sub.mqtt == nil. Ignore 4778 // wildcard subscriptions if this subject starts with '$', per Spec 4779 // [MQTT-4.7.2-1]. 4780 sess.subsMu.RLock() 4781 subQoS := sub.mqtt.qos 4782 ignore := mqttMustIgnoreForReservedSub(sub, subject) 4783 sess.subsMu.RUnlock() 4784 4785 if ignore { 4786 return 4787 } 4788 4789 hdr, msg := pc.msgParts(rmsg) 4790 var topic []byte 4791 if pc.isMqtt() { 4792 // This is an MQTT publisher directly connected to this server. 4793 4794 // Check the subscription's QoS. If the message was published with a 4795 // QoS>0 and the sub has the QoS>0 then the message will be delivered by 4796 // mqttDeliverMsgCbQoS12. 4797 msgQoS := mqttGetQoS(pc.mqtt.pp.flags) 4798 if subQoS > 0 && msgQoS > 0 { 4799 return 4800 } 4801 topic = pc.mqtt.pp.topic 4802 // Check for service imports where subject mapping is in play. 4803 if len(pc.pa.mapped) > 0 && len(pc.pa.psi) > 0 { 4804 topic = natsSubjectStrToMQTTTopic(subject) 4805 } 4806 4807 } else { 4808 // Non MQTT client, could be NATS publisher, or ROUTER, etc.. 4809 h := mqttParsePublishNATSHeader(hdr) 4810 4811 // Check the subscription's QoS. If the message was published with a 4812 // QoS>0 (in the header) and the sub has the QoS>0 then the message will 4813 // be delivered by mqttDeliverMsgCbQoS12. 4814 if subQoS > 0 && h != nil && h.qos > 0 { 4815 return 4816 } 4817 4818 // If size is more than what a MQTT client can handle, we should probably reject, 4819 // for now just truncate. 4820 if len(msg) > mqttMaxPayloadSize { 4821 msg = msg[:mqttMaxPayloadSize] 4822 } 4823 topic = natsSubjectStrToMQTTTopic(subject) 4824 } 4825 4826 // Message never has a packet identifier nor is marked as duplicate. 4827 pc.mqttEnqueuePublishMsgTo(cc, sub, 0, 0, false, topic, msg) 4828 } 4829 4830 // This is the callback attached to a JS durable subscription for a MQTT QoS 1+ 4831 // sub. Only JETSTREAM should be sending a message to this subject (the delivery 4832 // subject associated with the JS durable consumer), but in cluster mode, this 4833 // can be coming from a route, gw, etc... We make sure that if this is the case, 4834 // the message contains a NATS/MQTT header that indicates that this is a 4835 // published QoS1+ message. 4836 func mqttDeliverMsgCbQoS12(sub *subscription, pc *client, _ *Account, subject, reply string, rmsg []byte) { 4837 // Message on foo.bar is stored under $MQTT.msgs.foo.bar, so the subject has to be 4838 // at least as long as the stream subject prefix "$MQTT.msgs.", and after removing 4839 // the prefix, has to be at least 1 character long. 4840 if len(subject) < len(mqttStreamSubjectPrefix)+1 { 4841 return 4842 } 4843 4844 hdr, msg := pc.msgParts(rmsg) 4845 h := mqttParsePublishNATSHeader(hdr) 4846 if pc.kind != JETSTREAM && (h == nil || h.qos == 0) { 4847 // MQTT QoS 0 messages must be ignored, they will be delivered by the 4848 // other callback, the direct NATS subscription. All JETSTREAM messages 4849 // will have the header. 4850 return 4851 } 4852 4853 // This is the client associated with the subscription. 4854 cc := sub.client 4855 4856 // This is immutable 4857 sess := cc.mqtt.sess 4858 4859 // We lock to check some of the subscription's fields and if we need to keep 4860 // track of pending acks, etc. There is no need to acquire the subsMu RLock 4861 // since sess.Lock is overarching for modifying subscriptions. 4862 sess.mu.Lock() 4863 if sess.c != cc || sub.mqtt == nil { 4864 sess.mu.Unlock() 4865 return 4866 } 4867 4868 // In this callback we handle only QoS-published messages to QoS 4869 // subscriptions. Ignore if either is 0, will be delivered by the other 4870 // callback, mqttDeliverMsgCbQos1. 4871 var qos byte 4872 if h != nil { 4873 qos = h.qos 4874 } 4875 if qos > sub.mqtt.qos { 4876 qos = sub.mqtt.qos 4877 } 4878 if qos == 0 { 4879 sess.mu.Unlock() 4880 return 4881 } 4882 4883 // Check for reserved subject violation. If so, we will send the ack to 4884 // remove the message, and do nothing else. 4885 strippedSubj := subject[len(mqttStreamSubjectPrefix):] 4886 if mqttMustIgnoreForReservedSub(sub, strippedSubj) { 4887 sess.mu.Unlock() 4888 sess.jsa.sendAck(reply) 4889 return 4890 } 4891 4892 pi, dup := sess.trackPublish(sub.mqtt.jsDur, reply) 4893 sess.mu.Unlock() 4894 4895 if pi == 0 { 4896 // We have reached max pending, don't send the message now. 4897 // JS will cause a redelivery and if by then the number of pending 4898 // messages has fallen below threshold, the message will be resent. 4899 return 4900 } 4901 4902 originalTopic := natsSubjectStrToMQTTTopic(strippedSubj) 4903 pc.mqttEnqueuePublishMsgTo(cc, sub, pi, qos, dup, originalTopic, msg) 4904 } 4905 4906 func mqttDeliverPubRelCb(sub *subscription, pc *client, _ *Account, subject, reply string, rmsg []byte) { 4907 if sub.client.mqtt == nil || sub.client.mqtt.sess == nil || reply == _EMPTY_ { 4908 return 4909 } 4910 4911 hdr, _ := pc.msgParts(rmsg) 4912 pi := mqttParsePubRelNATSHeader(hdr) 4913 if pi == 0 { 4914 return 4915 } 4916 4917 // This is the client associated with the subscription. 4918 cc := sub.client 4919 4920 // This is immutable 4921 sess := cc.mqtt.sess 4922 4923 sess.mu.Lock() 4924 if sess.c != cc || sess.pubRelConsumer == nil { 4925 sess.mu.Unlock() 4926 return 4927 } 4928 sess.trackAsPubRel(pi, reply) 4929 trace := cc.trace 4930 sess.mu.Unlock() 4931 4932 cc.mqttEnqueuePubResponse(mqttPacketPubRel, pi, trace) 4933 } 4934 4935 // The MQTT Server MUST NOT match Topic Filters starting with a wildcard 4936 // character (# or +) with Topic Names beginning with a $ character, Spec 4937 // [MQTT-4.7.2-1]. We will return true if there is a violation. 4938 // 4939 // Session or subMu lock must be held on entry to protect access to sub.mqtt. 4940 func mqttMustIgnoreForReservedSub(sub *subscription, subject string) bool { 4941 // If the subject does not start with $ nothing to do here. 4942 if !sub.mqtt.reserved || len(subject) == 0 || subject[0] != mqttReservedPre { 4943 return false 4944 } 4945 return true 4946 } 4947 4948 // Check if a sub is a reserved wildcard. E.g. '#', '*', or '*/" prefix. 4949 func isMQTTReservedSubscription(subject string) bool { 4950 if len(subject) == 1 && (subject[0] == fwc || subject[0] == pwc) { 4951 return true 4952 } 4953 // Match "*.<>" 4954 if len(subject) > 1 && (subject[0] == pwc && subject[1] == btsep) { 4955 return true 4956 } 4957 return false 4958 } 4959 4960 func sparkbReplaceDeathTimestamp(msg []byte) []byte { 4961 const VARINT = 0 4962 const TIMESTAMP = 1 4963 4964 orig := msg 4965 buf := bytes.NewBuffer(make([]byte, 0, len(msg)+16)) // 16 bytes should be enough if we need to add a timestamp 4966 writeDeathTimestamp := func() { 4967 // [tck-id-conformance-mqtt-aware-ndeath-timestamp] A Sparkplug Aware 4968 // MQTT Server MAY replace the timestamp of NDEATH messages. If it does, 4969 // it MUST set the timestamp to the UTC time at which it attempts to 4970 // deliver the NDEATH to subscribed clients 4971 // 4972 // sparkB spec: 6.4.1. Google Protocol Buffer Schema 4973 // optional uint64 timestamp = 1; // Timestamp at message sending time 4974 // 4975 // SparkplugB timestamps are milliseconds since epoch, represented as 4976 // uint64 in go, transmitted as protobuf varint. 4977 ts := uint64(time.Now().UnixMilli()) 4978 buf.Write(protoEncodeVarint(TIMESTAMP<<3 | VARINT)) 4979 buf.Write(protoEncodeVarint(ts)) 4980 } 4981 4982 for len(msg) > 0 { 4983 fieldNumericID, fieldType, size, err := protoScanField(msg) 4984 if err != nil { 4985 return orig 4986 } 4987 if fieldType != VARINT || fieldNumericID != TIMESTAMP { 4988 // Add the field as is 4989 buf.Write(msg[:size]) 4990 msg = msg[size:] 4991 continue 4992 } 4993 4994 writeDeathTimestamp() 4995 4996 // Add the rest of the message as is, we are done 4997 buf.Write(msg[size:]) 4998 return buf.Bytes() 4999 } 5000 5001 // Add timestamp if we did not find one. 5002 writeDeathTimestamp() 5003 5004 return buf.Bytes() 5005 } 5006 5007 // Common function to mqtt delivery callbacks to serialize and send the message 5008 // to the `cc` client. 5009 func (c *client) mqttEnqueuePublishMsgTo(cc *client, sub *subscription, pi uint16, qos byte, dup bool, topic, msg []byte) { 5010 // [tck-id-conformance-mqtt-aware-nbirth-mqtt-retain] A Sparkplug Aware 5011 // MQTT Server MUST make NBIRTH messages available on the topic: 5012 // $sparkplug/certificates/namespace/group_id/NBIRTH/edge_node_id with 5013 // the MQTT retain flag set to true 5014 // 5015 // [tck-id-conformance-mqtt-aware-dbirth-mqtt-retain] A Sparkplug Aware 5016 // MQTT Server MUST make DBIRTH messages available on the topic: 5017 // $sparkplug/certificates/namespace/group_id/DBIRTH/edge_node_id/device_id 5018 // with the MQTT retain flag set to true 5019 // 5020 // $sparkplug/certificates messages are sent as NATS messages, so we 5021 // need to add the retain flag when sending them to MQTT ciients. 5022 5023 retain := false 5024 isBirth, isDeath, isCertificate := sparkbParseBirthDeathTopic(topic) 5025 if isBirth && qos == 0 { 5026 retain = isCertificate 5027 } else if isDeath && !isCertificate { 5028 msg = sparkbReplaceDeathTimestamp(msg) 5029 } 5030 5031 flags, headerBytes := mqttMakePublishHeader(pi, qos, dup, retain, topic, len(msg)) 5032 5033 cc.mu.Lock() 5034 if sub.mqtt.prm != nil { 5035 for _, data := range sub.mqtt.prm { 5036 cc.queueOutbound(data) 5037 } 5038 sub.mqtt.prm = nil 5039 } 5040 cc.queueOutbound(headerBytes) 5041 cc.queueOutbound(msg) 5042 c.addToPCD(cc) 5043 trace := cc.trace 5044 cc.mu.Unlock() 5045 5046 if trace { 5047 pp := mqttPublish{ 5048 topic: topic, 5049 flags: flags, 5050 pi: pi, 5051 sz: len(msg), 5052 } 5053 cc.traceOutOp("PUBLISH", []byte(mqttPubTrace(&pp))) 5054 } 5055 } 5056 5057 // Serializes to the given writer the message for the given subject. 5058 func (w *mqttWriter) WritePublishHeader(pi uint16, qos byte, dup, retained bool, topic []byte, msgLen int) byte { 5059 // Compute len (will have to add packet id if message is sent as QoS>=1) 5060 pkLen := 2 + len(topic) + msgLen 5061 var flags byte 5062 5063 // Set flags for dup/retained/qos1 5064 if dup { 5065 flags |= mqttPubFlagDup 5066 } 5067 if retained { 5068 flags |= mqttPubFlagRetain 5069 } 5070 if qos > 0 { 5071 pkLen += 2 5072 flags |= qos << 1 5073 } 5074 5075 w.WriteByte(mqttPacketPub | flags) 5076 w.WriteVarInt(pkLen) 5077 w.WriteBytes(topic) 5078 if qos > 0 { 5079 w.WriteUint16(pi) 5080 } 5081 5082 return flags 5083 } 5084 5085 // Serializes to the given writer the message for the given subject. 5086 func mqttMakePublishHeader(pi uint16, qos byte, dup, retained bool, topic []byte, msgLen int) (byte, []byte) { 5087 headerBuf := newMQTTWriter(mqttInitialPubHeader + len(topic)) 5088 flags := headerBuf.WritePublishHeader(pi, qos, dup, retained, topic, msgLen) 5089 return flags, headerBuf.Bytes() 5090 } 5091 5092 // Process the SUBSCRIBE packet. 5093 // 5094 // Process the list of subscriptions and update the given filter 5095 // with the QoS that has been accepted (or failure). 5096 // 5097 // Spec [MQTT-3.8.4-3] says that if an exact same subscription is 5098 // found, it needs to be replaced with the new one (possibly updating 5099 // the qos) and that the flow of publications must not be interrupted, 5100 // which I read as the replacement cannot be a "remove then add" if there 5101 // is a chance that in between the 2 actions, published messages 5102 // would be "lost" because there would not be any matching subscription. 5103 // 5104 // Run from client's readLoop. 5105 // No lock held on entry. 5106 func (c *client) mqttProcessSubs(filters []*mqttFilter) ([]*subscription, error) { 5107 // Those things are immutable, but since processing subs is not 5108 // really in the fast path, let's get them under the client lock. 5109 c.mu.Lock() 5110 asm := c.mqtt.asm 5111 sess := c.mqtt.sess 5112 trace := c.trace 5113 c.mu.Unlock() 5114 5115 if err := asm.lockSession(sess, c); err != nil { 5116 return nil, err 5117 } 5118 defer asm.unlockSession(sess) 5119 return asm.processSubs(sess, c, filters, true, trace) 5120 } 5121 5122 // Cleanup that is performed in processSubs if there was an error. 5123 // 5124 // Runs from client's readLoop. 5125 // Lock not held on entry, but session is in the locked map. 5126 func (sess *mqttSession) cleanupFailedSub(c *client, sub *subscription, cc *ConsumerConfig, jssub *subscription) { 5127 if sub != nil { 5128 c.processUnsub(sub.sid) 5129 } 5130 if jssub != nil { 5131 c.processUnsub(jssub.sid) 5132 } 5133 if cc != nil { 5134 sess.deleteConsumer(cc) 5135 } 5136 } 5137 5138 // Make sure we are set up to deliver PUBREL messages to this QoS2-subscribed 5139 // session. 5140 func (sess *mqttSession) ensurePubRelConsumerSubscription(c *client) error { 5141 opts := c.srv.getOpts() 5142 ackWait := opts.MQTT.AckWait 5143 if ackWait == 0 { 5144 ackWait = mqttDefaultAckWait 5145 } 5146 maxAckPending := int(opts.MQTT.MaxAckPending) 5147 if maxAckPending == 0 { 5148 maxAckPending = mqttDefaultMaxAckPending 5149 } 5150 5151 sess.mu.Lock() 5152 pubRelSubscribed := sess.pubRelSubscribed 5153 pubRelSubject := sess.pubRelSubject 5154 pubRelDeliverySubjectB := sess.pubRelDeliverySubjectB 5155 pubRelDeliverySubject := sess.pubRelDeliverySubject 5156 pubRelConsumer := sess.pubRelConsumer 5157 tmaxack := sess.tmaxack 5158 idHash := sess.idHash 5159 id := sess.id 5160 sess.mu.Unlock() 5161 5162 // Subscribe before the consumer is created so we don't loose any messages. 5163 if !pubRelSubscribed { 5164 _, err := c.processSub(pubRelDeliverySubjectB, nil, pubRelDeliverySubjectB, 5165 mqttDeliverPubRelCb, false) 5166 if err != nil { 5167 c.Errorf("Unable to create subscription for JetStream consumer on %q: %v", pubRelDeliverySubject, err) 5168 return err 5169 } 5170 pubRelSubscribed = true 5171 } 5172 5173 // Create the consumer if needed. 5174 if pubRelConsumer == nil { 5175 // Check that the limit of subs' maxAckPending are not going over the limit 5176 if after := tmaxack + maxAckPending; after > mqttMaxAckTotalLimit { 5177 return fmt.Errorf("max_ack_pending for all consumers would be %v which exceeds the limit of %v", 5178 after, mqttMaxAckTotalLimit) 5179 } 5180 5181 ccr := &CreateConsumerRequest{ 5182 Stream: mqttOutStreamName, 5183 Config: ConsumerConfig{ 5184 DeliverSubject: pubRelDeliverySubject, 5185 Durable: mqttPubRelConsumerDurablePrefix + idHash, 5186 AckPolicy: AckExplicit, 5187 DeliverPolicy: DeliverNew, 5188 FilterSubject: pubRelSubject, 5189 AckWait: ackWait, 5190 MaxAckPending: maxAckPending, 5191 MemoryStorage: opts.MQTT.ConsumerMemoryStorage, 5192 }, 5193 } 5194 if opts.MQTT.ConsumerInactiveThreshold > 0 { 5195 ccr.Config.InactiveThreshold = opts.MQTT.ConsumerInactiveThreshold 5196 } 5197 if _, err := sess.jsa.createDurableConsumer(ccr); err != nil { 5198 c.Errorf("Unable to add JetStream consumer for PUBREL for client %q: err=%v", id, err) 5199 return err 5200 } 5201 pubRelConsumer = &ccr.Config 5202 tmaxack += maxAckPending 5203 } 5204 5205 sess.mu.Lock() 5206 sess.pubRelSubscribed = pubRelSubscribed 5207 sess.pubRelConsumer = pubRelConsumer 5208 sess.tmaxack = tmaxack 5209 sess.mu.Unlock() 5210 5211 return nil 5212 } 5213 5214 // When invoked with a QoS of 0, looks for an existing JS durable consumer for 5215 // the given sid and if one is found, delete the JS durable consumer and unsub 5216 // the NATS subscription on the delivery subject. 5217 // 5218 // With a QoS > 0, creates or update the existing JS durable consumer along with 5219 // its NATS subscription on a delivery subject. 5220 // 5221 // Session lock is acquired and released as needed. Session is in the locked 5222 // map. 5223 func (sess *mqttSession) processJSConsumer(c *client, subject, sid string, 5224 qos byte, fromSubProto bool) (*ConsumerConfig, *subscription, error) { 5225 5226 sess.mu.Lock() 5227 cc, exists := sess.cons[sid] 5228 tmaxack := sess.tmaxack 5229 idHash := sess.idHash 5230 sess.mu.Unlock() 5231 5232 // Check if we are already a JS consumer for this SID. 5233 if exists { 5234 // If current QoS is 0, it means that we need to delete the existing 5235 // one (that was QoS > 0) 5236 if qos == 0 { 5237 // The JS durable consumer's delivery subject is on a NUID of 5238 // the form: mqttSubPrefix + <nuid>. It is also used as the sid 5239 // for the NATS subscription, so use that for the lookup. 5240 c.mu.Lock() 5241 sub := c.subs[cc.DeliverSubject] 5242 c.mu.Unlock() 5243 5244 sess.mu.Lock() 5245 delete(sess.cons, sid) 5246 sess.mu.Unlock() 5247 5248 sess.deleteConsumer(cc) 5249 if sub != nil { 5250 c.processUnsub(sub.sid) 5251 } 5252 return nil, nil, nil 5253 } 5254 // If this is called when processing SUBSCRIBE protocol, then if 5255 // the JS consumer already exists, we are done (it was created 5256 // during the processing of CONNECT). 5257 if fromSubProto { 5258 return nil, nil, nil 5259 } 5260 } 5261 // Here it means we don't have a JS consumer and if we are QoS 0, 5262 // we have nothing to do. 5263 if qos == 0 { 5264 return nil, nil, nil 5265 } 5266 var err error 5267 var inbox string 5268 if exists { 5269 inbox = cc.DeliverSubject 5270 } else { 5271 inbox = mqttSubPrefix + nuid.Next() 5272 opts := c.srv.getOpts() 5273 ackWait := opts.MQTT.AckWait 5274 if ackWait == 0 { 5275 ackWait = mqttDefaultAckWait 5276 } 5277 maxAckPending := int(opts.MQTT.MaxAckPending) 5278 if maxAckPending == 0 { 5279 maxAckPending = mqttDefaultMaxAckPending 5280 } 5281 5282 // Check that the limit of subs' maxAckPending are not going over the limit 5283 if after := tmaxack + maxAckPending; after > mqttMaxAckTotalLimit { 5284 return nil, nil, fmt.Errorf("max_ack_pending for all consumers would be %v which exceeds the limit of %v", 5285 after, mqttMaxAckTotalLimit) 5286 } 5287 5288 durName := idHash + "_" + nuid.Next() 5289 ccr := &CreateConsumerRequest{ 5290 Stream: mqttStreamName, 5291 Config: ConsumerConfig{ 5292 DeliverSubject: inbox, 5293 Durable: durName, 5294 AckPolicy: AckExplicit, 5295 DeliverPolicy: DeliverNew, 5296 FilterSubject: mqttStreamSubjectPrefix + subject, 5297 AckWait: ackWait, 5298 MaxAckPending: maxAckPending, 5299 MemoryStorage: opts.MQTT.ConsumerMemoryStorage, 5300 }, 5301 } 5302 if opts.MQTT.ConsumerInactiveThreshold > 0 { 5303 ccr.Config.InactiveThreshold = opts.MQTT.ConsumerInactiveThreshold 5304 } 5305 if _, err := sess.jsa.createDurableConsumer(ccr); err != nil { 5306 c.Errorf("Unable to add JetStream consumer for subscription on %q: err=%v", subject, err) 5307 return nil, nil, err 5308 } 5309 cc = &ccr.Config 5310 tmaxack += maxAckPending 5311 } 5312 5313 // This is an internal subscription on subject like "$MQTT.sub.<nuid>" that is setup 5314 // for the JS durable's deliver subject. 5315 sess.mu.Lock() 5316 sess.tmaxack = tmaxack 5317 sub, err := sess.processQOS12Sub(c, []byte(inbox), []byte(inbox), 5318 isMQTTReservedSubscription(subject), qos, cc.Durable, mqttDeliverMsgCbQoS12) 5319 sess.mu.Unlock() 5320 5321 if err != nil { 5322 sess.deleteConsumer(cc) 5323 c.Errorf("Unable to create subscription for JetStream consumer on %q: %v", subject, err) 5324 return nil, nil, err 5325 } 5326 return cc, sub, nil 5327 } 5328 5329 // Queues the published retained messages for each subscription and signals 5330 // the writeLoop. 5331 func (c *client) mqttSendRetainedMsgsToNewSubs(subs []*subscription) { 5332 c.mu.Lock() 5333 for _, sub := range subs { 5334 if sub.mqtt != nil && sub.mqtt.prm != nil { 5335 for _, data := range sub.mqtt.prm { 5336 c.queueOutbound(data) 5337 } 5338 sub.mqtt.prm = nil 5339 } 5340 } 5341 c.flushSignal() 5342 c.mu.Unlock() 5343 } 5344 5345 func (c *client) mqttEnqueueSubAck(pi uint16, filters []*mqttFilter) { 5346 w := newMQTTWriter(7 + len(filters)) 5347 w.WriteByte(mqttPacketSubAck) 5348 // packet length is 2 (for packet identifier) and 1 byte per filter. 5349 w.WriteVarInt(2 + len(filters)) 5350 w.WriteUint16(pi) 5351 for _, f := range filters { 5352 w.WriteByte(f.qos) 5353 } 5354 c.mu.Lock() 5355 c.enqueueProto(w.Bytes()) 5356 c.mu.Unlock() 5357 } 5358 5359 ////////////////////////////////////////////////////////////////////////////// 5360 // 5361 // UNSUBSCRIBE related functions 5362 // 5363 ////////////////////////////////////////////////////////////////////////////// 5364 5365 func (c *client) mqttParseUnsubs(r *mqttReader, b byte, pl int) (uint16, []*mqttFilter, error) { 5366 return c.mqttParseSubsOrUnsubs(r, b, pl, false) 5367 } 5368 5369 // Process the UNSUBSCRIBE packet. 5370 // 5371 // Given the list of topics, this is going to unsubscribe the low level NATS subscriptions 5372 // and delete the JS durable consumers when applicable. 5373 // 5374 // Runs from the client's readLoop. 5375 // No lock held on entry. 5376 func (c *client) mqttProcessUnsubs(filters []*mqttFilter) error { 5377 // Those things are immutable, but since processing unsubs is not 5378 // really in the fast path, let's get them under the client lock. 5379 c.mu.Lock() 5380 asm := c.mqtt.asm 5381 sess := c.mqtt.sess 5382 c.mu.Unlock() 5383 5384 if err := asm.lockSession(sess, c); err != nil { 5385 return err 5386 } 5387 defer asm.unlockSession(sess) 5388 5389 removeJSCons := func(sid string) { 5390 cc, ok := sess.cons[sid] 5391 if ok { 5392 delete(sess.cons, sid) 5393 sess.deleteConsumer(cc) 5394 // Need lock here since these are accessed by callbacks 5395 sess.mu.Lock() 5396 if seqPis, ok := sess.cpending[cc.Durable]; ok { 5397 delete(sess.cpending, cc.Durable) 5398 for _, pi := range seqPis { 5399 delete(sess.pendingPublish, pi) 5400 } 5401 if len(sess.pendingPublish) == 0 { 5402 sess.last_pi = 0 5403 } 5404 } 5405 sess.mu.Unlock() 5406 } 5407 } 5408 for _, f := range filters { 5409 sid := f.filter 5410 // Remove JS Consumer if one exists for this sid 5411 removeJSCons(sid) 5412 if err := c.processUnsub([]byte(sid)); err != nil { 5413 c.Errorf("error unsubscribing from %q: %v", sid, err) 5414 } 5415 if mqttNeedSubForLevelUp(sid) { 5416 subject := sid[:len(sid)-2] 5417 sid = subject + mqttMultiLevelSidSuffix 5418 removeJSCons(sid) 5419 if err := c.processUnsub([]byte(sid)); err != nil { 5420 c.Errorf("error unsubscribing from %q: %v", subject, err) 5421 } 5422 } 5423 } 5424 return sess.update(filters, false) 5425 } 5426 5427 func (c *client) mqttEnqueueUnsubAck(pi uint16) { 5428 w := newMQTTWriter(4) 5429 w.WriteByte(mqttPacketUnsubAck) 5430 w.WriteVarInt(2) 5431 w.WriteUint16(pi) 5432 c.mu.Lock() 5433 c.enqueueProto(w.Bytes()) 5434 c.mu.Unlock() 5435 } 5436 5437 func mqttUnsubscribeTrace(pi uint16, filters []*mqttFilter) string { 5438 var sep string 5439 sb := strings.Builder{} 5440 sb.WriteString("[") 5441 for i, f := range filters { 5442 sb.WriteString(sep) 5443 sb.Write(f.ttopic) 5444 sb.WriteString(" (") 5445 sb.WriteString(f.filter) 5446 sb.WriteString(")") 5447 if i == 0 { 5448 sep = ", " 5449 } 5450 } 5451 sb.WriteString(fmt.Sprintf("] pi=%v", pi)) 5452 return sb.String() 5453 } 5454 5455 ////////////////////////////////////////////////////////////////////////////// 5456 // 5457 // PINGREQ/PINGRESP related functions 5458 // 5459 ////////////////////////////////////////////////////////////////////////////// 5460 5461 func (c *client) mqttEnqueuePingResp() { 5462 c.mu.Lock() 5463 c.enqueueProto(mqttPingResponse) 5464 c.mu.Unlock() 5465 } 5466 5467 ////////////////////////////////////////////////////////////////////////////// 5468 // 5469 // Trace functions 5470 // 5471 ////////////////////////////////////////////////////////////////////////////// 5472 5473 func errOrTrace(err error, trace string) []byte { 5474 if err != nil { 5475 return []byte(err.Error()) 5476 } 5477 return []byte(trace) 5478 } 5479 5480 ////////////////////////////////////////////////////////////////////////////// 5481 // 5482 // Subject/Topic conversion functions 5483 // 5484 ////////////////////////////////////////////////////////////////////////////// 5485 5486 // Converts an MQTT Topic Name to a NATS Subject (used by PUBLISH) 5487 // See mqttToNATSSubjectConversion() for details. 5488 func mqttTopicToNATSPubSubject(mt []byte) ([]byte, error) { 5489 return mqttToNATSSubjectConversion(mt, false) 5490 } 5491 5492 // Converts an MQTT Topic Filter to a NATS Subject (used by SUBSCRIBE) 5493 // See mqttToNATSSubjectConversion() for details. 5494 func mqttFilterToNATSSubject(filter []byte) ([]byte, error) { 5495 return mqttToNATSSubjectConversion(filter, true) 5496 } 5497 5498 // Converts an MQTT Topic Name or Filter to a NATS Subject. 5499 // In MQTT: 5500 // - a Topic Name does not have wildcard (PUBLISH uses only topic names). 5501 // - a Topic Filter can include wildcards (SUBSCRIBE uses those). 5502 // - '+' and '#' are wildcard characters (single and multiple levels respectively) 5503 // - '/' is the topic level separator. 5504 // 5505 // Conversion that occurs: 5506 // - '/' is replaced with '/.' if it is the first character in mt 5507 // - '/' is replaced with './' if the last or next character in mt is '/' 5508 // For instance, foo//bar would become foo./.bar 5509 // - '/' is replaced with '.' for all other conditions (foo/bar -> foo.bar) 5510 // - '.' is replaced with '//'. 5511 // - ' ' cause an error to be returned. 5512 // 5513 // If there is no need to convert anything (say "foo" remains "foo"), then 5514 // the no memory is allocated and the returned slice is the original `mt`. 5515 func mqttToNATSSubjectConversion(mt []byte, wcOk bool) ([]byte, error) { 5516 var cp bool 5517 var j int 5518 res := mt 5519 5520 makeCopy := func(i int) { 5521 cp = true 5522 res = make([]byte, 0, len(mt)+10) 5523 if i > 0 { 5524 res = append(res, mt[:i]...) 5525 } 5526 } 5527 5528 end := len(mt) - 1 5529 for i := 0; i < len(mt); i++ { 5530 switch mt[i] { 5531 case mqttTopicLevelSep: 5532 if i == 0 || res[j-1] == btsep { 5533 if !cp { 5534 makeCopy(0) 5535 } 5536 res = append(res, mqttTopicLevelSep, btsep) 5537 j++ 5538 } else if i == end || mt[i+1] == mqttTopicLevelSep { 5539 if !cp { 5540 makeCopy(i) 5541 } 5542 res = append(res, btsep, mqttTopicLevelSep) 5543 j++ 5544 } else { 5545 if !cp { 5546 makeCopy(i) 5547 } 5548 res = append(res, btsep) 5549 } 5550 case ' ': 5551 // As of now, we cannot support ' ' in the MQTT topic/filter. 5552 return nil, errMQTTUnsupportedCharacters 5553 case btsep: 5554 if !cp { 5555 makeCopy(i) 5556 } 5557 res = append(res, mqttTopicLevelSep, mqttTopicLevelSep) 5558 j++ 5559 case mqttSingleLevelWC, mqttMultiLevelWC: 5560 if !wcOk { 5561 // Spec [MQTT-3.3.2-2] and [MQTT-4.7.1-1] 5562 // The wildcard characters can be used in Topic Filters, but MUST NOT be used within a Topic Name 5563 return nil, fmt.Errorf("wildcards not allowed in publish's topic: %q", mt) 5564 } 5565 if !cp { 5566 makeCopy(i) 5567 } 5568 if mt[i] == mqttSingleLevelWC { 5569 res = append(res, pwc) 5570 } else { 5571 res = append(res, fwc) 5572 } 5573 default: 5574 if cp { 5575 res = append(res, mt[i]) 5576 } 5577 } 5578 j++ 5579 } 5580 if cp && res[j-1] == btsep { 5581 res = append(res, mqttTopicLevelSep) 5582 j++ 5583 } 5584 return res[:j], nil 5585 } 5586 5587 // Converts a NATS subject to MQTT topic. This is for publish 5588 // messages only, so there is no checking for wildcards. 5589 // Rules are reversed of mqttToNATSSubjectConversion. 5590 func natsSubjectStrToMQTTTopic(subject string) []byte { 5591 return natsSubjectToMQTTTopic(stringToBytes(subject)) 5592 } 5593 5594 func natsSubjectToMQTTTopic(subject []byte) []byte { 5595 topic := make([]byte, len(subject)) 5596 end := len(subject) - 1 5597 var j int 5598 for i := 0; i < len(subject); i++ { 5599 switch subject[i] { 5600 case mqttTopicLevelSep: 5601 if i < end { 5602 switch c := subject[i+1]; c { 5603 case btsep, mqttTopicLevelSep: 5604 if c == btsep { 5605 topic[j] = mqttTopicLevelSep 5606 } else { 5607 topic[j] = btsep 5608 } 5609 j++ 5610 i++ 5611 default: 5612 } 5613 } 5614 case btsep: 5615 topic[j] = mqttTopicLevelSep 5616 j++ 5617 default: 5618 topic[j] = subject[i] 5619 j++ 5620 } 5621 } 5622 return topic[:j] 5623 } 5624 5625 // Returns true if the subject has more than 1 token and ends with ".>" 5626 func mqttNeedSubForLevelUp(subject string) bool { 5627 if len(subject) < 3 { 5628 return false 5629 } 5630 end := len(subject) 5631 if subject[end-2] == '.' && subject[end-1] == fwc { 5632 return true 5633 } 5634 return false 5635 } 5636 5637 ////////////////////////////////////////////////////////////////////////////// 5638 // 5639 // MQTT Reader functions 5640 // 5641 ////////////////////////////////////////////////////////////////////////////// 5642 5643 func (r *mqttReader) reset(buf []byte) { 5644 if l := len(r.pbuf); l > 0 { 5645 tmp := make([]byte, l+len(buf)) 5646 copy(tmp, r.pbuf) 5647 copy(tmp[l:], buf) 5648 buf = tmp 5649 r.pbuf = nil 5650 } 5651 r.buf = buf 5652 r.pos = 0 5653 r.pstart = 0 5654 } 5655 5656 func (r *mqttReader) hasMore() bool { 5657 return r.pos != len(r.buf) 5658 } 5659 5660 func (r *mqttReader) readByte(field string) (byte, error) { 5661 if r.pos == len(r.buf) { 5662 return 0, fmt.Errorf("error reading %s: %v", field, io.EOF) 5663 } 5664 b := r.buf[r.pos] 5665 r.pos++ 5666 return b, nil 5667 } 5668 5669 func (r *mqttReader) readPacketLen() (int, bool, error) { 5670 return r.readPacketLenWithCheck(true) 5671 } 5672 5673 func (r *mqttReader) readPacketLenWithCheck(check bool) (int, bool, error) { 5674 m := 1 5675 v := 0 5676 for { 5677 var b byte 5678 if r.pos != len(r.buf) { 5679 b = r.buf[r.pos] 5680 r.pos++ 5681 } else { 5682 break 5683 } 5684 v += int(b&0x7f) * m 5685 if (b & 0x80) == 0 { 5686 if check && r.pos+v > len(r.buf) { 5687 break 5688 } 5689 return v, true, nil 5690 } 5691 m *= 0x80 5692 if m > 0x200000 { 5693 return 0, false, errMQTTMalformedVarInt 5694 } 5695 } 5696 r.pbuf = make([]byte, len(r.buf)-r.pstart) 5697 copy(r.pbuf, r.buf[r.pstart:]) 5698 return 0, false, nil 5699 } 5700 5701 func (r *mqttReader) readString(field string) (string, error) { 5702 var s string 5703 bs, err := r.readBytes(field, false) 5704 if err == nil { 5705 s = string(bs) 5706 } 5707 return s, err 5708 } 5709 5710 func (r *mqttReader) readBytes(field string, cp bool) ([]byte, error) { 5711 luint, err := r.readUint16(field) 5712 if err != nil { 5713 return nil, err 5714 } 5715 l := int(luint) 5716 if l == 0 { 5717 return nil, nil 5718 } 5719 start := r.pos 5720 if start+l > len(r.buf) { 5721 return nil, fmt.Errorf("error reading %s: %v", field, io.ErrUnexpectedEOF) 5722 } 5723 r.pos += l 5724 b := r.buf[start:r.pos] 5725 if cp { 5726 b = copyBytes(b) 5727 } 5728 return b, nil 5729 } 5730 5731 func (r *mqttReader) readUint16(field string) (uint16, error) { 5732 if len(r.buf)-r.pos < 2 { 5733 return 0, fmt.Errorf("error reading %s: %v", field, io.ErrUnexpectedEOF) 5734 } 5735 start := r.pos 5736 r.pos += 2 5737 return binary.BigEndian.Uint16(r.buf[start:r.pos]), nil 5738 } 5739 5740 ////////////////////////////////////////////////////////////////////////////// 5741 // 5742 // MQTT Writer functions 5743 // 5744 ////////////////////////////////////////////////////////////////////////////// 5745 5746 func (w *mqttWriter) WriteUint16(i uint16) { 5747 w.WriteByte(byte(i >> 8)) 5748 w.WriteByte(byte(i)) 5749 } 5750 5751 func (w *mqttWriter) WriteString(s string) { 5752 w.WriteBytes([]byte(s)) 5753 } 5754 5755 func (w *mqttWriter) WriteBytes(bs []byte) { 5756 w.WriteUint16(uint16(len(bs))) 5757 w.Write(bs) 5758 } 5759 5760 func (w *mqttWriter) WriteVarInt(value int) { 5761 for { 5762 b := byte(value & 0x7f) 5763 value >>= 7 5764 if value > 0 { 5765 b |= 0x80 5766 } 5767 w.WriteByte(b) 5768 if value == 0 { 5769 break 5770 } 5771 } 5772 } 5773 5774 func newMQTTWriter(cap int) *mqttWriter { 5775 w := &mqttWriter{} 5776 w.Grow(cap) 5777 return w 5778 }