(b []byte, addr string)
| 512 | } |
| 513 | |
| 514 | func (t *TCPTransport) writeTo(b []byte, addr string) error { |
| 515 | // Open connection, write packet header and data, data hash, close. Simple. |
| 516 | c, err := t.getConnection(addr, t.cfg.PacketDialTimeout) |
| 517 | if err != nil { |
| 518 | return err |
| 519 | } |
| 520 | |
| 521 | closed := false |
| 522 | defer func() { |
| 523 | if !closed { |
| 524 | // If we still need to close, then there was another error. Ignore this one. |
| 525 | _ = c.Close() |
| 526 | } |
| 527 | }() |
| 528 | |
| 529 | // Compute the digest *before* setting the deadline on the connection (so that the time |
| 530 | // it takes to compute the digest is not taken in account). |
| 531 | // We use md5 as quick and relatively short hash, not in cryptographic context. |
| 532 | // It's also used to detect if the whole packet has been received on the receiver side. |
| 533 | digest := md5.Sum(b) |
| 534 | |
| 535 | // Prepare the header *before* setting the deadline on the connection. |
| 536 | headerBuf := bytes.Buffer{} |
| 537 | headerBuf.WriteByte(byte(packet)) |
| 538 | |
| 539 | // We need to send our address to the other side, otherwise other side can only see IP and port from TCP header. |
| 540 | // But that doesn't match our node address (new TCP connection has new random port), which confuses memberlist. |
| 541 | // So we send our advertised address, so that memberlist on the receiving side can match it with correct node. |
| 542 | // This seems to be important for node probes (pings) done by memberlist. |
| 543 | ourAddr := t.getAdvertisedAddr() |
| 544 | if len(ourAddr) > 255 { |
| 545 | return fmt.Errorf("local address too long") |
| 546 | } |
| 547 | |
| 548 | headerBuf.WriteByte(byte(len(ourAddr))) |
| 549 | headerBuf.WriteString(ourAddr) |
| 550 | |
| 551 | if t.cfg.PacketWriteTimeout > 0 { |
| 552 | deadline := time.Now().Add(t.cfg.PacketWriteTimeout) |
| 553 | err := c.SetDeadline(deadline) |
| 554 | if err != nil { |
| 555 | return fmt.Errorf("setting deadline: %v", err) |
| 556 | } |
| 557 | } |
| 558 | |
| 559 | _, err = c.Write(headerBuf.Bytes()) |
| 560 | if err != nil { |
| 561 | return fmt.Errorf("sending local address: %v", err) |
| 562 | } |
| 563 | |
| 564 | n, err := c.Write(b) |
| 565 | if err != nil { |
| 566 | return fmt.Errorf("sending data: %v", err) |
| 567 | } |
| 568 | if n != len(b) { |
| 569 | return fmt.Errorf("sending data: short write") |
| 570 | } |
| 571 |
no test coverage detected