get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/gateway_test.go (about) 1 // Copyright 2018-2020 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package server 15 16 import ( 17 "bufio" 18 "bytes" 19 "context" 20 "crypto/tls" 21 "encoding/json" 22 "fmt" 23 "net" 24 "net/url" 25 "runtime" 26 "strconv" 27 "strings" 28 "sync" 29 "sync/atomic" 30 "testing" 31 "time" 32 33 "get.pme.sh/pnats/logger" 34 "github.com/nats-io/nats.go" 35 ) 36 37 func init() { 38 gatewayConnectDelay = 15 * time.Millisecond 39 gatewayReconnectDelay = 15 * time.Millisecond 40 } 41 42 // Wait for the expected number of outbound gateways, or fails. 43 func waitForOutboundGateways(t *testing.T, s *Server, expected int, timeout time.Duration) { 44 t.Helper() 45 if timeout < 2*time.Second { 46 timeout = 2 * time.Second 47 } 48 checkFor(t, timeout, 15*time.Millisecond, func() error { 49 if n := s.numOutboundGateways(); n != expected { 50 return fmt.Errorf("Expected %v outbound gateway(s), got %v", expected, n) 51 } 52 return nil 53 }) 54 } 55 56 // Wait for the expected number of inbound gateways, or fails. 57 func waitForInboundGateways(t *testing.T, s *Server, expected int, timeout time.Duration) { 58 t.Helper() 59 if timeout < 2*time.Second { 60 timeout = 2 * time.Second 61 } 62 checkFor(t, timeout, 15*time.Millisecond, func() error { 63 if n := s.numInboundGateways(); n != expected { 64 return fmt.Errorf("Expected %v inbound gateway(s), got %v", expected, n) 65 } 66 return nil 67 }) 68 } 69 70 func waitForGatewayFailedConnect(t *testing.T, s *Server, gwName string, expectFailure bool, timeout time.Duration) { 71 t.Helper() 72 checkFor(t, timeout, 15*time.Millisecond, func() error { 73 var c int 74 cfg := s.getRemoteGateway(gwName) 75 if cfg != nil { 76 c = cfg.getConnAttempts() 77 } 78 if expectFailure && c <= 1 { 79 return fmt.Errorf("Expected several attempts to connect, got %v", c) 80 } else if !expectFailure && c > 1 { 81 return fmt.Errorf("Expected single attempt to connect, got %v", c) 82 } 83 return nil 84 }) 85 } 86 87 func checkForRegisteredQSubInterest(t *testing.T, s *Server, gwName, acc, subj string, expected int, timeout time.Duration) { 88 t.Helper() 89 checkFor(t, timeout, 15*time.Millisecond, func() error { 90 count := 0 91 c := s.getOutboundGatewayConnection(gwName) 92 ei, _ := c.gw.outsim.Load(acc) 93 if ei != nil { 94 sl := ei.(*outsie).sl 95 r := sl.Match(subj) 96 for _, qsubs := range r.qsubs { 97 count += len(qsubs) 98 } 99 } 100 if count == expected { 101 return nil 102 } 103 return fmt.Errorf("Expected %v qsubs in sublist, got %v", expected, count) 104 }) 105 } 106 107 func checkForSubjectNoInterest(t *testing.T, c *client, account, subject string, expectNoInterest bool, timeout time.Duration) { 108 t.Helper() 109 checkFor(t, timeout, 15*time.Millisecond, func() error { 110 ei, _ := c.gw.outsim.Load(account) 111 if ei == nil { 112 return fmt.Errorf("Did not receive subject no-interest") 113 } 114 e := ei.(*outsie) 115 e.RLock() 116 _, inMap := e.ni[subject] 117 e.RUnlock() 118 if expectNoInterest { 119 if inMap { 120 return nil 121 } 122 return fmt.Errorf("Did not receive subject no-interest on %q", subject) 123 } 124 if inMap { 125 return fmt.Errorf("No-interest on subject %q was not cleared", subject) 126 } 127 return nil 128 }) 129 } 130 131 func checkForAccountNoInterest(t *testing.T, c *client, account string, expectedNoInterest bool, timeout time.Duration) { 132 t.Helper() 133 checkFor(t, timeout, 15*time.Millisecond, func() error { 134 ei, ok := c.gw.outsim.Load(account) 135 if !ok && expectedNoInterest { 136 return fmt.Errorf("No-interest for account %q not yet registered", account) 137 } else if ok && !expectedNoInterest { 138 return fmt.Errorf("Account %q should not have a no-interest", account) 139 } 140 if ei != nil { 141 return fmt.Errorf("Account %q should have a global no-interest, not subject no-interest", account) 142 } 143 return nil 144 }) 145 } 146 147 func checkGWInterestOnlyMode(t *testing.T, s *Server, outboundGWName, accName string) { 148 t.Helper() 149 checkGWInterestOnlyModeOrNotPresent(t, s, outboundGWName, accName, false) 150 } 151 152 func checkGWInterestOnlyModeOrNotPresent(t *testing.T, s *Server, outboundGWName, accName string, notPresentOk bool) { 153 t.Helper() 154 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 155 gwc := s.getOutboundGatewayConnection(outboundGWName) 156 if gwc == nil { 157 return fmt.Errorf("No outbound gateway connection %q for server %v", outboundGWName, s) 158 } 159 gwc.mu.Lock() 160 defer gwc.mu.Unlock() 161 out, ok := gwc.gw.outsim.Load(accName) 162 if !ok { 163 if notPresentOk { 164 return nil 165 } else { 166 return fmt.Errorf("Server %v - outbound gateway connection %q: no account %q found in map", 167 s, outboundGWName, accName) 168 } 169 } 170 if out == nil { 171 return fmt.Errorf("Server %v - outbound gateway connection %q: interest map not found for account %q", 172 s, outboundGWName, accName) 173 } 174 e := out.(*outsie) 175 e.RLock() 176 defer e.RUnlock() 177 if e.mode != InterestOnly { 178 return fmt.Errorf( 179 "Server %v - outbound gateway connection %q: account %q mode shoule be InterestOnly but is %v", 180 s, outboundGWName, accName, e.mode) 181 } 182 return nil 183 }) 184 } 185 186 func checkGWInterestOnlyModeInterestOn(t *testing.T, s *Server, outboundGWName, accName, subject string) { 187 t.Helper() 188 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 189 c := s.getOutboundGatewayConnection(outboundGWName) 190 outsiei, _ := c.gw.outsim.Load(accName) 191 if outsiei == nil { 192 return fmt.Errorf("Server %s - outbound gateway connection %q: no map entry found for account %q", 193 s, outboundGWName, accName) 194 } 195 outsie := outsiei.(*outsie) 196 r := outsie.sl.Match(subject) 197 if len(r.psubs) == 0 { 198 return fmt.Errorf("Server %s - outbound gateway connection %q - account %q: no subject interest for %q", 199 s, outboundGWName, accName, subject) 200 } 201 return nil 202 }) 203 } 204 205 func waitCh(t *testing.T, ch chan bool, errTxt string) { 206 t.Helper() 207 select { 208 case <-ch: 209 return 210 case <-time.After(5 * time.Second): 211 t.Fatalf(errTxt) 212 } 213 } 214 215 var noOpErrHandler = func(_ *nats.Conn, _ *nats.Subscription, _ error) {} 216 217 func natsConnect(t testing.TB, url string, options ...nats.Option) *nats.Conn { 218 t.Helper() 219 opts := nats.GetDefaultOptions() 220 for _, opt := range options { 221 if err := opt(&opts); err != nil { 222 t.Fatalf("Error applying client option: %v", err) 223 } 224 } 225 nc, err := nats.Connect(url, options...) 226 if err != nil { 227 t.Fatalf("Error on connect: %v", err) 228 } 229 if opts.AsyncErrorCB == nil { 230 // Set this up to not pollute the logs when running tests. 231 nc.SetErrorHandler(noOpErrHandler) 232 } 233 234 return nc 235 } 236 237 func natsSub(t *testing.T, nc *nats.Conn, subj string, cb nats.MsgHandler) *nats.Subscription { 238 t.Helper() 239 sub, err := nc.Subscribe(subj, cb) 240 if err != nil { 241 t.Fatalf("Error on subscribe: %v", err) 242 } 243 return sub 244 } 245 246 func natsSubSync(t *testing.T, nc *nats.Conn, subj string) *nats.Subscription { 247 t.Helper() 248 sub, err := nc.SubscribeSync(subj) 249 if err != nil { 250 t.Fatalf("Error on subscribe: %v", err) 251 } 252 return sub 253 } 254 255 func natsNexMsg(t *testing.T, sub *nats.Subscription, timeout time.Duration) *nats.Msg { 256 t.Helper() 257 msg, err := sub.NextMsg(timeout) 258 if err != nil { 259 t.Fatalf("Failed getting next message: %v", err) 260 } 261 return msg 262 } 263 264 func natsQueueSub(t *testing.T, nc *nats.Conn, subj, queue string, cb nats.MsgHandler) *nats.Subscription { 265 t.Helper() 266 sub, err := nc.QueueSubscribe(subj, queue, cb) 267 if err != nil { 268 t.Fatalf("Error on subscribe: %v", err) 269 } 270 return sub 271 } 272 273 func natsQueueSubSync(t *testing.T, nc *nats.Conn, subj, queue string) *nats.Subscription { 274 t.Helper() 275 sub, err := nc.QueueSubscribeSync(subj, queue) 276 if err != nil { 277 t.Fatalf("Error on subscribe: %v", err) 278 } 279 return sub 280 } 281 282 func natsFlush(t *testing.T, nc *nats.Conn) { 283 t.Helper() 284 if err := nc.Flush(); err != nil { 285 t.Fatalf("Error on flush: %v", err) 286 } 287 } 288 289 func natsPub(t testing.TB, nc *nats.Conn, subj string, payload []byte) { 290 t.Helper() 291 if err := nc.Publish(subj, payload); err != nil { 292 t.Fatalf("Error on publish: %v", err) 293 } 294 } 295 296 func natsPubReq(t *testing.T, nc *nats.Conn, subj, reply string, payload []byte) { 297 t.Helper() 298 if err := nc.PublishRequest(subj, reply, payload); err != nil { 299 t.Fatalf("Error on publish: %v", err) 300 } 301 } 302 303 func natsUnsub(t *testing.T, sub *nats.Subscription) { 304 t.Helper() 305 if err := sub.Unsubscribe(); err != nil { 306 t.Fatalf("Error on unsubscribe: %v", err) 307 } 308 } 309 310 func testDefaultOptionsForGateway(name string) *Options { 311 o := DefaultOptions() 312 o.NoSystemAccount = true 313 o.Cluster.Name = name 314 o.Gateway.Name = name 315 o.Gateway.Host = "127.0.0.1" 316 o.Gateway.Port = -1 317 o.gatewaysSolicitDelay = 15 * time.Millisecond 318 return o 319 } 320 321 func runGatewayServer(o *Options) *Server { 322 s := RunServer(o) 323 s.SetLogger(&DummyLogger{}, true, true) 324 return s 325 } 326 327 func testGatewayOptionsFromToWithServers(t *testing.T, org, dst string, servers ...*Server) *Options { 328 t.Helper() 329 o := testDefaultOptionsForGateway(org) 330 gw := &RemoteGatewayOpts{Name: dst} 331 for _, s := range servers { 332 us := fmt.Sprintf("nats://127.0.0.1:%d", s.GatewayAddr().Port) 333 u, err := url.Parse(us) 334 if err != nil { 335 t.Fatalf("Error parsing url: %v", err) 336 } 337 gw.URLs = append(gw.URLs, u) 338 } 339 o.Gateway.Gateways = append(o.Gateway.Gateways, gw) 340 return o 341 } 342 343 func testAddGatewayURLs(t *testing.T, o *Options, dst string, urls []string) { 344 t.Helper() 345 gw := &RemoteGatewayOpts{Name: dst} 346 for _, us := range urls { 347 u, err := url.Parse(us) 348 if err != nil { 349 t.Fatalf("Error parsing url: %v", err) 350 } 351 gw.URLs = append(gw.URLs, u) 352 } 353 o.Gateway.Gateways = append(o.Gateway.Gateways, gw) 354 } 355 356 func testGatewayOptionsFromToWithURLs(t *testing.T, org, dst string, urls []string) *Options { 357 o := testDefaultOptionsForGateway(org) 358 testAddGatewayURLs(t, o, dst, urls) 359 return o 360 } 361 362 func testGatewayOptionsWithTLS(t *testing.T, name string) *Options { 363 t.Helper() 364 o := testDefaultOptionsForGateway(name) 365 var ( 366 tc = &TLSConfigOpts{} 367 err error 368 ) 369 if name == "A" { 370 tc.CertFile = "../test/configs/certs/srva-cert.pem" 371 tc.KeyFile = "../test/configs/certs/srva-key.pem" 372 } else { 373 tc.CertFile = "../test/configs/certs/srvb-cert.pem" 374 tc.KeyFile = "../test/configs/certs/srvb-key.pem" 375 } 376 tc.CaFile = "../test/configs/certs/ca.pem" 377 o.Gateway.TLSConfig, err = GenTLSConfig(tc) 378 if err != nil { 379 t.Fatalf("Error generating TLS config: %v", err) 380 } 381 o.Gateway.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert 382 o.Gateway.TLSConfig.RootCAs = o.Gateway.TLSConfig.ClientCAs 383 o.Gateway.TLSTimeout = 2.0 384 return o 385 } 386 387 func testGatewayOptionsFromToWithTLS(t *testing.T, org, dst string, urls []string) *Options { 388 o := testGatewayOptionsWithTLS(t, org) 389 testAddGatewayURLs(t, o, dst, urls) 390 return o 391 } 392 393 func TestGatewayBasic(t *testing.T) { 394 o2 := testDefaultOptionsForGateway("B") 395 o2.Gateway.ConnectRetries = 0 396 s2 := runGatewayServer(o2) 397 defer s2.Shutdown() 398 399 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 400 s1 := runGatewayServer(o1) 401 defer s1.Shutdown() 402 403 // s1 should have an outbound gateway to s2. 404 waitForOutboundGateways(t, s1, 1, time.Second) 405 // s2 should have an inbound gateway 406 waitForInboundGateways(t, s2, 1, time.Second) 407 // and an outbound too 408 waitForOutboundGateways(t, s2, 1, time.Second) 409 410 // Stop s2 server 411 s2.Shutdown() 412 413 // gateway should go away 414 waitForOutboundGateways(t, s1, 0, time.Second) 415 waitForInboundGateways(t, s1, 0, time.Second) 416 417 // Restart server 418 s2 = runGatewayServer(o2) 419 defer s2.Shutdown() 420 421 // gateway should reconnect 422 waitForOutboundGateways(t, s1, 1, 2*time.Second) 423 waitForOutboundGateways(t, s2, 1, 2*time.Second) 424 waitForInboundGateways(t, s1, 1, 2*time.Second) 425 waitForInboundGateways(t, s2, 1, 2*time.Second) 426 427 // Shutdown s1, remove the gateway from A to B and restart. 428 s1.Shutdown() 429 // When s2 detects the connection is closed, it will attempt 430 // to reconnect once (even if the route is implicit). 431 // We need to wait more than a dial timeout to make sure 432 // s1 does not restart too quickly and s2 can actually reconnect. 433 time.Sleep(DEFAULT_ROUTE_DIAL + 250*time.Millisecond) 434 // Restart s1 without gateway to B. 435 o1.Gateway.Gateways = nil 436 s1 = runGatewayServer(o1) 437 defer s1.Shutdown() 438 439 // s1 should not have any outbound nor inbound 440 waitForOutboundGateways(t, s1, 0, 2*time.Second) 441 waitForInboundGateways(t, s1, 0, 2*time.Second) 442 443 // Same for s2 444 waitForOutboundGateways(t, s2, 0, 2*time.Second) 445 waitForInboundGateways(t, s2, 0, 2*time.Second) 446 447 // Verify that s2 no longer has A gateway in its list 448 checkFor(t, time.Second, 15*time.Millisecond, func() error { 449 if s2.getRemoteGateway("A") != nil { 450 return fmt.Errorf("Gateway A should have been removed from s2") 451 } 452 return nil 453 }) 454 } 455 456 func TestGatewayIgnoreSelfReference(t *testing.T) { 457 o := testDefaultOptionsForGateway("A") 458 // To create a reference to itself before running the server 459 // it means that we have to assign an explicit port 460 o.Gateway.Port = 5222 461 o.gatewaysSolicitDelay = 0 462 u, _ := url.Parse(fmt.Sprintf("nats://%s:%d", o.Gateway.Host, o.Gateway.Port)) 463 cfg := &RemoteGatewayOpts{ 464 Name: "A", 465 URLs: []*url.URL{u}, 466 } 467 o.Gateway.Gateways = append(o.Gateway.Gateways, cfg) 468 o.NoSystemAccount = true 469 s := runGatewayServer(o) 470 defer s.Shutdown() 471 472 // Wait a bit to make sure that there is no attempt to connect. 473 time.Sleep(20 * time.Millisecond) 474 475 // No outbound connection expected, and no attempt to connect. 476 if s.getRemoteGateway("A") != nil { 477 t.Fatalf("Should not have a remote gateway config for A") 478 } 479 if s.getOutboundGatewayConnection("A") != nil { 480 t.Fatalf("Should not have a gateway connection to A") 481 } 482 s.Shutdown() 483 484 // Now try with config files and include 485 s1, _ := RunServerWithConfig("configs/gwa.conf") 486 defer s1.Shutdown() 487 488 s2, _ := RunServerWithConfig("configs/gwb.conf") 489 defer s2.Shutdown() 490 491 waitForOutboundGateways(t, s1, 1, 2*time.Second) 492 waitForOutboundGateways(t, s2, 1, 2*time.Second) 493 waitForInboundGateways(t, s1, 1, 2*time.Second) 494 waitForInboundGateways(t, s2, 1, 2*time.Second) 495 496 if s1.getRemoteGateway("A") != nil { 497 t.Fatalf("Should not have a remote gateway config for A") 498 } 499 if s1.getOutboundGatewayConnection("A") != nil { 500 t.Fatalf("Should not have a gateway connection to A") 501 } 502 if s2.getRemoteGateway("B") != nil { 503 t.Fatalf("Should not have a remote gateway config for B") 504 } 505 if s2.getOutboundGatewayConnection("B") != nil { 506 t.Fatalf("Should not have a gateway connection to B") 507 } 508 } 509 510 func TestGatewayHeaderInfo(t *testing.T) { 511 o := testDefaultOptionsForGateway("A") 512 s := runGatewayServer(o) 513 defer s.Shutdown() 514 515 gwconn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", o.Gateway.Host, o.Gateway.Port)) 516 if err != nil { 517 t.Fatalf("Error dialing server: %v\n", err) 518 } 519 defer gwconn.Close() 520 client := bufio.NewReaderSize(gwconn, maxBufSize) 521 l, err := client.ReadString('\n') 522 if err != nil { 523 t.Fatalf("Error receiving info from server: %v\n", err) 524 } 525 var info serverInfo 526 if err = json.Unmarshal([]byte(l[5:]), &info); err != nil { 527 t.Fatalf("Could not parse INFO json: %v\n", err) 528 } 529 if !info.Headers { 530 t.Fatalf("Expected by default for header support to be enabled") 531 } 532 533 s.Shutdown() 534 gwconn.Close() 535 536 // Now turn headers off. 537 o.NoHeaderSupport = true 538 s = runGatewayServer(o) 539 defer s.Shutdown() 540 541 gwconn, err = net.Dial("tcp", fmt.Sprintf("%s:%d", o.Gateway.Host, o.Gateway.Port)) 542 if err != nil { 543 t.Fatalf("Error dialing server: %v\n", err) 544 } 545 defer gwconn.Close() 546 client = bufio.NewReaderSize(gwconn, maxBufSize) 547 l, err = client.ReadString('\n') 548 if err != nil { 549 t.Fatalf("Error receiving info from server: %v\n", err) 550 } 551 if err = json.Unmarshal([]byte(l[5:]), &info); err != nil { 552 t.Fatalf("Could not parse INFO json: %v\n", err) 553 } 554 if info.Headers { 555 t.Fatalf("Expected header support to be disabled") 556 } 557 } 558 559 func TestGatewayHeaderSupport(t *testing.T) { 560 o2 := testDefaultOptionsForGateway("B") 561 o2.Gateway.ConnectRetries = 0 562 s2 := runGatewayServer(o2) 563 defer s2.Shutdown() 564 565 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 566 s1 := runGatewayServer(o1) 567 defer s1.Shutdown() 568 569 // s1 should have an outbound gateway to s2. 570 waitForOutboundGateways(t, s1, 1, time.Second) 571 // and an inbound too 572 waitForInboundGateways(t, s1, 1, time.Second) 573 // s2 should have an inbound gateway 574 waitForInboundGateways(t, s2, 1, time.Second) 575 // and an outbound too 576 waitForOutboundGateways(t, s2, 1, time.Second) 577 578 c, cr, _ := newClientForServer(s1) 579 defer c.close() 580 581 connect := "CONNECT {\"headers\":true}" 582 subOp := "SUB foo 1" 583 pingOp := "PING\r\n" 584 cmd := strings.Join([]string{connect, subOp, pingOp}, "\r\n") 585 c.parseAsync(cmd) 586 if _, err := cr.ReadString('\n'); err != nil { 587 t.Fatalf("Error receiving msg from server: %v\n", err) 588 } 589 590 // Wait for interest to be registered on s2 591 checkGWInterestOnlyModeInterestOn(t, s2, "A", globalAccountName, "foo") 592 593 b, _, _ := newClientForServer(s2) 594 defer b.close() 595 596 pubOp := "HPUB foo 12 14\r\nName:Derek\r\nOK\r\n" 597 cmd = strings.Join([]string{connect, pubOp}, "\r\n") 598 b.parseAsync(cmd) 599 600 l, err := cr.ReadString('\n') 601 if err != nil { 602 t.Fatalf("Error receiving msg from server: %v\n", err) 603 } 604 605 am := hmsgPat.FindAllStringSubmatch(l, -1) 606 if len(am) == 0 { 607 t.Fatalf("Did not get a match for %q", l) 608 } 609 matches := am[0] 610 if len(matches) != 7 { 611 t.Fatalf("Did not get correct # matches: %d vs %d\n", len(matches), 7) 612 } 613 if matches[SUB_INDEX] != "foo" { 614 t.Fatalf("Did not get correct subject: '%s'\n", matches[SUB_INDEX]) 615 } 616 if matches[SID_INDEX] != "1" { 617 t.Fatalf("Did not get correct sid: '%s'\n", matches[SID_INDEX]) 618 } 619 if matches[HDR_INDEX] != "12" { 620 t.Fatalf("Did not get correct msg length: '%s'\n", matches[HDR_INDEX]) 621 } 622 if matches[TLEN_INDEX] != "14" { 623 t.Fatalf("Did not get correct msg length: '%s'\n", matches[TLEN_INDEX]) 624 } 625 checkPayload(cr, []byte("Name:Derek\r\nOK\r\n"), t) 626 } 627 628 func TestGatewayHeaderDeliverStrippedMsg(t *testing.T) { 629 o2 := testDefaultOptionsForGateway("B") 630 o2.Gateway.ConnectRetries = 0 631 s2 := runGatewayServer(o2) 632 defer s2.Shutdown() 633 634 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 635 o1.NoHeaderSupport = true 636 s1 := runGatewayServer(o1) 637 defer s1.Shutdown() 638 639 // s1 should have an outbound gateway to s2. 640 waitForOutboundGateways(t, s1, 1, time.Second) 641 // and an inbound too 642 waitForInboundGateways(t, s1, 1, time.Second) 643 // s2 should have an inbound gateway 644 waitForInboundGateways(t, s2, 1, time.Second) 645 // and an outbound too 646 waitForOutboundGateways(t, s2, 1, time.Second) 647 648 c, cr, _ := newClientForServer(s1) 649 defer c.close() 650 651 connect := "CONNECT {\"headers\":true}" 652 subOp := "SUB foo 1" 653 pingOp := "PING\r\n" 654 cmd := strings.Join([]string{connect, subOp, pingOp}, "\r\n") 655 c.parseAsync(cmd) 656 if _, err := cr.ReadString('\n'); err != nil { 657 t.Fatalf("Error receiving msg from server: %v\n", err) 658 } 659 660 // Wait for interest to be registered on s2 661 checkGWInterestOnlyModeInterestOn(t, s2, "A", globalAccountName, "foo") 662 663 b, _, _ := newClientForServer(s2) 664 defer b.close() 665 666 pubOp := "HPUB foo 12 14\r\nName:Derek\r\nOK\r\n" 667 cmd = strings.Join([]string{connect, pubOp}, "\r\n") 668 b.parseAsync(cmd) 669 670 l, err := cr.ReadString('\n') 671 if err != nil { 672 t.Fatalf("Error receiving msg from server: %v\n", err) 673 } 674 am := smsgPat.FindAllStringSubmatch(l, -1) 675 if len(am) == 0 { 676 t.Fatalf("Did not get a correct match for %q", l) 677 } 678 matches := am[0] 679 if len(matches) != 6 { 680 t.Fatalf("Did not get correct # matches: %d vs %d\n", len(matches), 6) 681 } 682 if matches[SUB_INDEX] != "foo" { 683 t.Fatalf("Did not get correct subject: '%s'\n", matches[SUB_INDEX]) 684 } 685 if matches[SID_INDEX] != "1" { 686 t.Fatalf("Did not get correct sid: '%s'\n", matches[SID_INDEX]) 687 } 688 if matches[LEN_INDEX] != "2" { 689 t.Fatalf("Did not get correct msg length: '%s'\n", matches[LEN_INDEX]) 690 } 691 checkPayload(cr, []byte("OK\r\n"), t) 692 if cr.Buffered() != 0 { 693 t.Fatalf("Expected no extra bytes to be buffered, got %d", cr.Buffered()) 694 } 695 } 696 697 func TestGatewaySolicitDelay(t *testing.T) { 698 o2 := testDefaultOptionsForGateway("B") 699 s2 := runGatewayServer(o2) 700 defer s2.Shutdown() 701 702 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 703 // Set the solicit delay to 0. This tests that server will use its 704 // default value, currently set at 1 sec. 705 o1.gatewaysSolicitDelay = 0 706 start := time.Now() 707 s1 := runGatewayServer(o1) 708 defer s1.Shutdown() 709 710 // After 500ms, check outbound gateway. Should not be there. 711 time.Sleep(500 * time.Millisecond) 712 if time.Since(start) < defaultSolicitGatewaysDelay { 713 if s1.numOutboundGateways() > 0 { 714 t.Fatalf("The outbound gateway was initiated sooner than expected (%v)", time.Since(start)) 715 } 716 } 717 // Ultimately, s1 should have an outbound gateway to s2. 718 waitForOutboundGateways(t, s1, 1, 2*time.Second) 719 // s2 should have an inbound gateway 720 waitForInboundGateways(t, s2, 1, 2*time.Second) 721 722 s1.Shutdown() 723 // Make sure that server can be shutdown while waiting 724 // for that initial solicit delay 725 o1.gatewaysSolicitDelay = 2 * time.Second 726 s1 = runGatewayServer(o1) 727 start = time.Now() 728 s1.Shutdown() 729 if dur := time.Since(start); dur >= 2*time.Second { 730 t.Fatalf("Looks like shutdown was delayed: %v", dur) 731 } 732 } 733 734 func TestGatewaySolicitDelayWithImplicitOutbounds(t *testing.T) { 735 // Cause a situation where A connects to B, and because of 736 // delay of solicit gateways set on B, we want to make sure 737 // that B does not end-up with 2 connections to A. 738 o2 := testDefaultOptionsForGateway("B") 739 o2.gatewaysSolicitDelay = 500 * time.Millisecond 740 s2 := runGatewayServer(o2) 741 defer s2.Shutdown() 742 743 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 744 s1 := runGatewayServer(o1) 745 defer s1.Shutdown() 746 747 // s1 should have an outbound and inbound gateway to s2. 748 waitForOutboundGateways(t, s1, 1, 2*time.Second) 749 // s2 should have an inbound gateway 750 waitForInboundGateways(t, s2, 1, 2*time.Second) 751 // Wait for more than s2 solicit delay 752 time.Sleep(750 * time.Millisecond) 753 // The way we store outbound (map key'ed by gw name), we would 754 // not know if we had created 2 (since the newer would replace 755 // the older in the map). But if a second connection was made, 756 // then s1 would have 2 inbounds. So check it has only 1. 757 waitForInboundGateways(t, s1, 1, time.Second) 758 } 759 760 type slowResolver struct { 761 inLookupCh chan struct{} 762 releaseCh chan struct{} 763 } 764 765 func (r *slowResolver) LookupHost(ctx context.Context, h string) ([]string, error) { 766 if r.inLookupCh != nil { 767 select { 768 case r.inLookupCh <- struct{}{}: 769 default: 770 } 771 <-r.releaseCh 772 } else { 773 time.Sleep(500 * time.Millisecond) 774 } 775 return []string{h}, nil 776 } 777 778 func TestGatewaySolicitShutdown(t *testing.T) { 779 var urls []string 780 for i := 0; i < 5; i++ { 781 u := fmt.Sprintf("nats://localhost:%d", 1234+i) 782 urls = append(urls, u) 783 } 784 o1 := testGatewayOptionsFromToWithURLs(t, "A", "B", urls) 785 o1.Gateway.resolver = &slowResolver{} 786 s1 := runGatewayServer(o1) 787 defer s1.Shutdown() 788 789 time.Sleep(o1.gatewaysSolicitDelay + 10*time.Millisecond) 790 791 start := time.Now() 792 s1.Shutdown() 793 if dur := time.Since(start); dur > 1200*time.Millisecond { 794 t.Fatalf("Took too long to shutdown: %v", dur) 795 } 796 } 797 798 func testFatalErrorOnStart(t *testing.T, o *Options, errTxt string) { 799 t.Helper() 800 s := New(o) 801 defer s.Shutdown() 802 l := &captureFatalLogger{fatalCh: make(chan string, 1)} 803 s.SetLogger(l, false, false) 804 wg := sync.WaitGroup{} 805 wg.Add(1) 806 go func() { 807 s.Start() 808 wg.Done() 809 }() 810 select { 811 case e := <-l.fatalCh: 812 if !strings.Contains(e, errTxt) { 813 t.Fatalf("Error should contain %q, got %s", errTxt, e) 814 } 815 case <-time.After(time.Second): 816 t.Fatal("Should have got a fatal error") 817 } 818 s.Shutdown() 819 wg.Wait() 820 } 821 822 func TestGatewayListenError(t *testing.T) { 823 o2 := testDefaultOptionsForGateway("B") 824 s2 := runGatewayServer(o2) 825 defer s2.Shutdown() 826 827 o1 := testDefaultOptionsForGateway("A") 828 o1.Gateway.Port = s2.GatewayAddr().Port 829 testFatalErrorOnStart(t, o1, "listening on") 830 } 831 832 func TestGatewayWithListenToAny(t *testing.T) { 833 confB1 := createConfFile(t, []byte(` 834 listen: "127.0.0.1:-1" 835 cluster { 836 listen: "127.0.0.1:-1" 837 } 838 gateway { 839 name: "B" 840 listen: "0.0.0.0:-1" 841 } 842 `)) 843 sb1, ob1 := RunServerWithConfig(confB1) 844 defer sb1.Shutdown() 845 846 confB2 := createConfFile(t, []byte(fmt.Sprintf(` 847 listen: "127.0.0.1:-1" 848 cluster { 849 listen: "127.0.0.1:-1" 850 routes: ["%s"] 851 } 852 gateway { 853 name: "B" 854 listen: "0.0.0.0:-1" 855 } 856 `, fmt.Sprintf("nats://127.0.0.1:%d", sb1.ClusterAddr().Port)))) 857 sb2, ob2 := RunServerWithConfig(confB2) 858 defer sb2.Shutdown() 859 860 checkClusterFormed(t, sb1, sb2) 861 862 confA := createConfFile(t, []byte(fmt.Sprintf(` 863 listen: "127.0.0.1:-1" 864 cluster { 865 listen: "127.0.0.1:-1" 866 } 867 gateway { 868 name: "A" 869 listen: "0.0.0.0:-1" 870 gateways [ 871 { 872 name: "B" 873 urls: ["%s", "%s"] 874 } 875 ] 876 } 877 `, fmt.Sprintf("nats://127.0.0.1:%d", ob1.Gateway.Port), fmt.Sprintf("nats://127.0.0.1:%d", ob2.Gateway.Port)))) 878 oa := LoadConfig(confA) 879 oa.gatewaysSolicitDelay = 15 * time.Millisecond 880 sa := runGatewayServer(oa) 881 defer sa.Shutdown() 882 883 waitForOutboundGateways(t, sa, 1, time.Second) 884 waitForOutboundGateways(t, sb1, 1, time.Second) 885 waitForOutboundGateways(t, sb2, 1, time.Second) 886 waitForInboundGateways(t, sa, 2, time.Second) 887 888 checkAll := func(t *testing.T) { 889 t.Helper() 890 checkURL := func(t *testing.T, s *Server) { 891 t.Helper() 892 url := s.getGatewayURL() 893 if strings.HasPrefix(url, "0.0.0.0") { 894 t.Fatalf("URL still references 0.0.0.0") 895 } 896 s.gateway.RLock() 897 for url := range s.gateway.URLs { 898 if strings.HasPrefix(url, "0.0.0.0") { 899 s.gateway.RUnlock() 900 t.Fatalf("URL still references 0.0.0.0") 901 } 902 } 903 s.gateway.RUnlock() 904 905 var cfg *gatewayCfg 906 if s.getGatewayName() == "A" { 907 cfg = s.getRemoteGateway("B") 908 } else { 909 cfg = s.getRemoteGateway("A") 910 } 911 urls := cfg.getURLs() 912 for _, url := range urls { 913 if strings.HasPrefix(url.Host, "0.0.0.0") { 914 t.Fatalf("URL still references 0.0.0.0") 915 } 916 } 917 } 918 checkURL(t, sb1) 919 checkURL(t, sb2) 920 checkURL(t, sa) 921 } 922 checkAll(t) 923 // Perform a reload and ensure that nothing has changed 924 servers := []*Server{sb1, sb2, sa} 925 for _, s := range servers { 926 if err := s.Reload(); err != nil { 927 t.Fatalf("Error on reload: %v", err) 928 } 929 checkAll(t) 930 } 931 } 932 933 func TestGatewayAdvertise(t *testing.T) { 934 o3 := testDefaultOptionsForGateway("C") 935 s3 := runGatewayServer(o3) 936 defer s3.Shutdown() 937 938 o2 := testDefaultOptionsForGateway("B") 939 s2 := runGatewayServer(o2) 940 defer s2.Shutdown() 941 942 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 943 // Set the advertise so that this points to C 944 o1.Gateway.Advertise = fmt.Sprintf("127.0.0.1:%d", s3.GatewayAddr().Port) 945 s1 := runGatewayServer(o1) 946 defer s1.Shutdown() 947 948 // We should have outbound from s1 to s2 949 waitForOutboundGateways(t, s1, 1, time.Second) 950 // But no inbound from s2 951 waitForInboundGateways(t, s1, 0, time.Second) 952 953 // And since B tries to connect to A but reaches C, it should fail to connect, 954 // and without connect retries, stop trying. So no outbound for s2, and no 955 // inbound/outbound for s3. 956 waitForInboundGateways(t, s2, 1, time.Second) 957 waitForOutboundGateways(t, s2, 0, time.Second) 958 waitForInboundGateways(t, s3, 0, time.Second) 959 waitForOutboundGateways(t, s3, 0, time.Second) 960 } 961 962 func TestGatewayAdvertiseErr(t *testing.T) { 963 o1 := testDefaultOptionsForGateway("A") 964 o1.Gateway.Advertise = "wrong:address" 965 testFatalErrorOnStart(t, o1, "Gateway.Advertise") 966 } 967 968 func TestGatewayAuth(t *testing.T) { 969 o2 := testDefaultOptionsForGateway("B") 970 o2.Gateway.Username = "me" 971 o2.Gateway.Password = "pwd" 972 s2 := runGatewayServer(o2) 973 defer s2.Shutdown() 974 975 o1 := testGatewayOptionsFromToWithURLs(t, "A", "B", []string{fmt.Sprintf("nats://me:pwd@127.0.0.1:%d", s2.GatewayAddr().Port)}) 976 s1 := runGatewayServer(o1) 977 defer s1.Shutdown() 978 979 // s1 should have an outbound gateway to s2. 980 waitForOutboundGateways(t, s1, 1, time.Second) 981 // s2 should have an inbound gateway 982 waitForInboundGateways(t, s2, 1, time.Second) 983 984 s2.Shutdown() 985 s1.Shutdown() 986 987 o2.Gateway.Username = "me" 988 o2.Gateway.Password = "wrong" 989 s2 = runGatewayServer(o2) 990 defer s2.Shutdown() 991 992 s1 = runGatewayServer(o1) 993 defer s1.Shutdown() 994 995 // Connection should fail... 996 waitForGatewayFailedConnect(t, s1, "B", true, 2*time.Second) 997 998 s2.Shutdown() 999 s1.Shutdown() 1000 o2.Gateway.Username = "wrong" 1001 o2.Gateway.Password = "pwd" 1002 s2 = runGatewayServer(o2) 1003 defer s2.Shutdown() 1004 1005 s1 = runGatewayServer(o1) 1006 defer s1.Shutdown() 1007 1008 // Connection should fail... 1009 waitForGatewayFailedConnect(t, s1, "B", true, 2*time.Second) 1010 } 1011 1012 func TestGatewayTLS(t *testing.T) { 1013 o2 := testGatewayOptionsWithTLS(t, "B") 1014 s2 := runGatewayServer(o2) 1015 defer s2.Shutdown() 1016 1017 o1 := testGatewayOptionsFromToWithTLS(t, "A", "B", []string{fmt.Sprintf("nats://127.0.0.1:%d", s2.GatewayAddr().Port)}) 1018 s1 := runGatewayServer(o1) 1019 defer s1.Shutdown() 1020 1021 // s1 should have an outbound gateway to s2. 1022 waitForOutboundGateways(t, s1, 1, time.Second) 1023 // s2 should have an inbound gateway 1024 waitForInboundGateways(t, s2, 1, time.Second) 1025 // and vice-versa 1026 waitForOutboundGateways(t, s2, 1, time.Second) 1027 waitForInboundGateways(t, s1, 1, time.Second) 1028 1029 // Stop s2 server 1030 s2.Shutdown() 1031 1032 // gateway should go away 1033 waitForOutboundGateways(t, s1, 0, time.Second) 1034 waitForInboundGateways(t, s1, 0, time.Second) 1035 waitForOutboundGateways(t, s2, 0, time.Second) 1036 waitForInboundGateways(t, s2, 0, time.Second) 1037 1038 // Restart server 1039 s2 = runGatewayServer(o2) 1040 defer s2.Shutdown() 1041 1042 // gateway should reconnect 1043 waitForOutboundGateways(t, s1, 1, 2*time.Second) 1044 waitForOutboundGateways(t, s2, 1, 2*time.Second) 1045 waitForInboundGateways(t, s1, 1, 2*time.Second) 1046 waitForInboundGateways(t, s2, 1, 2*time.Second) 1047 1048 s1.Shutdown() 1049 // Wait for s2 to lose connections to s1. 1050 waitForOutboundGateways(t, s2, 0, 2*time.Second) 1051 waitForInboundGateways(t, s2, 0, 2*time.Second) 1052 1053 // Make an explicit TLS config for remote gateway config "B" 1054 // on cluster A. 1055 o1.Gateway.Gateways[0].TLSConfig = o1.Gateway.TLSConfig.Clone() 1056 u, _ := url.Parse(fmt.Sprintf("tls://localhost:%d", s2.GatewayAddr().Port)) 1057 o1.Gateway.Gateways[0].URLs = []*url.URL{u} 1058 // Make the TLSTimeout so small that it should fail to connect. 1059 smallTimeout := 0.00000001 1060 o1.Gateway.Gateways[0].TLSTimeout = smallTimeout 1061 s1 = runGatewayServer(o1) 1062 defer s1.Shutdown() 1063 1064 // Check that s1 reports connection failures 1065 waitForGatewayFailedConnect(t, s1, "B", true, 2*time.Second) 1066 1067 // Check that TLSConfig from s1's remote "B" is based on 1068 // what we have configured. 1069 cfg := s1.getRemoteGateway("B") 1070 cfg.RLock() 1071 tlsName := cfg.tlsName 1072 timeout := cfg.TLSTimeout 1073 cfg.RUnlock() 1074 if tlsName != "localhost" { 1075 t.Fatalf("Expected server name to be localhost, got %v", tlsName) 1076 } 1077 if timeout != smallTimeout { 1078 t.Fatalf("Expected tls timeout to be %v, got %v", smallTimeout, timeout) 1079 } 1080 s1.Shutdown() 1081 // Wait for s2 to lose connections to s1. 1082 waitForOutboundGateways(t, s2, 0, 2*time.Second) 1083 waitForInboundGateways(t, s2, 0, 2*time.Second) 1084 1085 // Remove explicit TLSTimeout from gateway "B" and check that 1086 // we use the A's spec one. 1087 o1.Gateway.Gateways[0].TLSTimeout = 0 1088 s1 = runGatewayServer(o1) 1089 defer s1.Shutdown() 1090 1091 waitForOutboundGateways(t, s1, 1, 2*time.Second) 1092 waitForOutboundGateways(t, s2, 1, 2*time.Second) 1093 waitForInboundGateways(t, s1, 1, 2*time.Second) 1094 waitForInboundGateways(t, s2, 1, 2*time.Second) 1095 1096 cfg = s1.getRemoteGateway("B") 1097 cfg.RLock() 1098 timeout = cfg.TLSTimeout 1099 cfg.RUnlock() 1100 if timeout != o1.Gateway.TLSTimeout { 1101 t.Fatalf("Expected tls timeout to be %v, got %v", o1.Gateway.TLSTimeout, timeout) 1102 } 1103 } 1104 1105 func TestGatewayTLSErrors(t *testing.T) { 1106 o2 := testDefaultOptionsForGateway("B") 1107 s2 := runGatewayServer(o2) 1108 defer s2.Shutdown() 1109 1110 o1 := testGatewayOptionsFromToWithTLS(t, "A", "B", []string{fmt.Sprintf("nats://127.0.0.1:%d", s2.ClusterAddr().Port)}) 1111 s1 := runGatewayServer(o1) 1112 defer s1.Shutdown() 1113 1114 // Expect s1 to have a failed to connect count > 0 1115 waitForGatewayFailedConnect(t, s1, "B", true, 2*time.Second) 1116 } 1117 1118 func TestGatewayServerNameInTLSConfig(t *testing.T) { 1119 o2 := testDefaultOptionsForGateway("B") 1120 var ( 1121 tc = &TLSConfigOpts{} 1122 err error 1123 ) 1124 tc.CertFile = "../test/configs/certs/server-noip.pem" 1125 tc.KeyFile = "../test/configs/certs/server-key-noip.pem" 1126 tc.CaFile = "../test/configs/certs/ca.pem" 1127 o2.Gateway.TLSConfig, err = GenTLSConfig(tc) 1128 if err != nil { 1129 t.Fatalf("Error generating TLS config: %v", err) 1130 } 1131 o2.Gateway.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert 1132 o2.Gateway.TLSConfig.RootCAs = o2.Gateway.TLSConfig.ClientCAs 1133 o2.Gateway.TLSTimeout = 2.0 1134 s2 := runGatewayServer(o2) 1135 defer s2.Shutdown() 1136 1137 o1 := testGatewayOptionsFromToWithTLS(t, "A", "B", []string{fmt.Sprintf("nats://127.0.0.1:%d", s2.GatewayAddr().Port)}) 1138 s1 := runGatewayServer(o1) 1139 defer s1.Shutdown() 1140 1141 // s1 should fail to connect since we don't have proper expected hostname. 1142 waitForGatewayFailedConnect(t, s1, "B", true, 2*time.Second) 1143 1144 // Now set server name, and it should work. 1145 s1.Shutdown() 1146 o1.Gateway.TLSConfig.ServerName = "localhost" 1147 s1 = runGatewayServer(o1) 1148 defer s1.Shutdown() 1149 1150 waitForOutboundGateways(t, s1, 1, 2*time.Second) 1151 } 1152 1153 func TestGatewayWrongDestination(t *testing.T) { 1154 // Start a server with a gateway named "C" 1155 o2 := testDefaultOptionsForGateway("C") 1156 s2 := runGatewayServer(o2) 1157 defer s2.Shutdown() 1158 1159 // Configure a gateway to "B", but since we are connecting to "C"... 1160 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 1161 s1 := runGatewayServer(o1) 1162 defer s1.Shutdown() 1163 1164 // we should not be able to connect. 1165 waitForGatewayFailedConnect(t, s1, "B", true, time.Second) 1166 1167 // Shutdown s2 and fix the gateway name. 1168 // s1 should then connect ok and failed connect should be cleared. 1169 s2.Shutdown() 1170 1171 // Reset the conn attempts 1172 cfg := s1.getRemoteGateway("B") 1173 cfg.resetConnAttempts() 1174 1175 o2.Gateway.Name = "B" 1176 o2.Cluster.Name = "B" 1177 s2 = runGatewayServer(o2) 1178 defer s2.Shutdown() 1179 1180 // At some point, the number of failed connect count should be reset to 0. 1181 waitForGatewayFailedConnect(t, s1, "B", false, 2*time.Second) 1182 } 1183 1184 func TestGatewayConnectToWrongPort(t *testing.T) { 1185 o2 := testDefaultOptionsForGateway("B") 1186 s2 := runGatewayServer(o2) 1187 defer s2.Shutdown() 1188 1189 // Configure a gateway to "B", but connect to the wrong port 1190 urls := []string{fmt.Sprintf("nats://127.0.0.1:%d", s2.Addr().(*net.TCPAddr).Port)} 1191 o1 := testGatewayOptionsFromToWithURLs(t, "A", "B", urls) 1192 s1 := runGatewayServer(o1) 1193 defer s1.Shutdown() 1194 1195 // we should not be able to connect. 1196 waitForGatewayFailedConnect(t, s1, "B", true, time.Second) 1197 1198 s1.Shutdown() 1199 1200 // Repeat with route port 1201 urls = []string{fmt.Sprintf("nats://127.0.0.1:%d", s2.ClusterAddr().Port)} 1202 o1 = testGatewayOptionsFromToWithURLs(t, "A", "B", urls) 1203 s1 = runGatewayServer(o1) 1204 defer s1.Shutdown() 1205 1206 // we should not be able to connect. 1207 waitForGatewayFailedConnect(t, s1, "B", true, time.Second) 1208 1209 s1.Shutdown() 1210 1211 // Now have a client connect to s2's gateway port. 1212 nc, err := nats.Connect(fmt.Sprintf("nats://127.0.0.1:%d", s2.GatewayAddr().Port)) 1213 if err == nil { 1214 nc.Close() 1215 t.Fatal("Expected error, got none") 1216 } 1217 } 1218 1219 func TestGatewayCreateImplicit(t *testing.T) { 1220 // Create a regular cluster of 2 servers 1221 o2 := testDefaultOptionsForGateway("B") 1222 s2 := runGatewayServer(o2) 1223 defer s2.Shutdown() 1224 1225 o3 := testDefaultOptionsForGateway("B") 1226 o3.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", s2.ClusterAddr().Port)) 1227 s3 := runGatewayServer(o3) 1228 defer s3.Shutdown() 1229 1230 checkClusterFormed(t, s2, s3) 1231 1232 // Now start s1 that creates a Gateway connection to s2 or s3 1233 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2, s3) 1234 s1 := runGatewayServer(o1) 1235 defer s1.Shutdown() 1236 1237 // We should have an outbound gateway connection on ALL servers. 1238 waitForOutboundGateways(t, s1, 1, 2*time.Second) 1239 waitForOutboundGateways(t, s2, 1, 2*time.Second) 1240 waitForOutboundGateways(t, s3, 1, 2*time.Second) 1241 1242 // Server s1 must have 2 inbound ones 1243 waitForInboundGateways(t, s1, 2, 2*time.Second) 1244 1245 // However, s1 may have created the outbound to s2 or s3. It is possible that 1246 // either s2 or s3 does not an inbound connection. 1247 s2Inbound := s2.numInboundGateways() 1248 s3Inbound := s3.numInboundGateways() 1249 if (s2Inbound == 1 && s3Inbound != 0) || (s3Inbound == 1 && s2Inbound != 0) { 1250 t.Fatalf("Unexpected inbound for s2/s3: %v/%v", s2Inbound, s3Inbound) 1251 } 1252 } 1253 1254 func TestGatewayCreateImplicitOnNewRoute(t *testing.T) { 1255 // Start with only 2 clusters of 1 server each 1256 o2 := testDefaultOptionsForGateway("B") 1257 s2 := runGatewayServer(o2) 1258 defer s2.Shutdown() 1259 1260 // Now start s1 that creates a Gateway connection to s2 1261 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 1262 s1 := runGatewayServer(o1) 1263 defer s1.Shutdown() 1264 1265 // Check outbounds 1266 waitForOutboundGateways(t, s1, 1, 2*time.Second) 1267 waitForOutboundGateways(t, s2, 1, 2*time.Second) 1268 1269 // Now add a server to cluster B 1270 o3 := testDefaultOptionsForGateway("B") 1271 o3.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", s2.ClusterAddr().Port)) 1272 s3 := runGatewayServer(o3) 1273 defer s3.Shutdown() 1274 1275 // Wait for cluster between s2/s3 to form 1276 checkClusterFormed(t, s2, s3) 1277 1278 // s3 should have been notified about existence of A and create its gateway to A. 1279 waitForOutboundGateways(t, s1, 1, 2*time.Second) 1280 waitForOutboundGateways(t, s2, 1, 2*time.Second) 1281 waitForOutboundGateways(t, s3, 1, 2*time.Second) 1282 } 1283 1284 func TestGatewayImplicitReconnect(t *testing.T) { 1285 o2 := testDefaultOptionsForGateway("B") 1286 o2.Gateway.ConnectRetries = 5 1287 s2 := runGatewayServer(o2) 1288 defer s2.Shutdown() 1289 1290 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 1291 s1 := runGatewayServer(o1) 1292 defer s1.Shutdown() 1293 1294 // s1 should have an outbound gateway to s2. 1295 waitForOutboundGateways(t, s1, 1, time.Second) 1296 // s2 should have an inbound gateway 1297 waitForInboundGateways(t, s2, 1, time.Second) 1298 // It will have also created an implicit outbound connection to s1. 1299 // We need to wait for that implicit outbound connection to be made 1300 // to show that it will try to reconnect when we stop/restart s1 1301 // (without config to connect to B). 1302 waitForOutboundGateways(t, s2, 1, time.Second) 1303 1304 // Shutdown s1, remove the gateway from A to B and restart. 1305 s1.Shutdown() 1306 o1.Gateway.Gateways = o1.Gateway.Gateways[:0] 1307 s1 = runGatewayServer(o1) 1308 defer s1.Shutdown() 1309 1310 // s1 should have both outbound and inbound to s2 1311 waitForOutboundGateways(t, s1, 1, 2*time.Second) 1312 waitForInboundGateways(t, s1, 1, 2*time.Second) 1313 1314 // Same for s2 1315 waitForOutboundGateways(t, s2, 1, 2*time.Second) 1316 waitForInboundGateways(t, s2, 1, 2*time.Second) 1317 1318 // Verify that s2 still has "A" in its gateway config 1319 if s2.getRemoteGateway("A") == nil { 1320 t.Fatal("Gateway A should be in s2") 1321 } 1322 } 1323 1324 func TestGatewayImplicitReconnectRace(t *testing.T) { 1325 ob := testDefaultOptionsForGateway("B") 1326 resolver := &slowResolver{ 1327 inLookupCh: make(chan struct{}, 1), 1328 releaseCh: make(chan struct{}), 1329 } 1330 ob.Gateway.resolver = resolver 1331 sb := runGatewayServer(ob) 1332 defer sb.Shutdown() 1333 1334 oa1 := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 1335 sa1 := runGatewayServer(oa1) 1336 defer sa1.Shutdown() 1337 1338 // Wait for the proper connections 1339 waitForOutboundGateways(t, sa1, 1, time.Second) 1340 waitForOutboundGateways(t, sb, 1, time.Second) 1341 waitForInboundGateways(t, sa1, 1, time.Second) 1342 waitForInboundGateways(t, sb, 1, time.Second) 1343 1344 // On sb, change the URL to sa1 so that it is a name, instead of an IP, 1345 // so that we hit the slow resolver. 1346 cfg := sb.getRemoteGateway("A") 1347 cfg.updateURLs([]string{fmt.Sprintf("localhost:%d", sa1.GatewayAddr().Port)}) 1348 1349 // Shutdown sa1 now... 1350 sa1.Shutdown() 1351 1352 // Wait to be notified that B has detected the connection close 1353 // and it is trying to resolve the host during the reconnect. 1354 <-resolver.inLookupCh 1355 1356 // Start a new "A" server (sa2). 1357 oa2 := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 1358 sa2 := runGatewayServer(oa2) 1359 defer sa2.Shutdown() 1360 1361 // Make sure we have our outbound to sb registered on sa2 and inbound 1362 // from sa2 on sb before releasing the resolver. 1363 waitForOutboundGateways(t, sa2, 1, 2*time.Second) 1364 waitForInboundGateways(t, sb, 1, 2*time.Second) 1365 1366 // Now release the resolver and ensure we have all connections. 1367 close(resolver.releaseCh) 1368 1369 waitForOutboundGateways(t, sb, 1, 2*time.Second) 1370 waitForInboundGateways(t, sa2, 1, 2*time.Second) 1371 } 1372 1373 type gwReconnAttemptLogger struct { 1374 DummyLogger 1375 errCh chan string 1376 } 1377 1378 func (l *gwReconnAttemptLogger) Errorf(format string, v ...interface{}) { 1379 msg := fmt.Sprintf(format, v...) 1380 if strings.Contains(msg, `Error connecting to implicit gateway "A"`) { 1381 select { 1382 case l.errCh <- msg: 1383 default: 1384 } 1385 } 1386 } 1387 1388 func TestGatewayImplicitReconnectHonorConnectRetries(t *testing.T) { 1389 ob := testDefaultOptionsForGateway("B") 1390 ob.ReconnectErrorReports = 1 1391 ob.Gateway.ConnectRetries = 2 1392 sb := runGatewayServer(ob) 1393 defer sb.Shutdown() 1394 1395 l := &gwReconnAttemptLogger{errCh: make(chan string, 3)} 1396 sb.SetLogger(l, true, false) 1397 1398 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 1399 sa := runGatewayServer(oa) 1400 defer sa.Shutdown() 1401 1402 // Wait for the proper connections 1403 waitForOutboundGateways(t, sa, 1, time.Second) 1404 waitForOutboundGateways(t, sb, 1, time.Second) 1405 waitForInboundGateways(t, sa, 1, time.Second) 1406 waitForInboundGateways(t, sb, 1, time.Second) 1407 1408 // Now have C connect to B. 1409 oc := testGatewayOptionsFromToWithServers(t, "C", "B", sb) 1410 sc := runGatewayServer(oc) 1411 defer sc.Shutdown() 1412 1413 // Wait for the proper connections 1414 waitForOutboundGateways(t, sa, 2, time.Second) 1415 waitForOutboundGateways(t, sb, 2, time.Second) 1416 waitForOutboundGateways(t, sc, 2, time.Second) 1417 waitForInboundGateways(t, sa, 2, time.Second) 1418 waitForInboundGateways(t, sb, 2, time.Second) 1419 waitForInboundGateways(t, sc, 2, time.Second) 1420 1421 // Shutdown sa now... 1422 sa.Shutdown() 1423 1424 // B will try to reconnect to A 3 times (we stop after attempts > ConnectRetries) 1425 timeout := time.NewTimer(time.Second) 1426 for i := 0; i < 3; i++ { 1427 select { 1428 case <-l.errCh: 1429 // OK 1430 case <-timeout.C: 1431 t.Fatal("Did not get debug trace about reconnect") 1432 } 1433 } 1434 // If we get 1 more, we have an issue! 1435 select { 1436 case e := <-l.errCh: 1437 t.Fatalf("Should not have attempted to reconnect: %q", e) 1438 case <-time.After(250 * time.Millisecond): 1439 // OK! 1440 } 1441 1442 waitForOutboundGateways(t, sb, 1, 2*time.Second) 1443 waitForInboundGateways(t, sb, 1, 2*time.Second) 1444 waitForOutboundGateways(t, sc, 1, 2*time.Second) 1445 waitForInboundGateways(t, sc, 1, 2*time.Second) 1446 } 1447 1448 func TestGatewayURLsFromClusterSentInINFO(t *testing.T) { 1449 o2 := testDefaultOptionsForGateway("B") 1450 s2 := runGatewayServer(o2) 1451 defer s2.Shutdown() 1452 1453 o3 := testDefaultOptionsForGateway("B") 1454 o3.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", s2.ClusterAddr().Port)) 1455 s3 := runGatewayServer(o3) 1456 defer s3.Shutdown() 1457 1458 checkClusterFormed(t, s2, s3) 1459 1460 // Now start s1 that creates a Gateway connection to s2 1461 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 1462 s1 := runGatewayServer(o1) 1463 defer s1.Shutdown() 1464 1465 // Make sure we have proper outbound/inbound 1466 waitForOutboundGateways(t, s1, 1, time.Second) 1467 waitForOutboundGateways(t, s2, 1, time.Second) 1468 waitForOutboundGateways(t, s3, 1, time.Second) 1469 1470 // Although s1 connected to s2 and knew only about s2, it should have 1471 // received the list of gateway URLs in the B cluster. So if we shutdown 1472 // server s2, it should be able to reconnect to s3. 1473 s2.Shutdown() 1474 // Wait for s3 to register that there s2 is gone. 1475 checkNumRoutes(t, s3, 0) 1476 // s1 should have reconnected to s3 because it learned about it 1477 // when connecting earlier to s2. 1478 waitForOutboundGateways(t, s1, 1, 2*time.Second) 1479 // Also make sure that the gateway's urls map has 2 urls. 1480 gw := s1.getRemoteGateway("B") 1481 if gw == nil { 1482 t.Fatal("Did not find gateway B") 1483 } 1484 gw.RLock() 1485 l := len(gw.urls) 1486 gw.RUnlock() 1487 if l != 2 { 1488 t.Fatalf("S1 should have 2 urls, got %v", l) 1489 } 1490 } 1491 1492 func TestGatewayUseUpdatedURLs(t *testing.T) { 1493 // For this test, we have cluster B with an explicit gateway to cluster A 1494 // on a given URL. Then we create cluster A with a gateway to B with server B's 1495 // GW url, and we expect server B to ultimately create an outbound GW connection 1496 // to server A (with the URL it will get from server A connecting to it). 1497 1498 ob := testGatewayOptionsFromToWithURLs(t, "B", "A", []string{"nats://127.0.0.1:1234"}) 1499 sb := runGatewayServer(ob) 1500 defer sb.Shutdown() 1501 1502 // Add a delay before starting server A to make sure that server B start 1503 // initiating the connection to A on inexistant server at :1234. 1504 time.Sleep(100 * time.Millisecond) 1505 1506 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 1507 sa := runGatewayServer(oa) 1508 defer sa.Shutdown() 1509 1510 // sa should have no problem creating outbound connection to sb 1511 waitForOutboundGateways(t, sa, 1, time.Second) 1512 1513 // Make sure that since sb learns about sa's GW URL, it can successfully 1514 // connect to it. 1515 waitForOutboundGateways(t, sb, 1, 3*time.Second) 1516 waitForInboundGateways(t, sb, 1, time.Second) 1517 waitForInboundGateways(t, sa, 1, time.Second) 1518 } 1519 1520 func TestGatewayAutoDiscovery(t *testing.T) { 1521 o4 := testDefaultOptionsForGateway("D") 1522 s4 := runGatewayServer(o4) 1523 defer s4.Shutdown() 1524 1525 o3 := testGatewayOptionsFromToWithServers(t, "C", "D", s4) 1526 s3 := runGatewayServer(o3) 1527 defer s3.Shutdown() 1528 1529 o2 := testGatewayOptionsFromToWithServers(t, "B", "C", s3) 1530 s2 := runGatewayServer(o2) 1531 defer s2.Shutdown() 1532 1533 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 1534 s1 := runGatewayServer(o1) 1535 defer s1.Shutdown() 1536 1537 // Each server should have 3 outbound gateway connections. 1538 waitForOutboundGateways(t, s1, 3, 2*time.Second) 1539 waitForOutboundGateways(t, s2, 3, 2*time.Second) 1540 waitForOutboundGateways(t, s3, 3, 2*time.Second) 1541 waitForOutboundGateways(t, s4, 3, 2*time.Second) 1542 1543 s1.Shutdown() 1544 s2.Shutdown() 1545 s3.Shutdown() 1546 s4.Shutdown() 1547 1548 o2 = testDefaultOptionsForGateway("B") 1549 s2 = runGatewayServer(o2) 1550 defer s2.Shutdown() 1551 1552 o4 = testGatewayOptionsFromToWithServers(t, "D", "B", s2) 1553 s4 = runGatewayServer(o4) 1554 defer s4.Shutdown() 1555 1556 o3 = testGatewayOptionsFromToWithServers(t, "C", "B", s2) 1557 s3 = runGatewayServer(o3) 1558 defer s3.Shutdown() 1559 1560 o1 = testGatewayOptionsFromToWithServers(t, "A", "B", s2) 1561 s1 = runGatewayServer(o1) 1562 defer s1.Shutdown() 1563 1564 // Each server should have 3 outbound gateway connections. 1565 waitForOutboundGateways(t, s1, 3, 2*time.Second) 1566 waitForOutboundGateways(t, s2, 3, 2*time.Second) 1567 waitForOutboundGateways(t, s3, 3, 2*time.Second) 1568 waitForOutboundGateways(t, s4, 3, 2*time.Second) 1569 1570 s1.Shutdown() 1571 s2.Shutdown() 1572 s3.Shutdown() 1573 s4.Shutdown() 1574 1575 o1 = testDefaultOptionsForGateway("A") 1576 s1 = runGatewayServer(o1) 1577 defer s1.Shutdown() 1578 1579 o2 = testDefaultOptionsForGateway("A") 1580 o2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", s1.ClusterAddr().Port)) 1581 s2 = runGatewayServer(o2) 1582 defer s2.Shutdown() 1583 1584 o3 = testDefaultOptionsForGateway("A") 1585 o3.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", s1.ClusterAddr().Port)) 1586 s3 = runGatewayServer(o3) 1587 defer s3.Shutdown() 1588 1589 checkClusterFormed(t, s1, s2, s3) 1590 1591 o4 = testGatewayOptionsFromToWithServers(t, "B", "A", s1) 1592 s4 = runGatewayServer(o4) 1593 defer s4.Shutdown() 1594 1595 waitForOutboundGateways(t, s1, 1, 2*time.Second) 1596 waitForOutboundGateways(t, s2, 1, 2*time.Second) 1597 waitForOutboundGateways(t, s3, 1, 2*time.Second) 1598 waitForOutboundGateways(t, s4, 1, 2*time.Second) 1599 waitForInboundGateways(t, s4, 3, 2*time.Second) 1600 1601 o5 := testGatewayOptionsFromToWithServers(t, "C", "B", s4) 1602 s5 := runGatewayServer(o5) 1603 defer s5.Shutdown() 1604 1605 waitForOutboundGateways(t, s1, 2, 2*time.Second) 1606 waitForOutboundGateways(t, s2, 2, 2*time.Second) 1607 waitForOutboundGateways(t, s3, 2, 2*time.Second) 1608 waitForOutboundGateways(t, s4, 2, 2*time.Second) 1609 waitForInboundGateways(t, s4, 4, 2*time.Second) 1610 waitForOutboundGateways(t, s5, 2, 2*time.Second) 1611 waitForInboundGateways(t, s5, 4, 2*time.Second) 1612 } 1613 1614 func TestGatewayRejectUnknown(t *testing.T) { 1615 o2 := testDefaultOptionsForGateway("B") 1616 s2 := runGatewayServer(o2) 1617 defer s2.Shutdown() 1618 1619 // Create a gateway from A to B, but configure B to reject non configured ones. 1620 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 1621 o1.Gateway.RejectUnknown = true 1622 s1 := runGatewayServer(o1) 1623 defer s1.Shutdown() 1624 1625 // Wait for outbound/inbound to be created. 1626 waitForOutboundGateways(t, s1, 1, time.Second) 1627 waitForOutboundGateways(t, s2, 1, time.Second) 1628 waitForInboundGateways(t, s1, 1, time.Second) 1629 waitForInboundGateways(t, s2, 1, time.Second) 1630 1631 // Create gateway C to B. B will tell C to connect to A, 1632 // which A should reject. 1633 o3 := testGatewayOptionsFromToWithServers(t, "C", "B", s2) 1634 s3 := runGatewayServer(o3) 1635 defer s3.Shutdown() 1636 1637 // s3 should have outbound to B, but not to A 1638 waitForOutboundGateways(t, s3, 1, time.Second) 1639 // s2 should have 2 inbounds (one from s1 one from s3) 1640 waitForInboundGateways(t, s2, 2, time.Second) 1641 1642 // s1 should have single outbound/inbound with s2. 1643 waitForOutboundGateways(t, s1, 1, time.Second) 1644 waitForInboundGateways(t, s1, 1, time.Second) 1645 1646 // It should not have a registered remote gateway with C (s3) 1647 if s1.getOutboundGatewayConnection("C") != nil { 1648 t.Fatalf("A should not have outbound gateway to C") 1649 } 1650 if s1.getRemoteGateway("C") != nil { 1651 t.Fatalf("A should not have a registered remote gateway to C") 1652 } 1653 1654 // Restart s1 and this time, B will tell A to connect to C. 1655 // But A will not even attempt that since it does not have 1656 // C configured. 1657 s1.Shutdown() 1658 waitForOutboundGateways(t, s2, 1, time.Second) 1659 waitForInboundGateways(t, s2, 1, time.Second) 1660 s1 = runGatewayServer(o1) 1661 defer s1.Shutdown() 1662 waitForOutboundGateways(t, s2, 2, time.Second) 1663 waitForInboundGateways(t, s2, 2, time.Second) 1664 waitForOutboundGateways(t, s1, 1, time.Second) 1665 waitForInboundGateways(t, s1, 1, time.Second) 1666 waitForOutboundGateways(t, s3, 1, time.Second) 1667 waitForInboundGateways(t, s3, 1, time.Second) 1668 // It should not have a registered remote gateway with C (s3) 1669 if s1.getOutboundGatewayConnection("C") != nil { 1670 t.Fatalf("A should not have outbound gateway to C") 1671 } 1672 if s1.getRemoteGateway("C") != nil { 1673 t.Fatalf("A should not have a registered remote gateway to C") 1674 } 1675 } 1676 1677 func TestGatewayNoReconnectOnClose(t *testing.T) { 1678 o2 := testDefaultOptionsForGateway("B") 1679 s2 := runGatewayServer(o2) 1680 defer s2.Shutdown() 1681 1682 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 1683 s1 := runGatewayServer(o1) 1684 defer s1.Shutdown() 1685 1686 waitForOutboundGateways(t, s1, 1, time.Second) 1687 waitForOutboundGateways(t, s2, 1, time.Second) 1688 1689 // Shutdown s1, and check that there is no attempt to reconnect. 1690 s1.Shutdown() 1691 time.Sleep(250 * time.Millisecond) 1692 waitForOutboundGateways(t, s1, 0, time.Second) 1693 waitForOutboundGateways(t, s2, 0, time.Second) 1694 waitForInboundGateways(t, s2, 0, time.Second) 1695 } 1696 1697 func TestGatewayDontSendSubInterest(t *testing.T) { 1698 o2 := testDefaultOptionsForGateway("B") 1699 s2 := runGatewayServer(o2) 1700 defer s2.Shutdown() 1701 1702 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 1703 s1 := runGatewayServer(o1) 1704 defer s1.Shutdown() 1705 1706 waitForOutboundGateways(t, s1, 1, time.Second) 1707 waitForOutboundGateways(t, s2, 1, time.Second) 1708 1709 s2Url := fmt.Sprintf("nats://127.0.0.1:%d", o2.Port) 1710 subnc := natsConnect(t, s2Url) 1711 defer subnc.Close() 1712 natsSub(t, subnc, "foo", func(_ *nats.Msg) {}) 1713 natsFlush(t, subnc) 1714 1715 checkExpectedSubs(t, 1, s2) 1716 // Subscription should not be sent to s1 1717 checkExpectedSubs(t, 0, s1) 1718 1719 // Restart s1 1720 s1.Shutdown() 1721 s1 = runGatewayServer(o1) 1722 defer s1.Shutdown() 1723 waitForOutboundGateways(t, s1, 1, time.Second) 1724 waitForOutboundGateways(t, s2, 1, time.Second) 1725 1726 checkExpectedSubs(t, 1, s2) 1727 checkExpectedSubs(t, 0, s1) 1728 } 1729 1730 func setAccountUserPassInOptions(o *Options, accName, username, password string) { 1731 acc := NewAccount(accName) 1732 o.Accounts = append(o.Accounts, acc) 1733 o.Users = append(o.Users, &User{Username: username, Password: password, Account: acc}) 1734 } 1735 1736 func TestGatewayAccountInterest(t *testing.T) { 1737 GatewayDoNotForceInterestOnlyMode(true) 1738 defer GatewayDoNotForceInterestOnlyMode(false) 1739 1740 o2 := testDefaultOptionsForGateway("B") 1741 // Add users to cause s2 to require auth. Will add an account with user later. 1742 o2.Users = append([]*User(nil), &User{Username: "test", Password: "pwd"}) 1743 s2 := runGatewayServer(o2) 1744 defer s2.Shutdown() 1745 1746 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 1747 setAccountUserPassInOptions(o1, "$foo", "ivan", "password") 1748 s1 := runGatewayServer(o1) 1749 defer s1.Shutdown() 1750 1751 // Make this server initiate connection to A, so it is faster 1752 // when restarting it at the end of this test. 1753 o3 := testGatewayOptionsFromToWithServers(t, "C", "A", s1) 1754 setAccountUserPassInOptions(o3, "$foo", "ivan", "password") 1755 s3 := runGatewayServer(o3) 1756 defer s3.Shutdown() 1757 1758 waitForOutboundGateways(t, s1, 2, time.Second) 1759 waitForOutboundGateways(t, s2, 2, time.Second) 1760 waitForOutboundGateways(t, s3, 2, time.Second) 1761 1762 s1Url := fmt.Sprintf("nats://ivan:password@127.0.0.1:%d", o1.Port) 1763 nc := natsConnect(t, s1Url) 1764 defer nc.Close() 1765 natsPub(t, nc, "foo", []byte("hello")) 1766 natsFlush(t, nc) 1767 1768 // On first send, the message should be sent. 1769 checkCount := func(t *testing.T, c *client, expected int) { 1770 t.Helper() 1771 c.mu.Lock() 1772 out := c.outMsgs 1773 c.mu.Unlock() 1774 if int(out) != expected { 1775 t.Fatalf("Expected %d message(s) to be sent over, got %v", expected, out) 1776 } 1777 } 1778 gwcb := s1.getOutboundGatewayConnection("B") 1779 checkCount(t, gwcb, 1) 1780 gwcc := s1.getOutboundGatewayConnection("C") 1781 checkCount(t, gwcc, 1) 1782 1783 // S2 and S3 should have sent a protocol indicating no account interest. 1784 checkForAccountNoInterest(t, gwcb, "$foo", true, 2*time.Second) 1785 checkForAccountNoInterest(t, gwcc, "$foo", true, 2*time.Second) 1786 // Second send should not go to B nor C. 1787 natsPub(t, nc, "foo", []byte("hello")) 1788 natsFlush(t, nc) 1789 checkCount(t, gwcb, 1) 1790 checkCount(t, gwcc, 1) 1791 1792 // Add account to S2 and a client, this should clear the no-interest 1793 // for that account. 1794 s2FooAcc, err := s2.RegisterAccount("$foo") 1795 if err != nil { 1796 t.Fatalf("Error registering account: %v", err) 1797 } 1798 s2.mu.Lock() 1799 s2.users["ivan"] = &User{Account: s2FooAcc, Username: "ivan", Password: "password"} 1800 s2.mu.Unlock() 1801 s2Url := fmt.Sprintf("nats://ivan:password@127.0.0.1:%d", o2.Port) 1802 ncS2 := natsConnect(t, s2Url) 1803 defer ncS2.Close() 1804 // Any subscription should cause s2 to send an A+ 1805 natsSubSync(t, ncS2, "asub") 1806 // Wait for the A+ 1807 checkForAccountNoInterest(t, gwcb, "$foo", false, 2*time.Second) 1808 1809 // Now publish a message that should go to B 1810 natsPub(t, nc, "foo", []byte("hello")) 1811 natsFlush(t, nc) 1812 checkCount(t, gwcb, 2) 1813 // Still won't go to C since there is no sub interest 1814 checkCount(t, gwcc, 1) 1815 1816 // We should have received a subject no interest for foo 1817 checkForSubjectNoInterest(t, gwcb, "$foo", "foo", true, 2*time.Second) 1818 1819 // Now if we close the client, which removed the sole subscription, 1820 // and publish to a new subject, we should then get an A- 1821 ncS2.Close() 1822 // Wait a bit... 1823 time.Sleep(20 * time.Millisecond) 1824 // Publish on new subject 1825 natsPub(t, nc, "bar", []byte("hello")) 1826 natsFlush(t, nc) 1827 // It should go out to B... 1828 checkCount(t, gwcb, 3) 1829 // But then we should get a A- 1830 checkForAccountNoInterest(t, gwcb, "$foo", true, 2*time.Second) 1831 1832 // Restart C and that should reset the no-interest 1833 s3.Shutdown() 1834 s3 = runGatewayServer(o3) 1835 defer s3.Shutdown() 1836 1837 waitForOutboundGateways(t, s1, 2, 2*time.Second) 1838 waitForOutboundGateways(t, s2, 2, 2*time.Second) 1839 waitForOutboundGateways(t, s3, 2, 2*time.Second) 1840 1841 // First refresh gwcc 1842 gwcc = s1.getOutboundGatewayConnection("C") 1843 // Verify that it's count is 0 1844 checkCount(t, gwcc, 0) 1845 // Publish and now... 1846 natsPub(t, nc, "foo", []byte("hello")) 1847 natsFlush(t, nc) 1848 // it should not go to B (no sub interest) 1849 checkCount(t, gwcb, 3) 1850 // but will go to C 1851 checkCount(t, gwcc, 1) 1852 } 1853 1854 func TestGatewayAccountUnsub(t *testing.T) { 1855 ob := testDefaultOptionsForGateway("B") 1856 sb := runGatewayServer(ob) 1857 defer sb.Shutdown() 1858 1859 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 1860 sa := runGatewayServer(oa) 1861 defer sa.Shutdown() 1862 1863 waitForOutboundGateways(t, sa, 1, time.Second) 1864 waitForOutboundGateways(t, sb, 1, time.Second) 1865 waitForInboundGateways(t, sa, 1, time.Second) 1866 waitForInboundGateways(t, sb, 1, time.Second) 1867 1868 // Connect on B 1869 ncb := natsConnect(t, fmt.Sprintf("nats://%s:%d", ob.Host, ob.Port)) 1870 defer ncb.Close() 1871 // Create subscription 1872 natsSub(t, ncb, "foo", func(m *nats.Msg) { 1873 ncb.Publish(m.Reply, []byte("reply")) 1874 }) 1875 natsFlush(t, ncb) 1876 1877 // Connect on A 1878 nca := natsConnect(t, fmt.Sprintf("nats://%s:%d", oa.Host, oa.Port)) 1879 defer nca.Close() 1880 // Send a request 1881 if _, err := nca.Request("foo", []byte("req"), time.Second); err != nil { 1882 t.Fatalf("Error getting reply: %v", err) 1883 } 1884 1885 // Now close connection on B 1886 ncb.Close() 1887 1888 // Publish lots of messages on "foo" from A. 1889 // We should receive an A- shortly and the number 1890 // of outbound messages from A to B should not be 1891 // close to the number of messages sent here. 1892 total := 5000 1893 for i := 0; i < total; i++ { 1894 natsPub(t, nca, "foo", []byte("hello")) 1895 // Try to slow down things a bit to give a chance 1896 // to srvB to send the A- and to srvA to be able 1897 // to process it, which will then suppress the sends. 1898 if i%100 == 0 { 1899 natsFlush(t, nca) 1900 } 1901 } 1902 natsFlush(t, nca) 1903 1904 c := sa.getOutboundGatewayConnection("B") 1905 c.mu.Lock() 1906 out := c.outMsgs 1907 c.mu.Unlock() 1908 1909 if out >= int64(80*total)/100 { 1910 t.Fatalf("Unexpected number of messages sent from A to B: %v", out) 1911 } 1912 } 1913 1914 func TestGatewaySubjectInterest(t *testing.T) { 1915 GatewayDoNotForceInterestOnlyMode(true) 1916 defer GatewayDoNotForceInterestOnlyMode(false) 1917 1918 o1 := testDefaultOptionsForGateway("A") 1919 setAccountUserPassInOptions(o1, "$foo", "ivan", "password") 1920 s1 := runGatewayServer(o1) 1921 defer s1.Shutdown() 1922 1923 o2 := testGatewayOptionsFromToWithServers(t, "B", "A", s1) 1924 setAccountUserPassInOptions(o2, "$foo", "ivan", "password") 1925 s2 := runGatewayServer(o2) 1926 defer s2.Shutdown() 1927 1928 waitForOutboundGateways(t, s1, 1, time.Second) 1929 waitForOutboundGateways(t, s2, 1, time.Second) 1930 1931 // We will create a subscription that we are not testing so 1932 // that we don't get an A- in this test. 1933 s2Url := fmt.Sprintf("nats://ivan:password@127.0.0.1:%d", o2.Port) 1934 ncb := natsConnect(t, s2Url) 1935 defer ncb.Close() 1936 natsSubSync(t, ncb, "not.used") 1937 checkExpectedSubs(t, 1, s2) 1938 1939 s1Url := fmt.Sprintf("nats://ivan:password@127.0.0.1:%d", o1.Port) 1940 nc := natsConnect(t, s1Url) 1941 defer nc.Close() 1942 natsPub(t, nc, "foo", []byte("hello")) 1943 natsFlush(t, nc) 1944 1945 // On first send, the message should be sent. 1946 checkCount := func(t *testing.T, c *client, expected int) { 1947 t.Helper() 1948 c.mu.Lock() 1949 out := c.outMsgs 1950 c.mu.Unlock() 1951 if int(out) != expected { 1952 t.Fatalf("Expected %d message(s) to be sent over, got %v", expected, out) 1953 } 1954 } 1955 gwcb := s1.getOutboundGatewayConnection("B") 1956 checkCount(t, gwcb, 1) 1957 1958 // S2 should have sent a protocol indicating no subject interest. 1959 checkNoInterest := func(t *testing.T, subject string, expectedNoInterest bool) { 1960 t.Helper() 1961 checkForSubjectNoInterest(t, gwcb, "$foo", subject, expectedNoInterest, 2*time.Second) 1962 } 1963 checkNoInterest(t, "foo", true) 1964 // Second send should not go through to B 1965 natsPub(t, nc, "foo", []byte("hello")) 1966 natsFlush(t, nc) 1967 checkCount(t, gwcb, 1) 1968 1969 // Now create subscription interest on B (s2) 1970 ch := make(chan bool, 1) 1971 sub := natsSub(t, ncb, "foo", func(_ *nats.Msg) { 1972 ch <- true 1973 }) 1974 natsFlush(t, ncb) 1975 checkExpectedSubs(t, 2, s2) 1976 checkExpectedSubs(t, 0, s1) 1977 1978 // This should clear the no interest for this subject 1979 checkNoInterest(t, "foo", false) 1980 // Third send should go to B 1981 natsPub(t, nc, "foo", []byte("hello")) 1982 natsFlush(t, nc) 1983 checkCount(t, gwcb, 2) 1984 1985 // Make sure message is received 1986 waitCh(t, ch, "Did not get our message") 1987 // Now unsubscribe, there won't be an UNSUB sent to the gateway. 1988 natsUnsub(t, sub) 1989 natsFlush(t, ncb) 1990 checkExpectedSubs(t, 1, s2) 1991 checkExpectedSubs(t, 0, s1) 1992 1993 // So now sending a message should go over, but then we should get an RS- 1994 natsPub(t, nc, "foo", []byte("hello")) 1995 natsFlush(t, nc) 1996 checkCount(t, gwcb, 3) 1997 1998 checkNoInterest(t, "foo", true) 1999 2000 // Send one more time and now it should not go to B 2001 natsPub(t, nc, "foo", []byte("hello")) 2002 natsFlush(t, nc) 2003 checkCount(t, gwcb, 3) 2004 2005 // Send on bar, message should go over. 2006 natsPub(t, nc, "bar", []byte("hello")) 2007 natsFlush(t, nc) 2008 checkCount(t, gwcb, 4) 2009 2010 // But now we should have receives an RS- on bar. 2011 checkNoInterest(t, "bar", true) 2012 2013 // Check that wildcards are supported. Create a subscription on '*' on B. 2014 // This should clear the no-interest on both "foo" and "bar" 2015 natsSub(t, ncb, "*", func(_ *nats.Msg) {}) 2016 natsFlush(t, ncb) 2017 checkExpectedSubs(t, 2, s2) 2018 checkExpectedSubs(t, 0, s1) 2019 checkNoInterest(t, "foo", false) 2020 checkNoInterest(t, "bar", false) 2021 // Publish on message on foo and one on bar and they should go. 2022 natsPub(t, nc, "foo", []byte("hello")) 2023 natsPub(t, nc, "bar", []byte("hello")) 2024 natsFlush(t, nc) 2025 checkCount(t, gwcb, 6) 2026 2027 // Restart B and that should clear everything on A 2028 ncb.Close() 2029 s2.Shutdown() 2030 s2 = runGatewayServer(o2) 2031 defer s2.Shutdown() 2032 2033 waitForOutboundGateways(t, s1, 1, time.Second) 2034 waitForOutboundGateways(t, s2, 1, time.Second) 2035 2036 ncb = natsConnect(t, s2Url) 2037 defer ncb.Close() 2038 natsSubSync(t, ncb, "not.used") 2039 checkExpectedSubs(t, 1, s2) 2040 2041 gwcb = s1.getOutboundGatewayConnection("B") 2042 checkCount(t, gwcb, 0) 2043 natsPub(t, nc, "foo", []byte("hello")) 2044 natsFlush(t, nc) 2045 checkCount(t, gwcb, 1) 2046 2047 checkNoInterest(t, "foo", true) 2048 2049 natsPub(t, nc, "foo", []byte("hello")) 2050 natsFlush(t, nc) 2051 checkCount(t, gwcb, 1) 2052 2053 // Add a node to B cluster and subscribe there. 2054 // We want to ensure that the no-interest is cleared 2055 // when s2 receives remote SUB from s2bis 2056 o2bis := testGatewayOptionsFromToWithServers(t, "B", "A", s1) 2057 setAccountUserPassInOptions(o2bis, "$foo", "ivan", "password") 2058 o2bis.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", s2.ClusterAddr().Port)) 2059 s2bis := runGatewayServer(o2bis) 2060 defer s2bis.Shutdown() 2061 2062 checkClusterFormed(t, s2, s2bis) 2063 2064 // Make sure all outbound gateway connections are setup 2065 waitForOutboundGateways(t, s1, 1, time.Second) 2066 waitForOutboundGateways(t, s2, 1, time.Second) 2067 waitForOutboundGateways(t, s2bis, 1, time.Second) 2068 2069 // A should have 2 inbound 2070 waitForInboundGateways(t, s1, 2, time.Second) 2071 2072 // Create sub on s2bis 2073 ncb2bis := natsConnect(t, fmt.Sprintf("nats://ivan:password@127.0.0.1:%d", o2bis.Port)) 2074 defer ncb2bis.Close() 2075 natsSub(t, ncb2bis, "foo", func(_ *nats.Msg) {}) 2076 natsFlush(t, ncb2bis) 2077 2078 // Wait for subscriptions to be registered locally on s2bis and remotely on s2 2079 checkExpectedSubs(t, 2, s2, s2bis) 2080 2081 // Check that subject no-interest on A was cleared. 2082 checkNoInterest(t, "foo", false) 2083 2084 // Now publish. Remember, s1 has outbound gateway to s2, and s2 does not 2085 // have a local subscription and has previously sent a no-interest on "foo". 2086 // We check that this has been cleared due to the interest on s2bis. 2087 natsPub(t, nc, "foo", []byte("hello")) 2088 natsFlush(t, nc) 2089 checkCount(t, gwcb, 2) 2090 } 2091 2092 func TestGatewayDoesntSendBackToItself(t *testing.T) { 2093 o2 := testDefaultOptionsForGateway("B") 2094 s2 := runGatewayServer(o2) 2095 defer s2.Shutdown() 2096 2097 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 2098 s1 := runGatewayServer(o1) 2099 defer s1.Shutdown() 2100 2101 waitForOutboundGateways(t, s1, 1, time.Second) 2102 waitForOutboundGateways(t, s2, 1, time.Second) 2103 2104 s2Url := fmt.Sprintf("nats://127.0.0.1:%d", o2.Port) 2105 nc2 := natsConnect(t, s2Url) 2106 defer nc2.Close() 2107 2108 count := int32(0) 2109 cb := func(_ *nats.Msg) { 2110 atomic.AddInt32(&count, 1) 2111 } 2112 natsSub(t, nc2, "foo", cb) 2113 natsFlush(t, nc2) 2114 2115 s1Url := fmt.Sprintf("nats://127.0.0.1:%d", o1.Port) 2116 nc1 := natsConnect(t, s1Url) 2117 defer nc1.Close() 2118 2119 natsSub(t, nc1, "foo", cb) 2120 natsFlush(t, nc1) 2121 2122 // Now send 1 message. If there is a cycle, after few ms we 2123 // should have tons of messages... 2124 natsPub(t, nc1, "foo", []byte("cycle")) 2125 natsFlush(t, nc1) 2126 time.Sleep(100 * time.Millisecond) 2127 if c := atomic.LoadInt32(&count); c != 2 { 2128 t.Fatalf("Expected only 2 messages, got %v", c) 2129 } 2130 } 2131 2132 func TestGatewayOrderedOutbounds(t *testing.T) { 2133 o2 := testDefaultOptionsForGateway("B") 2134 s2 := runGatewayServer(o2) 2135 defer s2.Shutdown() 2136 2137 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 2138 s1 := runGatewayServer(o1) 2139 defer s1.Shutdown() 2140 2141 o3 := testGatewayOptionsFromToWithServers(t, "C", "B", s2) 2142 s3 := runGatewayServer(o3) 2143 defer s3.Shutdown() 2144 2145 waitForOutboundGateways(t, s1, 2, time.Second) 2146 waitForOutboundGateways(t, s2, 2, time.Second) 2147 waitForOutboundGateways(t, s3, 2, time.Second) 2148 2149 gws := make([]*client, 0, 2) 2150 s2.getOutboundGatewayConnections(&gws) 2151 2152 // RTTs are expected to be initially 0. So update RTT of first 2153 // in the array so that its value is no longer 0, this should 2154 // cause order to be flipped. 2155 c := gws[0] 2156 c.mu.Lock() 2157 c.sendPing() 2158 c.mu.Unlock() 2159 2160 // Wait a tiny but 2161 time.Sleep(15 * time.Millisecond) 2162 // Get the ordering again. 2163 gws = gws[:0] 2164 s2.getOutboundGatewayConnections(&gws) 2165 // Verify order is correct. 2166 fRTT := gws[0].getRTTValue() 2167 sRTT := gws[1].getRTTValue() 2168 if fRTT > sRTT { 2169 t.Fatalf("Wrong ordering: %v, %v", fRTT, sRTT) 2170 } 2171 2172 // What is the first in the array? 2173 gws[0].mu.Lock() 2174 gwName := gws[0].gw.name 2175 gws[0].mu.Unlock() 2176 if gwName == "A" { 2177 s1.Shutdown() 2178 } else { 2179 s3.Shutdown() 2180 } 2181 waitForOutboundGateways(t, s2, 1, time.Second) 2182 gws = gws[:0] 2183 s2.getOutboundGatewayConnections(&gws) 2184 if len(gws) != 1 { 2185 t.Fatalf("Expected size of outo to be 1, got %v", len(gws)) 2186 } 2187 gws[0].mu.Lock() 2188 name := gws[0].gw.name 2189 gws[0].mu.Unlock() 2190 if gwName == name { 2191 t.Fatalf("Gateway %q should have been removed", gwName) 2192 } 2193 // Stop the remaining gateway 2194 if gwName == "A" { 2195 s3.Shutdown() 2196 } else { 2197 s1.Shutdown() 2198 } 2199 waitForOutboundGateways(t, s2, 0, time.Second) 2200 gws = gws[:0] 2201 s2.getOutboundGatewayConnections(&gws) 2202 if len(gws) != 0 { 2203 t.Fatalf("Expected size of outo to be 0, got %v", len(gws)) 2204 } 2205 } 2206 2207 func TestGatewayQueueSub(t *testing.T) { 2208 o2 := testDefaultOptionsForGateway("B") 2209 s2 := runGatewayServer(o2) 2210 defer s2.Shutdown() 2211 2212 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 2213 s1 := runGatewayServer(o1) 2214 defer s1.Shutdown() 2215 2216 waitForOutboundGateways(t, s1, 1, time.Second) 2217 waitForOutboundGateways(t, s2, 1, time.Second) 2218 2219 sBUrl := fmt.Sprintf("nats://127.0.0.1:%d", o2.Port) 2220 ncB := natsConnect(t, sBUrl) 2221 defer ncB.Close() 2222 2223 count2 := int32(0) 2224 cb2 := func(_ *nats.Msg) { 2225 atomic.AddInt32(&count2, 1) 2226 } 2227 qsubOnB := natsQueueSub(t, ncB, "foo", "bar", cb2) 2228 natsFlush(t, ncB) 2229 2230 sAUrl := fmt.Sprintf("nats://127.0.0.1:%d", o1.Port) 2231 ncA := natsConnect(t, sAUrl) 2232 defer ncA.Close() 2233 2234 count1 := int32(0) 2235 cb1 := func(_ *nats.Msg) { 2236 atomic.AddInt32(&count1, 1) 2237 } 2238 qsubOnA := natsQueueSub(t, ncA, "foo", "bar", cb1) 2239 natsFlush(t, ncA) 2240 2241 // Make sure subs are registered on each server 2242 checkExpectedSubs(t, 1, s1, s2) 2243 checkForRegisteredQSubInterest(t, s1, "B", globalAccountName, "foo", 1, time.Second) 2244 checkForRegisteredQSubInterest(t, s2, "A", globalAccountName, "foo", 1, time.Second) 2245 2246 total := 100 2247 send := func(t *testing.T, nc *nats.Conn) { 2248 t.Helper() 2249 for i := 0; i < total; i++ { 2250 // Alternate with adding a reply 2251 if i%2 == 0 { 2252 natsPubReq(t, nc, "foo", "reply", []byte("msg")) 2253 } else { 2254 natsPub(t, nc, "foo", []byte("msg")) 2255 } 2256 } 2257 natsFlush(t, nc) 2258 } 2259 // Send from client connecting to S1 (cluster A) 2260 send(t, ncA) 2261 2262 check := func(t *testing.T, count *int32, expected int) { 2263 t.Helper() 2264 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 2265 if n := int(atomic.LoadInt32(count)); n != expected { 2266 return fmt.Errorf("Expected to get %v messages, got %v", expected, n) 2267 } 2268 return nil 2269 }) 2270 } 2271 // Check that all messages stay on S1 (cluster A) 2272 check(t, &count1, total) 2273 check(t, &count2, 0) 2274 2275 // Now send from the other side 2276 send(t, ncB) 2277 check(t, &count1, total) 2278 check(t, &count2, total) 2279 2280 // Reset counters 2281 atomic.StoreInt32(&count1, 0) 2282 atomic.StoreInt32(&count2, 0) 2283 2284 // Add different queue group and make sure that messages are received 2285 count3 := int32(0) 2286 cb3 := func(_ *nats.Msg) { 2287 atomic.AddInt32(&count3, 1) 2288 } 2289 batQSub := natsQueueSub(t, ncB, "foo", "bat", cb3) 2290 natsFlush(t, ncB) 2291 checkExpectedSubs(t, 2, s2) 2292 2293 checkForRegisteredQSubInterest(t, s1, "B", globalAccountName, "foo", 2, time.Second) 2294 2295 send(t, ncA) 2296 check(t, &count1, total) 2297 check(t, &count2, 0) 2298 check(t, &count3, total) 2299 2300 // Reset counters 2301 atomic.StoreInt32(&count1, 0) 2302 atomic.StoreInt32(&count2, 0) 2303 atomic.StoreInt32(&count3, 0) 2304 2305 natsUnsub(t, batQSub) 2306 natsFlush(t, ncB) 2307 checkExpectedSubs(t, 1, s2) 2308 2309 checkForRegisteredQSubInterest(t, s1, "B", globalAccountName, "foo", 1, time.Second) 2310 2311 // Stop qsub on A, and send messages to A, they should 2312 // be routed to B. 2313 qsubOnA.Unsubscribe() 2314 checkExpectedSubs(t, 0, s1) 2315 send(t, ncA) 2316 check(t, &count1, 0) 2317 check(t, &count2, total) 2318 2319 // Reset counters 2320 atomic.StoreInt32(&count1, 0) 2321 atomic.StoreInt32(&count2, 0) 2322 2323 // Create a C gateway now 2324 o3 := testGatewayOptionsFromToWithServers(t, "C", "B", s2) 2325 s3 := runGatewayServer(o3) 2326 defer s3.Shutdown() 2327 2328 waitForOutboundGateways(t, s1, 2, time.Second) 2329 waitForOutboundGateways(t, s2, 2, time.Second) 2330 waitForOutboundGateways(t, s3, 2, time.Second) 2331 2332 waitForInboundGateways(t, s1, 2, time.Second) 2333 waitForInboundGateways(t, s2, 2, time.Second) 2334 waitForInboundGateways(t, s3, 2, time.Second) 2335 2336 // Create another qsub "bar" 2337 sCUrl := fmt.Sprintf("nats://127.0.0.1:%d", o3.Port) 2338 ncC := natsConnect(t, sCUrl) 2339 defer ncC.Close() 2340 // Associate this with count1 (since A qsub is no longer running) 2341 natsQueueSub(t, ncC, "foo", "bar", cb1) 2342 natsFlush(t, ncC) 2343 checkExpectedSubs(t, 1, s3) 2344 checkForRegisteredQSubInterest(t, s1, "C", globalAccountName, "foo", 1, time.Second) 2345 checkForRegisteredQSubInterest(t, s2, "C", globalAccountName, "foo", 1, time.Second) 2346 2347 // Artificially bump the RTT from A to C so that 2348 // the code should favor sending to B. 2349 gwcC := s1.getOutboundGatewayConnection("C") 2350 gwcC.mu.Lock() 2351 gwcC.rtt = 10 * time.Second 2352 gwcC.mu.Unlock() 2353 s1.gateway.orderOutboundConnections() 2354 2355 send(t, ncA) 2356 check(t, &count1, 0) 2357 check(t, &count2, total) 2358 2359 // Add a new group on s3 that should receive all messages 2360 natsQueueSub(t, ncC, "foo", "baz", cb3) 2361 natsFlush(t, ncC) 2362 checkExpectedSubs(t, 2, s3) 2363 checkForRegisteredQSubInterest(t, s1, "C", globalAccountName, "foo", 2, time.Second) 2364 checkForRegisteredQSubInterest(t, s2, "C", globalAccountName, "foo", 2, time.Second) 2365 2366 // Reset counters 2367 atomic.StoreInt32(&count1, 0) 2368 atomic.StoreInt32(&count2, 0) 2369 2370 // Make the RTTs equal 2371 gwcC.mu.Lock() 2372 gwcC.rtt = time.Second 2373 gwcC.mu.Unlock() 2374 2375 gwcB := s1.getOutboundGatewayConnection("B") 2376 gwcB.mu.Lock() 2377 gwcB.rtt = time.Second 2378 gwcB.mu.Unlock() 2379 2380 s1.gateway.Lock() 2381 s1.gateway.orderOutboundConnectionsLocked() 2382 destName := s1.gateway.outo[0].gw.name 2383 s1.gateway.Unlock() 2384 2385 send(t, ncA) 2386 // Group baz should receive all messages 2387 check(t, &count3, total) 2388 2389 // Ordering is normally re-evaluated when processing PONGs, 2390 // but rest of the time order will remain the same. 2391 // Since RTT are equal, messages will go to the first 2392 // GW in the array. 2393 if destName == "B" { 2394 check(t, &count2, total) 2395 } else if destName == "C" && int(atomic.LoadInt32(&count2)) != total { 2396 check(t, &count1, total) 2397 } 2398 2399 // Unsubscribe qsub on B and C should receive 2400 // all messages on count1 and count3. 2401 qsubOnB.Unsubscribe() 2402 checkExpectedSubs(t, 0, s2) 2403 2404 // gwcB should have the qsubs interest map empty now. 2405 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 2406 ei, _ := gwcB.gw.outsim.Load(globalAccountName) 2407 if ei != nil { 2408 sl := ei.(*outsie).sl 2409 if sl.Count() == 0 { 2410 return nil 2411 } 2412 } 2413 return fmt.Errorf("Qsub interest for account should have been removed") 2414 }) 2415 2416 // Reset counters 2417 atomic.StoreInt32(&count1, 0) 2418 atomic.StoreInt32(&count2, 0) 2419 atomic.StoreInt32(&count3, 0) 2420 2421 send(t, ncA) 2422 check(t, &count1, total) 2423 check(t, &count3, total) 2424 } 2425 2426 func TestGatewayTotalQSubs(t *testing.T) { 2427 ob1 := testDefaultOptionsForGateway("B") 2428 sb1 := runGatewayServer(ob1) 2429 defer sb1.Shutdown() 2430 2431 ob2 := testDefaultOptionsForGateway("B") 2432 ob2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", sb1.ClusterAddr().Port)) 2433 sb2 := runGatewayServer(ob2) 2434 defer sb2.Shutdown() 2435 2436 checkClusterFormed(t, sb1, sb2) 2437 2438 sb1URL := fmt.Sprintf("nats://%s:%d", ob1.Host, ob1.Port) 2439 ncb1 := natsConnect(t, sb1URL, nats.ReconnectWait(50*time.Millisecond)) 2440 defer ncb1.Close() 2441 2442 sb2URL := fmt.Sprintf("nats://%s:%d", ob2.Host, ob2.Port) 2443 ncb2 := natsConnect(t, sb2URL, nats.ReconnectWait(50*time.Millisecond)) 2444 defer ncb2.Close() 2445 2446 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb1) 2447 sa := runGatewayServer(oa) 2448 defer sa.Shutdown() 2449 2450 waitForOutboundGateways(t, sa, 1, 2*time.Second) 2451 waitForOutboundGateways(t, sb1, 1, 2*time.Second) 2452 waitForOutboundGateways(t, sb2, 1, 2*time.Second) 2453 waitForInboundGateways(t, sa, 2, 2*time.Second) 2454 waitForInboundGateways(t, sb1, 1, 2*time.Second) 2455 2456 checkTotalQSubs := func(t *testing.T, s *Server, expected int) { 2457 t.Helper() 2458 checkFor(t, time.Second, 15*time.Millisecond, func() error { 2459 if n := int(atomic.LoadInt64(&s.gateway.totalQSubs)); n != expected { 2460 return fmt.Errorf("Expected TotalQSubs to be %v, got %v", expected, n) 2461 } 2462 return nil 2463 }) 2464 } 2465 2466 cb := func(_ *nats.Msg) {} 2467 2468 natsQueueSub(t, ncb1, "foo", "bar", cb) 2469 checkTotalQSubs(t, sa, 1) 2470 qsub2 := natsQueueSub(t, ncb1, "foo", "baz", cb) 2471 checkTotalQSubs(t, sa, 2) 2472 qsub3 := natsQueueSub(t, ncb1, "foo", "baz", cb) 2473 checkTotalQSubs(t, sa, 2) 2474 2475 // Shutdown sb1, there should be a failover from clients 2476 // to sb2. sb2 will then send the queue subs to sa. 2477 sb1.Shutdown() 2478 2479 checkClientsCount(t, sb2, 2) 2480 checkExpectedSubs(t, 3, sb2) 2481 2482 waitForOutboundGateways(t, sa, 1, 2*time.Second) 2483 waitForOutboundGateways(t, sb2, 1, 2*time.Second) 2484 waitForInboundGateways(t, sa, 1, 2*time.Second) 2485 waitForInboundGateways(t, sb2, 1, 2*time.Second) 2486 2487 // When sb1 is shutdown, the total qsubs on sa should fall 2488 // down to 0, but will be updated as soon as sa and sb2 2489 // connect to each other. So instead we will verify by 2490 // making sure that the count is 2 instead of 4 if there 2491 // was a bug. 2492 // (note that there are 2 qsubs on same group, so only 2493 // 1 RS+ would have been sent for that group) 2494 checkTotalQSubs(t, sa, 2) 2495 2496 // Restart sb1 2497 sb1 = runGatewayServer(ob1) 2498 defer sb1.Shutdown() 2499 2500 checkClusterFormed(t, sb1, sb2) 2501 2502 waitForOutboundGateways(t, sa, 1, 2*time.Second) 2503 waitForOutboundGateways(t, sb1, 1, 2*time.Second) 2504 waitForOutboundGateways(t, sb2, 1, 2*time.Second) 2505 waitForInboundGateways(t, sa, 2, 2*time.Second) 2506 waitForInboundGateways(t, sb1, 0, 2*time.Second) 2507 waitForInboundGateways(t, sb2, 1, 2*time.Second) 2508 2509 // Now start unsubscribing. Start with one of the duplicate 2510 // and check that count stays same. 2511 natsUnsub(t, qsub3) 2512 checkTotalQSubs(t, sa, 2) 2513 // Now the other, which would cause an RS- 2514 natsUnsub(t, qsub2) 2515 checkTotalQSubs(t, sa, 1) 2516 // Now test that if connections are closed, things are updated 2517 // properly. 2518 ncb1.Close() 2519 ncb2.Close() 2520 checkTotalQSubs(t, sa, 0) 2521 } 2522 2523 func TestGatewaySendQSubsOnGatewayConnect(t *testing.T) { 2524 o2 := testDefaultOptionsForGateway("B") 2525 s2 := runGatewayServer(o2) 2526 defer s2.Shutdown() 2527 2528 s2Url := fmt.Sprintf("nats://127.0.0.1:%d", o2.Port) 2529 subnc := natsConnect(t, s2Url) 2530 defer subnc.Close() 2531 2532 ch := make(chan bool, 1) 2533 cb := func(_ *nats.Msg) { 2534 ch <- true 2535 } 2536 natsQueueSub(t, subnc, "foo", "bar", cb) 2537 natsFlush(t, subnc) 2538 2539 // Now start s1 that creates a gateway to s2 2540 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 2541 s1 := runGatewayServer(o1) 2542 defer s1.Shutdown() 2543 2544 waitForOutboundGateways(t, s1, 1, time.Second) 2545 waitForOutboundGateways(t, s2, 1, time.Second) 2546 2547 checkForRegisteredQSubInterest(t, s1, "B", globalAccountName, "foo", 1, time.Second) 2548 2549 // Publish from s1, message should be received on s2. 2550 pubnc := natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", o1.Port)) 2551 defer pubnc.Close() 2552 // Publish 1 message 2553 natsPub(t, pubnc, "foo", []byte("hello")) 2554 waitCh(t, ch, "Did not get out message") 2555 pubnc.Close() 2556 2557 s1.Shutdown() 2558 s1 = runGatewayServer(o1) 2559 defer s1.Shutdown() 2560 2561 waitForOutboundGateways(t, s1, 1, time.Second) 2562 waitForOutboundGateways(t, s2, 1, time.Second) 2563 2564 checkForRegisteredQSubInterest(t, s1, "B", globalAccountName, "foo", 1, time.Second) 2565 2566 pubnc = natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", o1.Port)) 2567 defer pubnc.Close() 2568 // Publish 1 message 2569 natsPub(t, pubnc, "foo", []byte("hello")) 2570 waitCh(t, ch, "Did not get out message") 2571 } 2572 2573 func TestGatewaySendRemoteQSubs(t *testing.T) { 2574 GatewayDoNotForceInterestOnlyMode(true) 2575 defer GatewayDoNotForceInterestOnlyMode(false) 2576 2577 ob1 := testDefaultOptionsForGateway("B") 2578 sb1 := runGatewayServer(ob1) 2579 defer sb1.Shutdown() 2580 2581 ob2 := testDefaultOptionsForGateway("B") 2582 ob2.Routes = RoutesFromStr(fmt.Sprintf("nats://%s:%d", ob1.Cluster.Host, ob1.Cluster.Port)) 2583 sb2 := runGatewayServer(ob2) 2584 defer sb2.Shutdown() 2585 2586 checkClusterFormed(t, sb1, sb2) 2587 2588 sbURL := fmt.Sprintf("nats://127.0.0.1:%d", ob2.Port) 2589 subnc := natsConnect(t, sbURL) 2590 defer subnc.Close() 2591 2592 ch := make(chan bool, 1) 2593 cb := func(_ *nats.Msg) { 2594 ch <- true 2595 } 2596 qsub1 := natsQueueSub(t, subnc, "foo", "bar", cb) 2597 qsub2 := natsQueueSub(t, subnc, "foo", "bar", cb) 2598 natsFlush(t, subnc) 2599 2600 // There will be 2 local qsubs on the sb2 server where the client is connected 2601 checkExpectedSubs(t, 2, sb2) 2602 // But only 1 remote on sb1 2603 checkExpectedSubs(t, 1, sb1) 2604 2605 // Now start s1 that creates a gateway to sb1 (the one that does not have the local QSub) 2606 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb1) 2607 sa := runGatewayServer(oa) 2608 defer sa.Shutdown() 2609 2610 waitForOutboundGateways(t, sa, 1, time.Second) 2611 waitForOutboundGateways(t, sb1, 1, time.Second) 2612 waitForOutboundGateways(t, sb2, 1, time.Second) 2613 2614 checkForRegisteredQSubInterest(t, sa, "B", globalAccountName, "foo", 1, time.Second) 2615 2616 // Publish from s1, message should be received on s2. 2617 saURL := fmt.Sprintf("nats://127.0.0.1:%d", oa.Port) 2618 pubnc := natsConnect(t, saURL) 2619 defer pubnc.Close() 2620 // Publish 1 message 2621 natsPub(t, pubnc, "foo", []byte("hello")) 2622 natsFlush(t, pubnc) 2623 waitCh(t, ch, "Did not get out message") 2624 2625 // Note that since cluster B has no plain sub, an "RS- $G foo" will have been sent. 2626 // Wait for the no interest to be received by A 2627 checkFor(t, time.Second, 15*time.Millisecond, func() error { 2628 gw := sa.getOutboundGatewayConnection("B").gw 2629 ei, _ := gw.outsim.Load(globalAccountName) 2630 if ei != nil { 2631 e := ei.(*outsie) 2632 e.RLock() 2633 defer e.RUnlock() 2634 if _, inMap := e.ni["foo"]; inMap { 2635 return nil 2636 } 2637 } 2638 return fmt.Errorf("No-interest still not registered") 2639 }) 2640 2641 // Unsubscribe 1 qsub 2642 natsUnsub(t, qsub1) 2643 natsFlush(t, subnc) 2644 // There should be only 1 local qsub on sb2 now, and the remote should still exist on sb1 2645 checkExpectedSubs(t, 1, sb1, sb2) 2646 2647 // Publish 1 message 2648 natsPub(t, pubnc, "foo", []byte("hello")) 2649 natsFlush(t, pubnc) 2650 waitCh(t, ch, "Did not get out message") 2651 2652 // Unsubscribe the remaining 2653 natsUnsub(t, qsub2) 2654 natsFlush(t, subnc) 2655 2656 // No more subs now on both sb1 and sb2 2657 checkExpectedSubs(t, 0, sb1, sb2) 2658 2659 // Server sb1 should not have qsub in its sub interest map 2660 checkFor(t, time.Second, 15*time.Millisecond, func() error { 2661 var entry *sitally 2662 var err error 2663 sb1.gateway.pasi.Lock() 2664 asim := sb1.gateway.pasi.m[globalAccountName] 2665 if asim != nil { 2666 entry = asim["foo bar"] 2667 } 2668 if entry != nil { 2669 err = fmt.Errorf("Map should not have an entry, got %#v", entry) 2670 } 2671 sb1.gateway.pasi.Unlock() 2672 return err 2673 }) 2674 2675 // Let's wait for A to receive the unsubscribe 2676 checkFor(t, time.Second, 15*time.Millisecond, func() error { 2677 gw := sa.getOutboundGatewayConnection("B").gw 2678 ei, _ := gw.outsim.Load(globalAccountName) 2679 if ei != nil { 2680 sl := ei.(*outsie).sl 2681 if sl.Count() == 0 { 2682 return nil 2683 } 2684 } 2685 return fmt.Errorf("Interest still present") 2686 }) 2687 2688 // Now send a message, it won't be sent because A received an RS- 2689 // on the first published message since there was no plain sub interest. 2690 natsPub(t, pubnc, "foo", []byte("hello")) 2691 natsFlush(t, pubnc) 2692 2693 // Get the gateway connection from A (sa) to B (sb1) 2694 gw := sa.getOutboundGatewayConnection("B") 2695 gw.mu.Lock() 2696 out := gw.outMsgs 2697 gw.mu.Unlock() 2698 if out != 2 { 2699 t.Fatalf("Expected 2 out messages, got %v", out) 2700 } 2701 2702 // Restart A 2703 pubnc.Close() 2704 sa.Shutdown() 2705 sa = runGatewayServer(oa) 2706 defer sa.Shutdown() 2707 2708 waitForOutboundGateways(t, sa, 1, time.Second) 2709 2710 // Check qsubs interest should be empty 2711 checkFor(t, time.Second, 15*time.Millisecond, func() error { 2712 gw := sa.getOutboundGatewayConnection("B").gw 2713 if ei, _ := gw.outsim.Load(globalAccountName); ei == nil { 2714 return nil 2715 } 2716 return fmt.Errorf("Interest still present") 2717 }) 2718 } 2719 2720 func TestGatewayComplexSetup(t *testing.T) { 2721 doLog := false 2722 2723 // This test will have the following setup: 2724 // --- means route connection 2725 // === means gateway connection 2726 // [o] is outbound 2727 // [i] is inbound 2728 // Each server as an outbound connection to the other cluster. 2729 // It may have 0 or more inbound connection(s). 2730 // 2731 // Cluster A Cluster B 2732 // sa1 [o]===========>[i] 2733 // | [i]<===========[o] 2734 // | sb1 ------- sb2 2735 // | [i] [o] 2736 // sa2 [o]=============^ || 2737 // [i]<========================|| 2738 ob1 := testDefaultOptionsForGateway("B") 2739 sb1 := runGatewayServer(ob1) 2740 defer sb1.Shutdown() 2741 if doLog { 2742 sb1.SetLogger(logger.NewTestLogger("[B1] - ", true), true, true) 2743 } 2744 2745 oa1 := testGatewayOptionsFromToWithServers(t, "A", "B", sb1) 2746 sa1 := runGatewayServer(oa1) 2747 defer sa1.Shutdown() 2748 if doLog { 2749 sa1.SetLogger(logger.NewTestLogger("[A1] - ", true), true, true) 2750 } 2751 2752 waitForOutboundGateways(t, sa1, 1, time.Second) 2753 waitForOutboundGateways(t, sb1, 1, time.Second) 2754 2755 waitForInboundGateways(t, sa1, 1, time.Second) 2756 waitForInboundGateways(t, sb1, 1, time.Second) 2757 2758 oa2 := testGatewayOptionsFromToWithServers(t, "A", "B", sb1) 2759 oa2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", sa1.ClusterAddr().Port)) 2760 sa2 := runGatewayServer(oa2) 2761 defer sa2.Shutdown() 2762 if doLog { 2763 sa2.SetLogger(logger.NewTestLogger("[A2] - ", true), true, true) 2764 } 2765 2766 checkClusterFormed(t, sa1, sa2) 2767 2768 waitForOutboundGateways(t, sa2, 1, time.Second) 2769 waitForInboundGateways(t, sb1, 2, time.Second) 2770 2771 ob2 := testGatewayOptionsFromToWithServers(t, "B", "A", sa2) 2772 ob2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", sb1.ClusterAddr().Port)) 2773 var sb2 *Server 2774 for { 2775 sb2 = runGatewayServer(ob2) 2776 defer sb2.Shutdown() 2777 2778 checkClusterFormed(t, sb1, sb2) 2779 2780 waitForOutboundGateways(t, sb2, 1, time.Second) 2781 waitForInboundGateways(t, sb2, 0, time.Second) 2782 // For this test, we want the outbound to be to sa2, so if we don't have that, 2783 // restart sb2 until we get lucky. 2784 time.Sleep(100 * time.Millisecond) 2785 if sa2.numInboundGateways() == 0 { 2786 sb2.Shutdown() 2787 sb2 = nil 2788 } else { 2789 break 2790 } 2791 } 2792 if doLog { 2793 sb2.SetLogger(logger.NewTestLogger("[B2] - ", true), true, true) 2794 } 2795 2796 ch := make(chan bool, 1) 2797 cb := func(_ *nats.Msg) { 2798 ch <- true 2799 } 2800 2801 // Create a subscription on sa1 and sa2. 2802 ncsa1 := natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", oa1.Port)) 2803 defer ncsa1.Close() 2804 sub1 := natsSub(t, ncsa1, "foo", cb) 2805 natsFlush(t, ncsa1) 2806 2807 ncsa2 := natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", oa2.Port)) 2808 defer ncsa2.Close() 2809 sub2 := natsSub(t, ncsa2, "foo", cb) 2810 natsFlush(t, ncsa2) 2811 2812 // sa1 will have 1 local, one remote (from sa2), same for sa2. 2813 checkExpectedSubs(t, 2, sa1, sa2) 2814 2815 // Connect to sb2 and send 1 message 2816 ncsb2 := natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", ob2.Port)) 2817 defer ncsb2.Close() 2818 natsPub(t, ncsb2, "foo", []byte("hello")) 2819 natsFlush(t, ncsb2) 2820 2821 for i := 0; i < 2; i++ { 2822 waitCh(t, ch, "Did not get our message") 2823 } 2824 2825 // Unsubscribe sub2, and send 1, should still get it. 2826 natsUnsub(t, sub2) 2827 natsFlush(t, ncsa2) 2828 natsPub(t, ncsb2, "foo", []byte("hello")) 2829 natsFlush(t, ncsb2) 2830 waitCh(t, ch, "Did not get our message") 2831 2832 // Unsubscribe sub1, all server's sublist should be empty 2833 sub1.Unsubscribe() 2834 natsFlush(t, ncsa1) 2835 2836 checkExpectedSubs(t, 0, sa1, sa2, sb1, sb2) 2837 2838 // Create queue subs 2839 total := 100 2840 c1 := int32(0) 2841 c2 := int32(0) 2842 c3 := int32(0) 2843 tc := int32(0) 2844 natsQueueSub(t, ncsa1, "foo", "bar", func(_ *nats.Msg) { 2845 atomic.AddInt32(&c1, 1) 2846 if c := atomic.AddInt32(&tc, 1); int(c) == total { 2847 ch <- true 2848 } 2849 }) 2850 natsFlush(t, ncsa1) 2851 natsQueueSub(t, ncsa2, "foo", "bar", func(_ *nats.Msg) { 2852 atomic.AddInt32(&c2, 1) 2853 if c := atomic.AddInt32(&tc, 1); int(c) == total { 2854 ch <- true 2855 } 2856 }) 2857 natsFlush(t, ncsa2) 2858 checkExpectedSubs(t, 2, sa1, sa2) 2859 2860 qsubOnB2 := natsQueueSub(t, ncsb2, "foo", "bar", func(_ *nats.Msg) { 2861 atomic.AddInt32(&c3, 1) 2862 if c := atomic.AddInt32(&tc, 1); int(c) == total { 2863 ch <- true 2864 } 2865 }) 2866 natsFlush(t, ncsb2) 2867 checkExpectedSubs(t, 1, sb2) 2868 2869 checkForRegisteredQSubInterest(t, sb1, "A", globalAccountName, "foo", 1, time.Second) 2870 2871 // Publish all messages. The queue sub on cluster B should receive all 2872 // messages. 2873 for i := 0; i < total; i++ { 2874 natsPub(t, ncsb2, "foo", []byte("msg")) 2875 } 2876 natsFlush(t, ncsb2) 2877 2878 waitCh(t, ch, "Did not get all our queue messages") 2879 if n := int(atomic.LoadInt32(&c1)); n != 0 { 2880 t.Fatalf("No message should have been received by qsub1, got %v", n) 2881 } 2882 if n := int(atomic.LoadInt32(&c2)); n != 0 { 2883 t.Fatalf("No message should have been received by qsub2, got %v", n) 2884 } 2885 if n := int(atomic.LoadInt32(&c3)); n != total { 2886 t.Fatalf("All messages should have been delivered to qsub on B, got %v", n) 2887 } 2888 2889 // Reset counters 2890 atomic.StoreInt32(&c1, 0) 2891 atomic.StoreInt32(&c2, 0) 2892 atomic.StoreInt32(&c3, 0) 2893 atomic.StoreInt32(&tc, 0) 2894 2895 // Now send from cluster A, messages should be distributed to qsubs on A. 2896 for i := 0; i < total; i++ { 2897 natsPub(t, ncsa1, "foo", []byte("msg")) 2898 } 2899 natsFlush(t, ncsa1) 2900 2901 expectedLow := int(float32(total/2) * 0.6) 2902 expectedHigh := int(float32(total/2) * 1.4) 2903 checkCount := func(t *testing.T, count *int32) { 2904 t.Helper() 2905 c := int(atomic.LoadInt32(count)) 2906 if c < expectedLow || c > expectedHigh { 2907 t.Fatalf("Expected value to be between %v/%v, got %v", expectedLow, expectedHigh, c) 2908 } 2909 } 2910 waitCh(t, ch, "Did not get all our queue messages") 2911 checkCount(t, &c1) 2912 checkCount(t, &c2) 2913 2914 // Now unsubscribe sub on B and reset counters 2915 natsUnsub(t, qsubOnB2) 2916 checkExpectedSubs(t, 0, sb2) 2917 atomic.StoreInt32(&c1, 0) 2918 atomic.StoreInt32(&c2, 0) 2919 atomic.StoreInt32(&c3, 0) 2920 atomic.StoreInt32(&tc, 0) 2921 // Publish from cluster B, messages should be delivered to cluster A. 2922 for i := 0; i < total; i++ { 2923 natsPub(t, ncsb2, "foo", []byte("msg")) 2924 } 2925 natsFlush(t, ncsb2) 2926 2927 waitCh(t, ch, "Did not get all our queue messages") 2928 if n := int(atomic.LoadInt32(&c3)); n != 0 { 2929 t.Fatalf("There should not have been messages on unsubscribed sub, got %v", n) 2930 } 2931 checkCount(t, &c1) 2932 checkCount(t, &c2) 2933 } 2934 2935 func TestGatewayMsgSentOnlyOnce(t *testing.T) { 2936 o2 := testDefaultOptionsForGateway("B") 2937 s2 := runGatewayServer(o2) 2938 defer s2.Shutdown() 2939 2940 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 2941 s1 := runGatewayServer(o1) 2942 defer s1.Shutdown() 2943 2944 waitForOutboundGateways(t, s1, 1, time.Second) 2945 waitForOutboundGateways(t, s2, 1, time.Second) 2946 2947 s2Url := fmt.Sprintf("nats://127.0.0.1:%d", o2.Port) 2948 nc2 := natsConnect(t, s2Url) 2949 defer nc2.Close() 2950 2951 s1Url := fmt.Sprintf("nats://127.0.0.1:%d", o1.Port) 2952 nc1 := natsConnect(t, s1Url) 2953 defer nc1.Close() 2954 2955 ch := make(chan bool, 1) 2956 count := int32(0) 2957 expected := int32(4) 2958 cb := func(_ *nats.Msg) { 2959 if c := atomic.AddInt32(&count, 1); c == expected { 2960 ch <- true 2961 } 2962 } 2963 2964 // On s1, create 2 plain subs, 2 queue members for group 2965 // "bar" and 1 for group "baz". 2966 natsSub(t, nc1, ">", cb) 2967 natsSub(t, nc1, "foo", cb) 2968 natsQueueSub(t, nc1, "foo", "bar", cb) 2969 natsQueueSub(t, nc1, "foo", "bar", cb) 2970 natsQueueSub(t, nc1, "foo", "baz", cb) 2971 natsFlush(t, nc1) 2972 2973 // Ensure subs registered in S1 2974 checkExpectedSubs(t, 5, s1) 2975 2976 // Also need to wait for qsubs to be registered on s2. 2977 checkForRegisteredQSubInterest(t, s2, "A", globalAccountName, "foo", 2, time.Second) 2978 2979 // From s2, send 1 message, s1 should receive 1 only, 2980 // and total we should get the callback notified 4 times. 2981 natsPub(t, nc2, "foo", []byte("hello")) 2982 natsFlush(t, nc2) 2983 2984 waitCh(t, ch, "Did not get our messages") 2985 // Verifiy that count is still 4 2986 if c := atomic.LoadInt32(&count); c != expected { 2987 t.Fatalf("Expected %v messages, got %v", expected, c) 2988 } 2989 // Check s2 outbound connection stats. It should say that it 2990 // sent only 1 message. 2991 c := s2.getOutboundGatewayConnection("A") 2992 if c == nil { 2993 t.Fatalf("S2 outbound gateway not found") 2994 } 2995 c.mu.Lock() 2996 out := c.outMsgs 2997 c.mu.Unlock() 2998 if out != 1 { 2999 t.Fatalf("Expected s2's outbound gateway to have sent a single message, got %v", out) 3000 } 3001 // Now check s1's inbound gateway 3002 s1.gateway.RLock() 3003 c = nil 3004 for _, ci := range s1.gateway.in { 3005 c = ci 3006 break 3007 } 3008 s1.gateway.RUnlock() 3009 if c == nil { 3010 t.Fatalf("S1 inbound gateway not found") 3011 } 3012 if in := atomic.LoadInt64(&c.inMsgs); in != 1 { 3013 t.Fatalf("Expected s1's inbound gateway to have received a single message, got %v", in) 3014 } 3015 } 3016 3017 type checkErrorLogger struct { 3018 DummyLogger 3019 checkErrorStr string 3020 gotError bool 3021 } 3022 3023 func (l *checkErrorLogger) Errorf(format string, args ...interface{}) { 3024 l.DummyLogger.Errorf(format, args...) 3025 l.Lock() 3026 if strings.Contains(l.Msg, l.checkErrorStr) { 3027 l.gotError = true 3028 } 3029 l.Unlock() 3030 } 3031 3032 func TestGatewayRoutedServerWithoutGatewayConfigured(t *testing.T) { 3033 o2 := testDefaultOptionsForGateway("B") 3034 s2 := runGatewayServer(o2) 3035 defer s2.Shutdown() 3036 3037 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 3038 s1 := runGatewayServer(o1) 3039 defer s1.Shutdown() 3040 3041 waitForOutboundGateways(t, s1, 1, time.Second) 3042 waitForOutboundGateways(t, s2, 1, time.Second) 3043 3044 o3 := DefaultOptions() 3045 o3.NoSystemAccount = true 3046 o3.Cluster.Name = "B" 3047 o3.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", s2.ClusterAddr().Port)) 3048 s3 := New(o3) 3049 defer s3.Shutdown() 3050 l := &checkErrorLogger{checkErrorStr: "not configured"} 3051 s3.SetLogger(l, true, true) 3052 wg := sync.WaitGroup{} 3053 wg.Add(1) 3054 go func() { 3055 s3.Start() 3056 wg.Done() 3057 }() 3058 3059 checkClusterFormed(t, s2, s3) 3060 3061 // Check that server s3 does not panic when being notified 3062 // about the A gateway, but report an error. 3063 deadline := time.Now().Add(2 * time.Second) 3064 gotIt := false 3065 for time.Now().Before(deadline) { 3066 l.Lock() 3067 gotIt = l.gotError 3068 l.Unlock() 3069 if gotIt { 3070 break 3071 } 3072 time.Sleep(15 * time.Millisecond) 3073 } 3074 if !gotIt { 3075 t.Fatalf("Should have reported error about gateway not configured") 3076 } 3077 3078 s3.Shutdown() 3079 wg.Wait() 3080 } 3081 3082 func TestGatewaySendsToNonLocalSubs(t *testing.T) { 3083 ob1 := testDefaultOptionsForGateway("B") 3084 sb1 := runGatewayServer(ob1) 3085 defer sb1.Shutdown() 3086 3087 oa1 := testGatewayOptionsFromToWithServers(t, "A", "B", sb1) 3088 sa1 := runGatewayServer(oa1) 3089 defer sa1.Shutdown() 3090 3091 waitForOutboundGateways(t, sa1, 1, time.Second) 3092 waitForOutboundGateways(t, sb1, 1, time.Second) 3093 3094 waitForInboundGateways(t, sa1, 1, time.Second) 3095 waitForInboundGateways(t, sb1, 1, time.Second) 3096 3097 oa2 := testGatewayOptionsFromToWithServers(t, "A", "B", sb1) 3098 oa2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", sa1.ClusterAddr().Port)) 3099 sa2 := runGatewayServer(oa2) 3100 defer sa2.Shutdown() 3101 3102 checkClusterFormed(t, sa1, sa2) 3103 3104 waitForOutboundGateways(t, sa2, 1, time.Second) 3105 waitForInboundGateways(t, sb1, 2, time.Second) 3106 3107 ch := make(chan bool, 1) 3108 // Create an interest of sa2 3109 ncSub := natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", oa2.Port)) 3110 defer ncSub.Close() 3111 natsSub(t, ncSub, "foo", func(_ *nats.Msg) { ch <- true }) 3112 natsFlush(t, ncSub) 3113 checkExpectedSubs(t, 1, sa1, sa2) 3114 3115 // Produce a message from sb1, make sure it can be received. 3116 ncPub := natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", ob1.Port)) 3117 defer ncPub.Close() 3118 natsPub(t, ncPub, "foo", []byte("hello")) 3119 waitCh(t, ch, "Did not get our message") 3120 3121 ncSub.Close() 3122 ncPub.Close() 3123 checkExpectedSubs(t, 0, sa1, sa2) 3124 3125 // Now create sb2 that has a route to sb1 and gateway connects to sa2. 3126 ob2 := testGatewayOptionsFromToWithServers(t, "B", "A", sa2) 3127 ob2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", sb1.ClusterAddr().Port)) 3128 sb2 := runGatewayServer(ob2) 3129 defer sb2.Shutdown() 3130 3131 checkClusterFormed(t, sb1, sb2) 3132 waitForOutboundGateways(t, sb2, 1, time.Second) 3133 3134 ncSub = natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", oa1.Port)) 3135 defer ncSub.Close() 3136 natsSub(t, ncSub, "foo", func(_ *nats.Msg) { ch <- true }) 3137 natsFlush(t, ncSub) 3138 checkExpectedSubs(t, 1, sa1, sa2) 3139 3140 ncPub = natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", ob2.Port)) 3141 defer ncPub.Close() 3142 natsPub(t, ncPub, "foo", []byte("hello")) 3143 waitCh(t, ch, "Did not get our message") 3144 } 3145 3146 func TestGatewayUnknownGatewayCommand(t *testing.T) { 3147 o1 := testDefaultOptionsForGateway("A") 3148 s1 := runGatewayServer(o1) 3149 defer s1.Shutdown() 3150 3151 l := &checkErrorLogger{checkErrorStr: "Unknown command"} 3152 s1.SetLogger(l, true, true) 3153 3154 o2 := testDefaultOptionsForGateway("A") 3155 o2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", s1.ClusterAddr().Port)) 3156 s2 := runGatewayServer(o2) 3157 defer s2.Shutdown() 3158 3159 checkClusterFormed(t, s1, s2) 3160 3161 var route *client 3162 s2.mu.Lock() 3163 if r := getFirstRoute(s2); r != nil { 3164 route = r 3165 } 3166 s2.mu.Unlock() 3167 3168 route.mu.Lock() 3169 info := &Info{ 3170 Gateway: "B", 3171 GatewayCmd: 255, 3172 } 3173 b, _ := json.Marshal(info) 3174 route.enqueueProto([]byte(fmt.Sprintf(InfoProto, b))) 3175 route.mu.Unlock() 3176 3177 checkFor(t, time.Second, 15*time.Millisecond, func() error { 3178 l.Lock() 3179 gotIt := l.gotError 3180 l.Unlock() 3181 if gotIt { 3182 return nil 3183 } 3184 return fmt.Errorf("Did not get expected error") 3185 }) 3186 } 3187 3188 func TestGatewayRandomIP(t *testing.T) { 3189 ob := testDefaultOptionsForGateway("B") 3190 sb := runGatewayServer(ob) 3191 defer sb.Shutdown() 3192 3193 oa := testGatewayOptionsFromToWithURLs(t, "A", "B", 3194 []string{ 3195 "nats://noport", 3196 fmt.Sprintf("nats://localhost:%d", sb.GatewayAddr().Port), 3197 }) 3198 // Create a dummy resolver that returns error since we 3199 // don't provide any IP. The code should then use the configured 3200 // url (localhost:port) and try with that, which in this case 3201 // should work. 3202 oa.Gateway.resolver = &myDummyDNSResolver{} 3203 sa := runGatewayServer(oa) 3204 defer sa.Shutdown() 3205 3206 waitForOutboundGateways(t, sa, 1, 2*time.Second) 3207 waitForOutboundGateways(t, sb, 1, 2*time.Second) 3208 } 3209 3210 func TestGatewaySendQSubsBufSize(t *testing.T) { 3211 for _, test := range []struct { 3212 name string 3213 bufSize int 3214 }{ 3215 { 3216 name: "Bufsize 45, more than one at a time", 3217 bufSize: 45, 3218 }, 3219 { 3220 name: "Bufsize 15, one at a time", 3221 bufSize: 15, 3222 }, 3223 { 3224 name: "Bufsize 0, default to maxBufSize, all at once", 3225 bufSize: 0, 3226 }, 3227 } { 3228 t.Run(test.name, func(t *testing.T) { 3229 3230 o2 := testDefaultOptionsForGateway("B") 3231 o2.Gateway.sendQSubsBufSize = test.bufSize 3232 s2 := runGatewayServer(o2) 3233 defer s2.Shutdown() 3234 3235 s2Url := fmt.Sprintf("nats://%s:%d", o2.Host, o2.Port) 3236 nc := natsConnect(t, s2Url) 3237 defer nc.Close() 3238 natsQueueSub(t, nc, "foo", "bar", func(_ *nats.Msg) {}) 3239 natsQueueSub(t, nc, "foo", "baz", func(_ *nats.Msg) {}) 3240 natsQueueSub(t, nc, "foo", "bat", func(_ *nats.Msg) {}) 3241 natsQueueSub(t, nc, "foo", "bax", func(_ *nats.Msg) {}) 3242 3243 checkExpectedSubs(t, 4, s2) 3244 3245 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 3246 s1 := runGatewayServer(o1) 3247 defer s1.Shutdown() 3248 3249 waitForOutboundGateways(t, s1, 1, time.Second) 3250 waitForOutboundGateways(t, s2, 1, time.Second) 3251 3252 checkForRegisteredQSubInterest(t, s1, "B", globalAccountName, "foo", 4, time.Second) 3253 3254 // Make sure we have the 4 we expected 3255 c := s1.getOutboundGatewayConnection("B") 3256 ei, _ := c.gw.outsim.Load(globalAccountName) 3257 if ei == nil { 3258 t.Fatalf("No interest found") 3259 } 3260 sl := ei.(*outsie).sl 3261 r := sl.Match("foo") 3262 if len(r.qsubs) != 4 { 3263 t.Fatalf("Expected 4 groups, got %v", len(r.qsubs)) 3264 } 3265 var gotBar, gotBaz, gotBat, gotBax bool 3266 for _, qs := range r.qsubs { 3267 if len(qs) != 1 { 3268 t.Fatalf("Unexpected number of subs for group %s: %v", qs[0].queue, len(qs)) 3269 } 3270 q := qs[0].queue 3271 switch string(q) { 3272 case "bar": 3273 gotBar = true 3274 case "baz": 3275 gotBaz = true 3276 case "bat": 3277 gotBat = true 3278 case "bax": 3279 gotBax = true 3280 default: 3281 t.Fatalf("Unexpected group name: %s", q) 3282 } 3283 } 3284 if !gotBar || !gotBaz || !gotBat || !gotBax { 3285 t.Fatalf("Did not get all we wanted: bar=%v baz=%v bat=%v bax=%v", 3286 gotBar, gotBaz, gotBat, gotBax) 3287 } 3288 3289 nc.Close() 3290 s1.Shutdown() 3291 s2.Shutdown() 3292 3293 waitForOutboundGateways(t, s1, 0, time.Second) 3294 waitForOutboundGateways(t, s2, 0, time.Second) 3295 }) 3296 } 3297 } 3298 3299 func TestGatewayRaceBetweenPubAndSub(t *testing.T) { 3300 o2 := testDefaultOptionsForGateway("B") 3301 s2 := runGatewayServer(o2) 3302 defer s2.Shutdown() 3303 3304 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 3305 s1 := runGatewayServer(o1) 3306 defer s1.Shutdown() 3307 3308 waitForOutboundGateways(t, s1, 1, time.Second) 3309 waitForOutboundGateways(t, s2, 1, time.Second) 3310 3311 s2Url := fmt.Sprintf("nats://127.0.0.1:%d", o2.Port) 3312 nc2 := natsConnect(t, s2Url) 3313 defer nc2.Close() 3314 3315 s1Url := fmt.Sprintf("nats://127.0.0.1:%d", o1.Port) 3316 var ncaa [5]*nats.Conn 3317 var nca = ncaa[:0] 3318 for i := 0; i < 5; i++ { 3319 nc := natsConnect(t, s1Url) 3320 defer nc.Close() 3321 nca = append(nca, nc) 3322 } 3323 3324 ch := make(chan bool, 1) 3325 wg := sync.WaitGroup{} 3326 wg.Add(5) 3327 for _, nc := range nca { 3328 nc := nc 3329 go func(n *nats.Conn) { 3330 defer wg.Done() 3331 for { 3332 n.Publish("foo", []byte("hello")) 3333 select { 3334 case <-ch: 3335 return 3336 default: 3337 } 3338 } 3339 }(nc) 3340 } 3341 time.Sleep(100 * time.Millisecond) 3342 natsQueueSub(t, nc2, "foo", "bar", func(m *nats.Msg) { 3343 natsUnsub(t, m.Sub) 3344 close(ch) 3345 }) 3346 wg.Wait() 3347 } 3348 3349 // Returns the first (if any) of the inbound connections for this name. 3350 func getInboundGatewayConnection(s *Server, name string) *client { 3351 var gwsa [4]*client 3352 var gws = gwsa[:0] 3353 s.getInboundGatewayConnections(&gws) 3354 if len(gws) > 0 { 3355 return gws[0] 3356 } 3357 return nil 3358 } 3359 3360 func TestGatewaySendAllSubs(t *testing.T) { 3361 GatewayDoNotForceInterestOnlyMode(true) 3362 defer GatewayDoNotForceInterestOnlyMode(false) 3363 3364 gatewayMaxRUnsubBeforeSwitch = 100 3365 defer func() { gatewayMaxRUnsubBeforeSwitch = defaultGatewayMaxRUnsubBeforeSwitch }() 3366 3367 ob := testDefaultOptionsForGateway("B") 3368 sb := runGatewayServer(ob) 3369 defer sb.Shutdown() 3370 3371 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 3372 sa := runGatewayServer(oa) 3373 defer sa.Shutdown() 3374 3375 oc := testGatewayOptionsFromToWithServers(t, "C", "B", sb) 3376 sc := runGatewayServer(oc) 3377 defer sc.Shutdown() 3378 3379 waitForOutboundGateways(t, sa, 2, time.Second) 3380 waitForOutboundGateways(t, sb, 2, time.Second) 3381 waitForOutboundGateways(t, sc, 2, time.Second) 3382 waitForInboundGateways(t, sa, 2, time.Second) 3383 waitForInboundGateways(t, sb, 2, time.Second) 3384 waitForInboundGateways(t, sc, 2, time.Second) 3385 3386 // On A, create a sub to register some interest 3387 aURL := fmt.Sprintf("nats://%s:%d", oa.Host, oa.Port) 3388 ncA := natsConnect(t, aURL) 3389 defer ncA.Close() 3390 natsSub(t, ncA, "sub.on.a.*", func(m *nats.Msg) {}) 3391 natsFlush(t, ncA) 3392 checkExpectedSubs(t, 1, sa) 3393 3394 // On C, have some sub activity while it receives 3395 // unwanted messages and switches to interestOnly mode. 3396 cURL := fmt.Sprintf("nats://%s:%d", oc.Host, oc.Port) 3397 ncC := natsConnect(t, cURL) 3398 defer ncC.Close() 3399 wg := sync.WaitGroup{} 3400 wg.Add(2) 3401 done := make(chan bool) 3402 consCount := 0 3403 accsCount := 0 3404 go func() { 3405 defer wg.Done() 3406 for i := 0; ; i++ { 3407 // Create subs and qsubs on same subject 3408 natsSub(t, ncC, fmt.Sprintf("foo.%d", i+1), func(_ *nats.Msg) {}) 3409 natsQueueSub(t, ncC, fmt.Sprintf("foo.%d", i+1), fmt.Sprintf("bar.%d", i+1), func(_ *nats.Msg) {}) 3410 // Create psubs and qsubs on unique subjects 3411 natsSub(t, ncC, fmt.Sprintf("foox.%d", i+1), func(_ *nats.Msg) {}) 3412 natsQueueSub(t, ncC, fmt.Sprintf("fooy.%d", i+1), fmt.Sprintf("bar.%d", i+1), func(_ *nats.Msg) {}) 3413 consCount += 4 3414 // Register account 3415 sc.RegisterAccount(fmt.Sprintf("acc.%d", i+1)) 3416 accsCount++ 3417 select { 3418 case <-done: 3419 return 3420 case <-time.After(15 * time.Millisecond): 3421 } 3422 } 3423 }() 3424 3425 // From B publish on subjects for which C has an interest 3426 bURL := fmt.Sprintf("nats://%s:%d", ob.Host, ob.Port) 3427 ncB := natsConnect(t, bURL) 3428 defer ncB.Close() 3429 3430 go func() { 3431 defer wg.Done() 3432 time.Sleep(10 * time.Millisecond) 3433 for { 3434 for i := 0; i < 10; i++ { 3435 natsPub(t, ncB, fmt.Sprintf("foo.%d", i+1), []byte("hello")) 3436 } 3437 select { 3438 case <-done: 3439 return 3440 case <-time.After(5 * time.Millisecond): 3441 } 3442 } 3443 }() 3444 3445 // From B, send a lot of messages that A is interested in, 3446 // but not C. 3447 // TODO(ik): May need to change that if we change the threshold 3448 // for when the switch happens. 3449 total := 300 3450 for i := 0; i < total; i++ { 3451 if err := ncB.Publish(fmt.Sprintf("sub.on.a.%d", i), []byte("hi")); err != nil { 3452 t.Fatalf("Error waiting for reply: %v", err) 3453 } 3454 } 3455 close(done) 3456 3457 // Normally, C would receive a message for each req inbox and 3458 // would send and RS- on that to B, making both have an unbounded 3459 // growth of the no-interest map. But after a certain amount 3460 // of RS-, C will send all its sub for the given account and 3461 // instruct B to send only if there is explicit interest. 3462 checkFor(t, 2*time.Second, 50*time.Millisecond, func() error { 3463 // Check C inbound connection from B 3464 c := getInboundGatewayConnection(sc, "B") 3465 c.mu.Lock() 3466 var switchedMode bool 3467 e := c.gw.insim[globalAccountName] 3468 if e != nil { 3469 switchedMode = e.ni == nil && e.mode == InterestOnly 3470 } 3471 c.mu.Unlock() 3472 if !switchedMode { 3473 return fmt.Errorf("C has still not switched mode") 3474 } 3475 return nil 3476 }) 3477 checkGWInterestOnlyMode(t, sb, "C", globalAccountName) 3478 wg.Wait() 3479 3480 // Check consCount and accsCount on C 3481 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 3482 sc.gateway.pasi.Lock() 3483 scount := len(sc.gateway.pasi.m[globalAccountName]) 3484 sc.gateway.pasi.Unlock() 3485 if scount != consCount { 3486 return fmt.Errorf("Expected %v consumers for global account, got %v", consCount, scount) 3487 } 3488 acount := sc.numAccounts() 3489 if acount != accsCount+1 { 3490 return fmt.Errorf("Expected %v accounts, got %v", accsCount+1, acount) 3491 } 3492 return nil 3493 }) 3494 3495 // Also, after all that, if a sub is created on C, it should 3496 // be sent to B (but not A). Check that this is the case. 3497 // So first send from A on the subject that we are going to 3498 // use for this new sub. 3499 natsPub(t, ncA, "newsub", []byte("hello")) 3500 natsFlush(t, ncA) 3501 aOutboundToC := sa.getOutboundGatewayConnection("C") 3502 checkForSubjectNoInterest(t, aOutboundToC, globalAccountName, "newsub", true, 2*time.Second) 3503 3504 newSubSub := natsSub(t, ncC, "newsub", func(_ *nats.Msg) {}) 3505 natsFlush(t, ncC) 3506 checkExpectedSubs(t, consCount+1) 3507 checkFor(t, time.Second, 15*time.Millisecond, func() error { 3508 c := sb.getOutboundGatewayConnection("C") 3509 ei, _ := c.gw.outsim.Load(globalAccountName) 3510 if ei != nil { 3511 sl := ei.(*outsie).sl 3512 r := sl.Match("newsub") 3513 if len(r.psubs) == 1 { 3514 return nil 3515 } 3516 } 3517 return fmt.Errorf("Newsub not registered on B") 3518 }) 3519 checkForSubjectNoInterest(t, aOutboundToC, globalAccountName, "newsub", false, 2*time.Second) 3520 3521 natsUnsub(t, newSubSub) 3522 natsFlush(t, ncC) 3523 checkExpectedSubs(t, consCount) 3524 checkFor(t, time.Second, 15*time.Millisecond, func() error { 3525 c := sb.getOutboundGatewayConnection("C") 3526 ei, _ := c.gw.outsim.Load(globalAccountName) 3527 if ei != nil { 3528 sl := ei.(*outsie).sl 3529 r := sl.Match("newsub") 3530 if len(r.psubs) == 0 { 3531 return nil 3532 } 3533 } 3534 return fmt.Errorf("Newsub still registered on B") 3535 }) 3536 } 3537 3538 func TestGatewaySendAllSubsBadProtocol(t *testing.T) { 3539 ob := testDefaultOptionsForGateway("B") 3540 sb := runGatewayServer(ob) 3541 defer sb.Shutdown() 3542 3543 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 3544 sa := runGatewayServer(oa) 3545 defer sa.Shutdown() 3546 3547 waitForOutboundGateways(t, sa, 1, time.Second) 3548 waitForOutboundGateways(t, sb, 1, time.Second) 3549 waitForInboundGateways(t, sa, 1, time.Second) 3550 waitForInboundGateways(t, sb, 1, time.Second) 3551 3552 // For this test, make sure to use inbound from A so 3553 // A will reconnect when we send bad proto that 3554 // causes connection to be closed. 3555 c := getInboundGatewayConnection(sa, "A") 3556 // Mock an invalid protocol (account name missing) 3557 info := &Info{ 3558 Gateway: "B", 3559 GatewayCmd: gatewayCmdAllSubsStart, 3560 } 3561 b, _ := json.Marshal(info) 3562 c.mu.Lock() 3563 c.enqueueProto([]byte(fmt.Sprintf("INFO %s\r\n", b))) 3564 c.mu.Unlock() 3565 3566 orgConn := c 3567 checkFor(t, 3*time.Second, 100*time.Millisecond, func() error { 3568 curConn := getInboundGatewayConnection(sa, "A") 3569 if orgConn == curConn { 3570 return fmt.Errorf("Not reconnected") 3571 } 3572 return nil 3573 }) 3574 3575 waitForOutboundGateways(t, sa, 1, 2*time.Second) 3576 waitForOutboundGateways(t, sb, 1, 2*time.Second) 3577 3578 // Refresh 3579 c = nil 3580 checkFor(t, 3*time.Second, 15*time.Millisecond, func() error { 3581 c = getInboundGatewayConnection(sa, "A") 3582 if c == nil { 3583 return fmt.Errorf("Did not reconnect") 3584 } 3585 return nil 3586 }) 3587 // Do correct start 3588 info.GatewayCmdPayload = []byte(globalAccountName) 3589 b, _ = json.Marshal(info) 3590 c.mu.Lock() 3591 c.enqueueProto([]byte(fmt.Sprintf("INFO %s\r\n", b))) 3592 c.mu.Unlock() 3593 // But incorrect end. 3594 info.GatewayCmd = gatewayCmdAllSubsComplete 3595 info.GatewayCmdPayload = nil 3596 b, _ = json.Marshal(info) 3597 c.mu.Lock() 3598 c.enqueueProto([]byte(fmt.Sprintf("INFO %s\r\n", b))) 3599 c.mu.Unlock() 3600 3601 orgConn = c 3602 checkFor(t, 3*time.Second, 100*time.Millisecond, func() error { 3603 curConn := getInboundGatewayConnection(sa, "A") 3604 if orgConn == curConn { 3605 return fmt.Errorf("Not reconnected") 3606 } 3607 return nil 3608 }) 3609 } 3610 3611 func TestGatewayRaceOnClose(t *testing.T) { 3612 ob := testDefaultOptionsForGateway("B") 3613 sb := runGatewayServer(ob) 3614 defer sb.Shutdown() 3615 3616 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 3617 sa := runGatewayServer(oa) 3618 defer sa.Shutdown() 3619 3620 waitForOutboundGateways(t, sa, 1, time.Second) 3621 waitForOutboundGateways(t, sb, 1, time.Second) 3622 waitForInboundGateways(t, sa, 1, time.Second) 3623 waitForInboundGateways(t, sb, 1, time.Second) 3624 3625 bURL := fmt.Sprintf("nats://%s:%d", ob.Host, ob.Port) 3626 ncB := natsConnect(t, bURL, nats.NoReconnect()) 3627 defer ncB.Close() 3628 3629 wg := sync.WaitGroup{} 3630 wg.Add(1) 3631 go func() { 3632 defer wg.Done() 3633 cb := func(_ *nats.Msg) {} 3634 for { 3635 // Expect failure at one point and just return. 3636 qsub, err := ncB.QueueSubscribe("foo", "bar", cb) 3637 if err != nil { 3638 return 3639 } 3640 if err := qsub.Unsubscribe(); err != nil { 3641 return 3642 } 3643 } 3644 }() 3645 // Wait a bit and kill B 3646 time.Sleep(200 * time.Millisecond) 3647 sb.Shutdown() 3648 wg.Wait() 3649 } 3650 3651 // Similar to TestNewRoutesServiceImport but with 2 GW servers instead 3652 // of a cluster of 2 servers. 3653 func TestGatewayServiceImport(t *testing.T) { 3654 GatewayDoNotForceInterestOnlyMode(true) 3655 defer GatewayDoNotForceInterestOnlyMode(false) 3656 3657 oa := testDefaultOptionsForGateway("A") 3658 setAccountUserPassInOptions(oa, "$foo", "clientA", "password") 3659 setAccountUserPassInOptions(oa, "$bar", "yyyyyyy", "password") 3660 sa := runGatewayServer(oa) 3661 defer sa.Shutdown() 3662 3663 ob := testGatewayOptionsFromToWithServers(t, "B", "A", sa) 3664 setAccountUserPassInOptions(ob, "$foo", "clientBFoo", "password") 3665 setAccountUserPassInOptions(ob, "$bar", "clientB", "password") 3666 sb := runGatewayServer(ob) 3667 defer sb.Shutdown() 3668 3669 waitForOutboundGateways(t, sa, 1, time.Second) 3670 waitForOutboundGateways(t, sb, 1, time.Second) 3671 waitForInboundGateways(t, sa, 1, time.Second) 3672 waitForInboundGateways(t, sb, 1, time.Second) 3673 3674 // Get accounts 3675 fooA, _ := sa.LookupAccount("$foo") 3676 barA, _ := sa.LookupAccount("$bar") 3677 fooB, _ := sb.LookupAccount("$foo") 3678 barB, _ := sb.LookupAccount("$bar") 3679 3680 // Add in the service export for the requests. Make it public. 3681 fooA.AddServiceExport("test.request", nil) 3682 fooB.AddServiceExport("test.request", nil) 3683 3684 // Add import abilities to server B's bar account from foo. 3685 if err := barB.AddServiceImport(fooB, "foo.request", "test.request"); err != nil { 3686 t.Fatalf("Error adding service import: %v", err) 3687 } 3688 // Same on A. 3689 if err := barA.AddServiceImport(fooA, "foo.request", "test.request"); err != nil { 3690 t.Fatalf("Error adding service import: %v", err) 3691 } 3692 3693 // clientA will be connected to srvA and be the service endpoint and responder. 3694 aURL := fmt.Sprintf("nats://clientA:password@127.0.0.1:%d", oa.Port) 3695 clientA := natsConnect(t, aURL) 3696 defer clientA.Close() 3697 3698 subA := natsSubSync(t, clientA, "test.request") 3699 natsFlush(t, clientA) 3700 3701 // Now setup client B on srvB who will do a sub from account $bar 3702 // that should map account $foo's foo subject. 3703 bURL := fmt.Sprintf("nats://clientB:password@127.0.0.1:%d", ob.Port) 3704 clientB := natsConnect(t, bURL) 3705 defer clientB.Close() 3706 3707 subB := natsSubSync(t, clientB, "reply") 3708 natsFlush(t, clientB) 3709 3710 for i := 1; i <= 2; i++ { 3711 // Send the request from clientB on foo.request, 3712 natsPubReq(t, clientB, "foo.request", "reply", []byte("hi")) 3713 natsFlush(t, clientB) 3714 3715 // Expect the request on A 3716 msg, err := subA.NextMsg(time.Second) 3717 if err != nil { 3718 t.Fatalf("subA failed to get request: %v", err) 3719 } 3720 if msg.Subject != "test.request" || string(msg.Data) != "hi" { 3721 t.Fatalf("Unexpected message: %v", msg) 3722 } 3723 if msg.Reply == "reply" { 3724 t.Fatalf("Expected randomized reply, but got original") 3725 } 3726 3727 // Check for duplicate message 3728 if msg, err := subA.NextMsg(250 * time.Millisecond); err != nats.ErrTimeout { 3729 t.Fatalf("Unexpected msg: %v", msg) 3730 } 3731 3732 // Send reply 3733 natsPub(t, clientA, msg.Reply, []byte("ok")) 3734 natsFlush(t, clientA) 3735 3736 msg, err = subB.NextMsg(time.Second) 3737 if err != nil { 3738 t.Fatalf("subB failed to get reply: %v", err) 3739 } 3740 if msg.Subject != "reply" || string(msg.Data) != "ok" { 3741 t.Fatalf("Unexpected message: %v", msg) 3742 } 3743 3744 // Check for duplicate message 3745 if msg, err := subB.NextMsg(250 * time.Millisecond); err != nats.ErrTimeout { 3746 t.Fatalf("Unexpected msg: %v", msg) 3747 } 3748 3749 expected := int64(i * 2) 3750 vz, _ := sa.Varz(nil) 3751 if vz.OutMsgs != expected { 3752 t.Fatalf("Expected %d outMsgs for A, got %v", expected, vz.OutMsgs) 3753 } 3754 3755 // For B, we expect it to send to gateway on the two subjects: test.request 3756 // and foo.request then send the reply to the client and optimistically 3757 // to the other gateway. 3758 if i == 1 { 3759 expected = 4 3760 } else { 3761 // The second time, one of the accounts will be suppressed and the reply going 3762 // back so we should only get 2 more messages. 3763 expected = 6 3764 } 3765 vz, _ = sb.Varz(nil) 3766 if vz.OutMsgs != expected { 3767 t.Fatalf("Expected %d outMsgs for B, got %v", expected, vz.OutMsgs) 3768 } 3769 } 3770 3771 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 3772 if ts := fooA.TotalSubs(); ts != 1 { 3773 return fmt.Errorf("Expected one sub to be left on fooA, but got %d", ts) 3774 } 3775 return nil 3776 }) 3777 3778 // Speed up exiration 3779 err := fooA.SetServiceExportResponseThreshold("test.request", 50*time.Millisecond) 3780 if err != nil { 3781 t.Fatalf("Error setting response threshold: %v", err) 3782 } 3783 3784 // Send 100 requests from clientB on foo.request, 3785 for i := 0; i < 100; i++ { 3786 natsPubReq(t, clientB, "foo.request", "reply", []byte("hi")) 3787 } 3788 natsFlush(t, clientB) 3789 3790 // Consume the requests, but don't reply to them... 3791 for i := 0; i < 100; i++ { 3792 if _, err := subA.NextMsg(time.Second); err != nil { 3793 t.Fatalf("subA did not receive request: %v", err) 3794 } 3795 } 3796 3797 // These reply subjects will be dangling off of $foo account on serverA. 3798 // Remove our service endpoint and wait for the dangling replies to go to zero. 3799 natsUnsub(t, subA) 3800 natsFlush(t, clientA) 3801 3802 checkFor(t, 2*time.Second, 10*time.Millisecond, func() error { 3803 if ts := fooA.TotalSubs(); ts != 0 { 3804 return fmt.Errorf("Number of subs is %d, should be zero", ts) 3805 } 3806 return nil 3807 }) 3808 3809 // Repeat similar test but without the small TTL and verify 3810 // that if B is shutdown, the dangling subs for replies are 3811 // cleared from the account sublist. 3812 err = fooA.SetServiceExportResponseThreshold("test.request", 10*time.Second) 3813 if err != nil { 3814 t.Fatalf("Error setting response threshold: %v", err) 3815 } 3816 3817 subA = natsSubSync(t, clientA, "test.request") 3818 natsFlush(t, clientA) 3819 3820 // Send 100 requests from clientB on foo.request, 3821 for i := 0; i < 100; i++ { 3822 natsPubReq(t, clientB, "foo.request", "reply", []byte("hi")) 3823 } 3824 natsFlush(t, clientB) 3825 3826 // Consume the requests, but don't reply to them... 3827 for i := 0; i < 100; i++ { 3828 if _, err := subA.NextMsg(time.Second); err != nil { 3829 t.Fatalf("subA did not receive request: %v", err) 3830 } 3831 } 3832 3833 // Shutdown B 3834 clientB.Close() 3835 sb.Shutdown() 3836 3837 // Close our last sub 3838 natsUnsub(t, subA) 3839 natsFlush(t, clientA) 3840 3841 // Verify that they are gone before the 10 sec TTL 3842 checkFor(t, 2*time.Second, 10*time.Millisecond, func() error { 3843 if ts := fooA.TotalSubs(); ts != 0 { 3844 return fmt.Errorf("Number of subs is %d, should be zero", ts) 3845 } 3846 return nil 3847 }) 3848 3849 // Check that this all work in interest-only mode 3850 sb = runGatewayServer(ob) 3851 defer sb.Shutdown() 3852 3853 fooB, _ = sb.LookupAccount("$foo") 3854 barB, _ = sb.LookupAccount("$bar") 3855 3856 // Add in the service export for the requests. Make it public. 3857 fooB.AddServiceExport("test.request", nil) 3858 // Add import abilities to server B's bar account from foo. 3859 if err := barB.AddServiceImport(fooB, "foo.request", "test.request"); err != nil { 3860 t.Fatalf("Error adding service import: %v", err) 3861 } 3862 3863 waitForOutboundGateways(t, sa, 1, 2*time.Second) 3864 waitForOutboundGateways(t, sb, 1, 2*time.Second) 3865 waitForInboundGateways(t, sa, 1, 2*time.Second) 3866 waitForInboundGateways(t, sb, 1, 2*time.Second) 3867 3868 // We need at least a subscription on A otherwise when publishing 3869 // to subjects with no interest we would simply get an A- 3870 natsSubSync(t, clientA, "not.used") 3871 3872 // Create a client on B that will use account $foo 3873 bURL = fmt.Sprintf("nats://clientBFoo:password@127.0.0.1:%d", ob.Port) 3874 clientB = natsConnect(t, bURL) 3875 defer clientB.Close() 3876 3877 // First flood with subjects that remote gw is not interested 3878 // so we switch to interest-only. 3879 for i := 0; i < 1100; i++ { 3880 natsPub(t, clientB, fmt.Sprintf("no.interest.%d", i), []byte("hello")) 3881 } 3882 natsFlush(t, clientB) 3883 3884 checkGWInterestOnlyMode(t, sb, "A", "$foo") 3885 3886 // Go back to clientB on $bar. 3887 clientB.Close() 3888 bURL = fmt.Sprintf("nats://clientB:password@127.0.0.1:%d", ob.Port) 3889 clientB = natsConnect(t, bURL) 3890 defer clientB.Close() 3891 3892 subA = natsSubSync(t, clientA, "test.request") 3893 natsFlush(t, clientA) 3894 3895 subB = natsSubSync(t, clientB, "reply") 3896 natsFlush(t, clientB) 3897 3898 // Sine it is interest-only, B should receive an interest 3899 // on $foo test.request 3900 checkGWInterestOnlyModeInterestOn(t, sb, "A", "$foo", "test.request") 3901 3902 // Send the request from clientB on foo.request, 3903 natsPubReq(t, clientB, "foo.request", "reply", []byte("hi")) 3904 natsFlush(t, clientB) 3905 3906 // Expect the request on A 3907 msg, err := subA.NextMsg(time.Second) 3908 if err != nil { 3909 t.Fatalf("subA failed to get request: %v", err) 3910 } 3911 if msg.Subject != "test.request" || string(msg.Data) != "hi" { 3912 t.Fatalf("Unexpected message: %v", msg) 3913 } 3914 if msg.Reply == "reply" { 3915 t.Fatalf("Expected randomized reply, but got original") 3916 } 3917 3918 // Check for duplicate message 3919 if msg, err := subA.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 3920 t.Fatalf("Unexpected msg: %v", msg) 3921 } 3922 3923 // Send reply 3924 natsPub(t, clientA, msg.Reply, []byte("ok")) 3925 natsFlush(t, clientA) 3926 3927 msg, err = subB.NextMsg(time.Second) 3928 if err != nil { 3929 t.Fatalf("subB failed to get reply: %v", err) 3930 } 3931 if msg.Subject != "reply" || string(msg.Data) != "ok" { 3932 t.Fatalf("Unexpected message: %v", msg) 3933 } 3934 3935 // Check for duplicate message 3936 if msg, err := subB.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 3937 t.Fatalf("Unexpected msg: %v", msg) 3938 } 3939 } 3940 3941 func TestGatewayServiceImportWithQueue(t *testing.T) { 3942 GatewayDoNotForceInterestOnlyMode(true) 3943 defer GatewayDoNotForceInterestOnlyMode(false) 3944 3945 oa := testDefaultOptionsForGateway("A") 3946 setAccountUserPassInOptions(oa, "$foo", "clientA", "password") 3947 setAccountUserPassInOptions(oa, "$bar", "yyyyyyy", "password") 3948 sa := runGatewayServer(oa) 3949 defer sa.Shutdown() 3950 3951 ob := testGatewayOptionsFromToWithServers(t, "B", "A", sa) 3952 setAccountUserPassInOptions(ob, "$foo", "clientBFoo", "password") 3953 setAccountUserPassInOptions(ob, "$bar", "clientB", "password") 3954 sb := runGatewayServer(ob) 3955 defer sb.Shutdown() 3956 3957 waitForOutboundGateways(t, sa, 1, time.Second) 3958 waitForOutboundGateways(t, sb, 1, time.Second) 3959 waitForInboundGateways(t, sa, 1, time.Second) 3960 waitForInboundGateways(t, sb, 1, time.Second) 3961 3962 // Get accounts 3963 fooA, _ := sa.LookupAccount("$foo") 3964 barA, _ := sa.LookupAccount("$bar") 3965 fooB, _ := sb.LookupAccount("$foo") 3966 barB, _ := sb.LookupAccount("$bar") 3967 3968 // Add in the service export for the requests. Make it public. 3969 fooA.AddServiceExport("test.request", nil) 3970 fooB.AddServiceExport("test.request", nil) 3971 3972 // Add import abilities to server B's bar account from foo. 3973 if err := barB.AddServiceImport(fooB, "foo.request", "test.request"); err != nil { 3974 t.Fatalf("Error adding service import: %v", err) 3975 } 3976 // Same on A. 3977 if err := barA.AddServiceImport(fooA, "foo.request", "test.request"); err != nil { 3978 t.Fatalf("Error adding service import: %v", err) 3979 } 3980 3981 // clientA will be connected to srvA and be the service endpoint and responder. 3982 aURL := fmt.Sprintf("nats://clientA:password@127.0.0.1:%d", oa.Port) 3983 clientA := natsConnect(t, aURL) 3984 defer clientA.Close() 3985 3986 subA := natsQueueSubSync(t, clientA, "test.request", "queue") 3987 natsFlush(t, clientA) 3988 3989 // Now setup client B on srvB who will do a sub from account $bar 3990 // that should map account $foo's foo subject. 3991 bURL := fmt.Sprintf("nats://clientB:password@127.0.0.1:%d", ob.Port) 3992 clientB := natsConnect(t, bURL) 3993 defer clientB.Close() 3994 3995 subB := natsQueueSubSync(t, clientB, "reply", "queue2") 3996 natsFlush(t, clientB) 3997 3998 // Wait for queue interest on test.request from A to be registered 3999 // on server B. 4000 checkForRegisteredQSubInterest(t, sb, "A", "$foo", "test.request", 1, time.Second) 4001 4002 for i := 0; i < 2; i++ { 4003 // Send the request from clientB on foo.request, 4004 natsPubReq(t, clientB, "foo.request", "reply", []byte("hi")) 4005 natsFlush(t, clientB) 4006 4007 // Expect the request on A 4008 msg, err := subA.NextMsg(time.Second) 4009 if err != nil { 4010 t.Fatalf("subA failed to get request: %v", err) 4011 } 4012 if msg.Subject != "test.request" || string(msg.Data) != "hi" { 4013 t.Fatalf("Unexpected message: %v", msg) 4014 } 4015 if msg.Reply == "reply" { 4016 t.Fatalf("Expected randomized reply, but got original") 4017 } 4018 // Check for duplicate message 4019 if msg, err := subA.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 4020 t.Fatalf("Unexpected msg: %v", msg) 4021 } 4022 4023 // Send reply 4024 natsPub(t, clientA, msg.Reply, []byte("ok")) 4025 natsFlush(t, clientA) 4026 4027 msg, err = subB.NextMsg(time.Second) 4028 if err != nil { 4029 t.Fatalf("subB failed to get reply: %v", err) 4030 } 4031 if msg.Subject != "reply" || string(msg.Data) != "ok" { 4032 t.Fatalf("Unexpected message: %v", msg) 4033 } 4034 // Check for duplicate message 4035 if msg, err := subB.NextMsg(250 * time.Millisecond); err != nats.ErrTimeout { 4036 t.Fatalf("Unexpected msg: %v", msg) 4037 } 4038 4039 expected := int64((i + 1) * 2) 4040 vz, _ := sa.Varz(nil) 4041 if vz.OutMsgs != expected { 4042 t.Fatalf("Expected %d outMsgs for A, got %v", expected, vz.OutMsgs) 4043 } 4044 4045 // For B, we expect it to send to gateway on the two subjects: test.request 4046 // and foo.request then send the reply to the client and optimistically 4047 // to the other gateway. 4048 if i == 0 { 4049 expected = 4 4050 } else { 4051 // The second time, one of the accounts will be suppressed and the reply going 4052 // back so we should get only 2 more messages. 4053 expected = 6 4054 } 4055 vz, _ = sb.Varz(nil) 4056 if vz.OutMsgs != expected { 4057 t.Fatalf("Expected %d outMsgs for B, got %v", expected, vz.OutMsgs) 4058 } 4059 } 4060 4061 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 4062 if ts := fooA.TotalSubs(); ts != 1 { 4063 return fmt.Errorf("Expected one sub to be left on fooA, but got %d", ts) 4064 } 4065 return nil 4066 }) 4067 4068 // Speed up exiration 4069 err := fooA.SetServiceExportResponseThreshold("test.request", 10*time.Millisecond) 4070 if err != nil { 4071 t.Fatalf("Error setting response threshold: %v", err) 4072 } 4073 4074 // Send 100 requests from clientB on foo.request, 4075 for i := 0; i < 100; i++ { 4076 natsPubReq(t, clientB, "foo.request", "reply", []byte("hi")) 4077 } 4078 natsFlush(t, clientB) 4079 4080 // Consume the requests, but don't reply to them... 4081 for i := 0; i < 100; i++ { 4082 if _, err := subA.NextMsg(time.Second); err != nil { 4083 t.Fatalf("subA did not receive request: %v", err) 4084 } 4085 } 4086 4087 // These reply subjects will be dangling off of $foo account on serverA. 4088 // Remove our service endpoint and wait for the dangling replies to go to zero. 4089 natsUnsub(t, subA) 4090 natsFlush(t, clientA) 4091 4092 checkFor(t, 2*time.Second, 10*time.Millisecond, func() error { 4093 if ts := fooA.TotalSubs(); ts != 0 { 4094 return fmt.Errorf("Number of subs is %d, should be zero", ts) 4095 } 4096 return nil 4097 }) 4098 checkForRegisteredQSubInterest(t, sb, "A", "$foo", "test.request", 0, time.Second) 4099 4100 // Repeat similar test but without the small TTL and verify 4101 // that if B is shutdown, the dangling subs for replies are 4102 // cleared from the account sublist. 4103 err = fooA.SetServiceExportResponseThreshold("test.request", 10*time.Second) 4104 if err != nil { 4105 t.Fatalf("Error setting response threshold: %v", err) 4106 } 4107 4108 subA = natsQueueSubSync(t, clientA, "test.request", "queue") 4109 natsFlush(t, clientA) 4110 checkForRegisteredQSubInterest(t, sb, "A", "$foo", "test.request", 1, time.Second) 4111 4112 // Send 100 requests from clientB on foo.request, 4113 for i := 0; i < 100; i++ { 4114 natsPubReq(t, clientB, "foo.request", "reply", []byte("hi")) 4115 } 4116 natsFlush(t, clientB) 4117 4118 // Consume the requests, but don't reply to them... 4119 for i := 0; i < 100; i++ { 4120 if _, err := subA.NextMsg(time.Second); err != nil { 4121 t.Fatalf("subA did not receive request %d: %v", i+1, err) 4122 } 4123 } 4124 4125 // Shutdown B 4126 clientB.Close() 4127 sb.Shutdown() 4128 4129 // Close our last sub 4130 natsUnsub(t, subA) 4131 natsFlush(t, clientA) 4132 4133 // Verify that they are gone before the 10 sec TTL 4134 checkFor(t, 2*time.Second, 10*time.Millisecond, func() error { 4135 if ts := fooA.TotalSubs(); ts != 0 { 4136 return fmt.Errorf("Number of subs is %d, should be zero", ts) 4137 } 4138 return nil 4139 }) 4140 4141 // Check that this all work in interest-only mode 4142 sb = runGatewayServer(ob) 4143 defer sb.Shutdown() 4144 4145 fooB, _ = sb.LookupAccount("$foo") 4146 barB, _ = sb.LookupAccount("$bar") 4147 4148 // Add in the service export for the requests. Make it public. 4149 fooB.AddServiceExport("test.request", nil) 4150 // Add import abilities to server B's bar account from foo. 4151 if err := barB.AddServiceImport(fooB, "foo.request", "test.request"); err != nil { 4152 t.Fatalf("Error adding service import: %v", err) 4153 } 4154 4155 waitForOutboundGateways(t, sa, 1, 2*time.Second) 4156 waitForOutboundGateways(t, sb, 1, 2*time.Second) 4157 waitForInboundGateways(t, sa, 1, 2*time.Second) 4158 waitForInboundGateways(t, sb, 1, 2*time.Second) 4159 4160 // We need at least a subscription on A otherwise when publishing 4161 // to subjects with no interest we would simply get an A- 4162 natsSubSync(t, clientA, "not.used") 4163 4164 // Create a client on B that will use account $foo 4165 bURL = fmt.Sprintf("nats://clientBFoo:password@127.0.0.1:%d", ob.Port) 4166 clientB = natsConnect(t, bURL) 4167 defer clientB.Close() 4168 4169 // First flood with subjects that remote gw is not interested 4170 // so we switch to interest-only. 4171 for i := 0; i < 1100; i++ { 4172 natsPub(t, clientB, fmt.Sprintf("no.interest.%d", i), []byte("hello")) 4173 } 4174 natsFlush(t, clientB) 4175 4176 checkGWInterestOnlyMode(t, sb, "A", "$foo") 4177 4178 // Go back to clientB on $bar. 4179 clientB.Close() 4180 bURL = fmt.Sprintf("nats://clientB:password@127.0.0.1:%d", ob.Port) 4181 clientB = natsConnect(t, bURL) 4182 defer clientB.Close() 4183 4184 subA = natsSubSync(t, clientA, "test.request") 4185 natsFlush(t, clientA) 4186 4187 subB = natsSubSync(t, clientB, "reply") 4188 natsFlush(t, clientB) 4189 4190 // Sine it is interest-only, B should receive an interest 4191 // on $foo test.request 4192 checkGWInterestOnlyModeInterestOn(t, sb, "A", "$foo", "test.request") 4193 4194 // Send the request from clientB on foo.request, 4195 natsPubReq(t, clientB, "foo.request", "reply", []byte("hi")) 4196 natsFlush(t, clientB) 4197 4198 // Expect the request on A 4199 msg, err := subA.NextMsg(time.Second) 4200 if err != nil { 4201 t.Fatalf("subA failed to get request: %v", err) 4202 } 4203 if msg.Subject != "test.request" || string(msg.Data) != "hi" { 4204 t.Fatalf("Unexpected message: %v", msg) 4205 } 4206 if msg.Reply == "reply" { 4207 t.Fatalf("Expected randomized reply, but got original") 4208 } 4209 4210 // Check for duplicate message 4211 if msg, err := subA.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 4212 t.Fatalf("Unexpected msg: %v", msg) 4213 } 4214 4215 // Send reply 4216 natsPub(t, clientA, msg.Reply, []byte("ok")) 4217 natsFlush(t, clientA) 4218 4219 msg, err = subB.NextMsg(time.Second) 4220 if err != nil { 4221 t.Fatalf("subB failed to get reply: %v", err) 4222 } 4223 if msg.Subject != "reply" || string(msg.Data) != "ok" { 4224 t.Fatalf("Unexpected message: %v", msg) 4225 } 4226 4227 // Check for duplicate message 4228 if msg, err := subB.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 4229 t.Fatalf("Unexpected msg: %v", msg) 4230 } 4231 } 4232 4233 func ensureGWConnectTo(t *testing.T, s *Server, remoteGWName string, remoteGWServer *Server) { 4234 t.Helper() 4235 var good bool 4236 for i := 0; !good && (i < 3); i++ { 4237 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 4238 if s.numOutboundGateways() == 0 { 4239 return fmt.Errorf("Still no gw outbound connection") 4240 } 4241 return nil 4242 }) 4243 ogc := s.getOutboundGatewayConnection(remoteGWName) 4244 ogc.mu.Lock() 4245 name := ogc.opts.Name 4246 nc := ogc.nc 4247 ogc.mu.Unlock() 4248 if name != remoteGWServer.ID() { 4249 rg := s.getRemoteGateway(remoteGWName) 4250 goodURL := remoteGWServer.getGatewayURL() 4251 rg.Lock() 4252 for u := range rg.urls { 4253 if u != goodURL { 4254 delete(rg.urls, u) 4255 } 4256 } 4257 rg.Unlock() 4258 if nc != nil { 4259 nc.Close() 4260 } 4261 } else { 4262 good = true 4263 } 4264 } 4265 if !good { 4266 t.Fatalf("Could not ensure that server connects to remote gateway %q at URL %q", 4267 remoteGWName, remoteGWServer.getGatewayURL()) 4268 } 4269 } 4270 4271 func TestGatewayServiceImportComplexSetup(t *testing.T) { 4272 // This test will have following setup: 4273 // 4274 // |- responder (subs to "$foo test.request") 4275 // | (sends to "$foo _R_.xxxx") 4276 // route v 4277 // [A1]<----------------->[A2] 4278 // ^ |^ | 4279 // |gw| \______gw________ gw| 4280 // | v \ v 4281 // [B1]<----------------->[B2] 4282 // ^ route 4283 // | 4284 // |_ requestor (sends "$bar foo.request reply") 4285 // 4286 4287 // Setup first A1 and B1 to ensure that they have GWs 4288 // connections as described above. 4289 4290 oa1 := testDefaultOptionsForGateway("A") 4291 setAccountUserPassInOptions(oa1, "$foo", "clientA", "password") 4292 setAccountUserPassInOptions(oa1, "$bar", "yyyyyyy", "password") 4293 sa1 := runGatewayServer(oa1) 4294 defer sa1.Shutdown() 4295 4296 ob1 := testGatewayOptionsFromToWithServers(t, "B", "A", sa1) 4297 setAccountUserPassInOptions(ob1, "$foo", "xxxxxxx", "password") 4298 setAccountUserPassInOptions(ob1, "$bar", "clientB", "password") 4299 sb1 := runGatewayServer(ob1) 4300 defer sb1.Shutdown() 4301 4302 waitForOutboundGateways(t, sa1, 1, time.Second) 4303 waitForOutboundGateways(t, sb1, 1, time.Second) 4304 4305 waitForInboundGateways(t, sa1, 1, time.Second) 4306 waitForInboundGateways(t, sb1, 1, time.Second) 4307 4308 ob2 := testGatewayOptionsFromToWithServers(t, "B", "A", sa1) 4309 ob2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", sb1.ClusterAddr().Port)) 4310 setAccountUserPassInOptions(ob2, "$foo", "clientBFoo", "password") 4311 setAccountUserPassInOptions(ob2, "$bar", "clientB", "password") 4312 ob2.gatewaysSolicitDelay = time.Nanosecond // 0 would be default, so nano to connect asap 4313 sb2 := runGatewayServer(ob2) 4314 defer sb2.Shutdown() 4315 4316 waitForOutboundGateways(t, sa1, 1, time.Second) 4317 waitForOutboundGateways(t, sb1, 1, time.Second) 4318 waitForOutboundGateways(t, sb2, 1, 2*time.Second) 4319 4320 waitForInboundGateways(t, sa1, 2, time.Second) 4321 waitForInboundGateways(t, sb1, 1, time.Second) 4322 waitForInboundGateways(t, sb2, 0, time.Second) 4323 4324 oa2 := testGatewayOptionsFromToWithServers(t, "A", "B", sb2) 4325 oa2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", sa1.ClusterAddr().Port)) 4326 setAccountUserPassInOptions(oa2, "$foo", "clientA", "password") 4327 setAccountUserPassInOptions(oa2, "$bar", "yyyyyyy", "password") 4328 oa2.gatewaysSolicitDelay = time.Nanosecond // 0 would be default, so nano to connect asap 4329 sa2 := runGatewayServer(oa2) 4330 defer sa2.Shutdown() 4331 4332 ensureGWConnectTo(t, sa2, "B", sb2) 4333 4334 checkClusterFormed(t, sa1, sa2) 4335 checkClusterFormed(t, sb1, sb2) 4336 4337 waitForOutboundGateways(t, sa1, 1, time.Second) 4338 waitForOutboundGateways(t, sb1, 1, time.Second) 4339 waitForOutboundGateways(t, sb2, 1, time.Second) 4340 waitForOutboundGateways(t, sa2, 1, 2*time.Second) 4341 4342 waitForInboundGateways(t, sa1, 2, time.Second) 4343 waitForInboundGateways(t, sb1, 1, time.Second) 4344 waitForInboundGateways(t, sb2, 1, 2*time.Second) 4345 waitForInboundGateways(t, sa2, 0, time.Second) 4346 4347 // Verification that we have what we wanted 4348 c := sa2.getOutboundGatewayConnection("B") 4349 if c == nil || c.opts.Name != sb2.ID() { 4350 t.Fatalf("A2 does not have outbound to B2") 4351 } 4352 c = getInboundGatewayConnection(sa2, "A") 4353 if c != nil { 4354 t.Fatalf("Bad setup") 4355 } 4356 c = sb2.getOutboundGatewayConnection("A") 4357 if c == nil || c.opts.Name != sa1.ID() { 4358 t.Fatalf("B2 does not have outbound to A1") 4359 } 4360 c = getInboundGatewayConnection(sb2, "B") 4361 if c == nil || c.opts.Name != sa2.ID() { 4362 t.Fatalf("Bad setup") 4363 } 4364 4365 // Ok, so now that we have proper setup, do actual test! 4366 4367 // Get accounts 4368 fooA1, _ := sa1.LookupAccount("$foo") 4369 barA1, _ := sa1.LookupAccount("$bar") 4370 fooA2, _ := sa2.LookupAccount("$foo") 4371 barA2, _ := sa2.LookupAccount("$bar") 4372 4373 fooB1, _ := sb1.LookupAccount("$foo") 4374 barB1, _ := sb1.LookupAccount("$bar") 4375 fooB2, _ := sb2.LookupAccount("$foo") 4376 barB2, _ := sb2.LookupAccount("$bar") 4377 4378 // Add in the service export for the requests. Make it public. 4379 fooA1.AddServiceExport("test.request", nil) 4380 fooA2.AddServiceExport("test.request", nil) 4381 fooB1.AddServiceExport("test.request", nil) 4382 fooB2.AddServiceExport("test.request", nil) 4383 4384 // Add import abilities to server B's bar account from foo. 4385 if err := barB1.AddServiceImport(fooB1, "foo.request", "test.request"); err != nil { 4386 t.Fatalf("Error adding service import: %v", err) 4387 } 4388 if err := barB2.AddServiceImport(fooB2, "foo.request", "test.request"); err != nil { 4389 t.Fatalf("Error adding service import: %v", err) 4390 } 4391 // Same on A. 4392 if err := barA1.AddServiceImport(fooA1, "foo.request", "test.request"); err != nil { 4393 t.Fatalf("Error adding service import: %v", err) 4394 } 4395 if err := barA2.AddServiceImport(fooA2, "foo.request", "test.request"); err != nil { 4396 t.Fatalf("Error adding service import: %v", err) 4397 } 4398 4399 // clientA will be connected to A2 and be the service endpoint and responder. 4400 a2URL := fmt.Sprintf("nats://clientA:password@127.0.0.1:%d", oa2.Port) 4401 clientA := natsConnect(t, a2URL) 4402 defer clientA.Close() 4403 4404 subA := natsSubSync(t, clientA, "test.request") 4405 natsFlush(t, clientA) 4406 4407 // Now setup client B on B1 who will do a sub from account $bar 4408 // that should map account $foo's foo subject. 4409 b1URL := fmt.Sprintf("nats://clientB:password@127.0.0.1:%d", ob1.Port) 4410 clientB := natsConnect(t, b1URL) 4411 defer clientB.Close() 4412 4413 subB := natsSubSync(t, clientB, "reply") 4414 natsFlush(t, clientB) 4415 4416 var msg *nats.Msg 4417 var err error 4418 for attempts := 1; attempts <= 2; attempts++ { 4419 // Send the request from clientB on foo.request, 4420 natsPubReq(t, clientB, "foo.request", "reply", []byte("hi")) 4421 natsFlush(t, clientB) 4422 4423 // Expect the request on A 4424 msg, err = subA.NextMsg(time.Second) 4425 if err != nil { 4426 if attempts == 1 { 4427 // Since we are in interestOnly mode, it is possible 4428 // that server B did not receive the subscription 4429 // interest yet, so try again. 4430 continue 4431 } 4432 t.Fatalf("subA failed to get request: %v", err) 4433 } 4434 if msg.Subject != "test.request" || string(msg.Data) != "hi" { 4435 t.Fatalf("Unexpected message: %v", msg) 4436 } 4437 if msg.Reply == "reply" { 4438 t.Fatalf("Expected randomized reply, but got original") 4439 } 4440 } 4441 // Make sure we don't receive a second copy 4442 if msg, err := subA.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 4443 t.Fatalf("Received unexpected message: %v", msg) 4444 } 4445 4446 // Send reply 4447 natsPub(t, clientA, msg.Reply, []byte("ok")) 4448 natsFlush(t, clientA) 4449 4450 msg, err = subB.NextMsg(time.Second) 4451 if err != nil { 4452 t.Fatalf("subB failed to get reply: %v", err) 4453 } 4454 if msg.Subject != "reply" || string(msg.Data) != "ok" { 4455 t.Fatalf("Unexpected message: %v", msg) 4456 } 4457 // Make sure we don't receive a second copy 4458 if msg, err := subB.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 4459 t.Fatalf("Received unexpected message: %v", msg) 4460 } 4461 4462 checkSubs := func(t *testing.T, acc *Account, srvName string, expected int) { 4463 t.Helper() 4464 checkFor(t, 2*time.Second, 10*time.Millisecond, func() error { 4465 if ts := acc.TotalSubs(); ts != expected { 4466 return fmt.Errorf("Number of subs is %d on acc=%s srv=%s, should be %v", ts, acc.Name, srvName, expected) 4467 } 4468 return nil 4469 }) 4470 } 4471 checkSubs(t, fooA1, "A1", 1) 4472 checkSubs(t, barA1, "A1", 1) 4473 checkSubs(t, fooA2, "A2", 1) 4474 checkSubs(t, barA2, "A2", 1) 4475 checkSubs(t, fooB1, "B1", 1) 4476 checkSubs(t, barB1, "B1", 2) 4477 checkSubs(t, fooB2, "B2", 1) 4478 checkSubs(t, barB2, "B2", 2) 4479 4480 // Speed up exiration 4481 err = fooA2.SetServiceExportResponseThreshold("test.request", 10*time.Millisecond) 4482 if err != nil { 4483 t.Fatalf("Error setting response threshold: %v", err) 4484 } 4485 err = fooB1.SetServiceExportResponseThreshold("test.request", 10*time.Millisecond) 4486 if err != nil { 4487 t.Fatalf("Error setting response threshold: %v", err) 4488 } 4489 4490 // Send 100 requests from clientB on foo.request, 4491 for i := 0; i < 100; i++ { 4492 natsPubReq(t, clientB, "foo.request", "reply", []byte("hi")) 4493 } 4494 natsFlush(t, clientB) 4495 4496 // Consume the requests, but don't reply to them... 4497 for i := 0; i < 100; i++ { 4498 if _, err := subA.NextMsg(time.Second); err != nil { 4499 t.Fatalf("subA did not receive request: %v", err) 4500 } 4501 } 4502 4503 // Unsubsribe all and ensure counts go to 0. 4504 natsUnsub(t, subA) 4505 natsFlush(t, clientA) 4506 natsUnsub(t, subB) 4507 natsFlush(t, clientB) 4508 4509 // We should expire because ttl. 4510 checkFor(t, 2*time.Second, 10*time.Millisecond, func() error { 4511 if nr := len(fooA1.exports.responses); nr != 0 { 4512 return fmt.Errorf("Number of responses is %d", nr) 4513 } 4514 return nil 4515 }) 4516 4517 checkSubs(t, fooA1, "A1", 0) 4518 checkSubs(t, fooA2, "A2", 0) 4519 checkSubs(t, fooB1, "B1", 1) 4520 checkSubs(t, fooB2, "B2", 1) 4521 4522 checkSubs(t, barA1, "A1", 1) 4523 checkSubs(t, barA2, "A2", 1) 4524 checkSubs(t, barB1, "B1", 1) 4525 checkSubs(t, barB2, "B2", 1) 4526 4527 // Check that this all work in interest-only mode. 4528 4529 // We need at least a subscription on B2 otherwise when publishing 4530 // to subjects with no interest we would simply get an A- 4531 b2URL := fmt.Sprintf("nats://clientBFoo:password@127.0.0.1:%d", ob2.Port) 4532 clientB2 := natsConnect(t, b2URL) 4533 defer clientB2.Close() 4534 natsSubSync(t, clientB2, "not.used") 4535 natsFlush(t, clientB2) 4536 4537 // Make A2 flood B2 with subjects that B2 is not interested in. 4538 for i := 0; i < 1100; i++ { 4539 natsPub(t, clientA, fmt.Sprintf("no.interest.%d", i), []byte("hello")) 4540 } 4541 natsFlush(t, clientA) 4542 // Wait for B2 to switch to interest-only 4543 checkGWInterestOnlyMode(t, sa2, "B", "$foo") 4544 4545 subA = natsSubSync(t, clientA, "test.request") 4546 natsFlush(t, clientA) 4547 4548 subB = natsSubSync(t, clientB, "reply") 4549 natsFlush(t, clientB) 4550 4551 for attempts := 1; attempts <= 2; attempts++ { 4552 // Send the request from clientB on foo.request, 4553 natsPubReq(t, clientB, "foo.request", "reply", []byte("hi")) 4554 natsFlush(t, clientB) 4555 4556 // Expect the request on A 4557 msg, err = subA.NextMsg(time.Second) 4558 if err != nil { 4559 if attempts == 1 { 4560 // Since we are in interestOnly mode, it is possible 4561 // that server B did not receive the subscription 4562 // interest yet, so try again. 4563 continue 4564 } 4565 t.Fatalf("subA failed to get request: %v", err) 4566 } 4567 if msg.Subject != "test.request" || string(msg.Data) != "hi" { 4568 t.Fatalf("Unexpected message: %v", msg) 4569 } 4570 if msg.Reply == "reply" { 4571 t.Fatalf("Expected randomized reply, but got original") 4572 } 4573 } 4574 4575 // Check for duplicate message 4576 if msg, err := subA.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 4577 t.Fatalf("Unexpected msg: %v", msg) 4578 } 4579 4580 // Send reply 4581 natsPub(t, clientA, msg.Reply, []byte("ok")) 4582 natsFlush(t, clientA) 4583 4584 msg, err = subB.NextMsg(time.Second) 4585 if err != nil { 4586 t.Fatalf("subB failed to get reply: %v", err) 4587 } 4588 if msg.Subject != "reply" || string(msg.Data) != "ok" { 4589 t.Fatalf("Unexpected message: %v", msg) 4590 } 4591 4592 // Check for duplicate message 4593 if msg, err := subB.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 4594 t.Fatalf("Unexpected msg: %v", msg) 4595 } 4596 } 4597 4598 func TestGatewayServiceExportWithWildcards(t *testing.T) { 4599 // This test will have following setup: 4600 // 4601 // |- responder 4602 // | 4603 // route v 4604 // [A1]<----------------->[A2] 4605 // ^ |^ | 4606 // |gw| \______gw________ gw| 4607 // | v \ v 4608 // [B1]<----------------->[B2] 4609 // ^ route 4610 // | 4611 // |_ requestor 4612 // 4613 4614 for _, test := range []struct { 4615 name string 4616 public bool 4617 }{ 4618 { 4619 name: "public", 4620 public: true, 4621 }, 4622 { 4623 name: "private", 4624 public: false, 4625 }, 4626 } { 4627 t.Run(test.name, func(t *testing.T) { 4628 4629 // Setup first A1 and B1 to ensure that they have GWs 4630 // connections as described above. 4631 4632 oa1 := testDefaultOptionsForGateway("A") 4633 setAccountUserPassInOptions(oa1, "$foo", "clientA", "password") 4634 setAccountUserPassInOptions(oa1, "$bar", "yyyyyyy", "password") 4635 sa1 := runGatewayServer(oa1) 4636 defer sa1.Shutdown() 4637 4638 ob1 := testGatewayOptionsFromToWithServers(t, "B", "A", sa1) 4639 setAccountUserPassInOptions(ob1, "$foo", "xxxxxxx", "password") 4640 setAccountUserPassInOptions(ob1, "$bar", "clientB", "password") 4641 sb1 := runGatewayServer(ob1) 4642 defer sb1.Shutdown() 4643 4644 waitForOutboundGateways(t, sa1, 1, time.Second) 4645 waitForOutboundGateways(t, sb1, 1, time.Second) 4646 4647 waitForInboundGateways(t, sa1, 1, time.Second) 4648 waitForInboundGateways(t, sb1, 1, time.Second) 4649 4650 ob2 := testGatewayOptionsFromToWithServers(t, "B", "A", sa1) 4651 ob2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", sb1.ClusterAddr().Port)) 4652 setAccountUserPassInOptions(ob2, "$foo", "clientBFoo", "password") 4653 setAccountUserPassInOptions(ob2, "$bar", "clientB", "password") 4654 ob2.gatewaysSolicitDelay = time.Nanosecond // 0 would be default, so nano to connect asap 4655 sb2 := runGatewayServer(ob2) 4656 defer sb2.Shutdown() 4657 4658 waitForOutboundGateways(t, sa1, 1, time.Second) 4659 waitForOutboundGateways(t, sb1, 1, time.Second) 4660 waitForOutboundGateways(t, sb2, 1, 2*time.Second) 4661 4662 waitForInboundGateways(t, sa1, 2, time.Second) 4663 waitForInboundGateways(t, sb1, 1, time.Second) 4664 waitForInboundGateways(t, sb2, 0, time.Second) 4665 4666 oa2 := testGatewayOptionsFromToWithServers(t, "A", "B", sb2) 4667 oa2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", sa1.ClusterAddr().Port)) 4668 setAccountUserPassInOptions(oa2, "$foo", "clientA", "password") 4669 setAccountUserPassInOptions(oa2, "$bar", "yyyyyyy", "password") 4670 oa2.gatewaysSolicitDelay = time.Nanosecond // 0 would be default, so nano to connect asap 4671 sa2 := runGatewayServer(oa2) 4672 defer sa2.Shutdown() 4673 4674 ensureGWConnectTo(t, sa2, "B", sb2) 4675 4676 checkClusterFormed(t, sa1, sa2) 4677 checkClusterFormed(t, sb1, sb2) 4678 4679 waitForOutboundGateways(t, sa1, 1, time.Second) 4680 waitForOutboundGateways(t, sb1, 1, time.Second) 4681 waitForOutboundGateways(t, sb2, 1, time.Second) 4682 waitForOutboundGateways(t, sa2, 1, 2*time.Second) 4683 4684 waitForInboundGateways(t, sa1, 2, time.Second) 4685 waitForInboundGateways(t, sb1, 1, time.Second) 4686 waitForInboundGateways(t, sb2, 1, 2*time.Second) 4687 waitForInboundGateways(t, sa2, 0, time.Second) 4688 4689 // Verification that we have what we wanted 4690 c := sa2.getOutboundGatewayConnection("B") 4691 if c == nil || c.opts.Name != sb2.ID() { 4692 t.Fatalf("A2 does not have outbound to B2") 4693 } 4694 c = getInboundGatewayConnection(sa2, "A") 4695 if c != nil { 4696 t.Fatalf("Bad setup") 4697 } 4698 c = sb2.getOutboundGatewayConnection("A") 4699 if c == nil || c.opts.Name != sa1.ID() { 4700 t.Fatalf("B2 does not have outbound to A1") 4701 } 4702 c = getInboundGatewayConnection(sb2, "B") 4703 if c == nil || c.opts.Name != sa2.ID() { 4704 t.Fatalf("Bad setup") 4705 } 4706 4707 // Ok, so now that we have proper setup, do actual test! 4708 4709 // Get accounts 4710 fooA1, _ := sa1.LookupAccount("$foo") 4711 barA1, _ := sa1.LookupAccount("$bar") 4712 fooA2, _ := sa2.LookupAccount("$foo") 4713 barA2, _ := sa2.LookupAccount("$bar") 4714 4715 fooB1, _ := sb1.LookupAccount("$foo") 4716 barB1, _ := sb1.LookupAccount("$bar") 4717 fooB2, _ := sb2.LookupAccount("$foo") 4718 barB2, _ := sb2.LookupAccount("$bar") 4719 4720 var accs []*Account 4721 // Add in the service export for the requests. 4722 if !test.public { 4723 accs = []*Account{barA1} 4724 } 4725 fooA1.AddServiceExport("ngs.update.*", accs) 4726 if !test.public { 4727 accs = []*Account{barA2} 4728 } 4729 fooA2.AddServiceExport("ngs.update.*", accs) 4730 if !test.public { 4731 accs = []*Account{barB1} 4732 } 4733 fooB1.AddServiceExport("ngs.update.*", accs) 4734 if !test.public { 4735 accs = []*Account{barB2} 4736 } 4737 fooB2.AddServiceExport("ngs.update.*", accs) 4738 4739 // Add import abilities to server B's bar account from foo. 4740 if err := barB1.AddServiceImport(fooB1, "ngs.update", "ngs.update.$bar"); err != nil { 4741 t.Fatalf("Error adding service import: %v", err) 4742 } 4743 if err := barB2.AddServiceImport(fooB2, "ngs.update", "ngs.update.$bar"); err != nil { 4744 t.Fatalf("Error adding service import: %v", err) 4745 } 4746 // Same on A. 4747 if err := barA1.AddServiceImport(fooA1, "ngs.update", "ngs.update.$bar"); err != nil { 4748 t.Fatalf("Error adding service import: %v", err) 4749 } 4750 if err := barA2.AddServiceImport(fooA2, "ngs.update", "ngs.update.$bar"); err != nil { 4751 t.Fatalf("Error adding service import: %v", err) 4752 } 4753 4754 // clientA will be connected to A2 and be the service endpoint and responder. 4755 a2URL := fmt.Sprintf("nats://clientA:password@127.0.0.1:%d", oa2.Port) 4756 clientA := natsConnect(t, a2URL) 4757 defer clientA.Close() 4758 4759 subA := natsSubSync(t, clientA, "ngs.update.$bar") 4760 natsFlush(t, clientA) 4761 4762 // Now setup client B on B1 who will do a sub from account $bar 4763 // that should map account $foo's foo subject. 4764 b1URL := fmt.Sprintf("nats://clientB:password@127.0.0.1:%d", ob1.Port) 4765 clientB := natsConnect(t, b1URL) 4766 defer clientB.Close() 4767 4768 subB := natsSubSync(t, clientB, "reply") 4769 natsFlush(t, clientB) 4770 4771 var msg *nats.Msg 4772 var err error 4773 for attempts := 1; attempts <= 2; attempts++ { 4774 // Send the request from clientB on foo.request, 4775 natsPubReq(t, clientB, "ngs.update", "reply", []byte("hi")) 4776 natsFlush(t, clientB) 4777 4778 // Expect the request on A 4779 msg, err = subA.NextMsg(time.Second) 4780 if err != nil { 4781 if attempts == 1 { 4782 // Since we are in interestOnly mode, it is possible 4783 // that server B did not receive the subscription 4784 // interest yet, so try again. 4785 continue 4786 } 4787 t.Fatalf("subA failed to get request: %v", err) 4788 } 4789 if msg.Subject != "ngs.update.$bar" || string(msg.Data) != "hi" { 4790 t.Fatalf("Unexpected message: %v", msg) 4791 } 4792 if msg.Reply == "reply" { 4793 t.Fatalf("Expected randomized reply, but got original") 4794 } 4795 } 4796 // Make sure we don't receive a second copy 4797 if msg, err := subA.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 4798 t.Fatalf("Received unexpected message: %v", msg) 4799 } 4800 4801 // Send reply 4802 natsPub(t, clientA, msg.Reply, []byte("ok")) 4803 natsFlush(t, clientA) 4804 4805 msg, err = subB.NextMsg(time.Second) 4806 if err != nil { 4807 t.Fatalf("subB failed to get reply: %v", err) 4808 } 4809 if msg.Subject != "reply" || string(msg.Data) != "ok" { 4810 t.Fatalf("Unexpected message: %v", msg) 4811 } 4812 // Make sure we don't receive a second copy 4813 if msg, err := subB.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 4814 t.Fatalf("Received unexpected message: %v", msg) 4815 } 4816 4817 checkSubs := func(t *testing.T, acc *Account, srvName string, expected int) { 4818 t.Helper() 4819 checkFor(t, 2*time.Second, 10*time.Millisecond, func() error { 4820 if ts := acc.TotalSubs(); ts != expected { 4821 return fmt.Errorf("Number of subs is %d on acc=%s srv=%s, should be %v", ts, acc.Name, srvName, expected) 4822 } 4823 return nil 4824 }) 4825 } 4826 checkSubs(t, fooA1, "A1", 1) 4827 checkSubs(t, barA1, "A1", 1) 4828 checkSubs(t, fooA2, "A2", 1) 4829 checkSubs(t, barA2, "A2", 1) 4830 checkSubs(t, fooB1, "B1", 1) 4831 checkSubs(t, barB1, "B1", 2) 4832 checkSubs(t, fooB2, "B2", 1) 4833 checkSubs(t, barB2, "B2", 2) 4834 4835 // Speed up exiration 4836 err = fooA1.SetServiceExportResponseThreshold("ngs.update.*", 10*time.Millisecond) 4837 if err != nil { 4838 t.Fatalf("Error setting response threshold: %v", err) 4839 } 4840 err = fooB1.SetServiceExportResponseThreshold("ngs.update.*", 10*time.Millisecond) 4841 if err != nil { 4842 t.Fatalf("Error setting response threshold: %v", err) 4843 } 4844 4845 // Send 100 requests from clientB on foo.request, 4846 for i := 0; i < 100; i++ { 4847 natsPubReq(t, clientB, "ngs.update", "reply", []byte("hi")) 4848 } 4849 natsFlush(t, clientB) 4850 4851 // Consume the requests, but don't reply to them... 4852 for i := 0; i < 100; i++ { 4853 if _, err := subA.NextMsg(time.Second); err != nil { 4854 t.Fatalf("subA did not receive request: %v", err) 4855 } 4856 } 4857 4858 // Unsubsribe all and ensure counts go to 0. 4859 natsUnsub(t, subA) 4860 natsFlush(t, clientA) 4861 natsUnsub(t, subB) 4862 natsFlush(t, clientB) 4863 4864 // We should expire because ttl. 4865 checkFor(t, 2*time.Second, 10*time.Millisecond, func() error { 4866 if nr := len(fooA1.exports.responses); nr != 0 { 4867 return fmt.Errorf("Number of responses is %d", nr) 4868 } 4869 return nil 4870 }) 4871 4872 checkSubs(t, fooA1, "A1", 0) 4873 checkSubs(t, fooA2, "A2", 0) 4874 checkSubs(t, fooB1, "B1", 1) 4875 checkSubs(t, fooB2, "B2", 1) 4876 4877 checkSubs(t, barA1, "A1", 1) 4878 checkSubs(t, barA2, "A2", 1) 4879 checkSubs(t, barB1, "B1", 1) 4880 checkSubs(t, barB2, "B2", 1) 4881 4882 // Check that this all work in interest-only mode. 4883 4884 // We need at least a subscription on B2 otherwise when publishing 4885 // to subjects with no interest we would simply get an A- 4886 b2URL := fmt.Sprintf("nats://clientBFoo:password@127.0.0.1:%d", ob2.Port) 4887 clientB2 := natsConnect(t, b2URL) 4888 defer clientB2.Close() 4889 natsSubSync(t, clientB2, "not.used") 4890 natsFlush(t, clientB2) 4891 4892 // Make A2 flood B2 with subjects that B2 is not interested in. 4893 for i := 0; i < 1100; i++ { 4894 natsPub(t, clientA, fmt.Sprintf("no.interest.%d", i), []byte("hello")) 4895 } 4896 natsFlush(t, clientA) 4897 4898 // Wait for B2 to switch to interest-only 4899 checkGWInterestOnlyMode(t, sa2, "B", "$foo") 4900 4901 subA = natsSubSync(t, clientA, "ngs.update.*") 4902 natsFlush(t, clientA) 4903 4904 subB = natsSubSync(t, clientB, "reply") 4905 natsFlush(t, clientB) 4906 4907 for attempts := 1; attempts <= 2; attempts++ { 4908 // Send the request from clientB on foo.request, 4909 natsPubReq(t, clientB, "ngs.update", "reply", []byte("hi")) 4910 natsFlush(t, clientB) 4911 4912 // Expect the request on A 4913 msg, err = subA.NextMsg(time.Second) 4914 if err != nil { 4915 if attempts == 1 { 4916 // Since we are in interestOnly mode, it is possible 4917 // that server B did not receive the subscription 4918 // interest yet, so try again. 4919 continue 4920 } 4921 t.Fatalf("subA failed to get request: %v", err) 4922 } 4923 if msg.Subject != "ngs.update.$bar" || string(msg.Data) != "hi" { 4924 t.Fatalf("Unexpected message: %v", msg) 4925 } 4926 if msg.Reply == "reply" { 4927 t.Fatalf("Expected randomized reply, but got original") 4928 } 4929 } 4930 4931 // Check for duplicate message 4932 if msg, err := subA.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 4933 t.Fatalf("Unexpected msg: %v", msg) 4934 } 4935 4936 // Send reply 4937 natsPub(t, clientA, msg.Reply, []byte("ok")) 4938 natsFlush(t, clientA) 4939 4940 msg, err = subB.NextMsg(time.Second) 4941 if err != nil { 4942 t.Fatalf("subB failed to get reply: %v", err) 4943 } 4944 if msg.Subject != "reply" || string(msg.Data) != "ok" { 4945 t.Fatalf("Unexpected message: %v", msg) 4946 } 4947 4948 // Check for duplicate message 4949 if msg, err := subB.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 4950 t.Fatalf("Unexpected msg: %v", msg) 4951 } 4952 }) 4953 } 4954 } 4955 4956 // NOTE: if this fails for you and says only has <10 outbound, make sure ulimit for open files > 256. 4957 func TestGatewayMemUsage(t *testing.T) { 4958 // Try to clean up. 4959 runtime.GC() 4960 var m runtime.MemStats 4961 runtime.ReadMemStats(&m) 4962 pta := m.TotalAlloc 4963 4964 o := testDefaultOptionsForGateway("A") 4965 s := runGatewayServer(o) 4966 defer s.Shutdown() 4967 4968 var servers []*Server 4969 servers = append(servers, s) 4970 4971 numServers := 10 4972 for i := 0; i < numServers; i++ { 4973 rn := fmt.Sprintf("RG_%d", i+1) 4974 o := testGatewayOptionsFromToWithServers(t, rn, "A", s) 4975 s := runGatewayServer(o) 4976 defer s.Shutdown() 4977 servers = append(servers, s) 4978 } 4979 4980 // Each server should have an outbound 4981 for _, s := range servers { 4982 waitForOutboundGateways(t, s, numServers, 2*time.Second) 4983 } 4984 // The first started server should have numServers inbounds (since 4985 // they all connect to it). 4986 waitForInboundGateways(t, s, numServers, 2*time.Second) 4987 4988 // Calculate in MB what we are using now. 4989 const max = 50 * 1024 * 1024 // 50MB 4990 runtime.ReadMemStats(&m) 4991 used := m.TotalAlloc - pta 4992 if used > max { 4993 t.Fatalf("Cluster using too much memory, expect < 50MB, got %dMB", used/(1024*1024)) 4994 } 4995 4996 for _, s := range servers { 4997 s.Shutdown() 4998 } 4999 } 5000 5001 func TestGatewayMapReplyOnlyForRecentSub(t *testing.T) { 5002 o2 := testDefaultOptionsForGateway("B") 5003 s2 := runGatewayServer(o2) 5004 defer s2.Shutdown() 5005 5006 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 5007 s1 := runGatewayServer(o1) 5008 defer s1.Shutdown() 5009 5010 waitForOutboundGateways(t, s1, 1, time.Second) 5011 waitForOutboundGateways(t, s2, 1, time.Second) 5012 5013 // Change s1's recent sub expiration default value 5014 s1.mu.Lock() 5015 s1.gateway.pasi.Lock() 5016 s1.gateway.recSubExp = 100 * time.Millisecond 5017 s1.gateway.pasi.Unlock() 5018 s1.mu.Unlock() 5019 5020 // Setup a replier on s2 5021 nc2 := natsConnect(t, fmt.Sprintf("nats://%s:%d", o2.Host, o2.Port)) 5022 defer nc2.Close() 5023 errCh := make(chan error, 1) 5024 natsSub(t, nc2, "foo", func(m *nats.Msg) { 5025 // Send reply regardless.. 5026 nc2.Publish(m.Reply, []byte("reply")) 5027 // Check that reply given to application is not mapped. 5028 if !strings.HasPrefix(m.Reply, nats.InboxPrefix) { 5029 errCh <- fmt.Errorf("Reply expected to have normal inbox, got %v", m.Reply) 5030 return 5031 } 5032 errCh <- nil 5033 }) 5034 natsFlush(t, nc2) 5035 checkExpectedSubs(t, 1, s2) 5036 5037 // Create requestor on s1 5038 nc1 := natsConnect(t, fmt.Sprintf("nats://%s:%d", o1.Host, o1.Port)) 5039 defer nc1.Close() 5040 // Send first request, reply should be mapped 5041 nc1.Request("foo", []byte("msg1"), time.Second) 5042 // Wait more than the recent sub expiration (that we have set to 100ms) 5043 time.Sleep(200 * time.Millisecond) 5044 // Send second request (reply should not be mapped) 5045 nc1.Request("foo", []byte("msg2"), time.Second) 5046 5047 select { 5048 case e := <-errCh: 5049 if e != nil { 5050 t.Fatalf(e.Error()) 5051 } 5052 case <-time.After(time.Second): 5053 t.Fatalf("Did not get replies") 5054 } 5055 } 5056 5057 type delayedWriteConn struct { 5058 sync.Mutex 5059 net.Conn 5060 bytes [][]byte 5061 delay bool 5062 wg sync.WaitGroup 5063 } 5064 5065 func (c *delayedWriteConn) Write(b []byte) (int, error) { 5066 c.Lock() 5067 defer c.Unlock() 5068 if c.delay || len(c.bytes) > 0 { 5069 c.bytes = append(c.bytes, append([]byte(nil), b...)) 5070 c.wg.Add(1) 5071 go func() { 5072 defer c.wg.Done() 5073 c.Lock() 5074 defer c.Unlock() 5075 if c.delay { 5076 c.Unlock() 5077 time.Sleep(100 * time.Millisecond) 5078 c.Lock() 5079 } 5080 if len(c.bytes) > 0 { 5081 b = c.bytes[0] 5082 c.bytes = c.bytes[1:] 5083 c.Conn.Write(b) 5084 } 5085 }() 5086 return len(b), nil 5087 } 5088 return c.Conn.Write(b) 5089 } 5090 5091 // This test uses a single account and makes sure that when 5092 // a reply subject is prefixed with $GR it comes back to 5093 // the origin cluster and delivered to proper reply subject 5094 // there, but also to subscribers on that reply subject 5095 // on the other cluster. 5096 func TestGatewaySendReplyAcrossGateways(t *testing.T) { 5097 for _, test := range []struct { 5098 name string 5099 poolSize int 5100 peracc bool 5101 }{ 5102 {"no pooling", -1, false}, 5103 {"pooling", 5, false}, 5104 {"per account", 0, true}, 5105 } { 5106 t.Run(test.name, func(t *testing.T) { 5107 ob := testDefaultOptionsForGateway("B") 5108 ob.Accounts = []*Account{NewAccount("ACC")} 5109 ob.Users = []*User{{Username: "user", Password: "pwd", Account: ob.Accounts[0]}} 5110 sb := runGatewayServer(ob) 5111 defer sb.Shutdown() 5112 5113 oa1 := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5114 oa1.Cluster.PoolSize = test.poolSize 5115 if test.peracc { 5116 oa1.Cluster.PinnedAccounts = []string{"ACC"} 5117 } 5118 oa1.Accounts = []*Account{NewAccount("ACC")} 5119 oa1.Users = []*User{{Username: "user", Password: "pwd", Account: oa1.Accounts[0]}} 5120 sa1 := runGatewayServer(oa1) 5121 defer sa1.Shutdown() 5122 5123 waitForOutboundGateways(t, sb, 1, time.Second) 5124 waitForInboundGateways(t, sb, 1, time.Second) 5125 waitForOutboundGateways(t, sa1, 1, time.Second) 5126 waitForInboundGateways(t, sa1, 1, time.Second) 5127 5128 // Now start another server in cluster "A". This will allow us 5129 // to test the reply from cluster "B" coming back directly to 5130 // the server where the request originates, and indirectly through 5131 // route. 5132 oa2 := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5133 oa2.Cluster.PoolSize = test.poolSize 5134 if test.peracc { 5135 oa2.Cluster.PinnedAccounts = []string{"ACC"} 5136 } 5137 oa2.Accounts = []*Account{NewAccount("ACC")} 5138 oa2.Users = []*User{{Username: "user", Password: "pwd", Account: oa2.Accounts[0]}} 5139 oa2.Routes = RoutesFromStr(fmt.Sprintf("nats://%s:%d", oa1.Cluster.Host, oa1.Cluster.Port)) 5140 sa2 := runGatewayServer(oa2) 5141 defer sa2.Shutdown() 5142 5143 waitForOutboundGateways(t, sa2, 1, time.Second) 5144 waitForInboundGateways(t, sb, 2, time.Second) 5145 checkClusterFormed(t, sa1, sa2) 5146 5147 replySubj := "bar" 5148 5149 // Setup a responder on sb 5150 ncb := natsConnect(t, fmt.Sprintf("nats://user:pwd@%s:%d", ob.Host, ob.Port)) 5151 defer ncb.Close() 5152 natsSub(t, ncb, "foo", func(m *nats.Msg) { 5153 m.Respond([]byte("reply")) 5154 }) 5155 // Set a subscription on the reply subject on sb 5156 subSB := natsSubSync(t, ncb, replySubj) 5157 natsFlush(t, ncb) 5158 checkExpectedSubs(t, 2, sb) 5159 5160 testReqReply := func(t *testing.T, host string, port int, createSubOnA bool) { 5161 t.Helper() 5162 nca := natsConnect(t, fmt.Sprintf("nats://user:pwd@%s:%d", host, port)) 5163 defer nca.Close() 5164 if createSubOnA { 5165 subSA := natsSubSync(t, nca, replySubj) 5166 natsPubReq(t, nca, "foo", replySubj, []byte("hello")) 5167 natsNexMsg(t, subSA, time.Second) 5168 // Check for duplicates 5169 if _, err := subSA.NextMsg(50 * time.Millisecond); err == nil { 5170 t.Fatalf("Received duplicate message on subSA!") 5171 } 5172 } else { 5173 natsPubReq(t, nca, "foo", replySubj, []byte("hello")) 5174 } 5175 natsNexMsg(t, subSB, time.Second) 5176 // Check for duplicates 5177 if _, err := subSB.NextMsg(50 * time.Millisecond); err == nil { 5178 t.Fatalf("Received duplicate message on subSB!") 5179 } 5180 } 5181 // Create requestor on sa1 to check for direct reply from GW: 5182 testReqReply(t, oa1.Host, oa1.Port, true) 5183 // Wait for subscription to be gone... 5184 checkExpectedSubs(t, 0, sa1) 5185 // Now create requestor on sa2, it will receive reply through sa1. 5186 testReqReply(t, oa2.Host, oa2.Port, true) 5187 checkExpectedSubs(t, 0, sa1) 5188 checkExpectedSubs(t, 0, sa2) 5189 5190 // Now issue requests but without any interest in the requestor's 5191 // origin cluster and make sure the other cluster gets the reply. 5192 testReqReply(t, oa1.Host, oa1.Port, false) 5193 testReqReply(t, oa2.Host, oa2.Port, false) 5194 5195 // There is a possible race between sa2 sending the RS+ for the 5196 // subscription on the reply subject, and the GW reply making it 5197 // to sa1 before the RS+ is processed there. 5198 // We are going to force this race by making the route connection 5199 // block as needed. 5200 5201 acc, _ := sa2.LookupAccount("ACC") 5202 acc.mu.RLock() 5203 api := acc.routePoolIdx 5204 acc.mu.RUnlock() 5205 5206 var route *client 5207 sa2.mu.Lock() 5208 if test.peracc { 5209 if conns, ok := sa2.accRoutes["ACC"]; ok { 5210 for _, r := range conns { 5211 route = r 5212 break 5213 } 5214 } 5215 } else if test.poolSize > 0 { 5216 sa2.forEachRoute(func(r *client) { 5217 r.mu.Lock() 5218 if r.route.poolIdx == api { 5219 route = r 5220 } 5221 r.mu.Unlock() 5222 }) 5223 } else if r := getFirstRoute(sa2); r != nil { 5224 route = r 5225 } 5226 sa2.mu.Unlock() 5227 route.mu.Lock() 5228 routeConn := &delayedWriteConn{ 5229 Conn: route.nc, 5230 wg: sync.WaitGroup{}, 5231 } 5232 route.nc = routeConn 5233 route.mu.Unlock() 5234 5235 delayRoute := func() { 5236 routeConn.Lock() 5237 routeConn.delay = true 5238 routeConn.Unlock() 5239 } 5240 stopDelayRoute := func() { 5241 routeConn.Lock() 5242 routeConn.delay = false 5243 wg := &routeConn.wg 5244 routeConn.Unlock() 5245 wg.Wait() 5246 } 5247 5248 delayRoute() 5249 testReqReply(t, oa2.Host, oa2.Port, true) 5250 stopDelayRoute() 5251 5252 // Same test but now we have a local interest on the reply subject 5253 // on sa1 to make sure that interest there does not prevent sending 5254 // the RMSG to sa2, which is the origin of the request. 5255 checkExpectedSubs(t, 0, sa1) 5256 checkExpectedSubs(t, 0, sa2) 5257 nca1 := natsConnect(t, fmt.Sprintf("nats://user:pwd@%s:%d", oa1.Host, oa1.Port)) 5258 defer nca1.Close() 5259 subSA1 := natsSubSync(t, nca1, replySubj) 5260 natsFlush(t, nca1) 5261 checkExpectedSubs(t, 1, sa1) 5262 checkExpectedSubs(t, 1, sa2) 5263 5264 delayRoute() 5265 testReqReply(t, oa2.Host, oa2.Port, true) 5266 stopDelayRoute() 5267 5268 natsNexMsg(t, subSA1, time.Second) 5269 }) 5270 } 5271 } 5272 5273 // This test will have a requestor on cluster A and responder 5274 // on cluster B, but when the responder sends the response, 5275 // it will also have a reply subject to receive a response 5276 // for the response. 5277 func TestGatewayPingPongReplyAcrossGateways(t *testing.T) { 5278 ob := testDefaultOptionsForGateway("B") 5279 ob.Accounts = []*Account{NewAccount("ACC")} 5280 ob.Users = []*User{{Username: "user", Password: "pwd", Account: ob.Accounts[0]}} 5281 sb := runGatewayServer(ob) 5282 defer sb.Shutdown() 5283 5284 oa1 := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5285 oa1.Accounts = []*Account{NewAccount("ACC")} 5286 oa1.Users = []*User{{Username: "user", Password: "pwd", Account: oa1.Accounts[0]}} 5287 sa1 := runGatewayServer(oa1) 5288 defer sa1.Shutdown() 5289 5290 waitForOutboundGateways(t, sb, 1, time.Second) 5291 waitForInboundGateways(t, sb, 1, time.Second) 5292 waitForOutboundGateways(t, sa1, 1, time.Second) 5293 waitForInboundGateways(t, sa1, 1, time.Second) 5294 5295 // Now start another server in cluster "A". This will allow us 5296 // to test the reply from cluster "B" coming back directly to 5297 // the server where the request originates, and indirectly through 5298 // route. 5299 oa2 := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5300 oa2.Accounts = []*Account{NewAccount("ACC")} 5301 oa2.Users = []*User{{Username: "user", Password: "pwd", Account: oa2.Accounts[0]}} 5302 oa2.Routes = RoutesFromStr(fmt.Sprintf("nats://%s:%d", oa1.Cluster.Host, oa1.Cluster.Port)) 5303 sa2 := runGatewayServer(oa2) 5304 defer sa2.Shutdown() 5305 5306 waitForOutboundGateways(t, sa2, 1, time.Second) 5307 waitForInboundGateways(t, sb, 2, time.Second) 5308 checkClusterFormed(t, sa1, sa2) 5309 5310 // Setup a responder on sb 5311 ncb := natsConnect(t, fmt.Sprintf("nats://user:pwd@%s:%d", ob.Host, ob.Port)) 5312 defer ncb.Close() 5313 sbReplySubj := "sbreply" 5314 subSB := natsSubSync(t, ncb, sbReplySubj) 5315 natsSub(t, ncb, "foo", func(m *nats.Msg) { 5316 ncb.PublishRequest(m.Reply, sbReplySubj, []byte("sb reply")) 5317 }) 5318 natsFlush(t, ncb) 5319 checkExpectedSubs(t, 2, sb) 5320 5321 testReqReply := func(t *testing.T, host string, port int) { 5322 t.Helper() 5323 nca := natsConnect(t, fmt.Sprintf("nats://user:pwd@%s:%d", host, port)) 5324 defer nca.Close() 5325 msg, err := nca.Request("foo", []byte("sa request"), time.Second) 5326 if err != nil { 5327 t.Fatalf("Did not get response: %v", err) 5328 } 5329 // Check response from sb, it should have content "sb reply" and 5330 // reply subject should not have GW prefix 5331 if string(msg.Data) != "sb reply" || msg.Reply != sbReplySubj { 5332 t.Fatalf("Unexpected message from sb: %+v", msg) 5333 } 5334 // Now send our own reply: 5335 nca.Publish(msg.Reply, []byte("sa reply")) 5336 // And make sure that subS2 receives it... 5337 msg = natsNexMsg(t, subSB, time.Second) 5338 if string(msg.Data) != "sa reply" || msg.Reply != _EMPTY_ { 5339 t.Fatalf("Unexpected message from sa: %v", msg) 5340 } 5341 } 5342 // Create requestor on sa1 to check for direct reply from GW: 5343 testReqReply(t, oa1.Host, oa1.Port) 5344 // Now from sa2 to see reply coming from route (sa1) 5345 testReqReply(t, oa2.Host, oa2.Port) 5346 } 5347 5348 // Similar to TestGatewaySendReplyAcrossGateways, but this time 5349 // with service import. 5350 func TestGatewaySendReplyAcrossGatewaysServiceImport(t *testing.T) { 5351 ob := testDefaultOptionsForGateway("B") 5352 setAccountUserPassInOptions(ob, "$foo", "clientBFoo", "password") 5353 setAccountUserPassInOptions(ob, "$bar", "clientBBar", "password") 5354 sb := runGatewayServer(ob) 5355 defer sb.Shutdown() 5356 5357 oa1 := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5358 oa1.Cluster.PoolSize = 1 5359 setAccountUserPassInOptions(oa1, "$foo", "clientAFoo", "password") 5360 setAccountUserPassInOptions(oa1, "$bar", "clientABar", "password") 5361 sa1 := runGatewayServer(oa1) 5362 defer sa1.Shutdown() 5363 5364 waitForOutboundGateways(t, sb, 1, time.Second) 5365 waitForInboundGateways(t, sb, 1, time.Second) 5366 waitForOutboundGateways(t, sa1, 1, time.Second) 5367 waitForInboundGateways(t, sa1, 1, time.Second) 5368 5369 oa2 := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5370 oa2.Cluster.PoolSize = 1 5371 setAccountUserPassInOptions(oa2, "$foo", "clientAFoo", "password") 5372 setAccountUserPassInOptions(oa2, "$bar", "clientABar", "password") 5373 oa2.Routes = RoutesFromStr(fmt.Sprintf("nats://%s:%d", oa1.Cluster.Host, oa1.Cluster.Port)) 5374 sa2 := runGatewayServer(oa2) 5375 defer sa2.Shutdown() 5376 5377 oa3 := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5378 oa3.Cluster.PoolSize = 1 5379 setAccountUserPassInOptions(oa3, "$foo", "clientAFoo", "password") 5380 setAccountUserPassInOptions(oa3, "$bar", "clientABar", "password") 5381 oa3.Routes = RoutesFromStr(fmt.Sprintf("nats://%s:%d", oa1.Cluster.Host, oa1.Cluster.Port)) 5382 sa3 := runGatewayServer(oa3) 5383 defer sa3.Shutdown() 5384 5385 waitForOutboundGateways(t, sa2, 1, time.Second) 5386 waitForOutboundGateways(t, sa3, 1, time.Second) 5387 waitForInboundGateways(t, sb, 3, time.Second) 5388 checkClusterFormed(t, sa1, sa2, sa3) 5389 5390 // Setup account on B 5391 fooB, _ := sb.LookupAccount("$foo") 5392 // Add in the service export for the requests. Make it public. 5393 fooB.AddServiceExport("foo.request", nil) 5394 5395 // Setup accounts on sa1, sa2 and sa3 5396 setupAccsOnA := func(s *Server) { 5397 // Get accounts 5398 fooA, _ := s.LookupAccount("$foo") 5399 barA, _ := s.LookupAccount("$bar") 5400 // Add in the service export for the requests. Make it public. 5401 fooA.AddServiceExport("foo.request", nil) 5402 // Add import abilities to server A's bar account from foo. 5403 if err := barA.AddServiceImport(fooA, "bar.request", "foo.request"); err != nil { 5404 t.Fatalf("Error adding service import: %v", err) 5405 } 5406 } 5407 setupAccsOnA(sa1) 5408 setupAccsOnA(sa2) 5409 setupAccsOnA(sa3) 5410 5411 // clientB will be connected to sb and be the service endpoint and responder. 5412 bURL := fmt.Sprintf("nats://clientBFoo:password@127.0.0.1:%d", ob.Port) 5413 clientBFoo := natsConnect(t, bURL) 5414 defer clientBFoo.Close() 5415 subBFoo := natsSubSync(t, clientBFoo, "foo.request") 5416 natsFlush(t, clientBFoo) 5417 5418 // Create another client on B for account $bar that will listen to 5419 // the reply subject. 5420 bURL = fmt.Sprintf("nats://clientBBar:password@127.0.0.1:%d", ob.Port) 5421 clientBBar := natsConnect(t, bURL) 5422 defer clientBBar.Close() 5423 replySubj := "reply" 5424 subBReply := natsSubSync(t, clientBBar, replySubj) 5425 natsFlush(t, clientBBar) 5426 5427 testServiceImport := func(t *testing.T, host string, port int) { 5428 t.Helper() 5429 bURL := fmt.Sprintf("nats://clientABar:password@%s:%d", host, port) 5430 clientABar := natsConnect(t, bURL) 5431 defer clientABar.Close() 5432 subAReply := natsSubSync(t, clientABar, replySubj) 5433 natsFlush(t, clientABar) 5434 5435 // Send the request from clientA on bar.request, which 5436 // will be translated to foo.request and sent over. 5437 natsPubReq(t, clientABar, "bar.request", replySubj, []byte("hi")) 5438 natsFlush(t, clientABar) 5439 5440 // Expect the request to be received on subAFoo 5441 msg, err := subBFoo.NextMsg(time.Second) 5442 if err != nil { 5443 t.Fatalf("subBFoo failed to get request: %v", err) 5444 } 5445 if msg.Subject != "foo.request" || string(msg.Data) != "hi" { 5446 t.Fatalf("Unexpected message: %v", msg) 5447 } 5448 if msg.Reply == replySubj { 5449 t.Fatalf("Expected randomized reply, but got original") 5450 } 5451 5452 // Check for duplicate message 5453 if msg, err := subBFoo.NextMsg(100 * time.Millisecond); err != nats.ErrTimeout { 5454 t.Fatalf("Unexpected msg: %v", msg) 5455 } 5456 5457 // Send reply 5458 natsPub(t, clientBFoo, msg.Reply, []byte("ok-42")) 5459 natsFlush(t, clientBFoo) 5460 5461 // Now check that the subscription on the reply receives the message... 5462 checkReply := func(t *testing.T, sub *nats.Subscription) { 5463 t.Helper() 5464 msg, err = sub.NextMsg(time.Second) 5465 if err != nil { 5466 t.Fatalf("sub failed to get reply: %v", err) 5467 } 5468 if msg.Subject != replySubj || string(msg.Data) != "ok-42" { 5469 t.Fatalf("Unexpected message: %v", msg) 5470 } 5471 } 5472 // Check subscription on A (where the request originated) 5473 checkReply(t, subAReply) 5474 // And the subscription on B (where the responder is located) 5475 checkReply(t, subBReply) 5476 } 5477 5478 // We check the service import with GW working ok with either 5479 // direct connection between the responder's server to the 5480 // requestor's server and also through routes. 5481 testServiceImport(t, oa1.Host, oa1.Port) 5482 testServiceImport(t, oa2.Host, oa2.Port) 5483 // sa1 is the one receiving the reply from GW between B and A. 5484 // Check that the server routes directly to the the server 5485 // with the interest. 5486 checkRoute := func(t *testing.T, s *Server, expected int64) { 5487 t.Helper() 5488 s.mu.Lock() 5489 defer s.mu.Unlock() 5490 s.forEachRoute(func(r *client) { 5491 r.mu.Lock() 5492 if r.route.remoteID != sa1.ID() { 5493 r.mu.Unlock() 5494 return 5495 } 5496 inMsgs := atomic.LoadInt64(&r.inMsgs) 5497 r.mu.Unlock() 5498 if inMsgs != expected { 5499 t.Fatalf("Expected %v incoming msgs, got %v", expected, inMsgs) 5500 } 5501 }) 5502 } 5503 // Wait a bit to make sure that we don't have a loop that 5504 // cause messages to be routed more than needed. 5505 time.Sleep(100 * time.Millisecond) 5506 checkRoute(t, sa2, 1) 5507 checkRoute(t, sa3, 0) 5508 5509 testServiceImport(t, oa3.Host, oa3.Port) 5510 // Wait a bit to make sure that we don't have a loop that 5511 // cause messages to be routed more than needed. 5512 time.Sleep(100 * time.Millisecond) 5513 checkRoute(t, sa2, 1) 5514 checkRoute(t, sa3, 1) 5515 } 5516 5517 func TestGatewayClientsDontReceiveMsgsOnGWPrefix(t *testing.T) { 5518 ob := testDefaultOptionsForGateway("B") 5519 sb := runGatewayServer(ob) 5520 defer sb.Shutdown() 5521 5522 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5523 sa := runGatewayServer(oa) 5524 defer sa.Shutdown() 5525 5526 waitForOutboundGateways(t, sa, 1, time.Second) 5527 waitForInboundGateways(t, sa, 1, time.Second) 5528 waitForOutboundGateways(t, sb, 1, time.Second) 5529 waitForInboundGateways(t, sb, 1, time.Second) 5530 5531 // Setup a responder on sb 5532 ncb := natsConnect(t, fmt.Sprintf("nats://%s:%d", ob.Host, ob.Port)) 5533 defer ncb.Close() 5534 natsSub(t, ncb, "foo", func(m *nats.Msg) { 5535 if strings.HasPrefix(m.Reply, gwReplyPrefix) { 5536 m.Respond([]byte(fmt.Sprintf("-ERR: received request with mapped reply subject %q", m.Reply))) 5537 } else { 5538 m.Respond([]byte("+OK: reply")) 5539 } 5540 }) 5541 // And create a sub on ">" that should not get the $GR reply. 5542 subSB := natsSubSync(t, ncb, ">") 5543 natsFlush(t, ncb) 5544 checkExpectedSubs(t, 2, sb) 5545 5546 nca := natsConnect(t, fmt.Sprintf("nats://%s:%d", oa.Host, oa.Port)) 5547 defer nca.Close() 5548 msg, err := nca.Request("foo", []byte("request"), time.Second) 5549 if err != nil { 5550 t.Fatalf("Did not get response: %v", err) 5551 } 5552 if string(msg.Data) != "+OK: reply" { 5553 t.Fatalf("Error from responder: %q", msg.Data) 5554 } 5555 5556 // subSB would have also received the request, so drop that one. 5557 msg = natsNexMsg(t, subSB, time.Second) 5558 if string(msg.Data) != "request" { 5559 t.Fatalf("Wrong request: %q", msg.Data) 5560 } 5561 // Once sa gets the direct reply, it should resend the reply 5562 // with normal subject. So subSB should get the message with 5563 // a subject that does not start with $GNR prefix. 5564 msg = natsNexMsg(t, subSB, time.Second) 5565 if string(msg.Data) != "+OK: reply" || strings.HasPrefix(msg.Subject, gwReplyPrefix) { 5566 t.Fatalf("Unexpected message from sa: %v", msg) 5567 } 5568 // Check no more message... 5569 if m, err := subSB.NextMsg(100 * time.Millisecond); m != nil || err == nil { 5570 t.Fatalf("Expected only 1 message, got %+v", m) 5571 } 5572 } 5573 5574 func TestGatewayNoAccInterestThenQSubThenRegularSub(t *testing.T) { 5575 GatewayDoNotForceInterestOnlyMode(true) 5576 defer GatewayDoNotForceInterestOnlyMode(false) 5577 5578 ob := testDefaultOptionsForGateway("B") 5579 sb := runGatewayServer(ob) 5580 defer sb.Shutdown() 5581 5582 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5583 sa := runGatewayServer(oa) 5584 defer sa.Shutdown() 5585 5586 waitForOutboundGateways(t, sa, 1, time.Second) 5587 waitForInboundGateways(t, sa, 1, time.Second) 5588 waitForOutboundGateways(t, sb, 1, time.Second) 5589 waitForInboundGateways(t, sb, 1, time.Second) 5590 5591 // Connect on A and send a message 5592 ncA := natsConnect(t, fmt.Sprintf("nats://%s:%d", oa.Host, oa.Port)) 5593 defer ncA.Close() 5594 natsPub(t, ncA, "foo", []byte("hello")) 5595 natsFlush(t, ncA) 5596 5597 // expect an A- on return 5598 gwb := sa.getOutboundGatewayConnection("B") 5599 checkForAccountNoInterest(t, gwb, globalAccountName, true, time.Second) 5600 5601 // Create a connection o B, and create a queue sub first 5602 ncB := natsConnect(t, fmt.Sprintf("nats://%s:%d", ob.Host, ob.Port)) 5603 defer ncB.Close() 5604 qsub := natsQueueSubSync(t, ncB, "bar", "queue") 5605 natsFlush(t, ncB) 5606 5607 // A should have received a queue interest 5608 checkForRegisteredQSubInterest(t, sa, "B", globalAccountName, "bar", 1, time.Second) 5609 5610 // Now on B, create a regular sub 5611 sub := natsSubSync(t, ncB, "baz") 5612 natsFlush(t, ncB) 5613 5614 // From A now, produce a message on each subject and 5615 // expect both subs to receive their message. 5616 msgForQSub := []byte("msg_qsub") 5617 natsPub(t, ncA, "bar", msgForQSub) 5618 natsFlush(t, ncA) 5619 5620 if msg := natsNexMsg(t, qsub, time.Second); !bytes.Equal(msgForQSub, msg.Data) { 5621 t.Fatalf("Expected msg for queue sub to be %q, got %q", msgForQSub, msg.Data) 5622 } 5623 5624 // Publish for the regular sub 5625 msgForSub := []byte("msg_sub") 5626 natsPub(t, ncA, "baz", msgForSub) 5627 natsFlush(t, ncA) 5628 5629 if msg := natsNexMsg(t, sub, time.Second); !bytes.Equal(msgForSub, msg.Data) { 5630 t.Fatalf("Expected msg for sub to be %q, got %q", msgForSub, msg.Data) 5631 } 5632 } 5633 5634 // Similar to TestGatewayNoAccInterestThenQSubThenRegularSub but simulate 5635 // older incorrect behavior. 5636 func TestGatewayHandleUnexpectedASubUnsub(t *testing.T) { 5637 GatewayDoNotForceInterestOnlyMode(true) 5638 defer GatewayDoNotForceInterestOnlyMode(false) 5639 5640 ob := testDefaultOptionsForGateway("B") 5641 sb := runGatewayServer(ob) 5642 defer sb.Shutdown() 5643 5644 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5645 sa := runGatewayServer(oa) 5646 defer sa.Shutdown() 5647 5648 waitForOutboundGateways(t, sa, 1, time.Second) 5649 waitForInboundGateways(t, sa, 1, time.Second) 5650 waitForOutboundGateways(t, sb, 1, time.Second) 5651 waitForInboundGateways(t, sb, 1, time.Second) 5652 5653 // Connect on A and send a message 5654 ncA := natsConnect(t, fmt.Sprintf("nats://%s:%d", oa.Host, oa.Port)) 5655 defer ncA.Close() 5656 natsPub(t, ncA, "foo", []byte("hello")) 5657 natsFlush(t, ncA) 5658 5659 // expect an A- on return 5660 gwb := sa.getOutboundGatewayConnection("B") 5661 checkForAccountNoInterest(t, gwb, globalAccountName, true, time.Second) 5662 5663 // Create a connection o B, and create a queue sub first 5664 ncB := natsConnect(t, fmt.Sprintf("nats://%s:%d", ob.Host, ob.Port)) 5665 defer ncB.Close() 5666 qsub := natsQueueSubSync(t, ncB, "bar", "queue") 5667 natsFlush(t, ncB) 5668 5669 // A should have received a queue interest 5670 checkForRegisteredQSubInterest(t, sa, "B", globalAccountName, "bar", 1, time.Second) 5671 5672 // Now on B, create a regular sub 5673 sub := natsSubSync(t, ncB, "baz") 5674 natsFlush(t, ncB) 5675 // and reproduce old, wrong, behavior that would have resulted in sending an A- 5676 gwA := getInboundGatewayConnection(sb, "A") 5677 gwA.mu.Lock() 5678 gwA.enqueueProto([]byte("A- $G\r\n")) 5679 gwA.mu.Unlock() 5680 5681 // From A now, produce a message on each subject and 5682 // expect both subs to receive their message. 5683 msgForQSub := []byte("msg_qsub") 5684 natsPub(t, ncA, "bar", msgForQSub) 5685 natsFlush(t, ncA) 5686 5687 if msg := natsNexMsg(t, qsub, time.Second); !bytes.Equal(msgForQSub, msg.Data) { 5688 t.Fatalf("Expected msg for queue sub to be %q, got %q", msgForQSub, msg.Data) 5689 } 5690 5691 // Publish for the regular sub 5692 msgForSub := []byte("msg_sub") 5693 natsPub(t, ncA, "baz", msgForSub) 5694 natsFlush(t, ncA) 5695 5696 if msg := natsNexMsg(t, sub, time.Second); !bytes.Equal(msgForSub, msg.Data) { 5697 t.Fatalf("Expected msg for sub to be %q, got %q", msgForSub, msg.Data) 5698 } 5699 5700 // Remove all subs on B. 5701 qsub.Unsubscribe() 5702 sub.Unsubscribe() 5703 ncB.Flush() 5704 5705 // Produce a message from A expect A- 5706 natsPub(t, ncA, "foo", []byte("hello")) 5707 natsFlush(t, ncA) 5708 5709 // expect an A- on return 5710 checkForAccountNoInterest(t, gwb, globalAccountName, true, time.Second) 5711 5712 // Simulate B sending another A-, on A account no interest should remain same. 5713 gwA.mu.Lock() 5714 gwA.enqueueProto([]byte("A- $G\r\n")) 5715 gwA.mu.Unlock() 5716 5717 checkForAccountNoInterest(t, gwb, globalAccountName, true, time.Second) 5718 5719 // Create a queue sub on B 5720 qsub = natsQueueSubSync(t, ncB, "bar", "queue") 5721 natsFlush(t, ncB) 5722 5723 checkForRegisteredQSubInterest(t, sa, "B", globalAccountName, "bar", 1, time.Second) 5724 5725 // Make B send an A+ and verify that we sitll have the registered qsub interest 5726 gwA.mu.Lock() 5727 gwA.enqueueProto([]byte("A+ $G\r\n")) 5728 gwA.mu.Unlock() 5729 5730 // Give a chance to A to possibly misbehave when receiving this proto 5731 time.Sleep(250 * time.Millisecond) 5732 // Now check interest is still there 5733 checkForRegisteredQSubInterest(t, sa, "B", globalAccountName, "bar", 1, time.Second) 5734 5735 qsub.Unsubscribe() 5736 natsFlush(t, ncB) 5737 checkForRegisteredQSubInterest(t, sa, "B", globalAccountName, "bar", 0, time.Second) 5738 5739 // Send A-, server A should set entry to nil 5740 gwA.mu.Lock() 5741 gwA.enqueueProto([]byte("A- $G\r\n")) 5742 gwA.mu.Unlock() 5743 checkForAccountNoInterest(t, gwb, globalAccountName, true, time.Second) 5744 5745 // Send A+ and entry should be removed since there is no longer reason to 5746 // keep the entry. 5747 gwA.mu.Lock() 5748 gwA.enqueueProto([]byte("A+ $G\r\n")) 5749 gwA.mu.Unlock() 5750 checkForAccountNoInterest(t, gwb, globalAccountName, false, time.Second) 5751 5752 // Last A+ should not change because account already removed from map. 5753 gwA.mu.Lock() 5754 gwA.enqueueProto([]byte("A+ $G\r\n")) 5755 gwA.mu.Unlock() 5756 checkForAccountNoInterest(t, gwb, globalAccountName, false, time.Second) 5757 } 5758 5759 type captureGWInterestSwitchLogger struct { 5760 DummyLogger 5761 imss []string 5762 } 5763 5764 func (l *captureGWInterestSwitchLogger) Debugf(format string, args ...interface{}) { 5765 l.Lock() 5766 msg := fmt.Sprintf(format, args...) 5767 if strings.Contains(msg, fmt.Sprintf("switching account %q to %s mode", globalAccountName, InterestOnly)) || 5768 strings.Contains(msg, fmt.Sprintf("switching account %q to %s mode complete", globalAccountName, InterestOnly)) { 5769 l.imss = append(l.imss, msg) 5770 } 5771 l.Unlock() 5772 } 5773 5774 func TestGatewayLogAccountInterestModeSwitch(t *testing.T) { 5775 GatewayDoNotForceInterestOnlyMode(true) 5776 defer GatewayDoNotForceInterestOnlyMode(false) 5777 5778 ob := testDefaultOptionsForGateway("B") 5779 sb := runGatewayServer(ob) 5780 defer sb.Shutdown() 5781 5782 logB := &captureGWInterestSwitchLogger{} 5783 sb.SetLogger(logB, true, true) 5784 5785 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5786 sa := runGatewayServer(oa) 5787 defer sa.Shutdown() 5788 5789 logA := &captureGWInterestSwitchLogger{} 5790 sa.SetLogger(logA, true, true) 5791 5792 waitForOutboundGateways(t, sa, 1, 2*time.Second) 5793 waitForInboundGateways(t, sa, 1, 2*time.Second) 5794 waitForOutboundGateways(t, sb, 1, 2*time.Second) 5795 waitForInboundGateways(t, sb, 1, 2*time.Second) 5796 5797 ncB := natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", ob.Port)) 5798 defer ncB.Close() 5799 natsSubSync(t, ncB, "foo") 5800 natsFlush(t, ncB) 5801 5802 ncA := natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", oa.Port)) 5803 defer ncA.Close() 5804 for i := 0; i < gatewayMaxRUnsubBeforeSwitch+10; i++ { 5805 subj := fmt.Sprintf("bar.%d", i) 5806 natsPub(t, ncA, subj, []byte("hello")) 5807 } 5808 natsFlush(t, ncA) 5809 5810 gwA := getInboundGatewayConnection(sb, "A") 5811 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 5812 mode := Optimistic 5813 gwA.mu.Lock() 5814 e := gwA.gw.insim[globalAccountName] 5815 if e != nil { 5816 mode = e.mode 5817 } 5818 gwA.mu.Unlock() 5819 if mode != InterestOnly { 5820 return fmt.Errorf("not switched yet") 5821 } 5822 return nil 5823 }) 5824 5825 checkGWInterestOnlyMode(t, sa, "B", globalAccountName) 5826 5827 checkLog := func(t *testing.T, l *captureGWInterestSwitchLogger) { 5828 t.Helper() 5829 l.Lock() 5830 logs := append([]string(nil), l.imss...) 5831 l.Unlock() 5832 5833 if len(logs) != 2 { 5834 t.Fatalf("Expected 2 logs about switching to interest-only, got %v", logs) 5835 } 5836 if !strings.Contains(logs[0], "switching account") { 5837 t.Fatalf("First log statement should have been about switching, got %v", logs[0]) 5838 } 5839 if !strings.Contains(logs[1], "complete") { 5840 t.Fatalf("Second log statement should have been about having switched, got %v", logs[1]) 5841 } 5842 } 5843 checkLog(t, logB) 5844 checkLog(t, logA) 5845 5846 // Clear log of server B 5847 logB.Lock() 5848 logB.imss = nil 5849 logB.Unlock() 5850 5851 // Force a switch on B to inbound gateway from A and make sure that it is 5852 // a no-op since this gateway connection has already been switched. 5853 sb.switchAccountToInterestMode(globalAccountName) 5854 5855 logB.Lock() 5856 didSwitch := len(logB.imss) > 0 5857 logB.Unlock() 5858 if didSwitch { 5859 t.Fatalf("Attempted to switch while it was already in interest mode only") 5860 } 5861 } 5862 5863 func TestGatewayAccountInterestModeSwitchOnlyOncePerAccount(t *testing.T) { 5864 GatewayDoNotForceInterestOnlyMode(true) 5865 defer GatewayDoNotForceInterestOnlyMode(false) 5866 5867 ob := testDefaultOptionsForGateway("B") 5868 sb := runGatewayServer(ob) 5869 defer sb.Shutdown() 5870 5871 logB := &captureGWInterestSwitchLogger{} 5872 sb.SetLogger(logB, true, true) 5873 5874 nc := natsConnect(t, sb.ClientURL()) 5875 defer nc.Close() 5876 natsSubSync(t, nc, "foo") 5877 natsQueueSubSync(t, nc, "bar", "baz") 5878 5879 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5880 sa := runGatewayServer(oa) 5881 defer sa.Shutdown() 5882 5883 waitForOutboundGateways(t, sa, 1, 2*time.Second) 5884 waitForInboundGateways(t, sa, 1, 2*time.Second) 5885 waitForOutboundGateways(t, sb, 1, 2*time.Second) 5886 waitForInboundGateways(t, sb, 1, 2*time.Second) 5887 5888 wg := sync.WaitGroup{} 5889 total := 20 5890 wg.Add(total) 5891 for i := 0; i < total; i++ { 5892 go func() { 5893 sb.switchAccountToInterestMode(globalAccountName) 5894 wg.Done() 5895 }() 5896 } 5897 wg.Wait() 5898 time.Sleep(50 * time.Millisecond) 5899 logB.Lock() 5900 nl := len(logB.imss) 5901 logB.Unlock() 5902 // There should be a trace for switching and when switch is complete 5903 if nl != 2 { 5904 t.Fatalf("Attempted to switch account too many times, number lines=%v", nl) 5905 } 5906 } 5907 5908 func TestGatewaySingleOutbound(t *testing.T) { 5909 l, err := natsListen("tcp", "127.0.0.1:0") 5910 if err != nil { 5911 t.Fatalf("Error on listen: %v", err) 5912 } 5913 defer l.Close() 5914 port := l.Addr().(*net.TCPAddr).Port 5915 5916 oa := testGatewayOptionsFromToWithTLS(t, "A", "B", []string{fmt.Sprintf("nats://127.0.0.1:%d", port)}) 5917 oa.Gateway.TLSTimeout = 0.1 5918 sa := runGatewayServer(oa) 5919 defer sa.Shutdown() 5920 5921 // Wait a bit for reconnections 5922 time.Sleep(500 * time.Millisecond) 5923 5924 // Now prepare gateway B to take place of the bare listener. 5925 ob := testGatewayOptionsWithTLS(t, "B") 5926 // There is a risk that when stopping the listener and starting 5927 // the actual server, that port is being reused by some other process. 5928 ob.Gateway.Port = port 5929 l.Close() 5930 sb := runGatewayServer(ob) 5931 defer sb.Shutdown() 5932 5933 // To make sure that we don't fail, bump the TLSTimeout now. 5934 cfg := sa.getRemoteGateway("B") 5935 cfg.Lock() 5936 cfg.TLSTimeout = 2.0 5937 cfg.Unlock() 5938 5939 waitForOutboundGateways(t, sa, 1, time.Second) 5940 sa.gateway.Lock() 5941 lm := len(sa.gateway.out) 5942 sa.gateway.Unlock() 5943 if lm != 1 { 5944 t.Fatalf("Expected 1 outbound, got %v", lm) 5945 } 5946 } 5947 5948 func TestGatewayReplyMapTracking(t *testing.T) { 5949 // Increase the recSubExp value on servers so we have time 5950 // to check the replies mapping structures. 5951 subExp := 400 * time.Millisecond 5952 setRecSub := func(s *Server) { 5953 s.gateway.pasi.Lock() 5954 s.gateway.recSubExp = subExp 5955 s.gateway.pasi.Unlock() 5956 } 5957 5958 ob := testDefaultOptionsForGateway("B") 5959 sb := runGatewayServer(ob) 5960 defer sb.Shutdown() 5961 setRecSub(sb) 5962 5963 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 5964 sa := runGatewayServer(oa) 5965 defer sa.Shutdown() 5966 setRecSub(sa) 5967 5968 waitForOutboundGateways(t, sa, 1, 2*time.Second) 5969 waitForInboundGateways(t, sa, 1, 2*time.Second) 5970 waitForOutboundGateways(t, sb, 1, 2*time.Second) 5971 waitForInboundGateways(t, sb, 1, 2*time.Second) 5972 5973 ncb := natsConnect(t, sb.ClientURL()) 5974 defer ncb.Close() 5975 count := 0 5976 total := 100 5977 ch := make(chan bool, 1) 5978 natsSub(t, ncb, "foo", func(m *nats.Msg) { 5979 m.Respond([]byte("reply")) 5980 if count++; count == total { 5981 ch <- true 5982 } 5983 }) 5984 natsFlush(t, ncb) 5985 5986 var bc *client 5987 sb.mu.Lock() 5988 for _, c := range sb.clients { 5989 bc = c 5990 break 5991 } 5992 sb.mu.Unlock() 5993 5994 nca := natsConnect(t, sa.ClientURL()) 5995 defer nca.Close() 5996 5997 replySub := natsSubSync(t, nca, "bar.>") 5998 for i := 0; i < total; i++ { 5999 nca.PublishRequest("foo", fmt.Sprintf("bar.%d", i), []byte("request")) 6000 } 6001 6002 waitCh(t, ch, "Did not receive all requests") 6003 6004 check := func(t *testing.T, expectedIndicator int32, expectLenMap int, expectedSrvMapEmpty bool) { 6005 t.Helper() 6006 bc.mu.Lock() 6007 mapIndicator := atomic.LoadInt32(&bc.gwReplyMapping.check) 6008 var lenMap int 6009 if bc.gwReplyMapping.mapping != nil { 6010 lenMap = len(bc.gwReplyMapping.mapping) 6011 } 6012 bc.mu.Unlock() 6013 if mapIndicator != expectedIndicator { 6014 t.Fatalf("Client should map indicator should be %v, got %v", expectedIndicator, mapIndicator) 6015 } 6016 if lenMap != expectLenMap { 6017 t.Fatalf("Client map should have %v entries, got %v", expectLenMap, lenMap) 6018 } 6019 srvMapEmpty := true 6020 sb.gwrm.m.Range(func(_, _ interface{}) bool { 6021 srvMapEmpty = false 6022 return false 6023 }) 6024 if srvMapEmpty != expectedSrvMapEmpty { 6025 t.Fatalf("Expected server map to be empty=%v, got %v", expectedSrvMapEmpty, srvMapEmpty) 6026 } 6027 } 6028 // Check that indicator is set and that there "total" entries in the map 6029 // and that srv map is not empty 6030 check(t, 1, total, false) 6031 6032 // Receive all replies 6033 for i := 0; i < total; i++ { 6034 natsNexMsg(t, replySub, time.Second) 6035 } 6036 6037 // Wait until entries expire 6038 time.Sleep(2*subExp + 100*time.Millisecond) 6039 6040 // Now check again. 6041 check(t, 0, 0, true) 6042 } 6043 6044 func TestGatewayNoAccountUnsubWhenServiceReplyInUse(t *testing.T) { 6045 oa := testDefaultOptionsForGateway("A") 6046 setAccountUserPassInOptions(oa, "$foo", "clientFoo", "password") 6047 setAccountUserPassInOptions(oa, "$bar", "clientBar", "password") 6048 sa := runGatewayServer(oa) 6049 defer sa.Shutdown() 6050 6051 ob := testGatewayOptionsFromToWithServers(t, "B", "A", sa) 6052 setAccountUserPassInOptions(ob, "$foo", "clientFoo", "password") 6053 setAccountUserPassInOptions(ob, "$bar", "clientBar", "password") 6054 sb := runGatewayServer(ob) 6055 defer sb.Shutdown() 6056 6057 waitForOutboundGateways(t, sa, 1, time.Second) 6058 waitForOutboundGateways(t, sb, 1, time.Second) 6059 waitForInboundGateways(t, sa, 1, time.Second) 6060 waitForInboundGateways(t, sb, 1, time.Second) 6061 6062 // Get accounts 6063 fooA, _ := sa.LookupAccount("$foo") 6064 barA, _ := sa.LookupAccount("$bar") 6065 fooB, _ := sb.LookupAccount("$foo") 6066 barB, _ := sb.LookupAccount("$bar") 6067 6068 // Add in the service export for the requests. Make it public. 6069 fooA.AddServiceExport("test.request", nil) 6070 fooB.AddServiceExport("test.request", nil) 6071 6072 // Add import abilities to server B's bar account from foo. 6073 if err := barB.AddServiceImport(fooB, "foo.request", "test.request"); err != nil { 6074 t.Fatalf("Error adding service import: %v", err) 6075 } 6076 // Same on A. 6077 if err := barA.AddServiceImport(fooA, "foo.request", "test.request"); err != nil { 6078 t.Fatalf("Error adding service import: %v", err) 6079 } 6080 6081 // clientA will be connected to srvA and be the service endpoint and responder. 6082 aURL := fmt.Sprintf("nats://clientFoo:password@127.0.0.1:%d", oa.Port) 6083 clientA := natsConnect(t, aURL) 6084 defer clientA.Close() 6085 6086 natsSub(t, clientA, "test.request", func(m *nats.Msg) { 6087 m.Respond([]byte("reply")) 6088 }) 6089 natsFlush(t, clientA) 6090 6091 // Now setup client B on srvB who will send the requests. 6092 bURL := fmt.Sprintf("nats://clientBar:password@127.0.0.1:%d", ob.Port) 6093 clientB := natsConnect(t, bURL) 6094 defer clientB.Close() 6095 6096 if _, err := clientB.Request("foo.request", []byte("request"), time.Second); err != nil { 6097 t.Fatalf("Did not get the reply: %v", err) 6098 } 6099 6100 quitCh := make(chan bool, 1) 6101 wg := sync.WaitGroup{} 6102 wg.Add(1) 6103 go func() { 6104 defer wg.Done() 6105 6106 for { 6107 select { 6108 case <-quitCh: 6109 return 6110 default: 6111 clientA.Publish("any.subject", []byte("any message")) 6112 time.Sleep(time.Millisecond) 6113 } 6114 } 6115 }() 6116 for i := 0; i < 1000; i++ { 6117 if _, err := clientB.Request("foo.request", []byte("request"), time.Second); err != nil { 6118 t.Fatalf("Did not get the reply: %v", err) 6119 } 6120 } 6121 close(quitCh) 6122 wg.Wait() 6123 } 6124 6125 func TestGatewayCloseTLSConnection(t *testing.T) { 6126 oa := testGatewayOptionsWithTLS(t, "A") 6127 oa.DisableShortFirstPing = true 6128 oa.Gateway.TLSConfig.ClientAuth = tls.NoClientCert 6129 oa.Gateway.TLSTimeout = 100 6130 sa := runGatewayServer(oa) 6131 defer sa.Shutdown() 6132 6133 ob1 := testGatewayOptionsFromToWithTLS(t, "B", "A", []string{fmt.Sprintf("nats://127.0.0.1:%d", sa.GatewayAddr().Port)}) 6134 sb1 := runGatewayServer(ob1) 6135 defer sb1.Shutdown() 6136 6137 waitForOutboundGateways(t, sa, 1, 2*time.Second) 6138 waitForInboundGateways(t, sa, 1, 2*time.Second) 6139 waitForOutboundGateways(t, sb1, 1, 2*time.Second) 6140 waitForInboundGateways(t, sb1, 1, 2*time.Second) 6141 6142 endpoint := fmt.Sprintf("%s:%d", oa.Gateway.Host, oa.Gateway.Port) 6143 conn, err := net.DialTimeout("tcp", endpoint, 2*time.Second) 6144 if err != nil { 6145 t.Fatalf("Unexpected error on dial: %v", err) 6146 } 6147 defer conn.Close() 6148 6149 tlsConn := tls.Client(conn, &tls.Config{InsecureSkipVerify: true}) 6150 defer tlsConn.Close() 6151 if err := tlsConn.Handshake(); err != nil { 6152 t.Fatalf("Unexpected error during handshake: %v", err) 6153 } 6154 connectOp := []byte("CONNECT {\"name\":\"serverID\",\"verbose\":false,\"pedantic\":false,\"tls_required\":true,\"gateway\":\"B\"}\r\n") 6155 if _, err := tlsConn.Write(connectOp); err != nil { 6156 t.Fatalf("Unexpected error writing CONNECT: %v", err) 6157 } 6158 infoOp := []byte("INFO {\"server_id\":\"serverID\",\"tls_required\":true,\"gateway\":\"B\",\"gateway_nrp\":true}\r\n") 6159 if _, err := tlsConn.Write(infoOp); err != nil { 6160 t.Fatalf("Unexpected error writing CONNECT: %v", err) 6161 } 6162 if _, err := tlsConn.Write([]byte("PING\r\n")); err != nil { 6163 t.Fatalf("Unexpected error writing PING: %v", err) 6164 } 6165 6166 // Get gw connection 6167 var gw *client 6168 checkFor(t, time.Second, 15*time.Millisecond, func() error { 6169 sa.gateway.RLock() 6170 for _, g := range sa.gateway.in { 6171 g.mu.Lock() 6172 if g.opts.Name == "serverID" { 6173 gw = g 6174 } 6175 g.mu.Unlock() 6176 break 6177 } 6178 sa.gateway.RUnlock() 6179 if gw == nil { 6180 return fmt.Errorf("No gw registered yet") 6181 } 6182 return nil 6183 }) 6184 // Fill the buffer. We want to timeout on write so that nc.Close() 6185 // would block due to a write that cannot complete. 6186 buf := make([]byte, 64*1024) 6187 done := false 6188 for !done { 6189 gw.nc.SetWriteDeadline(time.Now().Add(time.Second)) 6190 if _, err := gw.nc.Write(buf); err != nil { 6191 done = true 6192 } 6193 gw.nc.SetWriteDeadline(time.Time{}) 6194 } 6195 ch := make(chan bool) 6196 go func() { 6197 select { 6198 case <-ch: 6199 return 6200 case <-time.After(3 * time.Second): 6201 fmt.Println("!!!! closeConnection is blocked, test will hang !!!") 6202 return 6203 } 6204 }() 6205 // Close the gateway 6206 gw.closeConnection(SlowConsumerWriteDeadline) 6207 ch <- true 6208 } 6209 6210 func TestGatewayNoCrashOnInvalidSubject(t *testing.T) { 6211 ob := testDefaultOptionsForGateway("B") 6212 sb := runGatewayServer(ob) 6213 defer sb.Shutdown() 6214 6215 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 6216 sa := runGatewayServer(oa) 6217 defer sa.Shutdown() 6218 6219 waitForOutboundGateways(t, sa, 1, 2*time.Second) 6220 waitForInboundGateways(t, sa, 1, 2*time.Second) 6221 waitForOutboundGateways(t, sb, 1, 2*time.Second) 6222 waitForInboundGateways(t, sb, 1, 2*time.Second) 6223 6224 ncB := natsConnect(t, sb.ClientURL()) 6225 defer ncB.Close() 6226 6227 natsSubSync(t, ncB, "foo") 6228 natsFlush(t, ncB) 6229 6230 ncA := natsConnect(t, sa.ClientURL()) 6231 defer ncA.Close() 6232 6233 // Send on an invalid subject. Since there is interest on B, 6234 // we will receive an RS- instead of A- 6235 natsPub(t, ncA, "bar..baz", []byte("bad subject")) 6236 natsFlush(t, ncA) 6237 6238 // Now create on B a sub on a wildcard subject 6239 sub := natsSubSync(t, ncB, "bar.*") 6240 natsFlush(t, ncB) 6241 6242 // Server should not have crashed... 6243 natsPub(t, ncA, "bar.baz", []byte("valid subject")) 6244 if _, err := sub.NextMsg(time.Second); err != nil { 6245 t.Fatalf("Error getting message: %v", err) 6246 } 6247 } 6248 6249 func TestGatewayUpdateURLsFromRemoteCluster(t *testing.T) { 6250 ob1 := testDefaultOptionsForGateway("B") 6251 sb1 := RunServer(ob1) 6252 defer sb1.Shutdown() 6253 6254 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb1) 6255 sa := RunServer(oa) 6256 defer sa.Shutdown() 6257 6258 waitForOutboundGateways(t, sa, 1, 2*time.Second) 6259 waitForOutboundGateways(t, sb1, 1, 2*time.Second) 6260 6261 // Add a server to cluster B. 6262 ob2 := testDefaultOptionsForGateway("B") 6263 ob2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", ob1.Cluster.Port)) 6264 sb2 := RunServer(ob2) 6265 defer sb2.Shutdown() 6266 6267 checkClusterFormed(t, sb1, sb2) 6268 waitForOutboundGateways(t, sb2, 1, 2*time.Second) 6269 waitForInboundGateways(t, sa, 2, 2*time.Second) 6270 6271 pmap := make(map[int]string) 6272 pmap[ob1.Gateway.Port] = "B1" 6273 pmap[ob2.Gateway.Port] = "B2" 6274 6275 checkURLs := func(eurls map[string]string) { 6276 t.Helper() 6277 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 6278 rg := sa.getRemoteGateway("B") 6279 urls := rg.getURLsAsStrings() 6280 for _, u := range urls { 6281 if _, ok := eurls[u]; !ok { 6282 _, sport, _ := net.SplitHostPort(u) 6283 port, _ := strconv.Atoi(sport) 6284 return fmt.Errorf("URL %q (%s) should not be in the list of urls (%q)", u, pmap[port], eurls) 6285 } 6286 } 6287 return nil 6288 }) 6289 } 6290 expected := make(map[string]string) 6291 expected[fmt.Sprintf("127.0.0.1:%d", ob1.Gateway.Port)] = "B1" 6292 expected[fmt.Sprintf("127.0.0.1:%d", ob2.Gateway.Port)] = "B2" 6293 checkURLs(expected) 6294 6295 // Add another in cluster B 6296 ob3 := testDefaultOptionsForGateway("B") 6297 ob3.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", ob1.Cluster.Port)) 6298 sb3 := RunServer(ob3) 6299 defer sb3.Shutdown() 6300 6301 checkClusterFormed(t, sb1, sb2, sb3) 6302 waitForOutboundGateways(t, sb3, 1, 2*time.Second) 6303 waitForInboundGateways(t, sa, 3, 2*time.Second) 6304 6305 pmap[ob3.Gateway.Port] = "B3" 6306 6307 expected = make(map[string]string) 6308 expected[fmt.Sprintf("127.0.0.1:%d", ob1.Gateway.Port)] = "B1" 6309 expected[fmt.Sprintf("127.0.0.1:%d", ob2.Gateway.Port)] = "B2" 6310 expected[fmt.Sprintf("127.0.0.1:%d", ob3.Gateway.Port)] = "B3" 6311 checkURLs(expected) 6312 6313 // Now stop server SB2, which should cause SA to remove it from its list. 6314 sb2.Shutdown() 6315 6316 expected = make(map[string]string) 6317 expected[fmt.Sprintf("127.0.0.1:%d", ob1.Gateway.Port)] = "B1" 6318 expected[fmt.Sprintf("127.0.0.1:%d", ob3.Gateway.Port)] = "B3" 6319 checkURLs(expected) 6320 } 6321 6322 type capturePingConn struct { 6323 net.Conn 6324 ch chan struct{} 6325 } 6326 6327 func (c *capturePingConn) Write(b []byte) (int, error) { 6328 if bytes.Contains(b, []byte(pingProto)) { 6329 select { 6330 case c.ch <- struct{}{}: 6331 default: 6332 } 6333 } 6334 return c.Conn.Write(b) 6335 } 6336 6337 func TestGatewayPings(t *testing.T) { 6338 gatewayMaxPingInterval = 50 * time.Millisecond 6339 defer func() { gatewayMaxPingInterval = gwMaxPingInterval }() 6340 6341 ob := testDefaultOptionsForGateway("B") 6342 sb := RunServer(ob) 6343 defer sb.Shutdown() 6344 6345 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 6346 sa := RunServer(oa) 6347 defer sa.Shutdown() 6348 6349 waitForInboundGateways(t, sa, 1, 2*time.Second) 6350 waitForOutboundGateways(t, sa, 1, 2*time.Second) 6351 waitForInboundGateways(t, sb, 1, 2*time.Second) 6352 waitForOutboundGateways(t, sb, 1, 2*time.Second) 6353 6354 c := sa.getOutboundGatewayConnection("B") 6355 ch := make(chan struct{}, 1) 6356 c.mu.Lock() 6357 c.nc = &capturePingConn{c.nc, ch} 6358 c.mu.Unlock() 6359 6360 for i := 0; i < 5; i++ { 6361 select { 6362 case <-ch: 6363 case <-time.After(250 * time.Millisecond): 6364 t.Fatalf("Did not send PING") 6365 } 6366 } 6367 } 6368 6369 func TestGatewayTLSConfigReload(t *testing.T) { 6370 template := ` 6371 listen: 127.0.0.1:-1 6372 gateway { 6373 name: "A" 6374 listen: "127.0.0.1:-1" 6375 tls { 6376 cert_file: "../test/configs/certs/server-cert.pem" 6377 key_file: "../test/configs/certs/server-key.pem" 6378 %s 6379 timeout: 2 6380 } 6381 } 6382 ` 6383 confA := createConfFile(t, []byte(fmt.Sprintf(template, ""))) 6384 6385 srvA, optsA := RunServerWithConfig(confA) 6386 defer srvA.Shutdown() 6387 6388 optsB := testGatewayOptionsFromToWithTLS(t, "B", "A", []string{fmt.Sprintf("nats://127.0.0.1:%d", optsA.Gateway.Port)}) 6389 srvB := runGatewayServer(optsB) 6390 defer srvB.Shutdown() 6391 6392 waitForGatewayFailedConnect(t, srvB, "A", true, time.Second) 6393 6394 reloadUpdateConfig(t, srvA, confA, fmt.Sprintf(template, `ca_file: "../test/configs/certs/ca.pem"`)) 6395 6396 waitForInboundGateways(t, srvA, 1, time.Second) 6397 waitForOutboundGateways(t, srvA, 1, time.Second) 6398 waitForInboundGateways(t, srvB, 1, time.Second) 6399 waitForOutboundGateways(t, srvB, 1, time.Second) 6400 } 6401 6402 func TestGatewayTLSConfigReloadForRemote(t *testing.T) { 6403 SetGatewaysSolicitDelay(5 * time.Millisecond) 6404 defer ResetGatewaysSolicitDelay() 6405 6406 optsA := testGatewayOptionsWithTLS(t, "A") 6407 srvA := runGatewayServer(optsA) 6408 defer srvA.Shutdown() 6409 6410 template := ` 6411 listen: 127.0.0.1:-1 6412 gateway { 6413 name: "B" 6414 listen: "127.0.0.1:-1" 6415 tls { 6416 cert_file: "../test/configs/certs/server-cert.pem" 6417 key_file: "../test/configs/certs/server-key.pem" 6418 ca_file: "../test/configs/certs/ca.pem" 6419 timeout: 2 6420 } 6421 gateways [ 6422 { 6423 name: "A" 6424 url: "nats://127.0.0.1:%d" 6425 tls { 6426 cert_file: "../test/configs/certs/server-cert.pem" 6427 key_file: "../test/configs/certs/server-key.pem" 6428 %s 6429 timeout: 2 6430 } 6431 } 6432 ] 6433 } 6434 ` 6435 confB := createConfFile(t, []byte(fmt.Sprintf(template, optsA.Gateway.Port, ""))) 6436 6437 srvB, _ := RunServerWithConfig(confB) 6438 defer srvB.Shutdown() 6439 6440 waitForGatewayFailedConnect(t, srvB, "A", true, time.Second) 6441 6442 reloadUpdateConfig(t, srvB, confB, fmt.Sprintf(template, optsA.Gateway.Port, `ca_file: "../test/configs/certs/ca.pem"`)) 6443 6444 waitForInboundGateways(t, srvA, 1, time.Second) 6445 waitForOutboundGateways(t, srvA, 1, time.Second) 6446 waitForInboundGateways(t, srvB, 1, time.Second) 6447 waitForOutboundGateways(t, srvB, 1, time.Second) 6448 } 6449 6450 func TestGatewayAuthDiscovered(t *testing.T) { 6451 SetGatewaysSolicitDelay(5 * time.Millisecond) 6452 defer ResetGatewaysSolicitDelay() 6453 6454 confA := createConfFile(t, []byte(` 6455 listen: 127.0.0.1:-1 6456 gateway { 6457 name: "A" 6458 listen: 127.0.0.1:-1 6459 authorization: { user: gwuser, password: changeme } 6460 } 6461 `)) 6462 srvA, optsA := RunServerWithConfig(confA) 6463 defer srvA.Shutdown() 6464 6465 confB := createConfFile(t, []byte(fmt.Sprintf(` 6466 listen: 127.0.0.1:-1 6467 gateway { 6468 name: "B" 6469 listen: 127.0.0.1:-1 6470 authorization: { user: gwuser, password: changeme } 6471 gateways: [ 6472 { name: A, url: nats://gwuser:changeme@127.0.0.1:%d } 6473 ] 6474 } 6475 `, optsA.Gateway.Port))) 6476 srvB, _ := RunServerWithConfig(confB) 6477 defer srvB.Shutdown() 6478 6479 waitForInboundGateways(t, srvA, 1, time.Second) 6480 waitForOutboundGateways(t, srvA, 1, time.Second) 6481 waitForInboundGateways(t, srvB, 1, time.Second) 6482 waitForOutboundGateways(t, srvB, 1, time.Second) 6483 } 6484 6485 func TestTLSGatewaysCertificateImplicitAllowPass(t *testing.T) { 6486 testTLSGatewaysCertificateImplicitAllow(t, true) 6487 } 6488 6489 func TestTLSGatewaysCertificateImplicitAllowFail(t *testing.T) { 6490 testTLSGatewaysCertificateImplicitAllow(t, false) 6491 } 6492 6493 func testTLSGatewaysCertificateImplicitAllow(t *testing.T, pass bool) { 6494 // Base config for the servers 6495 cfg := createTempFile(t, "cfg") 6496 cfg.WriteString(fmt.Sprintf(` 6497 gateway { 6498 tls { 6499 cert_file = "../test/configs/certs/tlsauth/server.pem" 6500 key_file = "../test/configs/certs/tlsauth/server-key.pem" 6501 ca_file = "../test/configs/certs/tlsauth/ca.pem" 6502 verify_cert_and_check_known_urls = true 6503 insecure = %t 6504 timeout = 1 6505 } 6506 } 6507 `, !pass)) // set insecure to skip verification on the outgoing end 6508 if err := cfg.Sync(); err != nil { 6509 t.Fatal(err) 6510 } 6511 cfg.Close() 6512 6513 optsA := LoadConfig(cfg.Name()) 6514 optsB := LoadConfig(cfg.Name()) 6515 6516 urlA := "nats://localhost:9995" 6517 urlB := "nats://localhost:9996" 6518 if !pass { 6519 urlA = "nats://127.0.0.1:9995" 6520 urlB = "nats://127.0.0.1:9996" 6521 } 6522 6523 gwA, err := url.Parse(urlA) 6524 if err != nil { 6525 t.Fatal(err) 6526 } 6527 gwB, err := url.Parse(urlB) 6528 if err != nil { 6529 t.Fatal(err) 6530 } 6531 6532 optsA.Host = "127.0.0.1" 6533 optsA.Port = -1 6534 optsA.Gateway.Name = "A" 6535 optsA.Gateway.Port = 9995 6536 optsA.Gateway.resolver = &localhostResolver{} 6537 6538 optsB.Host = "127.0.0.1" 6539 optsB.Port = -1 6540 optsB.Gateway.Name = "B" 6541 optsB.Gateway.Port = 9996 6542 optsB.Gateway.resolver = &localhostResolver{} 6543 6544 gateways := make([]*RemoteGatewayOpts, 2) 6545 gateways[0] = &RemoteGatewayOpts{ 6546 Name: optsA.Gateway.Name, 6547 URLs: []*url.URL{gwA}, 6548 } 6549 gateways[1] = &RemoteGatewayOpts{ 6550 Name: optsB.Gateway.Name, 6551 URLs: []*url.URL{gwB}, 6552 } 6553 6554 optsA.Gateway.Gateways = gateways 6555 optsB.Gateway.Gateways = gateways 6556 6557 SetGatewaysSolicitDelay(100 * time.Millisecond) 6558 defer ResetGatewaysSolicitDelay() 6559 6560 srvA := RunServer(optsA) 6561 defer srvA.Shutdown() 6562 6563 srvB := RunServer(optsB) 6564 defer srvB.Shutdown() 6565 6566 if pass { 6567 waitForOutboundGateways(t, srvA, 1, 5*time.Second) 6568 waitForOutboundGateways(t, srvB, 1, 5*time.Second) 6569 } else { 6570 time.Sleep(1 * time.Second) // the fail case uses the IP, so a short wait is sufficient 6571 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 6572 if srvA.NumOutboundGateways() != 0 || srvB.NumOutboundGateways() != 0 { 6573 return fmt.Errorf("No outbound gateway connection expected") 6574 } 6575 return nil 6576 }) 6577 } 6578 } 6579 6580 func TestGatewayURLsNotRemovedOnDuplicateRoute(t *testing.T) { 6581 // For this test, we need to have servers in cluster B creating routes 6582 // to each other to help produce the "duplicate route" situation, so 6583 // we are forced to use deterministic ports. 6584 getEphemeralPort := func() int { 6585 t.Helper() 6586 l, err := net.Listen("tcp", "127.0.0.1:0") 6587 if err != nil { 6588 t.Fatalf("Error getting a port: %v", err) 6589 } 6590 p := l.Addr().(*net.TCPAddr).Port 6591 l.Close() 6592 return p 6593 } 6594 p1 := getEphemeralPort() 6595 p2 := getEphemeralPort() 6596 routeURLs := fmt.Sprintf("nats://127.0.0.1:%d,nats://127.0.0.1:%d", p1, p2) 6597 6598 ob1 := testDefaultOptionsForGateway("B") 6599 ob1.Cluster.Port = p1 6600 ob1.Routes = RoutesFromStr(routeURLs) 6601 sb1 := RunServer(ob1) 6602 defer sb1.Shutdown() 6603 6604 ob2 := testDefaultOptionsForGateway("B") 6605 ob2.Cluster.Port = p2 6606 ob2.Routes = RoutesFromStr(routeURLs) 6607 sb2 := RunServer(ob2) 6608 defer sb2.Shutdown() 6609 6610 checkClusterFormed(t, sb1, sb2) 6611 6612 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb1) 6613 sa := RunServer(oa) 6614 defer sa.Shutdown() 6615 6616 waitForOutboundGateways(t, sb1, 1, 2*time.Second) 6617 waitForOutboundGateways(t, sb2, 1, 2*time.Second) 6618 waitForOutboundGateways(t, sa, 1, 2*time.Second) 6619 waitForInboundGateways(t, sa, 2, 2*time.Second) 6620 6621 checkURLs := func(s *Server) { 6622 t.Helper() 6623 s.mu.Lock() 6624 urls := s.gateway.URLs.getAsStringSlice() 6625 s.mu.Unlock() 6626 if len(urls) != 2 { 6627 t.Fatalf("Expected 2 urls, got %v", urls) 6628 } 6629 } 6630 checkURLs(sb1) 6631 checkURLs(sb2) 6632 6633 // As for sa, we should have both sb1 and sb2 urls in its outbound urls map 6634 c := sa.getOutboundGatewayConnection("B") 6635 if c == nil { 6636 t.Fatal("No outound connection found!") 6637 } 6638 c.mu.Lock() 6639 urls := c.gw.cfg.urls 6640 c.mu.Unlock() 6641 if len(urls) != 2 { 6642 t.Fatalf("Expected 2 urls to B, got %v", urls) 6643 } 6644 } 6645 6646 func TestGatewayDuplicateServerName(t *testing.T) { 6647 // We will have 2 servers per cluster names "nats1" and "nats2", and have 6648 // the servers in the second cluster with the same name, but we will make 6649 // sure to connect "A/nats1" to "B/nats2" and "A/nats2" to "B/nats1" and 6650 // verify that we still discover the duplicate names. 6651 ob1 := testDefaultOptionsForGateway("B") 6652 ob1.ServerName = "nats1" 6653 sb1 := RunServer(ob1) 6654 defer sb1.Shutdown() 6655 6656 ob2 := testDefaultOptionsForGateway("B") 6657 ob2.ServerName = "nats2" 6658 ob2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", ob1.Cluster.Port)) 6659 sb2 := RunServer(ob2) 6660 defer sb2.Shutdown() 6661 6662 checkClusterFormed(t, sb1, sb2) 6663 6664 oa1 := testGatewayOptionsFromToWithServers(t, "A", "B", sb2) 6665 oa1.ServerName = "nats1" 6666 // Needed later in the test 6667 oa1.Gateway.RejectUnknown = true 6668 sa1 := RunServer(oa1) 6669 defer sa1.Shutdown() 6670 sa1l := &captureErrorLogger{errCh: make(chan string, 100)} 6671 sa1.SetLogger(sa1l, false, false) 6672 6673 oa2 := testGatewayOptionsFromToWithServers(t, "A", "B", sb1) 6674 oa2.ServerName = "nats2" 6675 // Needed later in the test 6676 oa2.Gateway.RejectUnknown = true 6677 oa2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", oa1.Cluster.Port)) 6678 sa2 := RunServer(oa2) 6679 defer sa2.Shutdown() 6680 sa2l := &captureErrorLogger{errCh: make(chan string, 100)} 6681 sa2.SetLogger(sa2l, false, false) 6682 6683 checkClusterFormed(t, sa1, sa2) 6684 6685 checkForDupError := func(errCh chan string) { 6686 t.Helper() 6687 timeout := time.NewTimer(time.Second) 6688 for done := false; !done; { 6689 select { 6690 case err := <-errCh: 6691 if strings.Contains(err, "server has a duplicate name") { 6692 done = true 6693 } 6694 case <-timeout.C: 6695 t.Fatal("Did not get error about servers in super-cluster with same name") 6696 } 6697 } 6698 } 6699 6700 // Since only servers from "A" have configured outbound to 6701 // cluster "B", only servers on "A" are expected to report error. 6702 for _, errCh := range []chan string{sa1l.errCh, sa2l.errCh} { 6703 checkForDupError(errCh) 6704 } 6705 6706 // So now we are going to fix names and wait for the super cluster to form. 6707 sa2.Shutdown() 6708 sa1.Shutdown() 6709 6710 // Drain the error channels 6711 for _, errCh := range []chan string{sa1l.errCh, sa2l.errCh} { 6712 for done := false; !done; { 6713 select { 6714 case <-errCh: 6715 default: 6716 done = true 6717 } 6718 } 6719 } 6720 6721 oa1.ServerName = "a_nats1" 6722 oa2.ServerName = "a_nats2" 6723 sa1 = RunServer(oa1) 6724 defer sa1.Shutdown() 6725 sa2 = RunServer(oa2) 6726 defer sa2.Shutdown() 6727 6728 checkClusterFormed(t, sa1, sa2) 6729 6730 waitForOutboundGateways(t, sa1, 1, 2*time.Second) 6731 waitForOutboundGateways(t, sa2, 1, 2*time.Second) 6732 waitForOutboundGateways(t, sb1, 1, 2*time.Second) 6733 waitForOutboundGateways(t, sb2, 1, 2*time.Second) 6734 6735 // Now add a server on cluster B (that does not have outbound 6736 // gateway connections explicitly defined) and use the name 6737 // of one of the cluster A's server. We should get an error. 6738 ob3 := testDefaultOptionsForGateway("B") 6739 ob3.ServerName = "a_nats2" 6740 ob3.Accounts = []*Account{NewAccount("sys")} 6741 ob3.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", ob2.Cluster.Port)) 6742 sb3 := RunServer(ob3) 6743 defer sb3.Shutdown() 6744 sb3l := &captureErrorLogger{errCh: make(chan string, 100)} 6745 sb3.SetLogger(sb3l, false, false) 6746 6747 checkClusterFormed(t, sb1, sb2, sb3) 6748 6749 // It should report the error when trying to create the GW connection 6750 checkForDupError(sb3l.errCh) 6751 6752 // Stop this node 6753 sb3.Shutdown() 6754 checkClusterFormed(t, sb1, sb2) 6755 6756 // Now create a GW "C" with a server that uses the same name than one of 6757 // the server on "A", say "a_nats2". 6758 // This server will connect to "B", and "B" will gossip "A" back to "C" 6759 // and "C" will then try to connect to "A", but "A" rejects unknown, so 6760 // connection will be refused. However, we want to make sure that the 6761 // duplicate server name is still detected. 6762 oc := testGatewayOptionsFromToWithServers(t, "C", "B", sb1) 6763 oc.ServerName = "a_nats2" 6764 oc.Accounts = []*Account{NewAccount("sys")} 6765 sc := RunServer(oc) 6766 defer sc.Shutdown() 6767 scl := &captureErrorLogger{errCh: make(chan string, 100)} 6768 sc.SetLogger(scl, false, false) 6769 6770 // It should report the error when trying to create the GW connection 6771 // to cluster "A" 6772 checkForDupError(scl.errCh) 6773 } 6774 6775 func TestGatewayNoPanicOnStartupWithMonitoring(t *testing.T) { 6776 o := testDefaultOptionsForGateway("B") 6777 o.HTTPHost = "127.0.0.1" 6778 o.HTTPPort = 8888 6779 s, err := NewServer(o) 6780 require_NoError(t, err) 6781 6782 wg := sync.WaitGroup{} 6783 wg.Add(1) 6784 go func() { 6785 defer wg.Done() 6786 6787 time.Sleep(50 * time.Millisecond) 6788 s.Start() 6789 s.WaitForShutdown() 6790 }() 6791 6792 for { 6793 g, err := s.Gatewayz(nil) 6794 if err != nil { 6795 continue 6796 } 6797 if g.Port != 0 && g.Port != s.GatewayAddr().Port { 6798 t.Fatalf("Unexpected port: %v vs %v", g.Port, s.GatewayAddr().Port) 6799 } 6800 break 6801 } 6802 s.Shutdown() 6803 wg.Wait() 6804 } 6805 6806 func TestGatewaySwitchToInterestOnlyModeImmediately(t *testing.T) { 6807 o2 := testDefaultOptionsForGateway("B") 6808 // Add users to cause s2 to require auth. Will add an account with user later. 6809 o2.Users = append([]*User(nil), &User{Username: "test", Password: "pwd"}) 6810 s2 := runGatewayServer(o2) 6811 defer s2.Shutdown() 6812 6813 o1 := testGatewayOptionsFromToWithServers(t, "A", "B", s2) 6814 setAccountUserPassInOptions(o1, "$foo", "ivan", "password") 6815 s1 := runGatewayServer(o1) 6816 defer s1.Shutdown() 6817 6818 waitForOutboundGateways(t, s1, 1, time.Second) 6819 waitForOutboundGateways(t, s2, 1, time.Second) 6820 6821 s1Url := fmt.Sprintf("nats://ivan:password@127.0.0.1:%d", o1.Port) 6822 nc := natsConnect(t, s1Url) 6823 defer nc.Close() 6824 natsPub(t, nc, "foo", []byte("hello")) 6825 natsFlush(t, nc) 6826 6827 checkCount := func(t *testing.T, c *client, expected int) { 6828 t.Helper() 6829 c.mu.Lock() 6830 out := c.outMsgs 6831 c.mu.Unlock() 6832 if int(out) != expected { 6833 t.Fatalf("Expected %d message(s) to be sent over, got %v", expected, out) 6834 } 6835 } 6836 // No message should be sent 6837 gwcb := s1.getOutboundGatewayConnection("B") 6838 checkCount(t, gwcb, 0) 6839 6840 // Check that we are in interest-only mode, but in this case, since s2 does 6841 // have the account, we should have the account not even present in the map. 6842 checkGWInterestOnlyModeOrNotPresent(t, s1, "B", "$foo", true) 6843 6844 // Add account to S2 and a client. 6845 s2FooAcc, err := s2.RegisterAccount("$foo") 6846 if err != nil { 6847 t.Fatalf("Error registering account: %v", err) 6848 } 6849 s2.mu.Lock() 6850 s2.users["ivan"] = &User{Account: s2FooAcc, Username: "ivan", Password: "password"} 6851 s2.mu.Unlock() 6852 s2Url := fmt.Sprintf("nats://ivan:password@127.0.0.1:%d", o2.Port) 6853 ncS2 := natsConnect(t, s2Url) 6854 defer ncS2.Close() 6855 natsSubSync(t, ncS2, "asub") 6856 // This time we will have the account in the map and it will be interest-only 6857 checkGWInterestOnlyMode(t, s1, "B", "$foo") 6858 6859 // Now publish a message, still should not go because the sub is on "asub" 6860 natsPub(t, nc, "foo", []byte("hello")) 6861 natsFlush(t, nc) 6862 checkCount(t, gwcb, 0) 6863 6864 natsSubSync(t, ncS2, "foo") 6865 natsFlush(t, ncS2) 6866 6867 checkGWInterestOnlyModeInterestOn(t, s1, "B", "$foo", "foo") 6868 6869 // Publish on foo 6870 natsPub(t, nc, "foo", []byte("hello")) 6871 natsFlush(t, nc) 6872 checkCount(t, gwcb, 1) 6873 } 6874 6875 func TestGatewaySlowConsumer(t *testing.T) { 6876 gatewayMaxPingInterval = 50 * time.Millisecond 6877 defer func() { gatewayMaxPingInterval = gwMaxPingInterval }() 6878 6879 ob := testDefaultOptionsForGateway("B") 6880 sb := RunServer(ob) 6881 defer sb.Shutdown() 6882 6883 oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb) 6884 sa := RunServer(oa) 6885 defer sa.Shutdown() 6886 6887 waitForInboundGateways(t, sa, 1, 2*time.Second) 6888 waitForOutboundGateways(t, sa, 1, 2*time.Second) 6889 waitForInboundGateways(t, sb, 1, 2*time.Second) 6890 waitForOutboundGateways(t, sb, 1, 2*time.Second) 6891 6892 c := sa.getOutboundGatewayConnection("B") 6893 c.mu.Lock() 6894 c.out.wdl = time.Nanosecond 6895 c.mu.Unlock() 6896 6897 <-time.After(250 * time.Millisecond) 6898 got := sa.NumSlowConsumersGateways() 6899 expected := uint64(1) 6900 if got != 1 { 6901 t.Errorf("got: %d, expected: %d", got, expected) 6902 } 6903 got = sb.NumSlowConsumersGateways() 6904 expected = 0 6905 if got != expected { 6906 t.Errorf("got: %d, expected: %d", got, expected) 6907 } 6908 }