go-emlid/reach/client/client.go

104 lines
2.0 KiB
Go

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{}