]> Cypherpunks.ru repositories - nncp.git/blob - src/yggdrasil.go
ca8629682fe2f2af4e1a43b22d0ea147e76e67a7
[nncp.git] / src / yggdrasil.go
1 //go:build !noyggdrasil
2 // +build !noyggdrasil
3
4 /*
5 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
6 Copyright (C) 2016-2022 Sergey Matveev <stargrave@stargrave.org>
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, version 3 of the License.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 package nncp
22
23 import (
24         "encoding/hex"
25         "errors"
26         "log"
27         "net"
28         "strings"
29
30         iwt "github.com/Arceliar/ironwood/types"
31         gologme "github.com/gologme/log"
32         "github.com/neilalexander/utp"
33         ycfg "github.com/yggdrasil-network/yggdrasil-go/src/config"
34         ycore "github.com/yggdrasil-network/yggdrasil-go/src/core"
35         "golang.org/x/crypto/ed25519"
36 )
37
38 var glog *gologme.Logger
39
40 func init() {
41         glog = gologme.New(log.Writer(), "yggdrasil: ", gologme.Lmsgprefix)
42         glog.EnableLevel("warn")
43         glog.EnableLevel("error")
44         glog.EnableLevel("info")
45 }
46
47 func NewYggdrasilConn(aliases map[string]string, in string) (ConnDeadlined, error) {
48         // pub;prv;peer[, ...]
49         cols := strings.Split(in, ";")
50         if len(cols) < 3 {
51                 return nil, errors.New("invalid yggdrasil: address format")
52         }
53         pubHex, prvHex, peersRaw := cols[0], cols[1], cols[2]
54         if v, ok := aliases[pubHex]; ok {
55                 pubHex = v
56         }
57         if v, ok := aliases[prvHex]; ok {
58                 prvHex = v
59         }
60         if v, ok := aliases[peersRaw]; ok {
61                 peersRaw = v
62         }
63         peers := strings.Split(peersRaw, ",")
64         for i, peer := range peers {
65                 if v, ok := aliases[peer]; ok {
66                         peers[i] = v
67                 }
68         }
69         addrRaw, err := hex.DecodeString(pubHex)
70         if err != nil {
71                 return nil, err
72         }
73         cfg := ycfg.NodeConfig{
74                 PrivateKey:      prvHex,
75                 Peers:           peers,
76                 NodeInfo:        map[string]interface{}{"name": "NNCP " + Version},
77                 NodeInfoPrivacy: true,
78         }
79         core := &ycore.Core{}
80         if err := core.Start(&cfg, glog); err != nil {
81                 return nil, err
82         }
83         utpSock, err := utp.NewSocketFromPacketConn(core)
84         if err != nil {
85                 return nil, err
86         }
87         addr := make(iwt.Addr, ed25519.PublicKeySize)
88         copy(addr, addrRaw)
89         return utpSock.DialAddr(addr)
90 }
91
92 func NewYggdrasilListener(aliases map[string]string, in string) (net.Listener, error) {
93         // prv;bind[, ...];[pub, ...];[peer, ...]
94         cols := strings.Split(in, ";")
95         if len(cols) < 4 {
96                 return nil, errors.New("invalid -yggdrasil address format")
97         }
98         prvHex, bindsRaw, pubsRaw, peersRaw := cols[0], cols[1], cols[2], cols[3]
99         if v, ok := aliases[prvHex]; ok {
100                 prvHex = v
101         }
102         if v, ok := aliases[bindsRaw]; ok {
103                 bindsRaw = v
104         }
105         binds := strings.Split(bindsRaw, ",")
106         for i, bind := range binds {
107                 if v, ok := aliases[bind]; ok {
108                         binds[i] = v
109                 }
110         }
111         if v, ok := aliases[pubsRaw]; ok {
112                 pubsRaw = v
113         }
114         pubs := strings.Split(pubsRaw, ",")
115         if len(pubs) == 1 && pubs[0] == "" {
116                 pubs = nil
117         }
118         for i, pub := range pubs {
119                 if v, ok := aliases[pub]; ok {
120                         pubs[i] = v
121                 }
122         }
123         if v, ok := aliases[peersRaw]; ok {
124                 peersRaw = v
125         }
126         peers := strings.Split(peersRaw, ",")
127         if len(peers) == 1 && peers[0] == "" {
128                 peers = nil
129         }
130         for i, peer := range peers {
131                 if v, ok := aliases[peer]; ok {
132                         peers[i] = v
133                 }
134         }
135         cfg := ycfg.NodeConfig{
136                 PrivateKey:        prvHex,
137                 Listen:            binds,
138                 AllowedPublicKeys: pubs,
139                 Peers:             peers,
140                 NodeInfo:          map[string]interface{}{"name": "NNCP " + Version},
141                 NodeInfoPrivacy:   true,
142         }
143         core := &ycore.Core{}
144         if err := core.Start(&cfg, glog); err != nil {
145                 return nil, err
146         }
147         utpSock, err := utp.NewSocketFromPacketConn(core)
148         if err != nil {
149                 return nil, err
150         }
151         return utpSock, nil
152 }