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.

130 lines
3.8 KiB

  1. package p2p
  2. /* this file implements the connection pool manager, keeping a list of active connections etc
  3. * this will also ensure that a single IP is connected only once
  4. *
  5. */
  6. import "fmt"
  7. import "net"
  8. import "sync"
  9. import "container/list"
  10. import log "github.com/sirupsen/logrus"
  11. import "github.com/deroproject/derosuite/crypto"
  12. // any connection incoming/outgoing can only be in this state
  13. type Conn_State string
  14. const (
  15. HANDSHAKE_PENDING Conn_State = "Pending"
  16. IDLE = "Idle"
  17. ACTIVE = "Active"
  18. )
  19. // This structure is used to do book keeping for the connection and keeps other DATA related to peer
  20. type Connection struct {
  21. Incoming bool // is connection incoming or outgoing
  22. Addr *net.TCPAddr // endpoint on the other end
  23. Port uint32 // port advertised by other end as its server,if it's 0 server cannot accept connections
  24. Peer_ID uint64 // Remote peer id
  25. Last_Height uint64 // last height sent by peer
  26. Top_Version uint64 // current hard fork version supported by peer
  27. Exit bool // Exit marker that connection needs to be killed
  28. State Conn_State // state of the connection
  29. Top_ID crypto.Hash // top block id of the connection
  30. Cumulative_Difficulty uint64 // cumulative difficulty of top block of peer
  31. logger *log.Entry // connection specific logger
  32. Requested_Objects [][32]byte // currently unused as we sync up with a single peer at a time
  33. Conn net.Conn // actual object to talk
  34. Command_queue *list.List // LEVIN protocol is syncronous
  35. sync.Mutex
  36. }
  37. var connection_map = map[string]*Connection{}
  38. var connection_mutex sync.Mutex
  39. func Key(ip net.IP) string {
  40. return string(ip.To16()) // Simple []byte => string conversion
  41. }
  42. // check whether an IP is in the map already
  43. func IsConnected(ip net.IP) bool {
  44. connection_mutex.Lock()
  45. defer connection_mutex.Unlock()
  46. if _, ok := connection_map[Key(ip)]; ok {
  47. return true
  48. }
  49. return false
  50. }
  51. // add connection to map
  52. func Connection_Add(c *Connection) {
  53. connection_mutex.Lock()
  54. defer connection_mutex.Unlock()
  55. connection_map[Key(c.Addr.IP)] = c
  56. }
  57. // add connection to map
  58. func Connection_Delete(c *Connection) {
  59. connection_mutex.Lock()
  60. defer connection_mutex.Unlock()
  61. delete(connection_map, Key(c.Addr.IP))
  62. }
  63. // prints all the connection info to screen
  64. func Connection_Print() {
  65. connection_mutex.Lock()
  66. defer connection_mutex.Unlock()
  67. fmt.Printf("Connection info for peers\n")
  68. fmt.Printf("%-20s %-16s %-5s %-7s %9s %3s\n", "Remote Addr", "PEER ID", "PORT", " State", "Height","DIR")
  69. for _, v := range connection_map {
  70. dir := "OUT"
  71. if v.Incoming {
  72. dir = "INC"
  73. }
  74. fmt.Printf("%-20s %16x %5d %7s %9d %s\n", v.Addr.IP, v.Peer_ID, v.Port, v.State, v.Last_Height, dir)
  75. }
  76. }
  77. // for continuos update on command line, get the maximum height of all peers
  78. func Best_Peer_Height() (best_height uint64) {
  79. connection_mutex.Lock()
  80. for _, v := range connection_map {
  81. if v.Last_Height > best_height {
  82. best_height = v.Last_Height
  83. }
  84. }
  85. connection_mutex.Unlock()
  86. return
  87. }
  88. // this function return peer count which have successful handshake
  89. func Peer_Count() (Count uint64) {
  90. connection_mutex.Lock()
  91. for _, v := range connection_map {
  92. if v.State != HANDSHAKE_PENDING {
  93. Count++
  94. }
  95. }
  96. connection_mutex.Unlock()
  97. return
  98. }
  99. // this returns count of peers in both directions
  100. func Peer_Direction_Count() (Incoming uint64, Outgoing uint64) {
  101. connection_mutex.Lock()
  102. for _, v := range connection_map {
  103. if v.State != HANDSHAKE_PENDING {
  104. if v.Incoming{
  105. Incoming++
  106. }else{
  107. Outgoing++
  108. }
  109. }
  110. }
  111. connection_mutex.Unlock()
  112. return
  113. }