config.go 5.96 KB
Newer Older
1
// package config implements the ipfs config file datastructures and utilities.
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
2 3 4
package config

import (
5
	"encoding/base64"
6
	"errors"
7
	"os"
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
8
	"path/filepath"
9 10 11 12
	"strings"

	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
	mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
13

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
14
	ic "github.com/jbenet/go-ipfs/p2p/crypto"
15
	u "github.com/jbenet/go-ipfs/util"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
16
	"github.com/jbenet/go-ipfs/util/debugerror"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
17 18
)

19 20
var log = u.Logger("config")

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
21
// Identity tracks the configuration of the local node's identity.
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
22
type Identity struct {
23
	PeerID  string
24
	PrivKey string
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
25 26
}

27 28 29 30 31 32 33 34
// Logs tracks the configuration of the event logger
type Logs struct {
	Filename   string
	MaxSizeMB  uint64
	MaxBackups uint64
	MaxAgeDays uint64
}

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
35
// Datastore tracks the configuration of the datastore.
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
36
type Datastore struct {
Juan Batiz-Benet's avatar
gofmt  
Juan Batiz-Benet committed
37 38
	Type string
	Path string
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
39 40
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
41 42
// Addresses stores the (string) multiaddr addresses for the node.
type Addresses struct {
43 44 45
	Swarm   []string // addresses for the swarm network
	API     string   // address for the local API (RPC)
	Gateway string   // address to listen on for IPFS HTTP object gateway
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
46 47
}

48 49 50 51 52 53
// Mounts stores the (string) mount points
type Mounts struct {
	IPFS string
	IPNS string
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
54 55
// BootstrapPeer is a peer used to bootstrap the network.
type BootstrapPeer struct {
56
	Address string
57
	PeerID  string // until multiaddr supports ipfs, use another field.
58 59
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
60 61 62 63
func (bp *BootstrapPeer) String() string {
	return bp.Address + "/" + bp.PeerID
}

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
func ParseBootstrapPeer(addr string) (BootstrapPeer, error) {
	// to be replaced with just multiaddr parsing, once ptp is a multiaddr protocol
	idx := strings.LastIndex(addr, "/")
	if idx == -1 {
		return BootstrapPeer{}, errors.New("invalid address")
	}
	addrS := addr[:idx]
	peeridS := addr[idx+1:]

	// make sure addrS parses as a multiaddr.
	if len(addrS) > 0 {
		maddr, err := ma.NewMultiaddr(addrS)
		if err != nil {
			return BootstrapPeer{}, err
		}

		addrS = maddr.String()
	}

	// make sure idS parses as a peer.ID
	_, err := mh.FromB58String(peeridS)
	if err != nil {
		return BootstrapPeer{}, err
	}

	return BootstrapPeer{
		Address: addrS,
		PeerID:  peeridS,
	}, nil
}

func ParseBootstrapPeers(addrs []string) ([]BootstrapPeer, error) {
	peers := make([]BootstrapPeer, len(addrs))
	var err error
	for i, addr := range addrs {
		peers[i], err = ParseBootstrapPeer(addr)
		if err != nil {
			return nil, err
		}
	}
	return peers, nil
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
107 108 109 110 111 112
// Tour stores the ipfs tour read-list and resume point
type Tour struct {
	Last string // last tour topic read
	// Done []string // all topics done so far
}

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
113
// Config is used to load IPFS config files.
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
114
type Config struct {
115 116 117 118 119 120 121 122
	Identity  Identity        // local node's peer identity
	Datastore Datastore       // local node's storage
	Addresses Addresses       // local node's addresses
	Mounts    Mounts          // local node's mount points
	Version   Version         // local node's version management
	Bootstrap []BootstrapPeer // local nodes's bootstrap peers
	Tour      Tour            // local node's tour position
	Logs      Logs            // local node's event log configuration
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
123 124
}

Juan Batiz-Benet's avatar
lint  
Juan Batiz-Benet committed
125
// DefaultPathRoot is the path to the default config dir location.
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
126
const DefaultPathRoot = "~/.go-ipfs"
Juan Batiz-Benet's avatar
lint  
Juan Batiz-Benet committed
127 128

// DefaultConfigFile is the filename of the configuration file
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
129
const DefaultConfigFile = "config"
Juan Batiz-Benet's avatar
lint  
Juan Batiz-Benet committed
130 131

// DefaultDataStoreDirectory is the directory to store all the local IPFS data.
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
132
const DefaultDataStoreDirectory = "datastore"
Juan Batiz-Benet's avatar
lint  
Juan Batiz-Benet committed
133 134

// EnvDir is the environment variable used to change the path root.
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
135 136
const EnvDir = "IPFS_DIR"

137 138 139
// LogsDefaultDirectory is the directory to store all IPFS event logs.
var LogsDefaultDirectory = "logs"

Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
140 141 142
// PathRoot returns the default configuration root directory
func PathRoot() (string, error) {
	dir := os.Getenv(EnvDir)
143 144
	var err error
	if len(dir) == 0 {
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
145
		dir, err = u.TildeExpansion(DefaultPathRoot)
146 147 148
	}
	return dir, err
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
149

Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
150 151 152
// Path returns the path `extension` relative to the configuration root. If an
// empty string is provided for `configroot`, the default root is used.
func Path(configroot, extension string) (string, error) {
153
	if len(configroot) == 0 {
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
154
		dir, err := PathRoot()
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
155 156 157
		if err != nil {
			return "", err
		}
Juan Batiz-Benet's avatar
lint  
Juan Batiz-Benet committed
158
		return filepath.Join(dir, extension), nil
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
159

160
	}
Juan Batiz-Benet's avatar
lint  
Juan Batiz-Benet committed
161
	return filepath.Join(configroot, extension), nil
162
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
163

Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
164 165 166
// DataStorePath returns the default data store path given a configuration root
// (set an empty string to have the default configuration root)
func DataStorePath(configroot string) (string, error) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
167
	return Path(configroot, DefaultDataStoreDirectory)
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
168 169
}

170 171 172 173 174 175
// LogsPath returns the default path for event logs given a configuration root
// (set an empty string to have the default configuration root)
func LogsPath(configroot string) (string, error) {
	return Path(configroot, LogsDefaultDirectory)
}

Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
176 177 178
// Filename returns the configuration file path given a configuration root
// directory. If the configuration root directory is empty, use the default one
func Filename(configroot string) (string, error) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
179
	return Path(configroot, DefaultConfigFile)
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
180 181
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
182
// DecodePrivateKey is a helper to decode the users PrivateKey
183
func (i *Identity) DecodePrivateKey(passphrase string) (ic.PrivKey, error) {
184 185 186 187 188
	pkb, err := base64.StdEncoding.DecodeString(i.PrivKey)
	if err != nil {
		return nil, err
	}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
189 190
	// currently storing key unencrypted. in the future we need to encrypt it.
	// TODO(security)
191
	return ic.UnmarshalPrivateKey(pkb)
192 193
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
194 195
// Load reads given file and returns the read config, or error.
func Load(filename string) (*Config, error) {
196
	// if nothing is there, fail. User must run 'ipfs init'
197
	if !u.FileExists(filename) {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
198
		return nil, debugerror.New("ipfs not initialized, please run 'ipfs init'")
Juan Batiz-Benet's avatar
gofmt  
Juan Batiz-Benet committed
199 200 201
	}

	var cfg Config
202
	err := ReadConfigFile(filename, &cfg)
203 204 205 206 207 208
	if err != nil {
		return nil, err
	}

	// tilde expansion on datastore path
	cfg.Datastore.Path, err = u.TildeExpansion(cfg.Datastore.Path)
Juan Batiz-Benet's avatar
gofmt  
Juan Batiz-Benet committed
209 210 211 212 213
	if err != nil {
		return nil, err
	}

	return &cfg, err
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
214
}
215 216 217

// Set sets the value of a particular config key
func Set(filename, key, value string) error {
218
	return WriteConfigKey(filename, key, value)
219
}