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.

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