(ctx context.Context, derpURL *url.URL)
| 480 | } |
| 481 | |
| 482 | func (r *NodeReport) derpClient(ctx context.Context, derpURL *url.URL) (*derphttp.Client, int, error) { |
| 483 | r.mu.Lock() |
| 484 | id := r.clientCounter |
| 485 | r.clientCounter++ |
| 486 | r.ClientLogs = append(r.ClientLogs, []string{}) |
| 487 | r.ClientErrs = append(r.ClientErrs, []string{}) |
| 488 | r.mu.Unlock() |
| 489 | |
| 490 | client, err := derphttp.NewClient(key.NewNode(), derpURL.String(), func(format string, args ...any) { |
| 491 | r.mu.Lock() |
| 492 | defer r.mu.Unlock() |
| 493 | |
| 494 | msg := fmt.Sprintf(format, args...) |
| 495 | if strings.Contains(msg, "We'll use WebSockets on the next connection attempt") { |
| 496 | r.UsesWebsocket = true |
| 497 | } |
| 498 | r.ClientLogs[id] = append(r.ClientLogs[id], msg) |
| 499 | }) |
| 500 | if err != nil { |
| 501 | err := xerrors.Errorf("create derp client: %w", err) |
| 502 | r.writeClientErr(id, err) |
| 503 | return nil, id, err |
| 504 | } |
| 505 | |
| 506 | if r.derpTLSConfig != nil { |
| 507 | client.TLSConfig = r.derpTLSConfig |
| 508 | } |
| 509 | |
| 510 | go func() { |
| 511 | <-ctx.Done() |
| 512 | _ = client.Close() |
| 513 | }() |
| 514 | |
| 515 | i := 0 |
| 516 | for ; i < 5; i++ { |
| 517 | err = client.Connect(ctx) |
| 518 | if err != nil { |
| 519 | r.writeClientErr(id, xerrors.Errorf("connect to derp: %w", err)) |
| 520 | continue |
| 521 | } |
| 522 | break |
| 523 | } |
| 524 | if i == 5 { |
| 525 | err := xerrors.Errorf("couldn't connect after 5 tries, last error: %w", err) |
| 526 | r.writeClientErr(id, xerrors.Errorf("couldn't connect after 5 tries, last error: %w", err)) |
| 527 | return nil, id, err |
| 528 | } |
| 529 | |
| 530 | return client, id, nil |
| 531 | } |
| 532 | |
| 533 | func (r *NodeReport) recvData(client *derphttp.Client) (derp.ReceivedPacket, error) { |
| 534 | for { |
no test coverage detected