requesthook.go 3.34 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
	ld "gitlab.dms3.io/ld/go-ld-prime"
	"gitlab.dms3.io/ld/go-ld-prime/traversal"
	peer "gitlab.dms3.io/p2p/go-p2p-core/peer"
Hannah Howard's avatar
Hannah Howard committed
10

11
	"gitlab.dms3.io/dms3/go-graphsync"
12 13 14 15
)

// PersistenceOptions is an interface for getting loaders by name
type PersistenceOptions interface {
16
	GetLinkSystem(name string) (ld.LinkSystem, bool)
17 18 19 20 21
}

// 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 {
Hannah Howard's avatar
Hannah Howard committed
53 54
	IsValidated      bool
	IsPaused         bool
55
	CustomLinkSystem ld.LinkSystem
Hannah Howard's avatar
Hannah Howard committed
56 57 58
	CustomChooser    traversal.LinkTargetNodePrototypeChooser
	Err              error
	Extensions       []graphsync.ExtensionData
59 60 61
}

// 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
	err                error
75
	linkSystem         ld.LinkSystem
Eric Myhre's avatar
Eric Myhre committed
76
	chooser            traversal.LinkTargetNodePrototypeChooser
77 78 79
	extensions         []graphsync.ExtensionData
}

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

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) {
Hannah Howard's avatar
Hannah Howard committed
104
	linkSystem, ok := ha.persistenceOptions.GetLinkSystem(name)
105 106 107 108
	if !ok {
		ha.TerminateWithError(errors.New("unknown loader option"))
		return
	}
Hannah Howard's avatar
Hannah Howard committed
109
	ha.linkSystem = linkSystem
110 111
}

Eric Myhre's avatar
Eric Myhre committed
112
func (ha *requestHookActions) UseLinkTargetNodePrototypeChooser(chooser traversal.LinkTargetNodePrototypeChooser) {
113 114
	ha.chooser = chooser
}
115 116 117 118

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