2c6fa3c5f8
libuplink was incorrectly setting timeouts to 10 seconds still, but should have been at least 10 minutes. the order sender was setting them to 1 hour. we don't want timeouts in uplink-side logic as it establishes a minimum rate on tcp streams. instead of all of this, just use tcp keep alive. tcp keep alive packets are sent every 15 seconds and if the peer stops responding the connection dies. this is enabled by default with go. this will kill tcp connections when they stop working. Change-Id: I3d7ad49f71950b3eb43044eedf4b17993116045b
168 lines
6.1 KiB
Go
168 lines
6.1 KiB
Go
// Copyright (C) 2019 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package uplink
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/zeebo/errs"
|
|
"gopkg.in/spacemonkeygo/monkit.v2"
|
|
|
|
"storj.io/storj/internal/memory"
|
|
libuplink "storj.io/storj/lib/uplink"
|
|
"storj.io/storj/pkg/peertls/tlsopts"
|
|
"storj.io/storj/pkg/storj"
|
|
)
|
|
|
|
var mon = monkit.Package()
|
|
|
|
// RSConfig is a configuration struct that keeps details about default
|
|
// redundancy strategy information
|
|
type RSConfig struct {
|
|
MaxBufferMem memory.Size `help:"maximum buffer memory (in bytes) to be allocated for read buffers" default:"4MiB" hidden:"true"`
|
|
ErasureShareSize memory.Size `help:"the size of each new erasure share in bytes" default:"256B" hidden:"true"`
|
|
MinThreshold int `help:"the minimum pieces required to recover a segment. k." releaseDefault:"29" devDefault:"4" hidden:"true"`
|
|
RepairThreshold int `help:"the minimum safe pieces before a repair is triggered. m." releaseDefault:"35" devDefault:"6" hidden:"true"`
|
|
SuccessThreshold int `help:"the desired total pieces for a segment. o." releaseDefault:"80" devDefault:"8" hidden:"true"`
|
|
MaxThreshold int `help:"the largest amount of pieces to encode to. n." releaseDefault:"130" devDefault:"10" hidden:"true"`
|
|
}
|
|
|
|
// EncryptionConfig is a configuration struct that keeps details about
|
|
// encrypting segments
|
|
type EncryptionConfig struct {
|
|
DataType int `help:"Type of encryption to use for content and metadata (2=AES-GCM, 3=SecretBox)" default:"2"`
|
|
PathType int `help:"Type of encryption to use for paths (1=Unencrypted, 2=AES-GCM, 3=SecretBox)" default:"2"`
|
|
}
|
|
|
|
// ClientConfig is a configuration struct for the uplink that controls how
|
|
// to talk to the rest of the network.
|
|
type ClientConfig struct {
|
|
MaxInlineSize memory.Size `help:"max inline segment size in bytes" default:"4KiB"`
|
|
SegmentSize memory.Size `help:"the size of a segment in bytes" default:"64MiB"`
|
|
DialTimeout time.Duration `help:"timeout for dials" default:"0h2m00s"`
|
|
}
|
|
|
|
// Config uplink configuration
|
|
type Config struct {
|
|
ScopeConfig
|
|
Client ClientConfig
|
|
RS RSConfig
|
|
Enc EncryptionConfig
|
|
TLS tlsopts.Config
|
|
}
|
|
|
|
// ScopeConfig holds information about which scopes exist and are selected.
|
|
type ScopeConfig struct {
|
|
Scopes map[string]string `internal:"true"`
|
|
Scope string `help:"the serialized scope, or name of the scope to use" default:""`
|
|
|
|
Legacy // Holds on to legacy configuration values
|
|
}
|
|
|
|
// Legacy holds deprecated configuration values
|
|
type Legacy struct {
|
|
Client struct {
|
|
APIKey string `default:"" help:"the api key to use for the satellite (deprecated)" noprefix:"true" deprecated:"true"`
|
|
SatelliteAddr string `releaseDefault:"127.0.0.1:7777" devDefault:"127.0.0.1:10000" help:"the address to use for the satellite (deprecated)" noprefix:"true"`
|
|
}
|
|
Enc struct {
|
|
EncryptionKey string `help:"the root key for encrypting the data which will be stored in KeyFilePath (deprecated)" setup:"true" deprecated:"true"`
|
|
KeyFilepath string `help:"the path to the file which contains the root key for encrypting the data (deprecated)" deprecated:"true"`
|
|
EncAccessFilepath string `help:"the path to a file containing a serialized encryption access (deprecated)" deprecated:"true"`
|
|
}
|
|
}
|
|
|
|
// GetScope returns the appropriate scope for the config.
|
|
func (c ScopeConfig) GetScope() (_ *libuplink.Scope, err error) {
|
|
defer mon.Task()(nil)(&err)
|
|
|
|
// if a scope exists for that name, try to load it.
|
|
if data, ok := c.Scopes[c.Scope]; ok && c.Scope != "" {
|
|
return libuplink.ParseScope(data)
|
|
}
|
|
|
|
// Otherwise, try to load the scope name as a serialized scope.
|
|
if scope, err := libuplink.ParseScope(c.Scope); err == nil {
|
|
return scope, nil
|
|
}
|
|
|
|
// fall back to trying to load the legacy values.
|
|
apiKey, err := libuplink.ParseAPIKey(c.Legacy.Client.APIKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
satelliteAddr := c.Legacy.Client.SatelliteAddr
|
|
if satelliteAddr == "" {
|
|
return nil, errs.New("must specify a satellite address")
|
|
}
|
|
|
|
var encAccess *libuplink.EncryptionAccess
|
|
if c.Legacy.Enc.EncAccessFilepath != "" {
|
|
data, err := ioutil.ReadFile(c.Legacy.Enc.EncAccessFilepath)
|
|
if err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
encAccess, err = libuplink.ParseEncryptionAccess(strings.TrimSpace(string(data)))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
data := []byte(c.Legacy.Enc.EncryptionKey)
|
|
if c.Legacy.Enc.KeyFilepath != "" {
|
|
data, err = ioutil.ReadFile(c.Legacy.Enc.KeyFilepath)
|
|
if err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
}
|
|
key, err := storj.NewKey(data)
|
|
if err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
encAccess = libuplink.NewEncryptionAccessWithDefaultKey(*key)
|
|
}
|
|
|
|
return &libuplink.Scope{
|
|
APIKey: apiKey,
|
|
SatelliteAddr: satelliteAddr,
|
|
EncryptionAccess: encAccess,
|
|
}, nil
|
|
}
|
|
|
|
// GetRedundancyScheme returns the configured redundancy scheme for new uploads
|
|
func (c Config) GetRedundancyScheme() storj.RedundancyScheme {
|
|
return storj.RedundancyScheme{
|
|
Algorithm: storj.ReedSolomon,
|
|
ShareSize: c.RS.ErasureShareSize.Int32(),
|
|
RequiredShares: int16(c.RS.MinThreshold),
|
|
RepairShares: int16(c.RS.RepairThreshold),
|
|
OptimalShares: int16(c.RS.SuccessThreshold),
|
|
TotalShares: int16(c.RS.MaxThreshold),
|
|
}
|
|
}
|
|
|
|
// GetPathCipherSuite returns the cipher suite used for path encryption for bucket objects
|
|
func (c Config) GetPathCipherSuite() storj.CipherSuite {
|
|
return storj.CipherSuite(c.Enc.PathType)
|
|
}
|
|
|
|
// GetEncryptionParameters returns the configured encryption scheme for new uploads
|
|
// Blocksize should align with the stripe size therefore multiples of stripes
|
|
// should fit in every encryption block. Instead of lettings users configure this
|
|
// multiple value, we hardcode stripesPerBlock as 2 for simplicity.
|
|
func (c Config) GetEncryptionParameters() storj.EncryptionParameters {
|
|
const stripesPerBlock = 2
|
|
return storj.EncryptionParameters{
|
|
CipherSuite: storj.CipherSuite(c.Enc.DataType),
|
|
BlockSize: c.GetRedundancyScheme().StripeSize() * stripesPerBlock,
|
|
}
|
|
}
|
|
|
|
// GetSegmentSize returns the segment size set in uplink config
|
|
func (c Config) GetSegmentSize() memory.Size {
|
|
return c.Client.SegmentSize
|
|
}
|