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.

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