options.go 8.8 KB

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