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.

168 lines
5.4 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 "io"
  18. import "net"
  19. //import "sync"
  20. import "time"
  21. import "runtime/debug"
  22. import "container/list"
  23. import "encoding/binary"
  24. import log "github.com/sirupsen/logrus"
  25. import "github.com/romana/rlog"
  26. import "github.com/vmihailenco/msgpack"
  27. // this function waits for any commands from the connection and suitably responds doing sanity checks
  28. // this is the core of the p2p package
  29. /* this is the entire connection handler, all incoming/outgoing connections end up here */
  30. func Handle_Connection(conn net.Conn, remote_addr *net.TCPAddr, incoming bool) {
  31. var connection Connection
  32. connection.Incoming = incoming
  33. connection.Conn = conn
  34. var idle int
  35. connection.Addr = remote_addr // since we may be connecting via socks, get target IP
  36. connection.Command_queue = list.New() // init command queue
  37. connection.State = HANDSHAKE_PENDING
  38. if incoming {
  39. connection.logger = logger.WithFields(log.Fields{"RIP": remote_addr.String(), "DIR": "INC", "V2": "1"})
  40. } else {
  41. connection.logger = logger.WithFields(log.Fields{"RIP": remote_addr.String(), "DIR": "OUT", "V2": "1"})
  42. }
  43. defer func() {
  44. if r := recover(); r != nil {
  45. connection.logger.Warnf("Recovered while handling connection, Stack trace below", r)
  46. connection.logger.Warnf("Stack trace \n%s", debug.Stack())
  47. }
  48. }()
  49. Connection_Add(&connection) // add connection to pool
  50. if !incoming { // we initiated the connection, we must send the handshake first
  51. connection.Send_Handshake_Command() // send handshake
  52. }
  53. // goroutine to exit the connection if signalled
  54. go func() {
  55. ticker := time.NewTicker(1 * time.Second) // 1 second ticker
  56. for {
  57. select {
  58. case <-ticker.C:
  59. idle++
  60. // if idle more than 13 secs, we should send a timed sync
  61. if idle > 13 {
  62. if connection.State != HANDSHAKE_PENDING {
  63. connection.State = IDLE
  64. }
  65. //Send_Timed_Sync(&connection)
  66. //connection.logger.Debugf("We should send a timed sync")
  67. idle = 0
  68. }
  69. case <-Exit_Event: // p2p is shutting down, close the connection
  70. connection.Exit = true
  71. ticker.Stop() // release resources of timer
  72. Connection_Delete(&connection)
  73. conn.Close()
  74. return // close the connection and close the routine
  75. }
  76. if connection.Exit { // release resources of timer
  77. ticker.Stop()
  78. Connection_Delete(&connection)
  79. conn.Close()
  80. return
  81. }
  82. }
  83. }()
  84. // the infinite loop handler
  85. for {
  86. length_buf := make([]byte, 4, 4) // prefix length is 4 bytes
  87. if connection.Exit {
  88. break
  89. }
  90. read_count, err := io.ReadFull(connection.Conn, length_buf)
  91. if err != nil {
  92. rlog.Tracef(2, "Error while reading command prefix length exiting err:%s\n", err)
  93. connection.Exit = true
  94. continue
  95. }
  96. length := binary.LittleEndian.Uint32(length_buf) // convert little endian bytes 4 bytes to length
  97. // check safety of length, we should not allocate more than 100 MB as that is the limit of the block
  98. command_buf := make([]byte, length, length)
  99. //set_timeout(&connection) // we should not hang for hrs waiting for data to come
  100. read_count, err = io.ReadFull(connection.Conn, command_buf)
  101. if err != nil {
  102. rlog.Tracef(2, "Error while reading command data exiting err:%s\n", err)
  103. connection.Exit = true
  104. continue
  105. }
  106. command_buf = command_buf[:read_count]
  107. var dummy_command Common
  108. err = msgpack.Unmarshal(command_buf, &dummy_command)
  109. if err != nil {
  110. rlog.Tracef(2, "Error while parsing command data exiting err:%s\n", err)
  111. connection.Exit = true
  112. continue
  113. }
  114. // if handshake not done, donot process any command
  115. if !connection.HandShakeCompleted && dummy_command.Command != V2_COMMAND_HANDSHAKE {
  116. rlog.Tracef(2, "Peer Sending something but we are waiting for handshake command data exiting err:%s\n", err)
  117. connection.Exit = true
  118. continue
  119. }
  120. switch dummy_command.Command {
  121. case V2_COMMAND_HANDSHAKE:
  122. var handshake Handshake
  123. err = msgpack.Unmarshal(command_buf, &handshake)
  124. if err != nil {
  125. rlog.Tracef(2, "Error while parsing incoming handshake data exiting err:%s\n", err)
  126. connection.Exit = true
  127. continue
  128. }
  129. case V2_COMMAND_SYNC:
  130. case V2_COMMAND_CHAIN_REQUEST:
  131. case V2_COMMAND_CHAIN_RESPONSE: // this should be verified whether we are waiting for it
  132. case V2_COMMAND_OBJECTS_REQUEST:
  133. case V2_COMMAND_OBJECTS_RESPONSE: // this should be verified whether we are waiting for it
  134. case V2_NOTIFY_NEW_BLOCK:
  135. case V2_NOTIFY_NEW_TX:
  136. }
  137. }
  138. }