github.com/nats-io/nats-server/v2@v2.11.0-preview.2/server/mqtt_test.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 //go:build !skip_mqtt_tests 15 // +build !skip_mqtt_tests 16 17 package server 18 19 import ( 20 "bufio" 21 "bytes" 22 "crypto/tls" 23 "encoding/json" 24 "errors" 25 "fmt" 26 "io" 27 "math/rand" 28 "net" 29 "os" 30 "reflect" 31 "strings" 32 "sync" 33 "testing" 34 "time" 35 36 "github.com/nats-io/jwt/v2" 37 "github.com/nats-io/nats.go" 38 "github.com/nats-io/nkeys" 39 "github.com/nats-io/nuid" 40 ) 41 42 var testMQTTTimeout = 10 * time.Second 43 44 var jsClusterTemplWithLeafAndMQTT = ` 45 listen: 127.0.0.1:-1 46 server_name: %s 47 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 48 49 {{leaf}} 50 51 cluster { 52 name: %s 53 listen: 127.0.0.1:%d 54 routes = [%s] 55 } 56 57 mqtt { 58 listen: 127.0.0.1:-1 59 } 60 61 # For access to system account. 62 accounts { $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } } 63 ` 64 65 type mqttWrapAsWs struct { 66 net.Conn 67 t testing.TB 68 br *bufio.Reader 69 tmp []byte 70 } 71 72 func (c *mqttWrapAsWs) Write(p []byte) (int, error) { 73 proto := testWSCreateClientMsg(wsBinaryMessage, 1, true, false, p) 74 return c.Conn.Write(proto) 75 } 76 77 func (c *mqttWrapAsWs) Read(p []byte) (int, error) { 78 for { 79 if n := len(c.tmp); n > 0 { 80 if len(p) < n { 81 n = len(p) 82 } 83 copy(p, c.tmp[:n]) 84 c.tmp = c.tmp[n:] 85 return n, nil 86 } 87 c.tmp = testWSReadFrame(c.t, c.br) 88 } 89 } 90 91 func testMQTTReadPacket(t testing.TB, r *mqttReader) (byte, int) { 92 t.Helper() 93 94 var b byte 95 var pl int 96 var err error 97 98 rd := r.reader 99 100 fill := func() []byte { 101 t.Helper() 102 var buf [512]byte 103 104 n, err := rd.Read(buf[:]) 105 if err != nil { 106 t.Fatalf("Error reading data: %v", err) 107 } 108 return copyBytes(buf[:n]) 109 } 110 111 rd.SetReadDeadline(time.Now().Add(testMQTTTimeout)) 112 for { 113 r.pstart = r.pos 114 if !r.hasMore() { 115 r.reset(fill()) 116 continue 117 } 118 b, err = r.readByte("packet type") 119 if err != nil { 120 t.Fatalf("Error reading packet: %v", err) 121 } 122 var complete bool 123 pl, complete, err = r.readPacketLen() 124 if err != nil { 125 t.Fatalf("Error reading packet: %v", err) 126 } 127 if !complete { 128 r.reset(fill()) 129 continue 130 } 131 break 132 } 133 rd.SetReadDeadline(time.Time{}) 134 return b, pl 135 } 136 137 func testMQTTReadPIPacket(expectedType byte, t testing.TB, r *mqttReader, expectedPI uint16) { 138 t.Helper() 139 b, _ := testMQTTReadPacket(t, r) 140 if pt := b & mqttPacketMask; pt != expectedType { 141 t.Fatalf("Expected packet %x, got %x", expectedType, pt) 142 } 143 rpi, err := r.readUint16("packet identifier") 144 if err != nil || rpi != expectedPI { 145 t.Fatalf("Expected PI %v got: %v, err=%v", expectedPI, rpi, err) 146 } 147 } 148 149 func TestMQTTReader(t *testing.T) { 150 r := &mqttReader{} 151 r.reset([]byte{0, 2, 'a', 'b'}) 152 bs, err := r.readBytes("", false) 153 if err != nil { 154 t.Fatal(err) 155 } 156 sbs := string(bs) 157 if sbs != "ab" { 158 t.Fatalf(`expected "ab", got %q`, sbs) 159 } 160 161 r.reset([]byte{0, 2, 'a', 'b'}) 162 bs, err = r.readBytes("", true) 163 if err != nil { 164 t.Fatal(err) 165 } 166 bs[0], bs[1] = 'c', 'd' 167 if bytes.Equal(bs, r.buf[2:]) { 168 t.Fatal("readBytes should have returned a copy") 169 } 170 171 r.reset([]byte{'a', 'b'}) 172 if b, err := r.readByte(""); err != nil || b != 'a' { 173 t.Fatalf("Error reading byte: b=%v err=%v", b, err) 174 } 175 if !r.hasMore() { 176 t.Fatal("expected to have more, did not") 177 } 178 if b, err := r.readByte(""); err != nil || b != 'b' { 179 t.Fatalf("Error reading byte: b=%v err=%v", b, err) 180 } 181 if r.hasMore() { 182 t.Fatal("expected to not have more") 183 } 184 if _, err := r.readByte("test"); err == nil || !strings.Contains(err.Error(), "error reading test") { 185 t.Fatalf("unexpected error: %v", err) 186 } 187 188 r.reset([]byte{0, 2, 'a', 'b'}) 189 if s, err := r.readString(""); err != nil || s != "ab" { 190 t.Fatalf("Error reading string: s=%q err=%v", s, err) 191 } 192 193 r.reset([]byte{10}) 194 if _, err := r.readUint16("uint16"); err == nil || !strings.Contains(err.Error(), "error reading uint16") { 195 t.Fatalf("unexpected error: %v", err) 196 } 197 198 r.reset([]byte{0x82, 0xff, 0x3}) 199 l, _, err := r.readPacketLenWithCheck(false) 200 if err != nil { 201 t.Fatal("error getting packet len") 202 } 203 if l != 0xff82 { 204 t.Fatalf("expected length 0xff82 got 0x%x", l) 205 } 206 r.reset([]byte{0xff, 0xff, 0xff, 0xff, 0xff}) 207 if _, _, err := r.readPacketLenWithCheck(false); err == nil || !strings.Contains(err.Error(), "malformed") { 208 t.Fatalf("unexpected error: %v", err) 209 } 210 211 r.reset([]byte{0, 2, 'a', 'b', mqttPacketPub, 0x82, 0xff, 0x3}) 212 r.readString("") 213 for i := 0; i < 2; i++ { 214 r.pstart = r.pos 215 b, err := r.readByte("") 216 if err != nil { 217 t.Fatalf("Error reading byte: %v", err) 218 } 219 if pt := b & mqttPacketMask; pt != mqttPacketPub { 220 t.Fatalf("Unexpected byte: %v", b) 221 } 222 pl, complete, err := r.readPacketLen() 223 if err != nil { 224 t.Fatalf("Unexpected error: %v", err) 225 } 226 if complete { 227 t.Fatal("Expected to be incomplete") 228 } 229 if pl != 0 { 230 t.Fatalf("Expected pl to be 0, got %v", pl) 231 } 232 if i > 0 { 233 break 234 } 235 if !bytes.Equal(r.pbuf, []byte{mqttPacketPub, 0x82, 0xff, 0x3}) { 236 t.Fatalf("Invalid recorded partial: %v", r.pbuf) 237 } 238 r.reset([]byte{'a', 'b', 'c'}) 239 if !bytes.Equal(r.buf, []byte{mqttPacketPub, 0x82, 0xff, 0x3, 'a', 'b', 'c'}) { 240 t.Fatalf("Invalid buffer: %v", r.buf) 241 } 242 if r.pbuf != nil { 243 t.Fatalf("Partial buffer should have been reset, got %v", r.pbuf) 244 } 245 if r.pos != 0 { 246 t.Fatalf("Pos should have been reset, got %v", r.pos) 247 } 248 if r.pstart != 0 { 249 t.Fatalf("Pstart should have been reset, got %v", r.pstart) 250 } 251 } 252 // On second pass, the pbuf should have been extended with 'abc' 253 if !bytes.Equal(r.pbuf, []byte{mqttPacketPub, 0x82, 0xff, 0x3, 'a', 'b', 'c'}) { 254 t.Fatalf("Invalid recorded partial: %v", r.pbuf) 255 } 256 } 257 258 func TestMQTTWriter(t *testing.T) { 259 w := newMQTTWriter(0) 260 w.WriteUint16(1234) 261 262 r := &mqttReader{} 263 r.reset(w.Bytes()) 264 if v, err := r.readUint16(""); err != nil || v != 1234 { 265 t.Fatalf("unexpected value: v=%v err=%v", v, err) 266 } 267 268 w.Reset() 269 w.WriteString("test") 270 r.reset(w.Bytes()) 271 if len(r.buf) != 6 { 272 t.Fatalf("Expected 2 bytes size before string, got %v", r.buf) 273 } 274 275 w.Reset() 276 w.WriteBytes([]byte("test")) 277 r.reset(w.Bytes()) 278 if len(r.buf) != 6 { 279 t.Fatalf("Expected 2 bytes size before bytes, got %v", r.buf) 280 } 281 282 ints := []int{ 283 0, 1, 127, 128, 16383, 16384, 2097151, 2097152, 268435455, 284 } 285 lens := []int{ 286 1, 1, 1, 2, 2, 3, 3, 4, 4, 287 } 288 289 tl := 0 290 w.Reset() 291 for i, v := range ints { 292 w.WriteVarInt(v) 293 tl += lens[i] 294 if tl != w.Len() { 295 t.Fatalf("expected len %d, got %d", tl, w.Len()) 296 } 297 } 298 299 r.reset(w.Bytes()) 300 for _, v := range ints { 301 x, _, _ := r.readPacketLenWithCheck(false) 302 if v != x { 303 t.Fatalf("expected %d, got %d", v, x) 304 } 305 } 306 } 307 308 func testMQTTDefaultOptions() *Options { 309 o := DefaultOptions() 310 o.ServerName = nuid.Next() 311 o.Cluster.Port = 0 312 o.Gateway.Name = "" 313 o.Gateway.Port = 0 314 o.LeafNode.Port = 0 315 o.Websocket.Port = 0 316 o.MQTT.Host = "127.0.0.1" 317 o.MQTT.Port = -1 318 o.JetStream = true 319 return o 320 } 321 322 func testMQTTRunServer(t testing.TB, o *Options) *Server { 323 t.Helper() 324 o.NoLog = false 325 if o.StoreDir == _EMPTY_ { 326 o.StoreDir = t.TempDir() 327 } 328 s, err := NewServer(o) 329 if err != nil { 330 t.Fatalf("Error creating server: %v", err) 331 } 332 l := &DummyLogger{} 333 s.SetLogger(l, true, true) 334 s.Start() 335 if err := s.readyForConnections(3 * time.Second); err != nil { 336 testMQTTShutdownServer(s) 337 t.Fatal(err) 338 } 339 return s 340 } 341 342 func testMQTTShutdownRestartedServer(s **Server) { 343 srv := *s 344 testMQTTShutdownServer(srv) 345 *s = nil 346 } 347 348 func testMQTTShutdownServer(s *Server) { 349 if c := s.JetStreamConfig(); c != nil { 350 dir := strings.TrimSuffix(c.StoreDir, JetStreamStoreDir) 351 defer os.RemoveAll(dir) 352 } 353 s.Shutdown() 354 } 355 356 func testMQTTDefaultTLSOptions(t *testing.T, verify bool) *Options { 357 t.Helper() 358 o := testMQTTDefaultOptions() 359 tc := &TLSConfigOpts{ 360 CertFile: "../test/configs/certs/server-cert.pem", 361 KeyFile: "../test/configs/certs/server-key.pem", 362 CaFile: "../test/configs/certs/ca.pem", 363 Verify: verify, 364 } 365 var err error 366 o.MQTT.TLSConfig, err = GenTLSConfig(tc) 367 o.MQTT.TLSTimeout = 2.0 368 if err != nil { 369 t.Fatalf("Error creating tls config: %v", err) 370 } 371 return o 372 } 373 374 func TestMQTTServerNameRequired(t *testing.T) { 375 conf := createConfFile(t, []byte(` 376 cluster { 377 port: -1 378 } 379 mqtt { 380 port: -1 381 } 382 `)) 383 o, err := ProcessConfigFile(conf) 384 if err != nil { 385 t.Fatalf("Error processing config file: %v", err) 386 } 387 if _, err := NewServer(o); err == nil || err.Error() != errMQTTServerNameMustBeSet.Error() { 388 t.Fatalf("Expected error about requiring server name to be set, got %v", err) 389 } 390 391 conf = createConfFile(t, []byte(` 392 mqtt { 393 port: -1 394 } 395 `)) 396 o, err = ProcessConfigFile(conf) 397 if err != nil { 398 t.Fatalf("Error processing config file: %v", err) 399 } 400 if _, err := NewServer(o); err == nil || err.Error() != errMQTTStandaloneNeedsJetStream.Error() { 401 t.Fatalf(`Expected errMQTTStandaloneNeedsJetStream ("next in line"), got %v`, err) 402 } 403 } 404 405 func TestMQTTStandaloneRequiresJetStream(t *testing.T) { 406 conf := createConfFile(t, []byte(` 407 server_name: mqtt 408 mqtt { 409 port: -1 410 tls { 411 cert_file: "./configs/certs/server.pem" 412 key_file: "./configs/certs/key.pem" 413 } 414 } 415 `)) 416 o, err := ProcessConfigFile(conf) 417 if err != nil { 418 t.Fatalf("Error processing config file: %v", err) 419 } 420 if _, err := NewServer(o); err == nil || err.Error() != errMQTTStandaloneNeedsJetStream.Error() { 421 t.Fatalf("Expected error about requiring JetStream in standalone mode, got %v", err) 422 } 423 } 424 425 func TestMQTTConfig(t *testing.T) { 426 conf := createConfFile(t, []byte(fmt.Sprintf(` 427 jetstream { 428 store_dir = %q 429 } 430 server_name: mqtt 431 mqtt { 432 port: -1 433 tls { 434 cert_file: "./configs/certs/server.pem" 435 key_file: "./configs/certs/key.pem" 436 } 437 } 438 `, t.TempDir()))) 439 s, o := RunServerWithConfig(conf) 440 defer testMQTTShutdownServer(s) 441 if o.MQTT.TLSConfig == nil { 442 t.Fatal("expected TLS config to be set") 443 } 444 } 445 446 func TestMQTTValidateOptions(t *testing.T) { 447 nmqtto := DefaultOptions() 448 mqtto := testMQTTDefaultOptions() 449 for _, test := range []struct { 450 name string 451 getOpts func() *Options 452 err error 453 }{ 454 {"mqtt disabled", func() *Options { return nmqtto.Clone() }, nil}, 455 {"mqtt username not allowed if users specified", func() *Options { 456 o := mqtto.Clone() 457 o.Users = []*User{{Username: "abc", Password: "pwd"}} 458 o.MQTT.Username = "b" 459 o.MQTT.Password = "pwd" 460 return o 461 }, errMQTTUserMixWithUsersNKeys}, 462 {"mqtt token not allowed if users specified", func() *Options { 463 o := mqtto.Clone() 464 o.Nkeys = []*NkeyUser{{Nkey: "abc"}} 465 o.MQTT.Token = "mytoken" 466 return o 467 }, errMQTTTokenMixWIthUsersNKeys}, 468 {"ack wait should be >=0", func() *Options { 469 o := mqtto.Clone() 470 o.MQTT.AckWait = -10 * time.Second 471 return o 472 }, errMQTTAckWaitMustBePositive}, 473 } { 474 t.Run(test.name, func(t *testing.T) { 475 err := validateMQTTOptions(test.getOpts()) 476 if test.err == nil && err != nil { 477 t.Fatalf("Unexpected error: %v", err) 478 } else if test.err != nil && (err == nil || err.Error() != test.err.Error()) { 479 t.Fatalf("Expected error to contain %q, got %v", test.err, err) 480 } 481 }) 482 } 483 } 484 485 func TestMQTTParseOptions(t *testing.T) { 486 for _, test := range []struct { 487 name string 488 content string 489 checkOpt func(*MQTTOpts) error 490 err string 491 }{ 492 // Negative tests 493 {"bad type", "mqtt: []", nil, "to be a map"}, 494 {"bad listen", "mqtt: { listen: [] }", nil, "port or host:port"}, 495 {"bad port", `mqtt: { port: "abc" }`, nil, "not int64"}, 496 {"bad host", `mqtt: { host: 123 }`, nil, "not string"}, 497 {"bad tls", `mqtt: { tls: 123 }`, nil, "not map[string]interface {}"}, 498 {"unknown field", `mqtt: { this_does_not_exist: 123 }`, nil, "unknown"}, 499 {"ack wait", `mqtt: {ack_wait: abc}`, nil, "invalid duration"}, 500 {"max ack pending", `mqtt: {max_ack_pending: abc}`, nil, "not int64"}, 501 {"max ack pending too high", `mqtt: {max_ack_pending: 12345678}`, nil, "invalid value"}, 502 // Positive tests 503 {"tls gen fails", ` 504 mqtt { 505 tls { 506 cert_file: "./configs/certs/server.pem" 507 } 508 }`, nil, "missing 'key_file'"}, 509 {"listen port only", `mqtt { listen: 1234 }`, func(o *MQTTOpts) error { 510 if o.Port != 1234 { 511 return fmt.Errorf("expected 1234, got %v", o.Port) 512 } 513 return nil 514 }, ""}, 515 {"listen host and port", `mqtt { listen: "localhost:1234" }`, func(o *MQTTOpts) error { 516 if o.Host != "localhost" || o.Port != 1234 { 517 return fmt.Errorf("expected localhost:1234, got %v:%v", o.Host, o.Port) 518 } 519 return nil 520 }, ""}, 521 {"host", `mqtt { host: "localhost" }`, func(o *MQTTOpts) error { 522 if o.Host != "localhost" { 523 return fmt.Errorf("expected localhost, got %v", o.Host) 524 } 525 return nil 526 }, ""}, 527 {"port", `mqtt { port: 1234 }`, func(o *MQTTOpts) error { 528 if o.Port != 1234 { 529 return fmt.Errorf("expected 1234, got %v", o.Port) 530 } 531 return nil 532 }, ""}, 533 {"tls config", 534 ` 535 mqtt { 536 tls { 537 cert_file: "./configs/certs/server.pem" 538 key_file: "./configs/certs/key.pem" 539 } 540 } 541 `, func(o *MQTTOpts) error { 542 if o.TLSConfig == nil { 543 return fmt.Errorf("TLSConfig should have been set") 544 } 545 return nil 546 }, ""}, 547 {"no auth user", 548 ` 549 mqtt { 550 no_auth_user: "noauthuser" 551 } 552 `, func(o *MQTTOpts) error { 553 if o.NoAuthUser != "noauthuser" { 554 return fmt.Errorf("Invalid NoAuthUser value: %q", o.NoAuthUser) 555 } 556 return nil 557 }, ""}, 558 {"auth block", 559 ` 560 mqtt { 561 authorization { 562 user: "mqttuser" 563 password: "pwd" 564 token: "token" 565 timeout: 2.0 566 } 567 } 568 `, func(o *MQTTOpts) error { 569 if o.Username != "mqttuser" || o.Password != "pwd" || o.Token != "token" || o.AuthTimeout != 2.0 { 570 return fmt.Errorf("Invalid auth block: %+v", o) 571 } 572 return nil 573 }, ""}, 574 {"auth timeout as int", 575 ` 576 mqtt { 577 authorization { 578 timeout: 2 579 } 580 } 581 `, func(o *MQTTOpts) error { 582 if o.AuthTimeout != 2.0 { 583 return fmt.Errorf("Invalid auth timeout: %v", o.AuthTimeout) 584 } 585 return nil 586 }, ""}, 587 {"ack wait", 588 ` 589 mqtt { 590 ack_wait: "10s" 591 } 592 `, func(o *MQTTOpts) error { 593 if o.AckWait != 10*time.Second { 594 return fmt.Errorf("Invalid ack wait: %v", o.AckWait) 595 } 596 return nil 597 }, ""}, 598 {"max ack pending", 599 ` 600 mqtt { 601 max_ack_pending: 123 602 } 603 `, func(o *MQTTOpts) error { 604 if o.MaxAckPending != 123 { 605 return fmt.Errorf("Invalid max ack pending: %v", o.MaxAckPending) 606 } 607 return nil 608 }, ""}, 609 {"reject_qos2_publish", 610 ` 611 mqtt { 612 reject_qos2_publish: true 613 } 614 `, func(o *MQTTOpts) error { 615 if !o.rejectQoS2Pub { 616 return fmt.Errorf("Invalid: expected rejectQoS2Pub to be set") 617 } 618 return nil 619 }, ""}, 620 {"downgrade_qos2_subscribe", 621 ` 622 mqtt { 623 downgrade_qos2_subscribe: true 624 } 625 `, func(o *MQTTOpts) error { 626 if !o.downgradeQoS2Sub { 627 return fmt.Errorf("Invalid: expected downgradeQoS2Sub to be set") 628 } 629 return nil 630 }, ""}, 631 } { 632 t.Run(test.name, func(t *testing.T) { 633 conf := createConfFile(t, []byte(test.content)) 634 o, err := ProcessConfigFile(conf) 635 if test.err != _EMPTY_ { 636 if err == nil || !strings.Contains(err.Error(), test.err) { 637 t.Fatalf("For content: %q, expected error about %q, got %v", test.content, test.err, err) 638 } 639 return 640 } else if err != nil { 641 t.Fatalf("Unexpected error for content %q: %v", test.content, err) 642 } 643 if err := test.checkOpt(&o.MQTT); err != nil { 644 t.Fatalf("Incorrect option for content %q: %v", test.content, err.Error()) 645 } 646 }) 647 } 648 } 649 650 func TestMQTTStart(t *testing.T) { 651 o := testMQTTDefaultOptions() 652 s := testMQTTRunServer(t, o) 653 defer testMQTTShutdownServer(s) 654 655 nc, err := net.Dial("tcp", fmt.Sprintf("%s:%d", o.MQTT.Host, o.MQTT.Port)) 656 if err != nil { 657 t.Fatalf("Unable to create tcp connection to mqtt port: %v", err) 658 } 659 nc.Close() 660 661 // Check failure to start due to port in use 662 o2 := testMQTTDefaultOptions() 663 o2.MQTT.Port = o.MQTT.Port 664 s2, err := NewServer(o2) 665 if err != nil { 666 t.Fatalf("Error creating server: %v", err) 667 } 668 defer s2.Shutdown() 669 l := &captureFatalLogger{fatalCh: make(chan string, 1)} 670 s2.SetLogger(l, false, false) 671 672 wg := sync.WaitGroup{} 673 wg.Add(1) 674 go func() { 675 s2.Start() 676 wg.Done() 677 }() 678 679 select { 680 case e := <-l.fatalCh: 681 if !strings.Contains(e, "Unable to listen for MQTT connections") { 682 t.Fatalf("Unexpected error: %q", e) 683 } 684 case <-time.After(time.Second): 685 t.Fatal("Should have gotten a fatal error") 686 } 687 } 688 689 func TestMQTTTLS(t *testing.T) { 690 o := testMQTTDefaultTLSOptions(t, false) 691 s := testMQTTRunServer(t, o) 692 defer testMQTTShutdownServer(s) 693 694 c, _, err := testMQTTConnectRetryWithError(t, &mqttConnInfo{tls: true}, o.MQTT.Host, o.MQTT.Port, 0) 695 if err != nil { 696 t.Fatal(err) 697 } 698 c.Close() 699 c = nil 700 testMQTTShutdownServer(s) 701 702 // Force client cert verification 703 o = testMQTTDefaultTLSOptions(t, true) 704 s = testMQTTRunServer(t, o) 705 defer testMQTTShutdownServer(s) 706 707 c, _, err = testMQTTConnectRetryWithError(t, &mqttConnInfo{tls: true}, o.MQTT.Host, o.MQTT.Port, 0) 708 if err == nil || c != nil { 709 if c != nil { 710 c.Close() 711 } 712 t.Fatal("Handshake expected to fail since client did not provide cert") 713 } 714 715 // Add client cert. 716 tc := &TLSConfigOpts{ 717 CertFile: "../test/configs/certs/client-cert.pem", 718 KeyFile: "../test/configs/certs/client-key.pem", 719 } 720 tlsc, err := GenTLSConfig(tc) 721 if err != nil { 722 t.Fatalf("Error generating tls config: %v", err) 723 } 724 tlsc.InsecureSkipVerify = true 725 c, _, err = testMQTTConnectRetryWithError(t, &mqttConnInfo{ 726 tls: true, 727 tlsc: tlsc, 728 }, o.MQTT.Host, o.MQTT.Port, 0) 729 if err != nil { 730 t.Fatal(err) 731 } 732 c.Close() 733 c = nil 734 testMQTTShutdownServer(s) 735 736 // Lower TLS timeout so low that we should fail 737 o.MQTT.TLSTimeout = 0.001 738 s = testMQTTRunServer(t, o) 739 defer testMQTTShutdownServer(s) 740 741 nc, err := net.Dial("tcp", fmt.Sprintf("%s:%d", o.MQTT.Host, o.MQTT.Port)) 742 if err != nil { 743 t.Fatalf("Unable to create tcp connection to mqtt port: %v", err) 744 } 745 defer nc.Close() 746 time.Sleep(100 * time.Millisecond) 747 tlsConn := tls.Client(nc, tlsc) 748 tlsConn.SetDeadline(time.Now().Add(time.Second)) 749 if err := tlsConn.Handshake(); err == nil { 750 t.Fatal("Expected failure, did not get one") 751 } 752 } 753 754 type mqttConnInfo struct { 755 clientID string 756 cleanSess bool 757 keepAlive uint16 758 will *mqttWill 759 user string 760 pass string 761 ws bool 762 tls bool 763 tlsc *tls.Config 764 } 765 766 func testMQTTGetClient(t testing.TB, s *Server, clientID string) *client { 767 t.Helper() 768 var mc *client 769 s.mu.Lock() 770 for _, c := range s.clients { 771 c.mu.Lock() 772 if c.isMqtt() && c.mqtt.cid == clientID { 773 mc = c 774 } 775 c.mu.Unlock() 776 if mc != nil { 777 break 778 } 779 } 780 s.mu.Unlock() 781 if mc == nil { 782 t.Fatalf("Did not find client %q", clientID) 783 } 784 return mc 785 } 786 787 func testMQTTRead(c net.Conn) ([]byte, error) { 788 var buf [512]byte 789 // Make sure that test does not block 790 c.SetReadDeadline(time.Now().Add(testMQTTTimeout)) 791 n, err := c.Read(buf[:]) 792 if err != nil { 793 return nil, err 794 } 795 c.SetReadDeadline(time.Time{}) 796 return copyBytes(buf[:n]), nil 797 } 798 799 func testMQTTWrite(c net.Conn, buf []byte) (int, error) { 800 c.SetWriteDeadline(time.Now().Add(testMQTTTimeout)) 801 n, err := c.Write(buf) 802 c.SetWriteDeadline(time.Time{}) 803 return n, err 804 } 805 806 func testMQTTConnect(t testing.TB, ci *mqttConnInfo, host string, port int) (net.Conn, *mqttReader) { 807 t.Helper() 808 return testMQTTConnectRetry(t, ci, host, port, 0) 809 } 810 811 func testMQTTConnectRetry(t testing.TB, ci *mqttConnInfo, host string, port int, retryCount int) (net.Conn, *mqttReader) { 812 t.Helper() 813 c, r, err := testMQTTConnectRetryWithError(t, ci, host, port, retryCount) 814 if err != nil { 815 t.Fatal(err) 816 } 817 return c, r 818 } 819 820 func testMQTTConnectRetryWithError(t testing.TB, ci *mqttConnInfo, host string, port int, retryCount int) (net.Conn, *mqttReader, error) { 821 retry := func(c net.Conn) bool { 822 if c != nil { 823 c.Close() 824 } 825 if retryCount == 0 { 826 return false 827 } 828 time.Sleep(time.Second) 829 retryCount-- 830 return true 831 } 832 833 addr := fmt.Sprintf("%s:%d", host, port) 834 var c net.Conn 835 var err error 836 RETRY: 837 if ci.ws { 838 var br *bufio.Reader 839 c, br, _, err = testNewWSClientWithError(t, testWSClientOptions{ 840 host: host, 841 port: port, 842 noTLS: !ci.tls, 843 path: mqttWSPath, 844 }) 845 if err == nil { 846 c = &mqttWrapAsWs{Conn: c, t: t, br: br} 847 } 848 } else { 849 c, err = net.Dial("tcp", addr) 850 if err == nil && ci.tls { 851 tc := ci.tlsc 852 if tc == nil { 853 tc = &tls.Config{InsecureSkipVerify: true} 854 } 855 c = tls.Client(c, tc) 856 c.SetDeadline(time.Now().Add(time.Second)) 857 err = c.(*tls.Conn).Handshake() 858 c.SetDeadline(time.Time{}) 859 } 860 } 861 if err != nil { 862 if retry(c) { 863 goto RETRY 864 } 865 return nil, nil, fmt.Errorf("Error creating mqtt connection: %v", err) 866 } 867 868 proto := mqttCreateConnectProto(ci) 869 if _, err := testMQTTWrite(c, proto); err != nil { 870 if retry(c) { 871 goto RETRY 872 } 873 return nil, nil, fmt.Errorf("Error writing connect: %v", err) 874 } 875 876 buf, err := testMQTTRead(c) 877 if err != nil { 878 if retry(c) { 879 goto RETRY 880 } 881 return nil, nil, fmt.Errorf("Error reading: %v", err) 882 } 883 mr := &mqttReader{reader: c} 884 mr.reset(buf) 885 886 return c, mr, nil 887 } 888 889 func mqttCreateConnectProto(ci *mqttConnInfo) []byte { 890 flags := byte(0) 891 if ci.cleanSess { 892 flags |= mqttConnFlagCleanSession 893 } 894 if ci.will != nil { 895 flags |= mqttConnFlagWillFlag | (ci.will.qos << 3) 896 if ci.will.retain { 897 flags |= mqttConnFlagWillRetain 898 } 899 } 900 if ci.user != _EMPTY_ { 901 flags |= mqttConnFlagUsernameFlag 902 } 903 if ci.pass != _EMPTY_ { 904 flags |= mqttConnFlagPasswordFlag 905 } 906 907 pkLen := 2 + len(mqttProtoName) + 908 1 + // proto level 909 1 + // flags 910 2 + // keepAlive 911 2 + len(ci.clientID) 912 913 if ci.will != nil { 914 pkLen += 2 + len(ci.will.topic) 915 pkLen += 2 + len(ci.will.message) 916 } 917 if ci.user != _EMPTY_ { 918 pkLen += 2 + len(ci.user) 919 } 920 if ci.pass != _EMPTY_ { 921 pkLen += 2 + len(ci.pass) 922 } 923 924 w := newMQTTWriter(0) 925 w.WriteByte(mqttPacketConnect) 926 w.WriteVarInt(pkLen) 927 w.WriteString(string(mqttProtoName)) 928 w.WriteByte(0x4) 929 w.WriteByte(flags) 930 w.WriteUint16(ci.keepAlive) 931 w.WriteString(ci.clientID) 932 if ci.will != nil { 933 w.WriteBytes(ci.will.topic) 934 w.WriteBytes(ci.will.message) 935 } 936 if ci.user != _EMPTY_ { 937 w.WriteString(ci.user) 938 } 939 if ci.pass != _EMPTY_ { 940 w.WriteBytes([]byte(ci.pass)) 941 } 942 return w.Bytes() 943 } 944 945 func testMQTTCheckConnAck(t testing.TB, r *mqttReader, rc byte, sessionPresent bool) { 946 t.Helper() 947 b, pl := testMQTTReadPacket(t, r) 948 pt := b & mqttPacketMask 949 if pt != mqttPacketConnectAck { 950 t.Fatalf("Expected ConnAck (%x), got %x", mqttPacketConnectAck, pt) 951 } 952 if pl != 2 { 953 t.Fatalf("ConnAck packet length should be 2, got %v", pl) 954 } 955 caf, err := r.readByte("connack flags") 956 if err != nil { 957 t.Fatalf("Error reading packet length: %v", err) 958 } 959 if caf&0xfe != 0 { 960 t.Fatalf("ConnAck flag bits 7-1 should all be 0, got %x", caf>>1) 961 } 962 if sp := caf == 1; sp != sessionPresent { 963 t.Fatalf("Expected session present flag=%v got %v", sessionPresent, sp) 964 } 965 carc, err := r.readByte("connack return code") 966 if err != nil { 967 t.Fatalf("Error reading returned code: %v", err) 968 } 969 if carc != rc { 970 t.Fatalf("Expected return code to be %v, got %v", rc, carc) 971 } 972 } 973 974 func testMQTTCheckPubAck(t testing.TB, r *mqttReader, packetType byte) { 975 t.Helper() 976 b, pl := testMQTTReadPacket(t, r) 977 pt := b & mqttPacketMask 978 if pt != packetType { 979 t.Fatalf("Expected %x, got %x", packetType, pt) 980 } 981 r.pos += pl 982 } 983 984 func TestMQTTRequiresJSEnabled(t *testing.T) { 985 o := testMQTTDefaultOptions() 986 acc := NewAccount("mqtt") 987 o.Accounts = []*Account{acc} 988 o.Users = []*User{{Username: "mqtt", Account: acc}} 989 s := testMQTTRunServer(t, o) 990 defer testMQTTShutdownServer(s) 991 992 addr := fmt.Sprintf("%s:%d", o.MQTT.Host, o.MQTT.Port) 993 c, err := net.Dial("tcp", addr) 994 if err != nil { 995 t.Fatalf("Error creating mqtt connection: %v", err) 996 } 997 defer c.Close() 998 999 proto := mqttCreateConnectProto(&mqttConnInfo{cleanSess: true, user: "mqtt"}) 1000 if _, err := testMQTTWrite(c, proto); err != nil { 1001 t.Fatalf("Error writing connect: %v", err) 1002 } 1003 if _, err := testMQTTRead(c); err == nil { 1004 t.Fatal("Expected failure, did not get one") 1005 } 1006 } 1007 1008 func testMQTTEnableJSForAccount(t *testing.T, s *Server, accName string) { 1009 t.Helper() 1010 acc, err := s.LookupAccount(accName) 1011 if err != nil { 1012 t.Fatalf("Error looking up account: %v", err) 1013 } 1014 limits := map[string]JetStreamAccountLimits{ 1015 _EMPTY_: { 1016 MaxConsumers: -1, 1017 MaxStreams: -1, 1018 MaxMemory: 1024 * 1024, 1019 MaxStore: 1024 * 1024, 1020 }, 1021 } 1022 if err := acc.EnableJetStream(limits); err != nil { 1023 t.Fatalf("Error enabling JS: %v", err) 1024 } 1025 } 1026 1027 func TestMQTTTLSVerifyAndMap(t *testing.T) { 1028 accName := "MyAccount" 1029 acc := NewAccount(accName) 1030 certUserName := "CN=example.com,OU=NATS.io" 1031 users := []*User{{Username: certUserName, Account: acc}} 1032 1033 for _, test := range []struct { 1034 name string 1035 filtering bool 1036 provideCert bool 1037 }{ 1038 {"no filtering, client provides cert", false, true}, 1039 {"no filtering, client does not provide cert", false, false}, 1040 {"filtering, client provides cert", true, true}, 1041 {"filtering, client does not provide cert", true, false}, 1042 } { 1043 t.Run(test.name, func(t *testing.T) { 1044 o := testMQTTDefaultOptions() 1045 o.Host = "localhost" 1046 o.Accounts = []*Account{acc} 1047 o.Users = users 1048 if test.filtering { 1049 o.Users[0].AllowedConnectionTypes = testCreateAllowedConnectionTypes([]string{jwt.ConnectionTypeStandard, jwt.ConnectionTypeMqtt}) 1050 } 1051 tc := &TLSConfigOpts{ 1052 CertFile: "../test/configs/certs/tlsauth/server.pem", 1053 KeyFile: "../test/configs/certs/tlsauth/server-key.pem", 1054 CaFile: "../test/configs/certs/tlsauth/ca.pem", 1055 Verify: true, 1056 } 1057 tlsc, err := GenTLSConfig(tc) 1058 if err != nil { 1059 t.Fatalf("Error creating tls config: %v", err) 1060 } 1061 o.MQTT.TLSConfig = tlsc 1062 o.MQTT.TLSTimeout = 2.0 1063 o.MQTT.TLSMap = true 1064 s := testMQTTRunServer(t, o) 1065 defer testMQTTShutdownServer(s) 1066 1067 testMQTTEnableJSForAccount(t, s, accName) 1068 1069 tlscc := &tls.Config{} 1070 if test.provideCert { 1071 tc := &TLSConfigOpts{ 1072 CertFile: "../test/configs/certs/tlsauth/client.pem", 1073 KeyFile: "../test/configs/certs/tlsauth/client-key.pem", 1074 } 1075 var err error 1076 tlscc, err = GenTLSConfig(tc) 1077 if err != nil { 1078 t.Fatalf("Error generating tls config: %v", err) 1079 } 1080 } 1081 tlscc.InsecureSkipVerify = true 1082 if test.provideCert { 1083 tlscc.MinVersion = tls.VersionTLS13 1084 } 1085 mc, r, err := testMQTTConnectRetryWithError(t, &mqttConnInfo{ 1086 cleanSess: true, 1087 tls: true, 1088 tlsc: tlscc, 1089 }, o.MQTT.Host, o.MQTT.Port, 0) 1090 if !test.provideCert { 1091 if err == nil { 1092 t.Fatal("Expected error, did not get one") 1093 } else if !strings.Contains(err.Error(), "bad certificate") && !strings.Contains(err.Error(), "certificate required") { 1094 t.Fatalf("Unexpected error: %v", err) 1095 } 1096 return 1097 } 1098 if err != nil { 1099 t.Fatalf("Error reading: %v", err) 1100 } 1101 defer mc.Close() 1102 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 1103 1104 var c *client 1105 s.mu.Lock() 1106 for _, sc := range s.clients { 1107 sc.mu.Lock() 1108 if sc.isMqtt() { 1109 c = sc 1110 } 1111 sc.mu.Unlock() 1112 if c != nil { 1113 break 1114 } 1115 } 1116 s.mu.Unlock() 1117 if c == nil { 1118 t.Fatal("Client not found") 1119 } 1120 1121 var uname string 1122 var accname string 1123 c.mu.Lock() 1124 uname = c.opts.Username 1125 if c.acc != nil { 1126 accname = c.acc.GetName() 1127 } 1128 c.mu.Unlock() 1129 if uname != certUserName { 1130 t.Fatalf("Expected username %q, got %q", certUserName, uname) 1131 } 1132 if accname != accName { 1133 t.Fatalf("Expected account %q, got %v", accName, accname) 1134 } 1135 }) 1136 } 1137 } 1138 1139 func TestMQTTBasicAuth(t *testing.T) { 1140 for _, test := range []struct { 1141 name string 1142 opts func() *Options 1143 user string 1144 pass string 1145 rc byte 1146 }{ 1147 { 1148 "top level auth, no override, wrong u/p", 1149 func() *Options { 1150 o := testMQTTDefaultOptions() 1151 o.Username = "normal" 1152 o.Password = "client" 1153 return o 1154 }, 1155 "mqtt", "client", mqttConnAckRCNotAuthorized, 1156 }, 1157 { 1158 "top level auth, no override, correct u/p", 1159 func() *Options { 1160 o := testMQTTDefaultOptions() 1161 o.Username = "normal" 1162 o.Password = "client" 1163 return o 1164 }, 1165 "normal", "client", mqttConnAckRCConnectionAccepted, 1166 }, 1167 { 1168 "no top level auth, mqtt auth, wrong u/p", 1169 func() *Options { 1170 o := testMQTTDefaultOptions() 1171 o.MQTT.Username = "mqtt" 1172 o.MQTT.Password = "client" 1173 return o 1174 }, 1175 "normal", "client", mqttConnAckRCNotAuthorized, 1176 }, 1177 { 1178 "no top level auth, mqtt auth, correct u/p", 1179 func() *Options { 1180 o := testMQTTDefaultOptions() 1181 o.MQTT.Username = "mqtt" 1182 o.MQTT.Password = "client" 1183 return o 1184 }, 1185 "mqtt", "client", mqttConnAckRCConnectionAccepted, 1186 }, 1187 { 1188 "top level auth, mqtt override, wrong u/p", 1189 func() *Options { 1190 o := testMQTTDefaultOptions() 1191 o.Username = "normal" 1192 o.Password = "client" 1193 o.MQTT.Username = "mqtt" 1194 o.MQTT.Password = "client" 1195 return o 1196 }, 1197 "normal", "client", mqttConnAckRCNotAuthorized, 1198 }, 1199 { 1200 "top level auth, mqtt override, correct u/p", 1201 func() *Options { 1202 o := testMQTTDefaultOptions() 1203 o.Username = "normal" 1204 o.Password = "client" 1205 o.MQTT.Username = "mqtt" 1206 o.MQTT.Password = "client" 1207 return o 1208 }, 1209 "mqtt", "client", mqttConnAckRCConnectionAccepted, 1210 }, 1211 } { 1212 t.Run(test.name, func(t *testing.T) { 1213 o := test.opts() 1214 s := testMQTTRunServer(t, o) 1215 defer testMQTTShutdownServer(s) 1216 1217 ci := &mqttConnInfo{ 1218 cleanSess: true, 1219 user: test.user, 1220 pass: test.pass, 1221 } 1222 mc, r := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 1223 defer mc.Close() 1224 testMQTTCheckConnAck(t, r, test.rc, false) 1225 }) 1226 } 1227 } 1228 1229 func TestMQTTAuthTimeout(t *testing.T) { 1230 for _, test := range []struct { 1231 name string 1232 at float64 1233 mat float64 1234 ok bool 1235 }{ 1236 {"use top-level auth timeout", 0.5, 0.0, true}, 1237 {"use mqtt auth timeout", 0.5, 0.05, false}, 1238 } { 1239 t.Run(test.name, func(t *testing.T) { 1240 o := testMQTTDefaultOptions() 1241 o.AuthTimeout = test.at 1242 o.MQTT.Username = "mqtt" 1243 o.MQTT.Password = "client" 1244 o.MQTT.AuthTimeout = test.mat 1245 s := testMQTTRunServer(t, o) 1246 defer testMQTTShutdownServer(s) 1247 1248 mc, err := net.Dial("tcp", fmt.Sprintf("%s:%d", o.MQTT.Host, o.MQTT.Port)) 1249 if err != nil { 1250 t.Fatalf("Error connecting: %v", err) 1251 } 1252 defer mc.Close() 1253 1254 time.Sleep(100 * time.Millisecond) 1255 1256 ci := &mqttConnInfo{ 1257 cleanSess: true, 1258 user: "mqtt", 1259 pass: "client", 1260 } 1261 proto := mqttCreateConnectProto(ci) 1262 if _, err := testMQTTWrite(mc, proto); err != nil { 1263 if test.ok { 1264 t.Fatalf("Error sending connect: %v", err) 1265 } 1266 // else it is ok since we got disconnected due to auth timeout 1267 return 1268 } 1269 buf, err := testMQTTRead(mc) 1270 if err != nil { 1271 if test.ok { 1272 t.Fatalf("Error reading: %v", err) 1273 } 1274 // else it is ok since we got disconnected due to auth timeout 1275 return 1276 } 1277 r := &mqttReader{reader: mc} 1278 r.reset(buf) 1279 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 1280 1281 time.Sleep(500 * time.Millisecond) 1282 testMQTTPublish(t, mc, r, 1, false, false, "foo", 1, []byte("msg")) 1283 }) 1284 } 1285 } 1286 1287 func TestMQTTTokenAuth(t *testing.T) { 1288 for _, test := range []struct { 1289 name string 1290 opts func() *Options 1291 token string 1292 rc byte 1293 }{ 1294 { 1295 "top level auth, no override, wrong token", 1296 func() *Options { 1297 o := testMQTTDefaultOptions() 1298 o.Authorization = "goodtoken" 1299 return o 1300 }, 1301 "badtoken", mqttConnAckRCNotAuthorized, 1302 }, 1303 { 1304 "top level auth, no override, correct token", 1305 func() *Options { 1306 o := testMQTTDefaultOptions() 1307 o.Authorization = "goodtoken" 1308 return o 1309 }, 1310 "goodtoken", mqttConnAckRCConnectionAccepted, 1311 }, 1312 { 1313 "no top level auth, mqtt auth, wrong token", 1314 func() *Options { 1315 o := testMQTTDefaultOptions() 1316 o.MQTT.Token = "goodtoken" 1317 return o 1318 }, 1319 "badtoken", mqttConnAckRCNotAuthorized, 1320 }, 1321 { 1322 "no top level auth, mqtt auth, correct token", 1323 func() *Options { 1324 o := testMQTTDefaultOptions() 1325 o.MQTT.Token = "goodtoken" 1326 return o 1327 }, 1328 "goodtoken", mqttConnAckRCConnectionAccepted, 1329 }, 1330 { 1331 "top level auth, mqtt override, wrong token", 1332 func() *Options { 1333 o := testMQTTDefaultOptions() 1334 o.Authorization = "clienttoken" 1335 o.MQTT.Token = "mqtttoken" 1336 return o 1337 }, 1338 "clienttoken", mqttConnAckRCNotAuthorized, 1339 }, 1340 { 1341 "top level auth, mqtt override, correct token", 1342 func() *Options { 1343 o := testMQTTDefaultOptions() 1344 o.Authorization = "clienttoken" 1345 o.MQTT.Token = "mqtttoken" 1346 return o 1347 }, 1348 "mqtttoken", mqttConnAckRCConnectionAccepted, 1349 }, 1350 } { 1351 t.Run(test.name, func(t *testing.T) { 1352 o := test.opts() 1353 s := testMQTTRunServer(t, o) 1354 defer testMQTTShutdownServer(s) 1355 1356 ci := &mqttConnInfo{ 1357 cleanSess: true, 1358 user: "ignore_use_token", 1359 pass: test.token, 1360 } 1361 mc, r := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 1362 defer mc.Close() 1363 testMQTTCheckConnAck(t, r, test.rc, false) 1364 }) 1365 } 1366 } 1367 1368 func TestMQTTJWTWithAllowedConnectionTypes(t *testing.T) { 1369 o := testMQTTDefaultOptions() 1370 // Create System Account 1371 syskp, _ := nkeys.CreateAccount() 1372 syspub, _ := syskp.PublicKey() 1373 sysAc := jwt.NewAccountClaims(syspub) 1374 sysjwt, err := sysAc.Encode(oKp) 1375 if err != nil { 1376 t.Fatalf("Error generating account JWT: %v", err) 1377 } 1378 // Create memory resolver and store system account 1379 mr := &MemAccResolver{} 1380 mr.Store(syspub, sysjwt) 1381 if err != nil { 1382 t.Fatalf("Error saving system account JWT to memory resolver: %v", err) 1383 } 1384 // Add system account and memory resolver to server options 1385 o.SystemAccount = syspub 1386 o.AccountResolver = mr 1387 setupAddTrusted(o) 1388 1389 s := testMQTTRunServer(t, o) 1390 defer testMQTTShutdownServer(s) 1391 1392 for _, test := range []struct { 1393 name string 1394 connectionTypes []string 1395 rc byte 1396 }{ 1397 {"not allowed", []string{jwt.ConnectionTypeStandard}, mqttConnAckRCNotAuthorized}, 1398 {"allowed", []string{jwt.ConnectionTypeStandard, strings.ToLower(jwt.ConnectionTypeMqtt)}, mqttConnAckRCConnectionAccepted}, 1399 {"allowed with unknown", []string{jwt.ConnectionTypeMqtt, "SomeNewType"}, mqttConnAckRCConnectionAccepted}, 1400 {"not allowed with unknown", []string{"SomeNewType"}, mqttConnAckRCNotAuthorized}, 1401 } { 1402 t.Run(test.name, func(t *testing.T) { 1403 1404 nuc := newJWTTestUserClaims() 1405 nuc.AllowedConnectionTypes = test.connectionTypes 1406 nuc.BearerToken = true 1407 1408 okp, _ := nkeys.FromSeed(oSeed) 1409 1410 akp, _ := nkeys.CreateAccount() 1411 apub, _ := akp.PublicKey() 1412 nac := jwt.NewAccountClaims(apub) 1413 // Enable Jetstream on account with lax limitations 1414 nac.Limits.JetStreamLimits.Consumer = -1 1415 nac.Limits.JetStreamLimits.Streams = -1 1416 nac.Limits.JetStreamLimits.MemoryStorage = 1024 * 1024 1417 nac.Limits.JetStreamLimits.DiskStorage = 1024 * 1024 1418 ajwt, err := nac.Encode(okp) 1419 if err != nil { 1420 t.Fatalf("Error generating account JWT: %v", err) 1421 } 1422 1423 nkp, _ := nkeys.CreateUser() 1424 pub, _ := nkp.PublicKey() 1425 nuc.Subject = pub 1426 jwt, err := nuc.Encode(akp) 1427 if err != nil { 1428 t.Fatalf("Error generating user JWT: %v", err) 1429 } 1430 1431 addAccountToMemResolver(s, apub, ajwt) 1432 1433 ci := &mqttConnInfo{ 1434 cleanSess: true, 1435 user: "ignore_use_token", 1436 pass: jwt, 1437 } 1438 1439 mc, r := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 1440 defer mc.Close() 1441 testMQTTCheckConnAck(t, r, test.rc, false) 1442 }) 1443 } 1444 } 1445 1446 func TestMQTTUsersAuth(t *testing.T) { 1447 users := []*User{{Username: "user", Password: "pwd"}} 1448 for _, test := range []struct { 1449 name string 1450 opts func() *Options 1451 user string 1452 pass string 1453 rc byte 1454 }{ 1455 { 1456 "no filtering, wrong user", 1457 func() *Options { 1458 o := testMQTTDefaultOptions() 1459 o.Users = users 1460 return o 1461 }, 1462 "wronguser", "pwd", mqttConnAckRCNotAuthorized, 1463 }, 1464 { 1465 "no filtering, correct user", 1466 func() *Options { 1467 o := testMQTTDefaultOptions() 1468 o.Users = users 1469 return o 1470 }, 1471 "user", "pwd", mqttConnAckRCConnectionAccepted, 1472 }, 1473 { 1474 "filtering, user not allowed", 1475 func() *Options { 1476 o := testMQTTDefaultOptions() 1477 o.Users = users 1478 // Only allowed for regular clients 1479 o.Users[0].AllowedConnectionTypes = testCreateAllowedConnectionTypes([]string{jwt.ConnectionTypeStandard}) 1480 return o 1481 }, 1482 "user", "pwd", mqttConnAckRCNotAuthorized, 1483 }, 1484 { 1485 "filtering, user allowed", 1486 func() *Options { 1487 o := testMQTTDefaultOptions() 1488 o.Users = users 1489 o.Users[0].AllowedConnectionTypes = testCreateAllowedConnectionTypes([]string{jwt.ConnectionTypeStandard, jwt.ConnectionTypeMqtt}) 1490 return o 1491 }, 1492 "user", "pwd", mqttConnAckRCConnectionAccepted, 1493 }, 1494 { 1495 "filtering, wrong password", 1496 func() *Options { 1497 o := testMQTTDefaultOptions() 1498 o.Users = users 1499 o.Users[0].AllowedConnectionTypes = testCreateAllowedConnectionTypes([]string{jwt.ConnectionTypeStandard, jwt.ConnectionTypeMqtt}) 1500 return o 1501 }, 1502 "user", "badpassword", mqttConnAckRCNotAuthorized, 1503 }, 1504 } { 1505 t.Run(test.name, func(t *testing.T) { 1506 o := test.opts() 1507 s := testMQTTRunServer(t, o) 1508 defer testMQTTShutdownServer(s) 1509 1510 ci := &mqttConnInfo{ 1511 cleanSess: true, 1512 user: test.user, 1513 pass: test.pass, 1514 } 1515 mc, r := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 1516 defer mc.Close() 1517 testMQTTCheckConnAck(t, r, test.rc, false) 1518 }) 1519 } 1520 } 1521 1522 func TestMQTTNoAuthUserValidation(t *testing.T) { 1523 o := testMQTTDefaultOptions() 1524 o.Users = []*User{{Username: "user", Password: "pwd"}} 1525 // Should fail because it is not part of o.Users. 1526 o.MQTT.NoAuthUser = "notfound" 1527 if _, err := NewServer(o); err == nil || !strings.Contains(err.Error(), "not present as user") { 1528 t.Fatalf("Expected error saying not present as user, got %v", err) 1529 } 1530 1531 // Set a valid no auth user for global options, but still should fail because 1532 // of o.MQTT.NoAuthUser 1533 o.NoAuthUser = "user" 1534 o.MQTT.NoAuthUser = "notfound" 1535 if _, err := NewServer(o); err == nil || !strings.Contains(err.Error(), "not present as user") { 1536 t.Fatalf("Expected error saying not present as user, got %v", err) 1537 } 1538 } 1539 1540 func TestMQTTNoAuthUser(t *testing.T) { 1541 for _, test := range []struct { 1542 name string 1543 override bool 1544 useAuth bool 1545 expectedUser string 1546 expectedAcc string 1547 }{ 1548 {"no override, no user provided", false, false, "noauth", "normal"}, 1549 {"no override, user povided", false, true, "user", "normal"}, 1550 {"override, no user provided", true, false, "mqttnoauth", "mqtt"}, 1551 {"override, user provided", true, true, "mqttuser", "mqtt"}, 1552 } { 1553 t.Run(test.name, func(t *testing.T) { 1554 o := testMQTTDefaultOptions() 1555 normalAcc := NewAccount("normal") 1556 mqttAcc := NewAccount("mqtt") 1557 o.Accounts = []*Account{normalAcc, mqttAcc} 1558 o.Users = []*User{ 1559 {Username: "noauth", Password: "pwd", Account: normalAcc}, 1560 {Username: "user", Password: "pwd", Account: normalAcc}, 1561 {Username: "mqttnoauth", Password: "pwd", Account: mqttAcc}, 1562 {Username: "mqttuser", Password: "pwd", Account: mqttAcc}, 1563 } 1564 o.NoAuthUser = "noauth" 1565 if test.override { 1566 o.MQTT.NoAuthUser = "mqttnoauth" 1567 } 1568 s := testMQTTRunServer(t, o) 1569 defer testMQTTShutdownServer(s) 1570 1571 testMQTTEnableJSForAccount(t, s, "normal") 1572 testMQTTEnableJSForAccount(t, s, "mqtt") 1573 1574 ci := &mqttConnInfo{clientID: "mqtt", cleanSess: true} 1575 if test.useAuth { 1576 ci.user = test.expectedUser 1577 ci.pass = "pwd" 1578 } 1579 mc, r := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 1580 defer mc.Close() 1581 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 1582 1583 c := testMQTTGetClient(t, s, "mqtt") 1584 c.mu.Lock() 1585 uname := c.opts.Username 1586 aname := c.acc.GetName() 1587 c.mu.Unlock() 1588 if uname != test.expectedUser { 1589 t.Fatalf("Expected selected user to be %q, got %q", test.expectedUser, uname) 1590 } 1591 if aname != test.expectedAcc { 1592 t.Fatalf("Expected selected account to be %q, got %q", test.expectedAcc, aname) 1593 } 1594 }) 1595 } 1596 } 1597 1598 func TestMQTTConnectNotFirstPacket(t *testing.T) { 1599 o := testMQTTDefaultOptions() 1600 s := testMQTTRunServer(t, o) 1601 defer testMQTTShutdownServer(s) 1602 1603 l := &captureErrorLogger{errCh: make(chan string, 10)} 1604 s.SetLogger(l, false, false) 1605 1606 c, err := net.Dial("tcp", fmt.Sprintf("%s:%d", o.MQTT.Host, o.MQTT.Port)) 1607 if err != nil { 1608 t.Fatalf("Error on dial: %v", err) 1609 } 1610 defer c.Close() 1611 1612 testMQTTSendPublishPacket(t, c, 0, false, false, "foo", 0, []byte("hello")) 1613 testMQTTExpectDisconnect(t, c) 1614 1615 select { 1616 case err := <-l.errCh: 1617 if !strings.Contains(err, "should be a CONNECT") { 1618 t.Fatalf("Expected error about first packet being a CONNECT, got %v", err) 1619 } 1620 case <-time.After(time.Second): 1621 t.Fatal("Did not log any error") 1622 } 1623 } 1624 1625 func TestMQTTSecondConnect(t *testing.T) { 1626 o := testMQTTDefaultOptions() 1627 s := testMQTTRunServer(t, o) 1628 defer testMQTTShutdownServer(s) 1629 1630 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 1631 defer mc.Close() 1632 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 1633 1634 proto := mqttCreateConnectProto(&mqttConnInfo{cleanSess: true}) 1635 if _, err := testMQTTWrite(mc, proto); err != nil { 1636 t.Fatalf("Error writing connect: %v", err) 1637 } 1638 testMQTTExpectDisconnect(t, mc) 1639 } 1640 1641 func TestMQTTParseConnect(t *testing.T) { 1642 for _, test := range []struct { 1643 name string 1644 proto []byte 1645 err string 1646 }{ 1647 {"packet in buffer error", []byte{0}, io.ErrUnexpectedEOF.Error()}, 1648 {"bad proto name", []byte{0, 4, 'B', 'A', 'D'}, "protocol name"}, 1649 {"invalid proto name", []byte{0, 3, 'B', 'A', 'D'}, "expected connect packet with protocol name"}, 1650 {"old proto not supported", []byte{0, 6, 'M', 'Q', 'I', 's', 'd', 'p'}, "older protocol"}, 1651 {"error on protocol level", []byte{0, 4, 'M', 'Q', 'T', 'T'}, "protocol level"}, 1652 {"unacceptable protocol version", []byte{0, 4, 'M', 'Q', 'T', 'T', 10}, "unacceptable protocol version"}, 1653 {"error on flags", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel}, "flags"}, 1654 {"reserved flag", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, 1}, errMQTTConnFlagReserved.Error()}, 1655 {"will qos without will flag", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, 1 << 3}, "if Will flag is set to 0, Will QoS must be 0 too"}, 1656 {"will retain without will flag", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, 1 << 5}, errMQTTWillAndRetainFlag.Error()}, 1657 {"will qos", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, 3<<3 | 1<<2}, "if Will flag is set to 1, Will QoS can be 0, 1 or 2"}, 1658 {"no user but password", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, mqttConnFlagPasswordFlag}, errMQTTPasswordFlagAndNoUser.Error()}, 1659 {"missing keep alive", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, 0}, "keep alive"}, 1660 {"missing client ID", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, 0, 0, 1}, "client ID"}, 1661 {"empty client ID", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, 0, 0, 1, 0, 0}, errMQTTCIDEmptyNeedsCleanFlag.Error()}, 1662 {"invalid utf8 client ID", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, 0, 0, 1, 0, 1, 241}, "invalid utf8 for client ID"}, 1663 {"missing will topic", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, mqttConnFlagWillFlag | mqttConnFlagCleanSession, 0, 0, 0, 0}, "Will topic"}, 1664 {"empty will topic", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, mqttConnFlagWillFlag | mqttConnFlagCleanSession, 0, 0, 0, 0, 0, 0}, errMQTTEmptyWillTopic.Error()}, 1665 {"invalid utf8 will topic", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, mqttConnFlagWillFlag | mqttConnFlagCleanSession, 0, 0, 0, 0, 0, 1, 241}, "invalid utf8 for Will topic"}, 1666 {"invalid wildcard will topic", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, mqttConnFlagWillFlag | mqttConnFlagCleanSession, 0, 0, 0, 0, 0, 1, '#'}, "wildcards not allowed"}, 1667 {"error on will message", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, mqttConnFlagWillFlag | mqttConnFlagCleanSession, 0, 0, 0, 0, 0, 1, 'a', 0, 3}, "Will message"}, 1668 {"error on username", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, mqttConnFlagUsernameFlag | mqttConnFlagCleanSession, 0, 0, 0, 0}, "user name"}, 1669 {"empty username", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, mqttConnFlagUsernameFlag | mqttConnFlagCleanSession, 0, 0, 0, 0, 0, 0}, errMQTTEmptyUsername.Error()}, 1670 {"invalid utf8 username", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, mqttConnFlagUsernameFlag | mqttConnFlagCleanSession, 0, 0, 0, 0, 0, 1, 241}, "invalid utf8 for user name"}, 1671 {"error on password", []byte{0, 4, 'M', 'Q', 'T', 'T', mqttProtoLevel, mqttConnFlagUsernameFlag | mqttConnFlagPasswordFlag | mqttConnFlagCleanSession, 0, 0, 0, 0, 0, 1, 'a'}, "password"}, 1672 } { 1673 t.Run(test.name, func(t *testing.T) { 1674 r := &mqttReader{} 1675 r.reset(test.proto) 1676 mqtt := &mqtt{r: r} 1677 c := &client{mqtt: mqtt} 1678 if _, _, err := c.mqttParseConnect(r, false); err == nil || !strings.Contains(err.Error(), test.err) { 1679 t.Fatalf("Expected error %q, got %v", test.err, err) 1680 } 1681 }) 1682 } 1683 } 1684 1685 func TestMQTTConnectFailsOnParse(t *testing.T) { 1686 o := testMQTTDefaultOptions() 1687 s := testMQTTRunServer(t, o) 1688 defer testMQTTShutdownServer(s) 1689 1690 addr := fmt.Sprintf("%s:%d", o.MQTT.Host, o.MQTT.Port) 1691 c, err := net.Dial("tcp", addr) 1692 if err != nil { 1693 t.Fatalf("Error creating mqtt connection: %v", err) 1694 } 1695 1696 pkLen := 2 + len(mqttProtoName) + 1697 1 + // proto level 1698 1 + // flags 1699 2 + // keepAlive 1700 2 + len("mqtt") 1701 1702 w := newMQTTWriter(0) 1703 w.WriteByte(mqttPacketConnect) 1704 w.WriteVarInt(pkLen) 1705 w.WriteString(string(mqttProtoName)) 1706 w.WriteByte(0x7) 1707 w.WriteByte(mqttConnFlagCleanSession) 1708 w.WriteUint16(0) 1709 w.WriteString("mqtt") 1710 c.Write(w.Bytes()) 1711 1712 buf, err := testMQTTRead(c) 1713 if err != nil { 1714 t.Fatalf("Error reading: %v", err) 1715 } 1716 r := &mqttReader{reader: c} 1717 r.reset(buf) 1718 testMQTTCheckConnAck(t, r, mqttConnAckRCUnacceptableProtocolVersion, false) 1719 } 1720 1721 func TestMQTTConnKeepAlive(t *testing.T) { 1722 o := testMQTTDefaultOptions() 1723 s := testMQTTRunServer(t, o) 1724 defer testMQTTShutdownServer(s) 1725 1726 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true, keepAlive: 1}, o.MQTT.Host, o.MQTT.Port) 1727 defer mc.Close() 1728 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 1729 1730 testMQTTPublish(t, mc, r, 0, false, false, "foo", 0, []byte("msg")) 1731 1732 time.Sleep(2 * time.Second) 1733 testMQTTExpectDisconnect(t, mc) 1734 } 1735 1736 func TestMQTTDontSetPinger(t *testing.T) { 1737 o := testMQTTDefaultOptions() 1738 o.PingInterval = 15 * time.Millisecond 1739 s := testMQTTRunServer(t, o) 1740 defer testMQTTShutdownServer(s) 1741 1742 mc, r := testMQTTConnect(t, &mqttConnInfo{clientID: "mqtt", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 1743 defer mc.Close() 1744 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 1745 1746 c := testMQTTGetClient(t, s, "mqtt") 1747 c.mu.Lock() 1748 timerSet := c.ping.tmr != nil 1749 c.mu.Unlock() 1750 if timerSet { 1751 t.Fatalf("Ping timer should not be set for MQTT clients") 1752 } 1753 1754 // Wait a bit and expect nothing (and connection should still be valid) 1755 testMQTTExpectNothing(t, r) 1756 testMQTTPublish(t, mc, r, 0, false, false, "foo", 0, []byte("msg")) 1757 } 1758 1759 func TestMQTTTopicAndSubjectConversion(t *testing.T) { 1760 for _, test := range []struct { 1761 name string 1762 mqttTopic string 1763 natsSubject string 1764 err string 1765 }{ 1766 {"/", "/", "/./", ""}, 1767 {"//", "//", "/././", ""}, 1768 {"///", "///", "/./././", ""}, 1769 {"////", "////", "/././././", ""}, 1770 {"foo", "foo", "foo", ""}, 1771 {"/foo", "/foo", "/.foo", ""}, 1772 {"//foo", "//foo", "/./.foo", ""}, 1773 {"///foo", "///foo", "/././.foo", ""}, 1774 {"///foo/", "///foo/", "/././.foo./", ""}, 1775 {"///foo//", "///foo//", "/././.foo././", ""}, 1776 {"///foo///", "///foo///", "/././.foo./././", ""}, 1777 {"//.foo.//", "//.foo.//", "/././/foo//././", ""}, 1778 {"foo/bar", "foo/bar", "foo.bar", ""}, 1779 {"/foo/bar", "/foo/bar", "/.foo.bar", ""}, 1780 {"/foo/bar/", "/foo/bar/", "/.foo.bar./", ""}, 1781 {"foo/bar/baz", "foo/bar/baz", "foo.bar.baz", ""}, 1782 {"/foo/bar/baz", "/foo/bar/baz", "/.foo.bar.baz", ""}, 1783 {"/foo/bar/baz/", "/foo/bar/baz/", "/.foo.bar.baz./", ""}, 1784 {"bar", "bar/", "bar./", ""}, 1785 {"bar//", "bar//", "bar././", ""}, 1786 {"bar///", "bar///", "bar./././", ""}, 1787 {"foo//bar", "foo//bar", "foo./.bar", ""}, 1788 {"foo///bar", "foo///bar", "foo././.bar", ""}, 1789 {"foo////bar", "foo////bar", "foo./././.bar", ""}, 1790 {".", ".", "//", ""}, 1791 {"..", "..", "////", ""}, 1792 {"...", "...", "//////", ""}, 1793 {"./", "./", "//./", ""}, 1794 {".//.", ".//.", "//././/", ""}, 1795 {"././.", "././.", "//.//.//", ""}, 1796 {"././/.", "././/.", "//.//././/", ""}, 1797 {".foo", ".foo", "//foo", ""}, 1798 {"foo.", "foo.", "foo//", ""}, 1799 {".foo.", ".foo.", "//foo//", ""}, 1800 {"foo../bar/", "foo../bar/", "foo////.bar./", ""}, 1801 {"foo../bar/.", "foo../bar/.", "foo////.bar.//", ""}, 1802 {"/foo/", "/foo/", "/.foo./", ""}, 1803 {"./foo/.", "./foo/.", "//.foo.//", ""}, 1804 {"foo.bar/baz", "foo.bar/baz", "foo//bar.baz", ""}, 1805 // These should produce errors 1806 {"foo/+", "foo/+", "", "wildcards not allowed in publish"}, 1807 {"foo/#", "foo/#", "", "wildcards not allowed in publish"}, 1808 {"foo bar", "foo bar", "", "not supported"}, 1809 } { 1810 t.Run(test.name, func(t *testing.T) { 1811 res, err := mqttTopicToNATSPubSubject([]byte(test.mqttTopic)) 1812 if test.err != _EMPTY_ { 1813 if err == nil || !strings.Contains(err.Error(), test.err) { 1814 t.Fatalf("Expected error %q, got %v", test.err, err) 1815 } 1816 return 1817 } 1818 toNATS := string(res) 1819 if toNATS != test.natsSubject { 1820 t.Fatalf("Expected subject %q got %q", test.natsSubject, toNATS) 1821 } 1822 1823 res = natsSubjectToMQTTTopic(res) 1824 backToMQTT := string(res) 1825 if backToMQTT != test.mqttTopic { 1826 t.Fatalf("Expected topic %q got %q (NATS conversion was %q)", test.mqttTopic, backToMQTT, toNATS) 1827 } 1828 }) 1829 } 1830 } 1831 1832 func TestMQTTFilterConversion(t *testing.T) { 1833 // Similar to TopicConversion test except that wildcards are OK here. 1834 // So testing only those. 1835 for _, test := range []struct { 1836 name string 1837 mqttTopic string 1838 natsSubject string 1839 }{ 1840 {"single level wildcard", "+", "*"}, 1841 {"single level wildcard", "/+", "/.*"}, 1842 {"single level wildcard", "+/", "*./"}, 1843 {"single level wildcard", "/+/", "/.*./"}, 1844 {"single level wildcard", "foo/+", "foo.*"}, 1845 {"single level wildcard", "foo/+/", "foo.*./"}, 1846 {"single level wildcard", "foo/+/bar", "foo.*.bar"}, 1847 {"single level wildcard", "foo/+/+", "foo.*.*"}, 1848 {"single level wildcard", "foo/+/+/", "foo.*.*./"}, 1849 {"single level wildcard", "foo/+/+/bar", "foo.*.*.bar"}, 1850 {"single level wildcard", "foo//+", "foo./.*"}, 1851 {"single level wildcard", "foo//+/", "foo./.*./"}, 1852 {"single level wildcard", "foo//+//", "foo./.*././"}, 1853 {"single level wildcard", "foo//+//bar", "foo./.*./.bar"}, 1854 {"single level wildcard", "foo///+///bar", "foo././.*././.bar"}, 1855 {"single level wildcard", "foo.bar///+///baz", "foo//bar././.*././.baz"}, 1856 1857 {"multi level wildcard", "#", ">"}, 1858 {"multi level wildcard", "/#", "/.>"}, 1859 {"multi level wildcard", "/foo/#", "/.foo.>"}, 1860 {"multi level wildcard", "foo/#", "foo.>"}, 1861 {"multi level wildcard", "foo//#", "foo./.>"}, 1862 {"multi level wildcard", "foo///#", "foo././.>"}, 1863 {"multi level wildcard", "foo/bar/#", "foo.bar.>"}, 1864 {"multi level wildcard", "foo/bar.baz/#", "foo.bar//baz.>"}, 1865 } { 1866 t.Run(test.name, func(t *testing.T) { 1867 res, err := mqttFilterToNATSSubject([]byte(test.mqttTopic)) 1868 if err != nil { 1869 t.Fatalf("Error: %v", err) 1870 } 1871 if string(res) != test.natsSubject { 1872 t.Fatalf("Expected subject %q got %q", test.natsSubject, res) 1873 } 1874 }) 1875 } 1876 } 1877 1878 func TestMQTTParseSub(t *testing.T) { 1879 for _, test := range []struct { 1880 name string 1881 proto []byte 1882 b byte 1883 pl int 1884 err string 1885 }{ 1886 {"reserved flag", nil, 3, 0, "wrong subscribe reserved flags"}, 1887 {"ensure packet loaded", []byte{1, 2}, mqttSubscribeFlags, 10, io.ErrUnexpectedEOF.Error()}, 1888 {"error reading packet id", []byte{1}, mqttSubscribeFlags, 1, "reading packet identifier"}, 1889 {"missing filters", []byte{0, 1}, mqttSubscribeFlags, 2, "subscribe protocol must contain at least 1 topic filter"}, 1890 {"error reading topic", []byte{0, 1, 0, 2, 'a'}, mqttSubscribeFlags, 5, "topic filter"}, 1891 {"empty topic", []byte{0, 1, 0, 0}, mqttSubscribeFlags, 4, errMQTTTopicFilterCannotBeEmpty.Error()}, 1892 {"invalid utf8 topic", []byte{0, 1, 0, 1, 241}, mqttSubscribeFlags, 5, "invalid utf8 for topic filter"}, 1893 {"missing qos", []byte{0, 1, 0, 1, 'a'}, mqttSubscribeFlags, 5, "QoS"}, 1894 {"invalid qos", []byte{0, 1, 0, 1, 'a', 3}, mqttSubscribeFlags, 6, "subscribe QoS value must be 0, 1 or 2"}, 1895 } { 1896 t.Run(test.name, func(t *testing.T) { 1897 r := &mqttReader{} 1898 r.reset(test.proto) 1899 mqtt := &mqtt{r: r} 1900 c := &client{mqtt: mqtt} 1901 if _, _, err := c.mqttParseSubsOrUnsubs(r, test.b, test.pl, true); err == nil || !strings.Contains(err.Error(), test.err) { 1902 t.Fatalf("Expected error %q, got %v", test.err, err) 1903 } 1904 }) 1905 } 1906 } 1907 1908 func testMQTTSub(t testing.TB, pi uint16, c net.Conn, r *mqttReader, filters []*mqttFilter, expected []byte) { 1909 t.Helper() 1910 w := newMQTTWriter(0) 1911 pkLen := 2 // for pi 1912 for i := 0; i < len(filters); i++ { 1913 f := filters[i] 1914 pkLen += 2 + len(f.filter) + 1 1915 } 1916 w.WriteByte(mqttPacketSub | mqttSubscribeFlags) 1917 w.WriteVarInt(pkLen) 1918 w.WriteUint16(pi) 1919 for i := 0; i < len(filters); i++ { 1920 f := filters[i] 1921 w.WriteBytes([]byte(f.filter)) 1922 w.WriteByte(f.qos) 1923 } 1924 if _, err := testMQTTWrite(c, w.Bytes()); err != nil { 1925 t.Fatalf("Error writing SUBSCRIBE protocol: %v", err) 1926 } 1927 b, pl := testMQTTReadPacket(t, r) 1928 if pt := b & mqttPacketMask; pt != mqttPacketSubAck { 1929 t.Fatalf("Expected SUBACK packet %x, got %x", mqttPacketSubAck, pt) 1930 } 1931 rpi, err := r.readUint16("packet identifier") 1932 if err != nil || rpi != pi { 1933 t.Fatalf("Error with packet identifier expected=%v got: %v err=%v", pi, rpi, err) 1934 } 1935 for i, rem := 0, pl-2; rem > 0; rem-- { 1936 qos, err := r.readByte("filter qos") 1937 if err != nil { 1938 t.Fatal(err) 1939 } 1940 if expected != nil && qos != expected[i] { 1941 t.Fatalf("For topic filter %q expected qos of %v, got %v", 1942 filters[i].filter, expected[i], qos) 1943 } 1944 i++ 1945 } 1946 } 1947 1948 func TestMQTTSubAck(t *testing.T) { 1949 o := testMQTTDefaultOptions() 1950 s := testMQTTRunServer(t, o) 1951 defer testMQTTShutdownServer(s) 1952 1953 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 1954 defer mc.Close() 1955 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 1956 1957 subs := []*mqttFilter{ 1958 {filter: "foo", qos: 0}, 1959 {filter: "bar", qos: 1}, 1960 {filter: "baz", qos: 2}, 1961 {filter: "foo/#/bar", qos: 0}, // Invalid sub, so we should receive a result of mqttSubAckFailure 1962 } 1963 expected := []byte{ 1964 0, 1965 1, 1966 2, 1967 mqttSubAckFailure, 1968 } 1969 testMQTTSub(t, 1, mc, r, subs, expected) 1970 } 1971 1972 func TestMQTTQoS2SubDowngrade(t *testing.T) { 1973 o := testMQTTDefaultOptions() 1974 o.MQTT.downgradeQoS2Sub = true 1975 s := testMQTTRunServer(t, o) 1976 defer testMQTTShutdownServer(s) 1977 1978 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 1979 defer mc.Close() 1980 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 1981 1982 subs := []*mqttFilter{ 1983 {filter: "bar", qos: 1}, 1984 {filter: "baz", qos: 2}, 1985 } 1986 expected := []byte{ 1987 1, 1988 1, 1989 } 1990 testMQTTSub(t, 1, mc, r, subs, expected) 1991 } 1992 1993 func testMQTTFlush(t testing.TB, c net.Conn, bw *bufio.Writer, r *mqttReader) { 1994 t.Helper() 1995 w := newMQTTWriter(0) 1996 w.WriteByte(mqttPacketPing) 1997 w.WriteByte(0) 1998 if bw != nil { 1999 bw.Write(w.Bytes()) 2000 bw.Flush() 2001 } else { 2002 c.Write(w.Bytes()) 2003 } 2004 ab, l := testMQTTReadPacket(t, r) 2005 if pt := ab & mqttPacketMask; pt != mqttPacketPingResp { 2006 t.Fatalf("Expected ping response got %x", pt) 2007 } 2008 if l != 0 { 2009 t.Fatalf("Expected PINGRESP length to be 0, got %v", l) 2010 } 2011 } 2012 2013 func testMQTTExpectNothing(t testing.TB, r *mqttReader) { 2014 t.Helper() 2015 var buf [128]byte 2016 r.reader.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) 2017 if n, err := r.reader.Read(buf[:]); err == nil { 2018 t.Fatalf("Expected nothing, got %v", buf[:n]) 2019 } 2020 r.reader.SetReadDeadline(time.Time{}) 2021 } 2022 2023 func testMQTTCheckPubMsg(t testing.TB, c net.Conn, r *mqttReader, topic string, expectedFlags byte, payload []byte) uint16 { 2024 t.Helper() 2025 pi := testMQTTCheckPubMsgNoAck(t, c, r, topic, expectedFlags, payload) 2026 if pi == 0 { 2027 return 0 2028 } 2029 qos := mqttGetQoS(expectedFlags) 2030 switch qos { 2031 case 1: 2032 testMQTTSendPIPacket(mqttPacketPubAck, t, c, pi) 2033 case 2: 2034 testMQTTSendPIPacket(mqttPacketPubRec, t, c, pi) 2035 } 2036 return pi 2037 } 2038 2039 func testMQTTCheckPubMsgNoAck(t testing.TB, c net.Conn, r *mqttReader, topic string, expectedFlags byte, payload []byte) uint16 { 2040 t.Helper() 2041 pflags, pi := testMQTTGetPubMsg(t, c, r, topic, payload) 2042 if pflags != expectedFlags { 2043 t.Fatalf("Expected flags to be %x, got %x", expectedFlags, pflags) 2044 } 2045 return pi 2046 } 2047 2048 func testMQTTGetPubMsg(t testing.TB, c net.Conn, r *mqttReader, topic string, payload []byte) (byte, uint16) { 2049 t.Helper() 2050 flags, pi, _, _ := testMQTTGetPubMsgEx(t, c, r, topic, payload) 2051 return flags, pi 2052 } 2053 2054 func testMQTTGetPubMsgEx(t testing.TB, _ net.Conn, r *mqttReader, topic string, payload []byte) (byte, uint16, string, []byte) { 2055 t.Helper() 2056 b, pl := testMQTTReadPacket(t, r) 2057 if pt := b & mqttPacketMask; pt != mqttPacketPub { 2058 t.Fatalf("Expected PUBLISH packet %x, got %x", mqttPacketPub, pt) 2059 } 2060 return testMQTTGetPubMsgExEx(t, nil, r, b, pl, topic, payload) 2061 } 2062 2063 func testMQTTGetPubMsgExEx(t testing.TB, _ net.Conn, r *mqttReader, b byte, pl int, topic string, payload []byte) (byte, uint16, string, []byte) { 2064 t.Helper() 2065 pflags := b & mqttPacketFlagMask 2066 qos := (pflags & mqttPubFlagQoS) >> 1 2067 start := r.pos 2068 ptopic, err := r.readString("topic name") 2069 if err != nil { 2070 t.Fatal(err) 2071 } 2072 if topic != _EMPTY_ && ptopic != topic { 2073 t.Fatalf("Expected topic %q, got %q", topic, ptopic) 2074 } 2075 var pi uint16 2076 if qos > 0 { 2077 pi, err = r.readUint16("packet identifier") 2078 if err != nil { 2079 t.Fatal(err) 2080 } 2081 } 2082 msgLen := pl - (r.pos - start) 2083 if r.pos+msgLen > len(r.buf) { 2084 t.Fatalf("computed message length goes beyond buffer: ml=%v pos=%v lenBuf=%v", 2085 msgLen, r.pos, len(r.buf)) 2086 } 2087 ppayload := r.buf[r.pos : r.pos+msgLen] 2088 if payload != nil && !bytes.Equal(payload, ppayload) { 2089 t.Fatalf("Expected payload %q, got %q", payload, ppayload) 2090 } 2091 r.pos += msgLen 2092 return pflags, pi, ptopic, ppayload 2093 } 2094 2095 func testMQTTReadPubPacket(t testing.TB, r *mqttReader) (flags byte, pi uint16, topic string, payload []byte) { 2096 t.Helper() 2097 b, pl := testMQTTReadPacket(t, r) 2098 if pt := b & mqttPacketMask; pt != mqttPacketPub { 2099 t.Fatalf("Expected PUBLISH packet %x, got %x", mqttPacketPub, pt) 2100 } 2101 flags = b & mqttPacketFlagMask 2102 start := r.pos 2103 topic, err := r.readString("topic name") 2104 if err != nil { 2105 t.Fatal(err) 2106 } 2107 qos := (flags & mqttPubFlagQoS) >> 1 2108 if qos > 0 { 2109 pi, err = r.readUint16("packet identifier") 2110 if err != nil { 2111 t.Fatal(err) 2112 } 2113 } 2114 msgLen := pl - (r.pos - start) 2115 if r.pos+msgLen > len(r.buf) { 2116 t.Fatalf("computed message length goes beyond buffer: ml=%v pos=%v lenBuf=%v", 2117 msgLen, r.pos, len(r.buf)) 2118 } 2119 payload = r.buf[r.pos : r.pos+msgLen] 2120 r.pos += msgLen 2121 return flags, pi, topic, payload 2122 } 2123 2124 func testMQTTSendPIPacket(packetType byte, t testing.TB, c net.Conn, pi uint16) { 2125 t.Helper() 2126 w := newMQTTWriter(0) 2127 w.WriteByte(packetType) 2128 w.WriteVarInt(2) 2129 w.WriteUint16(pi) 2130 if _, err := testMQTTWrite(c, w.Bytes()); err != nil { 2131 t.Fatalf("Error writing packet type %v: %v", packetType, err) 2132 } 2133 } 2134 2135 func testMQTTWritePublishPacket(t testing.TB, w *mqttWriter, qos byte, dup, retain bool, topic string, pi uint16, payload []byte) { 2136 t.Helper() 2137 w.WritePublishHeader(pi, qos, dup, retain, []byte(topic), len(payload)) 2138 if _, err := w.Write(payload); err != nil { 2139 t.Fatalf("Error writing PUBLISH proto: %v", err) 2140 } 2141 } 2142 2143 func testMQTTSendPublishPacket(t testing.TB, c net.Conn, qos byte, dup, retain bool, topic string, pi uint16, payload []byte) { 2144 t.Helper() 2145 c.SetWriteDeadline(time.Now().Add(testMQTTTimeout)) 2146 _, header := mqttMakePublishHeader(pi, qos, dup, retain, []byte(topic), len(payload)) 2147 if _, err := c.Write(header); err != nil { 2148 t.Fatalf("Error writing PUBLISH header: %v", err) 2149 } 2150 if _, err := c.Write(payload); err != nil { 2151 t.Fatalf("Error writing PUBLISH payload: %v", err) 2152 } 2153 c.SetWriteDeadline(time.Time{}) 2154 } 2155 2156 func testMQTTPublish(t testing.TB, c net.Conn, r *mqttReader, qos byte, dup, retain bool, topic string, pi uint16, payload []byte) { 2157 t.Helper() 2158 testMQTTSendPublishPacket(t, c, qos, dup, retain, topic, pi, payload) 2159 switch qos { 2160 case 1: 2161 b, _ := testMQTTReadPacket(t, r) 2162 if pt := b & mqttPacketMask; pt != mqttPacketPubAck { 2163 t.Fatalf("Expected PUBACK packet %x, got %x", mqttPacketPubAck, pt) 2164 } 2165 rpi, err := r.readUint16("packet identifier") 2166 if err != nil || rpi != pi { 2167 t.Fatalf("Error with packet identifier expected=%v got: %v err=%v", pi, rpi, err) 2168 } 2169 2170 case 2: 2171 b, _ := testMQTTReadPacket(t, r) 2172 if pt := b & mqttPacketMask; pt != mqttPacketPubRec { 2173 t.Fatalf("Expected PUBREC packet %x, got %x", mqttPacketPubRec, pt) 2174 } 2175 rpi, err := r.readUint16("packet identifier") 2176 if err != nil || rpi != pi { 2177 t.Fatalf("Error with packet identifier expected=%v got: %v err=%v", pi, rpi, err) 2178 } 2179 2180 testMQTTSendPIPacket(mqttPacketPubRel, t, c, pi) 2181 2182 b, _ = testMQTTReadPacket(t, r) 2183 if pt := b & mqttPacketMask; pt != mqttPacketPubComp { 2184 t.Fatalf("Expected PUBCOMP packet %x, got %x", mqttPacketPubComp, pt) 2185 } 2186 rpi, err = r.readUint16("packet identifier") 2187 if err != nil || rpi != pi { 2188 t.Fatalf("Error with packet identifier expected=%v got: %v err=%v", pi, rpi, err) 2189 } 2190 2191 testMQTTFlush(t, c, nil, r) 2192 } 2193 } 2194 2195 func TestMQTTParsePub(t *testing.T) { 2196 for _, test := range []struct { 2197 name string 2198 flags byte 2199 proto []byte 2200 pl int 2201 err string 2202 }{ 2203 {"qos not supported", (3 << 1), nil, 0, "QoS=3 is invalid in MQTT"}, 2204 {"packet in buffer error", 0, nil, 10, io.ErrUnexpectedEOF.Error()}, 2205 {"error on topic", 0, []byte{0, 3, 'f', 'o'}, 4, "topic"}, 2206 {"empty topic", 0, []byte{0, 0}, 2, errMQTTTopicIsEmpty.Error()}, 2207 {"wildcards topic", 0, []byte{0, 1, '#'}, 3, "wildcards not allowed"}, 2208 {"error on packet identifier", mqttPubQos1, []byte{0, 3, 'f', 'o', 'o'}, 5, "packet identifier"}, 2209 {"invalid packet identifier", mqttPubQos1, []byte{0, 3, 'f', 'o', 'o', 0, 0}, 7, errMQTTPacketIdentifierIsZero.Error()}, 2210 } { 2211 t.Run(test.name, func(t *testing.T) { 2212 r := &mqttReader{} 2213 r.reset(test.proto) 2214 mqtt := &mqtt{r: r} 2215 c := &client{mqtt: mqtt} 2216 pp := &mqttPublish{flags: test.flags} 2217 if err := c.mqttParsePub(r, test.pl, pp, false); err == nil || !strings.Contains(err.Error(), test.err) { 2218 t.Fatalf("Expected error %q, got %v", test.err, err) 2219 } 2220 }) 2221 } 2222 } 2223 2224 func TestMQTTParsePIMsg(t *testing.T) { 2225 for _, test := range []struct { 2226 name string 2227 proto []byte 2228 err string 2229 }{ 2230 {"packet in buffer error", nil, io.ErrUnexpectedEOF.Error()}, 2231 {"error reading packet identifier", []byte{0}, "packet identifier"}, 2232 {"invalid packet identifier", []byte{0, 0}, errMQTTPacketIdentifierIsZero.Error()}, 2233 } { 2234 t.Run(test.name, func(t *testing.T) { 2235 r := &mqttReader{} 2236 r.reset(test.proto) 2237 if _, err := mqttParsePIPacket(r); err == nil || !strings.Contains(err.Error(), test.err) { 2238 t.Fatalf("Expected error %q, got %v", test.err, err) 2239 } 2240 }) 2241 } 2242 } 2243 2244 func TestMQTTPublish(t *testing.T) { 2245 o := testMQTTDefaultOptions() 2246 s := testMQTTRunServer(t, o) 2247 defer testMQTTShutdownServer(s) 2248 2249 nc := natsConnect(t, s.ClientURL()) 2250 defer nc.Close() 2251 2252 mcp, mpr := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2253 defer mcp.Close() 2254 testMQTTCheckConnAck(t, mpr, mqttConnAckRCConnectionAccepted, false) 2255 2256 testMQTTPublish(t, mcp, mpr, 0, false, false, "foo", 0, []byte("msg")) 2257 testMQTTPublish(t, mcp, mpr, 1, false, false, "foo", 1, []byte("msg")) 2258 testMQTTPublish(t, mcp, mpr, 2, false, false, "foo", 2, []byte("msg")) 2259 } 2260 2261 func TestMQTTQoS2PubReject(t *testing.T) { 2262 o := testMQTTDefaultOptions() 2263 o.MQTT.rejectQoS2Pub = true 2264 s := testMQTTRunServer(t, o) 2265 defer testMQTTShutdownServer(s) 2266 2267 nc := natsConnect(t, s.ClientURL()) 2268 defer nc.Close() 2269 2270 mcp, mpr := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2271 defer mcp.Close() 2272 testMQTTCheckConnAck(t, mpr, mqttConnAckRCConnectionAccepted, false) 2273 2274 testMQTTPublish(t, mcp, mpr, 1, false, false, "foo", 1, []byte("msg")) 2275 2276 testMQTTSendPublishPacket(t, mcp, 2, false, false, "foo", 2, []byte("msg")) 2277 testMQTTExpectDisconnect(t, mcp) 2278 } 2279 2280 func TestMQTTSub(t *testing.T) { 2281 o := testMQTTDefaultOptions() 2282 s := testMQTTRunServer(t, o) 2283 defer testMQTTShutdownServer(s) 2284 2285 nc := natsConnect(t, s.ClientURL()) 2286 defer nc.Close() 2287 2288 mcp, mpr := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2289 defer mcp.Close() 2290 testMQTTCheckConnAck(t, mpr, mqttConnAckRCConnectionAccepted, false) 2291 2292 for _, test := range []struct { 2293 name string 2294 mqttSubTopic string 2295 natsPubSubject string 2296 mqttPubTopic string 2297 ok bool 2298 }{ 2299 {"1 level match", "foo", "foo", "foo", true}, 2300 {"1 level no match", "foo", "bar", "bar", false}, 2301 {"2 levels match", "foo/bar", "foo.bar", "foo/bar", true}, 2302 {"2 levels no match", "foo/bar", "foo.baz", "foo/baz", false}, 2303 {"3 levels match", "/foo/bar", "/.foo.bar", "/foo/bar", true}, 2304 {"3 levels no match", "/foo/bar", "/.foo.baz", "/foo/baz", false}, 2305 2306 {"single level wc", "foo/+", "foo.bar.baz", "foo/bar/baz", false}, 2307 {"single level wc", "foo/+", "foo.bar./", "foo/bar/", false}, 2308 {"single level wc", "foo/+", "foo.bar", "foo/bar", true}, 2309 {"single level wc", "foo/+", "foo./", "foo/", true}, 2310 {"single level wc", "foo/+", "foo", "foo", false}, 2311 {"single level wc", "foo/+", "/.foo", "/foo", false}, 2312 2313 {"multiple level wc", "foo/#", "foo.bar.baz./", "foo/bar/baz/", true}, 2314 {"multiple level wc", "foo/#", "foo.bar.baz", "foo/bar/baz", true}, 2315 {"multiple level wc", "foo/#", "foo.bar./", "foo/bar/", true}, 2316 {"multiple level wc", "foo/#", "foo.bar", "foo/bar", true}, 2317 {"multiple level wc", "foo/#", "foo./", "foo/", true}, 2318 {"multiple level wc", "foo/#", "foo", "foo", true}, 2319 {"multiple level wc", "foo/#", "/.foo", "/foo", false}, 2320 } { 2321 t.Run(test.name, func(t *testing.T) { 2322 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2323 defer mc.Close() 2324 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 2325 2326 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: test.mqttSubTopic, qos: 0}}, []byte{0}) 2327 testMQTTFlush(t, mc, nil, r) 2328 2329 natsPub(t, nc, test.natsPubSubject, []byte("msg")) 2330 if test.ok { 2331 testMQTTCheckPubMsg(t, mc, r, test.mqttPubTopic, 0, []byte("msg")) 2332 } else { 2333 testMQTTExpectNothing(t, r) 2334 } 2335 2336 testMQTTPublish(t, mcp, mpr, 0, false, false, test.mqttPubTopic, 0, []byte("msg")) 2337 if test.ok { 2338 testMQTTCheckPubMsg(t, mc, r, test.mqttPubTopic, 0, []byte("msg")) 2339 } else { 2340 testMQTTExpectNothing(t, r) 2341 } 2342 }) 2343 } 2344 } 2345 2346 func TestMQTTSubQoS2(t *testing.T) { 2347 o := testMQTTDefaultOptions() 2348 s := testMQTTRunServer(t, o) 2349 defer testMQTTShutdownServer(s) 2350 2351 nc := natsConnect(t, s.ClientURL()) 2352 defer nc.Close() 2353 2354 mcp, mpr := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2355 defer mcp.Close() 2356 testMQTTCheckConnAck(t, mpr, mqttConnAckRCConnectionAccepted, false) 2357 2358 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2359 defer mc.Close() 2360 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 2361 2362 topic := "foo/bar/baz" 2363 mqttTopic0 := "foo/#" 2364 mqttTopic1 := "foo/bar/#" 2365 mqttTopic2 := topic 2366 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: mqttTopic0, qos: 0}}, []byte{0}) 2367 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: mqttTopic1, qos: 1}}, []byte{1}) 2368 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: mqttTopic2, qos: 2}}, []byte{2}) 2369 testMQTTFlush(t, mc, nil, r) 2370 2371 for pubQoS, expectedCounts := range map[byte]map[byte]int{ 2372 0: {0: 3}, 2373 1: {0: 1, 1: 2}, 2374 2: {0: 1, 1: 1, 2: 1}, 2375 } { 2376 t.Run(fmt.Sprintf("pubQoS %v", pubQoS), func(t *testing.T) { 2377 pubPI := uint16(456) 2378 2379 testMQTTPublish(t, mcp, mpr, pubQoS, false, false, topic, pubPI, []byte("msg")) 2380 2381 qosCounts := map[byte]int{} 2382 delivered := map[uint16]byte{} 2383 2384 // We have 3 subscriptions, each should receive the message, with the 2385 // QoS that maybe "trimmed" to that of the subscription. 2386 for i := 0; i < 3; i++ { 2387 flags, pi := testMQTTGetPubMsg(t, mc, r, topic, []byte("msg")) 2388 delivered[pi] = flags 2389 qosCounts[mqttGetQoS(flags)]++ 2390 } 2391 2392 for pi, flags := range delivered { 2393 switch mqttGetQoS(flags) { 2394 case 1: 2395 testMQTTSendPIPacket(mqttPacketPubAck, t, mc, pi) 2396 2397 case 2: 2398 testMQTTSendPIPacket(mqttPacketPubRec, t, mc, pi) 2399 testMQTTReadPIPacket(mqttPacketPubRel, t, r, pi) 2400 testMQTTSendPIPacket(mqttPacketPubComp, t, mc, pi) 2401 } 2402 } 2403 2404 if !reflect.DeepEqual(qosCounts, expectedCounts) { 2405 t.Fatalf("Expected QoS %#v, got %#v", expectedCounts, qosCounts) 2406 } 2407 }) 2408 } 2409 } 2410 2411 func TestMQTTSubQoS1(t *testing.T) { 2412 o := testMQTTDefaultOptions() 2413 s := testMQTTRunServer(t, o) 2414 defer testMQTTShutdownServer(s) 2415 2416 nc := natsConnect(t, s.ClientURL()) 2417 defer nc.Close() 2418 2419 mcp, mpr := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2420 defer mcp.Close() 2421 testMQTTCheckConnAck(t, mpr, mqttConnAckRCConnectionAccepted, false) 2422 2423 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2424 defer mc.Close() 2425 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 2426 2427 mqttTopic := "foo/bar" 2428 2429 // Subscribe with QoS 1 2430 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo/#", qos: 1}}, []byte{1}) 2431 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: mqttTopic, qos: 1}}, []byte{1}) 2432 testMQTTFlush(t, mc, nil, r) 2433 2434 // Publish from NATS, which means QoS 0 2435 natsPub(t, nc, "foo.bar", []byte("NATS")) 2436 // Will receive as QoS 0 2437 testMQTTCheckPubMsg(t, mc, r, mqttTopic, 0, []byte("NATS")) 2438 testMQTTCheckPubMsg(t, mc, r, mqttTopic, 0, []byte("NATS")) 2439 2440 // Publish from MQTT with QoS 0 2441 testMQTTPublish(t, mcp, mpr, 0, false, false, mqttTopic, 0, []byte("msg")) 2442 // Will receive as QoS 0 2443 testMQTTCheckPubMsg(t, mc, r, mqttTopic, 0, []byte("msg")) 2444 testMQTTCheckPubMsg(t, mc, r, mqttTopic, 0, []byte("msg")) 2445 2446 // Publish from MQTT with QoS 1 2447 testMQTTPublish(t, mcp, mpr, 1, false, false, mqttTopic, 1, []byte("msg")) 2448 pflags1, pi1 := testMQTTGetPubMsg(t, mc, r, mqttTopic, []byte("msg")) 2449 if pflags1 != 0x2 { 2450 t.Fatalf("Expected flags to be 0x2, got %v", pflags1) 2451 } 2452 pflags2, pi2 := testMQTTGetPubMsg(t, mc, r, mqttTopic, []byte("msg")) 2453 if pflags2 != 0x2 { 2454 t.Fatalf("Expected flags to be 0x2, got %v", pflags2) 2455 } 2456 if pi1 == pi2 { 2457 t.Fatalf("packet identifier for message 1: %v should be different from message 2", pi1) 2458 } 2459 testMQTTSendPIPacket(mqttPacketPubAck, t, mc, pi1) 2460 testMQTTSendPIPacket(mqttPacketPubAck, t, mc, pi2) 2461 } 2462 2463 func getSubQoS(sub *subscription) int { 2464 if sub.mqtt != nil { 2465 return int(sub.mqtt.qos) 2466 } 2467 return -1 2468 } 2469 2470 func TestMQTTSubDups(t *testing.T) { 2471 o := testMQTTDefaultOptions() 2472 s := testMQTTRunServer(t, o) 2473 defer testMQTTShutdownServer(s) 2474 2475 mcp, mpr := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2476 defer mcp.Close() 2477 testMQTTCheckConnAck(t, mpr, mqttConnAckRCConnectionAccepted, false) 2478 2479 mc, r := testMQTTConnect(t, &mqttConnInfo{clientID: "sub", user: "sub", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2480 defer mc.Close() 2481 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 2482 2483 // Test with single SUBSCRIBE protocol but multiple filters 2484 filters := []*mqttFilter{ 2485 {filter: "foo", qos: 1}, 2486 {filter: "foo", qos: 0}, 2487 } 2488 testMQTTSub(t, 1, mc, r, filters, []byte{1, 0}) 2489 testMQTTFlush(t, mc, nil, r) 2490 2491 // And also with separate SUBSCRIBE protocols 2492 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "bar", qos: 0}}, []byte{0}) 2493 // Ask for QoS 1 but server will downgrade to 1 2494 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 2495 testMQTTFlush(t, mc, nil, r) 2496 2497 // Publish and test msg received only once 2498 testMQTTPublish(t, mcp, r, 0, false, false, "foo", 0, []byte("msg")) 2499 testMQTTCheckPubMsg(t, mc, r, "foo", 0, []byte("msg")) 2500 testMQTTExpectNothing(t, r) 2501 2502 testMQTTPublish(t, mcp, r, 0, false, false, "bar", 0, []byte("msg")) 2503 testMQTTCheckPubMsg(t, mc, r, "bar", 0, []byte("msg")) 2504 testMQTTExpectNothing(t, r) 2505 2506 // Check that the QoS for subscriptions have been updated to the latest received filter 2507 var err error 2508 subc := testMQTTGetClient(t, s, "sub") 2509 subc.mu.Lock() 2510 if subc.opts.Username != "sub" { 2511 err = fmt.Errorf("wrong user name") 2512 } 2513 if err == nil { 2514 if sub := subc.subs["foo"]; sub == nil || getSubQoS(sub) != 0 { 2515 err = fmt.Errorf("subscription foo QoS should be 0, got %v", getSubQoS(sub)) 2516 } 2517 } 2518 if err == nil { 2519 if sub := subc.subs["bar"]; sub == nil || getSubQoS(sub) != 1 { 2520 err = fmt.Errorf("subscription bar QoS should be 1, got %v", getSubQoS(sub)) 2521 } 2522 } 2523 subc.mu.Unlock() 2524 if err != nil { 2525 t.Fatal(err) 2526 } 2527 2528 // Now subscribe on "foo/#" which means that a PUBLISH on "foo" will be received 2529 // by this subscription and also the one on "foo". 2530 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo/#", qos: 1}}, []byte{1}) 2531 testMQTTFlush(t, mc, nil, r) 2532 2533 // Publish and test msg received twice 2534 testMQTTPublish(t, mcp, r, 0, false, false, "foo", 0, []byte("msg")) 2535 testMQTTCheckPubMsg(t, mc, r, "foo", 0, []byte("msg")) 2536 testMQTTCheckPubMsg(t, mc, r, "foo", 0, []byte("msg")) 2537 2538 checkWCSub := func(expectedQoS int) { 2539 t.Helper() 2540 2541 subc.mu.Lock() 2542 defer subc.mu.Unlock() 2543 2544 // When invoked with expectedQoS==1, we have the following subs: 2545 // foo (QoS-0), bar (QoS-1), foo.> (QoS-1) 2546 // which means (since QoS-1 have a JS consumer + sub for delivery 2547 // and foo.> causes a "foo fwc") that we should have the following 2548 // number of NATS subs: foo (1), bar (2), foo.> (2) and "foo fwc" (2), 2549 // so total=7. 2550 // When invoked with expectedQoS==0, it means that we have replaced 2551 // foo/# QoS-1 to QoS-0, so we should have 2 less NATS subs, 2552 // so total=5 2553 expected := 7 2554 if expectedQoS == 0 { 2555 expected = 5 2556 } 2557 if lenmap := len(subc.subs); lenmap != expected { 2558 t.Fatalf("Subs map should have %v entries, got %v", expected, lenmap) 2559 } 2560 if sub, ok := subc.subs["foo.>"]; !ok { 2561 t.Fatal("Expected sub foo.> to be present but was not") 2562 } else if getSubQoS(sub) != expectedQoS { 2563 t.Fatalf("Expected sub foo.> QoS to be %v, got %v", expectedQoS, getSubQoS(sub)) 2564 } 2565 if sub, ok := subc.subs["foo fwc"]; !ok { 2566 t.Fatal("Expected sub foo fwc to be present but was not") 2567 } else if getSubQoS(sub) != expectedQoS { 2568 t.Fatalf("Expected sub foo fwc QoS to be %v, got %v", expectedQoS, getSubQoS(sub)) 2569 } 2570 // Make sure existing sub on "foo" qos was not changed. 2571 if sub, ok := subc.subs["foo"]; !ok { 2572 t.Fatal("Expected sub foo to be present but was not") 2573 } else if getSubQoS(sub) != 0 { 2574 t.Fatalf("Expected sub foo QoS to be 0, got %v", getSubQoS(sub)) 2575 } 2576 } 2577 checkWCSub(1) 2578 2579 // Sub again on same subject with lower QoS 2580 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo/#", qos: 0}}, []byte{0}) 2581 testMQTTFlush(t, mc, nil, r) 2582 2583 // Publish and test msg received twice 2584 testMQTTPublish(t, mcp, r, 0, false, false, "foo", 0, []byte("msg")) 2585 testMQTTCheckPubMsg(t, mc, r, "foo", 0, []byte("msg")) 2586 testMQTTCheckPubMsg(t, mc, r, "foo", 0, []byte("msg")) 2587 checkWCSub(0) 2588 } 2589 2590 func TestMQTTSubWithSpaces(t *testing.T) { 2591 o := testMQTTDefaultOptions() 2592 s := testMQTTRunServer(t, o) 2593 defer testMQTTShutdownServer(s) 2594 2595 mcp, mpr := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2596 defer mcp.Close() 2597 testMQTTCheckConnAck(t, mpr, mqttConnAckRCConnectionAccepted, false) 2598 2599 mc, r := testMQTTConnect(t, &mqttConnInfo{user: "sub", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2600 defer mc.Close() 2601 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 2602 2603 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo bar", qos: 0}}, []byte{mqttSubAckFailure}) 2604 } 2605 2606 func TestMQTTSubCaseSensitive(t *testing.T) { 2607 o := testMQTTDefaultOptions() 2608 s := testMQTTRunServer(t, o) 2609 defer testMQTTShutdownServer(s) 2610 2611 mcp, mpr := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2612 defer mcp.Close() 2613 testMQTTCheckConnAck(t, mpr, mqttConnAckRCConnectionAccepted, false) 2614 2615 mc, r := testMQTTConnect(t, &mqttConnInfo{user: "sub", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2616 defer mc.Close() 2617 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 2618 2619 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "Foo/Bar", qos: 0}}, []byte{0}) 2620 testMQTTFlush(t, mc, nil, r) 2621 2622 testMQTTPublish(t, mcp, r, 0, false, false, "Foo/Bar", 0, []byte("msg")) 2623 testMQTTCheckPubMsg(t, mc, r, "Foo/Bar", 0, []byte("msg")) 2624 2625 testMQTTPublish(t, mcp, r, 0, false, false, "foo/bar", 0, []byte("msg")) 2626 testMQTTExpectNothing(t, r) 2627 2628 nc := natsConnect(t, s.ClientURL()) 2629 defer nc.Close() 2630 2631 natsPub(t, nc, "Foo.Bar", []byte("nats")) 2632 testMQTTCheckPubMsg(t, mc, r, "Foo/Bar", 0, []byte("nats")) 2633 2634 natsPub(t, nc, "foo.bar", []byte("nats")) 2635 testMQTTExpectNothing(t, r) 2636 } 2637 2638 func TestMQTTPubSubMatrix(t *testing.T) { 2639 for _, test := range []struct { 2640 name string 2641 natsPub bool 2642 mqttPub bool 2643 mqttPubQoS byte 2644 natsSub bool 2645 mqttSubQoS0 bool 2646 mqttSubQoS1 bool 2647 }{ 2648 {"NATS to MQTT sub QoS-0", true, false, 0, false, true, false}, 2649 {"NATS to MQTT sub QoS-1", true, false, 0, false, false, true}, 2650 {"NATS to MQTT sub QoS-0 and QoS-1", true, false, 0, false, true, true}, 2651 2652 {"MQTT QoS-0 to NATS sub", false, true, 0, true, false, false}, 2653 {"MQTT QoS-0 to MQTT sub QoS-0", false, true, 0, false, true, false}, 2654 {"MQTT QoS-0 to MQTT sub QoS-1", false, true, 0, false, false, true}, 2655 {"MQTT QoS-0 to NATS sub and MQTT sub QoS-0", false, true, 0, true, true, false}, 2656 {"MQTT QoS-0 to NATS sub and MQTT sub QoS-1", false, true, 0, true, false, true}, 2657 {"MQTT QoS-0 to all subs", false, true, 0, true, true, true}, 2658 2659 {"MQTT QoS-1 to NATS sub", false, true, 1, true, false, false}, 2660 {"MQTT QoS-1 to MQTT sub QoS-0", false, true, 1, false, true, false}, 2661 {"MQTT QoS-1 to MQTT sub QoS-1", false, true, 1, false, false, true}, 2662 {"MQTT QoS-1 to NATS sub and MQTT sub QoS-0", false, true, 1, true, true, false}, 2663 {"MQTT QoS-1 to NATS sub and MQTT sub QoS-1", false, true, 1, true, false, true}, 2664 {"MQTT QoS-1 to all subs", false, true, 1, true, true, true}, 2665 } { 2666 t.Run(test.name, func(t *testing.T) { 2667 o := testMQTTDefaultOptions() 2668 s := testMQTTRunServer(t, o) 2669 defer testMQTTShutdownServer(s) 2670 2671 nc := natsConnect(t, s.ClientURL()) 2672 defer nc.Close() 2673 2674 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2675 defer mc.Close() 2676 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 2677 2678 mc1, r1 := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2679 defer mc1.Close() 2680 testMQTTCheckConnAck(t, r1, mqttConnAckRCConnectionAccepted, false) 2681 2682 mc2, r2 := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2683 defer mc2.Close() 2684 testMQTTCheckConnAck(t, r2, mqttConnAckRCConnectionAccepted, false) 2685 2686 // First setup subscriptions based on test options. 2687 var ns *nats.Subscription 2688 if test.natsSub { 2689 ns = natsSubSync(t, nc, "foo") 2690 } 2691 if test.mqttSubQoS0 { 2692 testMQTTSub(t, 1, mc1, r1, []*mqttFilter{{filter: "foo", qos: 0}}, []byte{0}) 2693 testMQTTFlush(t, mc1, nil, r1) 2694 } 2695 if test.mqttSubQoS1 { 2696 testMQTTSub(t, 1, mc2, r2, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 2697 testMQTTFlush(t, mc2, nil, r2) 2698 } 2699 2700 // Just as a barrier 2701 natsFlush(t, nc) 2702 2703 // Now publish 2704 if test.natsPub { 2705 natsPubReq(t, nc, "foo", "", []byte("msg")) 2706 } else { 2707 testMQTTPublish(t, mc, r, test.mqttPubQoS, false, false, "foo", 1, []byte("msg")) 2708 } 2709 2710 // Check message received 2711 if test.natsSub { 2712 natsNexMsg(t, ns, time.Second) 2713 // Make sure no other is received 2714 if msg, err := ns.NextMsg(50 * time.Millisecond); err == nil { 2715 t.Fatalf("Should not have gotten a second message, got %v", msg) 2716 } 2717 } 2718 if test.mqttSubQoS0 { 2719 testMQTTCheckPubMsg(t, mc1, r1, "foo", 0, []byte("msg")) 2720 testMQTTExpectNothing(t, r1) 2721 } 2722 if test.mqttSubQoS1 { 2723 var expectedFlag byte 2724 if test.mqttPubQoS > 0 { 2725 expectedFlag = test.mqttPubQoS << 1 2726 } 2727 testMQTTCheckPubMsg(t, mc2, r2, "foo", expectedFlag, []byte("msg")) 2728 testMQTTExpectNothing(t, r2) 2729 } 2730 }) 2731 } 2732 } 2733 2734 func TestMQTTPreventSubWithMQTTSubPrefix(t *testing.T) { 2735 o := testMQTTDefaultOptions() 2736 s := testMQTTRunServer(t, o) 2737 defer testMQTTShutdownServer(s) 2738 2739 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2740 defer mc.Close() 2741 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 2742 testMQTTSub(t, 1, mc, r, 2743 []*mqttFilter{{filter: strings.ReplaceAll(mqttSubPrefix, ".", "/") + "foo/bar", qos: 1}}, 2744 []byte{mqttSubAckFailure}) 2745 } 2746 2747 func TestMQTTSubWithNATSStream(t *testing.T) { 2748 o := testMQTTDefaultOptions() 2749 s := testMQTTRunServer(t, o) 2750 defer testMQTTShutdownServer(s) 2751 2752 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2753 defer mc.Close() 2754 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 2755 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo/bar", qos: 1}}, []byte{1}) 2756 testMQTTFlush(t, mc, nil, r) 2757 2758 mcp, rp := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2759 defer mcp.Close() 2760 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 2761 testMQTTFlush(t, mcp, nil, rp) 2762 2763 nc := natsConnect(t, s.ClientURL()) 2764 defer nc.Close() 2765 2766 sc := &StreamConfig{ 2767 Name: "test", 2768 Storage: FileStorage, 2769 Retention: InterestPolicy, 2770 Subjects: []string{"foo.>"}, 2771 } 2772 mset, err := s.GlobalAccount().addStream(sc) 2773 if err != nil { 2774 t.Fatalf("Unable to create stream: %v", err) 2775 } 2776 2777 sub := natsSubSync(t, nc, "bar") 2778 cc := &ConsumerConfig{ 2779 Durable: "dur", 2780 AckPolicy: AckExplicit, 2781 DeliverSubject: "bar", 2782 } 2783 if _, err := mset.addConsumer(cc); err != nil { 2784 t.Fatalf("Unable to add consumer: %v", err) 2785 } 2786 2787 // Now send message from NATS 2788 resp, err := nc.Request("foo.bar", []byte("nats"), time.Second) 2789 if err != nil { 2790 t.Fatalf("Error publishing: %v", err) 2791 } 2792 ar := &ApiResponse{} 2793 if err := json.Unmarshal(resp.Data, ar); err != nil || ar.Error != nil { 2794 t.Fatalf("Unexpected response: err=%v resp=%+v", err, ar.Error) 2795 } 2796 2797 // Check that message is received by both 2798 checkRecv := func(content string, flags byte) { 2799 t.Helper() 2800 if msg := natsNexMsg(t, sub, time.Second); string(msg.Data) != content { 2801 t.Fatalf("Expected %q, got %q", content, msg.Data) 2802 } 2803 testMQTTCheckPubMsg(t, mc, r, "foo/bar", flags, []byte(content)) 2804 } 2805 checkRecv("nats", 0) 2806 2807 // Send from MQTT as a QoS0 2808 testMQTTPublish(t, mcp, rp, 0, false, false, "foo/bar", 0, []byte("qos0")) 2809 checkRecv("qos0", 0) 2810 2811 // Send from MQTT as a QoS1 2812 testMQTTPublish(t, mcp, rp, 1, false, false, "foo/bar", 1, []byte("qos1")) 2813 checkRecv("qos1", mqttPubQos1) 2814 } 2815 2816 func TestMQTTTrackPendingOverrun(t *testing.T) { 2817 sess := mqttSession{} 2818 2819 sess.last_pi = 0xFFFF 2820 pi := sess.trackPublishRetained() 2821 if pi != 1 { 2822 t.Fatalf("Expected 1, got %v", pi) 2823 } 2824 2825 p := &mqttPending{} 2826 for i := 1; i <= 0xFFFF; i++ { 2827 sess.pendingPublish[uint16(i)] = p 2828 } 2829 pi, _ = sess.trackPublish("test", "test") 2830 if pi != 0 { 2831 t.Fatalf("Expected 0, got %v", pi) 2832 } 2833 2834 delete(sess.pendingPublish, 1234) 2835 pi = sess.trackPublishRetained() 2836 if pi != 1234 { 2837 t.Fatalf("Expected 1234, got %v", pi) 2838 } 2839 } 2840 2841 func TestMQTTSubRestart(t *testing.T) { 2842 o := testMQTTDefaultOptions() 2843 s := testMQTTRunServer(t, o) 2844 defer testMQTTShutdownServer(s) 2845 2846 nc := natsConnect(t, s.ClientURL()) 2847 defer nc.Close() 2848 2849 mc, r := testMQTTConnect(t, &mqttConnInfo{clientID: "sub", cleanSess: false}, o.MQTT.Host, o.MQTT.Port) 2850 defer mc.Close() 2851 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 2852 2853 // Start an MQTT subscription QoS=1 on "foo" 2854 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 2855 testMQTTFlush(t, mc, nil, r) 2856 2857 // Now start a NATS subscription on ">" (anything that would match the JS consumer delivery subject) 2858 natsSubSync(t, nc, ">") 2859 natsFlush(t, nc) 2860 2861 // Restart the MQTT client 2862 testMQTTDisconnect(t, mc, nil) 2863 2864 mc, r = testMQTTConnect(t, &mqttConnInfo{clientID: "sub", cleanSess: false}, o.MQTT.Host, o.MQTT.Port) 2865 defer mc.Close() 2866 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 2867 2868 // Restart an MQTT subscription QoS=1 on "foo" 2869 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 2870 testMQTTFlush(t, mc, nil, r) 2871 2872 pc, pr := testMQTTConnect(t, &mqttConnInfo{clientID: "pub", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2873 defer pc.Close() 2874 testMQTTCheckConnAck(t, pr, mqttConnAckRCConnectionAccepted, false) 2875 2876 // Publish a message QoS1 2877 testMQTTPublish(t, pc, pr, 1, false, false, "foo", 1, []byte("msg1")) 2878 // Make sure we receive it 2879 testMQTTCheckPubMsg(t, mc, r, "foo", mqttPubQos1, []byte("msg1")) 2880 2881 // Now "restart" the subscription but as a Qos0 2882 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo", qos: 0}}, []byte{0}) 2883 testMQTTFlush(t, mc, nil, r) 2884 2885 // Publish a message QoS 2886 testMQTTPublish(t, pc, pr, 1, false, false, "foo", 1, []byte("msg2")) 2887 // Make sure we receive but as a QoS0 2888 testMQTTCheckPubMsg(t, mc, r, "foo", 0, []byte("msg2")) 2889 } 2890 2891 func testMQTTGetClusterTemplaceNoLeaf() string { 2892 return strings.Replace(jsClusterTemplWithLeafAndMQTT, "{{leaf}}", "", 1) 2893 } 2894 2895 func TestMQTTSubPropagation(t *testing.T) { 2896 cl := createJetStreamClusterWithTemplate(t, testMQTTGetClusterTemplaceNoLeaf(), "MQTT", 2) 2897 defer cl.shutdown() 2898 2899 o := cl.opts[0] 2900 s2 := cl.servers[1] 2901 nc := natsConnect(t, s2.ClientURL()) 2902 defer nc.Close() 2903 2904 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2905 defer mc.Close() 2906 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 2907 2908 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo/#", qos: 0}}, []byte{0}) 2909 testMQTTFlush(t, mc, nil, r) 2910 2911 // Because in MQTT foo/# means foo.> but also foo, check that this is propagated 2912 checkSubInterest(t, s2, globalAccountName, "foo", time.Second) 2913 2914 // Publish on foo.bar, foo./ and foo and we should receive them 2915 natsPub(t, nc, "foo.bar", []byte("hello")) 2916 testMQTTCheckPubMsg(t, mc, r, "foo/bar", 0, []byte("hello")) 2917 2918 natsPub(t, nc, "foo./", []byte("from")) 2919 testMQTTCheckPubMsg(t, mc, r, "foo/", 0, []byte("from")) 2920 2921 natsPub(t, nc, "foo", []byte("NATS")) 2922 testMQTTCheckPubMsg(t, mc, r, "foo", 0, []byte("NATS")) 2923 } 2924 2925 func TestMQTTCluster(t *testing.T) { 2926 cl := createJetStreamClusterWithTemplate(t, testMQTTGetClusterTemplaceNoLeaf(), "MQTT", 2) 2927 defer cl.shutdown() 2928 2929 for _, topTest := range []struct { 2930 name string 2931 restart bool 2932 }{ 2933 {"first_start", true}, 2934 {"restart", false}, 2935 } { 2936 t.Run(topTest.name, func(t *testing.T) { 2937 for _, test := range []struct { 2938 name string 2939 subQos byte 2940 }{ 2941 {"qos_0", 0}, 2942 {"qos_1", 1}, 2943 } { 2944 t.Run(test.name, func(t *testing.T) { 2945 clientID := nuid.Next() 2946 2947 o := cl.opts[0] 2948 mc, r := testMQTTConnectRetry(t, &mqttConnInfo{clientID: clientID, cleanSess: false}, o.MQTT.Host, o.MQTT.Port, 5) 2949 defer mc.Close() 2950 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 2951 2952 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo/#", qos: test.subQos}}, []byte{test.subQos}) 2953 testMQTTFlush(t, mc, nil, r) 2954 2955 check := func(mc net.Conn, r *mqttReader, o *Options, s *Server) { 2956 t.Helper() 2957 2958 nc := natsConnect(t, s.ClientURL()) 2959 defer nc.Close() 2960 2961 natsPub(t, nc, "foo.bar", []byte("fromNats")) 2962 testMQTTCheckPubMsg(t, mc, r, "foo/bar", 0, []byte("fromNats")) 2963 2964 mpc, pr := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 2965 defer mpc.Close() 2966 testMQTTCheckConnAck(t, pr, mqttConnAckRCConnectionAccepted, false) 2967 2968 testMQTTPublish(t, mpc, pr, 0, false, false, "foo/baz", 0, []byte("mqtt_qos0")) 2969 testMQTTCheckPubMsg(t, mc, r, "foo/baz", 0, []byte("mqtt_qos0")) 2970 2971 testMQTTPublish(t, mpc, pr, 1, false, false, "foo/bat", 1, []byte("mqtt_qos1")) 2972 expectedQoS := byte(0) 2973 if test.subQos == 1 { 2974 expectedQoS = mqttPubQos1 2975 } 2976 testMQTTCheckPubMsg(t, mc, r, "foo/bat", expectedQoS, []byte("mqtt_qos1")) 2977 testMQTTDisconnect(t, mpc, nil) 2978 } 2979 check(mc, r, cl.opts[0], cl.servers[0]) 2980 check(mc, r, cl.opts[1], cl.servers[1]) 2981 2982 // Start the same subscription from the other server. It should disconnect 2983 // the one connected in the first server. 2984 o = cl.opts[1] 2985 2986 mc2, r2 := testMQTTConnect(t, &mqttConnInfo{clientID: clientID, cleanSess: false}, o.MQTT.Host, o.MQTT.Port) 2987 defer mc2.Close() 2988 testMQTTCheckConnAck(t, r2, mqttConnAckRCConnectionAccepted, true) 2989 2990 // Expect first connection to be closed. 2991 testMQTTExpectDisconnect(t, mc) 2992 2993 // Now re-run the checks 2994 check(mc2, r2, cl.opts[0], cl.servers[0]) 2995 check(mc2, r2, cl.opts[1], cl.servers[1]) 2996 2997 // Disconnect our sub and restart with clean session then disconnect again to clear the state. 2998 testMQTTDisconnect(t, mc2, nil) 2999 mc2, r2 = testMQTTConnect(t, &mqttConnInfo{clientID: clientID, cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 3000 defer mc2.Close() 3001 testMQTTCheckConnAck(t, r2, mqttConnAckRCConnectionAccepted, false) 3002 testMQTTFlush(t, mc2, nil, r2) 3003 testMQTTDisconnect(t, mc2, nil) 3004 3005 // Remove the session from the flappers so we can restart the test 3006 // without failure and have to wait for 1sec before being able to reconnect. 3007 s := cl.servers[0] 3008 sm := &s.mqtt.sessmgr 3009 sm.mu.Lock() 3010 asm := sm.sessions[globalAccountName] 3011 sm.mu.Unlock() 3012 if asm != nil { 3013 asm.mu.Lock() 3014 delete(asm.flappers, clientID) 3015 asm.mu.Unlock() 3016 } 3017 }) 3018 } 3019 if !t.Failed() && topTest.restart { 3020 cl.stopAll() 3021 cl.restartAll() 3022 3023 streams := []string{mqttStreamName, mqttRetainedMsgsStreamName, mqttSessStreamName} 3024 for _, sn := range streams { 3025 cl.waitOnStreamLeader(globalAccountName, sn) 3026 } 3027 3028 mset, err := cl.randomServer().GlobalAccount().lookupStream(mqttRetainedMsgsStreamName) 3029 if err != nil { 3030 t.Fatalf("Expected to find a stream for %q", mqttRetainedMsgsStreamName) 3031 } 3032 3033 rmConsumerNames := []string{} 3034 mset.mu.RLock() 3035 for _, o := range mset.consumers { 3036 rmConsumerNames = append(rmConsumerNames, o.name) 3037 } 3038 mset.mu.RUnlock() 3039 3040 for _, consumerName := range rmConsumerNames { 3041 cl.waitOnConsumerLeader(globalAccountName, mqttRetainedMsgsStreamName, consumerName) 3042 } 3043 } 3044 }) 3045 } 3046 } 3047 3048 func testMQTTConnectDisconnect(t *testing.T, o *Options, clientID string, clean bool, found bool) { 3049 t.Helper() 3050 mc, r := testMQTTConnect(t, &mqttConnInfo{clientID: clientID, cleanSess: clean}, o.MQTT.Host, o.MQTT.Port) 3051 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, found) 3052 testMQTTDisconnectEx(t, mc, nil, false) 3053 mc.Close() 3054 } 3055 3056 func TestMQTTClusterConnectDisconnectClean(t *testing.T) { 3057 nServers := 3 3058 cl := createJetStreamClusterWithTemplate(t, testMQTTGetClusterTemplaceNoLeaf(), "MQTT", nServers) 3059 defer cl.shutdown() 3060 3061 clientID := nuid.Next() 3062 3063 // test runs a connect/disconnect against a random server in the cluster, as 3064 // specified. 3065 N := 100 3066 for n := 0; n < N; n++ { 3067 testMQTTConnectDisconnect(t, cl.opts[rand.Intn(nServers)], clientID, true, false) 3068 } 3069 } 3070 3071 func TestMQTTClusterConnectDisconnectPersist(t *testing.T) { 3072 nServers := 3 3073 cl := createJetStreamClusterWithTemplate(t, testMQTTGetClusterTemplaceNoLeaf(), "MQTT", nServers) 3074 defer cl.shutdown() 3075 3076 clientID := nuid.Next() 3077 3078 // test runs a connect/disconnect against a random server in the cluster, as 3079 // specified. 3080 N := 20 3081 for n := 0; n < N; n++ { 3082 // First clean sessions on all servers 3083 for i := 0; i < nServers; i++ { 3084 testMQTTConnectDisconnect(t, cl.opts[i], clientID, true, false) 3085 } 3086 3087 testMQTTConnectDisconnect(t, cl.opts[0], clientID, false, false) 3088 testMQTTConnectDisconnect(t, cl.opts[1], clientID, false, true) 3089 testMQTTConnectDisconnect(t, cl.opts[2], clientID, false, true) 3090 testMQTTConnectDisconnect(t, cl.opts[0], clientID, false, true) 3091 } 3092 } 3093 3094 func TestMQTTClusterRetainedMsg(t *testing.T) { 3095 cl := createJetStreamClusterWithTemplate(t, testMQTTGetClusterTemplaceNoLeaf(), "MQTT", 2) 3096 defer cl.shutdown() 3097 3098 srv1Opts := cl.opts[0] 3099 srv2Opts := cl.opts[1] 3100 3101 // Connect subscription on server 1. 3102 mc, rc := testMQTTConnectRetry(t, &mqttConnInfo{clientID: "sub", cleanSess: false}, srv1Opts.MQTT.Host, srv1Opts.MQTT.Port, 5) 3103 defer mc.Close() 3104 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, false) 3105 3106 testMQTTSub(t, 1, mc, rc, []*mqttFilter{{filter: "foo/#", qos: 1}}, []byte{1}) 3107 testMQTTFlush(t, mc, nil, rc) 3108 3109 // Create a publisher from server 2. 3110 mp, rp := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, srv2Opts.MQTT.Host, srv2Opts.MQTT.Port) 3111 defer mp.Close() 3112 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 3113 3114 // Send retained message. 3115 testMQTTPublish(t, mp, rp, 1, false, true, "foo/bar", 1, []byte("retained")) 3116 // Check it is received. 3117 testMQTTCheckPubMsg(t, mc, rc, "foo/bar", mqttPubQos1, []byte("retained")) 3118 3119 // Start a new subscription on server 1 and make sure we receive the retained message 3120 mc2, rc2 := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, srv1Opts.MQTT.Host, srv1Opts.MQTT.Port) 3121 defer mc2.Close() 3122 testMQTTCheckConnAck(t, rc2, mqttConnAckRCConnectionAccepted, false) 3123 testMQTTSub(t, 1, mc2, rc2, []*mqttFilter{{filter: "foo/#", qos: 1}}, []byte{1}) 3124 testMQTTCheckPubMsg(t, mc2, rc2, "foo/bar", mqttPubQos1|mqttPubFlagRetain, []byte("retained")) 3125 testMQTTDisconnect(t, mc2, nil) 3126 3127 // Send an empty retained message which should remove it from storage, but still be delivered. 3128 testMQTTPublish(t, mp, rp, 1, false, true, "foo/bar", 1, []byte("")) 3129 testMQTTCheckPubMsg(t, mc, rc, "foo/bar", mqttPubQos1, []byte("")) 3130 3131 // Now shutdown the consumer connection 3132 testMQTTDisconnect(t, mc, nil) 3133 mc.Close() 3134 3135 // Reconnect to server where the retained message was published (server 2) 3136 mc, rc = testMQTTConnect(t, &mqttConnInfo{clientID: "sub", cleanSess: false}, srv2Opts.MQTT.Host, srv2Opts.MQTT.Port) 3137 defer mc.Close() 3138 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, true) 3139 testMQTTSub(t, 1, mc, rc, []*mqttFilter{{filter: "foo/#", qos: 1}}, []byte{1}) 3140 // The retained message should not be delivered. 3141 testMQTTExpectNothing(t, rc) 3142 // Now disconnect and reconnect back to first server 3143 testMQTTDisconnect(t, mc, nil) 3144 mc.Close() 3145 3146 // Now reconnect to the server 1, which is not where the messages were published, and check 3147 // that we don't receive the message. 3148 mc, rc = testMQTTConnect(t, &mqttConnInfo{clientID: "sub", cleanSess: false}, srv1Opts.MQTT.Host, srv1Opts.MQTT.Port) 3149 defer mc.Close() 3150 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, true) 3151 testMQTTSub(t, 1, mc, rc, []*mqttFilter{{filter: "foo/#", qos: 1}}, []byte{1}) 3152 testMQTTExpectNothing(t, rc) 3153 testMQTTDisconnect(t, mc, nil) 3154 mc.Close() 3155 3156 // Will now test network deletes 3157 3158 // Create a subscription on server 1 and server 2 3159 mc, rc = testMQTTConnect(t, &mqttConnInfo{clientID: "sub_one", cleanSess: false}, srv1Opts.MQTT.Host, srv1Opts.MQTT.Port) 3160 defer mc.Close() 3161 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, false) 3162 testMQTTSub(t, 1, mc, rc, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 3163 testMQTTFlush(t, mc, nil, rc) 3164 3165 mc2, rc2 = testMQTTConnect(t, &mqttConnInfo{clientID: "sub_two", cleanSess: false}, srv2Opts.MQTT.Host, srv2Opts.MQTT.Port) 3166 defer mc2.Close() 3167 testMQTTCheckConnAck(t, rc2, mqttConnAckRCConnectionAccepted, false) 3168 testMQTTSub(t, 1, mc2, rc2, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 3169 testMQTTFlush(t, mc2, nil, rc2) 3170 3171 // Publish 1 retained message (producer is connected to server 2) 3172 testMQTTPublish(t, mp, rp, 1, false, true, "bar", 1, []byte("msg1")) 3173 3174 // Make sure messages are received by both 3175 testMQTTCheckPubMsg(t, mc, rc, "bar", mqttPubQos1, []byte("msg1")) 3176 testMQTTCheckPubMsg(t, mc2, rc2, "bar", mqttPubQos1, []byte("msg1")) 3177 3178 // Now send an empty retained message that should delete it. For the one on server 1, 3179 // this will be a network delete. 3180 testMQTTPublish(t, mp, rp, 1, false, true, "bar", 1, []byte("")) 3181 testMQTTCheckPubMsg(t, mc, rc, "bar", mqttPubQos1, []byte("")) 3182 testMQTTCheckPubMsg(t, mc2, rc2, "bar", mqttPubQos1, []byte("")) 3183 3184 // Now send a new retained message 3185 testMQTTPublish(t, mp, rp, 1, false, true, "bar", 1, []byte("msg2")) 3186 3187 // Again, verify that they all receive it. 3188 testMQTTCheckPubMsg(t, mc, rc, "bar", mqttPubQos1, []byte("msg2")) 3189 testMQTTCheckPubMsg(t, mc2, rc2, "bar", mqttPubQos1, []byte("msg2")) 3190 3191 // But now, restart the consumer that was in the server that processed the 3192 // original network delete. 3193 testMQTTDisconnect(t, mc, nil) 3194 mc.Close() 3195 3196 mc, rc = testMQTTConnect(t, &mqttConnInfo{clientID: "sub_one", cleanSess: false}, srv1Opts.MQTT.Host, srv1Opts.MQTT.Port) 3197 defer mc.Close() 3198 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, true) 3199 testMQTTSub(t, 1, mc, rc, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 3200 // Expect the message to be delivered as retained 3201 testMQTTCheckPubMsg(t, mc, rc, "bar", mqttPubQos1|mqttPubFlagRetain, []byte("msg2")) 3202 } 3203 3204 func TestMQTTRetainedMsgNetworkUpdates(t *testing.T) { 3205 o := testMQTTDefaultOptions() 3206 s := testMQTTRunServer(t, o) 3207 defer testMQTTShutdownServer(s) 3208 3209 mc, rc := testMQTTConnect(t, &mqttConnInfo{clientID: "sub", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 3210 defer mc.Close() 3211 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, false) 3212 3213 c := testMQTTGetClient(t, s, "sub") 3214 asm := c.mqtt.asm 3215 3216 // For this test, we are going to simulate updates arriving in a 3217 // mixed order and verify that we have the expected outcome. 3218 check := func(t *testing.T, subject string, present bool, current, floor uint64) { 3219 t.Helper() 3220 asm.mu.RLock() 3221 defer asm.mu.RUnlock() 3222 erm, ok := asm.retmsgs[subject] 3223 if present && !ok { 3224 t.Fatalf("Subject %q not present", subject) 3225 } else if !present && ok { 3226 t.Fatalf("Subject %q should not be present", subject) 3227 } else if !present { 3228 return 3229 } 3230 if floor != erm.floor { 3231 t.Fatalf("Expected floor to be %v, got %v", floor, erm.floor) 3232 } 3233 if erm.sseq != current { 3234 t.Fatalf("Expected current sequence to be %v, got %v", current, erm.sseq) 3235 } 3236 } 3237 3238 type action struct { 3239 add bool 3240 seq uint64 3241 } 3242 for _, test := range []struct { 3243 subject string 3244 order []action 3245 seq uint64 3246 floor uint64 3247 }{ 3248 {"foo.1", []action{{true, 1}, {true, 2}, {true, 3}}, 3, 0}, 3249 {"foo.2", []action{{true, 3}, {true, 1}, {true, 2}}, 3, 0}, 3250 {"foo.3", []action{{true, 1}, {false, 1}, {true, 2}}, 2, 0}, 3251 {"foo.4", []action{{false, 2}, {true, 1}, {true, 3}, {true, 2}}, 3, 0}, 3252 {"foo.5", []action{{false, 2}, {true, 1}, {true, 2}}, 0, 2}, 3253 {"foo.6", []action{{true, 1}, {true, 2}, {false, 2}}, 0, 2}, 3254 } { 3255 t.Run(test.subject, func(t *testing.T) { 3256 for _, a := range test.order { 3257 if a.add { 3258 rf := &mqttRetainedMsgRef{sseq: a.seq} 3259 asm.handleRetainedMsg(test.subject, rf, nil, false) 3260 } else { 3261 asm.handleRetainedMsgDel(test.subject, a.seq) 3262 } 3263 } 3264 check(t, test.subject, true, test.seq, test.floor) 3265 }) 3266 } 3267 3268 for _, subject := range []string{"foo.5", "foo.6"} { 3269 t.Run("clear_"+subject, func(t *testing.T) { 3270 // Now add a new message, which should clear the floor. 3271 rf := &mqttRetainedMsgRef{sseq: 3} 3272 asm.handleRetainedMsg(subject, rf, nil, false) 3273 check(t, subject, true, 3, 0) 3274 // Now do a non network delete and make sure it is gone. 3275 asm.handleRetainedMsgDel(subject, 0) 3276 check(t, subject, false, 0, 0) 3277 }) 3278 } 3279 } 3280 3281 func TestMQTTRetainedMsgDel(t *testing.T) { 3282 o := testMQTTDefaultOptions() 3283 s := testMQTTRunServer(t, o) 3284 defer testMQTTShutdownServer(s) 3285 mc, _ := testMQTTConnect(t, &mqttConnInfo{clientID: "sub", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 3286 defer mc.Close() 3287 3288 c := testMQTTGetClient(t, s, "sub") 3289 asm := c.mqtt.asm 3290 var i uint64 3291 for i = 0; i < 3; i++ { 3292 rf := &mqttRetainedMsgRef{sseq: i} 3293 asm.handleRetainedMsg("subject", rf, nil, false) 3294 } 3295 asm.handleRetainedMsgDel("subject", 2) 3296 if asm.sl.count > 0 { 3297 t.Fatalf("all retained messages subs should be removed, but %d still present", asm.sl.count) 3298 } 3299 } 3300 3301 func TestMQTTRetainedMsgMigration(t *testing.T) { 3302 o := testMQTTDefaultOptions() 3303 s := testMQTTRunServer(t, o) 3304 defer testMQTTShutdownServer(s) 3305 3306 nc, js := jsClientConnect(t, s) 3307 defer nc.Close() 3308 3309 // Create the retained messages stream to listen on the old subject first. 3310 // The server will correct this when the migration takes place. 3311 _, err := js.AddStream(&nats.StreamConfig{ 3312 Name: mqttRetainedMsgsStreamName, 3313 Subjects: []string{`$MQTT.rmsgs`}, 3314 Storage: nats.FileStorage, 3315 Retention: nats.LimitsPolicy, 3316 Replicas: 1, 3317 }) 3318 require_NoError(t, err) 3319 3320 // Publish some retained messages on the old "$MQTT.rmsgs" subject. 3321 const N = 100 3322 for i := 0; i < N; i++ { 3323 msg := fmt.Sprintf( 3324 `{"origin":"b5IQZNtG","subject":"test%d","topic":"test%d","msg":"YmFy","flags":1}`, i, i, 3325 ) 3326 _, err := js.Publish(`$MQTT.rmsgs`, []byte(msg)) 3327 require_NoError(t, err) 3328 } 3329 3330 // Check that the old subject looks right. 3331 si, err := js.StreamInfo(mqttRetainedMsgsStreamName, &nats.StreamInfoRequest{ 3332 SubjectsFilter: `$MQTT.>`, 3333 }) 3334 require_NoError(t, err) 3335 if si.State.NumSubjects != 1 { 3336 t.Fatalf("expected 1 subject, got %d", si.State.NumSubjects) 3337 } 3338 if n := si.State.Subjects[`$MQTT.rmsgs`]; n != N { 3339 t.Fatalf("expected to find %d messages on the original subject but found %d", N, n) 3340 } 3341 3342 // Create an MQTT client, this will cause a migration to take place. 3343 mc, rc := testMQTTConnect(t, &mqttConnInfo{clientID: "sub", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 3344 defer mc.Close() 3345 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, false) 3346 3347 testMQTTSub(t, 1, mc, rc, []*mqttFilter{{filter: "+", qos: 0}}, []byte{0}) 3348 topics := map[string]struct{}{} 3349 for i := 0; i < N; i++ { 3350 _, _, topic, _ := testMQTTGetPubMsgEx(t, mc, rc, _EMPTY_, []byte("bar")) 3351 topics[topic] = struct{}{} 3352 } 3353 if len(topics) != N { 3354 t.Fatalf("Unexpected topics: %v", topics) 3355 } 3356 3357 // Now look at the stream, there should be N messages on the new 3358 // divided subjects and none on the old undivided subject. 3359 si, err = js.StreamInfo(mqttRetainedMsgsStreamName, &nats.StreamInfoRequest{ 3360 SubjectsFilter: `$MQTT.>`, 3361 }) 3362 require_NoError(t, err) 3363 if si.State.NumSubjects != N { 3364 t.Fatalf("expected %d subjects, got %d", N, si.State.NumSubjects) 3365 } 3366 if n := si.State.Subjects[`$MQTT.rmsgs`]; n > 0 { 3367 t.Fatalf("expected to find no messages on the original subject but found %d", n) 3368 } 3369 3370 // Check that the message counts look right. There should be one 3371 // retained message per key. 3372 for i := 0; i < N; i++ { 3373 expected := fmt.Sprintf(`$MQTT.rmsgs.test%d`, i) 3374 n, ok := si.State.Subjects[expected] 3375 if !ok { 3376 t.Fatalf("expected to find %q but didn't", expected) 3377 } 3378 if n != 1 { 3379 t.Fatalf("expected %q to have 1 message but had %d", expected, n) 3380 } 3381 } 3382 } 3383 3384 func TestMQTTClusterReplicasCount(t *testing.T) { 3385 for _, test := range []struct { 3386 size int 3387 replicas int 3388 }{ 3389 {1, 1}, 3390 {2, 2}, 3391 {3, 3}, 3392 {5, 3}, 3393 } { 3394 t.Run(fmt.Sprintf("size %v", test.size), func(t *testing.T) { 3395 var s *Server 3396 var o *Options 3397 if test.size == 1 { 3398 o = testMQTTDefaultOptions() 3399 s = testMQTTRunServer(t, o) 3400 defer testMQTTShutdownServer(s) 3401 } else { 3402 cl := createJetStreamClusterWithTemplate(t, testMQTTGetClusterTemplaceNoLeaf(), "MQTT", test.size) 3403 defer cl.shutdown() 3404 o = cl.opts[0] 3405 s = cl.randomServer() 3406 } 3407 3408 mc, rc := testMQTTConnectRetry(t, &mqttConnInfo{clientID: "sub", cleanSess: false}, o.MQTT.Host, o.MQTT.Port, 5) 3409 defer mc.Close() 3410 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, false) 3411 testMQTTSub(t, 1, mc, rc, []*mqttFilter{{filter: "foo/#", qos: 1}}, []byte{1}) 3412 testMQTTFlush(t, mc, nil, rc) 3413 3414 nc := natsConnect(t, s.ClientURL()) 3415 defer nc.Close() 3416 3417 // Check the replicas of all MQTT streams 3418 js, err := nc.JetStream() 3419 if err != nil { 3420 t.Fatalf("Error getting js: %v", err) 3421 } 3422 for _, sname := range []string{ 3423 mqttStreamName, 3424 mqttRetainedMsgsStreamName, 3425 mqttSessStreamName, 3426 } { 3427 t.Run(sname, func(t *testing.T) { 3428 si, err := js.StreamInfo(sname) 3429 if err != nil { 3430 t.Fatalf("Error getting stream info: %v", err) 3431 } 3432 if si.Config.Replicas != test.replicas { 3433 t.Fatalf("Expected %v replicas, got %v", test.replicas, si.Config.Replicas) 3434 } 3435 }) 3436 } 3437 }) 3438 } 3439 } 3440 3441 func TestMQTTClusterCanCreateSessionWithOnServerDown(t *testing.T) { 3442 cl := createJetStreamClusterWithTemplate(t, testMQTTGetClusterTemplaceNoLeaf(), "MQTT", 3) 3443 defer cl.shutdown() 3444 o := cl.opts[0] 3445 3446 mc, rc := testMQTTConnectRetry(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port, 5) 3447 defer mc.Close() 3448 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, false) 3449 mc.Close() 3450 3451 // Shutdown one of the server. 3452 sd := cl.servers[1].StoreDir() 3453 defer os.RemoveAll(strings.TrimSuffix(sd, JetStreamStoreDir)) 3454 cl.servers[1].Shutdown() 3455 3456 // Make sure there is a meta leader 3457 cl.waitOnPeerCount(2) 3458 cl.waitOnLeader() 3459 3460 // Now try to create a new session. Since we use a single stream now for all sessions, 3461 // this should succeed. 3462 o = cl.opts[2] 3463 // We may still get failures because of some JS APIs may timeout while things 3464 // settle, so try again for a certain amount of times. 3465 mc, rc = testMQTTConnectRetry(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port, 5) 3466 defer mc.Close() 3467 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, false) 3468 } 3469 3470 func TestMQTTClusterPlacement(t *testing.T) { 3471 sc := createJetStreamSuperCluster(t, 3, 2) 3472 defer sc.shutdown() 3473 3474 c := sc.randomCluster() 3475 lnc := c.createLeafNodesWithTemplateAndStartPort(jsClusterTemplWithLeafAndMQTT, "SPOKE", 3, 22111) 3476 defer lnc.shutdown() 3477 3478 sc.waitOnPeerCount(9) 3479 sc.waitOnLeader() 3480 3481 for i := 0; i < 10; i++ { 3482 mc, rc := testMQTTConnectRetry(t, &mqttConnInfo{cleanSess: true}, lnc.opts[i%3].MQTT.Host, lnc.opts[i%3].MQTT.Port, 5) 3483 defer mc.Close() 3484 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, false) 3485 } 3486 3487 // Now check that MQTT assets have been created in the LEAF node's side, not the Hub. 3488 nc := natsConnect(t, lnc.servers[0].ClientURL()) 3489 defer nc.Close() 3490 js, err := nc.JetStream() 3491 if err != nil { 3492 t.Fatalf("Unable to get JetStream: %v", err) 3493 } 3494 count := 0 3495 for si := range js.StreamsInfo() { 3496 if si.Cluster == nil || si.Cluster.Name != "SPOKE" { 3497 t.Fatalf("Expected asset %q to be placed on spoke cluster, was placed on %+v", si.Config.Name, si.Cluster) 3498 } 3499 for _, repl := range si.Cluster.Replicas { 3500 if !strings.HasPrefix(repl.Name, "SPOKE-") { 3501 t.Fatalf("Replica on the wrong cluster: %+v", repl) 3502 } 3503 } 3504 if si.State.Consumers > 0 { 3505 for ci := range js.ConsumersInfo(si.Config.Name) { 3506 if ci.Cluster == nil || ci.Cluster.Name != "SPOKE" { 3507 t.Fatalf("Expected asset %q to be placed on spoke cluster, was placed on %+v", ci.Name, si.Cluster) 3508 } 3509 for _, repl := range ci.Cluster.Replicas { 3510 if !strings.HasPrefix(repl.Name, "SPOKE-") { 3511 t.Fatalf("Replica on the wrong cluster: %+v", repl) 3512 } 3513 } 3514 } 3515 } 3516 count++ 3517 } 3518 if count == 0 { 3519 t.Fatal("No stream found!") 3520 } 3521 } 3522 3523 func TestMQTTLeafnodeWithoutJSToClusterWithJSNoSharedSysAcc(t *testing.T) { 3524 test := func(t *testing.T, resolution int) { 3525 getClusterOpts := func(name string, i int) *Options { 3526 o := testMQTTDefaultOptions() 3527 o.ServerName = name 3528 o.Cluster.Name = "hub" 3529 // first two test cases rely on domain not being set in hub 3530 if resolution > 1 { 3531 o.JetStreamDomain = "DOMAIN" 3532 } 3533 o.Cluster.Host = "127.0.0.1" 3534 o.Cluster.Port = 2790 + i 3535 o.Routes = RoutesFromStr("nats://127.0.0.1:2791,nats://127.0.0.1:2792,nats://127.0.0.1:2793") 3536 o.LeafNode.Host = "127.0.0.1" 3537 o.LeafNode.Port = -1 3538 return o 3539 } 3540 o1 := getClusterOpts("S1", 1) 3541 s1 := testMQTTRunServer(t, o1) 3542 defer testMQTTShutdownServer(s1) 3543 3544 o2 := getClusterOpts("S2", 2) 3545 s2 := testMQTTRunServer(t, o2) 3546 defer testMQTTShutdownServer(s2) 3547 3548 o3 := getClusterOpts("S3", 3) 3549 s3 := testMQTTRunServer(t, o3) 3550 defer testMQTTShutdownServer(s3) 3551 3552 cluster := []*Server{s1, s2, s3} 3553 checkClusterFormed(t, cluster...) 3554 checkFor(t, 10*time.Second, 50*time.Millisecond, func() error { 3555 for _, s := range cluster { 3556 if s.JetStreamIsLeader() { 3557 // Need to wait for usage updates now to propagate to meta leader. 3558 if len(s.JetStreamClusterPeers()) == len(cluster) { 3559 time.Sleep(100 * time.Millisecond) 3560 return nil 3561 } 3562 } 3563 } 3564 return fmt.Errorf("no leader yet") 3565 }) 3566 3567 // Now define a leafnode that has mqtt enabled, but no JS. This should still work. 3568 lno := testMQTTDefaultOptions() 3569 // Make sure jetstream is not explicitly defined here. 3570 lno.JetStream = false 3571 switch resolution { 3572 case 0: 3573 // turn off jetstream in $G by adding another account and set mqtt domain option and set account default 3574 lno.Accounts = append(lno.Accounts, NewAccount("unused-account")) 3575 fallthrough 3576 case 1: 3577 lno.JsAccDefaultDomain = map[string]string{"$G": ""} 3578 case 2: 3579 lno.JsAccDefaultDomain = map[string]string{"$G": o1.JetStreamDomain} 3580 case 3: 3581 // turn off jetstream in $G by adding another account and set mqtt domain option 3582 lno.Accounts = append(lno.Accounts, NewAccount("unused-account")) 3583 fallthrough 3584 case 4: 3585 // actual solution 3586 lno.MQTT.JsDomain = o1.JetStreamDomain 3587 case 5: 3588 // set per account overwrite and disable js in $G 3589 lno.Accounts = append(lno.Accounts, NewAccount("unused-account")) 3590 lno.JsAccDefaultDomain = map[string]string{ 3591 "$G": o1.JetStreamDomain, 3592 } 3593 } 3594 // Whenever an account was added to disable JS in $G, enable it in the server 3595 if len(lno.Accounts) > 0 { 3596 lno.JetStream = true 3597 lno.JetStreamDomain = "OTHER" 3598 lno.StoreDir = t.TempDir() 3599 } 3600 3601 // Use RoutesFromStr() to make an array of urls 3602 urls := RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d,nats://127.0.0.1:%d,nats://127.0.0.1:%d", 3603 o1.LeafNode.Port, o2.LeafNode.Port, o3.LeafNode.Port)) 3604 lno.LeafNode.Remotes = []*RemoteLeafOpts{{URLs: urls}} 3605 3606 ln := RunServer(lno) 3607 defer testMQTTShutdownServer(ln) 3608 3609 checkLeafNodeConnected(t, ln) 3610 3611 // Now connect to leafnode and subscribe 3612 mc, rc := testMQTTConnectRetry(t, &mqttConnInfo{clientID: "sub", cleanSess: true}, lno.MQTT.Host, lno.MQTT.Port, 5) 3613 defer mc.Close() 3614 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, false) 3615 testMQTTSub(t, 1, mc, rc, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 3616 testMQTTFlush(t, mc, nil, rc) 3617 3618 connectAndPublish := func(o *Options) { 3619 mp, rp := testMQTTConnectRetry(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port, 5) 3620 defer mp.Close() 3621 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 3622 3623 testMQTTPublish(t, mp, rp, 1, false, false, "foo", 1, []byte("msg")) 3624 } 3625 // Connect a publisher from leafnode and publish, verify message is received. 3626 connectAndPublish(lno) 3627 testMQTTCheckPubMsg(t, mc, rc, "foo", mqttPubQos1, []byte("msg")) 3628 3629 // Connect from one server in the cluster check it works from there too. 3630 connectAndPublish(o3) 3631 testMQTTCheckPubMsg(t, mc, rc, "foo", mqttPubQos1, []byte("msg")) 3632 3633 // Connect from a server in the hub and subscribe 3634 mc2, rc2 := testMQTTConnectRetry(t, &mqttConnInfo{clientID: "sub2", cleanSess: true}, o2.MQTT.Host, o2.MQTT.Port, 5) 3635 defer mc2.Close() 3636 testMQTTCheckConnAck(t, rc2, mqttConnAckRCConnectionAccepted, false) 3637 testMQTTSub(t, 1, mc2, rc2, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 3638 testMQTTFlush(t, mc2, nil, rc2) 3639 3640 // Connect a publisher from leafnode and publish, verify message is received. 3641 connectAndPublish(lno) 3642 testMQTTCheckPubMsg(t, mc2, rc2, "foo", mqttPubQos1, []byte("msg")) 3643 3644 // Connect from one server in the cluster check it works from there too. 3645 connectAndPublish(o1) 3646 testMQTTCheckPubMsg(t, mc2, rc2, "foo", mqttPubQos1, []byte("msg")) 3647 } 3648 t.Run("backwards-compatibility-default-js-enabled-in-leaf", func(t *testing.T) { 3649 test(t, 0) // test with JsAccDefaultDomain set to default (pointing at hub) but jetstream enabled in leaf node too 3650 }) 3651 t.Run("backwards-compatibility-default-js-disabled-in-leaf", func(t *testing.T) { 3652 // test with JsAccDefaultDomain set. Checks if it works with backwards compatibility code for empty domain 3653 test(t, 1) 3654 }) 3655 t.Run("backwards-compatibility-domain-js-disabled-in-leaf", func(t *testing.T) { 3656 // test with JsAccDefaultDomain set. Checks if it works with backwards compatibility code for domain set 3657 test(t, 2) // test with domain set in mqtt client 3658 }) 3659 t.Run("mqtt-explicit-js-enabled-in-leaf", func(t *testing.T) { 3660 test(t, 3) // test with domain set in mqtt client (pointing at hub) but jetstream enabled in leaf node too 3661 }) 3662 t.Run("mqtt-explicit-js-disabled-in-leaf", func(t *testing.T) { 3663 test(t, 4) // test with domain set in mqtt client 3664 }) 3665 t.Run("backwards-compatibility-domain-js-enabled-in-leaf", func(t *testing.T) { 3666 test(t, 5) // test with JsAccDefaultDomain set to domain (pointing at hub) but jetstream enabled in leaf node too 3667 }) 3668 } 3669 3670 func TestMQTTImportExport(t *testing.T) { 3671 conf := createConfFile(t, []byte(fmt.Sprintf(` 3672 listen: "127.0.0.1:-1" 3673 server_name: "mqtt" 3674 jetstream { 3675 store_dir = %q 3676 } 3677 accounts { 3678 org { 3679 jetstream: enabled 3680 users: [{user: org, password: pwd}] 3681 imports = [{stream: {account: "device", subject: "foo"}, prefix: "org"}] 3682 } 3683 device { 3684 users: [{user: device, password: pwd}] 3685 exports = [{stream: "foo"}] 3686 } 3687 } 3688 mqtt { 3689 listen: "127.0.0.1:-1" 3690 } 3691 no_auth_user: device 3692 `, t.TempDir()))) 3693 defer os.Remove(conf) 3694 3695 s, o := RunServerWithConfig(conf) 3696 defer s.Shutdown() 3697 3698 mc1, rc1 := testMQTTConnect(t, &mqttConnInfo{clientID: "sub1", user: "org", pass: "pwd", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 3699 defer mc1.Close() 3700 testMQTTCheckConnAck(t, rc1, mqttConnAckRCConnectionAccepted, false) 3701 testMQTTSub(t, 1, mc1, rc1, []*mqttFilter{{filter: "org/foo", qos: 0}}, []byte{0}) 3702 testMQTTFlush(t, mc1, nil, rc1) 3703 3704 mc2, rc2 := testMQTTConnect(t, &mqttConnInfo{clientID: "sub2", user: "org", pass: "pwd", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 3705 defer mc2.Close() 3706 testMQTTCheckConnAck(t, rc2, mqttConnAckRCConnectionAccepted, false) 3707 testMQTTSub(t, 1, mc2, rc2, []*mqttFilter{{filter: "org/foo", qos: 1}}, []byte{1}) 3708 testMQTTFlush(t, mc2, nil, rc2) 3709 3710 nc := natsConnect(t, s.ClientURL()) 3711 defer nc.Close() 3712 natsPub(t, nc, "foo", []byte("msg")) 3713 3714 // Verify message is received on receiver side. 3715 testMQTTCheckPubMsg(t, mc1, rc1, "org/foo", 0, []byte("msg")) 3716 testMQTTCheckPubMsg(t, mc2, rc2, "org/foo", 0, []byte("msg")) 3717 } 3718 3719 func TestMQTTSessionMovingDomains(t *testing.T) { 3720 tmpl := strings.Replace(jsClusterTemplWithLeafAndMQTT, "{{leaf}}", `leafnodes { listen: 127.0.0.1:-1 }`, 1) 3721 tmpl = strings.Replace(tmpl, "store_dir:", "domain: HUB, store_dir:", 1) 3722 c := createJetStreamCluster(t, tmpl, "HUB", _EMPTY_, 3, 22020, true) 3723 defer c.shutdown() 3724 c.waitOnLeader() 3725 3726 tmpl = strings.Replace(jsClusterTemplWithLeafAndMQTT, "store_dir:", "domain: SPOKE, store_dir:", 1) 3727 lnc := c.createLeafNodesWithTemplateAndStartPort(tmpl, "SPOKE", 3, 22111) 3728 defer lnc.shutdown() 3729 lnc.waitOnPeerCount(3) 3730 3731 connectSubAndDisconnect := func(host string, port int, present bool) { 3732 t.Helper() 3733 mc, rc := testMQTTConnectRetry(t, &mqttConnInfo{clientID: "sub", cleanSess: false}, host, port, 5) 3734 defer mc.Close() 3735 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, present) 3736 testMQTTSub(t, 1, mc, rc, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 3737 testMQTTFlush(t, mc, nil, rc) 3738 testMQTTDisconnect(t, mc, nil) 3739 } 3740 3741 // Create a session on the HUB. Make sure we don't use "clean" session so that 3742 // it is not removed when the client connection closes. 3743 for i := 0; i < 7; i++ { 3744 var present bool 3745 if i > 0 { 3746 present = true 3747 } 3748 connectSubAndDisconnect(c.opts[0].MQTT.Host, c.opts[0].MQTT.Port, present) 3749 } 3750 3751 // Now move to the SPOKE cluster, this is a brand new session there, so should not be present. 3752 connectSubAndDisconnect(lnc.opts[1].MQTT.Host, lnc.opts[1].MQTT.Port, false) 3753 3754 // Move back to HUB cluster. Make it interesting by connecting to a different 3755 // server in that cluster. This should work, and present flag should be true. 3756 connectSubAndDisconnect(c.opts[2].MQTT.Host, c.opts[2].MQTT.Port, true) 3757 } 3758 3759 type remoteConnSameClientIDLogger struct { 3760 DummyLogger 3761 warn chan string 3762 } 3763 3764 func (l *remoteConnSameClientIDLogger) Warnf(format string, args ...any) { 3765 msg := fmt.Sprintf(format, args...) 3766 if strings.Contains(msg, "remote connection has started with the same client ID") { 3767 l.warn <- msg 3768 } 3769 } 3770 3771 func TestMQTTSessionsDifferentDomains(t *testing.T) { 3772 tmpl := strings.Replace(jsClusterTemplWithLeafAndMQTT, "{{leaf}}", `leafnodes { listen: 127.0.0.1:-1 }`, 1) 3773 c := createJetStreamCluster(t, tmpl, "HUB", _EMPTY_, 3, 22020, true) 3774 defer c.shutdown() 3775 c.waitOnLeader() 3776 3777 tmpl = strings.Replace(jsClusterTemplWithLeafAndMQTT, "store_dir:", "domain: LEAF1, store_dir:", 1) 3778 lnc1 := c.createLeafNodesWithTemplateAndStartPort(tmpl, "LEAF1", 2, 22111) 3779 defer lnc1.shutdown() 3780 lnc1.waitOnPeerCount(2) 3781 3782 l := &remoteConnSameClientIDLogger{warn: make(chan string, 10)} 3783 lnc1.servers[0].SetLogger(l, false, false) 3784 3785 tmpl = strings.Replace(jsClusterTemplWithLeafAndMQTT, "store_dir:", "domain: LEAF2, store_dir:", 1) 3786 lnc2 := c.createLeafNodesWithTemplateAndStartPort(tmpl, "LEAF2", 2, 23111) 3787 defer lnc2.shutdown() 3788 lnc2.waitOnPeerCount(2) 3789 3790 o := &(lnc1.opts[0].MQTT) 3791 mc1, rc1 := testMQTTConnectRetry(t, &mqttConnInfo{clientID: "sub", cleanSess: false}, o.Host, o.Port, 5) 3792 defer mc1.Close() 3793 testMQTTCheckConnAck(t, rc1, mqttConnAckRCConnectionAccepted, false) 3794 testMQTTSub(t, 1, mc1, rc1, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 3795 testMQTTFlush(t, mc1, nil, rc1) 3796 3797 o = &(lnc2.opts[0].MQTT) 3798 connectSubAndDisconnect := func(host string, port int, present bool) { 3799 t.Helper() 3800 mc, rc := testMQTTConnectRetry(t, &mqttConnInfo{clientID: "sub", cleanSess: false}, host, port, 5) 3801 defer mc.Close() 3802 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, present) 3803 testMQTTSub(t, 1, mc, rc, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 3804 testMQTTFlush(t, mc, nil, rc) 3805 testMQTTDisconnect(t, mc, nil) 3806 } 3807 3808 for i := 0; i < 2; i++ { 3809 connectSubAndDisconnect(o.Host, o.Port, i > 0) 3810 } 3811 3812 select { 3813 case w := <-l.warn: 3814 t.Fatalf("Got a warning: %v", w) 3815 case <-time.After(500 * time.Millisecond): 3816 // OK 3817 } 3818 } 3819 3820 func TestMQTTParseUnsub(t *testing.T) { 3821 for _, test := range []struct { 3822 name string 3823 proto []byte 3824 b byte 3825 pl int 3826 err string 3827 }{ 3828 {"reserved flag", nil, 3, 0, "wrong unsubscribe reserved flags"}, 3829 {"ensure packet loaded", []byte{1, 2}, mqttUnsubscribeFlags, 10, io.ErrUnexpectedEOF.Error()}, 3830 {"error reading packet id", []byte{1}, mqttUnsubscribeFlags, 1, "reading packet identifier"}, 3831 {"missing filters", []byte{0, 1}, mqttUnsubscribeFlags, 2, "subscribe protocol must contain at least 1 topic filter"}, 3832 {"error reading topic", []byte{0, 1, 0, 2, 'a'}, mqttUnsubscribeFlags, 5, "topic filter"}, 3833 {"empty topic", []byte{0, 1, 0, 0}, mqttUnsubscribeFlags, 4, errMQTTTopicFilterCannotBeEmpty.Error()}, 3834 {"invalid utf8 topic", []byte{0, 1, 0, 1, 241}, mqttUnsubscribeFlags, 5, "invalid utf8 for topic filter"}, 3835 } { 3836 t.Run(test.name, func(t *testing.T) { 3837 r := &mqttReader{} 3838 r.reset(test.proto) 3839 mqtt := &mqtt{r: r} 3840 c := &client{mqtt: mqtt} 3841 if _, _, err := c.mqttParseSubsOrUnsubs(r, test.b, test.pl, false); err == nil || !strings.Contains(err.Error(), test.err) { 3842 t.Fatalf("Expected error %q, got %v", test.err, err) 3843 } 3844 }) 3845 } 3846 } 3847 3848 func testMQTTUnsub(t *testing.T, pi uint16, c net.Conn, r *mqttReader, filters []*mqttFilter) { 3849 t.Helper() 3850 w := newMQTTWriter(0) 3851 pkLen := 2 // for pi 3852 for i := 0; i < len(filters); i++ { 3853 f := filters[i] 3854 pkLen += 2 + len(f.filter) 3855 } 3856 w.WriteByte(mqttPacketUnsub | mqttUnsubscribeFlags) 3857 w.WriteVarInt(pkLen) 3858 w.WriteUint16(pi) 3859 for i := 0; i < len(filters); i++ { 3860 f := filters[i] 3861 w.WriteBytes([]byte(f.filter)) 3862 } 3863 if _, err := testMQTTWrite(c, w.Bytes()); err != nil { 3864 t.Fatalf("Error writing UNSUBSCRIBE protocol: %v", err) 3865 } 3866 b, _ := testMQTTReadPacket(t, r) 3867 if pt := b & mqttPacketMask; pt != mqttPacketUnsubAck { 3868 t.Fatalf("Expected UNSUBACK packet %x, got %x", mqttPacketUnsubAck, pt) 3869 } 3870 rpi, err := r.readUint16("packet identifier") 3871 if err != nil || rpi != pi { 3872 t.Fatalf("Error with packet identifier expected=%v got: %v err=%v", pi, rpi, err) 3873 } 3874 } 3875 3876 func TestMQTTUnsub(t *testing.T) { 3877 o := testMQTTDefaultOptions() 3878 s := testMQTTRunServer(t, o) 3879 defer testMQTTShutdownServer(s) 3880 3881 mcp, mpr := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 3882 defer mcp.Close() 3883 testMQTTCheckConnAck(t, mpr, mqttConnAckRCConnectionAccepted, false) 3884 3885 mc, r := testMQTTConnect(t, &mqttConnInfo{user: "sub", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 3886 defer mc.Close() 3887 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 3888 3889 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo", qos: 0}}, []byte{0}) 3890 testMQTTFlush(t, mc, nil, r) 3891 3892 // Publish and test msg received 3893 testMQTTPublish(t, mcp, r, 0, false, false, "foo", 0, []byte("msg")) 3894 testMQTTCheckPubMsg(t, mc, r, "foo", 0, []byte("msg")) 3895 3896 // Unsubscribe 3897 testMQTTUnsub(t, 1, mc, r, []*mqttFilter{{filter: "foo"}}) 3898 3899 // Publish and test msg not received 3900 testMQTTPublish(t, mcp, r, 0, false, false, "foo", 0, []byte("msg")) 3901 testMQTTExpectNothing(t, r) 3902 3903 // Use of wildcards subs 3904 filters := []*mqttFilter{ 3905 {filter: "foo/bar", qos: 0}, 3906 {filter: "foo/#", qos: 0}, 3907 } 3908 testMQTTSub(t, 1, mc, r, filters, []byte{0, 0}) 3909 testMQTTFlush(t, mc, nil, r) 3910 3911 // Publish and check that message received twice 3912 testMQTTPublish(t, mcp, r, 0, false, false, "foo/bar", 0, []byte("msg")) 3913 testMQTTCheckPubMsg(t, mc, r, "foo/bar", 0, []byte("msg")) 3914 testMQTTCheckPubMsg(t, mc, r, "foo/bar", 0, []byte("msg")) 3915 3916 // Unsub the wildcard one 3917 testMQTTUnsub(t, 1, mc, r, []*mqttFilter{{filter: "foo/#"}}) 3918 // Publish and check that message received once 3919 testMQTTPublish(t, mcp, r, 0, false, false, "foo/bar", 0, []byte("msg")) 3920 testMQTTCheckPubMsg(t, mc, r, "foo/bar", 0, []byte("msg")) 3921 testMQTTExpectNothing(t, r) 3922 3923 // Unsub last 3924 testMQTTUnsub(t, 1, mc, r, []*mqttFilter{{filter: "foo/bar"}}) 3925 // Publish and test msg not received 3926 testMQTTPublish(t, mcp, r, 0, false, false, "foo/bar", 0, []byte("msg")) 3927 testMQTTExpectNothing(t, r) 3928 } 3929 3930 func testMQTTExpectDisconnect(t testing.TB, c net.Conn) { 3931 t.Helper() 3932 if buf, err := testMQTTRead(c); err == nil { 3933 t.Fatalf("Expected connection to be disconnected, got %s", buf) 3934 } 3935 } 3936 3937 func TestMQTTPublishTopicErrors(t *testing.T) { 3938 o := testMQTTDefaultOptions() 3939 s := testMQTTRunServer(t, o) 3940 defer testMQTTShutdownServer(s) 3941 3942 for _, test := range []struct { 3943 name string 3944 topic string 3945 }{ 3946 {"empty", ""}, 3947 {"with single level wildcard", "foo/+"}, 3948 {"with multiple level wildcard", "foo/#"}, 3949 } { 3950 t.Run(test.name, func(t *testing.T) { 3951 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 3952 defer mc.Close() 3953 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 3954 3955 testMQTTPublish(t, mc, r, 0, false, false, test.topic, 0, []byte("msg")) 3956 testMQTTExpectDisconnect(t, mc) 3957 }) 3958 } 3959 } 3960 3961 func testMQTTDisconnect(t testing.TB, c net.Conn, bw *bufio.Writer) { 3962 t.Helper() 3963 testMQTTDisconnectEx(t, c, bw, true) 3964 } 3965 3966 func testMQTTDisconnectEx(t testing.TB, c net.Conn, bw *bufio.Writer, wait bool) { 3967 t.Helper() 3968 w := newMQTTWriter(0) 3969 w.WriteByte(mqttPacketDisconnect) 3970 w.WriteByte(0) 3971 if bw != nil { 3972 bw.Write(w.Bytes()) 3973 bw.Flush() 3974 } else { 3975 c.Write(w.Bytes()) 3976 } 3977 if wait { 3978 testMQTTExpectDisconnect(t, c) 3979 } 3980 } 3981 3982 func TestMQTTWill(t *testing.T) { 3983 o := testMQTTDefaultOptions() 3984 s := testMQTTRunServer(t, o) 3985 defer testMQTTShutdownServer(s) 3986 3987 nc := natsConnect(t, s.ClientURL()) 3988 defer nc.Close() 3989 3990 sub := natsSubSync(t, nc, "will.topic") 3991 natsFlush(t, nc) 3992 3993 willMsg := []byte("bye") 3994 3995 for _, test := range []struct { 3996 name string 3997 willExpected bool 3998 willQoS byte 3999 }{ 4000 {"will qos 0", true, 0}, 4001 {"will qos 1", true, 1}, 4002 {"will qos 2", true, 2}, 4003 {"proper disconnect no will", false, 0}, 4004 } { 4005 t.Run(test.name, func(t *testing.T) { 4006 mcs, rs := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 4007 defer mcs.Close() 4008 testMQTTCheckConnAck(t, rs, mqttConnAckRCConnectionAccepted, false) 4009 4010 testMQTTSub(t, 1, mcs, rs, []*mqttFilter{{filter: "will/#", qos: 2}}, []byte{2}) 4011 testMQTTFlush(t, mcs, nil, rs) 4012 4013 mc, r := testMQTTConnect(t, 4014 &mqttConnInfo{ 4015 cleanSess: true, 4016 will: &mqttWill{ 4017 topic: []byte("will/topic"), 4018 message: willMsg, 4019 qos: test.willQoS, 4020 }, 4021 }, o.MQTT.Host, o.MQTT.Port) 4022 defer mc.Close() 4023 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4024 4025 if test.willExpected { 4026 mc.Close() 4027 testMQTTCheckPubMsg(t, mcs, rs, "will/topic", test.willQoS<<1, willMsg) 4028 wm := natsNexMsg(t, sub, time.Second) 4029 if !bytes.Equal(wm.Data, willMsg) { 4030 t.Fatalf("Expected will message to be %q, got %q", willMsg, wm.Data) 4031 } 4032 } else { 4033 testMQTTDisconnect(t, mc, nil) 4034 testMQTTExpectNothing(t, rs) 4035 if wm, err := sub.NextMsg(100 * time.Millisecond); err == nil { 4036 t.Fatalf("Should not have receive a message, got subj=%q data=%q", 4037 wm.Subject, wm.Data) 4038 } 4039 } 4040 }) 4041 } 4042 } 4043 4044 func TestMQTTQoS2WillReject(t *testing.T) { 4045 o := testMQTTDefaultOptions() 4046 o.MQTT.rejectQoS2Pub = true 4047 s := testMQTTRunServer(t, o) 4048 defer testMQTTShutdownServer(s) 4049 4050 mcs, rs := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 4051 defer mcs.Close() 4052 testMQTTCheckConnAck(t, rs, mqttConnAckRCConnectionAccepted, false) 4053 4054 testMQTTSub(t, 1, mcs, rs, []*mqttFilter{{filter: "will/#", qos: 2}}, []byte{2}) 4055 testMQTTFlush(t, mcs, nil, rs) 4056 4057 mc, r := testMQTTConnect(t, 4058 &mqttConnInfo{ 4059 cleanSess: true, 4060 will: &mqttWill{ 4061 topic: []byte("will/topic"), 4062 message: []byte("bye"), 4063 qos: 2, 4064 }, 4065 }, o.MQTT.Host, o.MQTT.Port) 4066 defer mc.Close() 4067 testMQTTCheckConnAck(t, r, mqttConnAckRCQoS2WillRejected, false) 4068 } 4069 4070 func TestMQTTWillRetain(t *testing.T) { 4071 for _, test := range []struct { 4072 name string 4073 pubQoS byte 4074 subQoS byte 4075 }{ 4076 {"pub QoS0 sub QoS0", 0, 0}, 4077 {"pub QoS0 sub QoS1", 0, 1}, 4078 {"pub QoS1 sub QoS0", 1, 0}, 4079 {"pub QoS1 sub QoS1", 1, 1}, 4080 } { 4081 t.Run(test.name, func(t *testing.T) { 4082 o := testMQTTDefaultOptions() 4083 s := testMQTTRunServer(t, o) 4084 defer testMQTTShutdownServer(s) 4085 4086 mces, res := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 4087 defer mces.Close() 4088 testMQTTCheckConnAck(t, res, mqttConnAckRCConnectionAccepted, false) 4089 testMQTTSub(t, 1, mces, res, []*mqttFilter{{filter: "will/#", qos: test.subQoS}}, []byte{test.subQoS}) 4090 4091 willTopic := []byte("will/topic") 4092 willMsg := []byte("bye") 4093 4094 mc, r := testMQTTConnect(t, 4095 &mqttConnInfo{ 4096 cleanSess: true, 4097 will: &mqttWill{ 4098 topic: willTopic, 4099 message: willMsg, 4100 qos: test.pubQoS, 4101 retain: true, 4102 }, 4103 }, o.MQTT.Host, o.MQTT.Port) 4104 defer mc.Close() 4105 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4106 4107 // Disconnect the client 4108 mc.Close() 4109 4110 // Wait for the server to process the connection close, which will 4111 // cause the "will" message to be published (and retained). 4112 checkClientsCount(t, s, 1) 4113 4114 // Create subscription on will topic and expect will message. 4115 mcs, rs := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 4116 defer mcs.Close() 4117 testMQTTCheckConnAck(t, rs, mqttConnAckRCConnectionAccepted, false) 4118 4119 testMQTTSub(t, 1, mcs, rs, []*mqttFilter{{filter: "will/#", qos: test.subQoS}}, []byte{test.subQoS}) 4120 pflags, _ := testMQTTGetPubMsg(t, mcs, rs, "will/topic", willMsg) 4121 if !mqttIsRetained(pflags) { 4122 t.Fatalf("expected retain flag to be set, it was not: %v", pflags) 4123 } 4124 // Expected QoS will be the lesser of the pub/sub QoS. 4125 expectedQoS := test.pubQoS 4126 if test.subQoS == 0 { 4127 expectedQoS = 0 4128 } 4129 if qos := mqttGetQoS(pflags); qos != expectedQoS { 4130 t.Fatalf("expected qos to be %v, got %v", expectedQoS, qos) 4131 } 4132 4133 // The existing subscription (prior to sending the will) should receive 4134 // the will but the retain flag should not be set. 4135 pflags, _ = testMQTTGetPubMsg(t, mces, res, "will/topic", willMsg) 4136 if mqttIsRetained(pflags) { 4137 t.Fatalf("expected retain flag to not be set, it was: %v", pflags) 4138 } 4139 // Expected QoS will be the lesser of the pub/sub QoS. 4140 if qos := mqttGetQoS(pflags); qos != expectedQoS { 4141 t.Fatalf("expected qos to be %v, got %v", expectedQoS, qos) 4142 } 4143 }) 4144 } 4145 } 4146 4147 func TestMQTTWillRetainPermViolation(t *testing.T) { 4148 template := ` 4149 port: -1 4150 jetstream { 4151 store_dir = %q 4152 } 4153 server_name: mqtt 4154 authorization { 4155 mqtt_perms = { 4156 publish = ["%s"] 4157 subscribe = ["foo", "bar", "$MQTT.sub.>"] 4158 } 4159 users = [ 4160 {user: mqtt, password: pass, permissions: $mqtt_perms} 4161 ] 4162 } 4163 mqtt { 4164 port: -1 4165 } 4166 ` 4167 tdir := t.TempDir() 4168 conf := createConfFile(t, []byte(fmt.Sprintf(template, tdir, "foo"))) 4169 4170 s, o := RunServerWithConfig(conf) 4171 defer testMQTTShutdownServer(s) 4172 4173 ci := &mqttConnInfo{ 4174 cleanSess: true, 4175 user: "mqtt", 4176 pass: "pass", 4177 } 4178 4179 // We create first a connection with the Will topic that the publisher 4180 // is allowed to publish to. 4181 ci.will = &mqttWill{ 4182 topic: []byte("foo"), 4183 message: []byte("bye"), 4184 qos: 1, 4185 retain: true, 4186 } 4187 mc, r := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4188 defer mc.Close() 4189 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4190 4191 // Disconnect, which will cause the Will to be sent with retain flag. 4192 mc.Close() 4193 4194 // Wait for the server to process the connection close, which will 4195 // cause the "will" message to be published (and retained). 4196 checkClientsCount(t, s, 0) 4197 4198 // Create a subscription on the Will subject and we should receive it. 4199 ci.will = nil 4200 mcs, rs := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4201 defer mcs.Close() 4202 testMQTTCheckConnAck(t, rs, mqttConnAckRCConnectionAccepted, false) 4203 4204 testMQTTSub(t, 1, mcs, rs, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 4205 pflags, _ := testMQTTGetPubMsg(t, mcs, rs, "foo", []byte("bye")) 4206 if !mqttIsRetained(pflags) { 4207 t.Fatalf("expected retain flag to be set, it was not: %v", pflags) 4208 } 4209 if qos := mqttGetQoS(pflags); qos != 1 { 4210 t.Fatalf("expected qos to be 1, got %v", qos) 4211 } 4212 testMQTTDisconnect(t, mcs, nil) 4213 4214 // Now create another connection with a Will that client is not allowed to publish to. 4215 ci.will = &mqttWill{ 4216 topic: []byte("bar"), 4217 message: []byte("bye"), 4218 qos: 1, 4219 retain: true, 4220 } 4221 mc, r = testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4222 defer mc.Close() 4223 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4224 4225 // Disconnect, to cause Will to be produced, but in that case should not be stored 4226 // since user not allowed to publish on "bar". 4227 mc.Close() 4228 4229 // Wait for the server to process the connection close, which will 4230 // cause the "will" message to be published (and retained). 4231 checkClientsCount(t, s, 0) 4232 4233 // Create sub on "bar" which user is allowed to subscribe to. 4234 ci.will = nil 4235 mcs, rs = testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4236 defer mcs.Close() 4237 testMQTTCheckConnAck(t, rs, mqttConnAckRCConnectionAccepted, false) 4238 4239 testMQTTSub(t, 1, mcs, rs, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 4240 // No Will should be published since it should not have been stored in the first place. 4241 testMQTTExpectNothing(t, rs) 4242 testMQTTDisconnect(t, mcs, nil) 4243 4244 // Now remove permission to publish on "foo" and check that a new subscription 4245 // on "foo" is now not getting the will message because the original user no 4246 // longer has permission to do so. 4247 reloadUpdateConfig(t, s, conf, fmt.Sprintf(template, tdir, "baz")) 4248 4249 mcs, rs = testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4250 defer mcs.Close() 4251 testMQTTCheckConnAck(t, rs, mqttConnAckRCConnectionAccepted, false) 4252 4253 testMQTTSub(t, 1, mcs, rs, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 4254 testMQTTExpectNothing(t, rs) 4255 testMQTTDisconnect(t, mcs, nil) 4256 } 4257 4258 func TestMQTTPublishRetain(t *testing.T) { 4259 o := testMQTTDefaultOptions() 4260 s := testMQTTRunServer(t, o) 4261 defer testMQTTShutdownServer(s) 4262 4263 buf := strings.Builder{} 4264 for i := 0; i < 128; i++ { // 128Kb 4265 for j := 0; j < 64; j++ { // 16 * 64 = 1Kb 4266 buf.Write([]byte("0123456789abcdef")) 4267 } 4268 } 4269 large := buf.String() 4270 4271 for _, test := range []struct { 4272 name string 4273 retained bool 4274 sentValue string 4275 expectedValue string 4276 subGetsIt bool 4277 }{ 4278 {"publish large retained", true, large, large, true}, 4279 {"publish retained", true, "retained", "retained", true}, 4280 {"publish not retained", false, "not retained", "retained", true}, 4281 {"remove retained", true, "", "", false}, 4282 } { 4283 t.Run(test.name, func(t *testing.T) { 4284 mc1, rs1 := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 4285 defer mc1.Close() 4286 testMQTTCheckConnAck(t, rs1, mqttConnAckRCConnectionAccepted, false) 4287 testMQTTPublish(t, mc1, rs1, 0, false, test.retained, "foo", 0, []byte(test.sentValue)) 4288 testMQTTFlush(t, mc1, nil, rs1) 4289 4290 mc2, rs2 := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 4291 defer mc2.Close() 4292 testMQTTCheckConnAck(t, rs2, mqttConnAckRCConnectionAccepted, false) 4293 4294 testMQTTSub(t, 1, mc2, rs2, []*mqttFilter{{filter: "foo/#", qos: 1}}, []byte{1}) 4295 4296 if test.subGetsIt { 4297 pflags, _ := testMQTTGetPubMsg(t, mc2, rs2, "foo", []byte(test.expectedValue)) 4298 if !mqttIsRetained(pflags) { 4299 t.Fatalf("retain flag should have been set, it was not: flags=%v", pflags) 4300 } 4301 } else { 4302 testMQTTExpectNothing(t, rs2) 4303 } 4304 4305 testMQTTDisconnect(t, mc1, nil) 4306 testMQTTDisconnect(t, mc2, nil) 4307 }) 4308 } 4309 } 4310 4311 func TestMQTTQoS2RetainedReject(t *testing.T) { 4312 // Start the server with QOS2 enabled, and submit retained messages with QoS 4313 // 1 and 2. 4314 o := testMQTTDefaultOptions() 4315 s := testMQTTRunServer(t, o) 4316 mc1, rs1 := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 4317 testMQTTCheckConnAck(t, rs1, mqttConnAckRCConnectionAccepted, false) 4318 testMQTTPublish(t, mc1, rs1, 2, false, true, "foo", 1, []byte("qos2 failed")) 4319 testMQTTPublish(t, mc1, rs1, 1, false, true, "bar", 2, []byte("qos1 retained")) 4320 testMQTTFlush(t, mc1, nil, rs1) 4321 testMQTTDisconnect(t, mc1, nil) 4322 mc1.Close() 4323 s.Shutdown() 4324 4325 // Restart the server with QOS2 disabled; we should be using the same 4326 // JetStream store, so the retained message should still be there. 4327 o.MQTT.rejectQoS2Pub = true 4328 s = testMQTTRunServer(t, o) 4329 defer testMQTTShutdownServer(s) 4330 4331 mc2, rs2 := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 4332 defer mc2.Close() 4333 testMQTTCheckConnAck(t, rs2, mqttConnAckRCConnectionAccepted, false) 4334 4335 testMQTTSub(t, 1, mc2, rs2, []*mqttFilter{{filter: "bar/#", qos: 2}}, []byte{2}) 4336 pflags, _ := testMQTTGetPubMsg(t, mc2, rs2, "bar", []byte("qos1 retained")) 4337 if !mqttIsRetained(pflags) { 4338 t.Fatalf("retain flag should have been set, it was not: flags=%v", pflags) 4339 } 4340 4341 testMQTTSub(t, 1, mc2, rs2, []*mqttFilter{{filter: "foo/#", qos: 2}}, []byte{2}) 4342 testMQTTExpectNothing(t, rs2) 4343 testMQTTDisconnect(t, mc2, nil) 4344 } 4345 4346 func TestMQTTRetainFlag(t *testing.T) { 4347 o := testMQTTDefaultOptions() 4348 s := testMQTTRunServer(t, o) 4349 defer testMQTTShutdownServer(s) 4350 4351 mc1, rs1 := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 4352 defer mc1.Close() 4353 testMQTTCheckConnAck(t, rs1, mqttConnAckRCConnectionAccepted, false) 4354 testMQTTPublish(t, mc1, rs1, 0, false, true, "foo/0", 0, []byte("flag set")) 4355 testMQTTPublish(t, mc1, rs1, 0, false, true, "foo/1", 0, []byte("flag set")) 4356 testMQTTFlush(t, mc1, nil, rs1) 4357 4358 mc2, rs2 := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 4359 defer mc2.Close() 4360 testMQTTCheckConnAck(t, rs2, mqttConnAckRCConnectionAccepted, false) 4361 4362 testMQTTSub(t, 1, mc2, rs2, []*mqttFilter{{filter: "foo/0", qos: 0}}, []byte{0}) 4363 pflags, _ := testMQTTGetPubMsg(t, mc2, rs2, "foo/0", []byte("flag set")) 4364 if !mqttIsRetained(pflags) { 4365 t.Fatalf("retain flag should have been set, it was not: flags=%v", pflags) 4366 } 4367 4368 testMQTTSub(t, 1, mc2, rs2, []*mqttFilter{{filter: "foo/1", qos: 1}}, []byte{1}) 4369 pflags, _ = testMQTTGetPubMsg(t, mc2, rs2, "foo/1", []byte("flag set")) 4370 if !mqttIsRetained(pflags) { 4371 t.Fatalf("retain flag should have been set, it was not: flags=%v", pflags) 4372 } 4373 4374 // For existing subscriptions, RETAIN flag should not be set: [MQTT-3.3.1-9]. 4375 testMQTTPublish(t, mc1, rs1, 0, false, true, "foo/0", 0, []byte("flag not set")) 4376 testMQTTFlush(t, mc1, nil, rs1) 4377 4378 pflags, _ = testMQTTGetPubMsg(t, mc2, rs2, "foo/0", []byte("flag not set")) 4379 if mqttIsRetained(pflags) { 4380 t.Fatalf("retain flag should not have been set, it was: flags=%v", pflags) 4381 } 4382 4383 testMQTTPublish(t, mc1, rs1, 0, false, true, "foo/1", 0, []byte("flag not set")) 4384 testMQTTFlush(t, mc1, nil, rs1) 4385 4386 pflags, _ = testMQTTGetPubMsg(t, mc2, rs2, "foo/1", []byte("flag not set")) 4387 if mqttIsRetained(pflags) { 4388 t.Fatalf("retain flag should not have been set, it was: flags=%v", pflags) 4389 } 4390 } 4391 4392 func TestMQTTPublishRetainPermViolation(t *testing.T) { 4393 o := testMQTTDefaultOptions() 4394 o.Users = []*User{ 4395 { 4396 Username: "mqtt", 4397 Password: "pass", 4398 Permissions: &Permissions{ 4399 Publish: &SubjectPermission{Allow: []string{"foo"}}, 4400 Subscribe: &SubjectPermission{Allow: []string{"bar", "$MQTT.sub.>"}}, 4401 }, 4402 }, 4403 } 4404 s := testMQTTRunServer(t, o) 4405 defer testMQTTShutdownServer(s) 4406 4407 ci := &mqttConnInfo{ 4408 cleanSess: true, 4409 user: "mqtt", 4410 pass: "pass", 4411 } 4412 4413 mc1, rs1 := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4414 defer mc1.Close() 4415 testMQTTCheckConnAck(t, rs1, mqttConnAckRCConnectionAccepted, false) 4416 testMQTTPublish(t, mc1, rs1, 0, false, true, "bar", 0, []byte("retained")) 4417 testMQTTFlush(t, mc1, nil, rs1) 4418 4419 mc2, rs2 := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4420 defer mc2.Close() 4421 testMQTTCheckConnAck(t, rs2, mqttConnAckRCConnectionAccepted, false) 4422 4423 testMQTTSub(t, 1, mc2, rs2, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 4424 testMQTTExpectNothing(t, rs2) 4425 4426 testMQTTDisconnect(t, mc1, nil) 4427 testMQTTDisconnect(t, mc2, nil) 4428 } 4429 4430 func TestMQTTPublishViolation(t *testing.T) { 4431 o := testMQTTDefaultOptions() 4432 o.Users = []*User{ 4433 { 4434 Username: "mqtt", 4435 Password: "pass", 4436 Permissions: &Permissions{ 4437 Publish: &SubjectPermission{Allow: []string{"foo.bar"}}, 4438 Subscribe: &SubjectPermission{Allow: []string{"foo.*", "$MQTT.sub.>"}}, 4439 }, 4440 }, 4441 } 4442 s := testMQTTRunServer(t, o) 4443 defer testMQTTShutdownServer(s) 4444 4445 ci := &mqttConnInfo{ 4446 user: "mqtt", 4447 pass: "pass", 4448 } 4449 ci.clientID = "sub" 4450 mc, rc := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4451 defer mc.Close() 4452 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, false) 4453 testMQTTSub(t, 1, mc, rc, []*mqttFilter{{filter: "foo/+", qos: 1}}, []byte{1}) 4454 testMQTTFlush(t, mc, nil, rc) 4455 4456 ci.clientID = "pub" 4457 ci.cleanSess = true 4458 mp, rp := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4459 defer mp.Close() 4460 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 4461 4462 // These should be received since publisher has the right to publish on foo.bar 4463 testMQTTPublish(t, mp, rp, 0, false, false, "foo/bar", 0, []byte("msg1")) 4464 testMQTTCheckPubMsg(t, mc, rc, "foo/bar", 0, []byte("msg1")) 4465 testMQTTPublish(t, mp, rp, 1, false, false, "foo/bar", 1, []byte("msg2")) 4466 testMQTTCheckPubMsg(t, mc, rc, "foo/bar", mqttPubQos1, []byte("msg2")) 4467 4468 // But these should not be cause pub has no permission to publish on foo.baz 4469 testMQTTPublish(t, mp, rp, 0, false, false, "foo/baz", 0, []byte("msg3")) 4470 testMQTTExpectNothing(t, rc) 4471 testMQTTPublish(t, mp, rp, 1, false, false, "foo/baz", 1, []byte("msg4")) 4472 testMQTTExpectNothing(t, rc) 4473 4474 // Disconnect publisher 4475 testMQTTDisconnect(t, mp, nil) 4476 mp.Close() 4477 // Disconnect subscriber and restart it to make sure that it does not receive msg3/msg4 4478 testMQTTDisconnect(t, mc, nil) 4479 mc.Close() 4480 4481 ci.cleanSess = false 4482 ci.clientID = "sub" 4483 mc, rc = testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4484 defer mc.Close() 4485 testMQTTCheckConnAck(t, rc, mqttConnAckRCConnectionAccepted, true) 4486 testMQTTSub(t, 1, mc, rc, []*mqttFilter{{filter: "foo/+", qos: 1}}, []byte{1}) 4487 testMQTTExpectNothing(t, rc) 4488 } 4489 4490 func TestMQTTCleanSession(t *testing.T) { 4491 o := testMQTTDefaultOptions() 4492 s := testMQTTRunServer(t, o) 4493 defer testMQTTShutdownServer(s) 4494 4495 ci := &mqttConnInfo{ 4496 clientID: "me", 4497 cleanSess: false, 4498 } 4499 c, r := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4500 defer c.Close() 4501 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4502 testMQTTDisconnect(t, c, nil) 4503 4504 c, r = testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4505 defer c.Close() 4506 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 4507 testMQTTDisconnect(t, c, nil) 4508 4509 ci.cleanSess = true 4510 c, r = testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4511 defer c.Close() 4512 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4513 testMQTTDisconnect(t, c, nil) 4514 } 4515 4516 func TestMQTTDuplicateClientID(t *testing.T) { 4517 o := testMQTTDefaultOptions() 4518 s := testMQTTRunServer(t, o) 4519 defer testMQTTShutdownServer(s) 4520 4521 ci := &mqttConnInfo{ 4522 clientID: "me", 4523 cleanSess: false, 4524 } 4525 c1, r1 := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4526 defer c1.Close() 4527 testMQTTCheckConnAck(t, r1, mqttConnAckRCConnectionAccepted, false) 4528 4529 c2, r2 := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4530 defer c2.Close() 4531 testMQTTCheckConnAck(t, r2, mqttConnAckRCConnectionAccepted, true) 4532 4533 // The old client should be disconnected. 4534 testMQTTExpectDisconnect(t, c1) 4535 } 4536 4537 func TestMQTTPersistedSession(t *testing.T) { 4538 o := testMQTTDefaultOptions() 4539 s := testMQTTRunServer(t, o) 4540 defer testMQTTShutdownRestartedServer(&s) 4541 4542 cisub := &mqttConnInfo{clientID: "sub", cleanSess: false} 4543 cipub := &mqttConnInfo{clientID: "pub", cleanSess: true} 4544 4545 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 4546 defer c.Close() 4547 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4548 4549 testMQTTSub(t, 1, c, r, 4550 []*mqttFilter{ 4551 {filter: "foo/#", qos: 1}, 4552 {filter: "bar", qos: 1}, 4553 {filter: "baz", qos: 0}, 4554 }, 4555 []byte{1, 1, 0}) 4556 testMQTTFlush(t, c, nil, r) 4557 4558 // Shutdown server, close connection and restart server. It should 4559 // have restored the session and consumers. 4560 dir := strings.TrimSuffix(s.JetStreamConfig().StoreDir, JetStreamStoreDir) 4561 s.Shutdown() 4562 c.Close() 4563 4564 o.Port = -1 4565 o.MQTT.Port = -1 4566 o.StoreDir = dir 4567 s = testMQTTRunServer(t, o) 4568 // There is already the defer for shutdown at top of function 4569 4570 // Create a publisher that will send qos1 so we verify that messages 4571 // are stored for the persisted sessions. 4572 c, r = testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 4573 defer c.Close() 4574 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4575 4576 testMQTTPublish(t, c, r, 1, false, false, "foo/bar", 1, []byte("msg0")) 4577 testMQTTFlush(t, c, nil, r) 4578 testMQTTDisconnect(t, c, nil) 4579 c.Close() 4580 4581 // Recreate session 4582 c, r = testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 4583 defer c.Close() 4584 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 4585 4586 // Since consumers have been recovered, messages should be received 4587 // (MQTT does not need client to recreate consumers for a recovered 4588 // session) 4589 4590 // Check that qos1 publish message is received. 4591 testMQTTCheckPubMsg(t, c, r, "foo/bar", mqttPubQos1, []byte("msg0")) 4592 4593 // Flush to prevent publishes to be done too soon since we are 4594 // receiving the CONNACK before the subscriptions are restored. 4595 testMQTTFlush(t, c, nil, r) 4596 4597 // Now publish some messages to all subscriptions. 4598 nc := natsConnect(t, s.ClientURL()) 4599 defer nc.Close() 4600 4601 natsPub(t, nc, "foo.bar", []byte("msg1")) 4602 testMQTTCheckPubMsg(t, c, r, "foo/bar", 0, []byte("msg1")) 4603 4604 natsPub(t, nc, "foo", []byte("msg2")) 4605 testMQTTCheckPubMsg(t, c, r, "foo", 0, []byte("msg2")) 4606 4607 natsPub(t, nc, "bar", []byte("msg3")) 4608 testMQTTCheckPubMsg(t, c, r, "bar", 0, []byte("msg3")) 4609 4610 natsPub(t, nc, "baz", []byte("msg4")) 4611 testMQTTCheckPubMsg(t, c, r, "baz", 0, []byte("msg4")) 4612 4613 // Now unsub "bar" and verify that message published on this topic 4614 // is not received. 4615 testMQTTUnsub(t, 1, c, r, []*mqttFilter{{filter: "bar"}}) 4616 natsPub(t, nc, "bar", []byte("msg5")) 4617 testMQTTExpectNothing(t, r) 4618 4619 nc.Close() 4620 s.Shutdown() 4621 c.Close() 4622 4623 o.Port = -1 4624 o.MQTT.Port = -1 4625 o.StoreDir = dir 4626 s = testMQTTRunServer(t, o) 4627 // There is already the defer for shutdown at top of function 4628 4629 // Recreate a client 4630 c, r = testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 4631 defer c.Close() 4632 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 4633 4634 nc = natsConnect(t, s.ClientURL()) 4635 defer nc.Close() 4636 4637 natsPub(t, nc, "foo.bar", []byte("msg6")) 4638 testMQTTCheckPubMsg(t, c, r, "foo/bar", 0, []byte("msg6")) 4639 4640 natsPub(t, nc, "foo", []byte("msg7")) 4641 testMQTTCheckPubMsg(t, c, r, "foo", 0, []byte("msg7")) 4642 4643 // Make sure that we did not recover bar. 4644 natsPub(t, nc, "bar", []byte("msg8")) 4645 testMQTTExpectNothing(t, r) 4646 4647 natsPub(t, nc, "baz", []byte("msg9")) 4648 testMQTTCheckPubMsg(t, c, r, "baz", 0, []byte("msg9")) 4649 4650 // Have the sub client send a subscription downgrading the qos1 subscription. 4651 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo/#", qos: 0}}, []byte{0}) 4652 testMQTTFlush(t, c, nil, r) 4653 4654 nc.Close() 4655 s.Shutdown() 4656 c.Close() 4657 4658 o.Port = -1 4659 o.MQTT.Port = -1 4660 o.StoreDir = dir 4661 s = testMQTTRunServer(t, o) 4662 // There is already the defer for shutdown at top of function 4663 4664 // Recreate the sub client 4665 c, r = testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 4666 defer c.Close() 4667 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 4668 4669 // Publish as a qos1 4670 c2, r2 := testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 4671 defer c2.Close() 4672 testMQTTCheckConnAck(t, r2, mqttConnAckRCConnectionAccepted, false) 4673 testMQTTPublish(t, c2, r2, 1, false, false, "foo/bar", 1, []byte("msg10")) 4674 4675 // Verify that it is received as qos0 which is the qos of the subscription. 4676 testMQTTCheckPubMsg(t, c, r, "foo/bar", 0, []byte("msg10")) 4677 4678 testMQTTDisconnect(t, c, nil) 4679 c.Close() 4680 testMQTTDisconnect(t, c2, nil) 4681 c2.Close() 4682 4683 // Finally, recreate the sub with clean session and ensure that all is gone 4684 cisub.cleanSess = true 4685 for i := 0; i < 2; i++ { 4686 c, r = testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 4687 defer c.Close() 4688 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4689 4690 nc = natsConnect(t, s.ClientURL()) 4691 defer nc.Close() 4692 4693 natsPub(t, nc, "foo.bar", []byte("msg11")) 4694 testMQTTExpectNothing(t, r) 4695 4696 natsPub(t, nc, "foo", []byte("msg12")) 4697 testMQTTExpectNothing(t, r) 4698 4699 // Make sure that we did not recover bar. 4700 natsPub(t, nc, "bar", []byte("msg13")) 4701 testMQTTExpectNothing(t, r) 4702 4703 natsPub(t, nc, "baz", []byte("msg14")) 4704 testMQTTExpectNothing(t, r) 4705 4706 testMQTTDisconnect(t, c, nil) 4707 c.Close() 4708 nc.Close() 4709 4710 s.Shutdown() 4711 o.Port = -1 4712 o.MQTT.Port = -1 4713 o.StoreDir = dir 4714 s = testMQTTRunServer(t, o) 4715 // There is already the defer for shutdown at top of function 4716 } 4717 } 4718 4719 func TestMQTTRecoverSessionAndAddNewSub(t *testing.T) { 4720 o := testMQTTDefaultOptions() 4721 s := testMQTTRunServer(t, o) 4722 defer testMQTTShutdownRestartedServer(&s) 4723 4724 cisub := &mqttConnInfo{clientID: "sub1", cleanSess: false} 4725 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 4726 defer c.Close() 4727 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4728 testMQTTDisconnect(t, c, nil) 4729 c.Close() 4730 4731 // Shutdown server, close connection and restart server. It should 4732 // have restored the session and consumers. 4733 dir := strings.TrimSuffix(s.JetStreamConfig().StoreDir, JetStreamStoreDir) 4734 s.Shutdown() 4735 c.Close() 4736 4737 o.Port = -1 4738 o.MQTT.Port = -1 4739 o.StoreDir = dir 4740 s = testMQTTRunServer(t, o) 4741 // No need for defer since it is done top of function 4742 4743 c, r = testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 4744 defer c.Close() 4745 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 4746 // Now add sub and make sure it does not crash 4747 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 4748 testMQTTFlush(t, c, nil, r) 4749 4750 // Now repeat with a new client but without server restart. 4751 cisub2 := &mqttConnInfo{clientID: "sub2", cleanSess: false} 4752 c2, r2 := testMQTTConnect(t, cisub2, o.MQTT.Host, o.MQTT.Port) 4753 defer c2.Close() 4754 testMQTTCheckConnAck(t, r2, mqttConnAckRCConnectionAccepted, false) 4755 testMQTTDisconnect(t, c2, nil) 4756 c2.Close() 4757 4758 c2, r2 = testMQTTConnect(t, cisub2, o.MQTT.Host, o.MQTT.Port) 4759 defer c2.Close() 4760 testMQTTCheckConnAck(t, r2, mqttConnAckRCConnectionAccepted, true) 4761 testMQTTSub(t, 1, c2, r2, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 4762 testMQTTFlush(t, c2, nil, r2) 4763 } 4764 4765 func TestMQTTRecoverSessionWithSubAndClientResendSub(t *testing.T) { 4766 o := testMQTTDefaultOptions() 4767 s := testMQTTRunServer(t, o) 4768 defer testMQTTShutdownRestartedServer(&s) 4769 4770 cisub1 := &mqttConnInfo{clientID: "sub1", cleanSess: false} 4771 c, r := testMQTTConnect(t, cisub1, o.MQTT.Host, o.MQTT.Port) 4772 defer c.Close() 4773 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4774 4775 // Have a client send a SUBSCRIBE protocol for foo, QoS1 4776 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 4777 testMQTTDisconnect(t, c, nil) 4778 c.Close() 4779 4780 // Restart the server now. 4781 dir := strings.TrimSuffix(s.JetStreamConfig().StoreDir, JetStreamStoreDir) 4782 s.Shutdown() 4783 4784 o.Port = -1 4785 o.MQTT.Port = -1 4786 o.StoreDir = dir 4787 s = testMQTTRunServer(t, o) 4788 // No need for defer since it is done top of function 4789 4790 // Now restart the client. Since the client was created with cleanSess==false, 4791 // the server will have recorded the subscriptions for this client. 4792 c, r = testMQTTConnect(t, cisub1, o.MQTT.Host, o.MQTT.Port) 4793 defer c.Close() 4794 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 4795 // At this point, the server has recreated the subscription on foo, QoS1. 4796 4797 // For applications that restart, it is possible (likely) that they 4798 // will resend their SUBSCRIBE protocols, so do so now: 4799 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 4800 testMQTTFlush(t, c, nil, r) 4801 4802 checkNumSub := func(clientID string) { 4803 t.Helper() 4804 4805 // Find the MQTT client... 4806 mc := testMQTTGetClient(t, s, clientID) 4807 4808 // Check how many NATS subscriptions are registered. 4809 var fooSub int 4810 var otherSub int 4811 mc.mu.Lock() 4812 for _, sub := range mc.subs { 4813 switch string(sub.subject) { 4814 case "foo": 4815 fooSub++ 4816 default: 4817 otherSub++ 4818 } 4819 } 4820 mc.mu.Unlock() 4821 4822 // We should have 2 subscriptions, one on "foo", and one for the JS durable 4823 // consumer's delivery subject. 4824 if fooSub != 1 { 4825 t.Fatalf("Expected 1 sub on 'foo', got %v", fooSub) 4826 } 4827 if otherSub != 1 { 4828 t.Fatalf("Expected 1 subscription for JS durable, got %v", otherSub) 4829 } 4830 } 4831 checkNumSub("sub1") 4832 4833 c.Close() 4834 4835 // Now same but without the server restart in-between. 4836 cisub2 := &mqttConnInfo{clientID: "sub2", cleanSess: false} 4837 c, r = testMQTTConnect(t, cisub2, o.MQTT.Host, o.MQTT.Port) 4838 defer c.Close() 4839 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4840 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 4841 testMQTTDisconnect(t, c, nil) 4842 c.Close() 4843 // Restart client 4844 c, r = testMQTTConnect(t, cisub2, o.MQTT.Host, o.MQTT.Port) 4845 defer c.Close() 4846 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 4847 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 4848 testMQTTFlush(t, c, nil, r) 4849 // Check client subs 4850 checkNumSub("sub2") 4851 } 4852 4853 func TestMQTTFlappingSession(t *testing.T) { 4854 mqttSessJailDur = 250 * time.Millisecond 4855 mqttFlapCleanItvl = 350 * time.Millisecond 4856 defer func() { 4857 mqttSessJailDur = mqttSessFlappingJailDur 4858 mqttFlapCleanItvl = mqttSessFlappingCleanupInterval 4859 }() 4860 4861 o := testMQTTDefaultOptions() 4862 s := testMQTTRunServer(t, o) 4863 defer testMQTTShutdownServer(s) 4864 4865 ci := &mqttConnInfo{clientID: "flapper", cleanSess: false} 4866 c, r := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4867 defer c.Close() 4868 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4869 4870 // Let's get a handle on the asm to check things later. 4871 cli := testMQTTGetClient(t, s, "flapper") 4872 asm := cli.mqtt.asm 4873 4874 // Start a new connection with the same clientID, which should replace 4875 // the old one and put it in the flappers map. 4876 c2, r2 := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4877 defer c2.Close() 4878 testMQTTCheckConnAck(t, r2, mqttConnAckRCConnectionAccepted, true) 4879 4880 // Should be disconnected... 4881 testMQTTExpectDisconnect(t, c) 4882 4883 // Now try to reconnect "c" and we should fail. We have to do this manually, 4884 // since we expect it to fail. 4885 addr := fmt.Sprintf("%s:%d", o.MQTT.Host, o.MQTT.Port) 4886 c, err := net.Dial("tcp", addr) 4887 if err != nil { 4888 t.Fatalf("Error creating mqtt connection: %v", err) 4889 } 4890 defer c.Close() 4891 proto := mqttCreateConnectProto(ci) 4892 if _, err := testMQTTWrite(c, proto); err != nil { 4893 t.Fatalf("Error writing protocols: %v", err) 4894 } 4895 // Misbehave and send a SUB protocol without waiting for the CONNACK 4896 w := newMQTTWriter(0) 4897 pkLen := 2 // for pi 4898 // Topic "foo" 4899 pkLen += 2 + 3 + 1 4900 w.WriteByte(mqttPacketSub | mqttSubscribeFlags) 4901 w.WriteVarInt(pkLen) 4902 w.WriteUint16(1) 4903 w.WriteBytes([]byte("foo")) 4904 w.WriteByte(1) 4905 if _, err := testMQTTWrite(c, w.Bytes()); err != nil { 4906 t.Fatalf("Error writing protocols: %v", err) 4907 } 4908 // Now read the CONNACK and we should have been disconnected. 4909 if _, err := testMQTTRead(c); err == nil { 4910 t.Fatal("Expected connection to fail") 4911 } 4912 4913 // This should be in the flappers map, but after 250ms should be cleared. 4914 for i := 0; i < 2; i++ { 4915 asm.mu.RLock() 4916 _, present := asm.flappers["flapper"] 4917 asm.mu.RUnlock() 4918 if i == 0 { 4919 if !present { 4920 t.Fatal("Did not find the client ID in the flappers map") 4921 } 4922 // Wait for more than the cleanup interval 4923 time.Sleep(mqttFlapCleanItvl + 100*time.Millisecond) 4924 } else if present { 4925 t.Fatal("The client ID should have been cleared from the map") 4926 } 4927 } 4928 } 4929 4930 func TestMQTTLockedSession(t *testing.T) { 4931 o := testMQTTDefaultOptions() 4932 s := testMQTTRunServer(t, o) 4933 defer testMQTTShutdownServer(s) 4934 4935 subClientID := "sub" 4936 ci := &mqttConnInfo{clientID: subClientID, cleanSess: false} 4937 c, r := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4938 defer c.Close() 4939 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 4940 4941 sm := &s.mqtt.sessmgr 4942 sm.mu.Lock() 4943 asm := sm.sessions[globalAccountName] 4944 sm.mu.Unlock() 4945 if asm == nil { 4946 t.Fatalf("account session manager not found") 4947 } 4948 4949 // It is possible, however unlikely, to have received CONNACK while 4950 // mqttProcessConnect is still running, and the session remains locked. Wait 4951 // for it to finish. 4952 checkFor(t, 250*time.Millisecond, 10*time.Millisecond, func() error { 4953 asm.mu.RLock() 4954 defer asm.mu.RUnlock() 4955 if _, stillLocked := asm.sessLocked[subClientID]; stillLocked { 4956 return fmt.Errorf("session still locked") 4957 } 4958 return nil 4959 }) 4960 4961 // Get the session for "sub" 4962 cli := testMQTTGetClient(t, s, subClientID) 4963 sess := cli.mqtt.sess 4964 4965 // Pretend that the session above is locked. 4966 if err := asm.lockSession(sess, cli); err != nil { 4967 t.Fatalf("Unable to lock session: %v", err) 4968 } 4969 defer asm.unlockSession(sess) 4970 4971 // Now try to connect another client that wants to use "sub". 4972 // We can't use testMQTTConnect() because it is going to fail. 4973 addr := fmt.Sprintf("%s:%d", o.MQTT.Host, o.MQTT.Port) 4974 c2, err := net.Dial("tcp", addr) 4975 if err != nil { 4976 t.Fatalf("Error creating mqtt connection: %v", err) 4977 } 4978 defer c2.Close() 4979 proto := mqttCreateConnectProto(ci) 4980 if _, err := testMQTTWrite(c2, proto); err != nil { 4981 t.Fatalf("Error writing connect: %v", err) 4982 } 4983 if _, err := testMQTTRead(c2); err == nil { 4984 t.Fatal("Expected connection to fail") 4985 } 4986 4987 // Now try again, but this time release the session while waiting 4988 // to connect and it should succeed. 4989 time.AfterFunc(250*time.Millisecond, func() { asm.unlockSession(sess) }) 4990 c3, r3 := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 4991 defer c3.Close() 4992 testMQTTCheckConnAck(t, r3, mqttConnAckRCConnectionAccepted, true) 4993 } 4994 4995 func TestMQTTPersistRetainedMsg(t *testing.T) { 4996 o := testMQTTDefaultOptions() 4997 s := testMQTTRunServer(t, o) 4998 defer testMQTTShutdownRestartedServer(&s) 4999 5000 dir := strings.TrimSuffix(s.JetStreamConfig().StoreDir, JetStreamStoreDir) 5001 5002 cipub := &mqttConnInfo{clientID: "pub", cleanSess: true} 5003 c, r := testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5004 defer c.Close() 5005 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5006 5007 testMQTTPublish(t, c, r, 1, false, true, "moo/foo", 1, []byte("foo1")) 5008 testMQTTPublish(t, c, r, 1, false, true, "moo/foo", 1, []byte("foo2")) 5009 testMQTTPublish(t, c, r, 1, false, true, "moo/bar", 1, []byte("bar1")) 5010 testMQTTPublish(t, c, r, 0, false, true, "moo/baz", 1, []byte("baz1")) 5011 // Remove bar 5012 testMQTTPublish(t, c, r, 1, false, true, "moo/bar", 1, nil) 5013 testMQTTFlush(t, c, nil, r) 5014 testMQTTDisconnect(t, c, nil) 5015 c.Close() 5016 5017 s.Shutdown() 5018 5019 o.Port = -1 5020 o.MQTT.Port = -1 5021 o.StoreDir = dir 5022 s = testMQTTRunServer(t, o) 5023 5024 cisub := &mqttConnInfo{clientID: "sub", cleanSess: false} 5025 c, r = testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5026 defer c.Close() 5027 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5028 5029 t.Run("many subs one topic", func(t *testing.T) { 5030 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "moo/foo", qos: 1}}, []byte{1}) 5031 testMQTTCheckPubMsg(t, c, r, "moo/foo", mqttPubFlagRetain|mqttPubQos1, []byte("foo2")) 5032 5033 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "moo/baz", qos: 1}}, []byte{1}) 5034 testMQTTCheckPubMsg(t, c, r, "moo/baz", mqttPubFlagRetain, []byte("baz1")) 5035 5036 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "moo/bar", qos: 1}}, []byte{1}) 5037 testMQTTExpectNothing(t, r) 5038 }) 5039 5040 runSingleSubscribe := func(filters []*mqttFilter) func(t *testing.T) { 5041 return func(t *testing.T) { 5042 testMQTTSub(t, 1, c, r, filters, nil) 5043 5044 for i := 0; i < 2; i++ { 5045 flags, pi, topic, payload := testMQTTReadPubPacket(t, r) 5046 if (flags & mqttPubFlagRetain) == 0 { 5047 t.Fatalf("Expected flags to have retain set, got %v", flags) 5048 } 5049 if (flags & mqttPubFlagDup) != 0 { 5050 t.Fatalf("Expected flags to not have Dup set, got %v", flags) 5051 } 5052 var expQOS byte 5053 var expPayload []byte 5054 switch topic { 5055 case "moo/foo": 5056 expQOS = mqttPubQos1 5057 expPayload = []byte("foo2") 5058 testMQTTSendPIPacket(mqttPacketPubAck, t, c, pi) 5059 case "moo/baz": 5060 expQOS = 0 5061 expPayload = []byte("baz1") 5062 default: 5063 t.Fatalf("Unexpected topic: %v", topic) 5064 } 5065 if (flags & mqttPubFlagQoS) != expQOS { 5066 t.Fatalf("Expected flags to have QOS %x set, got %x", expQOS, flags) 5067 } 5068 if string(payload) != string(expPayload) { 5069 t.Fatalf("Expected payload to be %q, got %v", expPayload, string(payload)) 5070 } 5071 } 5072 testMQTTExpectNothing(t, r) 5073 } 5074 } 5075 5076 t.Run("one sub many topics", runSingleSubscribe([]*mqttFilter{ 5077 {filter: "moo/foo", qos: 1}, 5078 {filter: "moo/baz", qos: 1}, 5079 {filter: "moo/bar", qos: 1}, 5080 })) 5081 5082 t.Run("one sub wildcard plus", runSingleSubscribe([]*mqttFilter{ 5083 {filter: "moo/+", qos: 1}, 5084 })) 5085 5086 t.Run("one sub wildcard hash", runSingleSubscribe([]*mqttFilter{ 5087 {filter: "moo/#", qos: 1}, 5088 })) 5089 5090 testMQTTDisconnect(t, c, nil) 5091 c.Close() 5092 } 5093 5094 func TestMQTTRetainedMsgCleanup(t *testing.T) { 5095 mqttRetainedCacheTTL = 250 * time.Millisecond 5096 defer func() { mqttRetainedCacheTTL = mqttDefaultRetainedCacheTTL }() 5097 5098 o := testMQTTDefaultOptions() 5099 s := testMQTTRunServer(t, o) 5100 defer testMQTTShutdownServer(s) 5101 5102 ci := &mqttConnInfo{clientID: "cache", cleanSess: true} 5103 c, r := testMQTTConnect(t, ci, o.MQTT.Host, o.MQTT.Port) 5104 defer c.Close() 5105 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5106 5107 // Send a retained message. 5108 testMQTTPublish(t, c, r, 1, false, true, "foo", 1, []byte("msg")) 5109 testMQTTFlush(t, c, nil, r) 5110 5111 // Start a subscription. 5112 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 5113 testMQTTCheckPubMsg(t, c, r, "foo", mqttPubQos1|mqttPubFlagRetain, []byte("msg")) 5114 5115 time.Sleep(2 * mqttRetainedCacheTTL) 5116 5117 // Make sure not in cache anymore 5118 cli := testMQTTGetClient(t, s, "cache") 5119 asm := cli.mqtt.asm 5120 if v, ok := asm.rmsCache.Load("foo"); ok { 5121 t.Fatalf("Should not be in cache, got %+v", v) 5122 } 5123 } 5124 5125 func TestMQTTConnAckFirstPacket(t *testing.T) { 5126 o := testMQTTDefaultOptions() 5127 o.NoLog, o.Debug, o.Trace = true, false, false 5128 s := RunServer(o) 5129 defer testMQTTShutdownServer(s) 5130 5131 cisub := &mqttConnInfo{clientID: "sub", cleanSess: false} 5132 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5133 defer c.Close() 5134 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5135 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 0}}, []byte{0}) 5136 testMQTTDisconnect(t, c, nil) 5137 c.Close() 5138 5139 nc := natsConnect(t, s.ClientURL()) 5140 defer nc.Close() 5141 5142 wg := sync.WaitGroup{} 5143 wg.Add(1) 5144 ch := make(chan struct{}, 1) 5145 ready := make(chan struct{}) 5146 go func() { 5147 defer wg.Done() 5148 5149 close(ready) 5150 for { 5151 nc.Publish("foo", []byte("msg")) 5152 select { 5153 case <-ch: 5154 return 5155 default: 5156 } 5157 } 5158 }() 5159 5160 <-ready 5161 for i := 0; i < 100; i++ { 5162 c, r = testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5163 defer c.Close() 5164 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 5165 w := newMQTTWriter(0) 5166 w.WriteByte(mqttPacketDisconnect) 5167 w.WriteByte(0) 5168 c.Write(w.Bytes()) 5169 // Wait to be disconnected, we can't use testMQTTDisconnect() because 5170 // it would fail because we may still receive some NATS messages. 5171 var b [10]byte 5172 for { 5173 if _, err := c.Read(b[:]); err != nil { 5174 break 5175 } 5176 } 5177 c.Close() 5178 } 5179 close(ch) 5180 wg.Wait() 5181 } 5182 5183 func TestMQTTRedeliveryAckWait(t *testing.T) { 5184 o := testMQTTDefaultOptions() 5185 o.MQTT.AckWait = 250 * time.Millisecond 5186 s := testMQTTRunServer(t, o) 5187 defer testMQTTShutdownServer(s) 5188 5189 cisub := &mqttConnInfo{clientID: "sub", cleanSess: false} 5190 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5191 defer c.Close() 5192 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5193 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 5194 5195 cipub := &mqttConnInfo{clientID: "pub", cleanSess: true} 5196 cp, rp := testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5197 defer cp.Close() 5198 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 5199 5200 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("foo1")) 5201 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 2, []byte("foo2")) 5202 testMQTTDisconnect(t, cp, nil) 5203 cp.Close() 5204 5205 for i := 0; i < 2; i++ { 5206 flags := mqttPubQos1 5207 if i > 0 { 5208 flags |= mqttPubFlagDup 5209 } 5210 pi1 := testMQTTCheckPubMsgNoAck(t, c, r, "foo", flags, []byte("foo1")) 5211 pi2 := testMQTTCheckPubMsgNoAck(t, c, r, "foo", flags, []byte("foo2")) 5212 5213 if pi1 != 1 || pi2 != 2 { 5214 t.Fatalf("Unexpected pi values: %v, %v", pi1, pi2) 5215 } 5216 } 5217 // Ack first message 5218 testMQTTSendPIPacket(mqttPacketPubAck, t, c, 1) 5219 // Redelivery should only be for second message now 5220 for i := 0; i < 2; i++ { 5221 flags := mqttPubQos1 | mqttPubFlagDup 5222 pi := testMQTTCheckPubMsgNoAck(t, c, r, "foo", flags, []byte("foo2")) 5223 if pi != 2 { 5224 t.Fatalf("Unexpected pi to be 2, got %v", pi) 5225 } 5226 } 5227 5228 // Restart client, should receive second message with pi==2 5229 c.Close() 5230 c, r = testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5231 defer c.Close() 5232 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 5233 // Check that message is received with proper pi 5234 pi := testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQos1|mqttPubFlagDup, []byte("foo2")) 5235 if pi != 2 { 5236 t.Fatalf("Unexpected pi to be 2, got %v", pi) 5237 } 5238 // Now ack second message 5239 testMQTTSendPIPacket(mqttPacketPubAck, t, c, 2) 5240 // Flush to make sure it is processed before checking client's maps 5241 testMQTTFlush(t, c, nil, r) 5242 5243 // Look for the sub client 5244 mc := testMQTTGetClient(t, s, "sub") 5245 mc.mu.Lock() 5246 sess := mc.mqtt.sess 5247 sess.mu.Lock() 5248 lpi := len(sess.pendingPublish) 5249 var lsseq int 5250 for _, sseqToPi := range sess.cpending { 5251 lsseq += len(sseqToPi) 5252 } 5253 sess.mu.Unlock() 5254 mc.mu.Unlock() 5255 if lpi != 0 || lsseq != 0 { 5256 t.Fatalf("Maps should be empty, got %v, %v", lpi, lsseq) 5257 } 5258 } 5259 5260 // - [MQTT-3.10.4-3] If a Server deletes a Subscription It MUST complete the 5261 // delivery of any QoS 1 or QoS 2 messages which it has started to send to the 5262 // Client. 5263 // 5264 // Test flow: 5265 // - Subscribe to foo, publish 3 QoS2 messages. 5266 // - After one is PUBCOMP-ed, and one is PUBREC-ed, Unsubscribe. 5267 // - See that the remaining 2 are fully delivered. 5268 func TestMQTTQoS2InflightMsgsDeliveredAfterUnsubscribe(t *testing.T) { 5269 // This test has proven flaky on Travis, so skip for now. Line 4926, the 3rd 5270 // testMQTTCheckPubMsgNoAck sometimes returns `data1`, instead of `data3` 5271 // that we are expecting. It must be a retry since we did not acknowledge 5272 // `data1` until later. 5273 t.Skip() 5274 5275 o := testMQTTDefaultOptions() 5276 o.MQTT.AckWait = 10 * time.Millisecond 5277 s := testMQTTRunServer(t, o) 5278 defer testMQTTShutdownServer(s) 5279 5280 var qos2 byte = 2 5281 cisub := &mqttConnInfo{clientID: "sub", cleanSess: true} 5282 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5283 defer c.Close() 5284 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5285 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: qos2}}, []byte{qos2}) 5286 5287 cipub := &mqttConnInfo{clientID: "pub", cleanSess: true} 5288 cp, rp := testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5289 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 5290 5291 // send 3 messages 5292 testMQTTPublish(t, cp, rp, qos2, false, false, "foo", 441, []byte("data1")) 5293 testMQTTPublish(t, cp, rp, qos2, false, false, "foo", 442, []byte("data2")) 5294 testMQTTPublish(t, cp, rp, qos2, false, false, "foo", 443, []byte("data3")) 5295 5296 testMQTTDisconnect(t, cp, nil) 5297 cp.Close() 5298 5299 subPI1 := testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQoS2, []byte("data1")) 5300 subPI2 := testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQoS2, []byte("data2")) 5301 // subPI3 := testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQoS2, []byte("data3")) 5302 _ = testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQoS2, []byte("data3")) 5303 5304 // fully receive first message 5305 testMQTTSendPIPacket(mqttPacketPubRec, t, c, subPI1) 5306 testMQTTReadPIPacket(mqttPacketPubRel, t, r, subPI1) 5307 testMQTTSendPIPacket(mqttPacketPubComp, t, c, subPI1) 5308 5309 // Do not PUBCOMP the 2nd message yet. 5310 testMQTTSendPIPacket(mqttPacketPubRec, t, c, subPI2) 5311 testMQTTReadPIPacket(mqttPacketPubRel, t, r, subPI2) 5312 5313 // Unsubscribe 5314 testMQTTUnsub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: qos2}}) 5315 5316 // We expect that PI2 and PI3 will continue to be delivered, from their 5317 // respective states. 5318 gotPI2PubRel := false 5319 5320 // TODO: Currently, we do not get the unacknowledged PUBLISH re-delivered 5321 // after an UNSUBSCRIBE. Ongoing discussion if we should/must. 5322 // gotPI3Publish := false 5323 // gotPI3PubRel := false 5324 for !gotPI2PubRel /* || !gotPI3Publish || !gotPI3PubRel */ { 5325 b, _ /* len */ := testMQTTReadPacket(t, r) 5326 switch b & mqttPacketMask { 5327 case mqttPacketPubRel: 5328 pi, err := r.readUint16("packet identifier") 5329 if err != nil { 5330 t.Fatalf("got unexpected error: %v", err) 5331 } 5332 switch pi { 5333 case subPI2: 5334 testMQTTSendPIPacket(mqttPacketPubComp, t, c, pi) 5335 gotPI2PubRel = true 5336 // case subPI3: 5337 // testMQTTSendPIPacket(mqttPacketPubComp, t, c, pi) 5338 // gotPI3PubRel = true 5339 default: 5340 t.Fatalf("Expected PI %v got: %v", subPI2, pi) 5341 } 5342 5343 // case mqttPacketPub: 5344 // _, pi, _ := testMQTTGetPubMsgExEx(t, c, r, b, len, "foo", []byte("data3")) 5345 // if pi != subPI3 { 5346 // t.Fatalf("Expected PI %v got: %v", subPI3, pi) 5347 // } 5348 // gotPI3Publish = true 5349 // testMQTTSendPIPacket(mqttPacketPubRec, t, c, subPI3) 5350 5351 default: 5352 t.Fatalf("Unexpected packet type: %v", b&mqttPacketMask) 5353 } 5354 } 5355 5356 testMQTTExpectNothing(t, r) 5357 } 5358 5359 func TestMQTTQoS2RejectPublishDuplicates(t *testing.T) { 5360 o := testMQTTDefaultOptions() 5361 s := testMQTTRunServer(t, o) 5362 defer testMQTTShutdownServer(s) 5363 5364 var qos2 byte = 2 5365 cisub := &mqttConnInfo{clientID: "sub", cleanSess: true} 5366 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5367 defer c.Close() 5368 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5369 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: qos2}}, []byte{qos2}) 5370 5371 cipub := &mqttConnInfo{clientID: "pub", cleanSess: true} 5372 cp, rp := testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5373 defer cp.Close() 5374 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 5375 5376 // Publish 3 different with same PI before we get any PUBREC back, then 5377 // complete the PUBREL/PUBCOMP flow as needed. Only one message (first 5378 // payload) should be delivered. PUBRECs, 5379 var pubPI uint16 = 444 5380 testMQTTSendPublishPacket(t, cp, qos2, false, false, "foo", pubPI, []byte("data1")) 5381 testMQTTSendPublishPacket(t, cp, qos2, true, false, "foo", pubPI, []byte("data2")) 5382 testMQTTSendPublishPacket(t, cp, qos2, false, false, "foo", pubPI, []byte("data3")) 5383 5384 for i := 0; i < 3; i++ { 5385 // [MQTT-4.3.3-1] The receiver 5386 // 5387 // - MUST respond with a PUBREC containing the Packet Identifier from 5388 // the incoming PUBLISH Packet, having accepted ownership of the 5389 // Application Message. 5390 // 5391 // - Until it has received the corresponding PUBREL packet, the Receiver 5392 // MUST acknowledge any subsequent PUBLISH packet with the same Packet 5393 // Identifier by sending a PUBREC. It MUST NOT cause duplicate messages 5394 // to be delivered to any onward recipients in this case. 5395 testMQTTReadPIPacket(mqttPacketPubRec, t, rp, pubPI) 5396 } 5397 for i := 0; i < 3; i++ { 5398 testMQTTSendPIPacket(mqttPacketPubRel, t, cp, pubPI) 5399 } 5400 for i := 0; i < 3; i++ { 5401 // [MQTT-4.3.3-1] MUST respond to a PUBREL packet by sending a PUBCOMP 5402 // packet containing the same Packet Identifier as the PUBREL. 5403 testMQTTReadPIPacket(mqttPacketPubComp, t, rp, pubPI) 5404 } 5405 5406 // [MQTT-4.3.3-1] After it has sent a PUBCOMP, the receiver MUST treat any 5407 // subsequent PUBLISH packet that contains that Packet Identifier as being a 5408 // new publication. 5409 // 5410 // Publish another message, identical to the first one. Since the server 5411 // already sent us a PUBCOMP, it will deliver this message, for a total of 2 5412 // delivered. 5413 testMQTTPublish(t, cp, rp, qos2, false, false, "foo", pubPI, []byte("data5")) 5414 5415 testMQTTDisconnect(t, cp, nil) 5416 cp.Close() 5417 5418 // Verify we got a total of 2 messages. 5419 subPI1 := testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQoS2, []byte("data1")) 5420 subPI2 := testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQoS2, []byte("data5")) 5421 for _, pi := range []uint16{subPI1, subPI2} { 5422 testMQTTSendPIPacket(mqttPacketPubRec, t, c, pi) 5423 testMQTTReadPIPacket(mqttPacketPubRel, t, r, pi) 5424 testMQTTSendPIPacket(mqttPacketPubComp, t, c, pi) 5425 } 5426 testMQTTExpectNothing(t, r) 5427 } 5428 5429 func TestMQTTQoS2RetriesPublish(t *testing.T) { 5430 o := testMQTTDefaultOptions() 5431 o.MQTT.AckWait = 100 * time.Millisecond 5432 s := testMQTTRunServer(t, o) 5433 defer testMQTTShutdownServer(s) 5434 5435 var qos2 byte = 2 5436 cisub := &mqttConnInfo{clientID: "sub", cleanSess: true} 5437 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5438 defer c.Close() 5439 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5440 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: qos2}}, []byte{qos2}) 5441 5442 cipub := &mqttConnInfo{clientID: "pub", cleanSess: true} 5443 cp, rp := testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5444 defer cp.Close() 5445 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 5446 5447 // Publish a message and close the pub connection. 5448 var pubPI uint16 = 444 5449 testMQTTPublish(t, cp, rp, qos2, false, false, "foo", pubPI, []byte("data1")) 5450 testMQTTDisconnect(t, cp, nil) 5451 cp.Close() 5452 5453 // See that we got the message delivered to the sub, but don't PUBREC it 5454 // yet. 5455 subPI := testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQoS2, []byte("data1")) 5456 5457 // See that the message is redelivered again 2 times, with the DUP on, before we PUBREC it. 5458 for i := 0; i < 2; i++ { 5459 expectedFlags := mqttPubQoS2 | mqttPubFlagDup 5460 pi := testMQTTCheckPubMsgNoAck(t, c, r, "foo", expectedFlags, []byte("data1")) 5461 if pi != subPI { 5462 t.Fatalf("Expected pi to be %v, got %v", subPI, pi) 5463 } 5464 } 5465 5466 // Finish the exchange and make sure there are no more attempts. 5467 testMQTTSendPIPacket(mqttPacketPubRec, t, c, subPI) 5468 testMQTTReadPIPacket(mqttPacketPubRel, t, r, subPI) 5469 testMQTTSendPIPacket(mqttPacketPubComp, t, c, subPI) 5470 testMQTTExpectNothing(t, r) 5471 } 5472 5473 func TestMQTTQoS2RetriesPubRel(t *testing.T) { 5474 o := testMQTTDefaultOptions() 5475 o.MQTT.AckWait = 50 * time.Millisecond 5476 s := testMQTTRunServer(t, o) 5477 defer testMQTTShutdownServer(s) 5478 5479 var qos2 byte = 2 5480 cisub := &mqttConnInfo{clientID: "sub", cleanSess: true} 5481 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5482 defer c.Close() 5483 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5484 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: qos2}}, []byte{qos2}) 5485 5486 cipub := &mqttConnInfo{clientID: "pub", cleanSess: true} 5487 cp, rp := testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5488 defer cp.Close() 5489 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 5490 5491 // Publish a message and close the pub connection. 5492 var pubPI uint16 = 444 5493 testMQTTPublish(t, cp, rp, qos2, false, false, "foo", pubPI, []byte("data1")) 5494 testMQTTDisconnect(t, cp, nil) 5495 cp.Close() 5496 5497 // See that we got the message delivered to the sub, PUBREC it and expect a 5498 // PUBREL from the server. 5499 subPI := testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQoS2, []byte("data1")) 5500 testMQTTSendPIPacket(mqttPacketPubRec, t, c, subPI) 5501 5502 // See that we get PUBREL redelivered several times, there's no DUP flag to 5503 // check. 5504 testMQTTReadPIPacket(mqttPacketPubRel, t, r, subPI) 5505 testMQTTReadPIPacket(mqttPacketPubRel, t, r, subPI) 5506 testMQTTReadPIPacket(mqttPacketPubRel, t, r, subPI) 5507 5508 // Finish the exchange and make sure there are no more attempts. 5509 testMQTTSendPIPacket(mqttPacketPubComp, t, c, subPI) 5510 testMQTTExpectNothing(t, r) 5511 } 5512 5513 func TestMQTTAckWaitConfigChange(t *testing.T) { 5514 o := testMQTTDefaultOptions() 5515 o.MQTT.AckWait = 250 * time.Millisecond 5516 s := testMQTTRunServer(t, o) 5517 defer testMQTTShutdownRestartedServer(&s) 5518 5519 dir := strings.TrimSuffix(s.JetStreamConfig().StoreDir, JetStreamStoreDir) 5520 5521 cisub := &mqttConnInfo{clientID: "sub", cleanSess: false} 5522 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5523 defer c.Close() 5524 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5525 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 5526 5527 sendMsg := func(topic, payload string) { 5528 t.Helper() 5529 cipub := &mqttConnInfo{clientID: "pub", cleanSess: true} 5530 cp, rp := testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5531 defer cp.Close() 5532 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 5533 5534 testMQTTPublish(t, cp, rp, 1, false, false, topic, 1, []byte(payload)) 5535 testMQTTDisconnect(t, cp, nil) 5536 cp.Close() 5537 } 5538 sendMsg("foo", "msg1") 5539 5540 for i := 0; i < 2; i++ { 5541 flags := mqttPubQos1 5542 if i > 0 { 5543 flags |= mqttPubFlagDup 5544 } 5545 testMQTTCheckPubMsgNoAck(t, c, r, "foo", flags, []byte("msg1")) 5546 } 5547 5548 // Restart the server with a different AckWait option value. 5549 // Verify that MQTT sub restart succeeds. It will keep the 5550 // original value. 5551 c.Close() 5552 s.Shutdown() 5553 5554 o.Port = -1 5555 o.MQTT.Port = -1 5556 o.MQTT.AckWait = 10 * time.Millisecond 5557 o.StoreDir = dir 5558 s = testMQTTRunServer(t, o) 5559 // There is already the defer for shutdown at top of function 5560 5561 c, r = testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5562 defer c.Close() 5563 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 5564 testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQos1|mqttPubFlagDup, []byte("msg1")) 5565 start := time.Now() 5566 testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQos1|mqttPubFlagDup, []byte("msg1")) 5567 if dur := time.Since(start); dur < 200*time.Millisecond { 5568 t.Fatalf("AckWait seem to have changed for existing subscription: %v", dur) 5569 } 5570 5571 // Create new subscription 5572 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 5573 sendMsg("bar", "msg2") 5574 testMQTTCheckPubMsgNoAck(t, c, r, "bar", mqttPubQos1, []byte("msg2")) 5575 start = time.Now() 5576 testMQTTCheckPubMsgNoAck(t, c, r, "bar", mqttPubQos1|mqttPubFlagDup, []byte("msg2")) 5577 if dur := time.Since(start); dur > 50*time.Millisecond { 5578 t.Fatalf("AckWait new value not used by new sub: %v", dur) 5579 } 5580 c.Close() 5581 } 5582 5583 func TestMQTTUnsubscribeWithPendingAcks(t *testing.T) { 5584 o := testMQTTDefaultOptions() 5585 o.MQTT.AckWait = 250 * time.Millisecond 5586 s := testMQTTRunServer(t, o) 5587 defer testMQTTShutdownServer(s) 5588 5589 cisub := &mqttConnInfo{clientID: "sub", cleanSess: false} 5590 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5591 defer c.Close() 5592 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5593 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 5594 5595 cipub := &mqttConnInfo{clientID: "pub", cleanSess: true} 5596 cp, rp := testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5597 defer cp.Close() 5598 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 5599 5600 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg")) 5601 testMQTTDisconnect(t, cp, nil) 5602 cp.Close() 5603 5604 for i := 0; i < 2; i++ { 5605 flags := mqttPubQos1 5606 if i > 0 { 5607 flags |= mqttPubFlagDup 5608 } 5609 testMQTTCheckPubMsgNoAck(t, c, r, "foo", flags, []byte("msg")) 5610 } 5611 5612 testMQTTUnsub(t, 1, c, r, []*mqttFilter{{filter: "foo"}}) 5613 testMQTTFlush(t, c, nil, r) 5614 5615 mc := testMQTTGetClient(t, s, "sub") 5616 mc.mu.Lock() 5617 sess := mc.mqtt.sess 5618 sess.mu.Lock() 5619 pal := len(sess.pendingPublish) 5620 sess.mu.Unlock() 5621 mc.mu.Unlock() 5622 if pal != 0 { 5623 t.Fatalf("Expected pending ack map to be empty, got %v", pal) 5624 } 5625 } 5626 5627 func TestMQTTMaxAckPending(t *testing.T) { 5628 o := testMQTTDefaultOptions() 5629 o.MQTT.MaxAckPending = 1 5630 s := testMQTTRunServer(t, o) 5631 defer testMQTTShutdownRestartedServer(&s) 5632 5633 nc, js := jsClientConnect(t, s) 5634 defer nc.Close() 5635 5636 dir := strings.TrimSuffix(s.JetStreamConfig().StoreDir, JetStreamStoreDir) 5637 5638 cisub := &mqttConnInfo{clientID: "sub", cleanSess: false} 5639 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5640 defer c.Close() 5641 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5642 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 5643 5644 cipub := &mqttConnInfo{clientID: "pub", cleanSess: true} 5645 cp, rp := testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5646 defer cp.Close() 5647 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 5648 5649 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg1")) 5650 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg2")) 5651 5652 pi := testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQos1, []byte("msg1")) 5653 // Check that we don't receive the second one due to max ack pending 5654 testMQTTExpectNothing(t, r) 5655 5656 // Now ack first message 5657 testMQTTSendPIPacket(mqttPacketPubAck, t, c, pi) 5658 // Now we should receive message 2 5659 testMQTTCheckPubMsg(t, c, r, "foo", mqttPubQos1, []byte("msg2")) 5660 testMQTTDisconnect(t, c, nil) 5661 5662 // Give a chance to the server to "close" the consumer 5663 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 5664 for ci := range js.ConsumersInfo("$MQTT_msgs") { 5665 if ci.PushBound { 5666 return fmt.Errorf("Consumer still connected") 5667 } 5668 } 5669 return nil 5670 }) 5671 5672 // Send 2 messages while sub is offline 5673 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg3")) 5674 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg4")) 5675 5676 // Restart consumer 5677 c, r = testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5678 defer c.Close() 5679 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 5680 5681 // Should receive only message 3 5682 pi = testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQos1, []byte("msg3")) 5683 testMQTTExpectNothing(t, r) 5684 5685 // Ack and get the next 5686 testMQTTSendPIPacket(mqttPacketPubAck, t, c, pi) 5687 testMQTTCheckPubMsg(t, c, r, "foo", mqttPubQos1, []byte("msg4")) 5688 5689 // Make sure this message gets ack'ed 5690 mcli := testMQTTGetClient(t, s, cisub.clientID) 5691 checkFor(t, time.Second, 15*time.Millisecond, func() error { 5692 mcli.mu.Lock() 5693 sess := mcli.mqtt.sess 5694 sess.mu.Lock() 5695 np := len(sess.pendingPublish) 5696 sess.mu.Unlock() 5697 mcli.mu.Unlock() 5698 if np != 0 { 5699 return fmt.Errorf("Still %v pending messages", np) 5700 } 5701 return nil 5702 }) 5703 5704 // Check that change to config does not prevent restart of sub. 5705 cp.Close() 5706 c.Close() 5707 s.Shutdown() 5708 5709 o.Port = -1 5710 o.MQTT.Port = -1 5711 o.MQTT.MaxAckPending = 2 5712 o.StoreDir = dir 5713 s = testMQTTRunServer(t, o) 5714 // There is already the defer for shutdown at top of function 5715 5716 cp, rp = testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5717 defer cp.Close() 5718 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 5719 5720 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg5")) 5721 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg6")) 5722 5723 // Restart consumer 5724 c, r = testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5725 defer c.Close() 5726 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, true) 5727 5728 // Should receive only message 5 5729 pi = testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQos1, []byte("msg5")) 5730 testMQTTExpectNothing(t, r) 5731 5732 // Ack and get the next 5733 testMQTTSendPIPacket(mqttPacketPubAck, t, c, pi) 5734 testMQTTCheckPubMsg(t, c, r, "foo", mqttPubQos1, []byte("msg6")) 5735 } 5736 5737 func TestMQTTMaxAckPendingForMultipleSubs(t *testing.T) { 5738 o := testMQTTDefaultOptions() 5739 o.MQTT.AckWait = time.Second 5740 o.MQTT.MaxAckPending = 1 5741 s := testMQTTRunServer(t, o) 5742 defer testMQTTShutdownServer(s) 5743 5744 cisub := &mqttConnInfo{clientID: "sub", cleanSess: true} 5745 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5746 defer c.Close() 5747 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5748 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 5749 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 5750 5751 cipub := &mqttConnInfo{clientID: "pub", cleanSess: true} 5752 cp, rp := testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5753 defer cp.Close() 5754 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 5755 5756 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg1")) 5757 pi := testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQos1, []byte("msg1")) 5758 5759 // Now send a second message but on topic bar 5760 testMQTTPublish(t, cp, rp, 1, false, false, "bar", 1, []byte("msg2")) 5761 5762 // JS allows us to limit per consumer, but we apply the limit to the 5763 // session, so although JS will attempt to delivery this message, 5764 // the MQTT code will suppress it. 5765 testMQTTExpectNothing(t, r) 5766 5767 // Ack the first message. 5768 testMQTTSendPIPacket(mqttPacketPubAck, t, c, pi) 5769 5770 // Now we should get the second message 5771 testMQTTCheckPubMsg(t, c, r, "bar", mqttPubQos1|mqttPubFlagDup, []byte("msg2")) 5772 } 5773 5774 func TestMQTTMaxAckPendingOverLimit(t *testing.T) { 5775 o := testMQTTDefaultOptions() 5776 o.MQTT.MaxAckPending = 20000 5777 s := testMQTTRunServer(t, o) 5778 defer testMQTTShutdownServer(s) 5779 5780 checkTMax := func(sess *mqttSession, expected int) { 5781 t.Helper() 5782 sess.mu.Lock() 5783 tmax := sess.tmaxack 5784 sess.mu.Unlock() 5785 if tmax != expected { 5786 t.Fatalf("Expected current tmax to be %v, got %v", expected, tmax) 5787 } 5788 } 5789 5790 cisub := &mqttConnInfo{clientID: "sub", cleanSess: false} 5791 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5792 defer c.Close() 5793 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5794 5795 mc := testMQTTGetClient(t, s, "sub") 5796 mc.mu.Lock() 5797 sess := mc.mqtt.sess 5798 mc.mu.Unlock() 5799 5800 // After this one, total would be 20000 5801 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 5802 checkTMax(sess, 20000) 5803 // This one will count for 2, so total will be 60000 5804 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "bar/#", qos: 1}}, []byte{1}) 5805 checkTMax(sess, 60000) 5806 5807 // This should fail 5808 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{mqttSubAckFailure}) 5809 checkTMax(sess, 60000) 5810 5811 // Remove the one with wildcard 5812 testMQTTUnsub(t, 1, c, r, []*mqttFilter{{filter: "bar/#"}}) 5813 checkTMax(sess, 20000) 5814 5815 // Now we could add 2 more without wildcards 5816 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 5817 checkTMax(sess, 40000) 5818 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "baz", qos: 1}}, []byte{1}) 5819 checkTMax(sess, 60000) 5820 5821 // Again, this one should fail 5822 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "bat", qos: 1}}, []byte{mqttSubAckFailure}) 5823 checkTMax(sess, 60000) 5824 5825 // Now remove all and check that we are at 0 5826 testMQTTUnsub(t, 1, c, r, []*mqttFilter{{filter: "foo"}}) 5827 checkTMax(sess, 40000) 5828 testMQTTUnsub(t, 1, c, r, []*mqttFilter{{filter: "bar"}}) 5829 checkTMax(sess, 20000) 5830 testMQTTUnsub(t, 1, c, r, []*mqttFilter{{filter: "baz"}}) 5831 checkTMax(sess, 0) 5832 } 5833 5834 func TestMQTTConfigReload(t *testing.T) { 5835 template := ` 5836 jetstream: true 5837 server_name: mqtt 5838 mqtt { 5839 port: -1 5840 ack_wait: %s 5841 max_ack_pending: %s 5842 } 5843 ` 5844 conf := createConfFile(t, []byte(fmt.Sprintf(template, `"5s"`, `10000`))) 5845 5846 s, o := RunServerWithConfig(conf) 5847 defer testMQTTShutdownServer(s) 5848 5849 if val := o.MQTT.AckWait; val != 5*time.Second { 5850 t.Fatalf("Invalid ackwait: %v", val) 5851 } 5852 if val := o.MQTT.MaxAckPending; val != 10000 { 5853 t.Fatalf("Invalid ackwait: %v", val) 5854 } 5855 5856 changeCurrentConfigContentWithNewContent(t, conf, []byte(fmt.Sprintf(template, `"250ms"`, `1`))) 5857 if err := s.Reload(); err != nil { 5858 t.Fatalf("Error on reload: %v", err) 5859 } 5860 5861 cisub := &mqttConnInfo{clientID: "sub", cleanSess: false} 5862 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5863 defer c.Close() 5864 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5865 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 5866 5867 cipub := &mqttConnInfo{clientID: "pub", cleanSess: true} 5868 cp, rp := testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5869 defer cp.Close() 5870 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 5871 5872 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg1")) 5873 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg2")) 5874 5875 testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQos1, []byte("msg1")) 5876 start := time.Now() 5877 testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQos1|mqttPubFlagDup, []byte("msg1")) 5878 if dur := time.Since(start); dur > 500*time.Millisecond { 5879 t.Fatalf("AckWait not applied? dur=%v", dur) 5880 } 5881 c.Close() 5882 cp.Close() 5883 testMQTTShutdownServer(s) 5884 5885 changeCurrentConfigContentWithNewContent(t, conf, []byte(fmt.Sprintf(template, `"30s"`, `1`))) 5886 s, o = RunServerWithConfig(conf) 5887 defer testMQTTShutdownServer(s) 5888 5889 cisub.cleanSess = true 5890 c, r = testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5891 defer c.Close() 5892 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5893 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 5894 5895 cipub = &mqttConnInfo{clientID: "pub", cleanSess: true} 5896 cp, rp = testMQTTConnect(t, cipub, o.MQTT.Host, o.MQTT.Port) 5897 defer cp.Close() 5898 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 5899 5900 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg1")) 5901 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg2")) 5902 5903 testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQos1, []byte("msg1")) 5904 testMQTTExpectNothing(t, r) 5905 5906 // Increase the max ack pending 5907 changeCurrentConfigContentWithNewContent(t, conf, []byte(fmt.Sprintf(template, `"30s"`, `10`))) 5908 // Reload now 5909 if err := s.Reload(); err != nil { 5910 t.Fatalf("Error on reload: %v", err) 5911 } 5912 5913 // Reload will have effect only on new subscriptions. 5914 // Create a new subscription, and we should not be able to get the 2 messages. 5915 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 5916 5917 testMQTTPublish(t, cp, rp, 1, false, false, "bar", 1, []byte("msg3")) 5918 testMQTTPublish(t, cp, rp, 1, false, false, "bar", 1, []byte("msg4")) 5919 5920 testMQTTCheckPubMsg(t, c, r, "bar", mqttPubQos1, []byte("msg3")) 5921 testMQTTCheckPubMsg(t, c, r, "bar", mqttPubQos1, []byte("msg4")) 5922 } 5923 5924 func TestMQTTStreamInfoReturnsNonEmptySubject(t *testing.T) { 5925 o := testMQTTDefaultOptions() 5926 s := testMQTTRunServer(t, o) 5927 defer testMQTTShutdownServer(s) 5928 5929 cisub := &mqttConnInfo{clientID: "sub", cleanSess: false} 5930 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 5931 defer c.Close() 5932 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 5933 5934 nc := natsConnect(t, s.ClientURL()) 5935 defer nc.Close() 5936 5937 // Check that we can query all MQTT streams. MQTT streams are 5938 // created without subject filter, however, if we return them like this, 5939 // the 'nats' utility will fail to display them due to some xml validation. 5940 for _, sname := range []string{ 5941 mqttStreamName, 5942 mqttRetainedMsgsStreamName, 5943 } { 5944 t.Run(sname, func(t *testing.T) { 5945 resp, err := nc.Request(fmt.Sprintf(JSApiStreamInfoT, sname), nil, time.Second) 5946 if err != nil { 5947 t.Fatalf("Unexpected error: %v", err) 5948 } 5949 var bResp JSApiStreamInfoResponse 5950 if err = json.Unmarshal(resp.Data, &bResp); err != nil { 5951 t.Fatalf("Unexpected error: %v", err) 5952 } 5953 if len(bResp.Config.Subjects) == 0 { 5954 t.Fatalf("No subject returned, which will cause nats tooling to fail: %+v", bResp.Config) 5955 } 5956 }) 5957 } 5958 } 5959 5960 func TestMQTTWebsocketToMQTTPort(t *testing.T) { 5961 conf := createConfFile(t, []byte(fmt.Sprintf(` 5962 listen: "127.0.0.1:-1" 5963 http: "127.0.0.1:-1" 5964 server_name: "mqtt" 5965 jetstream { 5966 store_dir = %q 5967 } 5968 mqtt { 5969 listen: "127.0.0.1:-1" 5970 } 5971 websocket { 5972 listen: "127.0.0.1:-1" 5973 no_tls: true 5974 } 5975 `, t.TempDir()))) 5976 s, o := RunServerWithConfig(conf) 5977 defer testMQTTShutdownServer(s) 5978 5979 l := &captureErrorLogger{errCh: make(chan string, 10)} 5980 s.SetLogger(l, false, false) 5981 5982 ci := &mqttConnInfo{cleanSess: true, ws: true} 5983 if _, _, err := testMQTTConnectRetryWithError(t, ci, o.MQTT.Host, o.MQTT.Port, 0); err == nil { 5984 t.Fatal("Expected error during connect") 5985 } 5986 select { 5987 case e := <-l.errCh: 5988 if !strings.Contains(e, errMQTTNotWebsocketPort.Error()) { 5989 t.Fatalf("Unexpected error: %v", e) 5990 } 5991 case <-time.After(time.Second): 5992 t.Fatal("No error regarding wrong port") 5993 } 5994 } 5995 5996 func TestMQTTWebsocket(t *testing.T) { 5997 tdir := t.TempDir() 5998 template := ` 5999 listen: "127.0.0.1:-1" 6000 http: "127.0.0.1:-1" 6001 server_name: "mqtt" 6002 jetstream { 6003 store_dir = %q 6004 } 6005 accounts { 6006 MQTT { 6007 jetstream: enabled 6008 users [ 6009 {user: "mqtt", pass: "pwd", connection_types: ["%s"%s]} 6010 ] 6011 } 6012 } 6013 mqtt { 6014 listen: "127.0.0.1:-1" 6015 } 6016 websocket { 6017 listen: "127.0.0.1:-1" 6018 no_tls: true 6019 } 6020 ` 6021 s, o, conf := runReloadServerWithContent(t, []byte(fmt.Sprintf(template, tdir, jwt.ConnectionTypeMqtt, ""))) 6022 defer testMQTTShutdownServer(s) 6023 6024 cisub := &mqttConnInfo{clientID: "sub", user: "mqtt", pass: "pwd", ws: true} 6025 c, r := testMQTTConnect(t, cisub, o.Websocket.Host, o.Websocket.Port) 6026 defer c.Close() 6027 testMQTTCheckConnAck(t, r, mqttConnAckRCNotAuthorized, false) 6028 c.Close() 6029 6030 ws := fmt.Sprintf(`, "%s"`, jwt.ConnectionTypeMqttWS) 6031 reloadUpdateConfig(t, s, conf, fmt.Sprintf(template, tdir, jwt.ConnectionTypeMqtt, ws)) 6032 6033 cisub = &mqttConnInfo{clientID: "sub", user: "mqtt", pass: "pwd", ws: true} 6034 c, r = testMQTTConnect(t, cisub, o.Websocket.Host, o.Websocket.Port) 6035 defer c.Close() 6036 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 6037 6038 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 6039 testMQTTFlush(t, c, nil, r) 6040 6041 cipub := &mqttConnInfo{clientID: "pub", user: "mqtt", pass: "pwd", ws: true} 6042 cp, rp := testMQTTConnect(t, cipub, o.Websocket.Host, o.Websocket.Port) 6043 defer cp.Close() 6044 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 6045 6046 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg1")) 6047 testMQTTCheckPubMsg(t, c, r, "foo", mqttPubQos1, []byte("msg1")) 6048 } 6049 6050 type chunkWriteConn struct { 6051 net.Conn 6052 } 6053 6054 func (cwc *chunkWriteConn) Write(p []byte) (int, error) { 6055 max := len(p) 6056 cs := rand.Intn(max) + 1 6057 if cs < max { 6058 if pn, perr := cwc.Conn.Write(p[:cs]); perr != nil { 6059 return pn, perr 6060 } 6061 time.Sleep(10 * time.Millisecond) 6062 if pn, perr := cwc.Conn.Write(p[cs:]); perr != nil { 6063 return pn, perr 6064 } 6065 return len(p), nil 6066 } 6067 return cwc.Conn.Write(p) 6068 } 6069 6070 func TestMQTTPartial(t *testing.T) { 6071 conf := createConfFile(t, []byte(fmt.Sprintf(` 6072 listen: "127.0.0.1:-1" 6073 http: "127.0.0.1:-1" 6074 server_name: "mqtt" 6075 jetstream { 6076 store_dir = %q 6077 } 6078 mqtt { 6079 listen: "127.0.0.1:-1" 6080 } 6081 websocket { 6082 listen: "127.0.0.1:-1" 6083 no_tls: true 6084 } 6085 `, t.TempDir()))) 6086 s, o := RunServerWithConfig(conf) 6087 defer testMQTTShutdownServer(s) 6088 6089 for _, test := range []struct { 6090 name string 6091 ws bool 6092 }{ 6093 {"standard", false}, 6094 {"websocket", true}, 6095 } { 6096 t.Run(test.name, func(t *testing.T) { 6097 ci := &mqttConnInfo{cleanSess: true, ws: test.ws} 6098 host, port := o.MQTT.Host, o.MQTT.Port 6099 if test.ws { 6100 host, port = o.Websocket.Host, o.Websocket.Port 6101 } 6102 c, r := testMQTTConnect(t, ci, host, port) 6103 defer c.Close() 6104 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 6105 c = &chunkWriteConn{Conn: c} 6106 6107 cp, rp := testMQTTConnect(t, ci, host, port) 6108 defer cp.Close() 6109 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 6110 cp = &chunkWriteConn{Conn: cp} 6111 6112 subj := nuid.Next() 6113 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: subj, qos: 1}}, []byte{1}) 6114 testMQTTFlush(t, c, nil, r) 6115 for i := 0; i < 10; i++ { 6116 testMQTTPublish(t, cp, rp, 1, false, false, subj, 1, []byte("msg")) 6117 testMQTTCheckPubMsg(t, c, r, subj, mqttPubQos1, []byte("msg")) 6118 } 6119 }) 6120 } 6121 } 6122 6123 func TestMQTTWebsocketTLS(t *testing.T) { 6124 conf := createConfFile(t, []byte(fmt.Sprintf(` 6125 listen: "127.0.0.1:-1" 6126 http: "127.0.0.1:-1" 6127 server_name: "mqtt" 6128 jetstream { 6129 store_dir = %q 6130 } 6131 mqtt { 6132 listen: "127.0.0.1:-1" 6133 } 6134 websocket { 6135 listen: "127.0.0.1:-1" 6136 tls { 6137 cert_file: '../test/configs/certs/server-cert.pem' 6138 key_file: '../test/configs/certs/server-key.pem' 6139 ca_file: '../test/configs/certs/ca.pem' 6140 } 6141 } 6142 `, t.TempDir()))) 6143 s, o := RunServerWithConfig(conf) 6144 defer testMQTTShutdownServer(s) 6145 6146 c, r := testMQTTConnect(t, &mqttConnInfo{clientID: "sub", ws: true, tls: true}, o.Websocket.Host, o.Websocket.Port) 6147 defer c.Close() 6148 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 6149 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 6150 testMQTTFlush(t, c, nil, r) 6151 6152 cp, rp := testMQTTConnect(t, &mqttConnInfo{clientID: "pub", ws: true, tls: true}, o.Websocket.Host, o.Websocket.Port) 6153 defer cp.Close() 6154 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 6155 6156 testMQTTPublish(t, cp, rp, 1, false, false, "foo", 1, []byte("msg1")) 6157 testMQTTCheckPubMsg(t, c, r, "foo", mqttPubQos1, []byte("msg1")) 6158 } 6159 6160 func TestMQTTTransferSessionStreamsToMuxed(t *testing.T) { 6161 cl := createJetStreamClusterWithTemplate(t, testMQTTGetClusterTemplaceNoLeaf(), "MQTT", 3) 6162 defer cl.shutdown() 6163 6164 nc, js := jsClientConnect(t, cl.randomServer()) 6165 defer nc.Close() 6166 6167 // Create 2 streams that start with "$MQTT_sess_" to check for transfer to new 6168 // mux'ed unique "$MQTT_sess" stream. One of this stream will not contain a 6169 // proper session record, and we will check that the stream does not get deleted. 6170 sessStreamName1 := mqttSessionsStreamNamePrefix + getHash("sub") 6171 if _, err := js.AddStream(&nats.StreamConfig{ 6172 Name: sessStreamName1, 6173 Subjects: []string{sessStreamName1}, 6174 Replicas: 3, 6175 MaxMsgs: 1, 6176 }); err != nil { 6177 t.Fatalf("Unable to add stream: %v", err) 6178 } 6179 // Then add the session record 6180 ps := mqttPersistedSession{ 6181 ID: "sub", 6182 Subs: map[string]byte{"foo": 1}, 6183 Cons: map[string]*ConsumerConfig{"foo": { 6184 Durable: "d6INCtp3_cK39H5WHEtOSU7sLy2oQv3", 6185 DeliverSubject: "$MQTT.sub.cK39H5WHEtOSU7sLy2oQrR", 6186 DeliverPolicy: DeliverNew, 6187 AckPolicy: AckExplicit, 6188 FilterSubject: "$MQTT.msgs.foo", 6189 MaxAckPending: 1024, 6190 }}, 6191 } 6192 b, _ := json.Marshal(&ps) 6193 if _, err := js.Publish(sessStreamName1, b); err != nil { 6194 t.Fatalf("Error on publish: %v", err) 6195 } 6196 6197 // Create the stream that has "$MQTT_sess_" prefix, but that is not really a MQTT session stream 6198 sessStreamName2 := mqttSessionsStreamNamePrefix + "ivan" 6199 if _, err := js.AddStream(&nats.StreamConfig{ 6200 Name: sessStreamName2, 6201 Subjects: []string{sessStreamName2}, 6202 Replicas: 3, 6203 MaxMsgs: 1, 6204 }); err != nil { 6205 t.Fatalf("Unable to add stream: %v", err) 6206 } 6207 if _, err := js.Publish(sessStreamName2, []byte("some content")); err != nil { 6208 t.Fatalf("Error on publish: %v", err) 6209 } 6210 6211 cl.waitOnStreamLeader(globalAccountName, sessStreamName1) 6212 cl.waitOnStreamLeader(globalAccountName, sessStreamName2) 6213 6214 // Now create a real MQTT connection 6215 o := cl.opts[0] 6216 sc, sr := testMQTTConnectRetry(t, &mqttConnInfo{clientID: "sub"}, o.MQTT.Host, o.MQTT.Port, 10) 6217 defer sc.Close() 6218 testMQTTCheckConnAck(t, sr, mqttConnAckRCConnectionAccepted, true) 6219 6220 // Check that old session stream is gone, but the non session stream is still present. 6221 var gotIt = false 6222 for info := range js.StreamsInfo() { 6223 if strings.HasPrefix(info.Config.Name, mqttSessionsStreamNamePrefix) { 6224 if strings.HasSuffix(info.Config.Name, "_ivan") { 6225 gotIt = true 6226 } else { 6227 t.Fatalf("The stream %q should have been deleted", info.Config.Name) 6228 } 6229 } 6230 } 6231 if !gotIt { 6232 t.Fatalf("The stream %q should not have been deleted", mqttSessionsStreamNamePrefix+"ivan") 6233 } 6234 6235 // We want to check that the record was properly transferred. 6236 rmsg, err := js.GetMsg(mqttSessStreamName, 2) 6237 if err != nil { 6238 t.Fatalf("Unable to get session message: %v", err) 6239 } 6240 ps2 := &mqttPersistedSession{} 6241 if err := json.Unmarshal(rmsg.Data, ps2); err != nil { 6242 t.Fatalf("Error unpacking session record: %v", err) 6243 } 6244 if ps2.ID != "sub" { 6245 t.Fatalf("Unexpected session record, %+v vs %+v", ps2, ps) 6246 } 6247 if qos, ok := ps2.Subs["foo"]; !ok || qos != 1 { 6248 t.Fatalf("Unexpected session record, %+v vs %+v", ps2, ps) 6249 } 6250 if cons, ok := ps2.Cons["foo"]; !ok || !reflect.DeepEqual(cons, ps.Cons["foo"]) { 6251 t.Fatalf("Unexpected session record, %+v vs %+v", ps2, ps) 6252 } 6253 6254 // Make sure we don't attempt to transfer again by creating a subscription 6255 // on the "stream names" API, which is used to get the list of streams to transfer 6256 sub := natsSubSync(t, nc, JSApiStreams) 6257 6258 // Make sure to connect an MQTT client from a different node so that this node 6259 // gets a connection for the account for the first time and tries to create 6260 // all MQTT streams, etc.. 6261 o = cl.opts[1] 6262 sc, sr = testMQTTConnectRetry(t, &mqttConnInfo{clientID: "sub2"}, o.MQTT.Host, o.MQTT.Port, 10) 6263 defer sc.Close() 6264 testMQTTCheckConnAck(t, sr, mqttConnAckRCConnectionAccepted, false) 6265 6266 if _, err := sub.NextMsg(200 * time.Millisecond); err == nil { 6267 t.Fatal("Looks like attempt to transfer was done again") 6268 } 6269 } 6270 6271 func TestMQTTConnectAndDisconnectEvent(t *testing.T) { 6272 conf := createConfFile(t, []byte(fmt.Sprintf(` 6273 listen: "127.0.0.1:-1" 6274 http: "127.0.0.1:-1" 6275 server_name: "mqtt" 6276 jetstream { 6277 store_dir = %q 6278 } 6279 accounts { 6280 MQTT { 6281 jetstream: enabled 6282 users: [{user: "mqtt", password: "pwd"}] 6283 } 6284 SYS { 6285 users: [{user: "sys", password: "pwd"}] 6286 } 6287 } 6288 mqtt { 6289 listen: "127.0.0.1:-1" 6290 } 6291 system_account: "SYS" 6292 `, t.TempDir()))) 6293 defer os.Remove(conf) 6294 s, o := RunServerWithConfig(conf) 6295 defer testMQTTShutdownServer(s) 6296 6297 nc := natsConnect(t, s.ClientURL(), nats.UserInfo("sys", "pwd")) 6298 defer nc.Close() 6299 6300 accConn := natsSubSync(t, nc, fmt.Sprintf(connectEventSubj, "MQTT")) 6301 accDisc := natsSubSync(t, nc, fmt.Sprintf(disconnectEventSubj, "MQTT")) 6302 accAuth := natsSubSync(t, nc, fmt.Sprintf(authErrorEventSubj, s.ID())) 6303 natsFlush(t, nc) 6304 6305 checkConnEvent := func(data []byte, expected string) { 6306 t.Helper() 6307 var ce ConnectEventMsg 6308 json.Unmarshal(data, &ce) 6309 if ce.Client.MQTTClient != expected { 6310 t.Fatalf("Expected client ID %q, got this connect event: %+v", expected, ce) 6311 } 6312 } 6313 checkDiscEvent := func(data []byte, expected string) { 6314 t.Helper() 6315 var de DisconnectEventMsg 6316 json.Unmarshal(data, &de) 6317 if de.Client.MQTTClient != expected { 6318 t.Fatalf("Expected client ID %q, got this disconnect event: %+v", expected, de) 6319 } 6320 } 6321 6322 c1, r1 := testMQTTConnect(t, &mqttConnInfo{user: "mqtt", pass: "pwd", clientID: "conn1", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 6323 defer c1.Close() 6324 testMQTTCheckConnAck(t, r1, mqttConnAckRCConnectionAccepted, false) 6325 6326 cm := natsNexMsg(t, accConn, time.Second) 6327 checkConnEvent(cm.Data, "conn1") 6328 6329 c2, r2 := testMQTTConnect(t, &mqttConnInfo{user: "mqtt", pass: "pwd", clientID: "conn2", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 6330 defer c2.Close() 6331 testMQTTCheckConnAck(t, r2, mqttConnAckRCConnectionAccepted, false) 6332 6333 cm = natsNexMsg(t, accConn, time.Second) 6334 checkConnEvent(cm.Data, "conn2") 6335 6336 c3, r3 := testMQTTConnect(t, &mqttConnInfo{user: "mqtt", pass: "pwd", clientID: "conn3", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 6337 defer c3.Close() 6338 testMQTTCheckConnAck(t, r3, mqttConnAckRCConnectionAccepted, false) 6339 6340 cm = natsNexMsg(t, accConn, time.Second) 6341 checkConnEvent(cm.Data, "conn3") 6342 6343 testMQTTDisconnect(t, c3, nil) 6344 cm = natsNexMsg(t, accDisc, time.Second) 6345 checkDiscEvent(cm.Data, "conn3") 6346 6347 // Now try a bad auth 6348 c4, r4 := testMQTTConnect(t, &mqttConnInfo{clientID: "conn4", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 6349 defer c4.Close() 6350 testMQTTCheckConnAck(t, r4, mqttConnAckRCNotAuthorized, false) 6351 // This will generate an auth error, which is a disconnect event 6352 cm = natsNexMsg(t, accAuth, time.Second) 6353 checkDiscEvent(cm.Data, "conn4") 6354 6355 url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port) 6356 for mode := 0; mode < 2; mode++ { 6357 c := pollConz(t, s, mode, url+"connz", nil) 6358 if c.Conns == nil || len(c.Conns) != 3 { 6359 t.Fatalf("Expected 3 connections in array, got %v", len(c.Conns)) 6360 } 6361 6362 // Check that client ID is present 6363 for _, conn := range c.Conns { 6364 if conn.Type == clientTypeStringMap[MQTT] && conn.MQTTClient == _EMPTY_ { 6365 t.Fatalf("Expected a client ID to be set, got %+v", conn) 6366 } 6367 } 6368 6369 // Check that we can select based on client ID: 6370 c = pollConz(t, s, mode, url+"connz?mqtt_client=conn2", &ConnzOptions{MQTTClient: "conn2"}) 6371 if c.Conns == nil || len(c.Conns) != 1 { 6372 t.Fatalf("Expected 1 connection in array, got %v", len(c.Conns)) 6373 } 6374 if c.Conns[0].MQTTClient != "conn2" { 6375 t.Fatalf("Unexpected client ID: %+v", c.Conns[0]) 6376 } 6377 6378 // Check that we have the closed ones 6379 c = pollConz(t, s, mode, url+"connz?state=closed", &ConnzOptions{State: ConnClosed}) 6380 if c.Conns == nil || len(c.Conns) != 2 { 6381 t.Fatalf("Expected 2 connections in array, got %v", len(c.Conns)) 6382 } 6383 for _, conn := range c.Conns { 6384 if conn.MQTTClient == _EMPTY_ { 6385 t.Fatalf("Expected a client ID, got %+v", conn) 6386 } 6387 } 6388 6389 // Check that we can select with client ID for closed state 6390 c = pollConz(t, s, mode, url+"connz?state=closed&mqtt_client=conn3", &ConnzOptions{State: ConnClosed, MQTTClient: "conn3"}) 6391 if c.Conns == nil || len(c.Conns) != 1 { 6392 t.Fatalf("Expected 1 connection in array, got %v", len(c.Conns)) 6393 } 6394 if c.Conns[0].MQTTClient != "conn3" { 6395 t.Fatalf("Unexpected client ID: %+v", c.Conns[0]) 6396 } 6397 // Check that we can select with client ID for closed state (but in this case not found) 6398 c = pollConz(t, s, mode, url+"connz?state=closed&mqtt_client=conn5", &ConnzOptions{State: ConnClosed, MQTTClient: "conn5"}) 6399 if len(c.Conns) != 0 { 6400 t.Fatalf("Expected 0 connection in array, got %v", len(c.Conns)) 6401 } 6402 } 6403 6404 reply := nc.NewRespInbox() 6405 replySub := natsSubSync(t, nc, reply) 6406 6407 // Test system events now 6408 for _, test := range []struct { 6409 opt any 6410 cid string 6411 }{ 6412 {&ConnzOptions{MQTTClient: "conn1"}, "conn1"}, 6413 {&ConnzOptions{MQTTClient: "conn3", State: ConnClosed}, "conn3"}, 6414 {&ConnzOptions{MQTTClient: "conn4", State: ConnClosed}, "conn4"}, 6415 {&ConnzOptions{MQTTClient: "conn5"}, _EMPTY_}, 6416 {json.RawMessage(`{"mqtt_client":"conn1"}`), "conn1"}, 6417 {json.RawMessage(fmt.Sprintf(`{"mqtt_client":"conn3", "state":%v}`, ConnClosed)), "conn3"}, 6418 {json.RawMessage(fmt.Sprintf(`{"mqtt_client":"conn4", "state":%v}`, ConnClosed)), "conn4"}, 6419 {json.RawMessage(`{"mqtt_client":"conn5"}`), _EMPTY_}, 6420 } { 6421 t.Run("sys connz", func(t *testing.T) { 6422 b, _ := json.Marshal(test.opt) 6423 6424 // set a header to make sure request parsing knows to ignore them 6425 nc.PublishMsg(&nats.Msg{ 6426 Subject: fmt.Sprintf("%s.CONNZ", serverStatsPingReqSubj), 6427 Reply: reply, 6428 Data: b, 6429 }) 6430 6431 msg := natsNexMsg(t, replySub, time.Second) 6432 var response ServerAPIResponse 6433 if err := json.Unmarshal(msg.Data, &response); err != nil { 6434 t.Fatalf("Error unmarshalling response json: %v", err) 6435 } 6436 tmp, _ := json.Marshal(response.Data) 6437 cz := &Connz{} 6438 if err := json.Unmarshal(tmp, cz); err != nil { 6439 t.Fatalf("Error unmarshalling connz: %v", err) 6440 } 6441 if test.cid == _EMPTY_ { 6442 if len(cz.Conns) != 0 { 6443 t.Fatalf("Expected no connections, got %v", len(cz.Conns)) 6444 } 6445 return 6446 } 6447 if len(cz.Conns) != 1 { 6448 t.Fatalf("Expected single connection, got %v", len(cz.Conns)) 6449 } 6450 conn := cz.Conns[0] 6451 if conn.MQTTClient != test.cid { 6452 t.Fatalf("Expected client ID %q, got %q", test.cid, conn.MQTTClient) 6453 } 6454 }) 6455 } 6456 } 6457 6458 func TestMQTTClientIDInLogStatements(t *testing.T) { 6459 o := testMQTTDefaultOptions() 6460 s := testMQTTRunServer(t, o) 6461 defer testMQTTShutdownServer(s) 6462 6463 l := &captureDebugLogger{dbgCh: make(chan string, 10)} 6464 s.SetLogger(l, true, false) 6465 6466 cisub := &mqttConnInfo{clientID: "my_client_id", cleanSess: false} 6467 c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) 6468 defer c.Close() 6469 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 6470 testMQTTDisconnect(t, c, nil) 6471 c.Close() 6472 6473 tm := time.NewTimer(2 * time.Second) 6474 var connected bool 6475 var disconnected bool 6476 for { 6477 select { 6478 case dl := <-l.dbgCh: 6479 if strings.Contains(dl, "my_client_id") { 6480 if strings.Contains(dl, "Client connected") { 6481 connected = true 6482 } else if strings.Contains(dl, "Client connection closed") { 6483 disconnected = true 6484 } 6485 if connected && disconnected { 6486 // OK! 6487 return 6488 } 6489 } 6490 case <-tm.C: 6491 t.Fatal("Did not get the debug statements or client_id in them") 6492 } 6493 } 6494 } 6495 6496 func TestMQTTStreamReplicasOverride(t *testing.T) { 6497 conf := ` 6498 listen: 127.0.0.1:-1 6499 server_name: %s 6500 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 6501 6502 cluster { 6503 name: %s 6504 listen: 127.0.0.1:%d 6505 routes = [%s] 6506 } 6507 6508 mqtt { 6509 listen: 127.0.0.1:-1 6510 stream_replicas: 3 6511 } 6512 6513 # For access to system account. 6514 accounts { $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } } 6515 ` 6516 cl := createJetStreamClusterWithTemplate(t, conf, "MQTT", 3) 6517 defer cl.shutdown() 6518 6519 connectAndCheck := func(restarted bool) { 6520 t.Helper() 6521 6522 o := cl.opts[0] 6523 mc, r := testMQTTConnectRetry(t, &mqttConnInfo{clientID: "test", cleanSess: false}, o.MQTT.Host, o.MQTT.Port, 5) 6524 defer mc.Close() 6525 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, restarted) 6526 6527 nc, js := jsClientConnect(t, cl.servers[2]) 6528 defer nc.Close() 6529 6530 streams := []string{mqttStreamName, mqttRetainedMsgsStreamName, mqttSessStreamName} 6531 for _, sn := range streams { 6532 si, err := js.StreamInfo(sn) 6533 require_NoError(t, err) 6534 if n := len(si.Cluster.Replicas); n != 2 { 6535 t.Fatalf("Expected stream %q to have 2 replicas, got %v", sn, n) 6536 } 6537 } 6538 } 6539 connectAndCheck(false) 6540 6541 cl.stopAll() 6542 for _, o := range cl.opts { 6543 o.MQTT.StreamReplicas = 2 6544 } 6545 cl.restartAllSamePorts() 6546 cl.waitOnStreamLeader(globalAccountName, mqttStreamName) 6547 cl.waitOnStreamLeader(globalAccountName, mqttRetainedMsgsStreamName) 6548 cl.waitOnStreamLeader(globalAccountName, mqttSessStreamName) 6549 6550 l := &captureWarnLogger{warn: make(chan string, 10)} 6551 cl.servers[0].SetLogger(l, false, false) 6552 6553 connectAndCheck(true) 6554 6555 select { 6556 case w := <-l.warn: 6557 if !strings.Contains(w, "current is 3 but configuration is 2") { 6558 t.Fatalf("Unexpected warning: %q", w) 6559 } 6560 case <-time.After(2 * time.Second): 6561 t.Fatal("Should have warned against replicas mismatch") 6562 } 6563 } 6564 6565 func TestMQTTStreamReplicasConfigReload(t *testing.T) { 6566 tdir := t.TempDir() 6567 tmpl := ` 6568 jetstream { 6569 store_dir = %q 6570 } 6571 server_name: mqtt 6572 mqtt { 6573 port: -1 6574 stream_replicas: %v 6575 } 6576 ` 6577 conf := createConfFile(t, []byte(fmt.Sprintf(tmpl, tdir, 3))) 6578 s, o := RunServerWithConfig(conf) 6579 defer testMQTTShutdownServer(s) 6580 6581 l := &captureErrorLogger{errCh: make(chan string, 10)} 6582 s.SetLogger(l, false, false) 6583 6584 _, _, err := testMQTTConnectRetryWithError(t, &mqttConnInfo{clientID: "mqtt", cleanSess: false}, o.MQTT.Host, o.MQTT.Port, 0) 6585 if err == nil { 6586 t.Fatal("Expected to fail, did not") 6587 } 6588 6589 select { 6590 case e := <-l.errCh: 6591 if !strings.Contains(e, NewJSStreamReplicasNotSupportedError().Description) { 6592 t.Fatalf("Expected error regarding replicas, got %v", e) 6593 } 6594 case <-time.After(2 * time.Second): 6595 t.Fatalf("Did not get the error regarding replicas count") 6596 } 6597 6598 reloadUpdateConfig(t, s, conf, fmt.Sprintf(tmpl, tdir, 1)) 6599 6600 mc, r := testMQTTConnect(t, &mqttConnInfo{clientID: "mqtt", cleanSess: false}, o.MQTT.Host, o.MQTT.Port) 6601 defer mc.Close() 6602 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 6603 } 6604 6605 func TestMQTTStreamReplicasInsufficientResources(t *testing.T) { 6606 conf := ` 6607 listen: 127.0.0.1:-1 6608 server_name: %s 6609 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 6610 6611 cluster { 6612 name: %s 6613 listen: 127.0.0.1:%d 6614 routes = [%s] 6615 } 6616 6617 mqtt { 6618 listen: 127.0.0.1:-1 6619 stream_replicas: 5 6620 } 6621 6622 # For access to system account. 6623 accounts { $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } } 6624 ` 6625 cl := createJetStreamClusterWithTemplate(t, conf, "MQTT", 3) 6626 defer cl.shutdown() 6627 6628 l := &captureErrorLogger{errCh: make(chan string, 10)} 6629 for _, s := range cl.servers { 6630 s.SetLogger(l, false, false) 6631 } 6632 6633 o := cl.opts[1] 6634 _, _, err := testMQTTConnectRetryWithError(t, &mqttConnInfo{clientID: "mqtt", cleanSess: false}, o.MQTT.Host, o.MQTT.Port, 0) 6635 if err == nil { 6636 t.Fatal("Expected to fail, did not") 6637 } 6638 6639 select { 6640 case e := <-l.errCh: 6641 if !strings.Contains(e, fmt.Sprintf("%d", NewJSClusterNoPeersError(errors.New("")).ErrCode)) { 6642 t.Fatalf("Expected error regarding no peers error, got %v", e) 6643 } 6644 case <-time.After(2 * time.Second): 6645 t.Fatalf("Did not get the error regarding replicas count") 6646 } 6647 } 6648 6649 func TestMQTTConsumerReplicasValidate(t *testing.T) { 6650 o := testMQTTDefaultOptions() 6651 for _, test := range []struct { 6652 name string 6653 sr int 6654 cr int 6655 err bool 6656 }{ 6657 {"stream replicas neg", -1, 3, false}, 6658 {"stream replicas 0", 0, 3, false}, 6659 {"consumer replicas neg", 0, -1, false}, 6660 {"consumer replicas 0", -1, 0, false}, 6661 {"consumer replicas too high", 1, 2, true}, 6662 } { 6663 t.Run(test.name, func(t *testing.T) { 6664 o.MQTT.StreamReplicas = test.sr 6665 o.MQTT.ConsumerReplicas = test.cr 6666 err := validateMQTTOptions(o) 6667 if test.err { 6668 if err == nil { 6669 t.Fatal("Expected error, did not get one") 6670 } 6671 if !strings.Contains(err.Error(), "cannot be higher") { 6672 t.Fatalf("Unexpected error: %v", err) 6673 } 6674 // OK 6675 return 6676 } else if err != nil { 6677 t.Fatalf("Unexpected error: %v", err) 6678 } 6679 }) 6680 } 6681 } 6682 6683 // This was ill-advised since the messages stream is currently interest policy. 6684 // Interest policy streams require consumers match the replica count. 6685 // Will leave her for now to make sure we do not override. 6686 func TestMQTTConsumerReplicasOverride(t *testing.T) { 6687 conf := ` 6688 listen: 127.0.0.1:-1 6689 server_name: %s 6690 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 6691 6692 cluster { 6693 name: %s 6694 listen: 127.0.0.1:%d 6695 routes = [%s] 6696 } 6697 6698 mqtt { 6699 listen: 127.0.0.1:-1 6700 stream_replicas: 5 6701 consumer_replicas: 1 6702 consumer_memory_storage: true 6703 } 6704 6705 # For access to system account. 6706 accounts { $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } } 6707 ` 6708 cl := createJetStreamClusterWithTemplate(t, conf, "MQTT", 5) 6709 defer cl.shutdown() 6710 6711 connectAndCheck := func(subject string, restarted bool) { 6712 t.Helper() 6713 6714 o := cl.opts[0] 6715 mc, r := testMQTTConnectRetry(t, &mqttConnInfo{clientID: "test", cleanSess: false}, o.MQTT.Host, o.MQTT.Port, 5) 6716 defer mc.Close() 6717 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, restarted) 6718 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: subject, qos: 1}}, []byte{1}) 6719 6720 nc, js := jsClientConnect(t, cl.servers[2]) 6721 defer nc.Close() 6722 6723 for ci := range js.ConsumersInfo(mqttStreamName) { 6724 if ci.Config.FilterSubject == mqttStreamSubjectPrefix+subject { 6725 if rf := len(ci.Cluster.Replicas) + 1; rf != 5 { 6726 t.Fatalf("Expected consumer to be R5, got: %d", rf) 6727 } 6728 } 6729 } 6730 } 6731 connectAndCheck("foo", false) 6732 6733 cl.stopAll() 6734 for _, o := range cl.opts { 6735 o.MQTT.ConsumerReplicas = 2 6736 o.MQTT.ConsumerMemoryStorage = false 6737 } 6738 cl.restartAllSamePorts() 6739 cl.waitOnStreamLeader(globalAccountName, mqttStreamName) 6740 cl.waitOnStreamLeader(globalAccountName, mqttRetainedMsgsStreamName) 6741 cl.waitOnStreamLeader(globalAccountName, mqttSessStreamName) 6742 6743 connectAndCheck("bar", true) 6744 } 6745 6746 func TestMQTTConsumerMemStorageReload(t *testing.T) { 6747 tdir := t.TempDir() 6748 tmpl := ` 6749 jetstream { 6750 store_dir = %q 6751 } 6752 server_name: mqtt 6753 mqtt { 6754 port: -1 6755 consumer_memory_storage: %s 6756 } 6757 ` 6758 conf := createConfFile(t, []byte(fmt.Sprintf(tmpl, tdir, "false"))) 6759 s, o := RunServerWithConfig(conf) 6760 defer testMQTTShutdownServer(s) 6761 6762 l := &captureErrorLogger{errCh: make(chan string, 10)} 6763 s.SetLogger(l, false, false) 6764 6765 c, r := testMQTTConnect(t, &mqttConnInfo{clientID: "sub", cleanSess: false}, o.MQTT.Host, o.MQTT.Port) 6766 defer c.Close() 6767 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 6768 6769 reloadUpdateConfig(t, s, conf, fmt.Sprintf(tmpl, tdir, "true")) 6770 6771 testMQTTSub(t, 1, c, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 6772 6773 mset, err := s.GlobalAccount().lookupStream(mqttStreamName) 6774 if err != nil { 6775 t.Fatalf("Error looking up stream: %v", err) 6776 } 6777 var cons *consumer 6778 mset.mu.RLock() 6779 for _, c := range mset.consumers { 6780 cons = c 6781 break 6782 } 6783 mset.mu.RUnlock() 6784 cons.mu.RLock() 6785 st := cons.store.Type() 6786 cons.mu.RUnlock() 6787 if st != MemoryStorage { 6788 t.Fatalf("Expected storage %v, got %v", MemoryStorage, st) 6789 } 6790 } 6791 6792 type unableToDeleteConsLogger struct { 6793 DummyLogger 6794 errCh chan string 6795 } 6796 6797 func (l *unableToDeleteConsLogger) Errorf(format string, args ...any) { 6798 msg := fmt.Sprintf(format, args...) 6799 if strings.Contains(msg, "unable to delete consumer") { 6800 l.errCh <- msg 6801 } 6802 } 6803 6804 func TestMQTTSessionNotDeletedOnDeleteConsumerError(t *testing.T) { 6805 org := mqttJSAPITimeout 6806 mqttJSAPITimeout = 1000 * time.Millisecond 6807 defer func() { mqttJSAPITimeout = org }() 6808 6809 cl := createJetStreamClusterWithTemplate(t, testMQTTGetClusterTemplaceNoLeaf(), "MQTT", 2) 6810 defer cl.shutdown() 6811 6812 o := cl.opts[0] 6813 s1 := cl.servers[0] 6814 // Plug error logger to s1 6815 l := &unableToDeleteConsLogger{errCh: make(chan string, 10)} 6816 s1.SetLogger(l, false, false) 6817 6818 nc, js := jsClientConnect(t, s1) 6819 defer nc.Close() 6820 6821 mc, r := testMQTTConnectRetry(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port, 5) 6822 defer mc.Close() 6823 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 6824 6825 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 6826 testMQTTFlush(t, mc, nil, r) 6827 6828 // Now shutdown server 2, we should lose quorum 6829 cl.servers[1].Shutdown() 6830 6831 // Close the MQTT client: 6832 testMQTTDisconnect(t, mc, nil) 6833 6834 // We should have reported that there was an error deleting the consumer 6835 select { 6836 case <-l.errCh: 6837 // OK 6838 case <-time.After(time.Second): 6839 t.Fatal("Server did not report any error") 6840 } 6841 6842 // Now restart the server 2 so that we can check that the session is still persisted. 6843 cl.restartAllSamePorts() 6844 cl.waitOnStreamLeader(globalAccountName, mqttSessStreamName) 6845 6846 si, err := js.StreamInfo(mqttSessStreamName) 6847 require_NoError(t, err) 6848 require_True(t, si.State.Msgs == 1) 6849 } 6850 6851 // Test for auto-cleanup of consumers. 6852 func TestMQTTConsumerInactiveThreshold(t *testing.T) { 6853 tdir := t.TempDir() 6854 tmpl := ` 6855 listen: 127.0.0.1:-1 6856 server_name: mqtt 6857 jetstream { 6858 store_dir = %q 6859 } 6860 6861 mqtt { 6862 listen: 127.0.0.1:-1 6863 consumer_inactive_threshold: %q 6864 } 6865 6866 # For access to system account. 6867 accounts { $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } } 6868 ` 6869 conf := createConfFile(t, []byte(fmt.Sprintf(tmpl, tdir, "0.2s"))) 6870 s, o := RunServerWithConfig(conf) 6871 defer testMQTTShutdownServer(s) 6872 6873 mc, r := testMQTTConnectRetry(t, &mqttConnInfo{clientID: "test", cleanSess: true}, o.MQTT.Host, o.MQTT.Port, 5) 6874 defer mc.Close() 6875 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 6876 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 6877 6878 nc, js := jsClientConnect(t, s) 6879 defer nc.Close() 6880 6881 ci := <-js.ConsumersInfo("$MQTT_msgs") 6882 6883 // Make sure we clean up this consumer. 6884 mc.Close() 6885 checkFor(t, 2*time.Second, 50*time.Millisecond, func() error { 6886 _, err := js.ConsumerInfo(ci.Stream, ci.Name) 6887 if err == nil { 6888 return fmt.Errorf("Consumer still present") 6889 } 6890 return nil 6891 }) 6892 6893 // Check reload. 6894 // We will not redo existing consumers however. 6895 reloadUpdateConfig(t, s, conf, fmt.Sprintf(tmpl, tdir, "22s")) 6896 if opts := s.getOpts(); opts.MQTT.ConsumerInactiveThreshold != 22*time.Second { 6897 t.Fatalf("Expected reloaded value of %v but got %v", 22*time.Second, opts.MQTT.ConsumerInactiveThreshold) 6898 } 6899 } 6900 6901 func TestMQTTSubjectMapping(t *testing.T) { 6902 conf := createConfFile(t, []byte(fmt.Sprintf(` 6903 listen: 127.0.0.1:-1 6904 server_name: mqtt 6905 jetstream { 6906 store_dir = %q 6907 } 6908 6909 mappings = { 6910 foo0: bar0 6911 foo1: bar1 6912 } 6913 6914 mqtt { 6915 listen: 127.0.0.1:-1 6916 } 6917 `, t.TempDir()))) 6918 s, o := RunServerWithConfig(conf) 6919 defer testMQTTShutdownServer(s) 6920 6921 nc, js := jsClientConnect(t, s) 6922 defer nc.Close() 6923 6924 for _, qos := range []byte{0, 1} { 6925 t.Run(fmt.Sprintf("qos%d", qos), func(t *testing.T) { 6926 mc, r := testMQTTConnect(t, &mqttConnInfo{clientID: "sub", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 6927 defer mc.Close() 6928 6929 bar := fmt.Sprintf("bar%v", qos) 6930 foo := fmt.Sprintf("foo%v", qos) 6931 6932 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 6933 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: bar, qos: qos}}, []byte{qos}) 6934 testMQTTFlush(t, mc, nil, r) 6935 6936 mcp, rp := testMQTTConnect(t, &mqttConnInfo{clientID: "pub", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 6937 defer mcp.Close() 6938 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 6939 6940 natsPub(t, nc, foo, []byte("msg0")) 6941 testMQTTCheckPubMsgNoAck(t, mc, r, bar, 0, []byte("msg0")) 6942 6943 testMQTTPublish(t, mcp, rp, 0, false, false, foo, 0, []byte("msg1")) 6944 testMQTTCheckPubMsgNoAck(t, mc, r, bar, 0, []byte("msg1")) 6945 6946 testMQTTPublish(t, mcp, rp, 0, false, true, foo, 0, []byte("msg1_retained")) 6947 testMQTTCheckPubMsgNoAck(t, mc, r, bar, 0, []byte("msg1_retained")) 6948 6949 testMQTTPublish(t, mcp, rp, 1, false, false, foo, 1, []byte("msg2")) 6950 // For the receiving side, the expected QoS is based on the subscription's QoS, 6951 // not the publisher. 6952 expected := byte(0) 6953 if qos == 1 { 6954 expected = mqttPubQos1 6955 } 6956 testMQTTCheckPubMsgNoAck(t, mc, r, bar, expected, []byte("msg2")) 6957 6958 testMQTTPublish(t, mcp, rp, 1, false, true, foo, 1, []byte("msg2_retained")) 6959 testMQTTCheckPubMsgNoAck(t, mc, r, bar, expected, []byte("msg2_retained")) 6960 6961 testMQTTDisconnect(t, mcp, nil) 6962 6963 // Try the with the "will" with QoS0 first 6964 mcp, rp = testMQTTConnect(t, &mqttConnInfo{ 6965 clientID: "pub", 6966 cleanSess: true, 6967 will: &mqttWill{topic: []byte(foo), qos: 0, message: []byte("willmsg1")}}, 6968 o.MQTT.Host, o.MQTT.Port) 6969 defer mcp.Close() 6970 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 6971 testMQTTFlush(t, mcp, nil, rp) 6972 6973 // Close the connection without proper disconnect for will to be sent 6974 mcp.Close() 6975 testMQTTCheckPubMsgNoAck(t, mc, r, bar, 0, []byte("willmsg1")) 6976 6977 // Try the with the "will" with QoS1 now 6978 mcp, rp = testMQTTConnect(t, &mqttConnInfo{ 6979 clientID: "pub", 6980 cleanSess: true, 6981 will: &mqttWill{topic: []byte(foo), qos: 1, message: []byte("willmsg2")}}, 6982 o.MQTT.Host, o.MQTT.Port) 6983 defer mcp.Close() 6984 testMQTTCheckConnAck(t, rp, mqttConnAckRCConnectionAccepted, false) 6985 testMQTTFlush(t, mcp, nil, rp) 6986 6987 // Close the connection without proper disconnect for will to be sent 6988 mcp.Close() 6989 testMQTTCheckPubMsgNoAck(t, mc, r, bar, expected, []byte("willmsg2")) 6990 6991 si, err := js.StreamInfo("$MQTT_msgs") 6992 require_NoError(t, err) 6993 if qos == 0 { 6994 require_True(t, si.State.Msgs == 0) 6995 require_True(t, si.State.NumSubjects == 0) 6996 } else { 6997 // Number of QoS1 messages: 1 regular, 1 retained, 1 from will. 6998 require_True(t, si.State.Msgs == 3) 6999 require_True(t, si.State.NumSubjects == 1) 7000 } 7001 testMQTTDisconnect(t, mc, nil) 7002 }) 7003 } 7004 } 7005 7006 func TestMQTTSubjectMappingWithImportExport(t *testing.T) { 7007 conf := createConfFile(t, []byte(fmt.Sprintf(` 7008 listen: 127.0.0.1:-1 7009 server_name: mqtt 7010 jetstream { 7011 store_dir = %q 7012 } 7013 7014 accounts { 7015 A { 7016 users = [{user: "a", password: "pwd"}] 7017 mappings = { 7018 bar: foo 7019 } 7020 exports = [{service: "bar"}] 7021 jetstream: enabled 7022 } 7023 B { 7024 users = [{user: "b", password: "pwd"}] 7025 mappings = { 7026 foo: bar 7027 } 7028 imports = [{service: {account: "A", subject: "bar"}}] 7029 jetstream: enabled 7030 } 7031 $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } 7032 } 7033 7034 mqtt { 7035 listen: 127.0.0.1:-1 7036 } 7037 `, t.TempDir()))) 7038 s, o := RunServerWithConfig(conf) 7039 defer testMQTTShutdownServer(s) 7040 7041 c1, r1 := testMQTTConnect(t, &mqttConnInfo{user: "a", pass: "pwd", clientID: "a1", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7042 defer c1.Close() 7043 testMQTTCheckConnAck(t, r1, mqttConnAckRCConnectionAccepted, false) 7044 testMQTTSub(t, 1, c1, r1, []*mqttFilter{{filter: "foo", qos: 0}}, []byte{0}) 7045 testMQTTFlush(t, c1, nil, r1) 7046 7047 c2, r2 := testMQTTConnect(t, &mqttConnInfo{user: "a", pass: "pwd", clientID: "a2", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7048 defer c2.Close() 7049 testMQTTCheckConnAck(t, r2, mqttConnAckRCConnectionAccepted, false) 7050 testMQTTSub(t, 1, c2, r2, []*mqttFilter{{filter: "foo", qos: 1}}, []byte{1}) 7051 testMQTTFlush(t, c2, nil, r2) 7052 7053 c3, r3 := testMQTTConnect(t, &mqttConnInfo{user: "a", pass: "pwd", clientID: "a3", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7054 defer c3.Close() 7055 testMQTTCheckConnAck(t, r3, mqttConnAckRCConnectionAccepted, false) 7056 testMQTTSub(t, 1, c3, r3, []*mqttFilter{{filter: "bar", qos: 0}}, []byte{0}) 7057 testMQTTFlush(t, c3, nil, r3) 7058 7059 c4, r4 := testMQTTConnect(t, &mqttConnInfo{user: "a", pass: "pwd", clientID: "a4", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7060 defer c4.Close() 7061 testMQTTCheckConnAck(t, r4, mqttConnAckRCConnectionAccepted, false) 7062 testMQTTSub(t, 1, c4, r4, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 7063 testMQTTFlush(t, c4, nil, r4) 7064 7065 bc, br := testMQTTConnect(t, &mqttConnInfo{user: "b", pass: "pwd", clientID: "b0", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7066 defer bc.Close() 7067 testMQTTCheckConnAck(t, br, mqttConnAckRCConnectionAccepted, false) 7068 7069 bc1, br1 := testMQTTConnect(t, &mqttConnInfo{user: "b", pass: "pwd", clientID: "b1", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7070 defer bc1.Close() 7071 testMQTTCheckConnAck(t, br1, mqttConnAckRCConnectionAccepted, false) 7072 testMQTTSub(t, 1, bc1, br1, []*mqttFilter{{filter: "foo", qos: 0}}, []byte{0}) 7073 testMQTTFlush(t, bc1, nil, br1) 7074 7075 bc2, br2 := testMQTTConnect(t, &mqttConnInfo{user: "b", pass: "pwd", clientID: "b2", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7076 defer bc2.Close() 7077 testMQTTCheckConnAck(t, br2, mqttConnAckRCConnectionAccepted, false) 7078 testMQTTSub(t, 1, bc2, br2, []*mqttFilter{{filter: "b", qos: 1}}, []byte{1}) 7079 testMQTTFlush(t, bc2, nil, br2) 7080 7081 bc3, br3 := testMQTTConnect(t, &mqttConnInfo{user: "b", pass: "pwd", clientID: "b3", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7082 defer bc3.Close() 7083 testMQTTCheckConnAck(t, br3, mqttConnAckRCConnectionAccepted, false) 7084 testMQTTSub(t, 1, bc3, br3, []*mqttFilter{{filter: "bar", qos: 0}}, []byte{0}) 7085 testMQTTFlush(t, bc3, nil, br3) 7086 7087 bc4, br4 := testMQTTConnect(t, &mqttConnInfo{user: "b", pass: "pwd", clientID: "b4", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7088 defer bc4.Close() 7089 testMQTTCheckConnAck(t, br4, mqttConnAckRCConnectionAccepted, false) 7090 testMQTTSub(t, 1, bc4, br4, []*mqttFilter{{filter: "bar", qos: 1}}, []byte{1}) 7091 testMQTTFlush(t, bc4, nil, br4) 7092 7093 nc := natsConnect(t, fmt.Sprintf("nats://b:pwd@%s:%d", o.Host, o.Port)) 7094 defer nc.Close() 7095 7096 natsPub(t, nc, "foo", []byte("msg0")) 7097 testMQTTCheckPubMsgNoAck(t, c1, r1, "foo", 0, []byte("msg0")) 7098 testMQTTCheckPubMsgNoAck(t, c2, r2, "foo", 0, []byte("msg0")) 7099 testMQTTExpectNothing(t, r3) 7100 testMQTTExpectNothing(t, r4) 7101 testMQTTExpectNothing(t, br1) 7102 testMQTTExpectNothing(t, br2) 7103 testMQTTCheckPubMsgNoAck(t, bc3, br3, "bar", 0, []byte("msg0")) 7104 testMQTTCheckPubMsgNoAck(t, bc4, br4, "bar", 0, []byte("msg0")) 7105 7106 testMQTTPublish(t, bc, br, 0, false, false, "foo", 0, []byte("msg1")) 7107 testMQTTCheckPubMsgNoAck(t, c1, r1, "foo", 0, []byte("msg1")) 7108 testMQTTCheckPubMsgNoAck(t, c2, r2, "foo", 0, []byte("msg1")) 7109 testMQTTExpectNothing(t, r3) 7110 testMQTTExpectNothing(t, r4) 7111 testMQTTExpectNothing(t, br1) 7112 testMQTTExpectNothing(t, br2) 7113 testMQTTCheckPubMsgNoAck(t, bc3, br3, "bar", 0, []byte("msg1")) 7114 testMQTTCheckPubMsgNoAck(t, bc4, br4, "bar", 0, []byte("msg1")) 7115 7116 testMQTTPublish(t, bc, br, 1, false, false, "foo", 1, []byte("msg2")) 7117 testMQTTCheckPubMsgNoAck(t, c1, r1, "foo", 0, []byte("msg2")) 7118 testMQTTCheckPubMsgNoAck(t, c2, r2, "foo", mqttPubQos1, []byte("msg2")) 7119 testMQTTExpectNothing(t, r3) 7120 testMQTTExpectNothing(t, r4) 7121 testMQTTExpectNothing(t, br1) 7122 testMQTTExpectNothing(t, br2) 7123 testMQTTCheckPubMsgNoAck(t, bc3, br3, "bar", 0, []byte("msg2")) 7124 testMQTTCheckPubMsgNoAck(t, bc4, br4, "bar", mqttPubQos1, []byte("msg2")) 7125 7126 // Connection nc is for account B 7127 check := func(nc *nats.Conn, subj string) { 7128 t.Helper() 7129 req, err := json.Marshal(&JSApiStreamInfoRequest{SubjectsFilter: ">"}) 7130 require_NoError(t, err) 7131 resp, err := nc.Request(fmt.Sprintf(JSApiStreamInfoT, "$MQTT_msgs"), req, time.Second) 7132 require_NoError(t, err) 7133 var si StreamInfo 7134 err = json.Unmarshal(resp.Data, &si) 7135 require_NoError(t, err) 7136 require_True(t, si.State.Msgs == 1) 7137 require_True(t, si.State.NumSubjects == 1) 7138 require_True(t, si.State.Subjects[subj] == 1) 7139 } 7140 // Currently, nc is for account B 7141 check(nc, "$MQTT.msgs.bar") 7142 7143 nc.Close() 7144 nc = natsConnect(t, fmt.Sprintf("nats://a:pwd@%s:%d", o.Host, o.Port)) 7145 defer nc.Close() 7146 check(nc, "$MQTT.msgs.foo") 7147 } 7148 7149 func TestMQTTSubRetainedRace(t *testing.T) { 7150 o := testMQTTDefaultOptions() 7151 s := testMQTTRunServer(t, o) 7152 defer testMQTTShutdownServer(s) 7153 7154 useCases := []struct { 7155 name string 7156 f func(t *testing.T, o *Options, subTopic, pubTopic string, QOS byte) 7157 }{ 7158 {"new top level", testMQTTNewSubRetainedRace}, 7159 {"existing top level", testMQTTNewSubWithExistingTopLevelRetainedRace}, 7160 } 7161 pubTopic := "/bar" 7162 subTopics := []string{"#", "/bar", "/+", "/#"} 7163 QOS := []byte{0, 1, 2} 7164 for _, tc := range useCases { 7165 t.Run(tc.name, func(t *testing.T) { 7166 for _, subTopic := range subTopics { 7167 t.Run(subTopic, func(t *testing.T) { 7168 for _, qos := range QOS { 7169 t.Run(fmt.Sprintf("QOS%d", qos), func(t *testing.T) { 7170 tc.f(t, o, subTopic, pubTopic, qos) 7171 }) 7172 } 7173 }) 7174 } 7175 }) 7176 } 7177 } 7178 7179 func testMQTTNewSubRetainedRace(t *testing.T, o *Options, subTopic, pubTopic string, QOS byte) { 7180 expectedFlags := (QOS << 1) | mqttPubFlagRetain 7181 payload := []byte("testmsg") 7182 7183 pubID := nuid.Next() 7184 pubc, pubr := testMQTTConnectRetry(t, &mqttConnInfo{clientID: pubID, cleanSess: true}, o.MQTT.Host, o.MQTT.Port, 3) 7185 testMQTTCheckConnAck(t, pubr, mqttConnAckRCConnectionAccepted, false) 7186 defer testMQTTDisconnectEx(t, pubc, nil, true) 7187 defer pubc.Close() 7188 testMQTTPublish(t, pubc, pubr, QOS, false, true, pubTopic, 1, payload) 7189 7190 subID := nuid.Next() 7191 subc, subr := testMQTTConnect(t, &mqttConnInfo{clientID: subID, cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7192 testMQTTCheckConnAck(t, subr, mqttConnAckRCConnectionAccepted, false) 7193 testMQTTSub(t, 1, subc, subr, []*mqttFilter{{filter: subTopic, qos: QOS}}, []byte{QOS}) 7194 7195 testMQTTCheckPubMsg(t, subc, subr, pubTopic, expectedFlags, payload) 7196 if QOS == 2 { 7197 testMQTTCheckPubAck(t, subr, mqttPacketPubRel) 7198 testMQTTSendPIPacket(mqttPacketPubComp, t, subc, 1) 7199 } 7200 7201 testMQTTDisconnectEx(t, subc, nil, true) 7202 subc.Close() 7203 } 7204 7205 func testMQTTNewSubWithExistingTopLevelRetainedRace(t *testing.T, o *Options, subTopic, pubTopic string, QOS byte) { 7206 expectedFlags := (QOS << 1) | mqttPubFlagRetain 7207 payload := []byte("testmsg") 7208 7209 pubID := nuid.Next() 7210 pubc, pubr := testMQTTConnectRetry(t, &mqttConnInfo{clientID: pubID, cleanSess: true}, o.MQTT.Host, o.MQTT.Port, 3) 7211 testMQTTCheckConnAck(t, pubr, mqttConnAckRCConnectionAccepted, false) 7212 defer testMQTTDisconnectEx(t, pubc, nil, true) 7213 defer pubc.Close() 7214 7215 subID := nuid.Next() 7216 subc, subr := testMQTTConnect(t, &mqttConnInfo{clientID: subID, cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7217 testMQTTCheckConnAck(t, subr, mqttConnAckRCConnectionAccepted, false) 7218 7219 // Clear retained messages from the prior run, and sleep a little to 7220 // ensure the change is propagated. 7221 testMQTTPublish(t, pubc, pubr, 0, false, true, pubTopic, 1, nil) 7222 time.Sleep(1 * time.Millisecond) 7223 7224 // Subscribe to `#` first, make sure we can get get the retained message 7225 // there. It's a QOS0 sub, so expect a QOS0 message. 7226 testMQTTSub(t, 1, subc, subr, []*mqttFilter{{filter: `#`, qos: 0}}, []byte{0}) 7227 testMQTTExpectNothing(t, subr) 7228 7229 // Publish the retained message with QOS2, see that the `#` subscriber gets it. 7230 testMQTTPublish(t, pubc, pubr, 2, false, true, pubTopic, 1, payload) 7231 testMQTTCheckPubMsg(t, subc, subr, pubTopic, 0, payload) 7232 testMQTTExpectNothing(t, subr) 7233 7234 // Now subscribe to the topic we want to test. We should get the retained 7235 // message there. 7236 testMQTTSub(t, 1, subc, subr, []*mqttFilter{{filter: subTopic, qos: QOS}}, []byte{QOS}) 7237 testMQTTCheckPubMsg(t, subc, subr, pubTopic, expectedFlags, payload) 7238 if QOS == 2 { 7239 testMQTTCheckPubAck(t, subr, mqttPacketPubRel) 7240 testMQTTSendPIPacket(mqttPacketPubComp, t, subc, 1) 7241 } 7242 7243 testMQTTDisconnectEx(t, subc, nil, true) 7244 subc.Close() 7245 } 7246 7247 // Issue https://github.com/nats-io/nats-server/issues/3924 7248 // The MQTT Server MUST NOT match Topic Filters starting with a wildcard character (# or +), 7249 // with Topic Names beginning with a $ character [MQTT-4.7.2-1] 7250 func TestMQTTSubjectWildcardStart(t *testing.T) { 7251 conf := createConfFile(t, []byte(fmt.Sprintf(` 7252 listen: 127.0.0.1:-1 7253 server_name: mqtt 7254 jetstream { 7255 store_dir = %q 7256 } 7257 mqtt { 7258 listen: 127.0.0.1:-1 7259 } 7260 `, t.TempDir()))) 7261 s, o := RunServerWithConfig(conf) 7262 defer testMQTTShutdownServer(s) 7263 7264 nc := natsConnect(t, s.ClientURL()) 7265 defer nc.Close() 7266 7267 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7268 defer mc.Close() 7269 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 7270 7271 mc1, r1 := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7272 defer mc1.Close() 7273 testMQTTCheckConnAck(t, r1, mqttConnAckRCConnectionAccepted, false) 7274 7275 mc2, r2 := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7276 defer mc2.Close() 7277 testMQTTCheckConnAck(t, r2, mqttConnAckRCConnectionAccepted, false) 7278 7279 mc3, r3 := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7280 defer mc3.Close() 7281 testMQTTCheckConnAck(t, r3, mqttConnAckRCConnectionAccepted, false) 7282 7283 // These will fail already with the bug due to messages already being queue up before the subAck. 7284 testMQTTSub(t, 1, mc1, r1, []*mqttFilter{{filter: "*", qos: 0}}, []byte{0}) 7285 testMQTTFlush(t, mc1, nil, r1) 7286 7287 testMQTTSub(t, 1, mc2, r2, []*mqttFilter{{filter: "#", qos: 1}}, []byte{1}) 7288 testMQTTFlush(t, mc2, nil, r2) 7289 7290 testMQTTSub(t, 1, mc3, r3, []*mqttFilter{{filter: "*/foo", qos: 1}}, []byte{1}) 7291 testMQTTFlush(t, mc2, nil, r2) 7292 7293 // Just as a barrier 7294 natsFlush(t, nc) 7295 7296 // Now publish 7297 7298 // NATS Publish 7299 msg := []byte("HELLO WORLD") 7300 natsPubReq(t, nc, "foo", _EMPTY_, msg) 7301 7302 // Check messages received 7303 testMQTTCheckPubMsg(t, mc1, r1, "foo", 0, msg) 7304 testMQTTExpectNothing(t, r1) 7305 7306 testMQTTCheckPubMsg(t, mc2, r2, "foo", 0, msg) 7307 testMQTTExpectNothing(t, r2) 7308 7309 testMQTTExpectNothing(t, r3) 7310 7311 // Anything that starts with $ is reserved against wildcard subjects like above. 7312 natsPubReq(t, nc, "$JS.foo", _EMPTY_, msg) 7313 testMQTTExpectNothing(t, r1) 7314 testMQTTExpectNothing(t, r2) 7315 testMQTTExpectNothing(t, r3) 7316 7317 // Now do MQTT QoS-0 7318 testMQTTPublish(t, mc, r, 0, false, false, "foo", 0, msg) 7319 7320 testMQTTCheckPubMsg(t, mc1, r1, "foo", 0, msg) 7321 testMQTTExpectNothing(t, r1) 7322 7323 testMQTTCheckPubMsg(t, mc2, r2, "foo", 0, msg) 7324 testMQTTExpectNothing(t, r2) 7325 7326 testMQTTExpectNothing(t, r3) 7327 7328 testMQTTPublish(t, mc, r, 0, false, false, "$JS/foo", 1, msg) 7329 7330 testMQTTExpectNothing(t, r1) 7331 testMQTTExpectNothing(t, r2) 7332 testMQTTExpectNothing(t, r3) 7333 7334 // Now do MQTT QoS-1 7335 msg = []byte("HELLO WORLD - RETAINED") 7336 testMQTTPublish(t, mc, r, 1, false, false, "$JS/foo", 4, msg) 7337 7338 testMQTTExpectNothing(t, r1) 7339 testMQTTExpectNothing(t, r2) 7340 testMQTTExpectNothing(t, r3) 7341 7342 testMQTTPublish(t, mc, r, 1, false, false, "foo", 2, msg) 7343 7344 testMQTTCheckPubMsg(t, mc1, r1, "foo", 0, msg) 7345 testMQTTExpectNothing(t, r1) 7346 7347 testMQTTCheckPubMsg(t, mc2, r2, "foo", 2, msg) 7348 testMQTTExpectNothing(t, r2) 7349 7350 testMQTTExpectNothing(t, r3) 7351 7352 testMQTTPublish(t, mc, r, 1, false, false, "foo/foo", 3, msg) 7353 7354 testMQTTExpectNothing(t, r1) 7355 7356 testMQTTCheckPubMsg(t, mc2, r2, "foo/foo", 2, msg) 7357 testMQTTExpectNothing(t, r2) 7358 7359 testMQTTCheckPubMsg(t, mc3, r3, "foo/foo", 2, msg) 7360 testMQTTExpectNothing(t, r3) 7361 7362 // Make sure we did not retain the messages prefixed with $. 7363 nc, js := jsClientConnect(t, s) 7364 defer nc.Close() 7365 7366 si, err := js.StreamInfo(mqttStreamName) 7367 require_NoError(t, err) 7368 7369 require_True(t, si.State.Msgs == 0) 7370 } 7371 7372 func TestMQTTTopicWithDot(t *testing.T) { 7373 o := testMQTTDefaultOptions() 7374 s := testMQTTRunServer(t, o) 7375 defer testMQTTShutdownServer(s) 7376 7377 nc := natsConnect(t, s.ClientURL(), nats.UserInfo("mqtt", "pwd")) 7378 defer nc.Close() 7379 7380 sub := natsSubSync(t, nc, "*.*") 7381 7382 c1, r1 := testMQTTConnect(t, &mqttConnInfo{user: "mqtt", pass: "pwd", clientID: "conn1", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7383 defer c1.Close() 7384 testMQTTCheckConnAck(t, r1, mqttConnAckRCConnectionAccepted, false) 7385 testMQTTSub(t, 1, c1, r1, []*mqttFilter{{filter: "spBv1.0/plant1", qos: 0}}, []byte{0}) 7386 testMQTTSub(t, 1, c1, r1, []*mqttFilter{{filter: "spBv1.0/plant2", qos: 1}}, []byte{1}) 7387 7388 c2, r2 := testMQTTConnect(t, &mqttConnInfo{user: "mqtt", pass: "pwd", clientID: "conn2", cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7389 defer c2.Close() 7390 testMQTTCheckConnAck(t, r2, mqttConnAckRCConnectionAccepted, false) 7391 7392 testMQTTPublish(t, c2, r2, 0, false, false, "spBv1.0/plant1", 0, []byte("msg1")) 7393 testMQTTCheckPubMsg(t, c1, r1, "spBv1.0/plant1", 0, []byte("msg1")) 7394 msg := natsNexMsg(t, sub, time.Second) 7395 require_Equal(t, msg.Subject, "spBv1//0.plant1") 7396 7397 testMQTTPublish(t, c2, r2, 1, false, false, "spBv1.0/plant2", 1, []byte("msg2")) 7398 testMQTTCheckPubMsg(t, c1, r1, "spBv1.0/plant2", mqttPubQos1, []byte("msg2")) 7399 msg = natsNexMsg(t, sub, time.Second) 7400 require_Equal(t, msg.Subject, "spBv1//0.plant2") 7401 7402 natsPub(t, nc, "spBv1//0.plant1", []byte("msg3")) 7403 testMQTTCheckPubMsg(t, c1, r1, "spBv1.0/plant1", 0, []byte("msg3")) 7404 msg = natsNexMsg(t, sub, time.Second) 7405 require_Equal(t, msg.Subject, "spBv1//0.plant1") 7406 7407 natsPub(t, nc, "spBv1//0.plant2", []byte("msg4")) 7408 testMQTTCheckPubMsg(t, c1, r1, "spBv1.0/plant2", 0, []byte("msg4")) 7409 msg = natsNexMsg(t, sub, time.Second) 7410 require_Equal(t, msg.Subject, "spBv1//0.plant2") 7411 } 7412 7413 // Issue https://github.com/nats-io/nats-server/issues/4291 7414 func TestMQTTJetStreamRepublishAndQoS0Subscribers(t *testing.T) { 7415 conf := createConfFile(t, []byte(fmt.Sprintf(` 7416 listen: 127.0.0.1:-1 7417 server_name: mqtt 7418 jetstream { 7419 store_dir = %q 7420 } 7421 mqtt { 7422 listen: 127.0.0.1:-1 7423 } 7424 `, t.TempDir()))) 7425 s, o := RunServerWithConfig(conf) 7426 defer testMQTTShutdownServer(s) 7427 7428 nc, js := jsClientConnect(t, s) 7429 defer nc.Close() 7430 7431 // Setup stream with republish on it. 7432 _, err := js.AddStream(&nats.StreamConfig{ 7433 Name: "TEST", 7434 Subjects: []string{"foo"}, 7435 RePublish: &nats.RePublish{ 7436 Source: "foo", 7437 Destination: "mqtt.foo", 7438 }, 7439 }) 7440 require_NoError(t, err) 7441 7442 // Create QoS0 subscriber to catch re-publishes. 7443 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7444 defer mc.Close() 7445 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 7446 7447 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "mqtt/foo", qos: 0}}, []byte{0}) 7448 testMQTTFlush(t, mc, nil, r) 7449 7450 msg := []byte("HELLO WORLD") 7451 _, err = js.Publish("foo", msg) 7452 require_NoError(t, err) 7453 7454 testMQTTCheckPubMsg(t, mc, r, "mqtt/foo", 0, msg) 7455 testMQTTExpectNothing(t, r) 7456 } 7457 7458 func TestMQTTDecodeRetainedMessage(t *testing.T) { 7459 tdir := t.TempDir() 7460 tmpl := ` 7461 listen: 127.0.0.1:-1 7462 server_name: mqtt 7463 jetstream { 7464 store_dir = %q 7465 } 7466 7467 mqtt { 7468 listen: 127.0.0.1:-1 7469 consumer_inactive_threshold: %q 7470 } 7471 7472 # For access to system account. 7473 accounts { $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } } 7474 ` 7475 conf := createConfFile(t, []byte(fmt.Sprintf(tmpl, tdir, "0.2s"))) 7476 s, o := RunServerWithConfig(conf) 7477 defer testMQTTShutdownServer(s) 7478 7479 // Connect and publish a retained message, this will be in the "newer" form, 7480 // with the metadata in the header. 7481 mc, r := testMQTTConnectRetry(t, &mqttConnInfo{clientID: "test", cleanSess: true}, o.MQTT.Host, o.MQTT.Port, 5) 7482 defer mc.Close() 7483 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 7484 testMQTTPublish(t, mc, r, 0, false, true, "foo/1", 0, []byte("msg1")) 7485 mc.Close() 7486 7487 // Store a "legacy", JSON-encoded payload directly into the stream. 7488 nc, js := jsClientConnect(t, s) 7489 defer nc.Close() 7490 7491 rm := mqttRetainedMsg{ 7492 Origin: "test", 7493 Subject: "foo.2", 7494 Topic: "foo/2", 7495 Flags: mqttPubFlagRetain, 7496 Msg: []byte("msg2"), 7497 } 7498 jsonData, _ := json.Marshal(rm) 7499 _, err := js.PublishMsg(&nats.Msg{ 7500 Subject: mqttRetainedMsgsStreamSubject + rm.Subject, 7501 Data: jsonData, 7502 }) 7503 if err != nil { 7504 t.Fatalf("Error publishing retained message to JS directly: %v", err) 7505 } 7506 7507 // Restart the server to see that it picks up both retained messages on restart. 7508 s.Shutdown() 7509 s = RunServer(o) 7510 defer testMQTTShutdownServer(s) 7511 7512 // Connect again, subscribe, and check that we get both messages. 7513 mc, r = testMQTTConnectRetry(t, &mqttConnInfo{clientID: "test", cleanSess: true}, o.MQTT.Host, o.MQTT.Port, 5) 7514 defer mc.Close() 7515 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 7516 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo/+", qos: 0}}, []byte{0}) 7517 for i := 0; i < 2; i++ { 7518 b, pl := testMQTTReadPacket(t, r) 7519 if pt := b & mqttPacketMask; pt != mqttPacketPub { 7520 t.Fatalf("Expected PUBLISH packet %x, got %x", mqttPacketPub, pt) 7521 } 7522 _, _, topic, _ := testMQTTGetPubMsgExEx(t, mc, r, mqttPubFlagRetain, pl, "", nil) 7523 if string(topic) != "foo/1" && string(topic) != "foo/2" { 7524 t.Fatalf("Expected foo/1 or foo/2, got %q", topic) 7525 } 7526 } 7527 testMQTTExpectNothing(t, r) 7528 mc.Close() 7529 7530 // Clear both retained messages. 7531 mc, r = testMQTTConnectRetry(t, &mqttConnInfo{clientID: "test", cleanSess: true}, o.MQTT.Host, o.MQTT.Port, 5) 7532 defer mc.Close() 7533 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 7534 testMQTTPublish(t, mc, r, 0, false, true, "foo/1", 0, []byte{}) 7535 testMQTTPublish(t, mc, r, 0, false, true, "foo/2", 0, []byte{}) 7536 mc.Close() 7537 7538 // Connect again, subscribe, and check that we get nothing. 7539 mc, r = testMQTTConnectRetry(t, &mqttConnInfo{clientID: "test", cleanSess: true}, o.MQTT.Host, o.MQTT.Port, 5) 7540 defer mc.Close() 7541 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 7542 testMQTTSub(t, 1, mc, r, []*mqttFilter{{filter: "foo/+", qos: 0}}, []byte{0}) 7543 testMQTTExpectNothing(t, r) 7544 } 7545 7546 func TestMQTTSparkbDeathHandling(t *testing.T) { 7547 o := testMQTTDefaultOptions() 7548 s := testMQTTRunServer(t, o) 7549 defer testMQTTShutdownServer(s) 7550 7551 // protoMetrics is protobuf-encoded test data, with no timestamp. 7552 // 7553 // p := &sproto.Payload{ 7554 // Metrics: []*sproto.Payload_Metric{ 7555 // newSparkbMetric_Uint64(sparkbBDSeqMetric, uint64(sparkbBDSeq)), 7556 // newSparkbMetric(sparkbDeviceMetric1, "value-at-death-1"), 7557 // newSparkbMetric(sparkbDeviceMetric2, "value-at-death-2"), 7558 // }, 7559 // Timestamp: nil, 7560 // } 7561 protoMetrics := []byte{0x12, 0x0b, 0x0a, 0x05, 0x62, 0x64, 0x53, 0x65, 0x71, 0x20, 0x04, 0x58, 0x02, 0x12, 0x24, 0x0a, 0x0e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x31, 0x20, 0x0c, 0x7a, 0x10, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2d, 0x61, 0x74, 0x2d, 0x64, 0x65, 0x61, 0x74, 0x68, 0x2d, 0x31, 0x12, 0x24, 0x0a, 0x0e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x32, 0x20, 0x0c, 0x7a, 0x10, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2d, 0x61, 0x74, 0x2d, 0x64, 0x65, 0x61, 0x74, 0x68, 0x2d, 0x32} 7562 7563 proto0Timestamp := []byte{0x08, 0x00} 7564 7565 protoDeadbeefTimestamp := []byte{0x08, 0xef, 0xfd, 0xb6, 0xf5, 0xfd, 0xde, 0xef, 0xd6, 0xde, 0x01} 7566 7567 mcPub, rPub := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7568 defer mcPub.Close() 7569 testMQTTCheckConnAck(t, rPub, mqttConnAckRCConnectionAccepted, false) 7570 7571 mcSub, rSub := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, o.MQTT.Host, o.MQTT.Port) 7572 defer mcSub.Close() 7573 testMQTTCheckConnAck(t, rSub, mqttConnAckRCConnectionAccepted, false) 7574 testMQTTSub(t, 0, mcSub, rSub, []*mqttFilter{{filter: "spBv1.0/ggg/#", qos: 0}}, []byte{0}) 7575 7576 for _, test := range []*struct { 7577 name string 7578 payload []byte 7579 expectTimestampOffset int 7580 expectUnchanged bool 7581 }{ 7582 {"append", protoMetrics, len(protoMetrics), false}, 7583 {"replace at the end", append(protoMetrics, proto0Timestamp...), len(protoMetrics), false}, 7584 {"replace at the start", append(protoDeadbeefTimestamp, protoMetrics...), 0, false}, 7585 {"invalid", []byte{0xde, 0xad, 0xbe, 0xef}, 0, true}, // invalid payload 7586 } { 7587 var sendPI uint16 7588 for _, topic := range []string{"NDEATH/nnn", "DDEATH/nnn/ddd"} { 7589 sendPI++ 7590 t.Run(test.name+" "+topic, func(t *testing.T) { 7591 testMQTTPublish(t, mcPub, rPub, 1, false, false, "spBv1.0/ggg/"+topic, sendPI, test.payload) 7592 7593 flags, pi, _, received := testMQTTGetPubMsgEx(t, mcSub, rSub, "", nil) 7594 if mqttGetQoS(flags) == 1 { 7595 testMQTTSendPIPacket(mqttPacketPubAck, t, mcSub, pi) 7596 } 7597 7598 if test.expectUnchanged { 7599 if !bytes.Equal(test.payload, received) { 7600 t.Fatalf("Expected payload to be unchanged, got %q", received) 7601 } 7602 return 7603 } 7604 7605 if test.expectTimestampOffset > len(received) { 7606 t.Fatalf("Expected timestamp offset %v to be less than %v", test.expectTimestampOffset, len(received)) 7607 } 7608 if test.expectTimestampOffset > 0 { 7609 if !bytes.Equal(protoMetrics, received[:test.expectTimestampOffset]) { 7610 t.Fatalf("Expected payload to be unchanged up to %v, got %q", test.expectTimestampOffset, received) 7611 } 7612 } 7613 7614 tsBytes := received[test.expectTimestampOffset:] 7615 if tsBytes[0] != 0x08 { 7616 t.Fatalf("Expected timestamp to start with 0x08, got %x", tsBytes) 7617 } 7618 v, _, err := protoScanVarint(tsBytes[1:]) 7619 if err != nil { 7620 t.Fatalf("Error scanning varint: %v", err) 7621 } 7622 7623 ts := time.UnixMilli(int64(v)) 7624 if time.Now().Before(ts) { 7625 t.Fatalf("Expected timestamp to be in the past, got %v", ts) 7626 } 7627 if time.Since(ts) > time.Second { 7628 t.Fatalf("Expected timestamp to be within a second, got %v", time.Since(ts)) 7629 } 7630 }) 7631 } 7632 } 7633 } 7634 7635 func TestMQTTSparkbBirthHandling(t *testing.T) { 7636 o := testMQTTDefaultOptions() 7637 s := testMQTTRunServer(t, o) 7638 defer testMQTTShutdownServer(s) 7639 7640 // Publish an NBIRTH message. Make sure it is received as both the original 7641 // subject, and as a $sparkplug/certificates one. 7642 7643 const NBORN = "NODE BORN FAKE MESSAGE" 7644 const DBORN = "DEVICE BORN FAKE MESSAGE" 7645 7646 tests := []*struct { 7647 topic string 7648 payload string 7649 flags byte 7650 mc net.Conn 7651 r *mqttReader 7652 }{ 7653 { 7654 topic: "spBv1.0/ggg/NBIRTH/nnn", 7655 payload: NBORN, 7656 flags: 0, 7657 }, 7658 { 7659 topic: "spBv1.0/ggg/DBIRTH/nnn/ddd", 7660 payload: DBORN, 7661 flags: 0, 7662 }, 7663 { 7664 topic: "$sparkplug/certificates/spBv1.0/ggg/NBIRTH/nnn", 7665 payload: NBORN, 7666 flags: mqttPubFlagRetain, 7667 }, 7668 { 7669 topic: "$sparkplug/certificates/spBv1.0/ggg/DBIRTH/nnn/ddd", 7670 payload: DBORN, 7671 flags: mqttPubFlagRetain, 7672 }, 7673 } 7674 7675 t.Run("$sparkplug messages delivered", func(t *testing.T) { 7676 // Connect the subscribers, unique for each topic we monitor. 7677 for i, test := range tests { 7678 test.mc, test.r = testMQTTConnect(t, &mqttConnInfo{cleanSess: true, clientID: fmt.Sprintf("sub-%v", i)}, o.MQTT.Host, o.MQTT.Port) 7679 defer test.mc.Close() 7680 testMQTTCheckConnAck(t, test.r, mqttConnAckRCConnectionAccepted, false) 7681 7682 // Subscribne at QoS2 to make sure the messages are posted at QoS0 and 7683 // not truncated to sub QoS. 7684 testMQTTSub(t, 0, test.mc, test.r, []*mqttFilter{{filter: test.topic, qos: 2}}, []byte{2}) 7685 } 7686 7687 // connect the publisher 7688 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true, clientID: "pub"}, o.MQTT.Host, o.MQTT.Port) 7689 defer mc.Close() 7690 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 7691 7692 // {Publish} [ND]BIRTH messages. Note that IRL these are protobuf payloads. 7693 testMQTTPublish(t, mc, r, 0, false, false, "spBv1.0/ggg/NBIRTH/nnn", 0, []byte("NODE BORN FAKE MESSAGE")) 7694 testMQTTPublish(t, mc, r, 0, false, false, "spBv1.0/ggg/DBIRTH/nnn/ddd", 0, []byte("DEVICE BORN FAKE MESSAGE")) 7695 7696 // Check that the subscribers got the messages. 7697 for _, test := range tests { 7698 testMQTTCheckPubMsg(t, test.mc, test.r, test.topic, test.flags, []byte(test.payload)) 7699 } 7700 }) 7701 7702 t.Run("$sparkplug messages retained", func(t *testing.T) { 7703 // Connect/subscribe again, and make sure that only retained messages are there. 7704 for i, test := range tests { 7705 mc, r := testMQTTConnect(t, &mqttConnInfo{cleanSess: true, clientID: fmt.Sprintf("sub-%v", i+100)}, o.MQTT.Host, o.MQTT.Port) 7706 defer mc.Close() 7707 testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) 7708 testMQTTSub(t, 0, mc, r, []*mqttFilter{{filter: test.topic, qos: 2}}, []byte{2}) 7709 if test.flags&mqttPubFlagRetain != 0 { 7710 testMQTTCheckPubMsg(t, mc, r, test.topic, test.flags, []byte(test.payload)) 7711 } else { 7712 testMQTTExpectNothing(t, r) 7713 } 7714 } 7715 }) 7716 } 7717 7718 ////////////////////////////////////////////////////////////////////////// 7719 // 7720 // Benchmarks 7721 // 7722 ////////////////////////////////////////////////////////////////////////// 7723 7724 const ( 7725 mqttPubSubj = "a" 7726 mqttBenchBufLen = 32768 7727 ) 7728 7729 func mqttBenchPubQoS0(b *testing.B, subject, payload string, numSubs int) { 7730 b.StopTimer() 7731 b.ReportAllocs() 7732 o := testMQTTDefaultOptions() 7733 s := RunServer(o) 7734 defer testMQTTShutdownServer(s) 7735 7736 ci := &mqttConnInfo{clientID: "pub", cleanSess: true} 7737 c, br := testMQTTConnect(b, ci, o.MQTT.Host, o.MQTT.Port) 7738 testMQTTCheckConnAck(b, br, mqttConnAckRCConnectionAccepted, false) 7739 w := newMQTTWriter(0) 7740 testMQTTWritePublishPacket(b, w, 0, false, false, subject, 0, []byte(payload)) 7741 sendOp := w.Bytes() 7742 7743 dch := make(chan error, 1) 7744 totalSize := int64(len(sendOp)) 7745 cdch := 0 7746 7747 createSub := func(i int) { 7748 ci := &mqttConnInfo{clientID: fmt.Sprintf("sub%d", i), cleanSess: true} 7749 cs, brs := testMQTTConnect(b, ci, o.MQTT.Host, o.MQTT.Port) 7750 testMQTTCheckConnAck(b, brs, mqttConnAckRCConnectionAccepted, false) 7751 7752 testMQTTSub(b, 1, cs, brs, []*mqttFilter{{filter: subject, qos: 0}}, []byte{0}) 7753 testMQTTFlush(b, cs, nil, brs) 7754 7755 w := newMQTTWriter(0) 7756 varHeaderAndPayload := 2 + len(subject) + len(payload) 7757 w.WriteVarInt(varHeaderAndPayload) 7758 size := 1 + w.Len() + varHeaderAndPayload 7759 totalSize += int64(size) 7760 7761 go func() { 7762 mqttBenchConsumeMsgQoS0(cs, int64(b.N)*int64(size), dch) 7763 cs.Close() 7764 }() 7765 } 7766 for i := 0; i < numSubs; i++ { 7767 createSub(i + 1) 7768 cdch++ 7769 } 7770 7771 bw := bufio.NewWriterSize(c, mqttBenchBufLen) 7772 b.SetBytes(totalSize) 7773 b.StartTimer() 7774 for i := 0; i < b.N; i++ { 7775 bw.Write(sendOp) 7776 } 7777 testMQTTFlush(b, c, bw, br) 7778 for i := 0; i < cdch; i++ { 7779 if e := <-dch; e != nil { 7780 b.Fatal(e.Error()) 7781 } 7782 } 7783 b.StopTimer() 7784 c.Close() 7785 s.Shutdown() 7786 } 7787 7788 func mqttBenchConsumeMsgQoS0(c net.Conn, total int64, dch chan<- error) { 7789 var buf [mqttBenchBufLen]byte 7790 var err error 7791 var n int 7792 for size := int64(0); size < total; { 7793 n, err = c.Read(buf[:]) 7794 if err != nil { 7795 break 7796 } 7797 size += int64(n) 7798 } 7799 dch <- err 7800 } 7801 7802 func mqttBenchPubQoS1(b *testing.B, subject, payload string, numSubs int) { 7803 b.StopTimer() 7804 o := testMQTTDefaultOptions() 7805 o.MQTT.MaxAckPending = 0xFFFF 7806 s := RunServer(o) 7807 defer testMQTTShutdownServer(s) 7808 7809 ci := &mqttConnInfo{cleanSess: true} 7810 c, br := testMQTTConnect(b, ci, o.MQTT.Host, o.MQTT.Port) 7811 testMQTTCheckConnAck(b, br, mqttConnAckRCConnectionAccepted, false) 7812 7813 w := newMQTTWriter(0) 7814 testMQTTWritePublishPacket(b, w, 1, false, false, subject, 1, []byte(payload)) 7815 // For reported bytes we will count the PUBLISH + PUBACK (4 bytes) 7816 totalSize := int64(w.Len() + 4) 7817 w.Reset() 7818 7819 pi := uint16(1) 7820 maxpi := uint16(60000) 7821 ppich := make(chan error, 10) 7822 dch := make(chan error, 1+numSubs) 7823 cdch := 1 7824 // Start go routine to consume PUBACK for published QoS 1 messages. 7825 go mqttBenchConsumePubAck(c, b.N, dch, ppich) 7826 7827 createSub := func(i int) { 7828 ci := &mqttConnInfo{clientID: fmt.Sprintf("sub%d", i), cleanSess: true} 7829 cs, brs := testMQTTConnect(b, ci, o.MQTT.Host, o.MQTT.Port) 7830 testMQTTCheckConnAck(b, brs, mqttConnAckRCConnectionAccepted, false) 7831 7832 testMQTTSub(b, 1, cs, brs, []*mqttFilter{{filter: subject, qos: 1}}, []byte{1}) 7833 testMQTTFlush(b, cs, nil, brs) 7834 7835 w := newMQTTWriter(0) 7836 varHeaderAndPayload := 2 + len(subject) + 2 + len(payload) 7837 w.WriteVarInt(varHeaderAndPayload) 7838 size := 1 + w.Len() + varHeaderAndPayload 7839 // Add to the bytes reported the size of message sent to subscriber + PUBACK (4 bytes) 7840 totalSize += int64(size + 4) 7841 7842 go func() { 7843 mqttBenchConsumeMsgQos1(cs, b.N, size, dch) 7844 cs.Close() 7845 }() 7846 } 7847 for i := 0; i < numSubs; i++ { 7848 createSub(i + 1) 7849 cdch++ 7850 } 7851 7852 flush := func() { 7853 b.Helper() 7854 if _, err := c.Write(w.Bytes()); err != nil { 7855 b.Fatalf("Error on write: %v", err) 7856 } 7857 w.Reset() 7858 } 7859 7860 b.SetBytes(totalSize) 7861 b.StartTimer() 7862 for i := 0; i < b.N; i++ { 7863 if pi <= maxpi { 7864 testMQTTWritePublishPacket(b, w, 1, false, false, subject, pi, []byte(payload)) 7865 pi++ 7866 if w.Len() >= mqttBenchBufLen { 7867 flush() 7868 } 7869 } else { 7870 if w.Len() > 0 { 7871 flush() 7872 } 7873 if pi > 60000 { 7874 pi = 1 7875 maxpi = 0 7876 } 7877 if e := <-ppich; e != nil { 7878 b.Fatal(e.Error()) 7879 } 7880 maxpi += 10000 7881 i-- 7882 } 7883 } 7884 if w.Len() > 0 { 7885 flush() 7886 } 7887 for i := 0; i < cdch; i++ { 7888 if e := <-dch; e != nil { 7889 b.Fatal(e.Error()) 7890 } 7891 } 7892 b.StopTimer() 7893 c.Close() 7894 s.Shutdown() 7895 } 7896 7897 func mqttBenchConsumeMsgQos1(c net.Conn, total, size int, dch chan<- error) { 7898 var buf [mqttBenchBufLen]byte 7899 pubAck := [4]byte{mqttPacketPubAck, 0x2, 0, 0} 7900 var err error 7901 var n int 7902 var pi uint16 7903 var prev int 7904 for i := 0; i < total; { 7905 n, err = c.Read(buf[:]) 7906 if err != nil { 7907 break 7908 } 7909 n += prev 7910 for ; n >= size; n -= size { 7911 i++ 7912 pi++ 7913 pubAck[2] = byte(pi >> 8) 7914 pubAck[3] = byte(pi) 7915 if _, err = c.Write(pubAck[:4]); err != nil { 7916 dch <- err 7917 return 7918 } 7919 if pi == 60000 { 7920 pi = 0 7921 } 7922 } 7923 prev = n 7924 } 7925 dch <- err 7926 } 7927 7928 func mqttBenchConsumePubAck(c net.Conn, total int, dch, ppich chan<- error) { 7929 var buf [mqttBenchBufLen]byte 7930 var err error 7931 var n int 7932 var pi uint16 7933 var prev int 7934 for i := 0; i < total; { 7935 n, err = c.Read(buf[:]) 7936 if err != nil { 7937 break 7938 } 7939 n += prev 7940 for ; n >= 4; n -= 4 { 7941 i++ 7942 pi++ 7943 if pi%10000 == 0 { 7944 ppich <- nil 7945 } 7946 if pi == 60001 { 7947 pi = 0 7948 } 7949 } 7950 prev = n 7951 } 7952 ppich <- err 7953 dch <- err 7954 } 7955 7956 func BenchmarkMQTT_QoS0_Pub_______0b_Payload(b *testing.B) { 7957 mqttBenchPubQoS0(b, mqttPubSubj, "", 0) 7958 } 7959 7960 func BenchmarkMQTT_QoS0_Pub_______8b_Payload(b *testing.B) { 7961 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(8), 0) 7962 } 7963 7964 func BenchmarkMQTT_QoS0_Pub______32b_Payload(b *testing.B) { 7965 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(32), 0) 7966 } 7967 7968 func BenchmarkMQTT_QoS0_Pub_____128b_Payload(b *testing.B) { 7969 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(128), 0) 7970 } 7971 7972 func BenchmarkMQTT_QoS0_Pub_____256b_Payload(b *testing.B) { 7973 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(256), 0) 7974 } 7975 7976 func BenchmarkMQTT_QoS0_Pub_______1K_Payload(b *testing.B) { 7977 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(1024), 0) 7978 } 7979 7980 func BenchmarkMQTT_QoS0_PubSub1___0b_Payload(b *testing.B) { 7981 mqttBenchPubQoS0(b, mqttPubSubj, "", 1) 7982 } 7983 7984 func BenchmarkMQTT_QoS0_PubSub1___8b_Payload(b *testing.B) { 7985 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(8), 1) 7986 } 7987 7988 func BenchmarkMQTT_QoS0_PubSub1__32b_Payload(b *testing.B) { 7989 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(32), 1) 7990 } 7991 7992 func BenchmarkMQTT_QoS0_PubSub1_128b_Payload(b *testing.B) { 7993 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(128), 1) 7994 } 7995 7996 func BenchmarkMQTT_QoS0_PubSub1_256b_Payload(b *testing.B) { 7997 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(256), 1) 7998 } 7999 8000 func BenchmarkMQTT_QoS0_PubSub1___1K_Payload(b *testing.B) { 8001 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(1024), 1) 8002 } 8003 8004 func BenchmarkMQTT_QoS0_PubSub2___0b_Payload(b *testing.B) { 8005 mqttBenchPubQoS0(b, mqttPubSubj, "", 2) 8006 } 8007 8008 func BenchmarkMQTT_QoS0_PubSub2___8b_Payload(b *testing.B) { 8009 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(8), 2) 8010 } 8011 8012 func BenchmarkMQTT_QoS0_PubSub2__32b_Payload(b *testing.B) { 8013 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(32), 2) 8014 } 8015 8016 func BenchmarkMQTT_QoS0_PubSub2_128b_Payload(b *testing.B) { 8017 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(128), 2) 8018 } 8019 8020 func BenchmarkMQTT_QoS0_PubSub2_256b_Payload(b *testing.B) { 8021 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(256), 2) 8022 } 8023 8024 func BenchmarkMQTT_QoS0_PubSub2___1K_Payload(b *testing.B) { 8025 mqttBenchPubQoS0(b, mqttPubSubj, sizedString(1024), 2) 8026 } 8027 8028 func BenchmarkMQTT_QoS1_Pub_______0b_Payload(b *testing.B) { 8029 mqttBenchPubQoS1(b, mqttPubSubj, "", 0) 8030 } 8031 8032 func BenchmarkMQTT_QoS1_Pub_______8b_Payload(b *testing.B) { 8033 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(8), 0) 8034 } 8035 8036 func BenchmarkMQTT_QoS1_Pub______32b_Payload(b *testing.B) { 8037 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(32), 0) 8038 } 8039 8040 func BenchmarkMQTT_QoS1_Pub_____128b_Payload(b *testing.B) { 8041 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(128), 0) 8042 } 8043 8044 func BenchmarkMQTT_QoS1_Pub_____256b_Payload(b *testing.B) { 8045 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(256), 0) 8046 } 8047 8048 func BenchmarkMQTT_QoS1_Pub_______1K_Payload(b *testing.B) { 8049 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(1024), 0) 8050 } 8051 8052 func BenchmarkMQTT_QoS1_PubSub1___0b_Payload(b *testing.B) { 8053 mqttBenchPubQoS1(b, mqttPubSubj, "", 1) 8054 } 8055 8056 func BenchmarkMQTT_QoS1_PubSub1___8b_Payload(b *testing.B) { 8057 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(8), 1) 8058 } 8059 8060 func BenchmarkMQTT_QoS1_PubSub1__32b_Payload(b *testing.B) { 8061 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(32), 1) 8062 } 8063 8064 func BenchmarkMQTT_QoS1_PubSub1_128b_Payload(b *testing.B) { 8065 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(128), 1) 8066 } 8067 8068 func BenchmarkMQTT_QoS1_PubSub1_256b_Payload(b *testing.B) { 8069 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(256), 1) 8070 } 8071 8072 func BenchmarkMQTT_QoS1_PubSub1___1K_Payload(b *testing.B) { 8073 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(1024), 1) 8074 } 8075 8076 func BenchmarkMQTT_QoS1_PubSub2___0b_Payload(b *testing.B) { 8077 mqttBenchPubQoS1(b, mqttPubSubj, "", 2) 8078 } 8079 8080 func BenchmarkMQTT_QoS1_PubSub2___8b_Payload(b *testing.B) { 8081 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(8), 2) 8082 } 8083 8084 func BenchmarkMQTT_QoS1_PubSub2__32b_Payload(b *testing.B) { 8085 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(32), 2) 8086 } 8087 8088 func BenchmarkMQTT_QoS1_PubSub2_128b_Payload(b *testing.B) { 8089 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(128), 2) 8090 } 8091 8092 func BenchmarkMQTT_QoS1_PubSub2_256b_Payload(b *testing.B) { 8093 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(256), 2) 8094 } 8095 8096 func BenchmarkMQTT_QoS1_PubSub2___1K_Payload(b *testing.B) { 8097 mqttBenchPubQoS1(b, mqttPubSubj, sizedString(1024), 2) 8098 }