2019-10-26 01:36:49 +00:00
|
|
|
package datatransfer
|
|
|
|
|
|
|
|
import (
|
2019-10-31 03:00:02 +00:00
|
|
|
"context"
|
2019-10-26 01:36:49 +00:00
|
|
|
"reflect"
|
|
|
|
|
|
|
|
"github.com/ipfs/go-cid"
|
2019-10-28 23:51:50 +00:00
|
|
|
ipld "github.com/ipld/go-ipld-prime"
|
2019-10-26 01:36:49 +00:00
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Voucher is used to validate
|
|
|
|
// a data transfer request against the underlying storage or retrieval deal
|
|
|
|
// that precipitated it. The only requirement is a voucher can read and write
|
2019-10-29 00:57:12 +00:00
|
|
|
// from bytes, and has a string identifier type
|
2019-10-26 01:36:49 +00:00
|
|
|
type Voucher interface {
|
2019-10-29 00:57:12 +00:00
|
|
|
// ToBytes converts the Voucher to raw bytes
|
2019-10-31 03:00:02 +00:00
|
|
|
ToBytes() ([]byte, error)
|
2019-10-29 00:57:12 +00:00
|
|
|
// FromBytes reads a Voucher from raw bytes
|
2019-10-31 03:00:02 +00:00
|
|
|
FromBytes([]byte) error
|
2019-10-29 00:57:12 +00:00
|
|
|
// Identifier is a unique string identifier for this voucher type
|
2019-10-26 01:36:49 +00:00
|
|
|
Identifier() string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Status is the status of transfer for a given channel
|
2019-11-11 21:02:49 +00:00
|
|
|
type Status int
|
2019-10-26 01:36:49 +00:00
|
|
|
|
|
|
|
const (
|
|
|
|
// Ongoing means the data transfer is in progress
|
2019-11-11 21:02:49 +00:00
|
|
|
Ongoing Status = iota
|
2019-10-26 01:36:49 +00:00
|
|
|
|
|
|
|
// Completed means the data transfer is completed successfully
|
2019-11-11 21:02:49 +00:00
|
|
|
Completed
|
2019-10-26 01:36:49 +00:00
|
|
|
|
|
|
|
// Failed means the data transfer failed
|
2019-11-11 21:02:49 +00:00
|
|
|
Failed
|
2019-10-26 01:36:49 +00:00
|
|
|
|
|
|
|
// ChannelNotFoundError means the searched for data transfer does not exist
|
2019-11-11 21:02:49 +00:00
|
|
|
ChannelNotFoundError
|
2019-10-26 01:36:49 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// TransferID is an identifier for a data transfer, shared between
|
2019-11-15 08:19:06 +00:00
|
|
|
// request/responder and unique to the requester
|
2019-10-26 01:36:49 +00:00
|
|
|
type TransferID uint64
|
|
|
|
|
|
|
|
// ChannelID is a unique identifier for a channel, distinct by both the other
|
|
|
|
// party's peer ID + the transfer ID
|
|
|
|
type ChannelID struct {
|
|
|
|
to peer.ID
|
|
|
|
id TransferID
|
|
|
|
}
|
|
|
|
|
|
|
|
// Channel represents all the parameters for a single data transfer
|
|
|
|
type Channel struct {
|
2019-11-15 08:19:06 +00:00
|
|
|
// an identifier for this channel shared by request and responder, set by requester through protocol
|
2019-10-26 01:36:49 +00:00
|
|
|
transferID TransferID
|
|
|
|
// base CID for the piece being transferred
|
2019-10-29 00:57:12 +00:00
|
|
|
baseCid cid.Cid
|
2019-11-15 08:19:06 +00:00
|
|
|
// portion of Piece to return, specified by an IPLD selector
|
2019-10-28 23:51:50 +00:00
|
|
|
selector ipld.Node
|
2019-10-26 01:36:49 +00:00
|
|
|
// used to verify this channel
|
|
|
|
voucher Voucher
|
|
|
|
// the party that is sending the data (not who initiated the request)
|
|
|
|
sender peer.ID
|
|
|
|
// the party that is receiving the data (not who initiated the request)
|
|
|
|
recipient peer.ID
|
|
|
|
// expected amount of data to be transferred
|
|
|
|
totalSize uint64
|
|
|
|
}
|
|
|
|
|
2019-10-29 00:57:12 +00:00
|
|
|
// TransferID returns the transfer id for this channel
|
|
|
|
func (c Channel) TransferID() TransferID { return c.transferID }
|
|
|
|
|
|
|
|
// BaseCID returns the CID that is at the root of this data transfer
|
|
|
|
func (c Channel) BaseCID() cid.Cid { return c.baseCid }
|
|
|
|
|
|
|
|
// Selector returns the IPLD selector for this data transfer (represented as
|
|
|
|
// an IPLD node)
|
|
|
|
func (c Channel) Selector() ipld.Node { return c.selector }
|
|
|
|
|
|
|
|
// Voucher returns the voucher for this data transfer
|
|
|
|
func (c Channel) Voucher() Voucher { return c.voucher }
|
|
|
|
|
|
|
|
// Sender returns the peer id for the node that is sending data
|
|
|
|
func (c Channel) Sender() peer.ID { return c.sender }
|
|
|
|
|
|
|
|
// Recipient returns the peer id for the node that is receiving data
|
|
|
|
func (c Channel) Recipient() peer.ID { return c.recipient }
|
|
|
|
|
|
|
|
// TotalSize returns the total size for the data being transferred
|
|
|
|
func (c Channel) TotalSize() uint64 { return c.totalSize }
|
2019-10-28 23:51:50 +00:00
|
|
|
|
2019-10-26 01:36:49 +00:00
|
|
|
// ChannelState is immutable channel data plus mutable state
|
|
|
|
type ChannelState struct {
|
|
|
|
Channel
|
|
|
|
// total bytes sent from this node (0 if receiver)
|
|
|
|
sent uint64
|
|
|
|
// total bytes received by this node (0 if sender)
|
|
|
|
received uint64
|
|
|
|
}
|
|
|
|
|
2019-10-29 00:57:12 +00:00
|
|
|
// Sent returns the number of bytes sent
|
|
|
|
func (c ChannelState) Sent() uint64 { return c.sent }
|
|
|
|
|
|
|
|
// Received returns the number of bytes received
|
2019-10-28 23:51:50 +00:00
|
|
|
func (c ChannelState) Received() uint64 { return c.received }
|
|
|
|
|
2019-10-26 01:36:49 +00:00
|
|
|
// Event is a name for an event that occurs on a data transfer channel
|
2019-11-11 21:02:49 +00:00
|
|
|
type Event int
|
2019-10-26 01:36:49 +00:00
|
|
|
|
|
|
|
const (
|
|
|
|
// Open is an event occurs when a channel is first opened
|
2019-11-11 21:02:49 +00:00
|
|
|
Open Event = iota
|
2019-10-26 01:36:49 +00:00
|
|
|
|
|
|
|
// Progress is an event that gets emitted every time more data is transferred
|
2019-11-11 21:02:49 +00:00
|
|
|
Progress
|
2019-10-26 01:36:49 +00:00
|
|
|
|
|
|
|
// Error is an event that emits when an error occurs in a data transfer
|
2019-11-11 21:02:49 +00:00
|
|
|
Error
|
2019-10-26 01:36:49 +00:00
|
|
|
|
|
|
|
// Complete is emitted when a data transfer is complete
|
2019-11-11 21:02:49 +00:00
|
|
|
Complete
|
2019-10-26 01:36:49 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Subscriber is a callback that is called when events are emitted
|
|
|
|
type Subscriber func(event Event, channelState ChannelState)
|
|
|
|
|
|
|
|
// RequestValidator is an interface implemented by the client of the
|
|
|
|
// data transfer module to validate requests
|
|
|
|
type RequestValidator interface {
|
2019-10-29 00:57:12 +00:00
|
|
|
// ValidatePush validates a push request received from the peer that will send data
|
2019-10-26 01:36:49 +00:00
|
|
|
ValidatePush(
|
|
|
|
sender peer.ID,
|
|
|
|
voucher Voucher,
|
2019-10-29 00:57:12 +00:00
|
|
|
baseCid cid.Cid,
|
|
|
|
selector ipld.Node) error
|
|
|
|
// ValidatePull validates a pull request received from the peer that will receive data
|
2019-10-26 01:36:49 +00:00
|
|
|
ValidatePull(
|
|
|
|
receiver peer.ID,
|
|
|
|
voucher Voucher,
|
2019-10-29 00:57:12 +00:00
|
|
|
baseCid cid.Cid,
|
|
|
|
selector ipld.Node) error
|
2019-10-26 01:36:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Manager is the core interface presented by all implementations of
|
|
|
|
// of the data transfer sub system
|
|
|
|
type Manager interface {
|
|
|
|
// RegisterVoucherType registers a validator for the given voucher type
|
|
|
|
// will error if voucher type does not implement voucher
|
|
|
|
// or if there is a voucher type registered with an identical identifier
|
|
|
|
RegisterVoucherType(voucherType reflect.Type, validator RequestValidator) error
|
|
|
|
|
|
|
|
// open a data transfer that will send data to the recipient peer and
|
|
|
|
// open a data transfer that will send data to the recipient peer and
|
|
|
|
// transfer parts of the piece that match the selector
|
2019-10-31 03:00:02 +00:00
|
|
|
OpenPushDataChannel(ctx context.Context, to peer.ID, voucher Voucher, baseCid cid.Cid, selector ipld.Node) (ChannelID, error)
|
2019-10-26 01:36:49 +00:00
|
|
|
|
|
|
|
// open a data transfer that will request data from the sending peer and
|
|
|
|
// transfer parts of the piece that match the selector
|
2019-10-31 03:00:02 +00:00
|
|
|
OpenPullDataChannel(ctx context.Context, to peer.ID, voucher Voucher, baseCid cid.Cid, selector ipld.Node) (ChannelID, error)
|
2019-10-26 01:36:49 +00:00
|
|
|
|
|
|
|
// close an open channel (effectively a cancel)
|
|
|
|
CloseDataTransferChannel(x ChannelID)
|
|
|
|
|
|
|
|
// get status of a transfer
|
|
|
|
TransferChannelStatus(x ChannelID) Status
|
|
|
|
|
|
|
|
// get notified when certain types of events happen
|
|
|
|
SubscribeToEvents(subscriber Subscriber)
|
|
|
|
|
|
|
|
// get all in progress transfers
|
|
|
|
InProgressChannels() map[ChannelID]ChannelState
|
|
|
|
}
|