Files
go-ethereum/network/newstream/wire.go
acud af3b5e9ce1 network/newstream: new stream! protocol base implementation (#1500)
network/newstream: merge new stream protocol wire protocol changes, changes to docs, add basic protocol handlers and placeholders
2019-07-08 13:25:56 +03:00

175 lines
6.0 KiB
Go

// Copyright 2019 The Swarm Authors
// This file is part of the Swarm library.
//
// The Swarm library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The Swarm library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the Swarm library. If not, see <http://www.gnu.org/licenses/>.
package newstream
import (
"context"
"fmt"
"github.com/ethersphere/swarm/chunk"
"github.com/ethersphere/swarm/storage"
)
// StreamProvider interface provides a lightweight abstraction that allows an easily-pluggable
// stream provider as part of the Stream! protocol specification.
// Since Stream! thoroughly defines the concepts of a stream, intervals, clients and servers, the
// interface therefore needs only a pluggable provider.
// The domain interpretable notions which are at the discretion of the implementing
// provider therefore are - sourcing data (get, put, subscribe for constant new data, and need data
// which is to decide whether to retrieve data or not), retrieving cursors from the data store, the
// implementation of which streams to maintain with a certain peer and providing functionality
// to expose, parse and encode values related to the string represntation of the stream
type StreamProvider interface {
// NeedData informs the caller whether a certain chunk needs to be fetched from another peer or not.
// Typically this will involve checking whether a certain chunk exists locally.
// In case a chunk does not exist locally - a `wait` function returns upon chunk delivery
NeedData(ctx context.Context, key []byte) (need bool, wait func(context.Context) error)
// Get a particular chunk identified by addr from the local storage
Get(ctx context.Context, addr chunk.Address) ([]byte, error)
// Put a certain chunk into the local storage
Put(ctx context.Context, addr chunk.Address, data []byte) (exists bool, err error)
// Subscribe to a data stream from an arbitrary data source
Subscribe(ctx context.Context, key interface{}, from, to uint64) (<-chan chunk.Descriptor, func())
// Cursor returns the last known Cursor for a given Stream Key
Cursor(interface{}) (uint64, error)
// RunUpdateStreams is a provider specific implementation on how to maintain running streams with
// an arbitrary Peer. This method should always be run in a separate goroutine
RunUpdateStreams(p *Peer)
// StreamName returns the Name of the Stream (see ID)
StreamName() string
// ParseStream from a standard pipe-separated string and return the Stream Key
ParseKey(string) (interface{}, error)
// EncodeStream from a Stream Key to a Stream pipe-separated string representation
EncodeKey(interface{}) (string, error)
// StreamBehavior defines how the stream behaves upon initialisation
StreamBehavior() StreamInitBehavior
Boundedness() bool
}
// StreamInitBehavior defines the stream behavior upon init
type StreamInitBehavior int
const (
// StreamIdle means that there is no initial automatic message exchange
// between the nodes when the protocol gets established
StreamIdle StreamInitBehavior = iota
// StreamGetCursors tells the two nodes to automatically fetch stream
// cursors from each other
StreamGetCursors
// StreamAutostart automatically starts fetching data from the streams
// once the cursors arrive
StreamAutostart
)
// StreamInfoReq is a request to get information about particular streams
type StreamInfoReq struct {
Streams []ID
}
// StreamInfoRes is a response to StreamInfoReq with the corresponding stream descriptors
type StreamInfoRes struct {
Streams []StreamDescriptor
}
// StreamDescriptor describes an arbitrary stream
type StreamDescriptor struct {
Stream ID
Cursor uint64
Bounded bool
}
// GetRange is a message sent from the downstream peer to the upstream peer asking for chunks
// within a particular interval for a certain stream
type GetRange struct {
Ruid uint
Stream ID
From uint64
To uint64 `rlp:nil`
BatchSize uint
Roundtrip bool
}
// OfferedHashes is a message sent from the upstream peer to the downstream peer allowing the latter
// to selectively ask for chunks within a particular requested interval
type OfferedHashes struct {
Ruid uint
LastIndex uint
Hashes []byte
}
// WantedHashes is a message sent from the downstream peer to the upstream peer in response
// to OfferedHashes in order to selectively ask for a particular chunks within an interval
type WantedHashes struct {
Ruid uint
BitVector []byte
}
// ChunkDelivery delivers a frame of chunks in response to a WantedHashes message
type ChunkDelivery struct {
Ruid uint
LastIndex uint
Chunks []DeliveredChunk
}
// DeliveredChunk encapsulates a particular chunk's underlying data within a ChunkDelivery message
type DeliveredChunk struct {
Addr storage.Address //chunk address
Data []byte //chunk data
}
// StreamState is a message exchanged between two nodes to notify of changes or errors in a stream's state
type StreamState struct {
Stream ID
Code uint16
Message string
}
// Stream defines a unique stream identifier in a textual representation
type ID struct {
// Name is used for the Stream provider identification
Name string
// Key is the name of specific data stream within the stream provider. The semantics of this value
// is at the discretion of the stream provider implementation
Key string
}
// NewID returns a new Stream ID for a particular stream Name and Key
func NewID(name string, key string) ID {
return ID{
Name: name,
Key: key,
}
}
// String return a stream id based on all Stream fields.
func (s ID) String() string {
return fmt.Sprintf("%s|%s", s.Name, s.Key)
}