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.

185 lines
4.0 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  1. package p2p
  2. import (
  3. "fmt"
  4. "net"
  5. "strconv"
  6. "sync/atomic"
  7. . "github.com/tendermint/tendermint/binary"
  8. . "github.com/tendermint/tendermint/common"
  9. "github.com/tendermint/tendermint/p2p/upnp"
  10. )
  11. /*
  12. Listener is part of a Server.
  13. */
  14. type Listener interface {
  15. Connections() <-chan *Connection
  16. ExternalAddress() *NetAddress
  17. Stop()
  18. }
  19. /*
  20. DefaultListener is an implementation that works on the golang network stack.
  21. */
  22. type DefaultListener struct {
  23. listener net.Listener
  24. extAddr *NetAddress
  25. connections chan *Connection
  26. stopped uint32
  27. }
  28. const (
  29. numBufferedConnections = 10
  30. defaultExternalPort = 8770
  31. )
  32. func splitHostPort(addr string) (host string, port int) {
  33. host, portStr, err := net.SplitHostPort(addr)
  34. if err != nil {
  35. panic(err)
  36. }
  37. port, err = strconv.Atoi(portStr)
  38. if err != nil {
  39. panic(err)
  40. }
  41. return host, port
  42. }
  43. func NewDefaultListener(protocol string, lAddr string) Listener {
  44. // Local listen IP & port
  45. lAddrIP, lAddrPort := splitHostPort(lAddr)
  46. // Create listener
  47. listener, err := net.Listen(protocol, lAddr)
  48. if err != nil {
  49. panic(err)
  50. }
  51. // Actual listener local IP & port
  52. listenerIP, listenerPort := splitHostPort(listener.Addr().String())
  53. log.Debug("Local listener: %v:%v", listenerIP, listenerPort)
  54. // Determine external address...
  55. var extAddr *NetAddress
  56. // If the lAddrIP is INADDR_ANY, try UPnP
  57. if lAddrIP == "" || lAddrIP == "0.0.0.0" {
  58. extAddr = getUPNPExternalAddress(lAddrPort, listenerPort)
  59. }
  60. // Otherwise just use the local address...
  61. if extAddr == nil {
  62. extAddr = getNaiveExternalAddress(listenerPort)
  63. }
  64. if extAddr == nil {
  65. panic("Could not determine external address!")
  66. }
  67. dl := &DefaultListener{
  68. listener: listener,
  69. extAddr: extAddr,
  70. connections: make(chan *Connection, numBufferedConnections),
  71. }
  72. go dl.listenHandler()
  73. return dl
  74. }
  75. // TODO: prevent abuse, esp a bunch of connections coming from the same IP range.
  76. func (l *DefaultListener) listenHandler() {
  77. for {
  78. conn, err := l.listener.Accept()
  79. if atomic.LoadUint32(&l.stopped) == 1 {
  80. break // Go to cleanup
  81. }
  82. // listener wasn't stopped,
  83. // yet we encountered an error.
  84. if err != nil {
  85. panic(err)
  86. }
  87. c := NewConnection(conn)
  88. l.connections <- c
  89. }
  90. // Cleanup
  91. close(l.connections)
  92. for _ = range l.connections {
  93. // Drain
  94. }
  95. }
  96. // A channel of inbound connections.
  97. // It gets closed when the listener closes.
  98. func (l *DefaultListener) Connections() <-chan *Connection {
  99. return l.connections
  100. }
  101. func (l *DefaultListener) ExternalAddress() *NetAddress {
  102. return l.extAddr
  103. }
  104. func (l *DefaultListener) Stop() {
  105. if atomic.CompareAndSwapUint32(&l.stopped, 0, 1) {
  106. l.listener.Close()
  107. }
  108. }
  109. func (l *DefaultListener) String() string {
  110. return fmt.Sprintf("Listener(@%v)", l.extAddr)
  111. }
  112. /* external address helpers */
  113. // UPNP external address discovery & port mapping
  114. func getUPNPExternalAddress(externalPort, internalPort int) *NetAddress {
  115. log.Debug("Getting UPNP external address")
  116. nat, err := upnp.Discover()
  117. if err != nil {
  118. log.Debug("Could not get UPNP extrernal address: %v", err)
  119. return nil
  120. }
  121. ext, err := nat.GetExternalAddress()
  122. if err != nil {
  123. log.Debug("Could not get UPNP external address: %v", err)
  124. return nil
  125. }
  126. // UPnP can't seem to get the external port, so let's just be explicit.
  127. if externalPort == 0 {
  128. externalPort = defaultExternalPort
  129. }
  130. externalPort, err = nat.AddPortMapping("tcp", externalPort, internalPort, "tendermint", 0)
  131. if err != nil {
  132. log.Debug("Could not get UPNP external address: %v", err)
  133. return nil
  134. }
  135. log.Debug("Got UPNP external address: %v", ext)
  136. return NewNetAddressIPPort(ext, UInt16(externalPort))
  137. }
  138. // TODO: use syscalls: http://pastebin.com/9exZG4rh
  139. func getNaiveExternalAddress(port int) *NetAddress {
  140. addrs, err := net.InterfaceAddrs()
  141. if err != nil {
  142. Panicf("Unexpected error fetching interface addresses: %v", err)
  143. }
  144. for _, a := range addrs {
  145. ipnet, ok := a.(*net.IPNet)
  146. if !ok {
  147. continue
  148. }
  149. v4 := ipnet.IP.To4()
  150. if v4 == nil || v4[0] == 127 {
  151. continue
  152. } // loopback
  153. return NewNetAddressIPPort(ipnet.IP, UInt16(port))
  154. }
  155. return nil
  156. }