104 lines
2.0 KiB
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{}
|