storj/uplink/config.go
JT Olio 2c6fa3c5f8
pkg/rpc: remove read/write deadlines as a mechanism for request timeouts (#3335)
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
2019-10-22 17:57:24 -06:00

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
}