go.nanomsg.org/mangos/v3@v3.4.3-0.20240217232803-46464076f1f5/internal/test/transport.go (about) 1 // Copyright 2019 The Mangos Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use file except in compliance with the License. 5 // You may obtain a copy of the license at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package test 16 17 import ( 18 "crypto/tls" 19 "fmt" 20 "io" 21 "net" 22 "strings" 23 "sync" 24 "testing" 25 "time" 26 27 "go.nanomsg.org/mangos/v3" 28 "go.nanomsg.org/mangos/v3/transport" 29 ) 30 31 type tranOption interface { 32 SetOption(string, interface{}) error 33 GetOption(string) (interface{}, error) 34 } 35 36 func getTranPair(t *testing.T, tran transport.Transport) (mangos.Dialer, mangos.Listener, mangos.Socket, mangos.Socket) { 37 addr := getScratchAddr(tran) 38 s1 := GetMockSocket() 39 s2 := GetMockSocket() 40 d, e := s1.NewDialer(addr, nil) 41 MustSucceed(t, e) 42 MustNotBeNil(t, d) 43 l, e := s2.NewListener(addr, nil) 44 MustSucceed(t, e) 45 MustNotBeNil(t, l) 46 return d, l, s1, s2 47 } 48 49 func getScratchAddr(tran transport.Transport) string { 50 switch tran.Scheme() { 51 case "mock": 52 return "mock://mock" 53 case "inproc": 54 return AddrTestInp() 55 case "tcp": 56 return AddrTestTCP() 57 case "ipc": 58 return AddrTestIPC() 59 case "tls+tcp": 60 return AddrTestTLS() 61 case "ws": 62 return AddrTestWS() 63 case "wss": 64 return AddrTestWSS() 65 } 66 return "unknown://" 67 } 68 69 // TranVerifyBoolOption verifies that a bool option behaves properly. 70 func TranVerifyBoolOption(t *testing.T, tran transport.Transport, name string) { 71 d, l, s1, s2 := getTranPair(t, tran) 72 defer MustClose(t, s1) 73 defer MustClose(t, s2) 74 75 for _, o := range []tranOption{d, l} { 76 MustBeError(t, o.SetOption(name, "nope"), mangos.ErrBadValue) 77 MustSucceed(t, o.SetOption(name, true)) 78 MustSucceed(t, o.SetOption(name, false)) 79 v, e := o.GetOption(name) 80 MustSucceed(t, e) 81 _, ok := v.(bool) 82 MustBeTrue(t, ok) 83 } 84 } 85 86 // TranVerifyIntOption verifies that an int option behaves properly. 87 func TranVerifyIntOption(t *testing.T, tran transport.Transport, name string) { 88 d, l, s1, s2 := getTranPair(t, tran) 89 defer MustClose(t, s1) 90 defer MustClose(t, s2) 91 92 for _, o := range []tranOption{d, l} { 93 94 MustBeError(t, o.SetOption(name, "nope"), mangos.ErrBadValue) 95 MustBeError(t, o.SetOption(name, false), mangos.ErrBadValue) 96 MustSucceed(t, o.SetOption(name, 2)) 97 MustSucceed(t, o.SetOption(name, 42)) 98 v, e := o.GetOption(name) 99 MustSucceed(t, e) 100 _, ok := v.(int) 101 MustBeTrue(t, ok) 102 } 103 } 104 105 // TranVerifyDurationOption verifies that a time.Duration option behaves properly. 106 func TranVerifyDurationOption(t *testing.T, tran transport.Transport, name string) { 107 d, l, s1, s2 := getTranPair(t, tran) 108 defer MustClose(t, s1) 109 defer MustClose(t, s2) 110 111 MustBeError(t, d.SetOption(name, "nope"), mangos.ErrBadValue) 112 MustSucceed(t, d.SetOption(name, time.Second)) 113 v, e := d.GetOption(name) 114 MustSucceed(t, e) 115 _, ok := v.(time.Duration) 116 MustBeTrue(t, ok) 117 118 MustBeError(t, l.SetOption(name, false), mangos.ErrBadValue) 119 MustSucceed(t, l.SetOption(name, time.Hour)) 120 v, e = l.GetOption(name) 121 MustSucceed(t, e) 122 _, ok = v.(time.Duration) 123 MustBeTrue(t, ok) 124 } 125 126 // TranVerifyNoDelayOption verifies that NoDelay is always true. 127 func TranVerifyNoDelayOption(t *testing.T, tran transport.Transport) { 128 d, l, s1, s2 := getTranPair(t, tran) 129 defer MustClose(t, s1) 130 defer MustClose(t, s2) 131 132 name := mangos.OptionNoDelay 133 for _, o := range []tranOption{d, l} { 134 MustBeError(t, o.SetOption(name, "nope"), mangos.ErrBadValue) 135 MustSucceed(t, o.SetOption(name, true)) 136 MustSucceed(t, o.SetOption(name, false)) // But it must not work 137 v, e := o.GetOption(name) 138 MustSucceed(t, e) 139 b, ok := v.(bool) 140 MustBeTrue(t, ok) 141 MustBeTrue(t, b) 142 } 143 } 144 145 // TranVerifyKeepAliveOption verifies that keep alive options work. 146 func TranVerifyKeepAliveOption(t *testing.T, tran transport.Transport) { 147 d, l, s1, s2 := getTranPair(t, tran) 148 defer MustClose(t, s1) 149 defer MustClose(t, s2) 150 151 // First verify that the base types work 152 TranVerifyBoolOption(t, tran, mangos.OptionKeepAlive) 153 TranVerifyDurationOption(t, tran, mangos.OptionKeepAliveTime) 154 155 // Now try setting various things. 156 for _, o := range []tranOption{d, l} { 157 158 // Setting the legacy option to true 159 MustSucceed(t, o.SetOption(mangos.OptionKeepAlive, true)) 160 b, e := o.GetOption(mangos.OptionKeepAlive) 161 MustSucceed(t, e) 162 MustBeTrue(t, b.(bool)) 163 x, e := o.GetOption(mangos.OptionKeepAliveTime) 164 MustSucceed(t, e) 165 MustBeTrue(t, x.(time.Duration) >= 0) 166 167 // Setting the legacy option to false 168 MustSucceed(t, o.SetOption(mangos.OptionKeepAlive, false)) 169 b, e = o.GetOption(mangos.OptionKeepAlive) 170 MustSucceed(t, e) 171 MustBeFalse(t, b.(bool)) 172 x, e = o.GetOption(mangos.OptionKeepAliveTime) 173 MustSucceed(t, e) 174 MustBeTrue(t, x.(time.Duration) < 0) 175 176 // Setting the duration to zero (on) 177 MustSucceed(t, o.SetOption(mangos.OptionKeepAliveTime, time.Duration(0))) 178 b, e = o.GetOption(mangos.OptionKeepAlive) 179 MustSucceed(t, e) 180 MustBeTrue(t, b.(bool)) 181 182 MustSucceed(t, o.SetOption(mangos.OptionKeepAliveTime, time.Duration(-1))) 183 b, e = o.GetOption(mangos.OptionKeepAlive) 184 MustSucceed(t, e) 185 MustBeFalse(t, b.(bool)) 186 187 MustSucceed(t, o.SetOption(mangos.OptionKeepAliveTime, time.Second)) 188 b, e = o.GetOption(mangos.OptionKeepAlive) 189 MustSucceed(t, e) 190 MustBeTrue(t, b.(bool)) 191 } 192 193 } 194 195 // TranVerifyTLSConfigOption verifies that OptionTLSConfig works properly. 196 func TranVerifyTLSConfigOption(t *testing.T, tran transport.Transport) { 197 d, l, s1, s2 := getTranPair(t, tran) 198 defer MustClose(t, s1) 199 defer MustClose(t, s2) 200 201 name := mangos.OptionTLSConfig 202 203 MustBeError(t, d.SetOption(name, "nope"), mangos.ErrBadValue) 204 MustSucceed(t, d.SetOption(name, GetTLSConfig(t, false))) 205 v, e := d.GetOption(name) 206 MustSucceed(t, e) 207 _, ok := v.(*tls.Config) 208 MustBeTrue(t, ok) 209 210 MustBeError(t, l.SetOption(name, false), mangos.ErrBadValue) 211 MustSucceed(t, l.SetOption(name, GetTLSConfig(t, true))) 212 v, e = l.GetOption(name) 213 MustSucceed(t, e) 214 _, ok = v.(*tls.Config) 215 MustBeTrue(t, ok) 216 } 217 218 // TranVerifyInvalidOption verifies that an invalid option behaves properly. 219 func TranVerifyInvalidOption(t *testing.T, tran transport.Transport) { 220 d, l, s1, s2 := getTranPair(t, tran) 221 defer MustClose(t, s1) 222 defer MustClose(t, s2) 223 224 // Dialer first. 225 MustBeError(t, d.SetOption("NoSuchOption", 0), mangos.ErrBadOption) 226 _, e := d.GetOption("NoSuchOption") 227 MustBeError(t, e, mangos.ErrBadOption) 228 229 MustBeError(t, l.SetOption("NoSuchOption", 0), mangos.ErrBadOption) 230 _, e = l.GetOption("NoSuchOption") 231 MustBeError(t, e, mangos.ErrBadOption) 232 } 233 234 // TranVerifyScheme verifies that we get the right scheme. It also tries 235 // an invalid scheme. 236 func TranVerifyScheme(t *testing.T, tran transport.Transport) { 237 sock := GetMockSocket() 238 defer MustClose(t, sock) 239 d, e := tran.NewDialer("wrong://", sock) 240 MustBeError(t, e, mangos.ErrBadTran) 241 MustBeTrue(t, d == nil) 242 l, e := tran.NewListener("wrong://", sock) 243 MustBeError(t, e, mangos.ErrBadTran) 244 MustBeTrue(t, l == nil) 245 246 addr := getScratchAddr(tran) 247 d, e = tran.NewDialer(addr, sock) 248 MustSucceed(t, e) 249 MustNotBeNil(t, d) 250 251 l, e = tran.NewListener(addr, sock) 252 MustSucceed(t, e) 253 MustNotBeNil(t, l) 254 addr2 := l.Address() 255 MustBeTrue(t, strings.HasPrefix(addr2, tran.Scheme()+"://")) 256 } 257 258 // TranVerifyConnectionRefused verifies that connection is refused if no listener. 259 func TranVerifyConnectionRefused(t *testing.T, tran transport.Transport, opts map[string]interface{}) { 260 sock := GetMockSocket() 261 defer MustClose(t, sock) 262 d, _ := sock.NewDialer(getScratchAddr(tran), opts) 263 MustFail(t, d.Dial()) // Windows won't let us validate properly 264 } 265 266 // TranVerifyDuplicateListen verifies that we can't bind to the same address twice. 267 func TranVerifyDuplicateListen(t *testing.T, tran transport.Transport, opts map[string]interface{}) { 268 sock1 := GetMockSocket() 269 defer MustClose(t, sock1) 270 sock2 := GetMockSocket() 271 defer MustClose(t, sock2) 272 addr := getScratchAddr(tran) 273 l1, _ := sock1.NewListener(addr, opts) 274 l2, _ := sock2.NewListener(addr, opts) 275 MustSucceed(t, l1.Listen()) 276 MustFail(t, l2.Listen()) // Cannot validate ErrAddrInUse because Windows 277 } 278 279 // TranVerifyListenAndAccept verifies that we can establish the connection. 280 func TranVerifyListenAndAccept(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) { 281 s1 := GetMockSocket() 282 s2 := GetMockSocket() 283 defer MustClose(t, s1) 284 defer MustClose(t, s2) 285 addr := getScratchAddr(tran) 286 d, e := s1.NewDialer(addr, dOpts) 287 MustSucceed(t, e) 288 l, e := s2.NewListener(addr, lOpts) 289 MustSucceed(t, e) 290 MustSucceed(t, l.Listen()) 291 292 var wg sync.WaitGroup 293 wg.Add(1) 294 pass := false 295 go func() { 296 defer wg.Done() 297 MustSucceed(t, d.Dial()) 298 pass = true 299 }() 300 301 wg.Wait() 302 MustBeTrue(t, pass) 303 } 304 305 // TranVerifyAcceptWithoutListen verifies that we can't call accept if we 306 // did not first call listen. 307 func TranVerifyAcceptWithoutListen(t *testing.T, tran transport.Transport) { 308 sock := GetMockSocket() 309 defer MustClose(t, sock) 310 l, e := tran.NewListener(getScratchAddr(tran), sock) 311 MustSucceed(t, e) 312 _, e = l.Accept() 313 MustBeError(t, e, mangos.ErrClosed) 314 } 315 316 // TranVerifyMaxRecvSize verifies the transport handles maximum receive size properly. 317 func TranVerifyMaxRecvSize(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) { 318 VerifyOptionMaxRecvSize(t, NewMockSocket) 319 320 addr := getScratchAddr(tran) 321 tx := GetMockSocket() 322 rx := GetMockSocket() 323 defer MustClose(t, tx) 324 defer MustClose(t, rx) 325 maxRx := 100 326 327 // Now try setting the option 328 MustSucceed(t, rx.SetOption(mangos.OptionMaxRecvSize, maxRx)) 329 // At this point, we can issue requests on rq, and read them from rp. 330 MustSucceed(t, rx.SetOption(mangos.OptionRecvDeadline, time.Millisecond*50)) 331 MustSucceed(t, tx.SetOption(mangos.OptionSendDeadline, time.Second)) 332 333 ConnectPairVia(t, addr, rx, tx, lOpts, dOpts) 334 335 for i := maxRx - 2; i < maxRx+2; i++ { 336 m := mangos.NewMessage(i) 337 m.Body = append(m.Body, make([]byte, i)...) 338 MustSendMsg(t, tx, m) 339 if i <= maxRx { 340 m = MustRecvMsg(t, rx) 341 m.Free() 342 } else { 343 MustNotRecv(t, rx, mangos.ErrRecvTimeout) 344 } 345 } 346 } 347 348 // TranVerifyHandshakeFail verifies that we fail if the protocols mismatch. 349 func TranVerifyHandshakeFail(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) { 350 s1 := GetMockSocketEx(1, "mock1") 351 s2 := GetMockSocketEx(2, "mock2") 352 defer MustClose(t, s1) 353 defer MustClose(t, s2) 354 addr := getScratchAddr(tran) 355 d, e := s1.NewDialer(addr, dOpts) 356 MustSucceed(t, e) 357 l, e := s2.NewListener(addr, lOpts) 358 MustSucceed(t, e) 359 MustSucceed(t, l.Listen()) 360 361 var wg sync.WaitGroup 362 wg.Add(1) 363 pass := false 364 go func() { 365 defer wg.Done() 366 e = d.Dial() 367 MustBeError(t, e, mangos.ErrBadProto) 368 pass = true 369 }() 370 371 wg.Wait() 372 MustBeTrue(t, pass) 373 } 374 375 // TranVerifySendRecv just verifies basic send and receive. 376 func TranVerifySendRecv(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) { 377 tx := GetMockSocket() 378 rx := GetMockSocket() 379 defer MustClose(t, tx) 380 defer MustClose(t, rx) 381 382 MustSucceed(t, rx.SetOption(mangos.OptionRecvDeadline, time.Second)) 383 MustSucceed(t, tx.SetOption(mangos.OptionRecvDeadline, time.Second)) 384 MustSucceed(t, rx.SetOption(mangos.OptionSendDeadline, time.Second)) 385 MustSucceed(t, tx.SetOption(mangos.OptionSendDeadline, time.Second)) 386 387 addr := getScratchAddr(tran) 388 d, e := tx.NewDialer(addr, dOpts) 389 MustSucceed(t, e) 390 l, e := rx.NewListener(addr, lOpts) 391 MustSucceed(t, e) 392 393 MustSucceed(t, l.Listen()) 394 MustSucceed(t, d.Dial()) 395 396 for i := 0; i < 10; i++ { 397 send := fmt.Sprintf("SEND%d", i) 398 repl := fmt.Sprintf("REPL%d", i) 399 MustSendString(t, tx, send) 400 MustRecvString(t, rx, send) 401 MustSendString(t, rx, repl) 402 MustRecvString(t, tx, repl) 403 } 404 } 405 406 // TranVerifyAnonymousPort is used by TCP based transports to verify that using 407 // a wild card port address works. The addr is an address using a wild card 408 // port (usually port 0). 409 func TranVerifyAnonymousPort(t *testing.T, addr string, dOpts, lOpts map[string]interface{}) { 410 tx := GetMockSocket() 411 rx := GetMockSocket() 412 defer MustClose(t, tx) 413 defer MustClose(t, rx) 414 415 MustSucceed(t, rx.SetOption(mangos.OptionRecvDeadline, time.Second)) 416 MustSucceed(t, tx.SetOption(mangos.OptionRecvDeadline, time.Second)) 417 MustSucceed(t, rx.SetOption(mangos.OptionSendDeadline, time.Second)) 418 MustSucceed(t, tx.SetOption(mangos.OptionSendDeadline, time.Second)) 419 420 // First get the listener. 421 l, e := rx.NewListener(addr, lOpts) 422 MustSucceed(t, e) 423 MustBeTrue(t, l.Address() == addr) 424 MustSucceed(t, l.Listen()) 425 MustBeTrue(t, l.Address() != addr) 426 427 d, e := tx.NewDialer(l.Address(), dOpts) 428 MustSucceed(t, e) 429 MustSucceed(t, d.Dial()) 430 431 MustSendString(t, tx, "hello") 432 MustRecvString(t, rx, "hello") 433 434 // Impossible to dial to a wildcard address 435 d2, e := tx.NewDialer(addr, dOpts) 436 if e == nil { 437 MustFail(t, d2.Dial()) 438 } 439 } 440 441 // TranVerifyPipeOptions verifies that the LocalAddr, RemoteAddr and invalid 442 // options all behave as we expect. 443 func TranVerifyPipeOptions(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) { 444 tx := GetMockSocket() 445 rx := GetMockSocket() 446 defer MustClose(t, tx) 447 defer MustClose(t, rx) 448 449 addr := getScratchAddr(tran) 450 MustSucceed(t, rx.SetOption(mangos.OptionRecvDeadline, time.Second)) 451 MustSucceed(t, tx.SetOption(mangos.OptionRecvDeadline, time.Second)) 452 MustSucceed(t, rx.SetOption(mangos.OptionSendDeadline, time.Second)) 453 MustSucceed(t, tx.SetOption(mangos.OptionSendDeadline, time.Second)) 454 455 MustSucceed(t, rx.ListenOptions(addr, lOpts)) 456 MustSucceed(t, tx.DialOptions(addr, dOpts)) 457 458 MustSendString(t, tx, "hello") 459 m := MustRecvMsg(t, rx) 460 p1 := m.Pipe 461 462 MustSendString(t, rx, "there") 463 m = MustRecvMsg(t, tx) 464 p2 := m.Pipe 465 466 remaddr := []net.Addr{} 467 locaddr := []net.Addr{} 468 469 for _, p := range []mangos.Pipe{p1, p2} { 470 a, e := p.GetOption(mangos.OptionLocalAddr) 471 addr1 := a.(net.Addr) 472 MustSucceed(t, e) 473 MustBeTrue(t, len(addr1.Network()) > 0) 474 MustBeTrue(t, len(addr1.String()) > 0) 475 476 a, e = p.GetOption(mangos.OptionRemoteAddr) 477 addr2 := a.(net.Addr) 478 MustSucceed(t, e) 479 MustBeTrue(t, len(addr2.Network()) > 0) 480 MustBeTrue(t, len(addr2.String()) > 0) 481 482 MustBeTrue(t, addr2.Network() == addr1.Network()) 483 484 locaddr = append(locaddr, addr1) 485 remaddr = append(remaddr, addr2) 486 487 _, e = p.GetOption("NO-SUCH-OPTION") 488 MustFail(t, e) 489 } 490 MustBeTrue(t, remaddr[0].String() == locaddr[1].String()) 491 MustBeTrue(t, remaddr[1].String() == locaddr[0].String()) 492 493 } 494 495 // TranVerifyBadLocalAddress is used to verify that a given address cannot be 496 // listened to. This could be for an address that we cannot resolve a name 497 // for, or an address that we do not have an IP address for. The failure can 498 // occur at either listener allocation time, or when trying to bind. 499 func TranVerifyBadLocalAddress(t *testing.T, addr string, opts map[string]interface{}) { 500 sock := GetMockSocket() 501 defer MustClose(t, sock) 502 503 if l, e := sock.NewListener(addr, opts); e == nil { 504 MustFail(t, l.Listen()) 505 } 506 } 507 508 // TranVerifyBadRemoteAddress is used to verify that a given address cannot be 509 // dialed to. This could be for an address that we cannot resolve a name 510 // for, or an address is known to be otherwise impossible or invalid. 511 func TranVerifyBadRemoteAddress(t *testing.T, addr string, opts map[string]interface{}) { 512 sock := GetMockSocket() 513 defer MustClose(t, sock) 514 515 if d, e := sock.NewDialer(addr, opts); e == nil { 516 MustFail(t, d.Dial()) 517 } 518 } 519 520 // TranVerifyBadAddress is used to verify that certain addresses are invalid 521 // and cannot be used for dialing or listening. This is useful, for example, 522 // when checking that DNS failures are handled properly. 523 func TranVerifyBadAddress(t *testing.T, addr string, dOpts, lOpts map[string]interface{}) { 524 TranVerifyBadLocalAddress(t, addr, lOpts) 525 TranVerifyBadRemoteAddress(t, addr, dOpts) 526 } 527 528 // TranVerifyListenerClosed verifies that the listener behaves after closed. 529 func TranVerifyListenerClosed(t *testing.T, tran transport.Transport, opts map[string]interface{}) { 530 sock := GetMockSocket() 531 defer MustClose(t, sock) 532 533 l, e := tran.NewListener(getScratchAddr(tran), sock) 534 MustSucceed(t, e) 535 for key, val := range opts { 536 MustSucceed(t, l.SetOption(key, val)) 537 } 538 MustSucceed(t, l.Close()) 539 MustBeError(t, l.Listen(), mangos.ErrClosed) 540 _, e = l.Accept() 541 MustBeError(t, e, mangos.ErrClosed) 542 _ = l.Close() // this might succeed or fail, we don't care. 543 544 l, e = tran.NewListener(getScratchAddr(tran), sock) 545 MustSucceed(t, e) 546 for key, val := range opts { 547 MustSucceed(t, l.SetOption(key, val)) 548 } 549 MustSucceed(t, l.Listen()) 550 MustSucceed(t, l.Close()) 551 _, e = l.Accept() 552 MustBeError(t, e, mangos.ErrClosed) 553 554 // Now async 555 l, e = tran.NewListener(getScratchAddr(tran), sock) 556 MustSucceed(t, e) 557 for key, val := range opts { 558 MustSucceed(t, l.SetOption(key, val)) 559 } 560 MustSucceed(t, l.Listen()) 561 time.AfterFunc(time.Millisecond*50, func() { 562 MustSucceed(t, l.Close()) 563 }) 564 _, e = l.Accept() 565 MustBeError(t, e, mangos.ErrClosed) 566 } 567 568 // TranVerifyDialNoCert verifies that we fail to dial if we lack a Server cert. 569 func TranVerifyDialNoCert(t *testing.T, tran transport.Transport) { 570 sock := GetMockSocket() 571 defer MustClose(t, sock) 572 573 addr := getScratchAddr(tran) 574 opts := make(map[string]interface{}) 575 opts[mangos.OptionTLSConfig] = GetTLSConfig(t, true) 576 MustSucceed(t, sock.ListenOptions(addr, opts)) 577 578 // Unfortunately the tls package doesn't allow us to distinguish 579 // the various errors. 580 MustFail(t, sock.Dial(addr)) 581 } 582 583 // TranVerifyDialInsecure verifies InsecureSkipVerify. 584 func TranVerifyDialInsecure(t *testing.T, tran transport.Transport) { 585 sock := GetMockSocket() 586 defer MustClose(t, sock) 587 588 addr := getScratchAddr(tran) 589 opts := make(map[string]interface{}) 590 opts[mangos.OptionTLSConfig] = GetTLSConfig(t, true) 591 MustSucceed(t, sock.ListenOptions(addr, opts)) 592 593 opts = make(map[string]interface{}) 594 opts[mangos.OptionTLSConfig] = &tls.Config{} 595 MustFail(t, sock.DialOptions(addr, opts)) 596 597 opts[mangos.OptionTLSConfig] = &tls.Config{ 598 InsecureSkipVerify: true, 599 } 600 MustSucceed(t, sock.DialOptions(addr, opts)) 601 } 602 603 // TranVerifyMessageSizes verifies we can transport a variety of message sizes 604 func TranVerifyMessageSizes(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) { 605 sock1 := GetMockSocket() 606 sock2 := GetMockSocket() 607 addr := getScratchAddr(tran) 608 defer MustClose(t, sock1) 609 defer MustClose(t, sock2) 610 611 MustSucceed(t, sock1.SetOption(mangos.OptionRecvDeadline, time.Second)) 612 MustSucceed(t, sock1.SetOption(mangos.OptionSendDeadline, time.Second)) 613 MustSucceed(t, sock2.SetOption(mangos.OptionRecvDeadline, time.Second)) 614 MustSucceed(t, sock2.SetOption(mangos.OptionSendDeadline, time.Second)) 615 MustSucceed(t, sock1.ListenOptions(addr, lOpts)) 616 MustSucceed(t, sock2.DialOptions(addr, dOpts)) 617 618 for i := 0; i < 20; i++ { 619 sz := 1 << i 620 m := mangos.NewMessage(sz) 621 for j := 0; j < sz; j++ { 622 m.Body = append(m.Body, byte(i)) 623 } 624 MustSendMsg(t, sock1, m) 625 m = MustRecvMsg(t, sock2) 626 MustBeTrue(t, len(m.Body) == sz) 627 for j := 0; j < sz; j++ { 628 MustBeTrue(t, m.Body[j] == byte(i)) 629 } 630 m.Free() 631 } 632 // And back down: 633 for i := 20; i >= 0; i-- { 634 sz := 1 << i 635 m := mangos.NewMessage(sz) 636 for j := 0; j < sz; j++ { 637 m.Body = append(m.Body, byte(i)) 638 } 639 MustSendMsg(t, sock1, m) 640 m = MustRecvMsg(t, sock2) 641 MustBeTrue(t, len(m.Body) == sz) 642 for j := 0; j < sz; j++ { 643 MustBeTrue(t, m.Body[j] == byte(i)) 644 } 645 m.Free() 646 } 647 } 648 649 // TranVerifyMessageHeader verifies that message headers are transmitted. 650 func TranVerifyMessageHeader(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) { 651 sock1 := GetMockSocket() 652 sock2 := GetMockSocket() 653 addr := getScratchAddr(tran) 654 defer MustClose(t, sock1) 655 defer MustClose(t, sock2) 656 657 MustSucceed(t, sock1.SetOption(mangos.OptionRecvDeadline, time.Second)) 658 MustSucceed(t, sock1.SetOption(mangos.OptionSendDeadline, time.Second)) 659 MustSucceed(t, sock2.SetOption(mangos.OptionRecvDeadline, time.Second)) 660 MustSucceed(t, sock2.SetOption(mangos.OptionSendDeadline, time.Second)) 661 MustSucceed(t, sock1.ListenOptions(addr, lOpts)) 662 MustSucceed(t, sock2.DialOptions(addr, dOpts)) 663 664 m := mangos.NewMessage(0) 665 m.Header = append(m.Header, 'h', 'e', 'l', 'l', 'o', ',', ' ') 666 m.Body = append(m.Body, 'w', 'o', 'r', 'l', 'd') 667 MustSendMsg(t, sock1, m) 668 MustRecvString(t, sock2, "hello, world") 669 } 670 671 // TranVerifyPipeAddresses performs basic validation of pipe address options. 672 func TranVerifyPipeAddresses(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) { 673 sock1 := GetMockSocket() 674 sock2 := GetMockSocket() 675 addr := getScratchAddr(tran) 676 defer MustClose(t, sock1) 677 defer MustClose(t, sock2) 678 679 MustSucceed(t, sock1.SetOption(mangos.OptionRecvDeadline, time.Second)) 680 MustSucceed(t, sock1.SetOption(mangos.OptionSendDeadline, time.Second)) 681 MustSucceed(t, sock2.SetOption(mangos.OptionRecvDeadline, time.Second)) 682 MustSucceed(t, sock2.SetOption(mangos.OptionSendDeadline, time.Second)) 683 MustSucceed(t, sock1.ListenOptions(addr, lOpts)) 684 MustSucceed(t, sock2.DialOptions(addr, dOpts)) 685 686 m := mangos.NewMessage(0) 687 MustSendMsg(t, sock1, m) 688 m = MustRecvMsg(t, sock2) 689 p1 := m.Pipe 690 691 // Now Send it back the other way. 692 MustSendMsg(t, sock2, m) 693 m = MustRecvMsg(t, sock1) 694 p2 := m.Pipe 695 696 v, e := m.Pipe.GetOption("JUNK") 697 MustBeError(t, e, mangos.ErrBadProperty) 698 MustBeTrue(t, v == nil) 699 700 v, e = p1.GetOption(mangos.OptionLocalAddr) 701 MustSucceed(t, e) 702 la1, ok := v.(net.Addr) 703 MustBeTrue(t, ok) 704 v, e = p1.GetOption(mangos.OptionRemoteAddr) 705 MustSucceed(t, e) 706 ra1, ok := v.(net.Addr) 707 MustBeTrue(t, ok) 708 709 v, e = p2.GetOption(mangos.OptionLocalAddr) 710 MustSucceed(t, e) 711 la2, ok := v.(net.Addr) 712 MustBeTrue(t, ok) 713 v, e = p2.GetOption(mangos.OptionRemoteAddr) 714 MustSucceed(t, e) 715 ra2, ok := v.(net.Addr) 716 MustBeTrue(t, ok) 717 718 MustBeTrue(t, la1.Network() == la2.Network()) 719 MustBeTrue(t, ra1.Network() == ra2.Network()) 720 MustBeTrue(t, ra2.Network() == ra1.Network()) 721 722 MustBeTrue(t, la1.String() == ra2.String()) 723 MustBeTrue(t, la2.String() == ra1.String()) 724 725 } 726 727 // TranVerifyPipeOptions2 verifies standard pipe Options. 728 func TranVerifyPipeOptions2(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) { 729 sock1 := GetMockSocket() 730 sock2 := GetMockSocket() 731 addr := getScratchAddr(tran) 732 defer MustClose(t, sock1) 733 defer MustClose(t, sock2) 734 735 MustSucceed(t, sock1.SetOption(mangos.OptionRecvDeadline, time.Second)) 736 MustSucceed(t, sock1.SetOption(mangos.OptionSendDeadline, time.Second)) 737 MustSucceed(t, sock2.SetOption(mangos.OptionRecvDeadline, time.Second)) 738 MustSucceed(t, sock2.SetOption(mangos.OptionSendDeadline, time.Second)) 739 MustSucceed(t, sock1.ListenOptions(addr, lOpts)) 740 MustSucceed(t, sock2.DialOptions(addr, dOpts)) 741 742 m := mangos.NewMessage(0) 743 MustSendMsg(t, sock1, m) 744 m = MustRecvMsg(t, sock2) 745 v, e := m.Pipe.GetOption("JUNK") 746 MustBeError(t, e, mangos.ErrBadProperty) 747 MustBeTrue(t, v == nil) 748 749 v, e = m.Pipe.GetOption(mangos.OptionMaxRecvSize) 750 MustSucceed(t, e) 751 _, ok := v.(int) 752 MustBeTrue(t, ok) 753 } 754 755 // type connHeader struct { 756 // Zero byte // must be zero 757 // S byte // 'S' 758 // P byte // 'P' 759 // Version byte // only zero at present 760 // Proto uint16 761 // Reserved uint16 // always zero at present 762 // } 763 764 // TranSendConnBadHandshakes just sends garbage handshakes. 765 func TranSendConnBadHandshakes(t *testing.T, dial func() (net.Conn, error)) { 766 767 tries := [][]byte{ 768 {}, 769 {0}, 770 {0, 'S'}, 771 {0, 'S', 'P'}, 772 {0, 'S', 'P', 0}, 773 {0, 'S', 'P', 0, 0}, 774 {0, 'S', 'P', 0, 0, 0}, 775 {0, 'S', 'P', 0, 0, 1, 0}, 776 {0, 'S', 'P', 0, 0, 1, 0, 0}, 777 {1, 'S', 'P', 0, 0, 0, 0, 0}, 778 {0, 'x', 'P', 0, 0, 0, 0, 0}, 779 {0, 'S', 'x', 0, 0, 0, 0, 0}, 780 {0, 'S', 'P', 2, 0, 0, 0, 0}, 781 {0, 'S', 'P', 0, 0, 0, 0, 1}, 782 } 783 784 for _, b := range tries { 785 c, e := dial() 786 MustSucceed(t, e) 787 _, e = c.Write(b) 788 MustSucceed(t, e) 789 time.Sleep(time.Millisecond * 10) 790 MustSucceed(t, c.Close()) 791 } 792 } 793 794 // TranConnHandshake just performs the handshake, the conn should be connected. 795 func TranConnHandshake(t *testing.T, c net.Conn, proto uint16) { 796 hs := []byte{ 797 0, // Zero 798 'S', // S 799 'P', // P 800 0, // Version 801 byte(proto / 256), // Proto Hi byte 802 byte(proto % 256), // Proto Lo byte 803 0, // Reserved Hi 804 0, // Reserved Lo 805 } 806 peer := make([]byte, 8) 807 _, e := c.Write(hs) 808 MustSucceed(t, e) 809 _, e = io.ReadFull(c, peer) 810 MustSucceed(t, e) 811 } 812 813 // TranSendBadMessages opens new connections and sends garbage to them. 814 func TranSendBadMessages(t *testing.T, proto uint16, isipc bool, dial func() (net.Conn, error)) { 815 816 bad := [][]byte{ 817 {}, 818 {0x80}, 819 {0, 0, 0, 1}, 820 {0, 0, 0, 0, 0, 0, 0, 10, 1, 2}, 821 {0x80, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6}, 822 } 823 for _, b := range bad { 824 c, e := dial() 825 MustSucceed(t, e) 826 TranConnHandshake(t, c, proto) 827 var x []byte 828 if isipc { 829 x = append([]byte{1}, b...) 830 } else { 831 x = b 832 } 833 _, e = c.Write(x) 834 MustSucceed(t, e) 835 time.Sleep(time.Millisecond * 10) 836 MustSucceed(t, c.Close()) 837 } 838 }