model.go 99 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246
  1. // Copyright (C) 2014 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. //go:generate counterfeiter -o mocks/model.go --fake-name Model . Model
  7. package model
  8. import (
  9. "bytes"
  10. "context"
  11. "encoding/json"
  12. "fmt"
  13. "io"
  14. "net"
  15. "os"
  16. "path/filepath"
  17. "reflect"
  18. "runtime"
  19. "strings"
  20. stdsync "sync"
  21. "time"
  22. "github.com/pkg/errors"
  23. "github.com/thejerf/suture/v4"
  24. "github.com/syncthing/syncthing/lib/config"
  25. "github.com/syncthing/syncthing/lib/connections"
  26. "github.com/syncthing/syncthing/lib/db"
  27. "github.com/syncthing/syncthing/lib/events"
  28. "github.com/syncthing/syncthing/lib/fs"
  29. "github.com/syncthing/syncthing/lib/ignore"
  30. "github.com/syncthing/syncthing/lib/osutil"
  31. "github.com/syncthing/syncthing/lib/protocol"
  32. "github.com/syncthing/syncthing/lib/scanner"
  33. "github.com/syncthing/syncthing/lib/stats"
  34. "github.com/syncthing/syncthing/lib/svcutil"
  35. "github.com/syncthing/syncthing/lib/sync"
  36. "github.com/syncthing/syncthing/lib/ur/contract"
  37. "github.com/syncthing/syncthing/lib/versioner"
  38. )
  39. type service interface {
  40. suture.Service
  41. BringToFront(string)
  42. Override()
  43. Revert()
  44. DelayScan(d time.Duration)
  45. SchedulePull() // something relevant changed, we should try a pull
  46. Jobs(page, perpage int) ([]string, []string, int) // In progress, Queued, skipped
  47. Scan(subs []string) error
  48. Errors() []FileError
  49. WatchError() error
  50. ScheduleForceRescan(path string)
  51. GetStatistics() (stats.FolderStatistics, error)
  52. getState() (folderState, time.Time, error)
  53. }
  54. type Availability struct {
  55. ID protocol.DeviceID `json:"id"`
  56. FromTemporary bool `json:"fromTemporary"`
  57. }
  58. type Model interface {
  59. suture.Service
  60. connections.Model
  61. ResetFolder(folder string)
  62. DelayScan(folder string, next time.Duration)
  63. ScanFolder(folder string) error
  64. ScanFolders() map[string]error
  65. ScanFolderSubdirs(folder string, subs []string) error
  66. State(folder string) (string, time.Time, error)
  67. FolderErrors(folder string) ([]FileError, error)
  68. WatchError(folder string) error
  69. Override(folder string)
  70. Revert(folder string)
  71. BringToFront(folder, file string)
  72. LoadIgnores(folder string) ([]string, []string, error)
  73. CurrentIgnores(folder string) ([]string, []string, error)
  74. SetIgnores(folder string, content []string) error
  75. GetFolderVersions(folder string) (map[string][]versioner.FileVersion, error)
  76. RestoreFolderVersions(folder string, versions map[string]time.Time) (map[string]error, error)
  77. DBSnapshot(folder string) (*db.Snapshot, error)
  78. NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated, error)
  79. RemoteNeedFolderFiles(folder string, device protocol.DeviceID, page, perpage int) ([]db.FileInfoTruncated, error)
  80. LocalChangedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, error)
  81. FolderProgressBytesCompleted(folder string) int64
  82. CurrentFolderFile(folder string, file string) (protocol.FileInfo, bool, error)
  83. CurrentGlobalFile(folder string, file string) (protocol.FileInfo, bool, error)
  84. Availability(folder string, file protocol.FileInfo, block protocol.BlockInfo) ([]Availability, error)
  85. Completion(device protocol.DeviceID, folder string) (FolderCompletion, error)
  86. ConnectionStats() map[string]interface{}
  87. DeviceStatistics() (map[protocol.DeviceID]stats.DeviceStatistics, error)
  88. FolderStatistics() (map[string]stats.FolderStatistics, error)
  89. UsageReportingStats(report *contract.Report, version int, preview bool)
  90. PendingDevices() (map[protocol.DeviceID]db.ObservedDevice, error)
  91. PendingFolders(device protocol.DeviceID) (map[string]db.PendingFolder, error)
  92. StartDeadlockDetector(timeout time.Duration)
  93. GlobalDirectoryTree(folder, prefix string, levels int, dirsOnly bool) ([]*TreeEntry, error)
  94. }
  95. type model struct {
  96. *suture.Supervisor
  97. // constructor parameters
  98. cfg config.Wrapper
  99. id protocol.DeviceID
  100. clientName string
  101. clientVersion string
  102. db *db.Lowlevel
  103. protectedFiles []string
  104. evLogger events.Logger
  105. // constant or concurrency safe fields
  106. finder *db.BlockFinder
  107. progressEmitter *ProgressEmitter
  108. shortID protocol.ShortID
  109. // globalRequestLimiter limits the amount of data in concurrent incoming
  110. // requests
  111. globalRequestLimiter *byteSemaphore
  112. // folderIOLimiter limits the number of concurrent I/O heavy operations,
  113. // such as scans and pulls.
  114. folderIOLimiter *byteSemaphore
  115. fatalChan chan error
  116. started chan struct{}
  117. // fields protected by fmut
  118. fmut sync.RWMutex
  119. folderCfgs map[string]config.FolderConfiguration // folder -> cfg
  120. folderFiles map[string]*db.FileSet // folder -> files
  121. deviceStatRefs map[protocol.DeviceID]*stats.DeviceStatisticsReference // deviceID -> statsRef
  122. folderIgnores map[string]*ignore.Matcher // folder -> matcher object
  123. folderRunners map[string]service // folder -> puller or scanner
  124. folderRunnerToken map[string]suture.ServiceToken // folder -> token for folder runner
  125. folderRestartMuts syncMutexMap // folder -> restart mutex
  126. folderVersioners map[string]versioner.Versioner // folder -> versioner (may be nil)
  127. folderEncryptionPasswordTokens map[string][]byte // folder -> encryption token (may be missing, and only for encryption type folders)
  128. folderEncryptionFailures map[string]map[protocol.DeviceID]error // folder -> device -> error regarding encryption consistency (may be missing)
  129. // fields protected by pmut
  130. pmut sync.RWMutex
  131. conn map[protocol.DeviceID]protocol.Connection
  132. connRequestLimiters map[protocol.DeviceID]*byteSemaphore
  133. closed map[protocol.DeviceID]chan struct{}
  134. helloMessages map[protocol.DeviceID]protocol.Hello
  135. deviceDownloads map[protocol.DeviceID]*deviceDownloadState
  136. remotePausedFolders map[protocol.DeviceID]map[string]struct{} // deviceID -> folders
  137. indexSenders map[protocol.DeviceID]*indexSenderRegistry
  138. // for testing only
  139. foldersRunning int32
  140. }
  141. type folderFactory func(*model, *db.FileSet, *ignore.Matcher, config.FolderConfiguration, versioner.Versioner, events.Logger, *byteSemaphore) service
  142. var (
  143. folderFactories = make(map[config.FolderType]folderFactory)
  144. )
  145. var (
  146. errDeviceUnknown = errors.New("unknown device")
  147. errDevicePaused = errors.New("device is paused")
  148. errDeviceIgnored = errors.New("device is ignored")
  149. errDeviceRemoved = errors.New("device has been removed")
  150. ErrFolderPaused = errors.New("folder is paused")
  151. ErrFolderNotRunning = errors.New("folder is not running")
  152. ErrFolderMissing = errors.New("no such folder")
  153. errNetworkNotAllowed = errors.New("network not allowed")
  154. errNoVersioner = errors.New("folder has no versioner")
  155. // errors about why a connection is closed
  156. errReplacingConnection = errors.New("replacing connection")
  157. errStopped = errors.New("Syncthing is being stopped")
  158. errEncryptionInvConfigLocal = errors.New("can't encrypt data for a device when the folder type is receiveEncrypted")
  159. errEncryptionInvConfigRemote = errors.New("remote has encrypted data and encrypts that data for us - this is impossible")
  160. errEncryptionNotEncryptedLocal = errors.New("folder is announced as encrypted, but not configured thus")
  161. errEncryptionNotEncryptedRemote = errors.New("folder is configured to be encrypted but not announced thus")
  162. errEncryptionNotEncryptedUntrusted = errors.New("device is untrusted, but configured to receive not encrypted data")
  163. errEncryptionPassword = errors.New("different encryption passwords used")
  164. errEncryptionTokenRead = errors.New("failed to read encryption token")
  165. errEncryptionTokenWrite = errors.New("failed to write encryption token")
  166. errEncryptionNeedToken = errors.New("require password token for receive-encrypted token")
  167. errMissingRemoteInClusterConfig = errors.New("remote device missing in cluster config")
  168. errMissingLocalInClusterConfig = errors.New("local device missing in cluster config")
  169. errConnLimitReached = errors.New("connection limit reached")
  170. // messages for failure reports
  171. failureUnexpectedGenerateCCError = "unexpected error occurred in generateClusterConfig"
  172. )
  173. // NewModel creates and starts a new model. The model starts in read-only mode,
  174. // where it sends index information to connected peers and responds to requests
  175. // for file data without altering the local folder in any way.
  176. func NewModel(cfg config.Wrapper, id protocol.DeviceID, clientName, clientVersion string, ldb *db.Lowlevel, protectedFiles []string, evLogger events.Logger) Model {
  177. spec := svcutil.SpecWithDebugLogger(l)
  178. m := &model{
  179. Supervisor: suture.New("model", spec),
  180. // constructor parameters
  181. cfg: cfg,
  182. id: id,
  183. clientName: clientName,
  184. clientVersion: clientVersion,
  185. db: ldb,
  186. protectedFiles: protectedFiles,
  187. evLogger: evLogger,
  188. // constant or concurrency safe fields
  189. finder: db.NewBlockFinder(ldb),
  190. progressEmitter: NewProgressEmitter(cfg, evLogger),
  191. shortID: id.Short(),
  192. globalRequestLimiter: newByteSemaphore(1024 * cfg.Options().MaxConcurrentIncomingRequestKiB()),
  193. folderIOLimiter: newByteSemaphore(cfg.Options().MaxFolderConcurrency()),
  194. fatalChan: make(chan error),
  195. started: make(chan struct{}),
  196. // fields protected by fmut
  197. fmut: sync.NewRWMutex(),
  198. folderCfgs: make(map[string]config.FolderConfiguration),
  199. folderFiles: make(map[string]*db.FileSet),
  200. deviceStatRefs: make(map[protocol.DeviceID]*stats.DeviceStatisticsReference),
  201. folderIgnores: make(map[string]*ignore.Matcher),
  202. folderRunners: make(map[string]service),
  203. folderRunnerToken: make(map[string]suture.ServiceToken),
  204. folderVersioners: make(map[string]versioner.Versioner),
  205. folderEncryptionPasswordTokens: make(map[string][]byte),
  206. folderEncryptionFailures: make(map[string]map[protocol.DeviceID]error),
  207. // fields protected by pmut
  208. pmut: sync.NewRWMutex(),
  209. conn: make(map[protocol.DeviceID]protocol.Connection),
  210. connRequestLimiters: make(map[protocol.DeviceID]*byteSemaphore),
  211. closed: make(map[protocol.DeviceID]chan struct{}),
  212. helloMessages: make(map[protocol.DeviceID]protocol.Hello),
  213. deviceDownloads: make(map[protocol.DeviceID]*deviceDownloadState),
  214. remotePausedFolders: make(map[protocol.DeviceID]map[string]struct{}),
  215. indexSenders: make(map[protocol.DeviceID]*indexSenderRegistry),
  216. }
  217. for devID := range cfg.Devices() {
  218. m.deviceStatRefs[devID] = stats.NewDeviceStatisticsReference(m.db, devID)
  219. }
  220. m.Add(m.progressEmitter)
  221. m.Add(svcutil.AsService(m.serve, m.String()))
  222. return m
  223. }
  224. func (m *model) serve(ctx context.Context) error {
  225. defer m.closeAllConnectionsAndWait()
  226. cfg := m.cfg.Subscribe(m)
  227. defer m.cfg.Unsubscribe(m)
  228. if err := m.initFolders(cfg); err != nil {
  229. close(m.started)
  230. return svcutil.AsFatalErr(err, svcutil.ExitError)
  231. }
  232. close(m.started)
  233. select {
  234. case <-ctx.Done():
  235. return ctx.Err()
  236. case err := <-m.fatalChan:
  237. return svcutil.AsFatalErr(err, svcutil.ExitError)
  238. }
  239. }
  240. func (m *model) initFolders(cfg config.Configuration) error {
  241. clusterConfigDevices := make(deviceIDSet, len(cfg.Devices))
  242. for _, folderCfg := range cfg.Folders {
  243. if folderCfg.Paused {
  244. folderCfg.CreateRoot()
  245. continue
  246. }
  247. err := m.newFolder(folderCfg, cfg.Options.CacheIgnoredFiles)
  248. if err != nil {
  249. return err
  250. }
  251. clusterConfigDevices.add(folderCfg.DeviceIDs())
  252. }
  253. ignoredDevices := observedDeviceSet(m.cfg.IgnoredDevices())
  254. m.cleanPending(cfg.DeviceMap(), cfg.FolderMap(), ignoredDevices, nil)
  255. m.sendClusterConfig(clusterConfigDevices.AsSlice())
  256. return nil
  257. }
  258. func (m *model) closeAllConnectionsAndWait() {
  259. m.pmut.RLock()
  260. closed := make([]chan struct{}, 0, len(m.conn))
  261. for id, conn := range m.conn {
  262. closed = append(closed, m.closed[id])
  263. go conn.Close(errStopped)
  264. }
  265. m.pmut.RUnlock()
  266. for _, c := range closed {
  267. <-c
  268. }
  269. }
  270. func (m *model) fatal(err error) {
  271. select {
  272. case m.fatalChan <- err:
  273. default:
  274. }
  275. }
  276. // StartDeadlockDetector starts a deadlock detector on the models locks which
  277. // causes panics in case the locks cannot be acquired in the given timeout
  278. // period.
  279. func (m *model) StartDeadlockDetector(timeout time.Duration) {
  280. l.Infof("Starting deadlock detector with %v timeout", timeout)
  281. detector := newDeadlockDetector(timeout)
  282. detector.Watch("fmut", m.fmut)
  283. detector.Watch("pmut", m.pmut)
  284. }
  285. // Need to hold lock on m.fmut when calling this.
  286. func (m *model) addAndStartFolderLocked(cfg config.FolderConfiguration, fset *db.FileSet, cacheIgnoredFiles bool) {
  287. ignores := ignore.New(cfg.Filesystem(), ignore.WithCache(cacheIgnoredFiles))
  288. if cfg.Type != config.FolderTypeReceiveEncrypted {
  289. if err := ignores.Load(".stignore"); err != nil && !fs.IsNotExist(err) {
  290. l.Warnln("Loading ignores:", err)
  291. }
  292. }
  293. m.addAndStartFolderLockedWithIgnores(cfg, fset, ignores)
  294. }
  295. // Only needed for testing, use addAndStartFolderLocked instead.
  296. func (m *model) addAndStartFolderLockedWithIgnores(cfg config.FolderConfiguration, fset *db.FileSet, ignores *ignore.Matcher) {
  297. m.folderCfgs[cfg.ID] = cfg
  298. m.folderFiles[cfg.ID] = fset
  299. m.folderIgnores[cfg.ID] = ignores
  300. _, ok := m.folderRunners[cfg.ID]
  301. if ok {
  302. l.Warnln("Cannot start already running folder", cfg.Description())
  303. panic("cannot start already running folder")
  304. }
  305. folderFactory, ok := folderFactories[cfg.Type]
  306. if !ok {
  307. panic(fmt.Sprintf("unknown folder type 0x%x", cfg.Type))
  308. }
  309. folder := cfg.ID
  310. // Find any devices for which we hold the index in the db, but the folder
  311. // is not shared, and drop it.
  312. expected := mapDevices(cfg.DeviceIDs())
  313. for _, available := range fset.ListDevices() {
  314. if _, ok := expected[available]; !ok {
  315. l.Debugln("dropping", folder, "state for", available)
  316. fset.Drop(available)
  317. }
  318. }
  319. v, ok := fset.Sequence(protocol.LocalDeviceID), true
  320. indexHasFiles := ok && v > 0
  321. if !indexHasFiles {
  322. // It's a blank folder, so this may the first time we're looking at
  323. // it. Attempt to create and tag with our marker as appropriate. We
  324. // don't really do anything with errors at this point except warn -
  325. // if these things don't work, we still want to start the folder and
  326. // it'll show up as errored later.
  327. if err := cfg.CreateRoot(); err != nil {
  328. l.Warnln("Failed to create folder root directory", err)
  329. } else if err = cfg.CreateMarker(); err != nil {
  330. l.Warnln("Failed to create folder marker:", err)
  331. }
  332. }
  333. if cfg.Type == config.FolderTypeReceiveEncrypted {
  334. if encryptionToken, err := readEncryptionToken(cfg); err == nil {
  335. m.folderEncryptionPasswordTokens[folder] = encryptionToken
  336. } else if !fs.IsNotExist(err) {
  337. l.Warnf("Failed to read encryption token: %v", err)
  338. }
  339. }
  340. // These are our metadata files, and they should always be hidden.
  341. ffs := cfg.Filesystem()
  342. _ = ffs.Hide(config.DefaultMarkerName)
  343. _ = ffs.Hide(".stversions")
  344. _ = ffs.Hide(".stignore")
  345. var ver versioner.Versioner
  346. if cfg.Versioning.Type != "" {
  347. var err error
  348. ver, err = versioner.New(cfg)
  349. if err != nil {
  350. panic(fmt.Errorf("creating versioner: %w", err))
  351. }
  352. }
  353. m.folderVersioners[folder] = ver
  354. p := folderFactory(m, fset, ignores, cfg, ver, m.evLogger, m.folderIOLimiter)
  355. m.folderRunners[folder] = p
  356. m.warnAboutOverwritingProtectedFiles(cfg, ignores)
  357. m.folderRunnerToken[folder] = m.Add(p)
  358. l.Infof("Ready to synchronize %s (%s)", cfg.Description(), cfg.Type)
  359. }
  360. func (m *model) warnAboutOverwritingProtectedFiles(cfg config.FolderConfiguration, ignores *ignore.Matcher) {
  361. if cfg.Type == config.FolderTypeSendOnly {
  362. return
  363. }
  364. // This is a bit of a hack.
  365. ffs := cfg.Filesystem()
  366. if ffs.Type() != fs.FilesystemTypeBasic {
  367. return
  368. }
  369. folderLocation := ffs.URI()
  370. var filesAtRisk []string
  371. for _, protectedFilePath := range m.protectedFiles {
  372. // check if file is synced in this folder
  373. if protectedFilePath != folderLocation && !fs.IsParent(protectedFilePath, folderLocation) {
  374. continue
  375. }
  376. // check if file is ignored
  377. relPath, _ := filepath.Rel(folderLocation, protectedFilePath)
  378. if ignores.Match(relPath).IsIgnored() {
  379. continue
  380. }
  381. filesAtRisk = append(filesAtRisk, protectedFilePath)
  382. }
  383. if len(filesAtRisk) > 0 {
  384. l.Warnln("Some protected files may be overwritten and cause issues. See https://docs.syncthing.net/users/config.html#syncing-configuration-files for more information. The at risk files are:", strings.Join(filesAtRisk, ", "))
  385. }
  386. }
  387. func (m *model) removeFolder(cfg config.FolderConfiguration) {
  388. m.fmut.RLock()
  389. token, ok := m.folderRunnerToken[cfg.ID]
  390. m.fmut.RUnlock()
  391. if ok {
  392. m.RemoveAndWait(token, 0)
  393. }
  394. // We need to hold both fmut and pmut and must acquire locks in the same
  395. // order always. (The locks can be *released* in any order.)
  396. m.fmut.Lock()
  397. m.pmut.RLock()
  398. isPathUnique := true
  399. for folderID, folderCfg := range m.folderCfgs {
  400. if folderID != cfg.ID && folderCfg.Path == cfg.Path {
  401. isPathUnique = false
  402. break
  403. }
  404. }
  405. if isPathUnique {
  406. // Remove (if empty and removable) or move away (if non-empty or
  407. // otherwise not removable) Syncthing-specific marker files.
  408. fs := cfg.Filesystem()
  409. if err := fs.Remove(config.DefaultMarkerName); err != nil {
  410. moved := config.DefaultMarkerName + time.Now().Format(".removed-20060102-150405")
  411. _ = fs.Rename(config.DefaultMarkerName, moved)
  412. }
  413. }
  414. m.cleanupFolderLocked(cfg)
  415. for _, r := range m.indexSenders {
  416. r.remove(cfg.ID)
  417. }
  418. m.fmut.Unlock()
  419. m.pmut.RUnlock()
  420. // Remove it from the database
  421. db.DropFolder(m.db, cfg.ID)
  422. }
  423. // Need to hold lock on m.fmut when calling this.
  424. func (m *model) cleanupFolderLocked(cfg config.FolderConfiguration) {
  425. // clear up our config maps
  426. delete(m.folderCfgs, cfg.ID)
  427. delete(m.folderFiles, cfg.ID)
  428. delete(m.folderIgnores, cfg.ID)
  429. delete(m.folderRunners, cfg.ID)
  430. delete(m.folderRunnerToken, cfg.ID)
  431. delete(m.folderVersioners, cfg.ID)
  432. }
  433. func (m *model) restartFolder(from, to config.FolderConfiguration, cacheIgnoredFiles bool) error {
  434. if len(to.ID) == 0 {
  435. panic("bug: cannot restart empty folder ID")
  436. }
  437. if to.ID != from.ID {
  438. l.Warnf("bug: folder restart cannot change ID %q -> %q", from.ID, to.ID)
  439. panic("bug: folder restart cannot change ID")
  440. }
  441. folder := to.ID
  442. // This mutex protects the entirety of the restart operation, preventing
  443. // there from being more than one folder restart operation in progress
  444. // at any given time. The usual fmut/pmut stuff doesn't cover this,
  445. // because those locks are released while we are waiting for the folder
  446. // to shut down (and must be so because the folder might need them as
  447. // part of its operations before shutting down).
  448. restartMut := m.folderRestartMuts.Get(folder)
  449. restartMut.Lock()
  450. defer restartMut.Unlock()
  451. m.fmut.RLock()
  452. token, ok := m.folderRunnerToken[from.ID]
  453. m.fmut.RUnlock()
  454. if ok {
  455. m.RemoveAndWait(token, 0)
  456. }
  457. m.fmut.Lock()
  458. defer m.fmut.Unlock()
  459. // Cache the (maybe) existing fset before it's removed by cleanupFolderLocked
  460. fset := m.folderFiles[folder]
  461. fsetNil := fset == nil
  462. m.cleanupFolderLocked(from)
  463. if !to.Paused {
  464. if fsetNil {
  465. // Create a new fset. Might take a while and we do it under
  466. // locking, but it's unsafe to create fset:s concurrently so
  467. // that's the price we pay.
  468. var err error
  469. fset, err = db.NewFileSet(folder, to.Filesystem(), m.db)
  470. if err != nil {
  471. return fmt.Errorf("restarting %v: %w", to.Description(), err)
  472. }
  473. }
  474. m.addAndStartFolderLocked(to, fset, cacheIgnoredFiles)
  475. }
  476. // Care needs to be taken because we already hold fmut and the lock order
  477. // must be the same everywhere. As fmut is acquired first, this is fine.
  478. // toDeviceIDs := to.DeviceIDs()
  479. m.pmut.RLock()
  480. for _, id := range to.DeviceIDs() {
  481. indexSenders, ok := m.indexSenders[id]
  482. if !ok {
  483. continue
  484. }
  485. // In case the folder was newly shared with us we already got a
  486. // cluster config and wont necessarily get another soon - start
  487. // sending indexes if connected.
  488. if to.Paused {
  489. indexSenders.pause(to.ID)
  490. } else if !from.SharedWith(indexSenders.deviceID) || fsetNil || from.Paused {
  491. indexSenders.resume(to, fset)
  492. }
  493. }
  494. m.pmut.RUnlock()
  495. var infoMsg string
  496. switch {
  497. case to.Paused:
  498. infoMsg = "Paused"
  499. case from.Paused:
  500. infoMsg = "Unpaused"
  501. default:
  502. infoMsg = "Restarted"
  503. }
  504. l.Infof("%v folder %v (%v)", infoMsg, to.Description(), to.Type)
  505. return nil
  506. }
  507. func (m *model) newFolder(cfg config.FolderConfiguration, cacheIgnoredFiles bool) error {
  508. // Creating the fileset can take a long time (metadata calculation) so
  509. // we do it outside of the lock.
  510. fset, err := db.NewFileSet(cfg.ID, cfg.Filesystem(), m.db)
  511. if err != nil {
  512. return fmt.Errorf("adding %v: %w", cfg.Description(), err)
  513. }
  514. m.fmut.Lock()
  515. defer m.fmut.Unlock()
  516. // Cluster configs might be received and processed before reaching this
  517. // point, i.e. before the folder is started. If that's the case, start
  518. // index senders here.
  519. m.pmut.RLock()
  520. for _, id := range cfg.DeviceIDs() {
  521. if is, ok := m.indexSenders[id]; ok {
  522. is.resume(cfg, fset)
  523. }
  524. }
  525. m.pmut.RUnlock()
  526. m.addAndStartFolderLocked(cfg, fset, cacheIgnoredFiles)
  527. return nil
  528. }
  529. func (m *model) UsageReportingStats(report *contract.Report, version int, preview bool) {
  530. if version >= 3 {
  531. // Block stats
  532. blockStatsMut.Lock()
  533. for k, v := range blockStats {
  534. switch k {
  535. case "total":
  536. report.BlockStats.Total = v
  537. case "renamed":
  538. report.BlockStats.Renamed = v
  539. case "reused":
  540. report.BlockStats.Reused = v
  541. case "pulled":
  542. report.BlockStats.Pulled = v
  543. case "copyOrigin":
  544. report.BlockStats.CopyOrigin = v
  545. case "copyOriginShifted":
  546. report.BlockStats.CopyOriginShifted = v
  547. case "copyElsewhere":
  548. report.BlockStats.CopyElsewhere = v
  549. }
  550. // Reset counts, as these are incremental
  551. if !preview {
  552. blockStats[k] = 0
  553. }
  554. }
  555. blockStatsMut.Unlock()
  556. // Transport stats
  557. m.pmut.RLock()
  558. for _, conn := range m.conn {
  559. report.TransportStats[conn.Transport()]++
  560. }
  561. m.pmut.RUnlock()
  562. // Ignore stats
  563. var seenPrefix [3]bool
  564. for folder := range m.cfg.Folders() {
  565. lines, _, err := m.CurrentIgnores(folder)
  566. if err != nil {
  567. continue
  568. }
  569. report.IgnoreStats.Lines += len(lines)
  570. for _, line := range lines {
  571. // Allow prefixes to be specified in any order, but only once.
  572. for {
  573. if strings.HasPrefix(line, "!") && !seenPrefix[0] {
  574. seenPrefix[0] = true
  575. line = line[1:]
  576. report.IgnoreStats.Inverts++
  577. } else if strings.HasPrefix(line, "(?i)") && !seenPrefix[1] {
  578. seenPrefix[1] = true
  579. line = line[4:]
  580. report.IgnoreStats.Folded++
  581. } else if strings.HasPrefix(line, "(?d)") && !seenPrefix[2] {
  582. seenPrefix[2] = true
  583. line = line[4:]
  584. report.IgnoreStats.Deletable++
  585. } else {
  586. seenPrefix[0] = false
  587. seenPrefix[1] = false
  588. seenPrefix[2] = false
  589. break
  590. }
  591. }
  592. // Noops, remove
  593. line = strings.TrimSuffix(line, "**")
  594. line = strings.TrimPrefix(line, "**/")
  595. if strings.HasPrefix(line, "/") {
  596. report.IgnoreStats.Rooted++
  597. } else if strings.HasPrefix(line, "#include ") {
  598. report.IgnoreStats.Includes++
  599. if strings.Contains(line, "..") {
  600. report.IgnoreStats.EscapedIncludes++
  601. }
  602. }
  603. if strings.Contains(line, "**") {
  604. report.IgnoreStats.DoubleStars++
  605. // Remove not to trip up star checks.
  606. line = strings.ReplaceAll(line, "**", "")
  607. }
  608. if strings.Contains(line, "*") {
  609. report.IgnoreStats.Stars++
  610. }
  611. }
  612. }
  613. }
  614. }
  615. type ConnectionInfo struct {
  616. protocol.Statistics
  617. Connected bool
  618. Paused bool
  619. Address string
  620. ClientVersion string
  621. Type string
  622. Crypto string
  623. }
  624. func (info ConnectionInfo) MarshalJSON() ([]byte, error) {
  625. return json.Marshal(map[string]interface{}{
  626. "at": info.At,
  627. "inBytesTotal": info.InBytesTotal,
  628. "outBytesTotal": info.OutBytesTotal,
  629. "connected": info.Connected,
  630. "paused": info.Paused,
  631. "address": info.Address,
  632. "clientVersion": info.ClientVersion,
  633. "type": info.Type,
  634. "crypto": info.Crypto,
  635. })
  636. }
  637. // NumConnections returns the current number of active connected devices.
  638. func (m *model) NumConnections() int {
  639. m.pmut.RLock()
  640. defer m.pmut.RUnlock()
  641. return len(m.conn)
  642. }
  643. // ConnectionStats returns a map with connection statistics for each device.
  644. func (m *model) ConnectionStats() map[string]interface{} {
  645. m.pmut.RLock()
  646. defer m.pmut.RUnlock()
  647. res := make(map[string]interface{})
  648. devs := m.cfg.Devices()
  649. conns := make(map[string]ConnectionInfo, len(devs))
  650. for device, deviceCfg := range devs {
  651. hello := m.helloMessages[device]
  652. versionString := hello.ClientVersion
  653. if hello.ClientName != "syncthing" {
  654. versionString = hello.ClientName + " " + hello.ClientVersion
  655. }
  656. ci := ConnectionInfo{
  657. ClientVersion: strings.TrimSpace(versionString),
  658. Paused: deviceCfg.Paused,
  659. }
  660. if conn, ok := m.conn[device]; ok {
  661. ci.Type = conn.Type()
  662. ci.Crypto = conn.Crypto()
  663. ci.Connected = ok
  664. ci.Statistics = conn.Statistics()
  665. if addr := conn.RemoteAddr(); addr != nil {
  666. ci.Address = addr.String()
  667. }
  668. }
  669. conns[device.String()] = ci
  670. }
  671. res["connections"] = conns
  672. in, out := protocol.TotalInOut()
  673. res["total"] = ConnectionInfo{
  674. Statistics: protocol.Statistics{
  675. At: time.Now().Truncate(time.Second),
  676. InBytesTotal: in,
  677. OutBytesTotal: out,
  678. },
  679. }
  680. return res
  681. }
  682. // DeviceStatistics returns statistics about each device
  683. func (m *model) DeviceStatistics() (map[protocol.DeviceID]stats.DeviceStatistics, error) {
  684. m.fmut.RLock()
  685. defer m.fmut.RUnlock()
  686. res := make(map[protocol.DeviceID]stats.DeviceStatistics, len(m.deviceStatRefs))
  687. for id, sr := range m.deviceStatRefs {
  688. stats, err := sr.GetStatistics()
  689. if err != nil {
  690. return nil, err
  691. }
  692. res[id] = stats
  693. }
  694. return res, nil
  695. }
  696. // FolderStatistics returns statistics about each folder
  697. func (m *model) FolderStatistics() (map[string]stats.FolderStatistics, error) {
  698. res := make(map[string]stats.FolderStatistics)
  699. m.fmut.RLock()
  700. defer m.fmut.RUnlock()
  701. for id, runner := range m.folderRunners {
  702. stats, err := runner.GetStatistics()
  703. if err != nil {
  704. return nil, err
  705. }
  706. res[id] = stats
  707. }
  708. return res, nil
  709. }
  710. type FolderCompletion struct {
  711. CompletionPct float64
  712. GlobalBytes int64
  713. NeedBytes int64
  714. GlobalItems int
  715. NeedItems int
  716. NeedDeletes int
  717. Sequence int64
  718. }
  719. func newFolderCompletion(global, need db.Counts, sequence int64) FolderCompletion {
  720. comp := FolderCompletion{
  721. GlobalBytes: global.Bytes,
  722. NeedBytes: need.Bytes,
  723. GlobalItems: global.Files + global.Directories + global.Symlinks,
  724. NeedItems: need.Files + need.Directories + need.Symlinks,
  725. NeedDeletes: need.Deleted,
  726. Sequence: sequence,
  727. }
  728. comp.setComplectionPct()
  729. return comp
  730. }
  731. func (comp *FolderCompletion) add(other FolderCompletion) {
  732. comp.GlobalBytes += other.GlobalBytes
  733. comp.NeedBytes += other.NeedBytes
  734. comp.GlobalItems += other.GlobalItems
  735. comp.NeedItems += other.NeedItems
  736. comp.NeedDeletes += other.NeedDeletes
  737. comp.setComplectionPct()
  738. }
  739. func (comp *FolderCompletion) setComplectionPct() {
  740. if comp.GlobalBytes == 0 {
  741. comp.CompletionPct = 100
  742. } else {
  743. needRatio := float64(comp.NeedBytes) / float64(comp.GlobalBytes)
  744. comp.CompletionPct = 100 * (1 - needRatio)
  745. }
  746. // If the completion is 100% but there are deletes we need to handle,
  747. // drop it down a notch. Hack for consumers that look only at the
  748. // percentage (our own GUI does the same calculation as here on its own
  749. // and needs the same fixup).
  750. if comp.NeedBytes == 0 && comp.NeedDeletes > 0 {
  751. comp.CompletionPct = 95 // chosen by fair dice roll
  752. }
  753. }
  754. // Map returns the members as a map, e.g. used in api to serialize as Json.
  755. func (comp FolderCompletion) Map() map[string]interface{} {
  756. return map[string]interface{}{
  757. "completion": comp.CompletionPct,
  758. "globalBytes": comp.GlobalBytes,
  759. "needBytes": comp.NeedBytes,
  760. "globalItems": comp.GlobalItems,
  761. "needItems": comp.NeedItems,
  762. "needDeletes": comp.NeedDeletes,
  763. "sequence": comp.Sequence,
  764. }
  765. }
  766. // Completion returns the completion status, in percent with some counters,
  767. // for the given device and folder. The device can be any known device ID
  768. // (including the local device) or explicitly protocol.LocalDeviceID. An
  769. // empty folder string means the aggregate of all folders shared with the
  770. // given device.
  771. func (m *model) Completion(device protocol.DeviceID, folder string) (FolderCompletion, error) {
  772. // The user specifically asked for our own device ID. Internally that is
  773. // known as protocol.LocalDeviceID so translate.
  774. if device == m.id {
  775. device = protocol.LocalDeviceID
  776. }
  777. if folder != "" {
  778. // We want completion for a specific folder.
  779. return m.folderCompletion(device, folder)
  780. }
  781. // We want completion for all (shared) folders as an aggregate.
  782. var comp FolderCompletion
  783. for _, fcfg := range m.cfg.FolderList() {
  784. if device == protocol.LocalDeviceID || fcfg.SharedWith(device) {
  785. folderComp, err := m.folderCompletion(device, fcfg.ID)
  786. if err != nil {
  787. return FolderCompletion{}, err
  788. }
  789. comp.add(folderComp)
  790. }
  791. }
  792. return comp, nil
  793. }
  794. func (m *model) folderCompletion(device protocol.DeviceID, folder string) (FolderCompletion, error) {
  795. m.fmut.RLock()
  796. err := m.checkFolderRunningLocked(folder)
  797. rf := m.folderFiles[folder]
  798. m.fmut.RUnlock()
  799. if err != nil {
  800. return FolderCompletion{}, err
  801. }
  802. snap, err := rf.Snapshot()
  803. if err != nil {
  804. return FolderCompletion{}, err
  805. }
  806. defer snap.Release()
  807. m.pmut.RLock()
  808. downloaded := m.deviceDownloads[device].BytesDownloaded(folder)
  809. m.pmut.RUnlock()
  810. need := snap.NeedSize(device)
  811. need.Bytes -= downloaded
  812. // This might might be more than it really is, because some blocks can be of a smaller size.
  813. if need.Bytes < 0 {
  814. need.Bytes = 0
  815. }
  816. comp := newFolderCompletion(snap.GlobalSize(), need, snap.Sequence(device))
  817. l.Debugf("%v Completion(%s, %q): %v", m, device, folder, comp.Map())
  818. return comp, nil
  819. }
  820. // DBSnapshot returns a snapshot of the database content relevant to the given folder.
  821. func (m *model) DBSnapshot(folder string) (*db.Snapshot, error) {
  822. m.fmut.RLock()
  823. err := m.checkFolderRunningLocked(folder)
  824. rf := m.folderFiles[folder]
  825. m.fmut.RUnlock()
  826. if err != nil {
  827. return nil, err
  828. }
  829. return rf.Snapshot()
  830. }
  831. func (m *model) FolderProgressBytesCompleted(folder string) int64 {
  832. return m.progressEmitter.BytesCompleted(folder)
  833. }
  834. // NeedFolderFiles returns paginated list of currently needed files in
  835. // progress, queued, and to be queued on next puller iteration.
  836. func (m *model) NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated, error) {
  837. m.fmut.RLock()
  838. rf, rfOk := m.folderFiles[folder]
  839. runner, runnerOk := m.folderRunners[folder]
  840. cfg := m.folderCfgs[folder]
  841. m.fmut.RUnlock()
  842. if !rfOk {
  843. return nil, nil, nil, ErrFolderMissing
  844. }
  845. snap, err := rf.Snapshot()
  846. if err != nil {
  847. return nil, nil, nil, err
  848. }
  849. defer snap.Release()
  850. var progress, queued, rest []db.FileInfoTruncated
  851. var seen map[string]struct{}
  852. p := newPager(page, perpage)
  853. if runnerOk {
  854. progressNames, queuedNames, skipped := runner.Jobs(page, perpage)
  855. progress = make([]db.FileInfoTruncated, len(progressNames))
  856. queued = make([]db.FileInfoTruncated, len(queuedNames))
  857. seen = make(map[string]struct{}, len(progressNames)+len(queuedNames))
  858. for i, name := range progressNames {
  859. if f, ok := snap.GetGlobalTruncated(name); ok {
  860. progress[i] = f
  861. seen[name] = struct{}{}
  862. }
  863. }
  864. for i, name := range queuedNames {
  865. if f, ok := snap.GetGlobalTruncated(name); ok {
  866. queued[i] = f
  867. seen[name] = struct{}{}
  868. }
  869. }
  870. p.get -= len(seen)
  871. if p.get == 0 {
  872. return progress, queued, nil, nil
  873. }
  874. p.toSkip -= skipped
  875. }
  876. rest = make([]db.FileInfoTruncated, 0, perpage)
  877. snap.WithNeedTruncated(protocol.LocalDeviceID, func(f protocol.FileIntf) bool {
  878. if cfg.IgnoreDelete && f.IsDeleted() {
  879. return true
  880. }
  881. if p.skip() {
  882. return true
  883. }
  884. ft := f.(db.FileInfoTruncated)
  885. if _, ok := seen[ft.Name]; !ok {
  886. rest = append(rest, ft)
  887. p.get--
  888. }
  889. return p.get > 0
  890. })
  891. return progress, queued, rest, nil
  892. }
  893. // RemoteNeedFolderFiles returns paginated list of currently needed files in
  894. // progress, queued, and to be queued on next puller iteration, as well as the
  895. // total number of files currently needed.
  896. func (m *model) RemoteNeedFolderFiles(folder string, device protocol.DeviceID, page, perpage int) ([]db.FileInfoTruncated, error) {
  897. m.fmut.RLock()
  898. rf, ok := m.folderFiles[folder]
  899. m.fmut.RUnlock()
  900. if !ok {
  901. return nil, ErrFolderMissing
  902. }
  903. snap, err := rf.Snapshot()
  904. if err != nil {
  905. return nil, err
  906. }
  907. defer snap.Release()
  908. files := make([]db.FileInfoTruncated, 0, perpage)
  909. p := newPager(page, perpage)
  910. snap.WithNeedTruncated(device, func(f protocol.FileIntf) bool {
  911. if p.skip() {
  912. return true
  913. }
  914. files = append(files, f.(db.FileInfoTruncated))
  915. return !p.done()
  916. })
  917. return files, nil
  918. }
  919. func (m *model) LocalChangedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, error) {
  920. m.fmut.RLock()
  921. rf, ok := m.folderFiles[folder]
  922. cfg := m.folderCfgs[folder]
  923. m.fmut.RUnlock()
  924. if !ok {
  925. return nil, ErrFolderMissing
  926. }
  927. snap, err := rf.Snapshot()
  928. if err != nil {
  929. return nil, err
  930. }
  931. defer snap.Release()
  932. if snap.ReceiveOnlyChangedSize().TotalItems() == 0 {
  933. return nil, nil
  934. }
  935. p := newPager(page, perpage)
  936. recvEnc := cfg.Type == config.FolderTypeReceiveEncrypted
  937. files := make([]db.FileInfoTruncated, 0, perpage)
  938. snap.WithHaveTruncated(protocol.LocalDeviceID, func(f protocol.FileIntf) bool {
  939. if !f.IsReceiveOnlyChanged() || (recvEnc && f.IsDeleted()) {
  940. return true
  941. }
  942. if p.skip() {
  943. return true
  944. }
  945. ft := f.(db.FileInfoTruncated)
  946. files = append(files, ft)
  947. return !p.done()
  948. })
  949. return files, nil
  950. }
  951. type pager struct {
  952. toSkip, get int
  953. }
  954. func newPager(page, perpage int) *pager {
  955. return &pager{
  956. toSkip: (page - 1) * perpage,
  957. get: perpage,
  958. }
  959. }
  960. func (p *pager) skip() bool {
  961. if p.toSkip == 0 {
  962. return false
  963. }
  964. p.toSkip--
  965. return true
  966. }
  967. func (p *pager) done() bool {
  968. if p.get > 0 {
  969. p.get--
  970. }
  971. return p.get == 0
  972. }
  973. // Index is called when a new device is connected and we receive their full index.
  974. // Implements the protocol.Model interface.
  975. func (m *model) Index(deviceID protocol.DeviceID, folder string, fs []protocol.FileInfo) error {
  976. return m.handleIndex(deviceID, folder, fs, false)
  977. }
  978. // IndexUpdate is called for incremental updates to connected devices' indexes.
  979. // Implements the protocol.Model interface.
  980. func (m *model) IndexUpdate(deviceID protocol.DeviceID, folder string, fs []protocol.FileInfo) error {
  981. return m.handleIndex(deviceID, folder, fs, true)
  982. }
  983. func (m *model) handleIndex(deviceID protocol.DeviceID, folder string, fs []protocol.FileInfo, update bool) error {
  984. op := "Index"
  985. if update {
  986. op += " update"
  987. }
  988. l.Debugf("%v (in): %s / %q: %d files", op, deviceID, folder, len(fs))
  989. if cfg, ok := m.cfg.Folder(folder); !ok || !cfg.SharedWith(deviceID) {
  990. l.Infof("%v for unexpected folder ID %q sent from device %q; ensure that the folder exists and that this device is selected under \"Share With\" in the folder configuration.", op, folder, deviceID)
  991. return errors.Wrap(ErrFolderMissing, folder)
  992. } else if cfg.Paused {
  993. l.Debugf("%v for paused folder (ID %q) sent from device %q.", op, folder, deviceID)
  994. return errors.Wrap(ErrFolderPaused, folder)
  995. }
  996. m.fmut.RLock()
  997. files, existing := m.folderFiles[folder]
  998. runner, running := m.folderRunners[folder]
  999. m.fmut.RUnlock()
  1000. if !existing {
  1001. l.Infof("%v for nonexistent folder %q", op, folder)
  1002. return errors.Wrap(ErrFolderMissing, folder)
  1003. }
  1004. if running {
  1005. defer runner.SchedulePull()
  1006. }
  1007. m.pmut.RLock()
  1008. downloads := m.deviceDownloads[deviceID]
  1009. m.pmut.RUnlock()
  1010. downloads.Update(folder, makeForgetUpdate(fs))
  1011. if !update {
  1012. files.Drop(deviceID)
  1013. }
  1014. for i := range fs {
  1015. // The local attributes should never be transmitted over the wire.
  1016. // Make sure they look like they weren't.
  1017. fs[i].LocalFlags = 0
  1018. fs[i].VersionHash = nil
  1019. }
  1020. files.Update(deviceID, fs)
  1021. seq := files.Sequence(deviceID)
  1022. m.evLogger.Log(events.RemoteIndexUpdated, map[string]interface{}{
  1023. "device": deviceID.String(),
  1024. "folder": folder,
  1025. "items": len(fs),
  1026. "sequence": seq,
  1027. "version": seq, // legacy for sequence
  1028. })
  1029. return nil
  1030. }
  1031. func (m *model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterConfig) error {
  1032. // Check the peer device's announced folders against our own. Emits events
  1033. // for folders that we don't expect (unknown or not shared).
  1034. // Also, collect a list of folders we do share, and if he's interested in
  1035. // temporary indexes, subscribe the connection.
  1036. m.pmut.RLock()
  1037. indexSenderRegistry, ok := m.indexSenders[deviceID]
  1038. m.pmut.RUnlock()
  1039. if !ok {
  1040. panic("bug: ClusterConfig called on closed or nonexistent connection")
  1041. }
  1042. deviceCfg, ok := m.cfg.Device(deviceID)
  1043. if !ok {
  1044. l.Debugln("Device disappeared from config while processing cluster-config")
  1045. return errDeviceUnknown
  1046. }
  1047. // Assemble the device information from the connected device about
  1048. // themselves and us for all folders.
  1049. ccDeviceInfos := make(map[string]*indexSenderStartInfo, len(cm.Folders))
  1050. for _, folder := range cm.Folders {
  1051. info := &indexSenderStartInfo{}
  1052. for _, dev := range folder.Devices {
  1053. if dev.ID == m.id {
  1054. info.local = dev
  1055. } else if dev.ID == deviceID {
  1056. info.remote = dev
  1057. }
  1058. if info.local.ID != protocol.EmptyDeviceID && info.remote.ID != protocol.EmptyDeviceID {
  1059. break
  1060. }
  1061. }
  1062. if info.remote.ID == protocol.EmptyDeviceID {
  1063. l.Infof("Device %v sent cluster-config without the device info for the remote on folder %v", deviceID, folder.Description())
  1064. return errMissingRemoteInClusterConfig
  1065. }
  1066. if info.local.ID == protocol.EmptyDeviceID {
  1067. l.Infof("Device %v sent cluster-config without the device info for us locally on folder %v", deviceID, folder.Description())
  1068. return errMissingLocalInClusterConfig
  1069. }
  1070. ccDeviceInfos[folder.ID] = info
  1071. }
  1072. // Needs to happen outside of the fmut, as can cause CommitConfiguration
  1073. if deviceCfg.AutoAcceptFolders {
  1074. w, _ := m.cfg.Modify(func(cfg *config.Configuration) {
  1075. changedFcfg := make(map[string]config.FolderConfiguration)
  1076. haveFcfg := cfg.FolderMap()
  1077. for _, folder := range cm.Folders {
  1078. from, ok := haveFcfg[folder.ID]
  1079. if to, changed := m.handleAutoAccepts(deviceID, folder, ccDeviceInfos[folder.ID], from, ok, cfg.Defaults.Folder.Path); changed {
  1080. changedFcfg[folder.ID] = to
  1081. }
  1082. }
  1083. if len(changedFcfg) == 0 {
  1084. return
  1085. }
  1086. for i := range cfg.Folders {
  1087. if fcfg, ok := changedFcfg[cfg.Folders[i].ID]; ok {
  1088. cfg.Folders[i] = fcfg
  1089. delete(changedFcfg, cfg.Folders[i].ID)
  1090. }
  1091. }
  1092. for _, fcfg := range changedFcfg {
  1093. cfg.Folders = append(cfg.Folders, fcfg)
  1094. }
  1095. })
  1096. // Need to wait for the waiter, as this calls CommitConfiguration,
  1097. // which sets up the folder and as we return from this call,
  1098. // ClusterConfig starts poking at m.folderFiles and other things
  1099. // that might not exist until the config is committed.
  1100. w.Wait()
  1101. }
  1102. tempIndexFolders, paused, err := m.ccHandleFolders(cm.Folders, deviceCfg, ccDeviceInfos, indexSenderRegistry)
  1103. if err != nil {
  1104. return err
  1105. }
  1106. m.pmut.Lock()
  1107. m.remotePausedFolders[deviceID] = paused
  1108. m.pmut.Unlock()
  1109. if len(tempIndexFolders) > 0 {
  1110. m.pmut.RLock()
  1111. conn, ok := m.conn[deviceID]
  1112. m.pmut.RUnlock()
  1113. // In case we've got ClusterConfig, and the connection disappeared
  1114. // from infront of our nose.
  1115. if ok {
  1116. m.progressEmitter.temporaryIndexSubscribe(conn, tempIndexFolders)
  1117. }
  1118. }
  1119. if deviceCfg.Introducer {
  1120. m.cfg.Modify(func(cfg *config.Configuration) {
  1121. folders, devices, foldersDevices, introduced := m.handleIntroductions(deviceCfg, cm, cfg.FolderMap(), cfg.DeviceMap())
  1122. folders, devices, deintroduced := m.handleDeintroductions(deviceCfg, foldersDevices, folders, devices)
  1123. if !introduced && !deintroduced {
  1124. return
  1125. }
  1126. cfg.Folders = make([]config.FolderConfiguration, 0, len(folders))
  1127. for _, fcfg := range folders {
  1128. cfg.Folders = append(cfg.Folders, fcfg)
  1129. }
  1130. cfg.Devices = make([]config.DeviceConfiguration, len(devices))
  1131. for _, dcfg := range devices {
  1132. cfg.Devices = append(cfg.Devices, dcfg)
  1133. }
  1134. })
  1135. }
  1136. return nil
  1137. }
  1138. func (m *model) ccHandleFolders(folders []protocol.Folder, deviceCfg config.DeviceConfiguration, ccDeviceInfos map[string]*indexSenderStartInfo, indexSenders *indexSenderRegistry) ([]string, map[string]struct{}, error) {
  1139. var folderDevice config.FolderDeviceConfiguration
  1140. tempIndexFolders := make([]string, 0, len(folders))
  1141. paused := make(map[string]struct{}, len(folders))
  1142. seenFolders := make(map[string]struct{}, len(folders))
  1143. updatedPending := make([]updatedPendingFolder, 0, len(folders))
  1144. deviceID := deviceCfg.DeviceID
  1145. expiredPending, err := m.db.PendingFoldersForDevice(deviceID)
  1146. if err != nil {
  1147. l.Infof("Could not get pending folders for cleanup: %v", err)
  1148. }
  1149. of := db.ObservedFolder{Time: time.Now().Truncate(time.Second)}
  1150. for _, folder := range folders {
  1151. seenFolders[folder.ID] = struct{}{}
  1152. cfg, ok := m.cfg.Folder(folder.ID)
  1153. if ok {
  1154. folderDevice, ok = cfg.Device(deviceID)
  1155. }
  1156. if !ok {
  1157. indexSenders.remove(folder.ID)
  1158. if deviceCfg.IgnoredFolder(folder.ID) {
  1159. l.Infof("Ignoring folder %s from device %s since we are configured to", folder.Description(), deviceID)
  1160. continue
  1161. }
  1162. delete(expiredPending, folder.ID)
  1163. of.Label = folder.Label
  1164. of.ReceiveEncrypted = len(ccDeviceInfos[folder.ID].local.EncryptionPasswordToken) > 0
  1165. if err := m.db.AddOrUpdatePendingFolder(folder.ID, of, deviceID); err != nil {
  1166. l.Warnf("Failed to persist pending folder entry to database: %v", err)
  1167. }
  1168. indexSenders.addPending(cfg, ccDeviceInfos[folder.ID])
  1169. updatedPending = append(updatedPending, updatedPendingFolder{
  1170. FolderID: folder.ID,
  1171. FolderLabel: folder.Label,
  1172. DeviceID: deviceID,
  1173. ReceiveEncrypted: of.ReceiveEncrypted,
  1174. })
  1175. // DEPRECATED: Only for backwards compatibility, should be removed.
  1176. m.evLogger.Log(events.FolderRejected, map[string]string{
  1177. "folder": folder.ID,
  1178. "folderLabel": folder.Label,
  1179. "device": deviceID.String(),
  1180. })
  1181. l.Infof("Unexpected folder %s sent from device %q; ensure that the folder exists and that this device is selected under \"Share With\" in the folder configuration.", folder.Description(), deviceID)
  1182. continue
  1183. }
  1184. if folder.Paused {
  1185. indexSenders.remove(folder.ID)
  1186. paused[cfg.ID] = struct{}{}
  1187. continue
  1188. }
  1189. if cfg.Paused {
  1190. indexSenders.addPending(cfg, ccDeviceInfos[folder.ID])
  1191. continue
  1192. }
  1193. if err := m.ccCheckEncryption(cfg, folderDevice, ccDeviceInfos[folder.ID], deviceCfg.Untrusted); err != nil {
  1194. sameError := false
  1195. if devs, ok := m.folderEncryptionFailures[folder.ID]; ok {
  1196. sameError = devs[deviceID] == err
  1197. } else {
  1198. m.folderEncryptionFailures[folder.ID] = make(map[protocol.DeviceID]error)
  1199. }
  1200. m.folderEncryptionFailures[folder.ID][deviceID] = err
  1201. msg := fmt.Sprintf("Failure checking encryption consistency with device %v for folder %v: %v", deviceID, cfg.Description(), err)
  1202. if sameError {
  1203. l.Debugln(msg)
  1204. } else {
  1205. if rerr, ok := err.(*redactedError); ok {
  1206. err = rerr.redacted
  1207. }
  1208. m.evLogger.Log(events.Failure, err.Error())
  1209. l.Warnln(msg)
  1210. }
  1211. return tempIndexFolders, paused, err
  1212. }
  1213. if devErrs, ok := m.folderEncryptionFailures[folder.ID]; ok {
  1214. if len(devErrs) == 1 {
  1215. delete(m.folderEncryptionFailures, folder.ID)
  1216. } else {
  1217. delete(m.folderEncryptionFailures[folder.ID], deviceID)
  1218. }
  1219. }
  1220. // Handle indexes
  1221. if !folder.DisableTempIndexes {
  1222. tempIndexFolders = append(tempIndexFolders, folder.ID)
  1223. }
  1224. m.fmut.RLock()
  1225. fs, ok := m.folderFiles[folder.ID]
  1226. m.fmut.RUnlock()
  1227. if !ok {
  1228. // Shouldn't happen because !cfg.Paused, but might happen
  1229. // if the folder is about to be unpaused, but not yet.
  1230. l.Debugln("ccH: no fset", folder.ID)
  1231. indexSenders.addPending(cfg, ccDeviceInfos[folder.ID])
  1232. continue
  1233. }
  1234. indexSenders.add(cfg, fs, ccDeviceInfos[folder.ID])
  1235. // We might already have files that we need to pull so let the
  1236. // folder runner know that it should recheck the index data.
  1237. m.fmut.RLock()
  1238. if runner := m.folderRunners[folder.ID]; runner != nil {
  1239. defer runner.SchedulePull()
  1240. }
  1241. m.fmut.RUnlock()
  1242. }
  1243. indexSenders.removeAllExcept(seenFolders)
  1244. for folder := range expiredPending {
  1245. m.db.RemovePendingFolderForDevice(folder, deviceID)
  1246. }
  1247. if len(updatedPending) > 0 || len(expiredPending) > 0 {
  1248. expiredPendingList := make([]map[string]string, 0, len(expiredPending))
  1249. for folderID := range expiredPending {
  1250. expiredPendingList = append(expiredPendingList, map[string]string{
  1251. "folderID": folderID,
  1252. "deviceID": deviceID.String(),
  1253. })
  1254. }
  1255. m.evLogger.Log(events.PendingFoldersChanged, map[string]interface{}{
  1256. "added": updatedPending,
  1257. "removed": expiredPendingList,
  1258. })
  1259. }
  1260. return tempIndexFolders, paused, nil
  1261. }
  1262. func (m *model) ccCheckEncryption(fcfg config.FolderConfiguration, folderDevice config.FolderDeviceConfiguration, ccDeviceInfos *indexSenderStartInfo, deviceUntrusted bool) error {
  1263. hasTokenRemote := len(ccDeviceInfos.remote.EncryptionPasswordToken) > 0
  1264. hasTokenLocal := len(ccDeviceInfos.local.EncryptionPasswordToken) > 0
  1265. isEncryptedRemote := folderDevice.EncryptionPassword != ""
  1266. isEncryptedLocal := fcfg.Type == config.FolderTypeReceiveEncrypted
  1267. if !isEncryptedRemote && !isEncryptedLocal && deviceUntrusted {
  1268. return errEncryptionNotEncryptedUntrusted
  1269. }
  1270. if !(hasTokenRemote || hasTokenLocal || isEncryptedRemote || isEncryptedLocal) {
  1271. // Noone cares about encryption here
  1272. return nil
  1273. }
  1274. if isEncryptedRemote && isEncryptedLocal {
  1275. // Should never happen, but config racyness and be safe.
  1276. return errEncryptionInvConfigLocal
  1277. }
  1278. if hasTokenRemote && hasTokenLocal {
  1279. return errEncryptionInvConfigRemote
  1280. }
  1281. if !(hasTokenRemote || hasTokenLocal) {
  1282. return errEncryptionNotEncryptedRemote
  1283. }
  1284. if !(isEncryptedRemote || isEncryptedLocal) {
  1285. return errEncryptionNotEncryptedLocal
  1286. }
  1287. if isEncryptedRemote {
  1288. passwordToken := protocol.PasswordToken(fcfg.ID, folderDevice.EncryptionPassword)
  1289. match := false
  1290. if hasTokenLocal {
  1291. match = bytes.Equal(passwordToken, ccDeviceInfos.local.EncryptionPasswordToken)
  1292. } else {
  1293. // hasTokenRemote == true
  1294. match = bytes.Equal(passwordToken, ccDeviceInfos.remote.EncryptionPasswordToken)
  1295. }
  1296. if !match {
  1297. return errEncryptionPassword
  1298. }
  1299. return nil
  1300. }
  1301. // isEncryptedLocal == true
  1302. var ccToken []byte
  1303. if hasTokenLocal {
  1304. ccToken = ccDeviceInfos.local.EncryptionPasswordToken
  1305. } else {
  1306. // hasTokenRemote == true
  1307. ccToken = ccDeviceInfos.remote.EncryptionPasswordToken
  1308. }
  1309. m.fmut.RLock()
  1310. token, ok := m.folderEncryptionPasswordTokens[fcfg.ID]
  1311. m.fmut.RUnlock()
  1312. if !ok {
  1313. var err error
  1314. token, err = readEncryptionToken(fcfg)
  1315. if err != nil && !fs.IsNotExist(err) {
  1316. if rerr, ok := redactPathError(err); ok {
  1317. return rerr
  1318. }
  1319. return &redactedError{
  1320. error: err,
  1321. redacted: errEncryptionTokenRead,
  1322. }
  1323. }
  1324. if err == nil {
  1325. m.fmut.Lock()
  1326. m.folderEncryptionPasswordTokens[fcfg.ID] = token
  1327. m.fmut.Unlock()
  1328. } else {
  1329. if err := writeEncryptionToken(ccToken, fcfg); err != nil {
  1330. if rerr, ok := redactPathError(err); ok {
  1331. return rerr
  1332. } else {
  1333. return &redactedError{
  1334. error: err,
  1335. redacted: errEncryptionTokenWrite,
  1336. }
  1337. }
  1338. }
  1339. m.fmut.Lock()
  1340. m.folderEncryptionPasswordTokens[fcfg.ID] = ccToken
  1341. m.fmut.Unlock()
  1342. // We can only announce ourselfs once we have the token,
  1343. // thus we need to resend CCs now that we have it.
  1344. m.sendClusterConfig(fcfg.DeviceIDs())
  1345. return nil
  1346. }
  1347. }
  1348. if !bytes.Equal(token, ccToken) {
  1349. return errEncryptionPassword
  1350. }
  1351. return nil
  1352. }
  1353. func (m *model) sendClusterConfig(ids []protocol.DeviceID) {
  1354. if len(ids) == 0 {
  1355. return
  1356. }
  1357. ccConns := make([]protocol.Connection, 0, len(ids))
  1358. m.pmut.RLock()
  1359. for _, id := range ids {
  1360. if conn, ok := m.conn[id]; ok {
  1361. ccConns = append(ccConns, conn)
  1362. }
  1363. }
  1364. m.pmut.RUnlock()
  1365. // Generating cluster-configs acquires fmut -> must happen outside of pmut.
  1366. for _, conn := range ccConns {
  1367. cm, passwords, err := m.generateClusterConfig(conn.ID())
  1368. if err != nil {
  1369. if err != errEncryptionNeedToken {
  1370. m.evLogger.Log(events.Failure, failureUnexpectedGenerateCCError)
  1371. continue
  1372. }
  1373. go conn.Close(err)
  1374. continue
  1375. }
  1376. conn.SetFolderPasswords(passwords)
  1377. go conn.ClusterConfig(cm)
  1378. }
  1379. }
  1380. // handleIntroductions handles adding devices/folders that are shared by an introducer device
  1381. func (m *model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm protocol.ClusterConfig, folders map[string]config.FolderConfiguration, devices map[protocol.DeviceID]config.DeviceConfiguration) (map[string]config.FolderConfiguration, map[protocol.DeviceID]config.DeviceConfiguration, folderDeviceSet, bool) {
  1382. changed := false
  1383. foldersDevices := make(folderDeviceSet)
  1384. for _, folder := range cm.Folders {
  1385. // Adds devices which we do not have, but the introducer has
  1386. // for the folders that we have in common. Also, shares folders
  1387. // with devices that we have in common, yet are currently not sharing
  1388. // the folder.
  1389. fcfg, ok := folders[folder.ID]
  1390. if !ok {
  1391. // Don't have this folder, carry on.
  1392. continue
  1393. }
  1394. folderChanged := false
  1395. for _, device := range folder.Devices {
  1396. // No need to share with self.
  1397. if device.ID == m.id {
  1398. continue
  1399. }
  1400. foldersDevices.set(device.ID, folder.ID)
  1401. if _, ok := devices[device.ID]; !ok {
  1402. // The device is currently unknown. Add it to the config.
  1403. devices[device.ID] = m.introduceDevice(device, introducerCfg)
  1404. } else if fcfg.SharedWith(device.ID) {
  1405. // We already share the folder with this device, so
  1406. // nothing to do.
  1407. continue
  1408. }
  1409. // We don't yet share this folder with this device. Add the device
  1410. // to sharing list of the folder.
  1411. l.Infof("Sharing folder %s with %v (vouched for by introducer %v)", folder.Description(), device.ID, introducerCfg.DeviceID)
  1412. fcfg.Devices = append(fcfg.Devices, config.FolderDeviceConfiguration{
  1413. DeviceID: device.ID,
  1414. IntroducedBy: introducerCfg.DeviceID,
  1415. })
  1416. folderChanged = true
  1417. }
  1418. if folderChanged {
  1419. folders[fcfg.ID] = fcfg
  1420. changed = true
  1421. }
  1422. }
  1423. return folders, devices, foldersDevices, changed
  1424. }
  1425. // handleDeintroductions handles removals of devices/shares that are removed by an introducer device
  1426. func (m *model) handleDeintroductions(introducerCfg config.DeviceConfiguration, foldersDevices folderDeviceSet, folders map[string]config.FolderConfiguration, devices map[protocol.DeviceID]config.DeviceConfiguration) (map[string]config.FolderConfiguration, map[protocol.DeviceID]config.DeviceConfiguration, bool) {
  1427. if introducerCfg.SkipIntroductionRemovals {
  1428. return folders, devices, false
  1429. }
  1430. changed := false
  1431. devicesNotIntroduced := make(map[protocol.DeviceID]struct{})
  1432. // Check if we should unshare some folders, if the introducer has unshared them.
  1433. for folderID, folderCfg := range folders {
  1434. for k := 0; k < len(folderCfg.Devices); k++ {
  1435. if folderCfg.Devices[k].IntroducedBy != introducerCfg.DeviceID {
  1436. devicesNotIntroduced[folderCfg.Devices[k].DeviceID] = struct{}{}
  1437. continue
  1438. }
  1439. if !foldersDevices.has(folderCfg.Devices[k].DeviceID, folderCfg.ID) {
  1440. // We could not find that folder shared on the
  1441. // introducer with the device that was introduced to us.
  1442. // We should follow and unshare as well.
  1443. l.Infof("Unsharing folder %s with %v as introducer %v no longer shares the folder with that device", folderCfg.Description(), folderCfg.Devices[k].DeviceID, folderCfg.Devices[k].IntroducedBy)
  1444. folderCfg.Devices = append(folderCfg.Devices[:k], folderCfg.Devices[k+1:]...)
  1445. folders[folderID] = folderCfg
  1446. k--
  1447. changed = true
  1448. }
  1449. }
  1450. }
  1451. // Check if we should remove some devices, if the introducer no longer
  1452. // shares any folder with them. Yet do not remove if we share other
  1453. // folders that haven't been introduced by the introducer.
  1454. for deviceID, device := range devices {
  1455. if device.IntroducedBy == introducerCfg.DeviceID {
  1456. if !foldersDevices.hasDevice(deviceID) {
  1457. if _, ok := devicesNotIntroduced[deviceID]; !ok {
  1458. // The introducer no longer shares any folder with the
  1459. // device, remove the device.
  1460. l.Infof("Removing device %v as introducer %v no longer shares any folders with that device", deviceID, device.IntroducedBy)
  1461. changed = true
  1462. delete(devices, deviceID)
  1463. continue
  1464. }
  1465. l.Infof("Would have removed %v as %v no longer shares any folders, yet there are other folders that are shared with this device that haven't been introduced by this introducer.", deviceID, device.IntroducedBy)
  1466. }
  1467. }
  1468. }
  1469. return folders, devices, changed
  1470. }
  1471. // handleAutoAccepts handles adding and sharing folders for devices that have
  1472. // AutoAcceptFolders set to true.
  1473. func (m *model) handleAutoAccepts(deviceID protocol.DeviceID, folder protocol.Folder, ccDeviceInfos *indexSenderStartInfo, cfg config.FolderConfiguration, haveCfg bool, defaultPath string) (config.FolderConfiguration, bool) {
  1474. if !haveCfg {
  1475. defaultPathFs := fs.NewFilesystem(fs.FilesystemTypeBasic, defaultPath)
  1476. pathAlternatives := []string{
  1477. fs.SanitizePath(folder.Label),
  1478. fs.SanitizePath(folder.ID),
  1479. }
  1480. for _, path := range pathAlternatives {
  1481. if _, err := defaultPathFs.Lstat(path); !fs.IsNotExist(err) {
  1482. continue
  1483. }
  1484. fcfg := newFolderConfiguration(m.cfg, folder.ID, folder.Label, fs.FilesystemTypeBasic, filepath.Join(defaultPath, path))
  1485. fcfg.Devices = append(fcfg.Devices, config.FolderDeviceConfiguration{
  1486. DeviceID: deviceID,
  1487. })
  1488. if len(ccDeviceInfos.remote.EncryptionPasswordToken) > 0 || len(ccDeviceInfos.local.EncryptionPasswordToken) > 0 {
  1489. fcfg.Type = config.FolderTypeReceiveEncrypted
  1490. }
  1491. l.Infof("Auto-accepted %s folder %s at path %s", deviceID, folder.Description(), fcfg.Path)
  1492. return fcfg, true
  1493. }
  1494. l.Infof("Failed to auto-accept folder %s from %s due to path conflict", folder.Description(), deviceID)
  1495. return config.FolderConfiguration{}, false
  1496. } else {
  1497. for _, device := range cfg.DeviceIDs() {
  1498. if device == deviceID {
  1499. // Already shared nothing todo.
  1500. return config.FolderConfiguration{}, false
  1501. }
  1502. }
  1503. if cfg.Type == config.FolderTypeReceiveEncrypted {
  1504. if len(ccDeviceInfos.remote.EncryptionPasswordToken) == 0 && len(ccDeviceInfos.local.EncryptionPasswordToken) == 0 {
  1505. l.Infof("Failed to auto-accept device %s on existing folder %s as the remote wants to send us unencrypted data, but the folder type is receive-encrypted", folder.Description(), deviceID)
  1506. return config.FolderConfiguration{}, false
  1507. }
  1508. } else {
  1509. if len(ccDeviceInfos.remote.EncryptionPasswordToken) > 0 || len(ccDeviceInfos.local.EncryptionPasswordToken) > 0 {
  1510. l.Infof("Failed to auto-accept device %s on existing folder %s as the remote wants to send us encrypted data, but the folder type is not receive-encrypted", folder.Description(), deviceID)
  1511. return config.FolderConfiguration{}, false
  1512. }
  1513. }
  1514. cfg.Devices = append(cfg.Devices, config.FolderDeviceConfiguration{
  1515. DeviceID: deviceID,
  1516. })
  1517. l.Infof("Shared %s with %s due to auto-accept", folder.ID, deviceID)
  1518. return cfg, true
  1519. }
  1520. }
  1521. func (m *model) introduceDevice(device protocol.Device, introducerCfg config.DeviceConfiguration) config.DeviceConfiguration {
  1522. addresses := []string{"dynamic"}
  1523. for _, addr := range device.Addresses {
  1524. if addr != "dynamic" {
  1525. addresses = append(addresses, addr)
  1526. }
  1527. }
  1528. l.Infof("Adding device %v to config (vouched for by introducer %v)", device.ID, introducerCfg.DeviceID)
  1529. newDeviceCfg := m.cfg.DefaultDevice()
  1530. newDeviceCfg.DeviceID = device.ID
  1531. newDeviceCfg.Name = device.Name
  1532. newDeviceCfg.Compression = introducerCfg.Compression
  1533. newDeviceCfg.Addresses = addresses
  1534. newDeviceCfg.CertName = device.CertName
  1535. newDeviceCfg.IntroducedBy = introducerCfg.DeviceID
  1536. // The introducers' introducers are also our introducers.
  1537. if device.Introducer {
  1538. l.Infof("Device %v is now also an introducer", device.ID)
  1539. newDeviceCfg.Introducer = true
  1540. newDeviceCfg.SkipIntroductionRemovals = device.SkipIntroductionRemovals
  1541. }
  1542. return newDeviceCfg
  1543. }
  1544. // Closed is called when a connection has been closed
  1545. func (m *model) Closed(device protocol.DeviceID, err error) {
  1546. m.pmut.Lock()
  1547. conn, ok := m.conn[device]
  1548. if !ok {
  1549. m.pmut.Unlock()
  1550. return
  1551. }
  1552. delete(m.conn, device)
  1553. delete(m.connRequestLimiters, device)
  1554. delete(m.helloMessages, device)
  1555. delete(m.deviceDownloads, device)
  1556. delete(m.remotePausedFolders, device)
  1557. closed := m.closed[device]
  1558. delete(m.closed, device)
  1559. delete(m.indexSenders, device)
  1560. m.pmut.Unlock()
  1561. m.progressEmitter.temporaryIndexUnsubscribe(conn)
  1562. m.deviceDidClose(device, time.Since(conn.EstablishedAt()))
  1563. l.Infof("Connection to %s at %s closed: %v", device, conn, err)
  1564. m.evLogger.Log(events.DeviceDisconnected, map[string]string{
  1565. "id": device.String(),
  1566. "error": err.Error(),
  1567. })
  1568. close(closed)
  1569. }
  1570. // Implements protocol.RequestResponse
  1571. type requestResponse struct {
  1572. data []byte
  1573. closed chan struct{}
  1574. once stdsync.Once
  1575. }
  1576. func newRequestResponse(size int) *requestResponse {
  1577. return &requestResponse{
  1578. data: protocol.BufferPool.Get(size),
  1579. closed: make(chan struct{}),
  1580. }
  1581. }
  1582. func (r *requestResponse) Data() []byte {
  1583. return r.data
  1584. }
  1585. func (r *requestResponse) Close() {
  1586. r.once.Do(func() {
  1587. protocol.BufferPool.Put(r.data)
  1588. close(r.closed)
  1589. })
  1590. }
  1591. func (r *requestResponse) Wait() {
  1592. <-r.closed
  1593. }
  1594. // Request returns the specified data segment by reading it from local disk.
  1595. // Implements the protocol.Model interface.
  1596. func (m *model) Request(deviceID protocol.DeviceID, folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (out protocol.RequestResponse, err error) {
  1597. if size < 0 || offset < 0 {
  1598. return nil, protocol.ErrInvalid
  1599. }
  1600. m.fmut.RLock()
  1601. folderCfg, ok := m.folderCfgs[folder]
  1602. folderIgnores := m.folderIgnores[folder]
  1603. m.fmut.RUnlock()
  1604. if !ok {
  1605. // The folder might be already unpaused in the config, but not yet
  1606. // in the model.
  1607. l.Debugf("Request from %s for file %s in unstarted folder %q", deviceID, name, folder)
  1608. return nil, protocol.ErrGeneric
  1609. }
  1610. if !folderCfg.SharedWith(deviceID) {
  1611. l.Warnf("Request from %s for file %s in unshared folder %q", deviceID, name, folder)
  1612. return nil, protocol.ErrGeneric
  1613. }
  1614. if folderCfg.Paused {
  1615. l.Debugf("Request from %s for file %s in paused folder %q", deviceID, name, folder)
  1616. return nil, protocol.ErrGeneric
  1617. }
  1618. // Make sure the path is valid and in canonical form
  1619. if name, err = fs.Canonicalize(name); err != nil {
  1620. l.Debugf("Request from %s in folder %q for invalid filename %s", deviceID, folder, name)
  1621. return nil, protocol.ErrGeneric
  1622. }
  1623. if deviceID != protocol.LocalDeviceID {
  1624. l.Debugf("%v REQ(in): %s: %q / %q o=%d s=%d t=%v", m, deviceID, folder, name, offset, size, fromTemporary)
  1625. }
  1626. if fs.IsInternal(name) {
  1627. l.Debugf("%v REQ(in) for internal file: %s: %q / %q o=%d s=%d", m, deviceID, folder, name, offset, size)
  1628. return nil, protocol.ErrInvalid
  1629. }
  1630. if folderIgnores.Match(name).IsIgnored() {
  1631. l.Debugf("%v REQ(in) for ignored file: %s: %q / %q o=%d s=%d", m, deviceID, folder, name, offset, size)
  1632. return nil, protocol.ErrInvalid
  1633. }
  1634. // Restrict parallel requests by connection/device
  1635. m.pmut.RLock()
  1636. limiter := m.connRequestLimiters[deviceID]
  1637. m.pmut.RUnlock()
  1638. // The requestResponse releases the bytes to the buffer pool and the
  1639. // limiters when its Close method is called.
  1640. res := newLimitedRequestResponse(int(size), limiter, m.globalRequestLimiter)
  1641. defer func() {
  1642. // Close it ourselves if it isn't returned due to an error
  1643. if err != nil {
  1644. res.Close()
  1645. }
  1646. }()
  1647. // Grab the FS after limiting, as it causes I/O and we want to minimize
  1648. // the race time between the symlink check and the read.
  1649. folderFs := folderCfg.Filesystem()
  1650. if err := osutil.TraversesSymlink(folderFs, filepath.Dir(name)); err != nil {
  1651. l.Debugf("%v REQ(in) traversal check: %s - %s: %q / %q o=%d s=%d", m, err, deviceID, folder, name, offset, size)
  1652. return nil, protocol.ErrNoSuchFile
  1653. }
  1654. // Only check temp files if the flag is set, and if we are set to advertise
  1655. // the temp indexes.
  1656. if fromTemporary && !folderCfg.DisableTempIndexes {
  1657. tempFn := fs.TempName(name)
  1658. if info, err := folderFs.Lstat(tempFn); err != nil || !info.IsRegular() {
  1659. // Reject reads for anything that doesn't exist or is something
  1660. // other than a regular file.
  1661. l.Debugf("%v REQ(in) failed stating temp file (%v): %s: %q / %q o=%d s=%d", m, err, deviceID, folder, name, offset, size)
  1662. return nil, protocol.ErrNoSuchFile
  1663. }
  1664. _, err := readOffsetIntoBuf(folderFs, tempFn, offset, res.data)
  1665. if err == nil && scanner.Validate(res.data, hash, weakHash) {
  1666. return res, nil
  1667. }
  1668. // Fall through to reading from a non-temp file, just incase the temp
  1669. // file has finished downloading.
  1670. }
  1671. if info, err := folderFs.Lstat(name); err != nil || !info.IsRegular() {
  1672. // Reject reads for anything that doesn't exist or is something
  1673. // other than a regular file.
  1674. l.Debugf("%v REQ(in) failed stating file (%v): %s: %q / %q o=%d s=%d", m, err, deviceID, folder, name, offset, size)
  1675. return nil, protocol.ErrNoSuchFile
  1676. }
  1677. n, err := readOffsetIntoBuf(folderFs, name, offset, res.data)
  1678. if fs.IsNotExist(err) {
  1679. l.Debugf("%v REQ(in) file doesn't exist: %s: %q / %q o=%d s=%d", m, deviceID, folder, name, offset, size)
  1680. return nil, protocol.ErrNoSuchFile
  1681. } else if err == io.EOF {
  1682. // Read beyond end of file. This might indicate a problem, or it
  1683. // might be a short block that gets padded when read for encrypted
  1684. // folders. We ignore the error and let the hash validation in the
  1685. // next step take care of it, by only hashing the part we actually
  1686. // managed to read.
  1687. } else if err != nil {
  1688. l.Debugf("%v REQ(in) failed reading file (%v): %s: %q / %q o=%d s=%d", m, err, deviceID, folder, name, offset, size)
  1689. return nil, protocol.ErrGeneric
  1690. }
  1691. if len(hash) > 0 && !scanner.Validate(res.data[:n], hash, weakHash) {
  1692. m.recheckFile(deviceID, folder, name, offset, hash, weakHash)
  1693. l.Debugf("%v REQ(in) failed validating data: %s: %q / %q o=%d s=%d", m, deviceID, folder, name, offset, size)
  1694. return nil, protocol.ErrNoSuchFile
  1695. }
  1696. return res, nil
  1697. }
  1698. // newLimitedRequestResponse takes size bytes from the limiters in order,
  1699. // skipping nil limiters, then returns a requestResponse of the given size.
  1700. // When the requestResponse is closed the limiters are given back the bytes,
  1701. // in reverse order.
  1702. func newLimitedRequestResponse(size int, limiters ...*byteSemaphore) *requestResponse {
  1703. for _, limiter := range limiters {
  1704. if limiter != nil {
  1705. limiter.take(size)
  1706. }
  1707. }
  1708. res := newRequestResponse(size)
  1709. go func() {
  1710. res.Wait()
  1711. for i := range limiters {
  1712. limiter := limiters[len(limiters)-1-i]
  1713. if limiter != nil {
  1714. limiter.give(size)
  1715. }
  1716. }
  1717. }()
  1718. return res
  1719. }
  1720. func (m *model) recheckFile(deviceID protocol.DeviceID, folder, name string, offset int64, hash []byte, weakHash uint32) {
  1721. cf, ok, err := m.CurrentFolderFile(folder, name)
  1722. if err != nil {
  1723. l.Debugf("%v recheckFile: %s: %q / %q: current file error: %v", m, deviceID, folder, name, err)
  1724. return
  1725. }
  1726. if !ok {
  1727. l.Debugf("%v recheckFile: %s: %q / %q: no current file", m, deviceID, folder, name)
  1728. return
  1729. }
  1730. if cf.IsDeleted() || cf.IsInvalid() || cf.IsSymlink() || cf.IsDirectory() {
  1731. l.Debugf("%v recheckFile: %s: %q / %q: not a regular file", m, deviceID, folder, name)
  1732. return
  1733. }
  1734. blockIndex := int(offset / int64(cf.BlockSize()))
  1735. if blockIndex >= len(cf.Blocks) {
  1736. l.Debugf("%v recheckFile: %s: %q / %q i=%d: block index too far", m, deviceID, folder, name, blockIndex)
  1737. return
  1738. }
  1739. block := cf.Blocks[blockIndex]
  1740. // Seems to want a different version of the file, whatever.
  1741. if !bytes.Equal(block.Hash, hash) {
  1742. l.Debugf("%v recheckFile: %s: %q / %q i=%d: hash mismatch %x != %x", m, deviceID, folder, name, blockIndex, block.Hash, hash)
  1743. return
  1744. }
  1745. if weakHash != 0 && block.WeakHash != weakHash {
  1746. l.Debugf("%v recheckFile: %s: %q / %q i=%d: weak hash mismatch %v != %v", m, deviceID, folder, name, blockIndex, block.WeakHash, weakHash)
  1747. return
  1748. }
  1749. // The hashes provided part of the request match what we expect to find according
  1750. // to what we have in the database, yet the content we've read off the filesystem doesn't
  1751. // Something is fishy, invalidate the file and rescan it.
  1752. // The file will temporarily become invalid, which is ok as the content is messed up.
  1753. m.fmut.RLock()
  1754. runner, ok := m.folderRunners[folder]
  1755. m.fmut.RUnlock()
  1756. if !ok {
  1757. l.Debugf("%v recheckFile: %s: %q / %q: Folder stopped before rescan could be scheduled", m, deviceID, folder, name)
  1758. return
  1759. }
  1760. runner.ScheduleForceRescan(name)
  1761. l.Debugf("%v recheckFile: %s: %q / %q", m, deviceID, folder, name)
  1762. }
  1763. func (m *model) CurrentFolderFile(folder string, file string) (protocol.FileInfo, bool, error) {
  1764. m.fmut.RLock()
  1765. fs, ok := m.folderFiles[folder]
  1766. m.fmut.RUnlock()
  1767. if !ok {
  1768. return protocol.FileInfo{}, false, ErrFolderMissing
  1769. }
  1770. snap, err := fs.Snapshot()
  1771. if err != nil {
  1772. return protocol.FileInfo{}, false, err
  1773. }
  1774. f, ok := snap.Get(protocol.LocalDeviceID, file)
  1775. snap.Release()
  1776. return f, ok, nil
  1777. }
  1778. func (m *model) CurrentGlobalFile(folder string, file string) (protocol.FileInfo, bool, error) {
  1779. m.fmut.RLock()
  1780. fs, ok := m.folderFiles[folder]
  1781. m.fmut.RUnlock()
  1782. if !ok {
  1783. return protocol.FileInfo{}, false, ErrFolderMissing
  1784. }
  1785. snap, err := fs.Snapshot()
  1786. if err != nil {
  1787. return protocol.FileInfo{}, false, err
  1788. }
  1789. f, ok := snap.GetGlobal(file)
  1790. snap.Release()
  1791. return f, ok, nil
  1792. }
  1793. // Connection returns the current connection for device, and a boolean whether a connection was found.
  1794. func (m *model) Connection(deviceID protocol.DeviceID) (protocol.Connection, bool) {
  1795. m.pmut.RLock()
  1796. cn, ok := m.conn[deviceID]
  1797. m.pmut.RUnlock()
  1798. if ok {
  1799. m.deviceWasSeen(deviceID)
  1800. }
  1801. return cn, ok
  1802. }
  1803. // LoadIgnores loads or refreshes the ignore patterns from disk, if the
  1804. // folder is healthy, and returns the refreshed lines and patterns.
  1805. func (m *model) LoadIgnores(folder string) ([]string, []string, error) {
  1806. m.fmut.RLock()
  1807. cfg, cfgOk := m.folderCfgs[folder]
  1808. ignores, ignoresOk := m.folderIgnores[folder]
  1809. m.fmut.RUnlock()
  1810. if !cfgOk {
  1811. cfg, cfgOk = m.cfg.Folder(folder)
  1812. if !cfgOk {
  1813. return nil, nil, fmt.Errorf("folder %s does not exist", folder)
  1814. }
  1815. }
  1816. if cfg.Type == config.FolderTypeReceiveEncrypted {
  1817. return nil, nil, nil
  1818. }
  1819. // On creation a new folder with ignore patterns validly has no marker yet.
  1820. if err := cfg.CheckPath(); err != nil && err != config.ErrMarkerMissing {
  1821. return nil, nil, err
  1822. }
  1823. if !ignoresOk {
  1824. ignores = ignore.New(cfg.Filesystem())
  1825. }
  1826. err := ignores.Load(".stignore")
  1827. if fs.IsNotExist(err) {
  1828. // Having no ignores is not an error.
  1829. return nil, nil, nil
  1830. }
  1831. // Return lines and patterns, which may have some meaning even when err
  1832. // != nil, depending on the specific error.
  1833. return ignores.Lines(), ignores.Patterns(), err
  1834. }
  1835. // CurrentIgnores returns the currently loaded set of ignore patterns,
  1836. // whichever it may be. No attempt is made to load or refresh ignore
  1837. // patterns from disk.
  1838. func (m *model) CurrentIgnores(folder string) ([]string, []string, error) {
  1839. m.fmut.RLock()
  1840. _, cfgOk := m.folderCfgs[folder]
  1841. ignores, ignoresOk := m.folderIgnores[folder]
  1842. m.fmut.RUnlock()
  1843. if !cfgOk {
  1844. return nil, nil, fmt.Errorf("folder %s does not exist", folder)
  1845. }
  1846. if !ignoresOk {
  1847. // Empty ignore patterns
  1848. return []string{}, []string{}, nil
  1849. }
  1850. return ignores.Lines(), ignores.Patterns(), nil
  1851. }
  1852. func (m *model) SetIgnores(folder string, content []string) error {
  1853. cfg, ok := m.cfg.Folder(folder)
  1854. if !ok {
  1855. return fmt.Errorf("folder %s does not exist", cfg.Description())
  1856. }
  1857. err := cfg.CheckPath()
  1858. if err == config.ErrPathMissing {
  1859. if err = cfg.CreateRoot(); err != nil {
  1860. return errors.Wrap(err, "failed to create folder root")
  1861. }
  1862. err = cfg.CheckPath()
  1863. }
  1864. if err != nil && err != config.ErrMarkerMissing {
  1865. return err
  1866. }
  1867. if err := ignore.WriteIgnores(cfg.Filesystem(), ".stignore", content); err != nil {
  1868. l.Warnln("Saving .stignore:", err)
  1869. return err
  1870. }
  1871. m.fmut.RLock()
  1872. runner, ok := m.folderRunners[folder]
  1873. m.fmut.RUnlock()
  1874. if ok {
  1875. return runner.Scan(nil)
  1876. }
  1877. return nil
  1878. }
  1879. // OnHello is called when an device connects to us.
  1880. // This allows us to extract some information from the Hello message
  1881. // and add it to a list of known devices ahead of any checks.
  1882. func (m *model) OnHello(remoteID protocol.DeviceID, addr net.Addr, hello protocol.Hello) error {
  1883. if m.cfg.IgnoredDevice(remoteID) {
  1884. return errDeviceIgnored
  1885. }
  1886. cfg, ok := m.cfg.Device(remoteID)
  1887. if !ok {
  1888. if err := m.db.AddOrUpdatePendingDevice(remoteID, hello.DeviceName, addr.String()); err != nil {
  1889. l.Warnf("Failed to persist pending device entry to database: %v", err)
  1890. }
  1891. m.evLogger.Log(events.PendingDevicesChanged, map[string][]interface{}{
  1892. "added": {map[string]string{
  1893. "deviceID": remoteID.String(),
  1894. "name": hello.DeviceName,
  1895. "address": addr.String(),
  1896. }},
  1897. })
  1898. // DEPRECATED: Only for backwards compatibility, should be removed.
  1899. m.evLogger.Log(events.DeviceRejected, map[string]string{
  1900. "name": hello.DeviceName,
  1901. "device": remoteID.String(),
  1902. "address": addr.String(),
  1903. })
  1904. return errDeviceUnknown
  1905. }
  1906. if cfg.Paused {
  1907. return errDevicePaused
  1908. }
  1909. if len(cfg.AllowedNetworks) > 0 && !connections.IsAllowedNetwork(addr.String(), cfg.AllowedNetworks) {
  1910. // The connection is not from an allowed network.
  1911. return errNetworkNotAllowed
  1912. }
  1913. if max := m.cfg.Options().ConnectionLimitMax; max > 0 && m.NumConnections() >= max {
  1914. // We're not allowed to accept any more connections.
  1915. return errConnLimitReached
  1916. }
  1917. return nil
  1918. }
  1919. // GetHello is called when we are about to connect to some remote device.
  1920. func (m *model) GetHello(id protocol.DeviceID) protocol.HelloIntf {
  1921. name := ""
  1922. if _, ok := m.cfg.Device(id); ok {
  1923. // Set our name (from the config of our device ID) only if we already know about the other side device ID.
  1924. if myCfg, ok := m.cfg.Device(m.id); ok {
  1925. name = myCfg.Name
  1926. }
  1927. }
  1928. return &protocol.Hello{
  1929. DeviceName: name,
  1930. ClientName: m.clientName,
  1931. ClientVersion: m.clientVersion,
  1932. }
  1933. }
  1934. // AddConnection adds a new peer connection to the model. An initial index will
  1935. // be sent to the connected peer, thereafter index updates whenever the local
  1936. // folder changes.
  1937. func (m *model) AddConnection(conn protocol.Connection, hello protocol.Hello) {
  1938. deviceID := conn.ID()
  1939. device, ok := m.cfg.Device(deviceID)
  1940. if !ok {
  1941. l.Infoln("Trying to add connection to unknown device")
  1942. return
  1943. }
  1944. m.pmut.Lock()
  1945. if oldConn, ok := m.conn[deviceID]; ok {
  1946. l.Infoln("Replacing old connection", oldConn, "with", conn, "for", deviceID)
  1947. // There is an existing connection to this device that we are
  1948. // replacing. We must close the existing connection and wait for the
  1949. // close to complete before adding the new connection. We do the
  1950. // actual close without holding pmut as the connection will call
  1951. // back into Closed() for the cleanup.
  1952. closed := m.closed[deviceID]
  1953. m.pmut.Unlock()
  1954. oldConn.Close(errReplacingConnection)
  1955. <-closed
  1956. m.pmut.Lock()
  1957. }
  1958. m.conn[deviceID] = conn
  1959. closed := make(chan struct{})
  1960. m.closed[deviceID] = closed
  1961. m.deviceDownloads[deviceID] = newDeviceDownloadState()
  1962. m.indexSenders[deviceID] = newIndexSenderRegistry(conn, closed, m.Supervisor, m.evLogger)
  1963. // 0: default, <0: no limiting
  1964. switch {
  1965. case device.MaxRequestKiB > 0:
  1966. m.connRequestLimiters[deviceID] = newByteSemaphore(1024 * device.MaxRequestKiB)
  1967. case device.MaxRequestKiB == 0:
  1968. m.connRequestLimiters[deviceID] = newByteSemaphore(1024 * defaultPullerPendingKiB)
  1969. }
  1970. m.helloMessages[deviceID] = hello
  1971. event := map[string]string{
  1972. "id": deviceID.String(),
  1973. "deviceName": hello.DeviceName,
  1974. "clientName": hello.ClientName,
  1975. "clientVersion": hello.ClientVersion,
  1976. "type": conn.Type(),
  1977. }
  1978. addr := conn.RemoteAddr()
  1979. if addr != nil {
  1980. event["addr"] = addr.String()
  1981. }
  1982. m.evLogger.Log(events.DeviceConnected, event)
  1983. l.Infof(`Device %s client is "%s %s" named "%s" at %s`, deviceID, hello.ClientName, hello.ClientVersion, hello.DeviceName, conn)
  1984. conn.Start()
  1985. m.pmut.Unlock()
  1986. // Acquires fmut, so has to be done outside of pmut.
  1987. cm, passwords, err := m.generateClusterConfig(deviceID)
  1988. // We ignore errEncryptionNeedToken on a new connection, as the missing
  1989. // token should be delivered in the cluster-config about to be received.
  1990. if err != nil && err != errEncryptionNeedToken {
  1991. m.evLogger.Log(events.Failure, failureUnexpectedGenerateCCError)
  1992. }
  1993. conn.SetFolderPasswords(passwords)
  1994. conn.ClusterConfig(cm)
  1995. if (device.Name == "" || m.cfg.Options().OverwriteRemoteDevNames) && hello.DeviceName != "" {
  1996. m.cfg.Modify(func(cfg *config.Configuration) {
  1997. for i := range cfg.Devices {
  1998. if cfg.Devices[i].DeviceID == deviceID {
  1999. if cfg.Devices[i].Name == "" || cfg.Options.OverwriteRemoteDevNames {
  2000. cfg.Devices[i].Name = hello.DeviceName
  2001. }
  2002. return
  2003. }
  2004. }
  2005. })
  2006. }
  2007. m.deviceWasSeen(deviceID)
  2008. }
  2009. func (m *model) DownloadProgress(device protocol.DeviceID, folder string, updates []protocol.FileDownloadProgressUpdate) error {
  2010. m.fmut.RLock()
  2011. cfg, ok := m.folderCfgs[folder]
  2012. m.fmut.RUnlock()
  2013. if !ok || cfg.DisableTempIndexes || !cfg.SharedWith(device) {
  2014. return nil
  2015. }
  2016. m.pmut.RLock()
  2017. downloads := m.deviceDownloads[device]
  2018. m.pmut.RUnlock()
  2019. downloads.Update(folder, updates)
  2020. state := downloads.GetBlockCounts(folder)
  2021. m.evLogger.Log(events.RemoteDownloadProgress, map[string]interface{}{
  2022. "device": device.String(),
  2023. "folder": folder,
  2024. "state": state,
  2025. })
  2026. return nil
  2027. }
  2028. func (m *model) deviceWasSeen(deviceID protocol.DeviceID) {
  2029. m.fmut.RLock()
  2030. sr, ok := m.deviceStatRefs[deviceID]
  2031. m.fmut.RUnlock()
  2032. if ok {
  2033. _ = sr.WasSeen()
  2034. }
  2035. }
  2036. func (m *model) deviceDidClose(deviceID protocol.DeviceID, duration time.Duration) {
  2037. m.fmut.RLock()
  2038. sr, ok := m.deviceStatRefs[deviceID]
  2039. m.fmut.RUnlock()
  2040. if ok {
  2041. _ = sr.LastConnectionDuration(duration)
  2042. }
  2043. }
  2044. func (m *model) requestGlobal(ctx context.Context, deviceID protocol.DeviceID, folder, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
  2045. m.pmut.RLock()
  2046. nc, ok := m.conn[deviceID]
  2047. m.pmut.RUnlock()
  2048. if !ok {
  2049. return nil, fmt.Errorf("requestGlobal: no such device: %s", deviceID)
  2050. }
  2051. l.Debugf("%v REQ(out): %s: %q / %q b=%d o=%d s=%d h=%x wh=%x ft=%t", m, deviceID, folder, name, blockNo, offset, size, hash, weakHash, fromTemporary)
  2052. return nc.Request(ctx, folder, name, blockNo, offset, size, hash, weakHash, fromTemporary)
  2053. }
  2054. func (m *model) ScanFolders() map[string]error {
  2055. m.fmut.RLock()
  2056. folders := make([]string, 0, len(m.folderCfgs))
  2057. for folder := range m.folderCfgs {
  2058. folders = append(folders, folder)
  2059. }
  2060. m.fmut.RUnlock()
  2061. errors := make(map[string]error, len(m.folderCfgs))
  2062. errorsMut := sync.NewMutex()
  2063. wg := sync.NewWaitGroup()
  2064. wg.Add(len(folders))
  2065. for _, folder := range folders {
  2066. folder := folder
  2067. go func() {
  2068. err := m.ScanFolder(folder)
  2069. if err != nil {
  2070. errorsMut.Lock()
  2071. errors[folder] = err
  2072. errorsMut.Unlock()
  2073. }
  2074. wg.Done()
  2075. }()
  2076. }
  2077. wg.Wait()
  2078. return errors
  2079. }
  2080. func (m *model) ScanFolder(folder string) error {
  2081. return m.ScanFolderSubdirs(folder, nil)
  2082. }
  2083. func (m *model) ScanFolderSubdirs(folder string, subs []string) error {
  2084. m.fmut.RLock()
  2085. err := m.checkFolderRunningLocked(folder)
  2086. runner := m.folderRunners[folder]
  2087. m.fmut.RUnlock()
  2088. if err != nil {
  2089. return err
  2090. }
  2091. return runner.Scan(subs)
  2092. }
  2093. func (m *model) DelayScan(folder string, next time.Duration) {
  2094. m.fmut.RLock()
  2095. runner, ok := m.folderRunners[folder]
  2096. m.fmut.RUnlock()
  2097. if !ok {
  2098. return
  2099. }
  2100. runner.DelayScan(next)
  2101. }
  2102. // numHashers returns the number of hasher routines to use for a given folder,
  2103. // taking into account configuration and available CPU cores.
  2104. func (m *model) numHashers(folder string) int {
  2105. m.fmut.RLock()
  2106. folderCfg := m.folderCfgs[folder]
  2107. numFolders := len(m.folderCfgs)
  2108. m.fmut.RUnlock()
  2109. if folderCfg.Hashers > 0 {
  2110. // Specific value set in the config, use that.
  2111. return folderCfg.Hashers
  2112. }
  2113. if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
  2114. // Interactive operating systems; don't load the system too heavily by
  2115. // default.
  2116. return 1
  2117. }
  2118. // For other operating systems and architectures, lets try to get some
  2119. // work done... Divide the available CPU cores among the configured
  2120. // folders.
  2121. if perFolder := runtime.GOMAXPROCS(-1) / numFolders; perFolder > 0 {
  2122. return perFolder
  2123. }
  2124. return 1
  2125. }
  2126. // generateClusterConfig returns a ClusterConfigMessage that is correct and the
  2127. // set of folder passwords for the given peer device
  2128. func (m *model) generateClusterConfig(device protocol.DeviceID) (protocol.ClusterConfig, map[string]string, error) {
  2129. var message protocol.ClusterConfig
  2130. m.fmut.RLock()
  2131. defer m.fmut.RUnlock()
  2132. folders := m.cfg.FolderList()
  2133. passwords := make(map[string]string, len(folders))
  2134. for _, folderCfg := range folders {
  2135. if !folderCfg.SharedWith(device) {
  2136. continue
  2137. }
  2138. var encryptionToken []byte
  2139. var hasEncryptionToken bool
  2140. if folderCfg.Type == config.FolderTypeReceiveEncrypted {
  2141. if encryptionToken, hasEncryptionToken = m.folderEncryptionPasswordTokens[folderCfg.ID]; !hasEncryptionToken {
  2142. // We haven't gotten a token yet and without one the other side
  2143. // can't validate us - reset the connection to trigger a new
  2144. // cluster-config and get the token.
  2145. return message, nil, errEncryptionNeedToken
  2146. }
  2147. }
  2148. protocolFolder := protocol.Folder{
  2149. ID: folderCfg.ID,
  2150. Label: folderCfg.Label,
  2151. ReadOnly: folderCfg.Type == config.FolderTypeSendOnly,
  2152. IgnorePermissions: folderCfg.IgnorePerms,
  2153. IgnoreDelete: folderCfg.IgnoreDelete,
  2154. DisableTempIndexes: folderCfg.DisableTempIndexes,
  2155. }
  2156. fs := m.folderFiles[folderCfg.ID]
  2157. // Even if we aren't paused, if we haven't started the folder yet
  2158. // pretend we are. Otherwise the remote might get confused about
  2159. // the missing index info (and drop all the info). We will send
  2160. // another cluster config once the folder is started.
  2161. protocolFolder.Paused = folderCfg.Paused || fs == nil
  2162. for _, folderDevice := range folderCfg.Devices {
  2163. deviceCfg, _ := m.cfg.Device(folderDevice.DeviceID)
  2164. protocolDevice := protocol.Device{
  2165. ID: deviceCfg.DeviceID,
  2166. Name: deviceCfg.Name,
  2167. Addresses: deviceCfg.Addresses,
  2168. Compression: deviceCfg.Compression,
  2169. CertName: deviceCfg.CertName,
  2170. Introducer: deviceCfg.Introducer,
  2171. }
  2172. if deviceCfg.DeviceID == m.id && hasEncryptionToken {
  2173. protocolDevice.EncryptionPasswordToken = encryptionToken
  2174. } else if folderDevice.EncryptionPassword != "" {
  2175. protocolDevice.EncryptionPasswordToken = protocol.PasswordToken(folderCfg.ID, folderDevice.EncryptionPassword)
  2176. if folderDevice.DeviceID == device {
  2177. passwords[folderCfg.ID] = folderDevice.EncryptionPassword
  2178. }
  2179. }
  2180. if fs != nil {
  2181. if deviceCfg.DeviceID == m.id {
  2182. protocolDevice.IndexID = fs.IndexID(protocol.LocalDeviceID)
  2183. protocolDevice.MaxSequence = fs.Sequence(protocol.LocalDeviceID)
  2184. } else {
  2185. protocolDevice.IndexID = fs.IndexID(deviceCfg.DeviceID)
  2186. protocolDevice.MaxSequence = fs.Sequence(deviceCfg.DeviceID)
  2187. }
  2188. }
  2189. protocolFolder.Devices = append(protocolFolder.Devices, protocolDevice)
  2190. }
  2191. message.Folders = append(message.Folders, protocolFolder)
  2192. }
  2193. return message, passwords, nil
  2194. }
  2195. func (m *model) State(folder string) (string, time.Time, error) {
  2196. m.fmut.RLock()
  2197. runner, ok := m.folderRunners[folder]
  2198. m.fmut.RUnlock()
  2199. if !ok {
  2200. // The returned error should be an actual folder error, so returning
  2201. // errors.New("does not exist") or similar here would be
  2202. // inappropriate.
  2203. return "", time.Time{}, nil
  2204. }
  2205. state, changed, err := runner.getState()
  2206. return state.String(), changed, err
  2207. }
  2208. func (m *model) FolderErrors(folder string) ([]FileError, error) {
  2209. m.fmut.RLock()
  2210. err := m.checkFolderRunningLocked(folder)
  2211. runner := m.folderRunners[folder]
  2212. m.fmut.RUnlock()
  2213. if err != nil {
  2214. return nil, err
  2215. }
  2216. return runner.Errors(), nil
  2217. }
  2218. func (m *model) WatchError(folder string) error {
  2219. m.fmut.RLock()
  2220. err := m.checkFolderRunningLocked(folder)
  2221. runner := m.folderRunners[folder]
  2222. m.fmut.RUnlock()
  2223. if err != nil {
  2224. return nil // If the folder isn't running, there's no error to report.
  2225. }
  2226. return runner.WatchError()
  2227. }
  2228. func (m *model) Override(folder string) {
  2229. // Grab the runner and the file set.
  2230. m.fmut.RLock()
  2231. runner, ok := m.folderRunners[folder]
  2232. m.fmut.RUnlock()
  2233. if !ok {
  2234. return
  2235. }
  2236. // Run the override, taking updates as if they came from scanning.
  2237. runner.Override()
  2238. }
  2239. func (m *model) Revert(folder string) {
  2240. // Grab the runner and the file set.
  2241. m.fmut.RLock()
  2242. runner, ok := m.folderRunners[folder]
  2243. m.fmut.RUnlock()
  2244. if !ok {
  2245. return
  2246. }
  2247. // Run the revert, taking updates as if they came from scanning.
  2248. runner.Revert()
  2249. }
  2250. type TreeEntry struct {
  2251. Name string `json:"name"`
  2252. ModTime time.Time `json:"modTime"`
  2253. Size int64 `json:"size"`
  2254. Type protocol.FileInfoType `json:"type"`
  2255. Children []*TreeEntry `json:"children,omitempty"`
  2256. }
  2257. func findByName(slice []*TreeEntry, name string) *TreeEntry {
  2258. for _, child := range slice {
  2259. if child.Name == name {
  2260. return child
  2261. }
  2262. }
  2263. return nil
  2264. }
  2265. func (m *model) GlobalDirectoryTree(folder, prefix string, levels int, dirsOnly bool) ([]*TreeEntry, error) {
  2266. m.fmut.RLock()
  2267. files, ok := m.folderFiles[folder]
  2268. m.fmut.RUnlock()
  2269. if !ok {
  2270. return nil, ErrFolderMissing
  2271. }
  2272. root := &TreeEntry{
  2273. Children: make([]*TreeEntry, 0),
  2274. }
  2275. sep := string(filepath.Separator)
  2276. prefix = osutil.NativeFilename(prefix)
  2277. if prefix != "" && !strings.HasSuffix(prefix, sep) {
  2278. prefix = prefix + sep
  2279. }
  2280. snap, err := files.Snapshot()
  2281. if err != nil {
  2282. return nil, err
  2283. }
  2284. defer snap.Release()
  2285. snap.WithPrefixedGlobalTruncated(prefix, func(fi protocol.FileIntf) bool {
  2286. f := fi.(db.FileInfoTruncated)
  2287. // Don't include the prefix itself.
  2288. if f.IsInvalid() || f.IsDeleted() || strings.HasPrefix(prefix, f.Name) {
  2289. return true
  2290. }
  2291. f.Name = strings.Replace(f.Name, prefix, "", 1)
  2292. dir := filepath.Dir(f.Name)
  2293. base := filepath.Base(f.Name)
  2294. if levels > -1 && strings.Count(f.Name, sep) > levels {
  2295. return true
  2296. }
  2297. parent := root
  2298. if dir != "." {
  2299. for _, path := range strings.Split(dir, sep) {
  2300. child := findByName(parent.Children, path)
  2301. if child == nil {
  2302. err = fmt.Errorf("could not find child '%s' for path '%s' in parent '%s'", path, f.Name, parent.Name)
  2303. return false
  2304. }
  2305. parent = child
  2306. }
  2307. }
  2308. if dirsOnly && !f.IsDirectory() {
  2309. return true
  2310. }
  2311. parent.Children = append(parent.Children, &TreeEntry{
  2312. Name: base,
  2313. Type: f.Type,
  2314. ModTime: f.ModTime(),
  2315. Size: f.FileSize(),
  2316. })
  2317. return true
  2318. })
  2319. if err != nil {
  2320. return nil, err
  2321. }
  2322. return root.Children, nil
  2323. }
  2324. func (m *model) GetFolderVersions(folder string) (map[string][]versioner.FileVersion, error) {
  2325. m.fmut.RLock()
  2326. err := m.checkFolderRunningLocked(folder)
  2327. ver := m.folderVersioners[folder]
  2328. m.fmut.RUnlock()
  2329. if err != nil {
  2330. return nil, err
  2331. }
  2332. if ver == nil {
  2333. return nil, errNoVersioner
  2334. }
  2335. return ver.GetVersions()
  2336. }
  2337. func (m *model) RestoreFolderVersions(folder string, versions map[string]time.Time) (map[string]error, error) {
  2338. m.fmut.RLock()
  2339. err := m.checkFolderRunningLocked(folder)
  2340. fcfg := m.folderCfgs[folder]
  2341. ver := m.folderVersioners[folder]
  2342. m.fmut.RUnlock()
  2343. if err != nil {
  2344. return nil, err
  2345. }
  2346. if ver == nil {
  2347. return nil, errNoVersioner
  2348. }
  2349. restoreErrors := make(map[string]error)
  2350. for file, version := range versions {
  2351. if err := ver.Restore(file, version); err != nil {
  2352. restoreErrors[file] = err
  2353. }
  2354. }
  2355. // Trigger scan
  2356. if !fcfg.FSWatcherEnabled {
  2357. go func() { _ = m.ScanFolder(folder) }()
  2358. }
  2359. return restoreErrors, nil
  2360. }
  2361. func (m *model) Availability(folder string, file protocol.FileInfo, block protocol.BlockInfo) ([]Availability, error) {
  2362. // The slightly unusual locking sequence here is because we need to hold
  2363. // pmut for the duration (as the value returned from foldersFiles can
  2364. // get heavily modified on Close()), but also must acquire fmut before
  2365. // pmut. (The locks can be *released* in any order.)
  2366. m.fmut.RLock()
  2367. m.pmut.RLock()
  2368. defer m.pmut.RUnlock()
  2369. fs, ok := m.folderFiles[folder]
  2370. cfg := m.folderCfgs[folder]
  2371. m.fmut.RUnlock()
  2372. if !ok {
  2373. return nil, ErrFolderMissing
  2374. }
  2375. snap, err := fs.Snapshot()
  2376. if err != nil {
  2377. return nil, err
  2378. }
  2379. defer snap.Release()
  2380. return m.availabilityInSnapshotPRlocked(cfg, snap, file, block), nil
  2381. }
  2382. func (m *model) availabilityInSnapshot(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo, block protocol.BlockInfo) []Availability {
  2383. m.pmut.RLock()
  2384. defer m.pmut.RUnlock()
  2385. return m.availabilityInSnapshotPRlocked(cfg, snap, file, block)
  2386. }
  2387. func (m *model) availabilityInSnapshotPRlocked(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo, block protocol.BlockInfo) []Availability {
  2388. var availabilities []Availability
  2389. for _, device := range snap.Availability(file.Name) {
  2390. if _, ok := m.remotePausedFolders[device]; !ok {
  2391. continue
  2392. }
  2393. if _, ok := m.remotePausedFolders[device][cfg.ID]; ok {
  2394. continue
  2395. }
  2396. _, ok := m.conn[device]
  2397. if ok {
  2398. availabilities = append(availabilities, Availability{ID: device, FromTemporary: false})
  2399. }
  2400. }
  2401. for _, device := range cfg.Devices {
  2402. if m.deviceDownloads[device.DeviceID].Has(cfg.ID, file.Name, file.Version, int(block.Offset/int64(file.BlockSize()))) {
  2403. availabilities = append(availabilities, Availability{ID: device.DeviceID, FromTemporary: true})
  2404. }
  2405. }
  2406. return availabilities
  2407. }
  2408. // BringToFront bumps the given files priority in the job queue.
  2409. func (m *model) BringToFront(folder, file string) {
  2410. m.fmut.RLock()
  2411. runner, ok := m.folderRunners[folder]
  2412. m.fmut.RUnlock()
  2413. if ok {
  2414. runner.BringToFront(file)
  2415. }
  2416. }
  2417. func (m *model) ResetFolder(folder string) {
  2418. l.Infof("Cleaning data for folder %q", folder)
  2419. db.DropFolder(m.db, folder)
  2420. }
  2421. func (m *model) String() string {
  2422. return fmt.Sprintf("model@%p", m)
  2423. }
  2424. func (m *model) VerifyConfiguration(from, to config.Configuration) error {
  2425. return nil
  2426. }
  2427. func (m *model) CommitConfiguration(from, to config.Configuration) bool {
  2428. // TODO: This should not use reflect, and should take more care to try to handle stuff without restart.
  2429. // Delay processing config changes until after the initial setup
  2430. <-m.started
  2431. // Go through the folder configs and figure out if we need to restart or not.
  2432. // Tracks devices affected by any configuration change to resend ClusterConfig.
  2433. clusterConfigDevices := make(deviceIDSet, len(from.Devices)+len(to.Devices))
  2434. fromFolders := mapFolders(from.Folders)
  2435. toFolders := mapFolders(to.Folders)
  2436. for folderID, cfg := range toFolders {
  2437. if _, ok := fromFolders[folderID]; !ok {
  2438. // A folder was added.
  2439. if cfg.Paused {
  2440. l.Infoln("Paused folder", cfg.Description())
  2441. } else {
  2442. l.Infoln("Adding folder", cfg.Description())
  2443. if err := m.newFolder(cfg, to.Options.CacheIgnoredFiles); err != nil {
  2444. m.fatal(err)
  2445. return true
  2446. }
  2447. }
  2448. clusterConfigDevices.add(cfg.DeviceIDs())
  2449. }
  2450. }
  2451. removedFolders := make(map[string]struct{})
  2452. for folderID, fromCfg := range fromFolders {
  2453. toCfg, ok := toFolders[folderID]
  2454. if !ok {
  2455. // The folder was removed.
  2456. m.removeFolder(fromCfg)
  2457. clusterConfigDevices.add(fromCfg.DeviceIDs())
  2458. removedFolders[fromCfg.ID] = struct{}{}
  2459. continue
  2460. }
  2461. if fromCfg.Paused && toCfg.Paused {
  2462. continue
  2463. }
  2464. // This folder exists on both sides. Settings might have changed.
  2465. // Check if anything differs that requires a restart.
  2466. if !reflect.DeepEqual(fromCfg.RequiresRestartOnly(), toCfg.RequiresRestartOnly()) || from.Options.CacheIgnoredFiles != to.Options.CacheIgnoredFiles {
  2467. if err := m.restartFolder(fromCfg, toCfg, to.Options.CacheIgnoredFiles); err != nil {
  2468. m.fatal(err)
  2469. return true
  2470. }
  2471. clusterConfigDevices.add(fromCfg.DeviceIDs())
  2472. clusterConfigDevices.add(toCfg.DeviceIDs())
  2473. }
  2474. // Emit the folder pause/resume event
  2475. if fromCfg.Paused != toCfg.Paused {
  2476. eventType := events.FolderResumed
  2477. if toCfg.Paused {
  2478. eventType = events.FolderPaused
  2479. }
  2480. m.evLogger.Log(eventType, map[string]string{"id": toCfg.ID, "label": toCfg.Label})
  2481. }
  2482. }
  2483. // Removing a device. We actually don't need to do anything.
  2484. // Because folder config has changed (since the device lists do not match)
  2485. // Folders for that had device got "restarted", which involves killing
  2486. // connections to all devices that we were sharing the folder with.
  2487. // At some point model.Close() will get called for that device which will
  2488. // clean residue device state that is not part of any folder.
  2489. // Pausing a device, unpausing is handled by the connection service.
  2490. fromDevices := from.DeviceMap()
  2491. toDevices := to.DeviceMap()
  2492. closeDevices := make([]protocol.DeviceID, 0, len(to.Devices))
  2493. for deviceID, toCfg := range toDevices {
  2494. fromCfg, ok := fromDevices[deviceID]
  2495. if !ok {
  2496. sr := stats.NewDeviceStatisticsReference(m.db, deviceID)
  2497. m.fmut.Lock()
  2498. m.deviceStatRefs[deviceID] = sr
  2499. m.fmut.Unlock()
  2500. continue
  2501. }
  2502. delete(fromDevices, deviceID)
  2503. if fromCfg.Paused == toCfg.Paused {
  2504. continue
  2505. }
  2506. // Ignored folder was removed, reconnect to retrigger the prompt.
  2507. if !toCfg.Paused && len(fromCfg.IgnoredFolders) > len(toCfg.IgnoredFolders) {
  2508. closeDevices = append(closeDevices, deviceID)
  2509. }
  2510. if toCfg.Paused {
  2511. l.Infoln("Pausing", deviceID)
  2512. closeDevices = append(closeDevices, deviceID)
  2513. delete(clusterConfigDevices, deviceID)
  2514. m.evLogger.Log(events.DevicePaused, map[string]string{"device": deviceID.String()})
  2515. } else {
  2516. m.evLogger.Log(events.DeviceResumed, map[string]string{"device": deviceID.String()})
  2517. }
  2518. }
  2519. // Clean up after removed devices
  2520. removedDevices := make([]protocol.DeviceID, 0, len(fromDevices))
  2521. m.fmut.Lock()
  2522. for deviceID := range fromDevices {
  2523. delete(m.deviceStatRefs, deviceID)
  2524. removedDevices = append(removedDevices, deviceID)
  2525. delete(clusterConfigDevices, deviceID)
  2526. }
  2527. m.fmut.Unlock()
  2528. m.pmut.RLock()
  2529. for _, id := range closeDevices {
  2530. if conn, ok := m.conn[id]; ok {
  2531. go conn.Close(errDevicePaused)
  2532. }
  2533. }
  2534. for _, id := range removedDevices {
  2535. if conn, ok := m.conn[id]; ok {
  2536. go conn.Close(errDeviceRemoved)
  2537. }
  2538. }
  2539. m.pmut.RUnlock()
  2540. // Generating cluster-configs acquires fmut -> must happen outside of pmut.
  2541. m.sendClusterConfig(clusterConfigDevices.AsSlice())
  2542. ignoredDevices := observedDeviceSet(to.IgnoredDevices)
  2543. m.cleanPending(toDevices, toFolders, ignoredDevices, removedFolders)
  2544. m.globalRequestLimiter.setCapacity(1024 * to.Options.MaxConcurrentIncomingRequestKiB())
  2545. m.folderIOLimiter.setCapacity(to.Options.MaxFolderConcurrency())
  2546. // Some options don't require restart as those components handle it fine
  2547. // by themselves. Compare the options structs containing only the
  2548. // attributes that require restart and act apprioriately.
  2549. if !reflect.DeepEqual(from.Options.RequiresRestartOnly(), to.Options.RequiresRestartOnly()) {
  2550. l.Debugln(m, "requires restart, options differ")
  2551. return false
  2552. }
  2553. return true
  2554. }
  2555. func (m *model) cleanPending(existingDevices map[protocol.DeviceID]config.DeviceConfiguration, existingFolders map[string]config.FolderConfiguration, ignoredDevices deviceIDSet, removedFolders map[string]struct{}) {
  2556. var removedPendingFolders []map[string]string
  2557. pendingFolders, err := m.db.PendingFolders()
  2558. if err != nil {
  2559. l.Infof("Could not iterate through pending folder entries for cleanup: %v", err)
  2560. // Continue with pending devices below, loop is skipped.
  2561. }
  2562. for folderID, pf := range pendingFolders {
  2563. if _, ok := removedFolders[folderID]; ok {
  2564. // Forget pending folder device associations for recently removed
  2565. // folders as well, assuming the folder is no longer of interest
  2566. // at all (but might become pending again).
  2567. l.Debugf("Discarding pending removed folder %v from all devices", folderID)
  2568. m.db.RemovePendingFolder(folderID)
  2569. removedPendingFolders = append(removedPendingFolders, map[string]string{
  2570. "folderID": folderID,
  2571. })
  2572. continue
  2573. }
  2574. for deviceID := range pf.OfferedBy {
  2575. if dev, ok := existingDevices[deviceID]; !ok {
  2576. l.Debugf("Discarding pending folder %v from unknown device %v", folderID, deviceID)
  2577. goto removeFolderForDevice
  2578. } else if dev.IgnoredFolder(folderID) {
  2579. l.Debugf("Discarding now ignored pending folder %v for device %v", folderID, deviceID)
  2580. goto removeFolderForDevice
  2581. }
  2582. if folderCfg, ok := existingFolders[folderID]; ok {
  2583. if folderCfg.SharedWith(deviceID) {
  2584. l.Debugf("Discarding now shared pending folder %v for device %v", folderID, deviceID)
  2585. goto removeFolderForDevice
  2586. }
  2587. }
  2588. continue
  2589. removeFolderForDevice:
  2590. m.db.RemovePendingFolderForDevice(folderID, deviceID)
  2591. removedPendingFolders = append(removedPendingFolders, map[string]string{
  2592. "folderID": folderID,
  2593. "deviceID": deviceID.String(),
  2594. })
  2595. }
  2596. }
  2597. if len(removedPendingFolders) > 0 {
  2598. m.evLogger.Log(events.PendingFoldersChanged, map[string]interface{}{
  2599. "removed": removedPendingFolders,
  2600. })
  2601. }
  2602. var removedPendingDevices []map[string]string
  2603. pendingDevices, err := m.db.PendingDevices()
  2604. if err != nil {
  2605. l.Infof("Could not iterate through pending device entries for cleanup: %v", err)
  2606. return
  2607. }
  2608. for deviceID := range pendingDevices {
  2609. if _, ok := ignoredDevices[deviceID]; ok {
  2610. l.Debugf("Discarding now ignored pending device %v", deviceID)
  2611. goto removeDevice
  2612. }
  2613. if _, ok := existingDevices[deviceID]; ok {
  2614. l.Debugf("Discarding now added pending device %v", deviceID)
  2615. goto removeDevice
  2616. }
  2617. continue
  2618. removeDevice:
  2619. m.db.RemovePendingDevice(deviceID)
  2620. removedPendingDevices = append(removedPendingDevices, map[string]string{
  2621. "deviceID": deviceID.String(),
  2622. })
  2623. }
  2624. if len(removedPendingDevices) > 0 {
  2625. m.evLogger.Log(events.PendingDevicesChanged, map[string]interface{}{
  2626. "removed": removedPendingDevices,
  2627. })
  2628. }
  2629. }
  2630. // checkFolderRunningLocked returns nil if the folder is up and running and a
  2631. // descriptive error if not.
  2632. // Need to hold (read) lock on m.fmut when calling this.
  2633. func (m *model) checkFolderRunningLocked(folder string) error {
  2634. _, ok := m.folderRunners[folder]
  2635. if ok {
  2636. return nil
  2637. }
  2638. if cfg, ok := m.cfg.Folder(folder); !ok {
  2639. return ErrFolderMissing
  2640. } else if cfg.Paused {
  2641. return ErrFolderPaused
  2642. }
  2643. return ErrFolderNotRunning
  2644. }
  2645. // PendingDevices lists unknown devices that tried to connect.
  2646. func (m *model) PendingDevices() (map[protocol.DeviceID]db.ObservedDevice, error) {
  2647. return m.db.PendingDevices()
  2648. }
  2649. // PendingFolders lists folders that we don't yet share with the offering devices. It
  2650. // returns the entries grouped by folder and filters for a given device unless the
  2651. // argument is specified as EmptyDeviceID.
  2652. func (m *model) PendingFolders(device protocol.DeviceID) (map[string]db.PendingFolder, error) {
  2653. return m.db.PendingFoldersForDevice(device)
  2654. }
  2655. // mapFolders returns a map of folder ID to folder configuration for the given
  2656. // slice of folder configurations.
  2657. func mapFolders(folders []config.FolderConfiguration) map[string]config.FolderConfiguration {
  2658. m := make(map[string]config.FolderConfiguration, len(folders))
  2659. for _, cfg := range folders {
  2660. m[cfg.ID] = cfg
  2661. }
  2662. return m
  2663. }
  2664. // mapDevices returns a map of device ID to nothing for the given slice of
  2665. // device IDs.
  2666. func mapDevices(devices []protocol.DeviceID) map[protocol.DeviceID]struct{} {
  2667. m := make(map[protocol.DeviceID]struct{}, len(devices))
  2668. for _, dev := range devices {
  2669. m[dev] = struct{}{}
  2670. }
  2671. return m
  2672. }
  2673. func observedDeviceSet(devices []config.ObservedDevice) deviceIDSet {
  2674. res := make(deviceIDSet, len(devices))
  2675. for _, dev := range devices {
  2676. res[dev.ID] = struct{}{}
  2677. }
  2678. return res
  2679. }
  2680. func readOffsetIntoBuf(fs fs.Filesystem, file string, offset int64, buf []byte) (int, error) {
  2681. fd, err := fs.Open(file)
  2682. if err != nil {
  2683. l.Debugln("readOffsetIntoBuf.Open", file, err)
  2684. return 0, err
  2685. }
  2686. defer fd.Close()
  2687. n, err := fd.ReadAt(buf, offset)
  2688. if err != nil {
  2689. l.Debugln("readOffsetIntoBuf.ReadAt", file, err)
  2690. }
  2691. return n, err
  2692. }
  2693. // makeForgetUpdate takes an index update and constructs a download progress update
  2694. // causing to forget any progress for files which we've just been sent.
  2695. func makeForgetUpdate(files []protocol.FileInfo) []protocol.FileDownloadProgressUpdate {
  2696. updates := make([]protocol.FileDownloadProgressUpdate, 0, len(files))
  2697. for _, file := range files {
  2698. if file.IsSymlink() || file.IsDirectory() || file.IsDeleted() {
  2699. continue
  2700. }
  2701. updates = append(updates, protocol.FileDownloadProgressUpdate{
  2702. Name: file.Name,
  2703. Version: file.Version,
  2704. UpdateType: protocol.FileDownloadProgressUpdateTypeForget,
  2705. })
  2706. }
  2707. return updates
  2708. }
  2709. // folderDeviceSet is a set of (folder, deviceID) pairs
  2710. type folderDeviceSet map[string]map[protocol.DeviceID]struct{}
  2711. // set adds the (dev, folder) pair to the set
  2712. func (s folderDeviceSet) set(dev protocol.DeviceID, folder string) {
  2713. devs, ok := s[folder]
  2714. if !ok {
  2715. devs = make(map[protocol.DeviceID]struct{})
  2716. s[folder] = devs
  2717. }
  2718. devs[dev] = struct{}{}
  2719. }
  2720. // has returns true if the (dev, folder) pair is in the set
  2721. func (s folderDeviceSet) has(dev protocol.DeviceID, folder string) bool {
  2722. _, ok := s[folder][dev]
  2723. return ok
  2724. }
  2725. // hasDevice returns true if the device is set on any folder
  2726. func (s folderDeviceSet) hasDevice(dev protocol.DeviceID) bool {
  2727. for _, devices := range s {
  2728. if _, ok := devices[dev]; ok {
  2729. return true
  2730. }
  2731. }
  2732. return false
  2733. }
  2734. // syncMutexMap is a type safe wrapper for a sync.Map that holds mutexes
  2735. type syncMutexMap struct {
  2736. inner stdsync.Map
  2737. }
  2738. func (m *syncMutexMap) Get(key string) sync.Mutex {
  2739. v, _ := m.inner.LoadOrStore(key, sync.NewMutex())
  2740. return v.(sync.Mutex)
  2741. }
  2742. type deviceIDSet map[protocol.DeviceID]struct{}
  2743. func (s deviceIDSet) add(ids []protocol.DeviceID) {
  2744. for _, id := range ids {
  2745. if _, ok := s[id]; !ok {
  2746. s[id] = struct{}{}
  2747. }
  2748. }
  2749. }
  2750. func (s deviceIDSet) AsSlice() []protocol.DeviceID {
  2751. ids := make([]protocol.DeviceID, 0, len(s))
  2752. for id := range s {
  2753. ids = append(ids, id)
  2754. }
  2755. return ids
  2756. }
  2757. func encryptionTokenPath(cfg config.FolderConfiguration) string {
  2758. return filepath.Join(cfg.MarkerName, config.EncryptionTokenName)
  2759. }
  2760. type storedEncryptionToken struct {
  2761. FolderID string
  2762. Token []byte
  2763. }
  2764. func readEncryptionToken(cfg config.FolderConfiguration) ([]byte, error) {
  2765. fd, err := cfg.Filesystem().Open(encryptionTokenPath(cfg))
  2766. if err != nil {
  2767. return nil, err
  2768. }
  2769. defer fd.Close()
  2770. var stored storedEncryptionToken
  2771. if err := json.NewDecoder(fd).Decode(&stored); err != nil {
  2772. return nil, err
  2773. }
  2774. return stored.Token, nil
  2775. }
  2776. func writeEncryptionToken(token []byte, cfg config.FolderConfiguration) error {
  2777. tokenName := encryptionTokenPath(cfg)
  2778. fd, err := cfg.Filesystem().OpenFile(tokenName, fs.OptReadWrite|fs.OptCreate, 0666)
  2779. if err != nil {
  2780. return err
  2781. }
  2782. defer fd.Close()
  2783. return json.NewEncoder(fd).Encode(storedEncryptionToken{
  2784. FolderID: cfg.ID,
  2785. Token: token,
  2786. })
  2787. }
  2788. func newFolderConfiguration(w config.Wrapper, id, label string, fsType fs.FilesystemType, path string) config.FolderConfiguration {
  2789. fcfg := w.DefaultFolder()
  2790. fcfg.ID = id
  2791. fcfg.Label = label
  2792. fcfg.FilesystemType = fsType
  2793. fcfg.Path = path
  2794. return fcfg
  2795. }
  2796. type updatedPendingFolder struct {
  2797. FolderID string `json:"folderID"`
  2798. FolderLabel string `json:"folderLabel"`
  2799. DeviceID protocol.DeviceID `json:"deviceID"`
  2800. ReceiveEncrypted bool `json:"receiveEncrypted"`
  2801. }
  2802. // redactPathError checks if the error is actually a os.PathError, and if yes
  2803. // returns a redactedError with the path removed.
  2804. func redactPathError(err error) (error, bool) {
  2805. perr, ok := err.(*os.PathError)
  2806. if !ok {
  2807. return nil, false
  2808. }
  2809. return &redactedError{
  2810. error: err,
  2811. redacted: fmt.Errorf("%v: %w", perr.Op, perr.Err),
  2812. }, true
  2813. }
  2814. type redactedError struct {
  2815. error
  2816. redacted error
  2817. }