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.

196 lines
4.2 KiB

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