network.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. package p2p
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "net"
  6. "strconv"
  7. "time"
  8. )
  9. const (
  10. DialerTimeout = 180 //seconds
  11. KeepAlivePeriod = 60 //minutes
  12. portMappingUpdateInterval = 900 // seconds = 15 mins
  13. upnpDiscoverAttempts = 3
  14. )
  15. // Dialer is not an interface in net, so we define one
  16. // *net.Dialer conforms to this
  17. type Dialer interface {
  18. Dial(network, address string) (net.Conn, error)
  19. }
  20. type Network interface {
  21. Start() error
  22. Listener(net.Addr) (net.Listener, error)
  23. Dialer(net.Addr) (Dialer, error)
  24. NewAddr(string, int) (addr net.Addr, err error)
  25. ParseAddr(string) (addr net.Addr, err error)
  26. }
  27. type NAT interface {
  28. GetExternalAddress() (addr net.IP, err error)
  29. AddPortMapping(protocol string, externalPort, internalPort int, description string, timeout int) (mappedExternalPort int, err error)
  30. DeletePortMapping(protocol string, externalPort, internalPort int) (err error)
  31. }
  32. type TCPNetwork struct {
  33. nat NAT
  34. natType NATType
  35. quit chan chan bool
  36. ports chan string
  37. }
  38. type NATType int
  39. const (
  40. NONE = iota
  41. UPNP
  42. PMP
  43. )
  44. const (
  45. portMappingTimeout = 1200 // 20 mins
  46. )
  47. func NewTCPNetwork(natType NATType) (net *TCPNetwork) {
  48. return &TCPNetwork{
  49. natType: natType,
  50. ports: make(chan string),
  51. }
  52. }
  53. func (self *TCPNetwork) Dialer(addr net.Addr) (Dialer, error) {
  54. return &net.Dialer{
  55. Timeout: DialerTimeout * time.Second,
  56. // KeepAlive: KeepAlivePeriod * time.Minute,
  57. LocalAddr: addr,
  58. }, nil
  59. }
  60. func (self *TCPNetwork) Listener(addr net.Addr) (net.Listener, error) {
  61. if self.natType == UPNP {
  62. _, port, _ := net.SplitHostPort(addr.String())
  63. if self.quit == nil {
  64. self.quit = make(chan chan bool)
  65. go self.updatePortMappings()
  66. }
  67. self.ports <- port
  68. }
  69. return net.Listen(addr.Network(), addr.String())
  70. }
  71. func (self *TCPNetwork) Start() (err error) {
  72. switch self.natType {
  73. case NONE:
  74. case UPNP:
  75. nat, uerr := upnpDiscover(upnpDiscoverAttempts)
  76. if uerr != nil {
  77. err = fmt.Errorf("UPNP failed: ", uerr)
  78. } else {
  79. self.nat = nat
  80. }
  81. case PMP:
  82. err = fmt.Errorf("PMP not implemented")
  83. default:
  84. err = fmt.Errorf("Invalid NAT type: %v", self.natType)
  85. }
  86. return
  87. }
  88. func (self *TCPNetwork) Stop() {
  89. q := make(chan bool)
  90. self.quit <- q
  91. <-q
  92. }
  93. func (self *TCPNetwork) addPortMapping(lport int) (err error) {
  94. _, err = self.nat.AddPortMapping("TCP", lport, lport, "p2p listen port", portMappingTimeout)
  95. if err != nil {
  96. logger.Errorf("unable to add port mapping on %v: %v", lport, err)
  97. } else {
  98. logger.Debugf("succesfully added port mapping on %v", lport)
  99. }
  100. return
  101. }
  102. func (self *TCPNetwork) updatePortMappings() {
  103. timer := time.NewTimer(portMappingUpdateInterval * time.Second)
  104. lports := []int{}
  105. out:
  106. for {
  107. select {
  108. case port := <-self.ports:
  109. int64lport, _ := strconv.ParseInt(port, 10, 16)
  110. lport := int(int64lport)
  111. if err := self.addPortMapping(lport); err != nil {
  112. lports = append(lports, lport)
  113. }
  114. case <-timer.C:
  115. for lport := range lports {
  116. if err := self.addPortMapping(lport); err != nil {
  117. }
  118. }
  119. case errc := <-self.quit:
  120. errc <- true
  121. break out
  122. }
  123. }
  124. timer.Stop()
  125. for lport := range lports {
  126. if err := self.nat.DeletePortMapping("TCP", lport, lport); err != nil {
  127. logger.Debugf("unable to remove port mapping on %v: %v", lport, err)
  128. } else {
  129. logger.Debugf("succesfully removed port mapping on %v", lport)
  130. }
  131. }
  132. }
  133. func (self *TCPNetwork) NewAddr(host string, port int) (net.Addr, error) {
  134. ip, err := self.lookupIP(host)
  135. if err == nil {
  136. return &net.TCPAddr{
  137. IP: ip,
  138. Port: port,
  139. }, nil
  140. }
  141. return nil, err
  142. }
  143. func (self *TCPNetwork) ParseAddr(address string) (net.Addr, error) {
  144. host, port, err := net.SplitHostPort(address)
  145. if err == nil {
  146. iport, _ := strconv.Atoi(port)
  147. addr, e := self.NewAddr(host, iport)
  148. return addr, e
  149. }
  150. return nil, err
  151. }
  152. func (*TCPNetwork) lookupIP(host string) (ip net.IP, err error) {
  153. if ip = net.ParseIP(host); ip != nil {
  154. return
  155. }
  156. var ips []net.IP
  157. ips, err = net.LookupIP(host)
  158. if err != nil {
  159. logger.Warnln(err)
  160. return
  161. }
  162. if len(ips) == 0 {
  163. err = fmt.Errorf("No IP addresses available for %v", host)
  164. logger.Warnln(err)
  165. return
  166. }
  167. if len(ips) > 1 {
  168. // Pick a random IP address, simulating round-robin DNS.
  169. rand.Seed(time.Now().UTC().UnixNano())
  170. ip = ips[rand.Intn(len(ips))]
  171. } else {
  172. ip = ips[0]
  173. }
  174. return
  175. }