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.

284 lines
7.1 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package p2p
  2. import (
  3. "fmt"
  4. "net"
  5. "strconv"
  6. "strings"
  7. "time"
  8. cmn "github.com/tendermint/tendermint/libs/common"
  9. "github.com/tendermint/tendermint/libs/log"
  10. "github.com/tendermint/tendermint/p2p/upnp"
  11. )
  12. // Listener is a network listener for stream-oriented protocols, providing
  13. // convenient methods to get listener's internal and external addresses.
  14. // Clients are supposed to read incoming connections from a channel, returned
  15. // by Connections() method.
  16. type Listener interface {
  17. Connections() <-chan net.Conn
  18. InternalAddress() *NetAddress
  19. ExternalAddress() *NetAddress
  20. ExternalAddressHost() string
  21. String() string
  22. Stop() error
  23. }
  24. // DefaultListener is a cmn.Service, running net.Listener underneath.
  25. // Optionally, UPnP is used upon calling NewDefaultListener to resolve external
  26. // address.
  27. type DefaultListener struct {
  28. cmn.BaseService
  29. listener net.Listener
  30. intAddr *NetAddress
  31. extAddr *NetAddress
  32. connections chan net.Conn
  33. }
  34. var _ Listener = (*DefaultListener)(nil)
  35. const (
  36. numBufferedConnections = 10
  37. defaultExternalPort = 8770
  38. tryListenSeconds = 5
  39. )
  40. func splitHostPort(addr string) (host string, port int) {
  41. host, portStr, err := net.SplitHostPort(addr)
  42. if err != nil {
  43. panic(err)
  44. }
  45. port, err = strconv.Atoi(portStr)
  46. if err != nil {
  47. panic(err)
  48. }
  49. return host, port
  50. }
  51. // NewDefaultListener creates a new DefaultListener on lAddr, optionally trying
  52. // to determine external address using UPnP.
  53. func NewDefaultListener(
  54. fullListenAddrString string,
  55. externalAddrString string,
  56. useUPnP bool,
  57. logger log.Logger) Listener {
  58. // Split protocol, address, and port.
  59. protocol, lAddr := cmn.ProtocolAndAddress(fullListenAddrString)
  60. lAddrIP, lAddrPort := splitHostPort(lAddr)
  61. // Create listener
  62. var listener net.Listener
  63. var err error
  64. for i := 0; i < tryListenSeconds; i++ {
  65. listener, err = net.Listen(protocol, lAddr)
  66. if err == nil {
  67. break
  68. } else if i < tryListenSeconds-1 {
  69. time.Sleep(time.Second * 1)
  70. }
  71. }
  72. if err != nil {
  73. panic(err)
  74. }
  75. // Actual listener local IP & port
  76. listenerIP, listenerPort := splitHostPort(listener.Addr().String())
  77. logger.Info("Local listener", "ip", listenerIP, "port", listenerPort)
  78. // Determine internal address...
  79. var intAddr *NetAddress
  80. intAddr, err = NewNetAddressStringWithOptionalID(lAddr)
  81. if err != nil {
  82. panic(err)
  83. }
  84. inAddrAny := lAddrIP == "" || lAddrIP == "0.0.0.0"
  85. // Determine external address.
  86. var extAddr *NetAddress
  87. if externalAddrString != "" {
  88. var err error
  89. extAddr, err = NewNetAddressStringWithOptionalID(externalAddrString)
  90. if err != nil {
  91. panic(fmt.Sprintf("Error in ExternalAddress: %v", err))
  92. }
  93. }
  94. // If the lAddrIP is INADDR_ANY, try UPnP.
  95. if extAddr == nil && useUPnP && inAddrAny {
  96. extAddr = getUPNPExternalAddress(lAddrPort, listenerPort, logger)
  97. }
  98. // Otherwise just use the local address.
  99. if extAddr == nil {
  100. defaultToIPv4 := inAddrAny
  101. extAddr = getNaiveExternalAddress(defaultToIPv4, listenerPort, false, logger)
  102. }
  103. if extAddr == nil {
  104. panic("Could not determine external address!")
  105. }
  106. dl := &DefaultListener{
  107. listener: listener,
  108. intAddr: intAddr,
  109. extAddr: extAddr,
  110. connections: make(chan net.Conn, numBufferedConnections),
  111. }
  112. dl.BaseService = *cmn.NewBaseService(logger, "DefaultListener", dl)
  113. err = dl.Start() // Started upon construction
  114. if err != nil {
  115. logger.Error("Error starting base service", "err", err)
  116. }
  117. return dl
  118. }
  119. // OnStart implements cmn.Service by spinning a goroutine, listening for new
  120. // connections.
  121. func (l *DefaultListener) OnStart() error {
  122. if err := l.BaseService.OnStart(); err != nil {
  123. return err
  124. }
  125. go l.listenRoutine()
  126. return nil
  127. }
  128. // OnStop implements cmn.Service by closing the listener.
  129. func (l *DefaultListener) OnStop() {
  130. l.BaseService.OnStop()
  131. l.listener.Close() // nolint: errcheck
  132. }
  133. // Accept connections and pass on the channel
  134. func (l *DefaultListener) listenRoutine() {
  135. for {
  136. conn, err := l.listener.Accept()
  137. if !l.IsRunning() {
  138. break // Go to cleanup
  139. }
  140. // listener wasn't stopped,
  141. // yet we encountered an error.
  142. if err != nil {
  143. panic(err)
  144. }
  145. l.connections <- conn
  146. }
  147. // Cleanup
  148. close(l.connections)
  149. for range l.connections {
  150. // Drain
  151. }
  152. }
  153. // Connections returns a channel of inbound connections.
  154. // It gets closed when the listener closes.
  155. func (l *DefaultListener) Connections() <-chan net.Conn {
  156. return l.connections
  157. }
  158. // InternalAddress returns the internal NetAddress (address used for
  159. // listening).
  160. func (l *DefaultListener) InternalAddress() *NetAddress {
  161. return l.intAddr
  162. }
  163. // ExternalAddress returns the external NetAddress (publicly available,
  164. // determined using either UPnP or local resolver).
  165. func (l *DefaultListener) ExternalAddress() *NetAddress {
  166. return l.extAddr
  167. }
  168. // ExternalAddressHost returns the external NetAddress IP string. If an IP is
  169. // IPv6, it's wrapped in brackets ("[2001:db8:1f70::999:de8:7648:6e8]").
  170. func (l *DefaultListener) ExternalAddressHost() string {
  171. ip := l.ExternalAddress().IP
  172. if isIpv6(ip) {
  173. // Means it's ipv6, so format it with brackets
  174. return "[" + ip.String() + "]"
  175. }
  176. return ip.String()
  177. }
  178. func (l *DefaultListener) String() string {
  179. return fmt.Sprintf("Listener(@%v)", l.extAddr)
  180. }
  181. /* external address helpers */
  182. // UPNP external address discovery & port mapping
  183. func getUPNPExternalAddress(externalPort, internalPort int, logger log.Logger) *NetAddress {
  184. logger.Info("Getting UPNP external address")
  185. nat, err := upnp.Discover()
  186. if err != nil {
  187. logger.Info("Could not perform UPNP discover", "err", err)
  188. return nil
  189. }
  190. ext, err := nat.GetExternalAddress()
  191. if err != nil {
  192. logger.Info("Could not get UPNP external address", "err", err)
  193. return nil
  194. }
  195. // UPnP can't seem to get the external port, so let's just be explicit.
  196. if externalPort == 0 {
  197. externalPort = defaultExternalPort
  198. }
  199. externalPort, err = nat.AddPortMapping("tcp", externalPort, internalPort, "tendermint", 0)
  200. if err != nil {
  201. logger.Info("Could not add UPNP port mapping", "err", err)
  202. return nil
  203. }
  204. logger.Info("Got UPNP external address", "address", ext)
  205. return NewNetAddressIPPort(ext, uint16(externalPort))
  206. }
  207. func isIpv6(ip net.IP) bool {
  208. v4 := ip.To4()
  209. if v4 != nil {
  210. return false
  211. }
  212. ipString := ip.String()
  213. // Extra check just to be sure it's IPv6
  214. return (strings.Contains(ipString, ":") && !strings.Contains(ipString, "."))
  215. }
  216. // TODO: use syscalls: see issue #712
  217. func getNaiveExternalAddress(defaultToIPv4 bool, port int, settleForLocal bool, logger log.Logger) *NetAddress {
  218. addrs, err := net.InterfaceAddrs()
  219. if err != nil {
  220. panic(cmn.Fmt("Could not fetch interface addresses: %v", err))
  221. }
  222. for _, a := range addrs {
  223. ipnet, ok := a.(*net.IPNet)
  224. if !ok {
  225. continue
  226. }
  227. if defaultToIPv4 || !isIpv6(ipnet.IP) {
  228. v4 := ipnet.IP.To4()
  229. if v4 == nil || (!settleForLocal && v4[0] == 127) {
  230. // loopback
  231. continue
  232. }
  233. } else if !settleForLocal && ipnet.IP.IsLoopback() {
  234. // IPv6, check for loopback
  235. continue
  236. }
  237. return NewNetAddressIPPort(ipnet.IP, uint16(port))
  238. }
  239. // try again, but settle for local
  240. logger.Info("Node may not be connected to internet. Settling for local address")
  241. return getNaiveExternalAddress(defaultToIPv4, port, true, logger)
  242. }