1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
package config
import (
"encoding/json"
"io/ioutil"
"reflect"
"regexp"
"strings"
"github.com/bfix/gospel/crypto/ed25519"
"github.com/bfix/gospel/logger"
"gnunet/util"
)
///////////////////////////////////////////////////////////////////////
// GNS configuration
// GNSConfig
type GNSConfig struct {
Endpoint string `json:"endpoint"` // end-point of GNS service
DHTReplLevel int `json:"dhtReplLevel"` // DHT replication level
RootZones map[string]string `json:"rootZones"` // pre-configured root zones
}
// GetRootZoneKey returns the zone key (PKEY) for a pre-configured root with given name.
func (gns *GNSConfig) GetRootZoneKey(name string) *ed25519.PublicKey {
// lookup key in the dictionary
if dStr, ok := gns.RootZones[name]; ok {
if data, err := util.DecodeStringToBinary(dStr, 32); err == nil {
return ed25519.NewPublicKeyFromBytes(data)
}
}
// no pkey found.
return nil
}
///////////////////////////////////////////////////////////////////////
// DHT configuration
// DHTConfig
type DHTConfig struct {
Endpoint string `json:"endpoint"` // end-point of DHT service
}
///////////////////////////////////////////////////////////////////////
// Namecache configuration
// NamecacheConfig
type NamecacheConfig struct {
Endpoint string `json:"endpoint"` // end-point of Namecache service
}
///////////////////////////////////////////////////////////////////////
// Environment settings
type Environ map[string]string
// Config is the aggregated configuration for GNUnet.
type Config struct {
Env Environ `json:"environ"`
DHT *DHTConfig `json:"dht"`
GNS *GNSConfig `json:"gns"`
Namecache *NamecacheConfig `json:"namecache"`
}
var (
Cfg *Config
)
// Parse a JSON-encoded configuration file map it to the Config data structure.
func ParseConfig(fileName string) (err error) {
// parse configuration file
file, err := ioutil.ReadFile(fileName)
if err != nil {
return
}
// unmarshal to Config data structure
Cfg = new(Config)
if err = json.Unmarshal(file, Cfg); err == nil {
// process all string-based config settings and apply
// string substitutions.
applySubstitutions(Cfg, Cfg.Env)
}
return
}
var (
rx = regexp.MustCompile("\\$\\{([^\\}]*)\\}")
)
func substString(s string, env map[string]string) string {
matches := rx.FindAllStringSubmatch(s, -1)
for _, m := range matches {
if len(m[1]) != 0 {
subst, ok := env[m[1]]
if !ok {
continue
}
s = strings.Replace(s, "${"+m[1]+"}", subst, -1)
}
}
return s
}
// applySubstitutions
func applySubstitutions(x interface{}, env map[string]string) {
var process func(v reflect.Value)
process = func(v reflect.Value) {
for i := 0; i < v.NumField(); i++ {
fld := v.Field(i)
if fld.CanSet() {
switch fld.Kind() {
case reflect.String:
// check for substitution
s := fld.Interface().(string)
for {
s1 := substString(s, env)
if s1 == s {
break
}
logger.Printf(logger.DBG, "[config] %s --> %s\n", s, s1)
fld.SetString(s1)
s = s1
}
case reflect.Struct:
// handle nested struct
process(fld)
case reflect.Ptr:
// handle pointer
e := fld.Elem()
if e.IsValid() {
process(fld.Elem())
} else {
logger.Printf(logger.ERROR, "[config] 'nil' pointer encountered")
}
}
}
}
}
v := reflect.ValueOf(x)
switch v.Kind() {
case reflect.Ptr:
e := v.Elem()
if e.IsValid() {
process(e)
} else {
logger.Printf(logger.ERROR, "[config] 'nil' pointer encountered")
}
case reflect.Struct:
process(v)
}
}
|