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.

191 lines
4.1 KiB

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