options.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. // Copyright © 2021 Ettore Di Giacinto <[email protected]>
  2. //
  3. // This program is free software; you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation; either version 2 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License along
  14. // with this program; if not, see <http://www.gnu.org/licenses/>.
  15. package node
  16. import (
  17. "encoding/base64"
  18. "io/ioutil"
  19. "time"
  20. "github.com/ipfs/go-log"
  21. "github.com/libp2p/go-libp2p"
  22. dht "github.com/libp2p/go-libp2p-kad-dht"
  23. "github.com/mudler/edgevpn/pkg/blockchain"
  24. discovery "github.com/mudler/edgevpn/pkg/discovery"
  25. "github.com/mudler/edgevpn/pkg/protocol"
  26. "github.com/mudler/edgevpn/pkg/utils"
  27. "github.com/pkg/errors"
  28. "github.com/xlzd/gotp"
  29. "gopkg.in/yaml.v2"
  30. )
  31. // WithLibp2pOptions Overrides defaults options
  32. func WithLibp2pOptions(i ...libp2p.Option) func(cfg *Config) error {
  33. return func(cfg *Config) error {
  34. cfg.Options = i
  35. return nil
  36. }
  37. }
  38. func WithSealer(i Sealer) Option {
  39. return func(cfg *Config) error {
  40. cfg.Sealer = i
  41. return nil
  42. }
  43. }
  44. func WithLibp2pAdditionalOptions(i ...libp2p.Option) func(cfg *Config) error {
  45. return func(cfg *Config) error {
  46. cfg.AdditionalOptions = append(cfg.AdditionalOptions, i...)
  47. return nil
  48. }
  49. }
  50. func WithNetworkService(ns ...NetworkService) func(cfg *Config) error {
  51. return func(cfg *Config) error {
  52. cfg.NetworkServices = append(cfg.NetworkServices, ns...)
  53. return nil
  54. }
  55. }
  56. func WithInterfaceAddress(i string) func(cfg *Config) error {
  57. return func(cfg *Config) error {
  58. cfg.InterfaceAddress = i
  59. return nil
  60. }
  61. }
  62. func WithBlacklist(i ...string) func(cfg *Config) error {
  63. return func(cfg *Config) error {
  64. cfg.Blacklist = i
  65. return nil
  66. }
  67. }
  68. func Logger(l log.StandardLogger) func(cfg *Config) error {
  69. return func(cfg *Config) error {
  70. cfg.Logger = l
  71. return nil
  72. }
  73. }
  74. func WithStore(s blockchain.Store) func(cfg *Config) error {
  75. return func(cfg *Config) error {
  76. cfg.Store = s
  77. return nil
  78. }
  79. }
  80. // Handlers adds a handler to the list that is called on each received message
  81. func Handlers(h ...Handler) func(cfg *Config) error {
  82. return func(cfg *Config) error {
  83. cfg.Handlers = append(cfg.Handlers, h...)
  84. return nil
  85. }
  86. }
  87. // GenericChannelHandlers adds a handler to the list that is called on each received message in the generic channel (not the one allocated for the blockchain)
  88. func GenericChannelHandlers(h ...Handler) func(cfg *Config) error {
  89. return func(cfg *Config) error {
  90. cfg.GenericChannelHandler = append(cfg.GenericChannelHandler, h...)
  91. return nil
  92. }
  93. }
  94. // WithStreamHandler adds a handler to the list that is called on each received message
  95. func WithStreamHandler(id protocol.Protocol, h StreamHandler) func(cfg *Config) error {
  96. return func(cfg *Config) error {
  97. cfg.StreamHandlers[id] = h
  98. return nil
  99. }
  100. }
  101. // DiscoveryService Adds the service given as argument to the discovery services
  102. func DiscoveryService(s ...ServiceDiscovery) func(cfg *Config) error {
  103. return func(cfg *Config) error {
  104. cfg.ServiceDiscovery = append(cfg.ServiceDiscovery, s...)
  105. return nil
  106. }
  107. }
  108. // EnableGenericHub enables an additional generic hub between peers.
  109. // This can be used to exchange messages between peers that are not related to any
  110. // blockchain event. For instance, messages could be used for authentication, or for other sort
  111. // of application.
  112. var EnableGenericHub = func(cfg *Config) error {
  113. cfg.GenericHub = true
  114. return nil
  115. }
  116. func ListenAddresses(ss ...string) func(cfg *Config) error {
  117. return func(cfg *Config) error {
  118. for _, s := range ss {
  119. a := &discovery.AddrList{}
  120. err := a.Set(s)
  121. if err != nil {
  122. return err
  123. }
  124. cfg.ListenAddresses = append(cfg.ListenAddresses, *a)
  125. }
  126. return nil
  127. }
  128. }
  129. func Insecure(b bool) func(cfg *Config) error {
  130. return func(cfg *Config) error {
  131. cfg.Insecure = b
  132. return nil
  133. }
  134. }
  135. func ExchangeKeys(s string) func(cfg *Config) error {
  136. return func(cfg *Config) error {
  137. cfg.ExchangeKey = s
  138. return nil
  139. }
  140. }
  141. func RoomName(s string) func(cfg *Config) error {
  142. return func(cfg *Config) error {
  143. cfg.RoomName = s
  144. return nil
  145. }
  146. }
  147. func SealKeyInterval(i int) func(cfg *Config) error {
  148. return func(cfg *Config) error {
  149. cfg.SealKeyInterval = i
  150. return nil
  151. }
  152. }
  153. func SealKeyLength(i int) func(cfg *Config) error {
  154. return func(cfg *Config) error {
  155. cfg.SealKeyLength = i
  156. return nil
  157. }
  158. }
  159. func LibP2PLogLevel(l log.LogLevel) func(cfg *Config) error {
  160. return func(cfg *Config) error {
  161. log.SetAllLoggers(l)
  162. return nil
  163. }
  164. }
  165. func MaxMessageSize(i int) func(cfg *Config) error {
  166. return func(cfg *Config) error {
  167. cfg.MaxMessageSize = i
  168. return nil
  169. }
  170. }
  171. func WithPeerGater(d Gater) Option {
  172. return func(cfg *Config) error {
  173. cfg.PeerGater = d
  174. return nil
  175. }
  176. }
  177. func WithLedgerAnnounceTime(t time.Duration) func(cfg *Config) error {
  178. return func(cfg *Config) error {
  179. cfg.LedgerAnnounceTime = t
  180. return nil
  181. }
  182. }
  183. func WithLedgerInterval(t time.Duration) func(cfg *Config) error {
  184. return func(cfg *Config) error {
  185. cfg.LedgerSyncronizationTime = t
  186. return nil
  187. }
  188. }
  189. func WithDiscoveryInterval(t time.Duration) func(cfg *Config) error {
  190. return func(cfg *Config) error {
  191. cfg.DiscoveryInterval = t
  192. return nil
  193. }
  194. }
  195. func WithDiscoveryBootstrapPeers(a discovery.AddrList) func(cfg *Config) error {
  196. return func(cfg *Config) error {
  197. cfg.DiscoveryBootstrapPeers = a
  198. return nil
  199. }
  200. }
  201. type OTPConfig struct {
  202. Interval int `yaml:"interval"`
  203. Key string `yaml:"key"`
  204. Length int `yaml:"length"`
  205. }
  206. type OTP struct {
  207. DHT OTPConfig `yaml:"dht"`
  208. Crypto OTPConfig `yaml:"crypto"`
  209. }
  210. type YAMLConnectionConfig struct {
  211. OTP OTP `yaml:"otp"`
  212. RoomName string `yaml:"room"`
  213. Rendezvous string `yaml:"rendezvous"`
  214. MDNS string `yaml:"mdns"`
  215. MaxMessageSize int `yaml:"max_message_size"`
  216. }
  217. // Base64 returns the base64 string representation of the connection
  218. func (y YAMLConnectionConfig) Base64() string {
  219. bytesData, _ := yaml.Marshal(y)
  220. return base64.StdEncoding.EncodeToString(bytesData)
  221. }
  222. // YAML returns the connection config as yaml string
  223. func (y YAMLConnectionConfig) YAML() string {
  224. bytesData, _ := yaml.Marshal(y)
  225. return string(bytesData)
  226. }
  227. func (y YAMLConnectionConfig) copy(mdns, dht bool, cfg *Config, opts ...dht.Option) {
  228. d := discovery.NewDHT(opts...)
  229. d.RefreshDiscoveryTime = cfg.DiscoveryInterval
  230. d.OTPInterval = y.OTP.DHT.Interval
  231. d.OTPKey = y.OTP.DHT.Key
  232. d.KeyLength = y.OTP.DHT.Length
  233. d.RendezvousString = y.Rendezvous
  234. d.BootstrapPeers = cfg.DiscoveryBootstrapPeers
  235. m := &discovery.MDNS{DiscoveryServiceTag: y.MDNS}
  236. cfg.ExchangeKey = y.OTP.Crypto.Key
  237. cfg.RoomName = y.RoomName
  238. cfg.SealKeyInterval = y.OTP.Crypto.Interval
  239. // cfg.ServiceDiscovery = []ServiceDiscovery{d, m}
  240. if mdns {
  241. cfg.ServiceDiscovery = append(cfg.ServiceDiscovery, m)
  242. }
  243. if dht {
  244. cfg.ServiceDiscovery = append(cfg.ServiceDiscovery, d)
  245. }
  246. cfg.SealKeyLength = y.OTP.Crypto.Length
  247. cfg.MaxMessageSize = y.MaxMessageSize
  248. }
  249. const defaultKeyLength = 32
  250. func GenerateNewConnectionData(i ...int) *YAMLConnectionConfig {
  251. defaultInterval := 9000
  252. maxMessSize := 20 << 20 // 20MB
  253. if len(i) >= 2 {
  254. defaultInterval = i[0]
  255. maxMessSize = i[1]
  256. } else if len(i) == 1 {
  257. defaultInterval = i[0]
  258. }
  259. return &YAMLConnectionConfig{
  260. MaxMessageSize: maxMessSize,
  261. RoomName: gotp.RandomSecret(defaultKeyLength),
  262. Rendezvous: utils.RandStringRunes(defaultKeyLength),
  263. MDNS: utils.RandStringRunes(defaultKeyLength),
  264. OTP: OTP{
  265. DHT: OTPConfig{
  266. Key: gotp.RandomSecret(defaultKeyLength),
  267. Interval: defaultInterval,
  268. Length: defaultKeyLength,
  269. },
  270. Crypto: OTPConfig{
  271. Key: gotp.RandomSecret(defaultKeyLength),
  272. Interval: defaultInterval,
  273. Length: defaultKeyLength,
  274. },
  275. },
  276. }
  277. }
  278. func FromYaml(enablemDNS, enableDHT bool, path string, d ...dht.Option) func(cfg *Config) error {
  279. return func(cfg *Config) error {
  280. if len(path) == 0 {
  281. return nil
  282. }
  283. t := YAMLConnectionConfig{}
  284. data, err := ioutil.ReadFile(path)
  285. if err != nil {
  286. return errors.Wrap(err, "reading yaml file")
  287. }
  288. if err := yaml.Unmarshal(data, &t); err != nil {
  289. return errors.Wrap(err, "parsing yaml")
  290. }
  291. t.copy(enablemDNS, enableDHT, cfg, d...)
  292. return nil
  293. }
  294. }
  295. func FromBase64(enablemDNS, enableDHT bool, bb string, d ...dht.Option) func(cfg *Config) error {
  296. return func(cfg *Config) error {
  297. if len(bb) == 0 {
  298. return nil
  299. }
  300. configDec, err := base64.StdEncoding.DecodeString(bb)
  301. if err != nil {
  302. return err
  303. }
  304. t := YAMLConnectionConfig{}
  305. if err := yaml.Unmarshal(configDec, &t); err != nil {
  306. return errors.Wrap(err, "parsing yaml")
  307. }
  308. t.copy(enablemDNS, enableDHT, cfg, d...)
  309. return nil
  310. }
  311. }