structs.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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. "context"
  9. "crypto/tls"
  10. "fmt"
  11. "io"
  12. "net"
  13. "net/url"
  14. "time"
  15. "github.com/syncthing/syncthing/lib/config"
  16. "github.com/syncthing/syncthing/lib/connections/registry"
  17. "github.com/syncthing/syncthing/lib/nat"
  18. "github.com/syncthing/syncthing/lib/osutil"
  19. "github.com/syncthing/syncthing/lib/protocol"
  20. "github.com/syncthing/syncthing/lib/stats"
  21. "github.com/thejerf/suture/v4"
  22. )
  23. type tlsConn interface {
  24. io.ReadWriteCloser
  25. ConnectionState() tls.ConnectionState
  26. RemoteAddr() net.Addr
  27. SetDeadline(time.Time) error
  28. SetWriteDeadline(time.Time) error
  29. LocalAddr() net.Addr
  30. }
  31. // internalConn is the raw TLS connection plus some metadata on where it
  32. // came from (type, priority).
  33. type internalConn struct {
  34. tlsConn
  35. connType connType
  36. isLocal bool
  37. priority int
  38. establishedAt time.Time
  39. connectionID string // set after Hello exchange
  40. }
  41. type connType int
  42. const (
  43. connTypeRelayClient connType = iota
  44. connTypeRelayServer
  45. connTypeTCPClient
  46. connTypeTCPServer
  47. connTypeQUICClient
  48. connTypeQUICServer
  49. )
  50. func (t connType) String() string {
  51. switch t {
  52. case connTypeRelayClient:
  53. return "relay-client"
  54. case connTypeRelayServer:
  55. return "relay-server"
  56. case connTypeTCPClient:
  57. return "tcp-client"
  58. case connTypeTCPServer:
  59. return "tcp-server"
  60. case connTypeQUICClient:
  61. return "quic-client"
  62. case connTypeQUICServer:
  63. return "quic-server"
  64. default:
  65. return "unknown-type"
  66. }
  67. }
  68. func (t connType) Transport() string {
  69. switch t {
  70. case connTypeRelayClient, connTypeRelayServer:
  71. return "relay"
  72. case connTypeTCPClient, connTypeTCPServer:
  73. return "tcp"
  74. case connTypeQUICClient, connTypeQUICServer:
  75. return "quic"
  76. default:
  77. return "unknown"
  78. }
  79. }
  80. func newInternalConn(tc tlsConn, connType connType, isLocal bool, priority int) internalConn {
  81. now := time.Now()
  82. return internalConn{
  83. tlsConn: tc,
  84. connType: connType,
  85. isLocal: isLocal,
  86. priority: priority,
  87. establishedAt: now.Truncate(time.Second),
  88. }
  89. }
  90. func (c internalConn) Close() error {
  91. // *tls.Conn.Close() does more than it says on the tin. Specifically, it
  92. // sends a TLS alert message, which might block forever if the
  93. // connection is dead and we don't have a deadline set.
  94. _ = c.SetWriteDeadline(time.Now().Add(250 * time.Millisecond))
  95. return c.tlsConn.Close()
  96. }
  97. func (c internalConn) Type() string {
  98. return c.connType.String()
  99. }
  100. func (c internalConn) IsLocal() bool {
  101. return c.isLocal
  102. }
  103. func (c internalConn) Priority() int {
  104. return c.priority
  105. }
  106. func (c internalConn) Crypto() string {
  107. cs := c.ConnectionState()
  108. return fmt.Sprintf("%s-%s", tlsVersionNames[cs.Version], tlsCipherSuiteNames[cs.CipherSuite])
  109. }
  110. func (c internalConn) Transport() string {
  111. transport := c.connType.Transport()
  112. ip, err := osutil.IPFromAddr(c.RemoteAddr())
  113. if err != nil {
  114. return transport
  115. }
  116. if ip.To4() != nil {
  117. return transport + "4"
  118. }
  119. return transport + "6"
  120. }
  121. func (c internalConn) EstablishedAt() time.Time {
  122. return c.establishedAt
  123. }
  124. func (c internalConn) ConnectionID() string {
  125. return c.connectionID
  126. }
  127. func (c internalConn) String() string {
  128. t := "WAN"
  129. if c.isLocal {
  130. t = "LAN"
  131. }
  132. return fmt.Sprintf("%s-%s/%s/%s/%s-P%d-%s", c.LocalAddr(), c.RemoteAddr(), c.Type(), c.Crypto(), t, c.Priority(), c.connectionID)
  133. }
  134. type dialerFactory interface {
  135. New(config.OptionsConfiguration, *tls.Config, *registry.Registry, *lanChecker) genericDialer
  136. AlwaysWAN() bool
  137. Valid(config.Configuration) error
  138. String() string
  139. }
  140. type commonDialer struct {
  141. trafficClass int
  142. reconnectInterval time.Duration
  143. tlsCfg *tls.Config
  144. lanChecker *lanChecker
  145. lanPriority int
  146. wanPriority int
  147. allowsMultiConns bool
  148. }
  149. func (d *commonDialer) RedialFrequency() time.Duration {
  150. return d.reconnectInterval
  151. }
  152. func (d *commonDialer) Priority(host string) int {
  153. if d.lanChecker.isLANHost(host) {
  154. return d.lanPriority
  155. }
  156. return d.wanPriority
  157. }
  158. func (d *commonDialer) AllowsMultiConns() bool {
  159. return d.allowsMultiConns
  160. }
  161. type genericDialer interface {
  162. Dial(context.Context, protocol.DeviceID, *url.URL) (internalConn, error)
  163. RedialFrequency() time.Duration
  164. Priority(host string) int
  165. AllowsMultiConns() bool
  166. }
  167. type listenerFactory interface {
  168. New(*url.URL, config.Wrapper, *tls.Config, chan internalConn, *nat.Service, *registry.Registry, *lanChecker) genericListener
  169. Valid(config.Configuration) error
  170. }
  171. type ListenerAddresses struct {
  172. URI *url.URL
  173. WANAddresses []*url.URL
  174. LANAddresses []*url.URL
  175. }
  176. type genericListener interface {
  177. suture.Service
  178. URI() *url.URL
  179. // A given address can potentially be mutated by the listener.
  180. // For example we bind to tcp://0.0.0.0, but that for example might return
  181. // tcp://gateway1.ip and tcp://gateway2.ip as WAN addresses due to there
  182. // being multiple gateways, and us managing to get a UPnP mapping on both
  183. // and tcp://192.168.0.1 and tcp://10.0.0.1 due to there being multiple
  184. // network interfaces. (The later case for LAN addresses is made up just
  185. // to provide an example)
  186. WANAddresses() []*url.URL
  187. LANAddresses() []*url.URL
  188. Error() error
  189. OnAddressesChanged(func(ListenerAddresses))
  190. String() string
  191. Factory() listenerFactory
  192. NATType() string
  193. }
  194. type Model interface {
  195. protocol.Model
  196. AddConnection(conn protocol.Connection, hello protocol.Hello)
  197. OnHello(protocol.DeviceID, net.Addr, protocol.Hello) error
  198. DeviceStatistics() (map[protocol.DeviceID]stats.DeviceStatistics, error)
  199. }
  200. type onAddressesChangedNotifier struct {
  201. callbacks []func(ListenerAddresses)
  202. }
  203. func (o *onAddressesChangedNotifier) OnAddressesChanged(callback func(ListenerAddresses)) {
  204. o.callbacks = append(o.callbacks, callback)
  205. }
  206. func (o *onAddressesChangedNotifier) notifyAddressesChanged(l genericListener) {
  207. o.notifyAddresses(ListenerAddresses{
  208. URI: l.URI(),
  209. WANAddresses: l.WANAddresses(),
  210. LANAddresses: l.LANAddresses(),
  211. })
  212. }
  213. func (o *onAddressesChangedNotifier) clearAddresses(l genericListener) {
  214. o.notifyAddresses(ListenerAddresses{
  215. URI: l.URI(),
  216. })
  217. }
  218. func (o *onAddressesChangedNotifier) notifyAddresses(l ListenerAddresses) {
  219. for _, callback := range o.callbacks {
  220. callback(l)
  221. }
  222. }
  223. type dialTarget struct {
  224. addr string
  225. dialer genericDialer
  226. priority int
  227. uri *url.URL
  228. deviceID protocol.DeviceID
  229. }
  230. func (t dialTarget) Dial(ctx context.Context) (internalConn, error) {
  231. l.Debugln("dialing", t.deviceID, t.uri, "prio", t.priority)
  232. return t.dialer.Dial(ctx, t.deviceID, t.uri)
  233. }