X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=src%2Fcypherpunks.ru%2Fnncp%2Fcfg.go;h=3400ed83a93e7d850f85da7b47653497592e14a9;hb=97b386a58ef33cac2ba39ac2e273bc632eb026ad;hp=9092be08c83fd48fbe6ec55277f2ff9fa121c6ca;hpb=23cb8cf3f4539e314209ad9976c00696a9969161;p=nncp.git diff --git a/src/cypherpunks.ru/nncp/cfg.go b/src/cypherpunks.ru/nncp/cfg.go index 9092be0..3400ed8 100644 --- a/src/cypherpunks.ru/nncp/cfg.go +++ b/src/cypherpunks.ru/nncp/cfg.go @@ -19,28 +19,55 @@ along with this program. If not, see . package nncp import ( + "bytes" "errors" + "log" + "os" "path" + "github.com/gorhill/cronexpr" "golang.org/x/crypto/ed25519" + "golang.org/x/crypto/ssh/terminal" "gopkg.in/yaml.v2" ) +const ( + CfgPathEnv = "NNCPCFG" +) + var ( DefaultCfgPath string = "/usr/local/etc/nncp.yaml" DefaultSendmailPath string = "/usr/sbin/sendmail" + DefaultSpoolPath string = "/var/spool/nncp" + DefaultLogPath string = "/var/spool/nncp/log" ) type NodeYAML struct { - Id string - ExchPub string - SignPub string - NoisePub string - Incoming *string `incoming,omitempty` - Freq *string `freq,omitempty` - Via []string `via,omitempty` + Id string + ExchPub string + SignPub string + NoisePub *string `noisepub,omitempty` + Sendmail []string `sendmail,omitempty` + Incoming *string `incoming,omitempty` + Freq *string `freq,omitempty` + FreqChunked *uint64 `freqchunked,omitempty` + FreqMinSize *uint64 `freqminsize,omitempty` + Via []string `via,omitempty` + Calls []CallYAML `calls,omitempty` Addrs map[string]string `addrs,omitempty` + + OnlineDeadline *uint `onlinedeadline,omitempty` + MaxOnlineTime *uint `maxonlinetime,omitempty` +} + +type CallYAML struct { + Cron string + Nice *int `nice,omitempty` + Xx *string `xx,omitempty` + Addr *string `addr,omitempty` + OnlineDeadline *uint `onlinedeadline,omitempty` + MaxOnlineTime *uint `maxonlinetime,omitempty` } type NodeOurYAML struct { @@ -64,13 +91,12 @@ type NotifyYAML struct { } type CfgYAML struct { - Self NodeOurYAML + Self *NodeOurYAML `self,omitempty` Neigh map[string]NodeYAML - Spool string - Log string - Sendmail []string - Notify *NotifyYAML `notify,omitempty` + Spool string + Log string + Notify *NotifyYAML `notify,omitempty` } func NewNode(name string, yml NodeYAML) (*Node, error) { @@ -95,12 +121,15 @@ func NewNode(name string, yml NodeYAML) (*Node, error) { return nil, errors.New("Invalid signPub size") } - noisePub, err := FromBase32(yml.NoisePub) - if err != nil { - return nil, err - } - if len(noisePub) != 32 { - return nil, errors.New("Invalid noisePub size") + var noisePub []byte + if yml.NoisePub != nil { + noisePub, err = FromBase32(*yml.NoisePub) + if err != nil { + return nil, err + } + if len(noisePub) != 32 { + return nil, errors.New("Invalid noisePub size") + } } var incoming *string @@ -120,23 +149,107 @@ func NewNode(name string, yml NodeYAML) (*Node, error) { } freq = &fr } + var freqChunked int64 + if yml.FreqChunked != nil { + if *yml.FreqChunked == 0 { + return nil, errors.New("freqchunked value must be greater than zero") + } + freqChunked = int64(*yml.FreqChunked) * 1024 + } + var freqMinSize int64 + if yml.FreqMinSize != nil { + freqMinSize = int64(*yml.FreqMinSize) * 1024 + } + + defOnlineDeadline := uint(DefaultDeadline) + if yml.OnlineDeadline != nil { + if *yml.OnlineDeadline <= 0 { + return nil, errors.New("OnlineDeadline must be at least 1 second") + } + defOnlineDeadline = *yml.OnlineDeadline + } + var defMaxOnlineTime uint + if yml.MaxOnlineTime != nil { + defMaxOnlineTime = *yml.MaxOnlineTime + } + + var calls []*Call + for _, callYml := range yml.Calls { + expr, err := cronexpr.Parse(callYml.Cron) + if err != nil { + return nil, err + } + nice := uint8(255) + if callYml.Nice != nil { + if *callYml.Nice < 1 || *callYml.Nice > 255 { + return nil, errors.New("Nice must be between 1 and 255") + } + nice = uint8(*callYml.Nice) + } + var xx TRxTx + if callYml.Xx != nil { + switch *callYml.Xx { + case "rx": + xx = TRx + case "tx": + xx = TTx + default: + return nil, errors.New("xx field must be either \"rx\" or \"tx\"") + } + } + var addr *string + if callYml.Addr != nil { + if a, exists := yml.Addrs[*callYml.Addr]; exists { + addr = &a + } else { + addr = callYml.Addr + } + } + onlineDeadline := defOnlineDeadline + if callYml.OnlineDeadline != nil { + if *callYml.OnlineDeadline == 0 { + return nil, errors.New("OnlineDeadline must be at least 1 second") + } + onlineDeadline = *callYml.OnlineDeadline + } + var maxOnlineTime uint + if callYml.MaxOnlineTime != nil { + maxOnlineTime = *callYml.MaxOnlineTime + } + calls = append(calls, &Call{ + Cron: expr, + Nice: nice, + Xx: &xx, + Addr: addr, + OnlineDeadline: onlineDeadline, + MaxOnlineTime: maxOnlineTime, + }) + } node := Node{ - Name: name, - Id: nodeId, - ExchPub: new([32]byte), - SignPub: ed25519.PublicKey(signPub), - NoisePub: new([32]byte), - Incoming: incoming, - Freq: freq, - Addrs: yml.Addrs, + Name: name, + Id: nodeId, + ExchPub: new([32]byte), + SignPub: ed25519.PublicKey(signPub), + Sendmail: yml.Sendmail, + Incoming: incoming, + Freq: freq, + FreqChunked: freqChunked, + FreqMinSize: freqMinSize, + Calls: calls, + Addrs: yml.Addrs, + OnlineDeadline: defOnlineDeadline, + MaxOnlineTime: defMaxOnlineTime, } copy(node.ExchPub[:], exchPub) - copy(node.NoisePub[:], noisePub) + if len(noisePub) > 0 { + node.NoisePub = new([32]byte) + copy(node.NoisePub[:], noisePub) + } return &node, nil } -func NewNodeOur(yml NodeOurYAML) (*NodeOur, error) { +func NewNodeOur(yml *NodeOurYAML) (*NodeOur, error) { id, err := NodeIdFromString(yml.Id) if err != nil { return nil, err @@ -224,14 +337,32 @@ func (nodeOur *NodeOur) ToYAML() string { } func CfgParse(data []byte) (*Ctx, error) { + var err error + if bytes.Compare(data[:8], MagicNNCPBv1[:]) == 0 { + os.Stderr.WriteString("Passphrase:") + password, err := terminal.ReadPassword(0) + if err != nil { + log.Fatalln(err) + } + os.Stderr.WriteString("\n") + data, err = DeEBlob(data, password) + if err != nil { + return nil, err + } + } var cfgYAML CfgYAML - err := yaml.Unmarshal(data, &cfgYAML) - if err != nil { + if err = yaml.Unmarshal(data, &cfgYAML); err != nil { return nil, err } - self, err := NewNodeOur(cfgYAML.Self) - if err != nil { - return nil, err + if _, exists := cfgYAML.Neigh["self"]; !exists { + return nil, errors.New("self neighbour missing") + } + var self *NodeOur + if cfgYAML.Self != nil { + self, err = NewNodeOur(cfgYAML.Self) + if err != nil { + return nil, err + } } spoolPath := path.Clean(cfgYAML.Spool) if !path.IsAbs(spoolPath) { @@ -242,12 +373,11 @@ func CfgParse(data []byte) (*Ctx, error) { return nil, errors.New("Log path must be absolute") } ctx := Ctx{ - Spool: spoolPath, - LogPath: logPath, - Self: self, - Neigh: make(map[NodeId]*Node, len(cfgYAML.Neigh)), - Alias: make(map[string]*NodeId), - Sendmail: cfgYAML.Sendmail, + Spool: spoolPath, + LogPath: logPath, + Self: self, + Neigh: make(map[NodeId]*Node, len(cfgYAML.Neigh)), + Alias: make(map[string]*NodeId), } if cfgYAML.Notify != nil { if cfgYAML.Notify.File != nil { @@ -270,6 +400,7 @@ func CfgParse(data []byte) (*Ctx, error) { ctx.Alias[name] = neigh.Id vias[*neigh.Id] = neighYAML.Via } + ctx.SelfId = ctx.Alias["self"] for neighId, viasRaw := range vias { for _, viaRaw := range viasRaw { foundNodeId, err := ctx.FindNode(viaRaw) @@ -284,3 +415,11 @@ func CfgParse(data []byte) (*Ctx, error) { } return &ctx, nil } + +func CfgPathFromEnv(cmdlineFlag *string) (p string) { + p = os.Getenv(CfgPathEnv) + if p == "" { + p = *cmdlineFlag + } + return +}