requesthook.go 3.25 KB
Newer Older
Hannah Howard's avatar
Hannah Howard committed
1
package hooks
2 3 4 5

import (
	"errors"

6
	"github.com/hannahhoward/go-pubsub"
7 8 9
	"github.com/ipld/go-ipld-prime"
	"github.com/ipld/go-ipld-prime/traversal"
	peer "github.com/libp2p/go-libp2p-core/peer"
Hannah Howard's avatar
Hannah Howard committed
10 11

	"github.com/ipfs/go-graphsync"
12 13 14 15 16 17 18 19 20 21
)

// PersistenceOptions is an interface for getting loaders by name
type PersistenceOptions interface {
	GetLoader(name string) (ipld.Loader, bool)
}

// IncomingRequestHooks is a set of incoming request hooks that can be processed
type IncomingRequestHooks struct {
	persistenceOptions PersistenceOptions
22 23 24 25 26 27 28 29 30 31 32 33 34 35
	pubSub             *pubsub.PubSub
}

type internalRequestHookEvent struct {
	p       peer.ID
	request graphsync.RequestData
	rha     *requestHookActions
}

func requestHookDispatcher(event pubsub.Event, subscriberFn pubsub.SubscriberFn) error {
	ie := event.(internalRequestHookEvent)
	hook := subscriberFn.(graphsync.OnIncomingRequestHook)
	hook(ie.p, ie.request, ie.rha)
	return ie.rha.err
36 37
}

Hannah Howard's avatar
Hannah Howard committed
38 39
// NewRequestHooks returns a new list of incoming request hooks
func NewRequestHooks(persistenceOptions PersistenceOptions) *IncomingRequestHooks {
40 41
	return &IncomingRequestHooks{
		persistenceOptions: persistenceOptions,
42
		pubSub:             pubsub.New(requestHookDispatcher),
43 44 45 46 47
	}
}

// Register registers an extension to process new incoming requests
func (irh *IncomingRequestHooks) Register(hook graphsync.OnIncomingRequestHook) graphsync.UnregisterHookFunc {
48
	return graphsync.UnregisterHookFunc(irh.pubSub.Subscribe(hook))
49 50
}

Hannah Howard's avatar
Hannah Howard committed
51 52
// RequestResult is the outcome of running requesthooks
type RequestResult struct {
53
	IsValidated   bool
54
	IsPaused      bool
55
	CustomLoader  ipld.Loader
Hannah Howard's avatar
Hannah Howard committed
56
	CustomChooser traversal.LinkTargetNodeStyleChooser
57 58 59 60 61
	Err           error
	Extensions    []graphsync.ExtensionData
}

// ProcessRequestHooks runs request hooks against an incoming request
Hannah Howard's avatar
Hannah Howard committed
62 63
func (irh *IncomingRequestHooks) ProcessRequestHooks(p peer.ID, request graphsync.RequestData) RequestResult {
	ha := &requestHookActions{
64 65
		persistenceOptions: irh.persistenceOptions,
	}
66
	_ = irh.pubSub.Publish(internalRequestHookEvent{p, request, ha})
67 68 69
	return ha.result()
}

Hannah Howard's avatar
Hannah Howard committed
70
type requestHookActions struct {
71 72
	persistenceOptions PersistenceOptions
	isValidated        bool
73
	isPaused           bool
74 75
	err                error
	loader             ipld.Loader
Hannah Howard's avatar
Hannah Howard committed
76
	chooser            traversal.LinkTargetNodeStyleChooser
77 78 79
	extensions         []graphsync.ExtensionData
}

Hannah Howard's avatar
Hannah Howard committed
80 81
func (ha *requestHookActions) result() RequestResult {
	return RequestResult{
82
		IsValidated:   ha.isValidated,
83
		IsPaused:      ha.isPaused,
84 85 86 87 88 89 90
		CustomLoader:  ha.loader,
		CustomChooser: ha.chooser,
		Err:           ha.err,
		Extensions:    ha.extensions,
	}
}

Hannah Howard's avatar
Hannah Howard committed
91
func (ha *requestHookActions) SendExtensionData(ext graphsync.ExtensionData) {
92 93 94
	ha.extensions = append(ha.extensions, ext)
}

Hannah Howard's avatar
Hannah Howard committed
95
func (ha *requestHookActions) TerminateWithError(err error) {
96 97 98
	ha.err = err
}

Hannah Howard's avatar
Hannah Howard committed
99
func (ha *requestHookActions) ValidateRequest() {
100 101 102
	ha.isValidated = true
}

Hannah Howard's avatar
Hannah Howard committed
103
func (ha *requestHookActions) UsePersistenceOption(name string) {
104 105 106 107 108 109 110 111
	loader, ok := ha.persistenceOptions.GetLoader(name)
	if !ok {
		ha.TerminateWithError(errors.New("unknown loader option"))
		return
	}
	ha.loader = loader
}

Hannah Howard's avatar
Hannah Howard committed
112
func (ha *requestHookActions) UseLinkTargetNodeStyleChooser(chooser traversal.LinkTargetNodeStyleChooser) {
113 114
	ha.chooser = chooser
}
115 116 117 118

func (ha *requestHookActions) PauseResponse() {
	ha.isPaused = true
}