structs.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // Copyright (C) 2016 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package connections
  7. import (
  8. "crypto/tls"
  9. "fmt"
  10. "net"
  11. "net/url"
  12. "time"
  13. "github.com/syncthing/syncthing/lib/config"
  14. "github.com/syncthing/syncthing/lib/nat"
  15. "github.com/syncthing/syncthing/lib/protocol"
  16. )
  17. // Connection is what we expose to the outside. It is a protocol.Connection
  18. // that can be closed and has some metadata.
  19. type Connection interface {
  20. protocol.Connection
  21. Type() string
  22. Transport() string
  23. RemoteAddr() net.Addr
  24. Priority() int
  25. String() string
  26. Crypto() string
  27. }
  28. // completeConn is the aggregation of an internalConn and the
  29. // protocol.Connection running on top of it. It implements the Connection
  30. // interface.
  31. type completeConn struct {
  32. internalConn
  33. protocol.Connection
  34. }
  35. func (c completeConn) Close(err error) {
  36. c.Connection.Close(err)
  37. c.internalConn.Close()
  38. }
  39. // internalConn is the raw TLS connection plus some metadata on where it
  40. // came from (type, priority).
  41. type internalConn struct {
  42. *tls.Conn
  43. connType connType
  44. priority int
  45. }
  46. type connType int
  47. const (
  48. connTypeRelayClient connType = iota
  49. connTypeRelayServer
  50. connTypeTCPClient
  51. connTypeTCPServer
  52. )
  53. func (t connType) String() string {
  54. switch t {
  55. case connTypeRelayClient:
  56. return "relay-client"
  57. case connTypeRelayServer:
  58. return "relay-server"
  59. case connTypeTCPClient:
  60. return "tcp-client"
  61. case connTypeTCPServer:
  62. return "tcp-server"
  63. default:
  64. return "unknown-type"
  65. }
  66. }
  67. func (t connType) Transport() string {
  68. switch t {
  69. case connTypeRelayClient, connTypeRelayServer:
  70. return "relay"
  71. case connTypeTCPClient, connTypeTCPServer:
  72. return "tcp"
  73. default:
  74. return "unknown"
  75. }
  76. }
  77. func (c internalConn) Close() {
  78. // *tls.Conn.Close() does more than it says on the tin. Specifically, it
  79. // sends a TLS alert message, which might block forever if the
  80. // connection is dead and we don't have a deadline set.
  81. c.SetWriteDeadline(time.Now().Add(250 * time.Millisecond))
  82. c.Conn.Close()
  83. }
  84. func (c internalConn) Type() string {
  85. return c.connType.String()
  86. }
  87. func (c internalConn) Priority() int {
  88. return c.priority
  89. }
  90. func (c internalConn) Crypto() string {
  91. cs := c.ConnectionState()
  92. return fmt.Sprintf("%s-%s", tlsVersionNames[cs.Version], tlsCipherSuiteNames[cs.CipherSuite])
  93. }
  94. func (c internalConn) Transport() string {
  95. transport := c.connType.Transport()
  96. host, _, err := net.SplitHostPort(c.LocalAddr().String())
  97. if err != nil {
  98. return transport
  99. }
  100. ip := net.ParseIP(host)
  101. if ip == nil {
  102. return transport
  103. }
  104. if ip.To4() != nil {
  105. return transport + "4"
  106. }
  107. return transport + "6"
  108. }
  109. func (c internalConn) String() string {
  110. return fmt.Sprintf("%s-%s/%s/%s", c.LocalAddr(), c.RemoteAddr(), c.Type(), c.Crypto())
  111. }
  112. type dialerFactory interface {
  113. New(config.Wrapper, *tls.Config) genericDialer
  114. Priority() int
  115. AlwaysWAN() bool
  116. Valid(config.Configuration) error
  117. String() string
  118. }
  119. type genericDialer interface {
  120. Dial(protocol.DeviceID, *url.URL) (internalConn, error)
  121. RedialFrequency() time.Duration
  122. }
  123. type listenerFactory interface {
  124. New(*url.URL, config.Wrapper, *tls.Config, chan internalConn, *nat.Service) genericListener
  125. Valid(config.Configuration) error
  126. }
  127. type genericListener interface {
  128. Serve()
  129. Stop()
  130. URI() *url.URL
  131. // A given address can potentially be mutated by the listener.
  132. // For example we bind to tcp://0.0.0.0, but that for example might return
  133. // tcp://gateway1.ip and tcp://gateway2.ip as WAN addresses due to there
  134. // being multiple gateways, and us managing to get a UPnP mapping on both
  135. // and tcp://192.168.0.1 and tcp://10.0.0.1 due to there being multiple
  136. // network interfaces. (The later case for LAN addresses is made up just
  137. // to provide an example)
  138. WANAddresses() []*url.URL
  139. LANAddresses() []*url.URL
  140. Error() error
  141. OnAddressesChanged(func(genericListener))
  142. String() string
  143. Factory() listenerFactory
  144. NATType() string
  145. }
  146. type Model interface {
  147. protocol.Model
  148. AddConnection(conn Connection, hello protocol.HelloResult)
  149. Connection(remoteID protocol.DeviceID) (Connection, bool)
  150. OnHello(protocol.DeviceID, net.Addr, protocol.HelloResult) error
  151. GetHello(protocol.DeviceID) protocol.HelloIntf
  152. }
  153. // serviceFunc wraps a function to create a suture.Service without stop
  154. // functionality.
  155. type serviceFunc func()
  156. func (f serviceFunc) Serve() { f() }
  157. func (f serviceFunc) Stop() {}
  158. type onAddressesChangedNotifier struct {
  159. callbacks []func(genericListener)
  160. }
  161. func (o *onAddressesChangedNotifier) OnAddressesChanged(callback func(genericListener)) {
  162. o.callbacks = append(o.callbacks, callback)
  163. }
  164. func (o *onAddressesChangedNotifier) notifyAddressesChanged(l genericListener) {
  165. for _, callback := range o.callbacks {
  166. callback(l)
  167. }
  168. }
  169. type dialTarget struct {
  170. dialer genericDialer
  171. priority int
  172. uri *url.URL
  173. deviceID protocol.DeviceID
  174. }
  175. func (t dialTarget) Dial() (internalConn, error) {
  176. l.Debugln("dialing", t.deviceID, t.uri, "prio", t.priority)
  177. conn, err := t.dialer.Dial(t.deviceID, t.uri)
  178. if err != nil {
  179. l.Debugln("dialing", t.deviceID, t.uri, "error:", err)
  180. } else {
  181. l.Debugln("dialing", t.deviceID, t.uri, "success:", conn)
  182. }
  183. return conn, err
  184. }