You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
3.7 KiB
142 lines
3.7 KiB
// Package grpc provides a gRPC client for the relay group service. |
|
package grpc |
|
|
|
import ( |
|
"context" |
|
"time" |
|
|
|
"google.golang.org/grpc" |
|
"google.golang.org/grpc/credentials/insecure" |
|
"lol.mleku.dev/log" |
|
|
|
commonv1 "next.orly.dev/pkg/proto/orlysync/common/v1" |
|
relaygroupv1 "next.orly.dev/pkg/proto/orlysync/relaygroup/v1" |
|
) |
|
|
|
// Client is a gRPC client for the relay group service. |
|
type Client struct { |
|
conn *grpc.ClientConn |
|
client relaygroupv1.RelayGroupServiceClient |
|
ready chan struct{} |
|
} |
|
|
|
// ClientConfig holds configuration for the gRPC client. |
|
type ClientConfig struct { |
|
ServerAddress string |
|
ConnectTimeout time.Duration |
|
} |
|
|
|
// New creates a new gRPC relay group client. |
|
func New(ctx context.Context, cfg *ClientConfig) (*Client, error) { |
|
timeout := cfg.ConnectTimeout |
|
if timeout == 0 { |
|
timeout = 10 * time.Second |
|
} |
|
|
|
dialCtx, cancel := context.WithTimeout(ctx, timeout) |
|
defer cancel() |
|
|
|
conn, err := grpc.DialContext(dialCtx, cfg.ServerAddress, |
|
grpc.WithTransportCredentials(insecure.NewCredentials()), |
|
grpc.WithDefaultCallOptions( |
|
grpc.MaxCallRecvMsgSize(16<<20), // 16MB |
|
grpc.MaxCallSendMsgSize(16<<20), // 16MB |
|
), |
|
) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
c := &Client{ |
|
conn: conn, |
|
client: relaygroupv1.NewRelayGroupServiceClient(conn), |
|
ready: make(chan struct{}), |
|
} |
|
|
|
go c.waitForReady(ctx) |
|
|
|
return c, nil |
|
} |
|
|
|
func (c *Client) waitForReady(ctx context.Context) { |
|
for { |
|
select { |
|
case <-ctx.Done(): |
|
return |
|
default: |
|
resp, err := c.client.Ready(ctx, &commonv1.Empty{}) |
|
if err == nil && resp.Ready { |
|
close(c.ready) |
|
log.I.F("gRPC relay group client connected and ready") |
|
return |
|
} |
|
time.Sleep(100 * time.Millisecond) |
|
} |
|
} |
|
} |
|
|
|
// Close closes the gRPC connection. |
|
func (c *Client) Close() error { |
|
if c.conn != nil { |
|
return c.conn.Close() |
|
} |
|
return nil |
|
} |
|
|
|
// Ready returns a channel that closes when the client is ready. |
|
func (c *Client) Ready() <-chan struct{} { |
|
return c.ready |
|
} |
|
|
|
// FindAuthoritativeConfig finds the authoritative relay group configuration. |
|
func (c *Client) FindAuthoritativeConfig(ctx context.Context) (*relaygroupv1.RelayGroupConfigResponse, error) { |
|
return c.client.FindAuthoritativeConfig(ctx, &commonv1.Empty{}) |
|
} |
|
|
|
// GetRelays returns the list of relays from the authoritative config. |
|
func (c *Client) GetRelays(ctx context.Context) ([]string, error) { |
|
resp, err := c.client.GetRelays(ctx, &commonv1.Empty{}) |
|
if err != nil { |
|
return nil, err |
|
} |
|
return resp.Relays, nil |
|
} |
|
|
|
// IsAuthorizedPublisher checks if a pubkey can publish relay group configs. |
|
func (c *Client) IsAuthorizedPublisher(ctx context.Context, pubkey []byte) (bool, error) { |
|
resp, err := c.client.IsAuthorizedPublisher(ctx, &relaygroupv1.AuthorizedPublisherRequest{ |
|
Pubkey: pubkey, |
|
}) |
|
if err != nil { |
|
return false, err |
|
} |
|
return resp.Authorized, nil |
|
} |
|
|
|
// GetAuthorizedPubkeys returns all authorized publisher pubkeys. |
|
func (c *Client) GetAuthorizedPubkeys(ctx context.Context) ([][]byte, error) { |
|
resp, err := c.client.GetAuthorizedPubkeys(ctx, &commonv1.Empty{}) |
|
if err != nil { |
|
return nil, err |
|
} |
|
return resp.Pubkeys, nil |
|
} |
|
|
|
// ValidateRelayGroupEvent validates a relay group configuration event. |
|
func (c *Client) ValidateRelayGroupEvent(ctx context.Context, event *commonv1.Event) (bool, string, error) { |
|
resp, err := c.client.ValidateRelayGroupEvent(ctx, &relaygroupv1.ValidateEventRequest{ |
|
Event: event, |
|
}) |
|
if err != nil { |
|
return false, "", err |
|
} |
|
return resp.Valid, resp.Error, nil |
|
} |
|
|
|
// HandleRelayGroupEvent processes a relay group event and triggers peer updates. |
|
func (c *Client) HandleRelayGroupEvent(ctx context.Context, event *commonv1.Event) error { |
|
_, err := c.client.HandleRelayGroupEvent(ctx, &relaygroupv1.HandleEventRequest{ |
|
Event: event, |
|
}) |
|
return err |
|
}
|
|
|