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.

184 lines
4.0 KiB

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