outofband

package
v0.1.6-0...-5c25bcb Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 1, 2021 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package outofband provides support for the Out-of-Band protocols: https://github.com/hyperledger/aries-rfcs/blob/master/features/0434-outofband/README.md.

Create your client:

ctx := getFrameworkContext() client, err := outofband.New(ctx)

if err != nil {
    panic(err)
}

You can create requests and invitations with client.CreateRequest() and client.CreateInvitation() respectively.

You can accept out-of-band requests and invitations received via out of band channels. If you have a request or an invitation on hand you can use the client.AcceptRequest() and client.AcceptInvitation() respectively. These return the ID of the newly-created connection record.

If you're expecting to receive out-of-band invitations or requests via a DIDComm channel then you should register to the action event stream and the state event stream:

events := make(chan service.DIDCommAction) err = client.RegisterActionEvent(events)

if err != nil {
    panic(err)
}

states := make(chan service.StateMsg) err = client.RegisterMsgEvent(states)

if err != nil {
   panic(err)
}
for {
    select {
    case event := <-events:
        switch event.Message.Type() {
        case outofband.RequestMsgType:
            // inspect the request
            req := &outofband.Request{}
            err = event.Message.Decode(req)
            if err != nil {
                panic(err)
            }

            // accept the request:
            event.Continue(&outofband.EventOptions{Label: "Bob"})
            // OR you may reject this request:
            // event.Stop(errors.New("rejected"))
        case outofband.InvitationMsgType:
            // inspect and handle the out-of-band invitation just like with the
            // request message above
        }
    case state := <-states:
        // the connection ID is delivered in a PostState
        if state.Type == service.PostState {
            props := state.Properties.(outofband.Event)
            if props.Error() != nil {
                panic(props.Error())
            }

            // the connection ID
            connID := props.ConnectionID()
        }
    }
}

Note: the ouf-of-band protocol results in the execution of other protocols. You need to subscribe to the event and state streams of those protocols as well.

Index

Examples

Constants

View Source
const (
	// RequestMsgType is the request message's '@type'.
	RequestMsgType = outofband.RequestMsgType
	// InvitationMsgType is the '@type' for the invitation message.
	InvitationMsgType = outofband.InvitationMsgType
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Action

type Action outofband.Action

Action contains helpful information about action.

type Client

type Client struct {
	service.Event
	// contains filtered or unexported fields
}

Client for the Out-Of-Band protocol: https://github.com/hyperledger/aries-rfcs/blob/master/features/0434-outofband/README.md

func New

func New(p Provider) (*Client, error)

New returns a new Client for the Out-Of-Band protocol.

func (*Client) AcceptInvitation

func (c *Client) AcceptInvitation(i *Invitation, myLabel string, opts ...MessageOption) (string, error)

AcceptInvitation from another agent and return the ID of the new connection records.

Example

Example of an edge agent sending an out-of-band request to another edge agent.

{ //nolint:gocyclo,gocognit
	// set up the router
	aliceCtx := getContext(Alice)

	alice, err := New(aliceCtx)
	if err != nil {
		panic(err)
	}

	aliceDIDs, err := didexchange.New(aliceCtx)
	if err != nil {
		panic(err)
	}

	aliceRouting, err := mediator.New(aliceCtx)
	if err != nil {
		panic(err)
	}

	aliceEvents := makeActionsChannel(Alice)

	err = aliceDIDs.RegisterActionEvent(aliceEvents)
	if err != nil {
		panic(err)
	}

	err = aliceRouting.RegisterActionEvent(aliceEvents)
	if err != nil {
		panic(err)
	}

	// set up the edge agent
	bob, err := New(getContext(Bob))
	if err != nil {
		panic(err)
	}

	// alice creates an outofband invitation
	inv, err := alice.CreateInvitation(nil, WithLabel(Alice))
	if err != nil {
		panic(err)
	}

	fmt.Printf("%s creates an out-of-band invitation\n", Alice)

	// the edge agent accepts the outofband invitation
	bobConnID, err := bob.AcceptInvitation(inv, Bob)
	if err != nil {
		panic(err)
	}

	fmt.Printf(
		"%s accepts the out-of-band invitation received via an out of band channel and created connectionID %s\n",
		Bob, bobConnID)

	done := make(chan struct{}) // ends this example

	go func() {
		for event := range aliceEvents {
			fmt.Printf("%s received %s from %s\n", Alice, event.Message.Type(), Bob)

			if event.ProtocolName == didexchange.ProtocolName &&
				event.Message.Type() == didexchange.RequestMsgType {
				didExchangeRequest := &didsvc.Request{}

				err = event.Message.Decode(didExchangeRequest)
				if err != nil {
					panic(err)
				}

				if didExchangeRequest.Label != Bob {
					err = fmt.Errorf(
						"%s expected a didexchange request from %s but got %s",
						Alice, Bob, didExchangeRequest.Label,
					)

					event.Stop(err)
					panic(err)
				}

				props, ok := event.Properties.(didexchange.Event)
				if !ok {
					panic("failed to cast event properties (shouldn't happen)")
				}

				fmt.Printf("%s created connectionID %s\n", Alice, props.ConnectionID())

				event.Continue(nil)
				done <- struct{}{}
			}
		}
	}()

	select {
	case <-done:
	case <-time.After(time.Second): // timeout varies in your environment
		panic("timeout")
	}

	
Output:

Alice creates an out-of-band invitation
Bob accepts the out-of-band invitation received via an out of band channel and created connectionID abcdefg
Alice received https://didcomm.org/didexchange/1.0/request from Bob
Alice created connectionID xyz

func (*Client) AcceptRequest

func (c *Client) AcceptRequest(r *Request, myLabel string, opts ...MessageOption) (string, error)

AcceptRequest from another agent and return the ID of a new connection record.

Example

Example of an edge agent accepting an out-of-band request from a router.

{ //nolint:gocyclo,gocognit
	// set up the router
	routerCtx := getContext(Router)

	router, err := New(routerCtx)
	if err != nil {
		panic(err)
	}

	routerDIDs, err := didexchange.New(routerCtx)
	if err != nil {
		panic(err)
	}

	routerClient, err := mediator.New(routerCtx)
	if err != nil {
		panic(err)
	}

	routerEvents := makeActionsChannel(Router)

	err = routerDIDs.RegisterActionEvent(routerEvents)
	if err != nil {
		panic(err)
	}

	err = routerClient.RegisterActionEvent(routerEvents)
	if err != nil {
		panic(err)
	}

	// set up the edge agent
	bobCtx := getContext(Bob)

	bob, err := New(bobCtx)
	if err != nil {
		panic(err)
	}

	// router creates the route-request message
	routeRequest, err := json.Marshal(mediator.NewRequest())
	if err != nil {
		panic(err)
	}

	// router creates outofband request and embeds the route-request message in it
	req, err := router.CreateRequest(
		[]*decorator.Attachment{{
			ID: uuid.New().String(),
			Data: decorator.AttachmentData{
				Base64: base64.StdEncoding.EncodeToString(routeRequest),
			},
		}},
		WithLabel(Router),
	)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%s creates an out-of-band request with an embedded route-request message\n", Router)

	// the edge agent accepts the outofband request
	bobConnID, err := bob.AcceptRequest(req, Bob)
	if err != nil {
		panic(err)
	}

	fmt.Printf(
		"%s accepts the out-of-band request received via an out of band channel and created connectionID %s\n",
		Bob, bobConnID)

	done := make(chan struct{}) // ends this example

	go func() {
		for event := range routerEvents {
			fmt.Printf("%s received %s from %s\n", Router, event.Message.Type(), Bob)

			switch event.ProtocolName {
			case didexchange.ProtocolName:
				if event.Message.Type() == didexchange.RequestMsgType {
					didExchangeRequest := &didsvc.Request{}

					err = event.Message.Decode(didExchangeRequest)
					if err != nil {
						panic(err)
					}

					if didExchangeRequest.Label != Bob {
						err = fmt.Errorf(
							"%s expected a didexchange request from %s but got %s",
							Router, Bob, didExchangeRequest.Label,
						)

						event.Stop(err)
						panic(err)
					}

					props, ok := event.Properties.(didexchange.Event)
					if !ok {
						panic("failed to cast event properties (shouldn't happen)")
					}

					fmt.Printf("%s created connectionID %s\n", Router, props.ConnectionID())

					event.Continue(nil)
				}
			case mediator.ProtocolName:
				if event.Message.Type() == mediator.RequestMsgType {
					event.Continue(nil)
					done <- struct{}{}
				}
			}
		}
	}()

	select {
	case <-done:
	case <-time.After(time.Second): // timeout varies in your environment
		panic("timeout")
	}

	bobRoutes, err := mediator.New(bobCtx)
	if err != nil {
		panic(err)
	}

	config, err := bobRoutes.GetConfig("xyz")
	if err != nil {
		panic(err)
	}

	fmt.Printf(
		"%s has registered a route on %s with routerEndpoint %s and routingKeys %+v\n",
		Bob, Router, config.Endpoint(), config.Keys())

	
Output:

Router creates an out-of-band request with an embedded route-request message
Bob accepts the out-of-band request received via an out of band channel and created connectionID xyz
Router received https://didcomm.org/didexchange/1.0/request from Bob
Router created connectionID xyz
Router received https://didcomm.org/coordinatemediation/1.0/mediate-request from Bob
Bob has registered a route on Router with routerEndpoint http://routers-r-us.com and routingKeys [key-1 key-2]

func (*Client) ActionContinue

func (c *Client) ActionContinue(piID, label string, opts ...MessageOption) error

ActionContinue allows continuing with the protocol after an action event was triggered.

func (*Client) ActionStop

func (c *Client) ActionStop(piID string, err error) error

ActionStop stops the protocol after an action event was triggered.

func (*Client) Actions

func (c *Client) Actions() ([]Action, error)

Actions returns unfinished actions for the async usage.

func (*Client) CreateInvitation

func (c *Client) CreateInvitation(protocols []string, opts ...MessageOption) (*Invitation, error)

CreateInvitation creates and saves an out-of-band invitation. Protocols is an optional list of protocol identifier URIs that can be used to form connections. A default will be set if none are provided.

func (*Client) CreateRequest

func (c *Client) CreateRequest(attchmnts []*decorator.Attachment, opts ...MessageOption) (*Request, error)

CreateRequest creates and saves an Out-Of-Band request message. At least one attachment must be provided. Service entries can be optionally provided. If none are provided then a new one will be automatically created for you.

type Event

type Event interface {
	// ConnectionID of the connection record, once it's created.
	// This becomes available in a post-state event unless an error condition is encountered.
	ConnectionID() string
	// Error is non-nil if an error is encountered.
	Error() error
}

Event is a container of out-of-band protocol-specific properties for DIDCommActions and StateMsgs.

type EventOptions

type EventOptions struct {
	// Label will be shared with the other agent during the subsequent did-exchange.
	Label string
	// Connections allows specifying router connections.
	Connections []string
}

EventOptions are is a container of options that you can pass to an event's Continue function to customize the reaction to incoming out-of-band messages.

func (*EventOptions) MyLabel

func (e *EventOptions) MyLabel() string

MyLabel will be shared with the other agent during the subsequent did-exchange.

func (*EventOptions) RouterConnections

func (e *EventOptions) RouterConnections() []string

RouterConnections return router connections.

type Invitation

type Invitation outofband.Invitation

Invitation is this protocol's `invitation` message.

type MessageOption

type MessageOption func(*message) error

MessageOption allow you to customize the way out-of-band messages are built.

func WithGoal

func WithGoal(goal, goalCode string) MessageOption

WithGoal allows you to specify the `goal` and `goalCode` for the message.

func WithLabel

func WithLabel(l string) MessageOption

WithLabel allows you to specify the label on the message.

func WithRouterConnections

func WithRouterConnections(conn ...string) MessageOption

WithRouterConnections allows you to specify the router connections.

func WithServices

func WithServices(svcs ...interface{}) MessageOption

WithServices allows you to specify service entries to include in the request message. Each entry must be either a valid DID (string) or a `service` object.

type OobService

type OobService interface {
	service.Event
	AcceptRequest(*outofband.Request, string, []string) (string, error)
	AcceptInvitation(*outofband.Invitation, string, []string) (string, error)
	SaveRequest(*outofband.Request) error
	SaveInvitation(*outofband.Invitation) error
	Actions() ([]outofband.Action, error)
	ActionContinue(string, outofband.Options) error
	ActionStop(string, error) error
}

OobService defines the outofband service.

type Provider

type Provider interface {
	ServiceEndpoint() string
	Service(id string) (interface{}, error)
	KMS() kms.KeyManager
}

Provider provides the dependencies for the client.

type Request

type Request outofband.Request

Request is the out-of-band protocol's 'request' message.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL