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.

221 lines
4.9 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
  1. package p2p
  2. import (
  3. "fmt"
  4. "net"
  5. "strconv"
  6. "time"
  7. . "github.com/tendermint/tendermint/common"
  8. "github.com/tendermint/tendermint/p2p/upnp"
  9. )
  10. type Listener interface {
  11. Connections() <-chan net.Conn
  12. InternalAddress() *NetAddress
  13. ExternalAddress() *NetAddress
  14. String() string
  15. Stop() bool
  16. }
  17. // Implements Listener
  18. type DefaultListener struct {
  19. BaseService
  20. listener net.Listener
  21. intAddr *NetAddress
  22. extAddr *NetAddress
  23. connections chan net.Conn
  24. }
  25. const (
  26. numBufferedConnections = 10
  27. defaultExternalPort = 8770
  28. tryListenSeconds = 5
  29. )
  30. func splitHostPort(addr string) (host string, port int) {
  31. host, portStr, err := net.SplitHostPort(addr)
  32. if err != nil {
  33. PanicSanity(err)
  34. }
  35. port, err = strconv.Atoi(portStr)
  36. if err != nil {
  37. PanicSanity(err)
  38. }
  39. return host, port
  40. }
  41. func NewDefaultListener(protocol string, lAddr string, requireUPNPHairpin bool) Listener {
  42. // Local listen IP & port
  43. lAddrIP, lAddrPort := splitHostPort(lAddr)
  44. // Create listener
  45. var listener net.Listener
  46. var err error
  47. for i := 0; i < tryListenSeconds; i++ {
  48. listener, err = net.Listen(protocol, lAddr)
  49. if err == nil {
  50. break
  51. } else if i < tryListenSeconds-1 {
  52. time.Sleep(time.Second * 1)
  53. }
  54. }
  55. if err != nil {
  56. PanicCrisis(err)
  57. }
  58. // Actual listener local IP & port
  59. listenerIP, listenerPort := splitHostPort(listener.Addr().String())
  60. log.Info("Local listener", "ip", listenerIP, "port", listenerPort)
  61. // Determine internal address...
  62. var intAddr *NetAddress = NewNetAddressString(lAddr)
  63. // Determine external address...
  64. var extAddr *NetAddress
  65. // If the lAddrIP is INADDR_ANY, try UPnP
  66. if lAddrIP == "" || lAddrIP == "0.0.0.0" {
  67. if requireUPNPHairpin {
  68. upnpCapabilities, err := upnp.Probe()
  69. if err != nil {
  70. log.Warn("Failed to probe UPNP", "error", err)
  71. goto SKIP_UPNP
  72. }
  73. if !upnpCapabilities.Hairpin {
  74. goto SKIP_UPNP
  75. }
  76. }
  77. extAddr = getUPNPExternalAddress(lAddrPort, listenerPort)
  78. }
  79. SKIP_UPNP:
  80. // Otherwise just use the local address...
  81. if extAddr == nil {
  82. extAddr = getNaiveExternalAddress(listenerPort)
  83. }
  84. if extAddr == nil {
  85. PanicCrisis("Could not determine external address!")
  86. }
  87. dl := &DefaultListener{
  88. listener: listener,
  89. intAddr: intAddr,
  90. extAddr: extAddr,
  91. connections: make(chan net.Conn, numBufferedConnections),
  92. }
  93. dl.BaseService = *NewBaseService(log, "DefaultListener", dl)
  94. dl.Start() // Started upon construction
  95. return dl
  96. }
  97. func (l *DefaultListener) OnStart() {
  98. l.BaseService.OnStart()
  99. go l.listenRoutine()
  100. }
  101. func (l *DefaultListener) OnStop() {
  102. l.BaseService.OnStop()
  103. l.listener.Close()
  104. }
  105. // Accept connections and pass on the channel
  106. func (l *DefaultListener) listenRoutine() {
  107. for {
  108. conn, err := l.listener.Accept()
  109. if !l.IsRunning() {
  110. break // Go to cleanup
  111. }
  112. // listener wasn't stopped,
  113. // yet we encountered an error.
  114. if err != nil {
  115. PanicCrisis(err)
  116. }
  117. l.connections <- conn
  118. }
  119. // Cleanup
  120. close(l.connections)
  121. for _ = range l.connections {
  122. // Drain
  123. }
  124. }
  125. // A channel of inbound connections.
  126. // It gets closed when the listener closes.
  127. func (l *DefaultListener) Connections() <-chan net.Conn {
  128. return l.connections
  129. }
  130. func (l *DefaultListener) InternalAddress() *NetAddress {
  131. return l.intAddr
  132. }
  133. func (l *DefaultListener) ExternalAddress() *NetAddress {
  134. return l.extAddr
  135. }
  136. // NOTE: The returned listener is already Accept()'ing.
  137. // So it's not suitable to pass into http.Serve().
  138. func (l *DefaultListener) NetListener() net.Listener {
  139. return l.listener
  140. }
  141. func (l *DefaultListener) String() string {
  142. return fmt.Sprintf("Listener(@%v)", l.extAddr)
  143. }
  144. /* external address helpers */
  145. // UPNP external address discovery & port mapping
  146. func getUPNPExternalAddress(externalPort, internalPort int) *NetAddress {
  147. log.Info("Getting UPNP external address")
  148. nat, err := upnp.Discover()
  149. if err != nil {
  150. log.Info("Could not perform UPNP discover", "error", err)
  151. return nil
  152. }
  153. ext, err := nat.GetExternalAddress()
  154. if err != nil {
  155. log.Info("Could not get UPNP external address", "error", err)
  156. return nil
  157. }
  158. // UPnP can't seem to get the external port, so let's just be explicit.
  159. if externalPort == 0 {
  160. externalPort = defaultExternalPort
  161. }
  162. externalPort, err = nat.AddPortMapping("tcp", externalPort, internalPort, "tendermint", 0)
  163. if err != nil {
  164. log.Info("Could not add UPNP port mapping", "error", err)
  165. return nil
  166. }
  167. log.Info("Got UPNP external address", "address", ext)
  168. return NewNetAddressIPPort(ext, uint16(externalPort))
  169. }
  170. // TODO: use syscalls: http://pastebin.com/9exZG4rh
  171. func getNaiveExternalAddress(port int) *NetAddress {
  172. addrs, err := net.InterfaceAddrs()
  173. if err != nil {
  174. PanicCrisis(Fmt("Could not fetch interface addresses: %v", err))
  175. }
  176. for _, a := range addrs {
  177. ipnet, ok := a.(*net.IPNet)
  178. if !ok {
  179. continue
  180. }
  181. v4 := ipnet.IP.To4()
  182. if v4 == nil || v4[0] == 127 {
  183. continue
  184. } // loopback
  185. return NewNetAddressIPPort(ipnet.IP, uint16(port))
  186. }
  187. return nil
  188. }