structs.go 6.0 KB

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