package client import ( "context" "sync" "forge.cadoles.com/cadoles/go-emlid/reach/client/protocol" "github.com/pkg/errors" ) type Client struct { addr string opts *Options ops protocol.Operations getOpsOnce sync.Once getOpsOnceErr error } // Close implements protocol.Operations. func (c *Client) Close() error { panic("unimplemented") } // Connect implements protocol.Operations. func (c *Client) Connect(ctx context.Context) error { ops, err := c.getOperations(ctx) if err != nil { return errors.WithStack(err) } if err := ops.Connect(ctx); err != nil { return errors.WithStack(err) } return nil } func (c *Client) getOperations(ctx context.Context) (protocol.Operations, error) { c.getOpsOnce.Do(func() { availables, err := c.opts.Protocols.Availables(ctx, c.addr) if err != nil { c.getOpsOnceErr = errors.WithStack(err) return } var preferred protocol.Operations var fallback protocol.Operations for _, proto := range availables { if proto.Identifier() == c.opts.FallbackProtocol { fallback = proto.Operations(c.addr) } if proto.Identifier() == c.opts.PreferredProtocol { preferred = proto.Operations(c.addr) break } } if preferred != nil { c.ops = preferred return } if fallback != nil { c.ops = fallback return } for _, proto := range availables { if proto.Identifier() != c.opts.FallbackProtocol { continue } fallback = proto.Operations(c.addr) break } if fallback == nil { c.getOpsOnceErr = errors.Errorf("neither preferred protocol '%v' or fallback '%v' are available", c.opts.PreferredProtocol, c.opts.FallbackProtocol) return } c.ops = fallback }) if c.getOpsOnceErr != nil { return nil, errors.WithStack(c.getOpsOnceErr) } return c.ops, nil } func NewClient(addr string, funcs ...OptionFunc) *Client { opts := NewOptions(funcs...) client := &Client{ addr: addr, opts: opts, } return client } var _ protocol.Operations = &Client{}