Files
cunicu/pkg/signaling/grpc/backend.go
Steffen Vogel a8859d74c3 refactor RPC package
Signed-off-by: Steffen Vogel <post@steffenvogel.de>
2022-07-27 13:39:18 +02:00

138 lines
2.9 KiB
Go

package grpc
import (
"context"
"fmt"
"go.uber.org/zap"
"google.golang.org/grpc"
"riasc.eu/wice/pkg/crypto"
"riasc.eu/wice/pkg/pb"
"riasc.eu/wice/pkg/signaling"
)
func init() {
signaling.Backends["grpc"] = &signaling.BackendPlugin{
New: NewBackend,
Description: "gRPC",
}
}
type Backend struct {
signaling.SubscriptionsRegistry
client pb.SignalingClient
conn *grpc.ClientConn
isClosing bool
config BackendConfig
logger *zap.Logger
}
func NewBackend(cfg *signaling.BackendConfig, logger *zap.Logger) (signaling.Backend, error) {
var err error
b := &Backend{
SubscriptionsRegistry: signaling.NewSubscriptionsRegistry(),
logger: logger,
}
if err := b.config.Parse(cfg); err != nil {
return nil, fmt.Errorf("failed to parse backend configuration: %w", err)
}
if b.conn, err = grpc.Dial(b.config.Target, b.config.Options...); err != nil {
return nil, fmt.Errorf("failed to connect to gRPC server: %w", err)
}
b.client = pb.NewSignalingClient(b.conn)
for _, h := range cfg.OnReady {
h.OnSignalingBackendReady(b)
}
return b, nil
}
func (b *Backend) Type() pb.BackendType {
return pb.BackendType_GRPC
}
func (b *Backend) SubscribeAll(ctx context.Context, sk *crypto.Key, h signaling.MessageHandler) error {
if created, err := b.SubscriptionsRegistry.SubscribeAll(sk, h); err != nil {
return err
} else if created {
pk := sk.PublicKey()
return b.subscribeFromServer(ctx, &pk)
}
return nil
}
func (b *Backend) Subscribe(ctx context.Context, kp *crypto.KeyPair, h signaling.MessageHandler) error {
if created, err := b.SubscriptionsRegistry.Subscribe(kp, h); err != nil {
return err
} else if created {
pk := kp.Ours.PublicKey()
return b.subscribeFromServer(ctx, &pk)
}
return nil
}
func (b *Backend) Publish(ctx context.Context, kp *crypto.KeyPair, msg *signaling.Message) error {
env, err := msg.Encrypt(kp)
if err != nil {
return fmt.Errorf("failed to encrypt message: %w", err)
}
if _, err = b.client.Publish(ctx, env); err != nil {
return fmt.Errorf("failed to publish offer: %w", err)
}
return nil
}
func (b *Backend) Close() error {
b.isClosing = true
if err := b.conn.Close(); err != nil {
return fmt.Errorf("failed to close gRPC connection: %w", err)
}
return nil
}
func (b *Backend) subscribeFromServer(ctx context.Context, pk *crypto.Key) error {
b.logger.Debug("Creating new subscription", zap.Any("pk", pk))
params := &pb.SubscribeParams{
Key: pk.Bytes(),
}
stream, err := b.client.Subscribe(ctx, params)
if err != nil {
return fmt.Errorf("failed to subscribe to offers: %s", err)
}
go func() {
for {
if env, err := stream.Recv(); err == nil {
if err := b.SubscriptionsRegistry.NewMessage(env); err != nil {
b.logger.Error("Failed to decrypt message", zap.Error(err))
}
} else {
if b.isClosing {
return
}
b.logger.Error("Failed to receive offer", zap.Error(err))
}
}
}()
return nil
}