Skip to content

Commit 43c9a51

Browse files
authored
[client] Migrate deprecated grpc client code (#4687)
1 parent c530db1 commit 43c9a51

File tree

8 files changed

+49
-22
lines changed

8 files changed

+49
-22
lines changed

client/grpc/dialer.go

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,25 @@ import (
44
"context"
55
"crypto/tls"
66
"crypto/x509"
7+
"errors"
8+
"fmt"
79
"runtime"
810
"time"
911

1012
"github.com/cenkalti/backoff/v4"
1113
log "github.com/sirupsen/logrus"
1214
"google.golang.org/grpc"
15+
"google.golang.org/grpc/connectivity"
1316
"google.golang.org/grpc/credentials"
1417
"google.golang.org/grpc/credentials/insecure"
1518
"google.golang.org/grpc/keepalive"
1619

1720
"github.com/netbirdio/netbird/util/embeddedroots"
1821
)
1922

23+
// ErrConnectionShutdown indicates that the connection entered shutdown state before becoming ready
24+
var ErrConnectionShutdown = errors.New("connection shutdown before ready")
25+
2026
// Backoff returns a backoff configuration for gRPC calls
2127
func Backoff(ctx context.Context) backoff.BackOff {
2228
b := backoff.NewExponentialBackOff()
@@ -25,6 +31,26 @@ func Backoff(ctx context.Context) backoff.BackOff {
2531
return backoff.WithContext(b, ctx)
2632
}
2733

34+
// waitForConnectionReady blocks until the connection becomes ready or fails.
35+
// Returns an error if the connection times out, is cancelled, or enters shutdown state.
36+
func waitForConnectionReady(ctx context.Context, conn *grpc.ClientConn) error {
37+
conn.Connect()
38+
39+
state := conn.GetState()
40+
for state != connectivity.Ready && state != connectivity.Shutdown {
41+
if !conn.WaitForStateChange(ctx, state) {
42+
return fmt.Errorf("wait state change from %s: %w", state, ctx.Err())
43+
}
44+
state = conn.GetState()
45+
}
46+
47+
if state == connectivity.Shutdown {
48+
return ErrConnectionShutdown
49+
}
50+
51+
return nil
52+
}
53+
2854
// CreateConnection creates a gRPC client connection with the appropriate transport options.
2955
// The component parameter specifies the WebSocket proxy component path (e.g., "/management", "/signal").
3056
func CreateConnection(ctx context.Context, addr string, tlsEnabled bool, component string) (*grpc.ClientConn, error) {
@@ -42,22 +68,24 @@ func CreateConnection(ctx context.Context, addr string, tlsEnabled bool, compone
4268
}))
4369
}
4470

45-
connCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
46-
defer cancel()
47-
48-
conn, err := grpc.DialContext(
49-
connCtx,
71+
conn, err := grpc.NewClient(
5072
addr,
5173
transportOption,
5274
WithCustomDialer(tlsEnabled, component),
53-
grpc.WithBlock(),
5475
grpc.WithKeepaliveParams(keepalive.ClientParameters{
5576
Time: 30 * time.Second,
5677
Timeout: 10 * time.Second,
5778
}),
5879
)
5980
if err != nil {
60-
log.Printf("DialContext error: %v", err)
81+
return nil, fmt.Errorf("new client: %w", err)
82+
}
83+
84+
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
85+
defer cancel()
86+
87+
if err := waitForConnectionReady(ctx, conn); err != nil {
88+
_ = conn.Close()
6189
return nil, err
6290
}
6391

client/grpc/dialer_generic.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
nbnet "github.com/netbirdio/netbird/client/net"
1919
)
2020

21-
func WithCustomDialer(tlsEnabled bool, component string) grpc.DialOption {
21+
func WithCustomDialer(_ bool, _ string) grpc.DialOption {
2222
return grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
2323
if runtime.GOOS == "linux" {
2424
currentUser, err := user.Current()
@@ -36,7 +36,6 @@ func WithCustomDialer(tlsEnabled bool, component string) grpc.DialOption {
3636

3737
conn, err := nbnet.NewDialer().DialContext(ctx, "tcp", addr)
3838
if err != nil {
39-
log.Errorf("Failed to dial: %s", err)
4039
return nil, fmt.Errorf("nbnet.NewDialer().DialContext: %w", err)
4140
}
4241
return conn, nil

client/net/conn.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ type Conn struct {
1717
ID hooks.ConnectionID
1818
}
1919

20-
// Close overrides the net.Conn Close method to execute all registered hooks after closing the connection
21-
// Close overrides the net.Conn Close method to execute all registered hooks before closing the connection.
20+
// Close overrides the net.Conn Close method to execute all registered hooks after closing the connection.
2221
func (c *Conn) Close() error {
2322
return closeConn(c.ID, c.Conn)
2423
}
@@ -29,21 +28,24 @@ type TCPConn struct {
2928
ID hooks.ConnectionID
3029
}
3130

32-
// Close overrides the net.TCPConn Close method to execute all registered hooks before closing the connection.
31+
// Close overrides the net.TCPConn Close method to execute all registered hooks after closing the connection.
3332
func (c *TCPConn) Close() error {
3433
return closeConn(c.ID, c.TCPConn)
3534
}
3635

3736
// closeConn is a helper function to close connections and execute close hooks.
3837
func closeConn(id hooks.ConnectionID, conn io.Closer) error {
3938
err := conn.Close()
39+
cleanupConnID(id)
40+
return err
41+
}
4042

43+
// cleanupConnID executes close hooks for a connection ID.
44+
func cleanupConnID(id hooks.ConnectionID) {
4145
closeHooks := hooks.GetCloseHooks()
4246
for _, hook := range closeHooks {
4347
if err := hook(id); err != nil {
4448
log.Errorf("Error executing close hook: %v", err)
4549
}
4650
}
47-
48-
return err
4951
}

client/net/dial.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ func DialTCP(network string, laddr, raddr *net.TCPAddr) (transport.TCPConn, erro
7474
}
7575
return &TCPConn{TCPConn: tcpConn, ID: c.ID}, nil
7676
}
77-
7877
if err := conn.Close(); err != nil {
7978
log.Errorf("failed to close connection: %v", err)
8079
}

client/net/dialer_dial.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.
3030

3131
conn, err := d.Dialer.DialContext(ctx, network, address)
3232
if err != nil {
33+
cleanupConnID(connID)
3334
return nil, fmt.Errorf("d.Dialer.DialContext: %w", err)
3435
}
3536

@@ -64,7 +65,7 @@ func callDialerHooks(ctx context.Context, connID hooks.ConnectionID, address str
6465

6566
ips, err := resolver.LookupIPAddr(ctx, host)
6667
if err != nil {
67-
return fmt.Errorf("failed to resolve address %s: %w", address, err)
68+
return fmt.Errorf("resolve address %s: %w", address, err)
6869
}
6970

7071
log.Debugf("Dialer resolved IPs for %s: %v", address, ips)

client/net/listener_listen.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func (c *PacketConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
4848
return c.PacketConn.WriteTo(b, addr)
4949
}
5050

51-
// Close overrides the net.PacketConn Close method to execute all registered hooks before closing the connection.
51+
// Close overrides the net.PacketConn Close method to execute all registered hooks after closing the connection.
5252
func (c *PacketConn) Close() error {
5353
defer c.seenAddrs.Clear()
5454
return closeConn(c.ID, c.PacketConn)
@@ -69,7 +69,7 @@ func (c *UDPConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
6969
return c.UDPConn.WriteTo(b, addr)
7070
}
7171

72-
// Close overrides the net.UDPConn Close method to execute all registered hooks before closing the connection.
72+
// Close overrides the net.UDPConn Close method to execute all registered hooks after closing the connection.
7373
func (c *UDPConn) Close() error {
7474
defer c.seenAddrs.Clear()
7575
return closeConn(c.ID, c.UDPConn)

shared/management/client/grpc.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsE
5555
var err error
5656
conn, err = nbgrpc.CreateConnection(ctx, addr, tlsEnabled, wsproxy.ManagementComponent)
5757
if err != nil {
58-
log.Printf("createConnection error: %v", err)
59-
return err
58+
return fmt.Errorf("create connection: %w", err)
6059
}
6160
return nil
6261
}

shared/signal/client/grpc.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ func NewClient(ctx context.Context, addr string, key wgtypes.Key, tlsEnabled boo
6060
var err error
6161
conn, err = nbgrpc.CreateConnection(ctx, addr, tlsEnabled, wsproxy.SignalComponent)
6262
if err != nil {
63-
log.Printf("createConnection error: %v", err)
64-
return err
63+
return fmt.Errorf("create connection: %w", err)
6564
}
6665
return nil
6766
}

0 commit comments

Comments
 (0)