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.

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