You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
4.5 KiB

  1. // Copyright 2017-2018 DERO Project. All rights reserved.
  2. // Use of this source code in any form is governed by RESEARCH license.
  3. // license can be found in the LICENSE file.
  4. // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
  5. //
  6. //
  7. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
  8. // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  9. // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  10. // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  11. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  12. // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  13. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  14. // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  15. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16. package p2p
  17. import "net"
  18. import "time"
  19. import "sync/atomic"
  20. import log "github.com/sirupsen/logrus"
  21. import "github.com/arnaucode/derosuite/globals"
  22. import "github.com/arnaucode/derosuite/blockchain"
  23. var chain *blockchain.Blockchain // external reference to chain
  24. var Exit_Event = make(chan bool) // causes all threads to exit
  25. var Exit_In_Progress bool // marks we are doing exit
  26. var logger *log.Entry // global logger, every logger in this package is a child of this
  27. // Initialize P2P subsystem
  28. func P2P_Init(params map[string]interface{}) error {
  29. logger = globals.Logger.WithFields(log.Fields{"com": "P2P"}) // all components must use this logger
  30. chain = params["chain"].(*blockchain.Blockchain)
  31. go P2P_engine() // start outgoing engine
  32. go P2P_Server_v1() // start accepting connections
  33. logger.Infof("P2P started")
  34. atomic.AddUint32(&globals.Subsystem_Active, 1) // increment subsystem
  35. return nil
  36. }
  37. func P2P_engine() {
  38. // if user provided ips at command line , use them, currently we use only the first one
  39. var end_point_list []string
  40. if _, ok := globals.Arguments["--add-exclusive-node"]; ok { // check if parameter is supported
  41. if globals.Arguments["--add-exclusive-node"] != nil {
  42. tmp_list := globals.Arguments["--add-exclusive-node"].([]string)
  43. for i := range tmp_list {
  44. end_point_list = append(end_point_list, tmp_list[i])
  45. }
  46. }
  47. }
  48. // add hard-coded seeds
  49. end_point_list = append(end_point_list, "212.8.242.60:18090")
  50. for {
  51. if Exit_In_Progress {
  52. return
  53. }
  54. //remote_addr := "localhost:18090"
  55. //remote_addr := "192.168.56.1:18090"
  56. remote_addr := end_point_list[0]
  57. remote_ip, err := net.ResolveTCPAddr("tcp", remote_addr)
  58. if err != nil {
  59. if Exit_In_Progress {
  60. return
  61. }
  62. logger.Debugf("Resolve address failed:", err.Error())
  63. time.Sleep(2 * time.Second)
  64. continue
  65. }
  66. // since we may be connecting through socks, grab the remote ip for our purpose rightnow
  67. conn, err := globals.Dialer.Dial("tcp", remote_ip.String())
  68. if err != nil {
  69. if Exit_In_Progress {
  70. return
  71. }
  72. logger.Debugf("Dial failed err %s", err.Error())
  73. time.Sleep(2 * time.Second)
  74. continue
  75. }
  76. logger.Debugf("Connection established to %s", remote_ip)
  77. Handle_Connection(conn, remote_ip, false) // handle connection
  78. time.Sleep(4 * time.Second)
  79. }
  80. }
  81. func P2P_Server_v1() {
  82. // listen to incoming tcp connections
  83. l, err := net.Listen("tcp", "0.0.0.0:30000")
  84. if err != nil {
  85. logger.Fatalf("Could not listen on port 30000, errr %s", err)
  86. }
  87. defer l.Close()
  88. // p2p is shutting down, close the listening socket
  89. go func() {
  90. <-Exit_Event
  91. l.Close()
  92. }()
  93. // A common pattern is to start a loop to continously accept connections
  94. for {
  95. conn, err := l.Accept() //accept connections using Listener.Accept()
  96. if err != nil {
  97. if Exit_In_Progress { // break the loop, since we are exiting
  98. break
  99. }
  100. logger.Warnf("Err while accepting incoming connection errr %s", err)
  101. continue
  102. }
  103. raddr := conn.RemoteAddr().(*net.TCPAddr)
  104. go Handle_Connection(conn, raddr, true) // handle connection in a different go routine
  105. }
  106. }
  107. // shutdown the p2p component
  108. func P2P_Shutdown() {
  109. Exit_In_Progress = true
  110. close(Exit_Event) // send signal to all connections to exit
  111. // TODO we must wait for connections to kill themselves
  112. time.Sleep(1 * time.Second)
  113. logger.Infof("P2P Shutdown")
  114. atomic.AddUint32(&globals.Subsystem_Active, ^uint32(0)) // this decrement 1 fom subsystem
  115. }
  116. func Connection_ShutDown(connection *Connection) {
  117. connection.Conn.Close()
  118. }