structs.go 5.5 KB

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