structs.go 6.0 KB

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