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.

147 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. end_point_list = append(end_point_list, "127.0.0.1:18090")
  51. for {
  52. if Exit_In_Progress {
  53. return
  54. }
  55. //remote_addr := "localhost:18090"
  56. //remote_addr := "192.168.56.1:18090"
  57. remote_addr := end_point_list[0]
  58. remote_ip, err := net.ResolveTCPAddr("tcp", remote_addr)
  59. if err != nil {
  60. if Exit_In_Progress {
  61. return
  62. }
  63. logger.Debugf("Resolve address failed:", err.Error())
  64. time.Sleep(2 * time.Second)
  65. continue
  66. }
  67. // since we may be connecting through socks, grab the remote ip for our purpose rightnow
  68. conn, err := globals.Dialer.Dial("tcp", remote_ip.String())
  69. if err != nil {
  70. if Exit_In_Progress {
  71. return
  72. }
  73. logger.Debugf("Dial failed err %s", err.Error())
  74. time.Sleep(2 * time.Second)
  75. continue
  76. }
  77. logger.Debugf("Connection established to %s", remote_ip)
  78. Handle_Connection(conn, remote_ip, false) // handle connection
  79. time.Sleep(4 * time.Second)
  80. }
  81. }
  82. func P2P_Server_v1() {
  83. // listen to incoming tcp connections
  84. l, err := net.Listen("tcp", "0.0.0.0:30000")
  85. if err != nil {
  86. logger.Fatalf("Could not listen on port 30000, errr %s", err)
  87. }
  88. defer l.Close()
  89. // p2p is shutting down, close the listening socket
  90. go func() {
  91. <-Exit_Event
  92. l.Close()
  93. }()
  94. // A common pattern is to start a loop to continously accept connections
  95. for {
  96. conn, err := l.Accept() //accept connections using Listener.Accept()
  97. if err != nil {
  98. if Exit_In_Progress { // break the loop, since we are exiting
  99. break
  100. }
  101. logger.Warnf("Err while accepting incoming connection errr %s", err)
  102. continue
  103. }
  104. raddr := conn.RemoteAddr().(*net.TCPAddr)
  105. go Handle_Connection(conn, raddr, true) // handle connection in a different go routine
  106. }
  107. }
  108. // shutdown the p2p component
  109. func P2P_Shutdown() {
  110. Exit_In_Progress = true
  111. close(Exit_Event) // send signal to all connections to exit
  112. // TODO we must wait for connections to kill themselves
  113. time.Sleep(1 * time.Second)
  114. logger.Infof("P2P Shutdown")
  115. atomic.AddUint32(&globals.Subsystem_Active, ^uint32(0)) // this decrement 1 fom subsystem
  116. }
  117. func Connection_ShutDown(connection *Connection) {
  118. connection.Conn.Close()
  119. }