├── .clang-format ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── conanfile.py ├── docs ├── building.md ├── config.md ├── ct-ng-config ├── daemon-generic.png ├── design.dot ├── different-uis.gif ├── fltk-01-main.png ├── fltk-02-settings.png ├── fltk-03-add-new-device.png ├── fltk-04-add-pending-device.png ├── fltk-05-peer-device-edit.png ├── fltk-06-pending-folders.png ├── fltk-07-scheduled.png ├── fltk-08-remote-view.png ├── fltk-09-sync.png ├── fltk-10-local-file.png ├── fltk-11-removed-files.png ├── fltk-12-removed-files-hidden.png ├── fltk-generic.png ├── mingw ├── old_linux ├── ui-daemon.md ├── ui-fltk.md └── xp ├── mdbx-xp-patch.diff ├── misc ├── SyncSpiritIcon.icns ├── make-appimage.sh ├── post-install-nix.pl ├── post-install-win32.py ├── syncspirit-config.h.in ├── syncspirit-fltk.desktop ├── syncspirit-fltk.ico ├── syncspirit-fltk.png └── ubuntu14.04.toolchain ├── src ├── config │ ├── bep.h │ ├── db.h │ ├── dialer.h │ ├── fltk.h │ ├── fs.h │ ├── global_announce.h │ ├── local_announce.h │ ├── log.h │ ├── main.h │ ├── relay.h │ ├── upnp.h │ ├── utils.cpp │ └── utils.h ├── constants.cpp ├── constants.h ├── db │ ├── cursor.cpp │ ├── cursor.h │ ├── error_code.cpp │ ├── error_code.h │ ├── prefix.cpp │ ├── prefix.h │ ├── transaction.cpp │ ├── transaction.h │ ├── utils.cpp │ └── utils.h ├── fs │ ├── chunk_iterator.cpp │ ├── chunk_iterator.h │ ├── file.cpp │ ├── file.h │ ├── file_actor.cpp │ ├── file_actor.h │ ├── fs_supervisor.cpp │ ├── fs_supervisor.h │ ├── messages.h │ ├── new_chunk_iterator.cpp │ ├── new_chunk_iterator.h │ ├── scan_actor.cpp │ ├── scan_actor.h │ ├── scan_scheduler.cpp │ ├── scan_scheduler.h │ ├── scan_task.cpp │ ├── scan_task.h │ ├── utils.cpp │ └── utils.h ├── hasher │ ├── hasher_actor.cpp │ ├── hasher_actor.h │ ├── hasher_proxy_actor.cpp │ ├── hasher_proxy_actor.h │ ├── hasher_supervisor.cpp │ ├── hasher_supervisor.h │ └── messages.h ├── model │ ├── block_info.cpp │ ├── block_info.h │ ├── cluster.cpp │ ├── cluster.h │ ├── device.cpp │ ├── device.h │ ├── device_id.cpp │ ├── device_id.h │ ├── diff │ │ ├── advance │ │ │ ├── advance.cpp │ │ │ ├── advance.h │ │ │ ├── local_update.cpp │ │ │ ├── local_update.h │ │ │ ├── remote_copy.cpp │ │ │ ├── remote_copy.h │ │ │ ├── remote_win.cpp │ │ │ └── remote_win.h │ │ ├── apply_controller.cpp │ │ ├── apply_controller.h │ │ ├── block_diff.cpp │ │ ├── block_diff.h │ │ ├── cluster_diff.cpp │ │ ├── cluster_diff.h │ │ ├── cluster_visitor.cpp │ │ ├── cluster_visitor.h │ │ ├── contact │ │ │ ├── connect_request.cpp │ │ │ ├── connect_request.h │ │ │ ├── dial_request.cpp │ │ │ ├── dial_request.h │ │ │ ├── ignored_connected.cpp │ │ │ ├── ignored_connected.h │ │ │ ├── peer_state.cpp │ │ │ ├── peer_state.h │ │ │ ├── relay_connect_request.cpp │ │ │ ├── relay_connect_request.h │ │ │ ├── unknown_connected.cpp │ │ │ ├── unknown_connected.h │ │ │ ├── update_contact.cpp │ │ │ └── update_contact.h │ │ ├── diffs_fwd.h │ │ ├── load │ │ │ ├── blocks.cpp │ │ │ ├── blocks.h │ │ │ ├── common.h │ │ │ ├── devices.cpp │ │ │ ├── devices.h │ │ │ ├── file_infos.cpp │ │ │ ├── file_infos.h │ │ │ ├── folder_infos.cpp │ │ │ ├── folder_infos.h │ │ │ ├── folders.cpp │ │ │ ├── folders.h │ │ │ ├── ignored_devices.cpp │ │ │ ├── ignored_devices.h │ │ │ ├── ignored_folders.cpp │ │ │ ├── ignored_folders.h │ │ │ ├── load_cluster.cpp │ │ │ ├── load_cluster.h │ │ │ ├── pending_devices.cpp │ │ │ ├── pending_devices.h │ │ │ ├── pending_folders.cpp │ │ │ ├── pending_folders.h │ │ │ └── some_devices.hpp │ │ ├── local │ │ │ ├── blocks_availability.cpp │ │ │ ├── blocks_availability.h │ │ │ ├── custom.cpp │ │ │ ├── custom.h │ │ │ ├── file_availability.cpp │ │ │ ├── file_availability.h │ │ │ ├── io_failure.cpp │ │ │ ├── io_failure.h │ │ │ ├── scan_finish.cpp │ │ │ ├── scan_finish.h │ │ │ ├── scan_request.cpp │ │ │ ├── scan_request.h │ │ │ ├── scan_start.cpp │ │ │ ├── scan_start.h │ │ │ ├── synchronization_finish.cpp │ │ │ ├── synchronization_finish.h │ │ │ ├── synchronization_start.cpp │ │ │ └── synchronization_start.h │ │ ├── modify │ │ │ ├── add_blocks.cpp │ │ │ ├── add_blocks.h │ │ │ ├── add_ignored_device.cpp │ │ │ ├── add_ignored_device.h │ │ │ ├── add_pending_device.cpp │ │ │ ├── add_pending_device.h │ │ │ ├── add_pending_folders.cpp │ │ │ ├── add_pending_folders.h │ │ │ ├── add_remote_folder_infos.cpp │ │ │ ├── add_remote_folder_infos.h │ │ │ ├── append_block.cpp │ │ │ ├── append_block.h │ │ │ ├── block_ack.cpp │ │ │ ├── block_ack.h │ │ │ ├── block_rej.cpp │ │ │ ├── block_rej.h │ │ │ ├── block_transaction.cpp │ │ │ ├── block_transaction.h │ │ │ ├── clone_block.cpp │ │ │ ├── clone_block.h │ │ │ ├── finish_file.cpp │ │ │ ├── finish_file.h │ │ │ ├── generic_remove.cpp │ │ │ ├── generic_remove.h │ │ │ ├── lock_file.cpp │ │ │ ├── lock_file.h │ │ │ ├── mark_reachable.cpp │ │ │ ├── mark_reachable.h │ │ │ ├── remove_blocks.cpp │ │ │ ├── remove_blocks.h │ │ │ ├── remove_files.cpp │ │ │ ├── remove_files.h │ │ │ ├── remove_folder.cpp │ │ │ ├── remove_folder.h │ │ │ ├── remove_folder_infos.cpp │ │ │ ├── remove_folder_infos.h │ │ │ ├── remove_ignored_device.cpp │ │ │ ├── remove_ignored_device.h │ │ │ ├── remove_peer.cpp │ │ │ ├── remove_peer.h │ │ │ ├── remove_pending_device.cpp │ │ │ ├── remove_pending_device.h │ │ │ ├── remove_pending_folders.cpp │ │ │ ├── remove_pending_folders.h │ │ │ ├── reset_folder_infos.cpp │ │ │ ├── reset_folder_infos.h │ │ │ ├── share_folder.cpp │ │ │ ├── share_folder.h │ │ │ ├── suspend_folder.cpp │ │ │ ├── suspend_folder.h │ │ │ ├── unshare_folder.cpp │ │ │ ├── unshare_folder.h │ │ │ ├── update_peer.cpp │ │ │ ├── update_peer.h │ │ │ ├── upsert_folder.cpp │ │ │ ├── upsert_folder.h │ │ │ ├── upsert_folder_info.cpp │ │ │ └── upsert_folder_info.h │ │ └── peer │ │ │ ├── cluster_update.cpp │ │ │ ├── cluster_update.h │ │ │ ├── update_folder.cpp │ │ │ └── update_folder.h │ ├── file_info.cpp │ ├── file_info.h │ ├── folder.cpp │ ├── folder.h │ ├── folder_data.cpp │ ├── folder_data.h │ ├── folder_info.cpp │ ├── folder_info.h │ ├── ignored_device.cpp │ ├── ignored_device.h │ ├── ignored_folder.cpp │ ├── ignored_folder.h │ ├── messages.h │ ├── misc │ │ ├── arc.hpp │ │ ├── augmentation.hpp │ │ ├── block_iterator.cpp │ │ ├── block_iterator.h │ │ ├── error_code.cpp │ │ ├── error_code.h │ │ ├── file_block.cpp │ │ ├── file_block.h │ │ ├── file_iterator.cpp │ │ ├── file_iterator.h │ │ ├── lru_cache.hpp │ │ ├── map.hpp │ │ ├── orphaned_blocks.cpp │ │ ├── orphaned_blocks.h │ │ ├── resolver.cpp │ │ ├── resolver.h │ │ ├── sequencer.cpp │ │ ├── sequencer.h │ │ ├── string_map.hpp │ │ ├── updates_streamer.cpp │ │ ├── updates_streamer.h │ │ ├── upnp.h │ │ ├── uuid.cpp │ │ └── uuid.h │ ├── pending_device.cpp │ ├── pending_device.h │ ├── pending_folder.cpp │ ├── pending_folder.h │ ├── remote_folder_info.cpp │ ├── remote_folder_info.h │ ├── some_device.cpp │ ├── some_device.h │ ├── version.cpp │ └── version.h ├── net │ ├── acceptor_actor.cpp │ ├── acceptor_actor.h │ ├── cluster_supervisor.cpp │ ├── cluster_supervisor.h │ ├── controller_actor.cpp │ ├── controller_actor.h │ ├── db_actor.cpp │ ├── db_actor.h │ ├── dialer_actor.cpp │ ├── dialer_actor.h │ ├── global_discovery_actor.cpp │ ├── global_discovery_actor.h │ ├── http_actor.cpp │ ├── http_actor.h │ ├── initiator_actor.cpp │ ├── initiator_actor.h │ ├── local_discovery_actor.cpp │ ├── local_discovery_actor.h │ ├── messages.cpp │ ├── messages.h │ ├── names.cpp │ ├── names.h │ ├── net_supervisor.cpp │ ├── net_supervisor.h │ ├── peer_actor.cpp │ ├── peer_actor.h │ ├── peer_supervisor.cpp │ ├── peer_supervisor.h │ ├── relay_actor.cpp │ ├── relay_actor.h │ ├── resolver_actor.cpp │ ├── resolver_actor.h │ ├── sink_actor.cpp │ ├── sink_actor.h │ ├── ssdp_actor.cpp │ ├── ssdp_actor.h │ ├── upnp_actor.cpp │ └── upnp_actor.h ├── proto │ ├── bep_support.cpp │ ├── bep_support.h │ ├── discovery_support.cpp │ ├── discovery_support.h │ ├── luhn32.cpp │ ├── luhn32.h │ ├── relay_support.cpp │ ├── relay_support.h │ ├── upnp_support.cpp │ └── upnp_support.h ├── protobuf │ ├── bep.proto │ └── structs.proto ├── transport │ ├── base.h │ ├── http.cpp │ ├── http.h │ ├── impl.hpp │ ├── stream.cpp │ └── stream.h ├── ui-daemon │ ├── CMakeLists.txt │ ├── command.cpp │ ├── command.h │ ├── command │ │ ├── add_folder.cpp │ │ ├── add_folder.h │ │ ├── add_peer.cpp │ │ ├── add_peer.h │ │ ├── inactivate.cpp │ │ ├── inactivate.h │ │ ├── pair_iterator.cpp │ │ ├── pair_iterator.h │ │ ├── share_folder.cpp │ │ └── share_folder.h │ ├── error_code.cpp │ ├── error_code.h │ ├── governor_actor.cpp │ ├── governor_actor.h │ └── main.cpp ├── ui-fltk │ ├── CMakeLists.txt │ ├── app-manifest.xml │ ├── app.h │ ├── app.rc │ ├── app_supervisor.cpp │ ├── app_supervisor.h │ ├── augmentation.cpp │ ├── augmentation.h │ ├── config │ │ ├── category.cpp │ │ ├── category.h │ │ ├── control.cpp │ │ ├── control.h │ │ ├── properties.cpp │ │ ├── properties.h │ │ ├── property.cpp │ │ ├── property.h │ │ ├── table.cpp │ │ └── table.h │ ├── content.cpp │ ├── content.h │ ├── content │ │ ├── folder_table.cpp │ │ ├── folder_table.h │ │ ├── remote_file_table.cpp │ │ └── remote_file_table.h │ ├── entry_stats.h │ ├── log_colors.cpp │ ├── log_colors.h │ ├── log_panel.cpp │ ├── log_panel.h │ ├── log_sink.cpp │ ├── log_sink.h │ ├── log_table.cpp │ ├── log_table.h │ ├── log_utils.cpp │ ├── log_utils.h │ ├── main.cpp │ ├── main_window.cpp │ ├── main_window.h │ ├── qr_button.cpp │ ├── qr_button.h │ ├── static_table.cpp │ ├── static_table.h │ ├── symbols.cpp │ ├── symbols.h │ ├── table_widget │ │ ├── checkbox.cpp │ │ ├── checkbox.h │ │ ├── choice.cpp │ │ ├── choice.h │ │ ├── input.cpp │ │ ├── input.h │ │ ├── int_input.cpp │ │ ├── int_input.h │ │ ├── label.cpp │ │ ├── label.h │ │ ├── path.cpp │ │ └── path.h │ ├── toolbar.cpp │ ├── toolbar.h │ ├── tree_item.cpp │ ├── tree_item.h │ ├── tree_item │ │ ├── devices.cpp │ │ ├── devices.h │ │ ├── entry.cpp │ │ ├── entry.h │ │ ├── file_entry.cpp │ │ ├── file_entry.h │ │ ├── folder.cpp │ │ ├── folder.h │ │ ├── folders.cpp │ │ ├── folders.h │ │ ├── ignored_device.cpp │ │ ├── ignored_device.h │ │ ├── ignored_devices.cpp │ │ ├── ignored_devices.h │ │ ├── local_entry.cpp │ │ ├── local_entry.h │ │ ├── peer_device.cpp │ │ ├── peer_device.h │ │ ├── peer_entry.cpp │ │ ├── peer_entry.h │ │ ├── peer_folder.cpp │ │ ├── peer_folder.h │ │ ├── peer_folders.cpp │ │ ├── peer_folders.h │ │ ├── pending_device.cpp │ │ ├── pending_device.h │ │ ├── pending_devices.cpp │ │ ├── pending_devices.h │ │ ├── pending_folder.cpp │ │ ├── pending_folder.h │ │ ├── pending_folders.cpp │ │ ├── pending_folders.h │ │ ├── self_device.cpp │ │ ├── self_device.h │ │ ├── settings.cpp │ │ └── settings.h │ ├── tree_view.cpp │ ├── tree_view.h │ ├── utils.cpp │ └── utils.hpp └── utils │ ├── base32.cpp │ ├── base32.h │ ├── beast_support.cpp │ ├── beast_support.h │ ├── dns.cpp │ ├── dns.h │ ├── error_code.cpp │ ├── error_code.h │ ├── format.hpp │ ├── io.h │ ├── location.cpp │ ├── location.h │ ├── log-setup.cpp │ ├── log-setup.h │ ├── log.cpp │ ├── log.h │ ├── network_interface.cpp │ ├── network_interface.h │ ├── platform.cpp │ ├── platform.h │ ├── string_comparator.hpp │ ├── time.cpp │ ├── time.h │ ├── tls.cpp │ ├── tls.h │ ├── uri.cpp │ └── uri.h ├── syncspirit.toml ├── tests ├── 009-uri.cpp ├── 010-upnp-support.cpp ├── 011-tls-util.cpp ├── 012-base32.cpp ├── 013-global-discovery.cpp ├── 014-configuration.cpp ├── 015-logger.cpp ├── 016-relay-support.cpp ├── 017-fs-utils.cpp ├── 018-dns.cpp ├── 020-generic-map.cpp ├── 021-orphaned-blocks.cpp ├── 022-version.cpp ├── 025-device_id.cpp ├── 026-file_info.cpp ├── 029-diff-generic.cpp ├── 030-diff-load-cluster.cpp ├── 031-diff-cluster_update.cpp ├── 032-diff-modify.cpp ├── 033-diffs-trivial.cpp ├── 034-diff-local_update.cpp ├── 036-diff-blocks.cpp ├── 037-diff-update_folder.cpp ├── 038-diff-clone_finish-file.cpp ├── 039-diff-remove-peer.cpp ├── 040-diff-contacts.cpp ├── 041-diff-remove-folder.cpp ├── 045-diff-advance.cpp ├── 050-file_iterator.cpp ├── 051-block_iterator.cpp ├── 052-file_info.cpp ├── 053-scan_task.cpp ├── 054-updates_streamer.cpp ├── 055-resolver.cpp ├── 060-bep.cpp ├── 070-db.cpp ├── 071-fs_actor.cpp ├── 072-global_discovery.cpp ├── 073-dialer.cpp ├── 074-hasher.cpp ├── 075-controller.cpp ├── 077-initiator.cpp ├── 078-relay.cpp ├── 079-peer.cpp ├── 080-resolver.cpp ├── 085-scan-scheduler.cpp ├── 086-scan_actor.cpp ├── CMakeLists.txt ├── access.h ├── data │ ├── 49652gatedesc.xml │ ├── cert.der │ ├── external-ip.xml │ ├── mykey.der │ ├── port-mapping-success.xml │ ├── port-unmapping-failure.xml │ ├── sample-cert.pem │ ├── sample-key.pem │ └── soap-failure.xml ├── diff-builder.cpp ├── diff-builder.h ├── fixture.cpp ├── fixture.h ├── test-db.cpp ├── test-db.h ├── test-utils.cpp ├── test-utils.h ├── test_supervisor.cpp ├── test_supervisor.h └── win32-resource.rc └── todo.txt /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/.gitmodules -------------------------------------------------------------------------------- /conanfile.py: -------------------------------------------------------------------------------- 1 | from conan import ConanFile 2 | from conan.tools.cmake import CMakeToolchain, CMake, CMakeDeps, cmake_layout 3 | 4 | class SyncspiritRecipe(ConanFile): 5 | settings = "os", "compiler", "build_type", "arch" 6 | options = { 7 | "shared": [True, False], 8 | } 9 | 10 | def requirements(self): 11 | # self.requires("c-ares/1.28.1") 12 | self.requires("fltk/1.3.9") 13 | self.requires("libqrencode/4.1.1") 14 | self.requires("lz4/1.9.4") 15 | self.requires("nlohmann_json/3.11.2") 16 | self.requires("openssl/3.3.2") 17 | self.requires("protobuf/3.21.12") 18 | self.requires("pugixml/1.13") 19 | self.requires("rotor/0.32") 20 | self.requires("spdlog/1.14.1") 21 | self.requires("tomlplusplus/3.3.0") 22 | self.requires("zlib/1.2.13") 23 | self.requires("catch2/3.3.1") 24 | self.requires("boost/1.86.0", headers=True, libs=True, transitive_libs=True, force=True) 25 | 26 | def build_requirements(self): 27 | self.tool_requires("protobuf/3.21.12") 28 | self.tool_requires("cmake/3.31.5") 29 | 30 | def generate(self): 31 | tc = CMakeToolchain(self) 32 | tc.variables["BUILD_SHARED_LIBS"] = self.options.shared 33 | tc.generate() 34 | tc = CMakeDeps(self) 35 | tc.generate() 36 | -------------------------------------------------------------------------------- /docs/daemon-generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/daemon-generic.png -------------------------------------------------------------------------------- /docs/design.dot: -------------------------------------------------------------------------------- 1 | // dot -Tpng -o /tmp/h.png < docs/hierarchy.dot 2 | digraph D { 3 | "net::sup" -> "http::sup"; 4 | "net::sup" -> "registry"; 5 | "http::sup" -> "http::actor"; 6 | "http::sup" -> "https::actor"; 7 | "http::sup" -> "registry" [style = "dotted"]; 8 | "net::sup" -> "local_announcer::actor"; 9 | "net::sup" -> "global_announcer::sup"; 10 | "net::sup" -> "acceptor::actor"; 11 | "acceptor::actor" -> "registry" [style = "dotted"]; 12 | "global_announcer::sup" -> "ssdp::actor"; 13 | "global_announcer::sup" -> "registry" [style = "dotted"]; 14 | "global_announcer::sup" -> "http::sup" [style = "dotted"]; 15 | "global_announcer::sup" -> "acceptor::actor" [style = "dotted"]; 16 | "local_announcer::actor" -> "registry" [style = "dotted"]; 17 | "local_announcer::actor" -> "acceptor::actor" [style = "dotted"]; 18 | } 19 | -------------------------------------------------------------------------------- /docs/different-uis.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/different-uis.gif -------------------------------------------------------------------------------- /docs/fltk-01-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-01-main.png -------------------------------------------------------------------------------- /docs/fltk-02-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-02-settings.png -------------------------------------------------------------------------------- /docs/fltk-03-add-new-device.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-03-add-new-device.png -------------------------------------------------------------------------------- /docs/fltk-04-add-pending-device.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-04-add-pending-device.png -------------------------------------------------------------------------------- /docs/fltk-05-peer-device-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-05-peer-device-edit.png -------------------------------------------------------------------------------- /docs/fltk-06-pending-folders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-06-pending-folders.png -------------------------------------------------------------------------------- /docs/fltk-07-scheduled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-07-scheduled.png -------------------------------------------------------------------------------- /docs/fltk-08-remote-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-08-remote-view.png -------------------------------------------------------------------------------- /docs/fltk-09-sync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-09-sync.png -------------------------------------------------------------------------------- /docs/fltk-10-local-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-10-local-file.png -------------------------------------------------------------------------------- /docs/fltk-11-removed-files.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-11-removed-files.png -------------------------------------------------------------------------------- /docs/fltk-12-removed-files-hidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-12-removed-files-hidden.png -------------------------------------------------------------------------------- /docs/fltk-generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/docs/fltk-generic.png -------------------------------------------------------------------------------- /docs/mingw: -------------------------------------------------------------------------------- 1 | [settings] 2 | os=Windows 3 | arch=x86_64 4 | compiler=gcc 5 | build_type=Release 6 | compiler.cppstd=gnu17 7 | compiler.libcxx=libstdc++11 8 | compiler.version=12 9 | [buildenv] 10 | CC=x86_64-w64-mingw32-gcc 11 | CXX=x86_64-w64-mingw32-g++ 12 | LD=ix86_64-w64-mingw32-ld 13 | RC=x86_64-w64-mingw32-windres 14 | 15 | [options] 16 | boost/*:without_fiber=True 17 | boost/*:without_graph=True 18 | boost/*:without_log=True 19 | boost/*:without_stacktrace=True 20 | boost/*:without_test=True 21 | boost/*:without_wave=True 22 | 23 | -------------------------------------------------------------------------------- /docs/old_linux: -------------------------------------------------------------------------------- 1 | [settings] 2 | os=Linux 3 | arch=x86_64 4 | compiler=gcc 5 | build_type=Release 6 | compiler.cppstd=gnu17 7 | compiler.libcxx=libstdc++11 8 | compiler.version=8 9 | 10 | [buildenv] 11 | CC=x86_64-syncspirit-linux-gnu-gcc 12 | CXX=x86_64-syncspirit-linux-gnu-g++ 13 | LD=x86_64-syncspirit-linux-gnu-ld 14 | 15 | [options] 16 | boost/*:without_fiber=True 17 | boost/*:without_graph=True 18 | boost/*:without_log=True 19 | boost/*:without_stacktrace=True 20 | boost/*:without_test=True 21 | boost/*:without_wave=True 22 | 23 | -------------------------------------------------------------------------------- /docs/xp: -------------------------------------------------------------------------------- 1 | [settings] 2 | os=Windows 3 | arch=x86 4 | compiler=gcc 5 | build_type=Release 6 | compiler.cppstd=gnu17 7 | compiler.libcxx=libstdc++11 8 | compiler.version=11 9 | [buildenv] 10 | CC=i686-w64-mingw32.shared-gcc 11 | CXX=i686-w64-mingw32.shared-g++ 12 | LD=i686-w64-mingw32.shared-ld 13 | RC=i686-w64-mingw32.shared-windres 14 | 15 | [options] 16 | boost/*:without_fiber=True 17 | boost/*:without_graph=True 18 | boost/*:without_log=True 19 | boost/*:without_stacktrace=True 20 | boost/*:without_test=True 21 | boost/*:without_wave=True 22 | 23 | [conf] 24 | tools.build:cflags=["-DHAVE_NOTIFYIPINTERFACECHANGE=False", "-DHAVE_CONVERTINTERFACELUIDTONAMEA=False", "-DHAVE_CONVERTINTERFACEINDEXTOLUID=false"] 25 | #tools.build:cflags=["-D_WIN32_WINNT=0x0501"] 26 | #tools.build:cxxflags=["-D_WIN32_WINNT=0x0501"] 27 | 28 | -------------------------------------------------------------------------------- /mdbx-xp-patch.diff: -------------------------------------------------------------------------------- 1 | diff --git a/src/osal.c b/src/osal.c 2 | index cdef5712..b54e91ce 100644 3 | --- a/src/osal.c 4 | +++ b/src/osal.c 5 | @@ -1005,7 +1005,7 @@ MDBX_INTERNAL void osal_ioring_reset(osal_ioring_t *ior) { 6 | for (ior_item_t *item = ior->pool; item <= ior->last;) { 7 | if (!HasOverlappedIoCompleted(&item->ov)) { 8 | assert(ior->overlapped_fd); 9 | - CancelIoEx(ior->overlapped_fd, &item->ov); 10 | + CancelIo(ior->overlapped_fd); 11 | } 12 | if (item->ov.hEvent && item->ov.hEvent != ior) 13 | ior_put_event(ior, item->ov.hEvent); 14 | -------------------------------------------------------------------------------- /misc/SyncSpiritIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/misc/SyncSpiritIcon.icns -------------------------------------------------------------------------------- /misc/make-appimage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sh 2 | 3 | if [ -z "$1" ]; then 4 | echo "Usage: make-appimage.sh path/to/app/application" 5 | exit 1 6 | fi 7 | 8 | APP_PATH=$1 9 | APP=$(basename $APP_PATH) 10 | APP_DIR="AppDir-$APP/usr/bin" 11 | WORK_DIR="AppDir/$APP_DIR" 12 | echo $WORK_DIR 13 | 14 | rm -rf "$WORK_DIR" 15 | mkdir -p "$WORK_DIR" 16 | strip --strip-all $APP_PATH 17 | cp $APP_PATH "$WORK_DIR" 18 | 19 | cd "AppDir" 20 | if [ ! -e "./linuxdeploy-x86_64.AppImage" ]; then 21 | echo "going to download linux-deploy..." 22 | wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage 23 | chmod +x linuxdeploy-x86_64.AppImage 24 | fi 25 | 26 | ./linuxdeploy-x86_64.AppImage -v 2 --appdir "$APP_DIR" --output appimage -e "$APP_DIR/$APP" --icon-file "../../misc/$APP.png" -d "../../misc/$APP.desktop" 27 | cd .. 28 | 29 | -------------------------------------------------------------------------------- /misc/syncspirit-config.h.in: -------------------------------------------------------------------------------- 1 | #cmakedefine SYNCSPIRIT_VERSION "@SYNCSPIRIT_VERSION@" 2 | 3 | -------------------------------------------------------------------------------- /misc/syncspirit-fltk.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=syncspirit-fltk 3 | Exec=syncspirit-fltk 4 | Icon=syncspirit-fltk 5 | Type=Application 6 | Categories=Utility; 7 | -------------------------------------------------------------------------------- /misc/syncspirit-fltk.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/misc/syncspirit-fltk.ico -------------------------------------------------------------------------------- /misc/syncspirit-fltk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/misc/syncspirit-fltk.png -------------------------------------------------------------------------------- /misc/ubuntu14.04.toolchain: -------------------------------------------------------------------------------- 1 | set(TOOLCHAIN_HOME "/home/b/x-tools/x86_64-ubuntu14.04-linux-gnu") 2 | set(CMAKE_C_COMPILER ${TOOLCHAIN_HOME}/bin/x86_64-ubuntu14.04-linux-gnu-gcc) 3 | set(CMAKE_CXX_COMPILER ${TOOLCHAIN_HOME}/bin/x86_64-ubuntu14.04-linux-gnu-g++) 4 | set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") 5 | set(CMAKE_FIND_ROOT_PATH 6 | ${TOOLCHAIN_HOME}/x86_64-ubuntu14.04-linux-gnu/sysroot/ 7 | /home/b/development/cpp/syncspirit-cross/sysroot 8 | ) 9 | -------------------------------------------------------------------------------- /src/config/bep.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace syncspirit::config { 9 | 10 | struct bep_config_t { 11 | std::uint32_t rx_buff_size; 12 | std::uint32_t tx_buff_limit; 13 | std::uint32_t connect_timeout; 14 | std::uint32_t request_timeout; 15 | std::uint32_t tx_timeout; 16 | std::uint32_t rx_timeout; 17 | std::uint32_t blocks_max_requested; 18 | std::uint32_t blocks_simultaneous_write; 19 | std::uint32_t advances_per_iteration; 20 | }; 21 | 22 | } // namespace syncspirit::config 23 | -------------------------------------------------------------------------------- /src/config/db.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #pragma once 7 | #include 8 | 9 | namespace syncspirit::config { 10 | 11 | struct db_config_t { 12 | std::int64_t upper_limit; 13 | std::uint32_t uncommitted_threshold; 14 | std::uint32_t max_blocks_per_diff; 15 | std::uint32_t max_files_per_diff; 16 | }; 17 | 18 | } // namespace syncspirit::config 19 | -------------------------------------------------------------------------------- /src/config/dialer.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace syncspirit::config { 9 | 10 | struct dialer_config_t { 11 | bool enabled; 12 | std::uint32_t redial_timeout; 13 | std::uint32_t skip_discovers; 14 | }; 15 | 16 | } // namespace syncspirit::config 17 | -------------------------------------------------------------------------------- /src/config/fltk.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | #include 6 | 7 | namespace syncspirit::config { 8 | 9 | struct fltk_config_t { 10 | spdlog::level::level_enum level; 11 | bool display_deleted; 12 | bool display_colorized; 13 | int main_window_width; 14 | int main_window_height; 15 | double left_panel_share; 16 | double bottom_panel_share; 17 | std::uint32_t log_records_buffer; 18 | }; 19 | 20 | } // namespace syncspirit::config 21 | -------------------------------------------------------------------------------- /src/config/fs.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | #include 6 | 7 | namespace syncspirit::config { 8 | 9 | struct fs_config_t { 10 | std::uint32_t temporally_timeout; 11 | std::uint32_t mru_size; 12 | std::int64_t bytes_scan_iteration_limit; 13 | std::int64_t files_scan_iteration_limit; 14 | }; 15 | 16 | } // namespace syncspirit::config 17 | -------------------------------------------------------------------------------- /src/config/global_announce.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | #include 6 | #include 7 | #include "utils/uri.h" 8 | 9 | namespace syncspirit::config { 10 | 11 | struct global_announce_config_t { 12 | bool enabled; 13 | bool debug; 14 | utils::uri_ptr_t announce_url; 15 | std::string device_id; 16 | std::string cert_file; 17 | std::string key_file; 18 | std::uint32_t rx_buff_size; 19 | std::uint32_t timeout; 20 | std::uint32_t reannounce_after = 600; 21 | }; 22 | 23 | } // namespace syncspirit::config 24 | -------------------------------------------------------------------------------- /src/config/local_announce.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | #include 6 | 7 | namespace syncspirit::config { 8 | 9 | struct local_announce_config_t { 10 | bool enabled; 11 | std::uint16_t port; 12 | std::uint32_t frequency; 13 | }; 14 | 15 | } // namespace syncspirit::config 16 | -------------------------------------------------------------------------------- /src/config/log.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | #include 6 | #include 7 | 8 | namespace syncspirit::config { 9 | 10 | struct log_config_t { 11 | using sinks_t = std::vector; 12 | 13 | std::string name; 14 | spdlog::level::level_enum level; 15 | sinks_t sinks; 16 | }; 17 | 18 | using log_configs_t = std::vector; 19 | 20 | } // namespace syncspirit::config 21 | -------------------------------------------------------------------------------- /src/config/main.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | #include 6 | #include "bep.h" 7 | #include "db.h" 8 | #include "dialer.h" 9 | #include "fs.h" 10 | #include "global_announce.h" 11 | #include "local_announce.h" 12 | #include "log.h" 13 | #include "relay.h" 14 | #include "upnp.h" 15 | #include "fltk.h" 16 | #include 17 | 18 | namespace syncspirit::config { 19 | 20 | namespace bfs = std::filesystem; 21 | 22 | struct main_t { 23 | bfs::path config_path; 24 | bfs::path default_location; 25 | 26 | local_announce_config_t local_announce_config; 27 | log_configs_t log_configs; 28 | upnp_config_t upnp_config; 29 | global_announce_config_t global_announce_config; 30 | bep_config_t bep_config; 31 | dialer_config_t dialer_config; 32 | fs_config_t fs_config; 33 | db_config_t db_config; 34 | relay_config_t relay_config; 35 | fltk_config_t fltk_config; 36 | 37 | std::uint32_t timeout; 38 | std::string device_name; 39 | std::uint32_t hasher_threads; 40 | }; 41 | 42 | } // namespace syncspirit::config 43 | -------------------------------------------------------------------------------- /src/config/relay.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "utils/uri.h" 7 | 8 | namespace syncspirit::config { 9 | 10 | struct relay_config_t { 11 | bool enabled; 12 | bool debug; 13 | utils::uri_ptr_t discovery_url; 14 | std::uint32_t rx_buff_size; 15 | }; 16 | 17 | } // namespace syncspirit::config 18 | -------------------------------------------------------------------------------- /src/config/upnp.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | #include 6 | 7 | namespace syncspirit::config { 8 | 9 | struct upnp_config_t { 10 | bool enabled; 11 | bool debug; 12 | std::uint32_t max_wait; 13 | std::uint16_t external_port; 14 | std::uint32_t rx_buff_size; 15 | }; 16 | 17 | } // namespace syncspirit::config 18 | -------------------------------------------------------------------------------- /src/config/utils.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | #include 6 | #include 7 | #include "main.h" 8 | #include "syncspirit-export.h" 9 | 10 | namespace syncspirit::config { 11 | 12 | namespace outcome = boost::outcome_v2; 13 | namespace bfs = std::filesystem; 14 | 15 | // comparators 16 | 17 | using config_result_t = outcome::outcome; 18 | 19 | SYNCSPIRIT_API config_result_t get_config(std::istream &config, const bfs::path &config_path); 20 | 21 | SYNCSPIRIT_API outcome::result generate_config(const bfs::path &config_path); 22 | 23 | SYNCSPIRIT_API outcome::result serialize(const main_t cfg, std::ostream &out) noexcept; 24 | 25 | } // namespace syncspirit::config 26 | -------------------------------------------------------------------------------- /src/constants.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "constants.h" 5 | #include "syncspirit-config.h" 6 | 7 | namespace syncspirit::constants { 8 | 9 | const char *client_name = "syncspirit"; 10 | const char *issuer_name = "syncthing"; 11 | const char *protocol_name = "bep/1.0"; 12 | const char *relay_protocol_name = "bep-relay"; 13 | const char *client_version = SYNCSPIRIT_VERSION; 14 | const char *console_sink_env = "SYNCSPIRIT_CONSOLE_SINK"; 15 | 16 | } // namespace syncspirit::constants 17 | -------------------------------------------------------------------------------- /src/constants.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "syncspirit-export.h" 8 | 9 | namespace syncspirit::constants { 10 | 11 | static const constexpr std::uint32_t bep_magic = 0x2EA7D90B; 12 | static const constexpr std::uint32_t rescan_interval = 3600; 13 | static const constexpr std::int_fast32_t tx_blocks_max_factor = 3; 14 | 15 | SYNCSPIRIT_API extern const char *client_name; 16 | SYNCSPIRIT_API extern const char *client_version; 17 | SYNCSPIRIT_API extern const char *issuer_name; 18 | SYNCSPIRIT_API extern const char *protocol_name; 19 | SYNCSPIRIT_API extern const char *relay_protocol_name; 20 | SYNCSPIRIT_API extern const char *console_sink_env; 21 | 22 | } // namespace syncspirit::constants 23 | -------------------------------------------------------------------------------- /src/db/cursor.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #include "cursor.h" 5 | #include 6 | 7 | namespace syncspirit::db { 8 | 9 | cursor_t::cursor_t(cursor_t &&other) noexcept { std::swap(impl, other.impl); } 10 | 11 | cursor_t::~cursor_t() { 12 | if (impl) { 13 | mdbx_cursor_close(impl); 14 | } 15 | } 16 | 17 | } // namespace syncspirit::db 18 | -------------------------------------------------------------------------------- /src/db/error_code.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #include "error_code.h" 5 | #include "mdbx.h" 6 | 7 | namespace syncspirit::db { 8 | 9 | const static detail::db_code_category category; 10 | const static detail::mdbx_code_category mdbx_category; 11 | 12 | const detail::db_code_category &db_code_category() { return category; } 13 | const detail::mdbx_code_category &mdbx_code_category() { return mdbx_category; } 14 | 15 | namespace detail { 16 | 17 | const char *db_code_category::name() const noexcept { return "syncspirit_db_error"; } 18 | 19 | std::string db_code_category::message(int c) const { return mdbx_strerror(c); } 20 | 21 | const char *mdbx_code_category::name() const noexcept { return "syncspirit_mdbx_error"; } 22 | 23 | std::string mdbx_code_category::message(int c) const { 24 | std::string r; 25 | switch (static_cast(c)) { 26 | case error_code::success: 27 | r = "success"; 28 | break; 29 | case error_code::db_version_size_mismatch: 30 | r = "db version size mismatch"; 31 | break; 32 | default: 33 | r = "unknown"; 34 | } 35 | r += " ("; 36 | r += std::to_string(c) + ")"; 37 | return r; 38 | } 39 | 40 | } // namespace detail 41 | } // namespace syncspirit::db 42 | -------------------------------------------------------------------------------- /src/db/prefix.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2023 Ivan Baidakou 3 | 4 | #include "prefix.h" 5 | 6 | using namespace syncspirit::db; 7 | 8 | static value_t mk(discr_t prefix, std::string_view name) noexcept { 9 | std::string r; 10 | r.resize(name.size() + 1); 11 | *r.data() = (char)prefix; 12 | std::copy(name.begin(), name.end(), r.begin() + 1); 13 | return r; 14 | } 15 | 16 | value_t prefixer_t::make(std::string_view name) noexcept { return mk(prefix::misc, name); } 17 | -------------------------------------------------------------------------------- /src/db/utils.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "utils/platform.h" 7 | #include 8 | #include "transaction.h" 9 | #include "prefix.h" 10 | #include "../model/diff/load/common.h" 11 | #include "../model/device.h" 12 | 13 | namespace syncspirit { 14 | namespace db { 15 | 16 | extern std::uint32_t version; 17 | 18 | using pair_t = model::diff::load::pair_t; 19 | using container_t = model::diff::load::container_t; 20 | 21 | SYNCSPIRIT_API outcome::result get_version(transaction_t &txn) noexcept; 22 | SYNCSPIRIT_API outcome::result migrate(std::uint32_t from, model::device_ptr_t device, 23 | transaction_t &txn) noexcept; 24 | 25 | SYNCSPIRIT_API outcome::result load(discr_t prefix, transaction_t &txn) noexcept; 26 | SYNCSPIRIT_API outcome::result save(const pair_t &container, transaction_t &txn) noexcept; 27 | SYNCSPIRIT_API outcome::result remove(std::string_view key, transaction_t &txn) noexcept; 28 | 29 | } // namespace db 30 | } // namespace syncspirit 31 | -------------------------------------------------------------------------------- /src/fs/messages.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2023 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "proto/bep_support.h" 8 | #include "scan_task.h" 9 | #include "file.h" 10 | #include "chunk_iterator.h" 11 | #include "new_chunk_iterator.h" 12 | 13 | namespace syncspirit::fs { 14 | 15 | namespace r = rotor; 16 | 17 | namespace payload { 18 | 19 | struct scan_progress_t { 20 | scan_task_ptr_t task; 21 | }; 22 | 23 | using rehash_needed_t = chunk_iterator_t; 24 | using hash_anew_t = new_chunk_iterator_t; 25 | 26 | struct block_request_t { 27 | proto::message::Request remote_request; 28 | r::address_ptr_t reply_to; 29 | }; 30 | 31 | struct block_response_t { 32 | proto::message::Request remote_request; 33 | sys::error_code ec; 34 | std::string data; 35 | }; 36 | 37 | } // namespace payload 38 | 39 | namespace message { 40 | 41 | using scan_progress_t = r::message_t; 42 | using rehash_needed_t = r::message_t; 43 | using hash_anew_t = r::message_t; 44 | using block_request_t = r::message_t; 45 | using block_response_t = r::message_t; 46 | 47 | } // namespace message 48 | 49 | } // namespace syncspirit::fs 50 | -------------------------------------------------------------------------------- /src/fs/utils.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include "syncspirit-export.h" 10 | 11 | namespace syncspirit { 12 | namespace fs { 13 | 14 | namespace bfs = std::filesystem; 15 | namespace sys = boost::system; 16 | namespace outcome = boost::outcome_v2; 17 | 18 | using fs_time_t = std::filesystem::file_time_type; 19 | 20 | struct block_division_t { 21 | size_t count; 22 | int32_t size; 23 | }; 24 | 25 | SYNCSPIRIT_API bfs::path make_temporal(const bfs::path &path) noexcept; 26 | SYNCSPIRIT_API bool is_temporal(const bfs::path &path) noexcept; 27 | SYNCSPIRIT_API block_division_t get_block_size(int64_t file_size, int32_t prev_size) noexcept; 28 | SYNCSPIRIT_API bfs::path relativize(const bfs::path &path, const bfs::path &root) noexcept; 29 | SYNCSPIRIT_API std::int64_t to_unix(const fs_time_t &at); 30 | SYNCSPIRIT_API fs_time_t from_unix(std::int64_t at); 31 | 32 | SYNCSPIRIT_API extern const std::size_t block_sizes_sz; 33 | SYNCSPIRIT_API extern const std::int64_t *block_sizes; 34 | SYNCSPIRIT_API extern const std::string_view tmp_suffix; 35 | 36 | } // namespace fs 37 | } // namespace syncspirit 38 | -------------------------------------------------------------------------------- /src/hasher/hasher_supervisor.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #include "hasher_supervisor.h" 5 | #include "hasher_actor.h" 6 | #include "../net/names.h" 7 | 8 | using namespace syncspirit::hasher; 9 | 10 | hasher_supervisor_t::hasher_supervisor_t(config_t &config) : parent_t(config), index{config.index} {} 11 | 12 | void hasher_supervisor_t::configure(r::plugin::plugin_base_t &plugin) noexcept { 13 | parent_t::configure(plugin); 14 | plugin.with_casted([&](auto &p) { 15 | p.set_identity("hasher.supervisor", false); 16 | log = utils::get_logger(identity); 17 | }); 18 | plugin.with_casted( 19 | [&](auto &p) { p.discover_name(net::names::coordinator, coordinator, true).link(false); }); 20 | plugin.with_casted([&](auto &) { launch(); }); 21 | } 22 | 23 | void hasher_supervisor_t::launch() noexcept { 24 | create_actor().index(index).timeout(shutdown_timeout).finish(); 25 | } 26 | 27 | void hasher_supervisor_t::on_start() noexcept { 28 | LOG_TRACE(log, "{}, on_start", identity); 29 | r::actor_base_t::on_start(); 30 | } 31 | -------------------------------------------------------------------------------- /src/model/diff/advance/advance.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/file_info.h" 8 | #include "model/misc/sequencer.h" 9 | #include "model/misc/resolver.h" 10 | #include "bep.pb.h" 11 | 12 | namespace syncspirit::model::diff::advance { 13 | 14 | struct SYNCSPIRIT_API advance_t : cluster_diff_t { 15 | static cluster_diff_ptr_t create(advance_action_t action, const model::file_info_t &source, 16 | sequencer_t &sequencer) noexcept; 17 | 18 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 19 | 20 | proto::FileInfo proto_source; 21 | proto::FileInfo proto_local; 22 | std::string folder_id; 23 | std::string peer_id; 24 | bu::uuid uuid; 25 | advance_action_t action; 26 | bool disable_blocks_removal; 27 | 28 | protected: 29 | advance_t(std::string_view folder_id, std::string_view peer_id, advance_action_t action, 30 | bool disable_blocks_removal = false) noexcept; 31 | void initialize(const cluster_t &cluster, sequencer_t &sequencer, proto::FileInfo proto_source, 32 | std::string_view local_file_name) noexcept; 33 | }; 34 | 35 | } // namespace syncspirit::model::diff::advance 36 | -------------------------------------------------------------------------------- /src/model/diff/advance/local_update.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "advance.h" 7 | 8 | namespace syncspirit::model::diff::advance { 9 | 10 | struct SYNCSPIRIT_API local_update_t final : advance_t { 11 | using parent_t = advance_t; 12 | using parent_t::parent_t; 13 | 14 | local_update_t(const cluster_t &cluster, sequencer_t &sequencer, proto::FileInfo proto_file, 15 | std::string_view folder_id) noexcept; 16 | 17 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 18 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 19 | }; 20 | 21 | } // namespace syncspirit::model::diff::advance 22 | -------------------------------------------------------------------------------- /src/model/diff/advance/remote_copy.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "advance.h" 7 | 8 | namespace syncspirit::model::diff::advance { 9 | 10 | struct SYNCSPIRIT_API remote_copy_t final : advance_t { 11 | using parent_t = advance_t; 12 | using parent_t::parent_t; 13 | 14 | remote_copy_t(const cluster_t &cluster, sequencer_t &sequencer, proto::FileInfo proto_file, 15 | std::string_view folder_id, std::string_view peer_id, bool disable_blocks_removal = false) noexcept; 16 | 17 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 18 | 19 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 20 | }; 21 | 22 | } // namespace syncspirit::model::diff::advance 23 | -------------------------------------------------------------------------------- /src/model/diff/advance/remote_win.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "advance.h" 7 | 8 | namespace syncspirit::model::diff::advance { 9 | 10 | struct SYNCSPIRIT_API remote_win_t final : advance_t { 11 | using parent_t = advance_t; 12 | using parent_t::parent_t; 13 | 14 | remote_win_t(const cluster_t &cluster, sequencer_t &sequencer, proto::FileInfo proto_file, 15 | std::string_view folder_id, std::string_view peer_id) noexcept; 16 | 17 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 18 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 19 | }; 20 | 21 | } // namespace syncspirit::model::diff::advance 22 | -------------------------------------------------------------------------------- /src/model/diff/apply_controller.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "apply_controller.h" 5 | #include "load/blocks.h" 6 | #include "load/file_infos.h" 7 | #include "load/load_cluster.h" 8 | 9 | namespace syncspirit::model::diff { 10 | 11 | auto apply_controller_t::apply(const cluster_diff_t &diff, cluster_t &cluster) noexcept -> outcome::result { 12 | return diff.apply_impl(cluster, *this); 13 | } 14 | 15 | auto apply_controller_t::apply(const load::blocks_t &diff, cluster_t &cluster) noexcept -> outcome::result { 16 | return diff.apply_impl(cluster, *this); 17 | } 18 | 19 | auto apply_controller_t::apply(const load::file_infos_t &diff, cluster_t &cluster) noexcept -> outcome::result { 20 | return diff.apply_impl(cluster, *this); 21 | } 22 | 23 | auto apply_controller_t::apply(const load::load_cluster_t &diff, cluster_t &cluster) noexcept -> outcome::result { 24 | return diff.apply_impl(cluster, *this); 25 | } 26 | 27 | } // namespace syncspirit::model::diff 28 | -------------------------------------------------------------------------------- /src/model/diff/apply_controller.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "syncspirit-export.h" 7 | #include "diffs_fwd.h" 8 | #include 9 | 10 | namespace syncspirit::model { 11 | struct cluster_t; 12 | } 13 | 14 | namespace syncspirit::model::diff { 15 | 16 | namespace outcome = boost::outcome_v2; 17 | 18 | struct SYNCSPIRIT_API apply_controller_t { 19 | virtual outcome::result apply(const cluster_diff_t &, cluster_t &cluster) noexcept; 20 | virtual outcome::result apply(const load::blocks_t &, cluster_t &cluster) noexcept; 21 | virtual outcome::result apply(const load::file_infos_t &, cluster_t &cluster) noexcept; 22 | virtual outcome::result apply(const load::load_cluster_t &, cluster_t &cluster) noexcept; 23 | }; 24 | 25 | } // namespace syncspirit::model::diff 26 | -------------------------------------------------------------------------------- /src/model/diff/block_diff.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #include "block_diff.h" 5 | #include "../cluster.h" 6 | 7 | using namespace syncspirit::model::diff; 8 | 9 | block_diff_t::block_diff_t(const block_diff_t &source) noexcept 10 | : file_name(source.file_name), folder_id{source.folder_id}, device_id{source.device_id}, 11 | block_hash{source.block_hash}, block_index{source.block_index} {} 12 | 13 | block_diff_t::block_diff_t(const file_info_t &file, size_t block_index_) noexcept 14 | : file_name{file.get_name()}, block_index{block_index_} { 15 | auto fi = file.get_folder_info(); 16 | folder_id = fi->get_folder()->get_id(); 17 | device_id = fi->get_device()->device_id().get_sha256(); 18 | block_hash = file.get_blocks()[block_index_]->get_hash(); 19 | } 20 | -------------------------------------------------------------------------------- /src/model/diff/block_diff.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "cluster_diff.h" 7 | 8 | namespace syncspirit::model { 9 | 10 | struct file_info_t; 11 | 12 | namespace diff { 13 | 14 | struct SYNCSPIRIT_API block_diff_t : cluster_diff_t { 15 | block_diff_t(const block_diff_t &) noexcept; 16 | block_diff_t(const file_info_t &file, size_t block_index = 0) noexcept; 17 | 18 | std::string file_name; 19 | std::string folder_id; 20 | std::string device_id; 21 | std::string block_hash; 22 | size_t block_index; 23 | }; 24 | 25 | } // namespace diff 26 | } // namespace syncspirit::model 27 | -------------------------------------------------------------------------------- /src/model/diff/contact/connect_request.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "connect_request.h" 5 | #include "../cluster_visitor.h" 6 | #include "utils/format.hpp" 7 | 8 | using namespace syncspirit::model::diff::contact; 9 | 10 | connect_request_t::connect_request_t(tcp::socket sock_, const tcp::endpoint &remote_) noexcept 11 | : sock{new tcp::socket(std::move(sock_))}, remote{remote_} { 12 | LOG_DEBUG(log, "connect_request_t, endpoint = {}", remote); 13 | } 14 | 15 | auto connect_request_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 16 | -> outcome::result { 17 | return applicator_t::apply_sibling(cluster, controller); 18 | } 19 | 20 | auto connect_request_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 21 | LOG_TRACE(log, "visiting connect_request_t"); 22 | return visitor(*this, custom); 23 | } 24 | -------------------------------------------------------------------------------- /src/model/diff/contact/connect_request.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include "model/diff/cluster_diff.h" 9 | #include "model/cluster.h" 10 | 11 | namespace syncspirit::model::diff::contact { 12 | 13 | namespace asio = boost::asio; 14 | using tcp = asio::ip::tcp; 15 | 16 | struct SYNCSPIRIT_API connect_request_t final : cluster_diff_t { 17 | using socket_ptr_t = std::unique_ptr; 18 | using mutex_t = std::mutex; 19 | 20 | connect_request_t(tcp::socket sock, const tcp::endpoint &remote) noexcept; 21 | 22 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 23 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 24 | 25 | mutable socket_ptr_t sock; 26 | tcp::endpoint remote; 27 | mutable mutex_t mutex; 28 | }; 29 | 30 | } // namespace syncspirit::model::diff::contact 31 | -------------------------------------------------------------------------------- /src/model/diff/contact/dial_request.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "dial_request.h" 5 | #include "../cluster_visitor.h" 6 | 7 | using namespace syncspirit::model::diff::contact; 8 | 9 | dial_request_t::dial_request_t(model::device_t &peer) noexcept : peer_id{peer.device_id().get_sha256()} { 10 | LOG_DEBUG(log, "dial_request_t, peer = ", peer.device_id().get_short()); 11 | } 12 | 13 | auto dial_request_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 14 | -> outcome::result { 15 | return applicator_t::apply_sibling(cluster, controller); 16 | } 17 | 18 | auto dial_request_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 19 | LOG_TRACE(log, "visiting dial_request_t"); 20 | return visitor(*this, custom); 21 | } 22 | -------------------------------------------------------------------------------- /src/model/diff/contact/dial_request.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "model/cluster.h" 8 | #include "model/diff/cluster_diff.h" 9 | 10 | namespace syncspirit::model::diff::contact { 11 | 12 | namespace asio = boost::asio; 13 | using tcp = asio::ip::tcp; 14 | 15 | struct SYNCSPIRIT_API dial_request_t final : cluster_diff_t { 16 | dial_request_t(model::device_t &peer) noexcept; 17 | 18 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 19 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 20 | 21 | std::string peer_id; 22 | }; 23 | 24 | } // namespace syncspirit::model::diff::contact 25 | -------------------------------------------------------------------------------- /src/model/diff/contact/ignored_connected.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "ignored_connected.h" 5 | #include "model/cluster.h" 6 | #include "../cluster_visitor.h" 7 | #include "model/misc/error_code.h" 8 | 9 | using namespace syncspirit::model::diff::contact; 10 | 11 | ignored_connected_t::ignored_connected_t(cluster_t &, const model::device_id_t &device_id_, 12 | db::SomeDevice db_device_) noexcept 13 | : device_id{device_id_}, db_device{std::move(db_device_)} { 14 | LOG_DEBUG(log, "ignored_connected_t, device = ", device_id.get_short()); 15 | } 16 | 17 | auto ignored_connected_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 18 | -> outcome::result { 19 | auto &ignored_devices = cluster.get_ignored_devices(); 20 | auto prev = ignored_devices.by_sha256(device_id.get_sha256()); 21 | if (!prev) { 22 | return make_error_code(error_code_t::no_such_device); 23 | } 24 | prev->assign(db_device); 25 | prev->notify_update(); 26 | return applicator_t::apply_sibling(cluster, controller); 27 | } 28 | 29 | auto ignored_connected_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 30 | LOG_TRACE(log, "visiting ignored_connected_t"); 31 | return visitor(*this, custom); 32 | } 33 | -------------------------------------------------------------------------------- /src/model/diff/contact/ignored_connected.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/ignored_device.h" 8 | 9 | namespace syncspirit::model::diff::contact { 10 | 11 | struct SYNCSPIRIT_API ignored_connected_t final : cluster_diff_t { 12 | ignored_connected_t(cluster_t &, const model::device_id_t &device_id, db::SomeDevice db_device) noexcept; 13 | 14 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 15 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 16 | 17 | model::device_id_t device_id; 18 | db::SomeDevice db_device; 19 | }; 20 | 21 | } // namespace syncspirit::model::diff::contact 22 | -------------------------------------------------------------------------------- /src/model/diff/contact/relay_connect_request.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "relay_connect_request.h" 5 | #include "../cluster_visitor.h" 6 | #include "utils/format.hpp" 7 | 8 | using namespace syncspirit::model::diff::contact; 9 | 10 | relay_connect_request_t::relay_connect_request_t(model::device_id_t peer_, std::string session_key_, 11 | tcp::endpoint relay_) noexcept 12 | : peer{std::move(peer_)}, session_key{std::move(session_key_)}, relay{std::move(relay_)} { 13 | LOG_DEBUG(log, "relay_connect_request_t, device = {}, relay = {}", peer.get_short(), relay); 14 | } 15 | 16 | auto relay_connect_request_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 17 | -> outcome::result { 18 | return applicator_t::apply_sibling(cluster, controller); 19 | } 20 | 21 | auto relay_connect_request_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 22 | LOG_TRACE(log, "visiting relay_connect_request_t"); 23 | return visitor(*this, custom); 24 | } 25 | -------------------------------------------------------------------------------- /src/model/diff/contact/relay_connect_request.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "../cluster_diff.h" 8 | #include "model/cluster.h" 9 | #include "model/device_id.h" 10 | 11 | namespace syncspirit::model::diff::contact { 12 | 13 | namespace asio = boost::asio; 14 | using tcp = asio::ip::tcp; 15 | 16 | struct SYNCSPIRIT_API relay_connect_request_t final : cluster_diff_t { 17 | relay_connect_request_t(model::device_id_t peer, std::string session_key, tcp::endpoint relay) noexcept; 18 | 19 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 20 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 21 | 22 | model::device_id_t peer; 23 | std::string session_key; 24 | tcp::endpoint relay; 25 | }; 26 | 27 | } // namespace syncspirit::model::diff::contact 28 | -------------------------------------------------------------------------------- /src/model/diff/contact/unknown_connected.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/pending_device.h" 8 | 9 | namespace syncspirit::model::diff::contact { 10 | 11 | struct SYNCSPIRIT_API unknown_connected_t final : cluster_diff_t { 12 | unknown_connected_t(cluster_t &cluster, const model::device_id_t &device_id, db::SomeDevice db_device) noexcept; 13 | 14 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 15 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 16 | 17 | model::device_id_t device_id; 18 | db::SomeDevice db_device; 19 | }; 20 | 21 | } // namespace syncspirit::model::diff::contact 22 | -------------------------------------------------------------------------------- /src/model/diff/contact/update_contact.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/cluster.h" 8 | 9 | namespace syncspirit::model::diff::contact { 10 | 11 | struct SYNCSPIRIT_API update_contact_t final : cluster_diff_t { 12 | using ip_addresses_t = std::vector; 13 | 14 | update_contact_t(const model::cluster_t &cluster, const model::device_id_t &device, 15 | const utils::uri_container_t &uris) noexcept; 16 | 17 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 18 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 19 | 20 | model::device_id_t device; 21 | utils::uri_container_t uris; 22 | bool known; 23 | bool self; 24 | }; 25 | 26 | } // namespace syncspirit::model::diff::contact 27 | -------------------------------------------------------------------------------- /src/model/diff/load/blocks.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "blocks.h" 5 | #include "model/cluster.h" 6 | #include "model/diff/apply_controller.h" 7 | #include "model/misc/error_code.h" 8 | 9 | using namespace syncspirit::model::diff::load; 10 | 11 | auto blocks_t::apply_forward(cluster_t &cluster, apply_controller_t &controller) const noexcept 12 | -> outcome::result { 13 | return controller.apply(*this, cluster); 14 | } 15 | 16 | auto blocks_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept -> outcome::result { 17 | auto &blocks_map = cluster.get_blocks(); 18 | for (auto &pair : blocks) { 19 | auto data = pair.value; 20 | auto db = db::BlockInfo(); 21 | auto ok = db.ParseFromArray(data.data(), data.size()); 22 | if (!ok) { 23 | return make_error_code(error_code_t::block_deserialization_failure); 24 | } 25 | auto block = block_info_t::create(pair.key, db); 26 | if (block.has_error()) { 27 | return block.assume_error(); 28 | } 29 | blocks_map.put(std::move(block.value())); 30 | } 31 | return applicator_t::apply_sibling(cluster, controller); 32 | } 33 | -------------------------------------------------------------------------------- /src/model/diff/load/blocks.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "common.h" 7 | 8 | namespace syncspirit::model::diff::load { 9 | 10 | struct SYNCSPIRIT_API blocks_t final : cluster_diff_t { 11 | template blocks_t(T &&blocks_) noexcept : blocks{std::forward(blocks_)} {} 12 | 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | outcome::result apply_forward(cluster_t &, apply_controller_t &) const noexcept override; 15 | 16 | container_t blocks; 17 | }; 18 | 19 | } // namespace syncspirit::model::diff::load 20 | -------------------------------------------------------------------------------- /src/model/diff/load/common.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include "../cluster_diff.h" 10 | 11 | namespace syncspirit::model::diff::load { 12 | 13 | struct pair_t { 14 | std::string_view key; 15 | std::string_view value; 16 | }; 17 | 18 | using container_t = std::vector; 19 | 20 | } // namespace syncspirit::model::diff::load 21 | -------------------------------------------------------------------------------- /src/model/diff/load/devices.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "common.h" 7 | 8 | namespace syncspirit::model::diff::load { 9 | 10 | struct SYNCSPIRIT_API devices_t final : cluster_diff_t { 11 | template devices_t(T &&devices_) noexcept : devices{std::forward(devices_)} {} 12 | 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 15 | 16 | container_t devices; 17 | }; 18 | 19 | } // namespace syncspirit::model::diff::load 20 | -------------------------------------------------------------------------------- /src/model/diff/load/file_infos.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "common.h" 7 | #include "structs.pb.h" 8 | 9 | namespace syncspirit::model::diff::load { 10 | 11 | struct SYNCSPIRIT_API file_infos_t final : cluster_diff_t { 12 | using item_t = std::pair; 13 | using container_t = std::vector; 14 | inline file_infos_t(container_t &&container_) noexcept : container{std::move(container_)} {} 15 | 16 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 17 | outcome::result apply_forward(cluster_t &, apply_controller_t &) const noexcept override; 18 | 19 | container_t container; 20 | }; 21 | 22 | } // namespace syncspirit::model::diff::load 23 | -------------------------------------------------------------------------------- /src/model/diff/load/folder_infos.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "common.h" 7 | 8 | namespace syncspirit::model::diff::load { 9 | 10 | struct SYNCSPIRIT_API folder_infos_t final : cluster_diff_t { 11 | template folder_infos_t(T &&container_) noexcept : container{std::forward(container_)} {} 12 | 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | 15 | container_t container; 16 | }; 17 | 18 | } // namespace syncspirit::model::diff::load 19 | -------------------------------------------------------------------------------- /src/model/diff/load/folders.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #include "folders.h" 5 | #include "../../cluster.h" 6 | #include "../../misc/error_code.h" 7 | 8 | using namespace syncspirit::model::diff::load; 9 | 10 | auto folders_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept -> outcome::result { 11 | auto &map = cluster.get_folders(); 12 | for (auto &pair : folders) { 13 | auto data = pair.value; 14 | auto db = db::Folder(); 15 | auto ok = db.ParseFromArray(data.data(), data.size()); 16 | if (!ok) { 17 | return make_error_code(error_code_t::folder_deserialization_failure); 18 | } 19 | 20 | auto option = folder_t::create(pair.key, db); 21 | if (!option) { 22 | return option.assume_error(); 23 | } 24 | auto &folder = option.value(); 25 | map.put(folder); 26 | folder->assign_cluster(&cluster); 27 | } 28 | return applicator_t::apply_sibling(cluster, controller); 29 | } 30 | -------------------------------------------------------------------------------- /src/model/diff/load/folders.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "common.h" 7 | 8 | namespace syncspirit::model::diff::load { 9 | 10 | struct SYNCSPIRIT_API folders_t final : cluster_diff_t { 11 | template folders_t(T &&folders_) noexcept : folders{std::forward(folders_)} {} 12 | 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | 15 | container_t folders; 16 | }; 17 | 18 | } // namespace syncspirit::model::diff::load 19 | -------------------------------------------------------------------------------- /src/model/diff/load/ignored_devices.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "model/cluster.h" 5 | #include "ignored_devices.h" 6 | #include "some_devices.hpp" 7 | #include "model/diff/cluster_visitor.h" 8 | 9 | using namespace syncspirit::model::diff::load; 10 | 11 | auto ignored_devices_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 12 | -> outcome::result { 13 | using device_t = model::ignored_device_t; 14 | auto &map = cluster.get_ignored_devices(); 15 | auto r = some_devices_t::apply(devices, map); 16 | return r ? applicator_t::apply_sibling(cluster, controller) : r; 17 | } 18 | 19 | auto ignored_devices_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 20 | return visitor(*this, custom); 21 | } 22 | -------------------------------------------------------------------------------- /src/model/diff/load/ignored_devices.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "common.h" 7 | 8 | namespace syncspirit::model::diff::load { 9 | 10 | struct SYNCSPIRIT_API ignored_devices_t final : cluster_diff_t { 11 | template ignored_devices_t(T &&devices_) noexcept : devices{std::forward(devices_)} {} 12 | 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 15 | 16 | container_t devices; 17 | }; 18 | 19 | } // namespace syncspirit::model::diff::load 20 | -------------------------------------------------------------------------------- /src/model/diff/load/ignored_folders.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "ignored_folders.h" 5 | #include "../../cluster.h" 6 | 7 | using namespace syncspirit::model::diff::load; 8 | 9 | auto ignored_folders_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 10 | -> outcome::result { 11 | auto &map = cluster.get_ignored_folders(); 12 | for (auto &pair : folders) { 13 | auto option = ignored_folder_t::create(pair.key, pair.value); 14 | if (!option) { 15 | return option.assume_error(); 16 | } 17 | auto &folder = option.value(); 18 | map.put(folder); 19 | } 20 | return applicator_t::apply_sibling(cluster, controller); 21 | }; 22 | -------------------------------------------------------------------------------- /src/model/diff/load/ignored_folders.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "common.h" 7 | 8 | namespace syncspirit::model::diff::load { 9 | 10 | struct SYNCSPIRIT_API ignored_folders_t final : cluster_diff_t { 11 | template ignored_folders_t(T &&folders_) noexcept : folders{std::forward(folders_)} {} 12 | 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | 15 | container_t folders; 16 | }; 17 | 18 | } // namespace syncspirit::model::diff::load 19 | -------------------------------------------------------------------------------- /src/model/diff/load/load_cluster.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "load_cluster.h" 5 | #include "model/diff/cluster_visitor.h" 6 | 7 | using namespace syncspirit::model::diff::load; 8 | 9 | load_cluster_t::load_cluster_t(db::transaction_t txn_, std::size_t blocks_count_, std::size_t files_count_) noexcept 10 | : txn{std::move(txn_)}, blocks_count{blocks_count_}, files_count{files_count_} {} 11 | 12 | auto load_cluster_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 13 | -> outcome::result { 14 | return applicator_t::apply_impl(cluster, controller); 15 | } 16 | 17 | auto load_cluster_t::apply_forward(cluster_t &cluster, apply_controller_t &controller) const noexcept 18 | -> outcome::result { 19 | return controller.apply(*this, cluster); 20 | } 21 | 22 | auto load_cluster_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 23 | return visitor(*this, custom); 24 | } 25 | -------------------------------------------------------------------------------- /src/model/diff/load/load_cluster.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | #include "model/diff/cluster_diff.h" 6 | #include "model/diff/apply_controller.h" 7 | #include "db/transaction.h" 8 | 9 | namespace syncspirit::model::diff::load { 10 | 11 | struct SYNCSPIRIT_API load_cluster_t final : cluster_diff_t { 12 | using parent_t = cluster_diff_t; 13 | 14 | load_cluster_t(db::transaction_t txn, std::size_t blocks_count, std::size_t files_count) noexcept; 15 | 16 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 17 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 18 | outcome::result apply_forward(cluster_t &, apply_controller_t &) const noexcept override; 19 | 20 | db::transaction_t txn; 21 | std::size_t blocks_count; 22 | std::size_t files_count; 23 | }; 24 | 25 | } // namespace syncspirit::model::diff::load 26 | -------------------------------------------------------------------------------- /src/model/diff/load/pending_devices.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "model/cluster.h" 5 | #include "pending_devices.h" 6 | #include "some_devices.hpp" 7 | #include "model/diff/cluster_visitor.h" 8 | 9 | using namespace syncspirit::model::diff::load; 10 | 11 | auto pending_devices_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 12 | -> outcome::result { 13 | using device_t = model::pending_device_t; 14 | auto &map = cluster.get_pending_devices(); 15 | auto r = some_devices_t::apply(devices, map); 16 | return r ? applicator_t::apply_sibling(cluster, controller) : r; 17 | } 18 | 19 | auto pending_devices_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 20 | return visitor(*this, custom); 21 | } 22 | -------------------------------------------------------------------------------- /src/model/diff/load/pending_devices.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "common.h" 7 | 8 | namespace syncspirit::model::diff::load { 9 | 10 | struct SYNCSPIRIT_API pending_devices_t final : cluster_diff_t { 11 | template pending_devices_t(T &&devices_) noexcept : devices{std::forward(devices_)} {} 12 | 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 15 | 16 | container_t devices; 17 | }; 18 | 19 | } // namespace syncspirit::model::diff::load 20 | -------------------------------------------------------------------------------- /src/model/diff/load/pending_folders.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "pending_folders.h" 5 | #include "../../cluster.h" 6 | #include "../../misc/error_code.h" 7 | 8 | using namespace syncspirit::model::diff::load; 9 | 10 | auto pending_folders_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 11 | -> outcome::result { 12 | auto &items = cluster.get_pending_folders(); 13 | for (auto &pair : folders) { 14 | auto data = pair.value; 15 | auto db = db::PendingFolder(); 16 | auto ok = db.ParseFromArray(data.data(), data.size()); 17 | if (!ok) { 18 | return make_error_code(error_code_t::pending_folder_deserialization_failure); 19 | } 20 | 21 | auto option = pending_folder_t::create(pair.key, db); 22 | if (!option) { 23 | return option.assume_error(); 24 | } 25 | auto &folder = option.value(); 26 | items.put(std::move(folder)); 27 | } 28 | return applicator_t::apply_sibling(cluster, controller); 29 | } 30 | -------------------------------------------------------------------------------- /src/model/diff/load/pending_folders.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "common.h" 7 | 8 | namespace syncspirit::model::diff::load { 9 | 10 | struct SYNCSPIRIT_API pending_folders_t final : cluster_diff_t { 11 | template pending_folders_t(T &&folders_) noexcept : folders{std::forward(folders_)} {} 12 | 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | 15 | container_t folders; 16 | }; 17 | 18 | } // namespace syncspirit::model::diff::load 19 | -------------------------------------------------------------------------------- /src/model/diff/local/blocks_availability.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../block_diff.h" 7 | #include "model/file_info.h" 8 | #include 9 | 10 | namespace syncspirit::model::diff::local { 11 | 12 | struct SYNCSPIRIT_API blocks_availability_t final : block_diff_t { 13 | using valid_blocks_map_t = std::vector; 14 | 15 | blocks_availability_t(const file_info_t &file, valid_blocks_map_t valid_blocks_map) noexcept; 16 | 17 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 18 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 19 | 20 | valid_blocks_map_t valid_blocks_map; 21 | }; 22 | 23 | } // namespace syncspirit::model::diff::local 24 | -------------------------------------------------------------------------------- /src/model/diff/local/custom.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "custom.h" 5 | #include "model/diff/cluster_visitor.h" 6 | 7 | using namespace syncspirit::model::diff::local; 8 | 9 | auto custom_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 10 | LOG_TRACE(log, "visiting custom_t"); 11 | return visitor(*this, custom); 12 | } 13 | -------------------------------------------------------------------------------- /src/model/diff/local/custom.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | 8 | namespace syncspirit::model::diff::local { 9 | 10 | struct SYNCSPIRIT_API custom_t : cluster_diff_t { 11 | custom_t() = default; 12 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 13 | }; 14 | 15 | } // namespace syncspirit::model::diff::local 16 | -------------------------------------------------------------------------------- /src/model/diff/local/file_availability.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/cluster.h" 7 | #include "../cluster_diff.h" 8 | #include "../cluster_visitor.h" 9 | 10 | namespace syncspirit::model::diff::local { 11 | 12 | struct SYNCSPIRIT_API file_availability_t final : cluster_diff_t { 13 | 14 | file_availability_t(file_info_ptr_t file) noexcept; 15 | 16 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 17 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 18 | 19 | std::string folder_id; 20 | model::file_info_ptr_t file; 21 | model::version_ptr_t version; 22 | }; 23 | 24 | } // namespace syncspirit::model::diff::local 25 | -------------------------------------------------------------------------------- /src/model/diff/local/io_failure.cpp: -------------------------------------------------------------------------------- 1 | #include "io_failure.h" 2 | #include "../cluster_visitor.h" 3 | 4 | using namespace syncspirit::model::diff::local; 5 | 6 | io_failure_t::io_failure_t(io_error_t e) noexcept : errors{std::move(e)} {} 7 | 8 | io_failure_t::io_failure_t(io_errors_t errors_) noexcept : errors{std::move(errors_)} {} 9 | 10 | auto io_failure_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 11 | LOG_TRACE(log, "visiting io_failure_t"); 12 | return visitor(*this, custom); 13 | } 14 | -------------------------------------------------------------------------------- /src/model/diff/local/io_failure.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include 8 | #include 9 | #include 10 | 11 | namespace syncspirit::model::diff::local { 12 | 13 | namespace sys = boost::system; 14 | namespace bfs = std::filesystem; 15 | 16 | struct io_error_t { 17 | bfs::path path; 18 | sys::error_code ec; 19 | }; 20 | 21 | using io_errors_t = std::vector; 22 | 23 | struct SYNCSPIRIT_API io_failure_t final : cluster_diff_t { 24 | io_failure_t(io_error_t) noexcept; 25 | io_failure_t(io_errors_t) noexcept; 26 | 27 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 28 | 29 | io_errors_t errors; 30 | }; 31 | 32 | } // namespace syncspirit::model::diff::local 33 | -------------------------------------------------------------------------------- /src/model/diff/local/scan_finish.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "scan_finish.h" 5 | #include "model/cluster.h" 6 | #include "model/diff/cluster_visitor.h" 7 | 8 | using namespace syncspirit::model::diff::local; 9 | 10 | scan_finish_t::scan_finish_t(std::string_view folder_id_, const pt::ptime &at_) 11 | : folder_id{std::move(folder_id_)}, at{at_} { 12 | LOG_DEBUG(log, "scan_finish_t, folder = {}", folder_id); 13 | } 14 | 15 | auto scan_finish_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 16 | -> outcome::result { 17 | auto folder = cluster.get_folders().by_id(folder_id); 18 | folder->set_scan_finish(at); 19 | auto r = applicator_t::apply_sibling(cluster, controller); 20 | folder->notify_update(); 21 | return r; 22 | } 23 | 24 | auto scan_finish_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 25 | LOG_TRACE(log, "visiting scan_finish_t"); 26 | return visitor(*this, custom); 27 | } 28 | -------------------------------------------------------------------------------- /src/model/diff/local/scan_finish.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include "../cluster_diff.h" 9 | 10 | namespace syncspirit::model::diff::local { 11 | 12 | namespace pt = boost::posix_time; 13 | 14 | struct SYNCSPIRIT_API scan_finish_t final : cluster_diff_t { 15 | scan_finish_t(std::string_view folder_id, const pt::ptime &at); 16 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 17 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 18 | 19 | std::string folder_id; 20 | pt::ptime at; 21 | }; 22 | 23 | } // namespace syncspirit::model::diff::local 24 | -------------------------------------------------------------------------------- /src/model/diff/local/scan_request.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "scan_request.h" 5 | #include "model/diff/cluster_visitor.h" 6 | 7 | using namespace syncspirit::model::diff::local; 8 | 9 | scan_request_t::scan_request_t(std::string_view folder_id_) : folder_id{std::move(folder_id_)} { 10 | LOG_DEBUG(log, "scan_request_t, folder = {}", folder_id); 11 | } 12 | 13 | auto scan_request_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 14 | LOG_TRACE(log, "visiting scan_request_t"); 15 | return visitor(*this, custom); 16 | } 17 | -------------------------------------------------------------------------------- /src/model/diff/local/scan_request.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "../cluster_diff.h" 8 | 9 | namespace syncspirit::model::diff::local { 10 | 11 | struct SYNCSPIRIT_API scan_request_t final : cluster_diff_t { 12 | scan_request_t(std::string_view folder_id); 13 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 14 | 15 | std::string folder_id; 16 | }; 17 | 18 | } // namespace syncspirit::model::diff::local 19 | -------------------------------------------------------------------------------- /src/model/diff/local/scan_start.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "scan_start.h" 5 | #include "model/cluster.h" 6 | #include "model/diff/cluster_visitor.h" 7 | 8 | using namespace syncspirit::model::diff::local; 9 | 10 | scan_start_t::scan_start_t(std::string_view folder_id_, const pt::ptime &at_) 11 | : folder_id{std::move(folder_id_)}, at{at_} { 12 | LOG_DEBUG(log, "scan_start_t, folder = {}", folder_id); 13 | } 14 | 15 | auto scan_start_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 16 | -> outcome::result { 17 | auto folder = cluster.get_folders().by_id(folder_id); 18 | folder->set_scan_start(at); 19 | auto r = applicator_t::apply_sibling(cluster, controller); 20 | folder->notify_update(); 21 | return r; 22 | } 23 | 24 | auto scan_start_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 25 | LOG_TRACE(log, "visiting scan_start_t"); 26 | return visitor(*this, custom); 27 | } 28 | -------------------------------------------------------------------------------- /src/model/diff/local/scan_start.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include "../cluster_diff.h" 9 | 10 | namespace syncspirit::model::diff::local { 11 | 12 | namespace pt = boost::posix_time; 13 | 14 | struct SYNCSPIRIT_API scan_start_t final : cluster_diff_t { 15 | scan_start_t(std::string_view folder_id, const pt::ptime &at); 16 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 17 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 18 | 19 | std::string folder_id; 20 | pt::ptime at; 21 | }; 22 | 23 | } // namespace syncspirit::model::diff::local 24 | -------------------------------------------------------------------------------- /src/model/diff/local/synchronization_finish.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "synchronization_finish.h" 5 | #include "model/cluster.h" 6 | #include "model/diff/cluster_visitor.h" 7 | 8 | using namespace syncspirit::model::diff::local; 9 | 10 | synchronization_finish_t::synchronization_finish_t(std::string_view folder_id_) : folder_id{std::move(folder_id_)} { 11 | LOG_DEBUG(log, "synchronization_finish_t, folder = {}", folder_id); 12 | } 13 | 14 | auto synchronization_finish_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 15 | -> outcome::result { 16 | auto folder = cluster.get_folders().by_id(folder_id); 17 | if (folder) { 18 | folder->adjust_synchronization(-1); 19 | folder->notify_update(); 20 | } 21 | auto r = applicator_t::apply_sibling(cluster, controller); 22 | return r; 23 | } 24 | 25 | auto synchronization_finish_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 26 | LOG_TRACE(log, "visiting synchronization_finish_t"); 27 | return visitor(*this, custom); 28 | } 29 | -------------------------------------------------------------------------------- /src/model/diff/local/synchronization_finish.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "../cluster_diff.h" 8 | 9 | namespace syncspirit::model::diff::local { 10 | 11 | struct SYNCSPIRIT_API synchronization_finish_t final : cluster_diff_t { 12 | synchronization_finish_t(std::string_view folder_id); 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 15 | 16 | std::string folder_id; 17 | }; 18 | 19 | } // namespace syncspirit::model::diff::local 20 | -------------------------------------------------------------------------------- /src/model/diff/local/synchronization_start.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "synchronization_start.h" 5 | #include "model/cluster.h" 6 | #include "model/diff/cluster_visitor.h" 7 | 8 | using namespace syncspirit::model::diff::local; 9 | 10 | synchronization_start_t::synchronization_start_t(std::string_view folder_id_) : folder_id{std::move(folder_id_)} { 11 | LOG_DEBUG(log, "synchronization_start_t, folder = {}", folder_id); 12 | } 13 | 14 | auto synchronization_start_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 15 | -> outcome::result { 16 | auto folder = cluster.get_folders().by_id(folder_id); 17 | if (folder) { 18 | folder->adjust_synchronization(1); 19 | folder->notify_update(); 20 | } 21 | auto r = applicator_t::apply_sibling(cluster, controller); 22 | return r; 23 | } 24 | 25 | auto synchronization_start_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 26 | LOG_TRACE(log, "visiting synchronization_start_t"); 27 | return visitor(*this, custom); 28 | } 29 | -------------------------------------------------------------------------------- /src/model/diff/local/synchronization_start.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "../cluster_diff.h" 8 | 9 | namespace syncspirit::model::diff::local { 10 | 11 | struct SYNCSPIRIT_API synchronization_start_t final : cluster_diff_t { 12 | synchronization_start_t(std::string_view folder_id); 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 15 | 16 | std::string folder_id; 17 | }; 18 | 19 | } // namespace syncspirit::model::diff::local 20 | -------------------------------------------------------------------------------- /src/model/diff/modify/add_blocks.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "add_blocks.h" 5 | #include "model/cluster.h" 6 | #include "model/diff/cluster_visitor.h" 7 | 8 | using namespace syncspirit::model::diff::modify; 9 | 10 | add_blocks_t::add_blocks_t(blocks_t blocks_) noexcept : blocks{std::move(blocks_)} { 11 | LOG_DEBUG(log, "add_blocks_t, count = {}", blocks.size()); 12 | } 13 | 14 | auto add_blocks_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 15 | -> outcome::result { 16 | auto &bm = cluster.get_blocks(); 17 | for (const auto &b : blocks) { 18 | auto opt = block_info_t::create(b); 19 | if (!opt) { 20 | return opt.assume_error(); 21 | } 22 | auto block = std::move(opt.assume_value()); 23 | bm.put(block); 24 | } 25 | return applicator_t::apply_sibling(cluster, controller); 26 | } 27 | 28 | auto add_blocks_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 29 | LOG_TRACE(log, "visiting add_blocks_t"); 30 | return visitor(*this, custom); 31 | } 32 | -------------------------------------------------------------------------------- /src/model/diff/modify/add_blocks.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/diff/cluster_diff.h" 7 | #include "bep.pb.h" 8 | #include 9 | 10 | namespace syncspirit::model::diff::modify { 11 | 12 | struct SYNCSPIRIT_API add_blocks_t : cluster_diff_t { 13 | using blocks_t = std::vector; 14 | 15 | add_blocks_t(blocks_t blocks) noexcept; 16 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 17 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 18 | 19 | blocks_t blocks; 20 | }; 21 | 22 | } // namespace syncspirit::model::diff::modify 23 | -------------------------------------------------------------------------------- /src/model/diff/modify/add_ignored_device.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/ignored_device.h" 8 | 9 | namespace syncspirit::model::diff::modify { 10 | 11 | struct SYNCSPIRIT_API add_ignored_device_t final : cluster_diff_t { 12 | using parent_t = cluster_diff_t; 13 | 14 | add_ignored_device_t(const cluster_t &cluster, const device_id_t &id, db::SomeDevice db_device) noexcept; 15 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 16 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 17 | 18 | device_id_t device_id; 19 | db::SomeDevice db_device; 20 | }; 21 | 22 | } // namespace syncspirit::model::diff::modify 23 | -------------------------------------------------------------------------------- /src/model/diff/modify/add_pending_device.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "add_pending_device.h" 5 | #include "model/cluster.h" 6 | #include "model/diff/cluster_visitor.h" 7 | 8 | using namespace syncspirit::model::diff::modify; 9 | 10 | add_pending_device_t::add_pending_device_t(const device_id_t &id_, db::SomeDevice db_device_) noexcept 11 | : device_id{id_}, db_device{db_device_} { 12 | LOG_DEBUG(log, "add_pending_device_t, peer = {}", device_id.get_short()); 13 | } 14 | 15 | auto add_pending_device_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 16 | -> outcome::result { 17 | auto opt = pending_device_t::create(device_id, db_device); 18 | if (!opt) { 19 | return opt.assume_error(); 20 | } 21 | auto &pending_device = opt.assume_value(); 22 | cluster.get_pending_devices().put(std::move(pending_device)); 23 | return applicator_t::apply_sibling(cluster, controller); 24 | } 25 | 26 | auto add_pending_device_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 27 | LOG_TRACE(log, "visiting add_pending_device_t"); 28 | return visitor(*this, custom); 29 | } 30 | -------------------------------------------------------------------------------- /src/model/diff/modify/add_pending_device.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/pending_device.h" 8 | 9 | namespace syncspirit::model::diff::modify { 10 | 11 | struct SYNCSPIRIT_API add_pending_device_t final : cluster_diff_t { 12 | add_pending_device_t(const device_id_t &id, db::SomeDevice db_device) noexcept; 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 15 | 16 | device_id_t device_id; 17 | db::SomeDevice db_device; 18 | }; 19 | 20 | } // namespace syncspirit::model::diff::modify 21 | -------------------------------------------------------------------------------- /src/model/diff/modify/add_pending_folders.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "add_pending_folders.h" 5 | #include "model/cluster.h" 6 | #include "model/diff/cluster_visitor.h" 7 | 8 | using namespace syncspirit::model::diff::modify; 9 | 10 | add_pending_folders_t::add_pending_folders_t(container_t items) noexcept : container(std::move(items)) { 11 | LOG_DEBUG(log, "add_pending_folders_t, count = {}", container.size()); 12 | } 13 | 14 | auto add_pending_folders_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 15 | -> outcome::result { 16 | auto &pending = cluster.get_pending_folders(); 17 | auto &devices = cluster.get_devices(); 18 | for (auto &item : container) { 19 | auto peer = devices.by_sha256(item.peer_id); 20 | auto &db = item.db; 21 | auto opt = pending_folder_t::create(item.uuid, db, peer->device_id()); 22 | if (!opt) { 23 | return opt.assume_error(); 24 | } 25 | pending.put(std::move(opt.value())); 26 | } 27 | return applicator_t::apply_sibling(cluster, controller); 28 | } 29 | 30 | auto add_pending_folders_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 31 | LOG_TRACE(log, "visiting add_pending_folders_t"); 32 | return visitor(*this, custom); 33 | } 34 | -------------------------------------------------------------------------------- /src/model/diff/modify/add_pending_folders.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/device.h" 8 | #include 9 | #include "structs.pb.h" 10 | 11 | namespace syncspirit::model::diff::modify { 12 | 13 | struct SYNCSPIRIT_API add_pending_folders_t final : cluster_diff_t { 14 | struct item_t { 15 | db::PendingFolder db; 16 | std::string peer_id; 17 | bu::uuid uuid; 18 | }; 19 | using container_t = std::vector; 20 | 21 | add_pending_folders_t(container_t items) noexcept; 22 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 23 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 24 | 25 | container_t container; 26 | }; 27 | 28 | } // namespace syncspirit::model::diff::modify 29 | -------------------------------------------------------------------------------- /src/model/diff/modify/add_remote_folder_infos.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/device.h" 8 | #include 9 | 10 | namespace syncspirit::model::diff::modify { 11 | 12 | struct SYNCSPIRIT_API add_remote_folder_infos_t final : cluster_diff_t { 13 | struct item_t { 14 | std::string folder_id; 15 | std::uint64_t index_id; 16 | std::int64_t max_sequence; 17 | }; 18 | using container_t = std::vector; 19 | 20 | add_remote_folder_infos_t(const model::device_t &peer, container_t items) noexcept; 21 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 22 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 23 | 24 | std::string device_id; 25 | container_t container; 26 | }; 27 | 28 | } // namespace syncspirit::model::diff::modify 29 | -------------------------------------------------------------------------------- /src/model/diff/modify/append_block.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "append_block.h" 5 | #include "model/diff/cluster_visitor.h" 6 | 7 | using namespace syncspirit::model::diff::modify; 8 | 9 | append_block_t::append_block_t(const file_info_t &file, size_t block_index_, std::string data_) noexcept 10 | : block_transaction_t{file, block_index_,}, data{std::move(data_)} { 11 | LOG_DEBUG(log, "append_block_t, file = {}, block = {}", file.get_name(), block_index); 12 | } 13 | 14 | auto append_block_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 15 | LOG_TRACE(log, "visiting append_block_t"); 16 | return visitor(*this, custom); 17 | } 18 | -------------------------------------------------------------------------------- /src/model/diff/modify/append_block.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "block_transaction.h" 7 | #include "model/file_info.h" 8 | 9 | namespace syncspirit::model::diff::modify { 10 | 11 | struct SYNCSPIRIT_API append_block_t final : block_transaction_t { 12 | 13 | append_block_t(const file_info_t &file, size_t block_index, std::string data) noexcept; 14 | 15 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 16 | 17 | std::string data; 18 | }; 19 | 20 | } // namespace syncspirit::model::diff::modify 21 | -------------------------------------------------------------------------------- /src/model/diff/modify/block_ack.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../block_diff.h" 7 | #include "block_transaction.h" 8 | 9 | namespace syncspirit::model::diff::modify { 10 | 11 | struct SYNCSPIRIT_API block_ack_t final : block_diff_t { 12 | using parent_t = block_diff_t; 13 | 14 | block_ack_t(const block_transaction_t &) noexcept; 15 | 16 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 17 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 18 | }; 19 | 20 | } // namespace syncspirit::model::diff::modify 21 | -------------------------------------------------------------------------------- /src/model/diff/modify/block_rej.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "block_rej.h" 5 | #include "model/diff/cluster_visitor.h" 6 | #include "model/file_info.h" 7 | #include "model/cluster.h" 8 | 9 | using namespace syncspirit::model::diff::modify; 10 | 11 | block_rej_t::block_rej_t(const block_transaction_t &txn) noexcept : parent_t(txn) { 12 | LOG_DEBUG(log, "block_rej_t, file = {}, folder = {}, block = {}", file_name, folder_id, block_index); 13 | } 14 | 15 | auto block_rej_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 16 | -> outcome::result { 17 | auto folder = cluster.get_folders().by_id(folder_id); 18 | auto folder_info = folder->get_folder_infos().by_device_id(device_id); 19 | auto file = folder_info->get_file_infos().by_name(file_name); 20 | LOG_TRACE(log, "block_rej_t, '{}' block # {}", file->get_full_name(), block_index); 21 | file->mark_local_available(block_index); 22 | return applicator_t::apply_sibling(cluster, controller); 23 | } 24 | 25 | auto block_rej_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 26 | LOG_TRACE(log, "visiting block_rej_t"); 27 | return visitor(*this, custom); 28 | } 29 | -------------------------------------------------------------------------------- /src/model/diff/modify/block_rej.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../block_diff.h" 7 | #include "block_transaction.h" 8 | 9 | namespace syncspirit::model::diff::modify { 10 | 11 | struct SYNCSPIRIT_API block_rej_t final : block_diff_t { 12 | using parent_t = block_diff_t; 13 | 14 | block_rej_t(const block_transaction_t &) noexcept; 15 | 16 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 17 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 18 | }; 19 | 20 | } // namespace syncspirit::model::diff::modify 21 | -------------------------------------------------------------------------------- /src/model/diff/modify/block_transaction.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "block_transaction.h" 5 | #include "block_ack.h" 6 | #include "block_rej.h" 7 | 8 | using namespace syncspirit::model::diff::modify; 9 | 10 | block_transaction_t::block_transaction_t(const file_info_t &file, size_t block_index) : parent_t(file, block_index) {} 11 | 12 | auto block_transaction_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 13 | -> outcome::result { 14 | return applicator_t::apply_sibling(cluster, controller); 15 | } 16 | 17 | auto block_transaction_t::ack() const -> cluster_diff_ptr_t { return new block_ack_t(*this); } 18 | 19 | auto block_transaction_t::rej() const -> cluster_diff_ptr_t { return new block_rej_t(*this); } 20 | -------------------------------------------------------------------------------- /src/model/diff/modify/block_transaction.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../block_diff.h" 7 | 8 | namespace syncspirit::model::diff::modify { 9 | 10 | struct SYNCSPIRIT_API block_transaction_t : block_diff_t { 11 | using parent_t = block_diff_t; 12 | 13 | block_transaction_t(const file_info_t &file, size_t block_index); 14 | 15 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 16 | 17 | cluster_diff_ptr_t ack() const; 18 | cluster_diff_ptr_t rej() const; 19 | }; 20 | 21 | } // namespace syncspirit::model::diff::modify 22 | -------------------------------------------------------------------------------- /src/model/diff/modify/clone_block.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "block_transaction.h" 7 | #include "model/misc/file_block.h" 8 | 9 | namespace syncspirit::model::diff::modify { 10 | 11 | struct SYNCSPIRIT_API clone_block_t final : block_transaction_t { 12 | clone_block_t(const file_block_t &file_block) noexcept; 13 | 14 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 15 | 16 | std::string source_device_id; 17 | std::string source_folder_id; 18 | std::string source_file_name; 19 | size_t source_block_index; 20 | }; 21 | 22 | } // namespace syncspirit::model::diff::modify 23 | -------------------------------------------------------------------------------- /src/model/diff/modify/finish_file.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "finish_file.h" 5 | 6 | #include "../cluster_visitor.h" 7 | #include "model/device_id.h" 8 | #include "model/cluster.h" 9 | #include "utils/format.hpp" 10 | 11 | using namespace syncspirit::model::diff::modify; 12 | 13 | finish_file_t::finish_file_t(const model::file_info_t &file) noexcept { 14 | auto fi = file.get_folder_info(); 15 | auto folder = fi->get_folder(); 16 | auto &device_id = fi->get_device()->device_id(); 17 | folder_id = folder->get_id(); 18 | file_name = file.get_name(); 19 | peer_id = device_id.get_sha256(); 20 | assert(device_id != folder->get_cluster()->get_device()->device_id()); 21 | action = resolve(file); 22 | assert(action != advance_action_t::ignore); 23 | LOG_DEBUG(log, "finish_file_t, file = {}, folder = {}, peer = {}, action = {}", file_name, folder_id, device_id, 24 | (int)action); 25 | } 26 | 27 | auto finish_file_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 28 | LOG_TRACE(log, "visiting finish_file_t (visitor = {}), folder = {}, file = {}", (const void *)&visitor, folder_id, 29 | file_name); 30 | return visitor(*this, custom); 31 | } 32 | -------------------------------------------------------------------------------- /src/model/diff/modify/finish_file.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/file_info.h" 8 | #include "model/device.h" 9 | #include "model/misc/resolver.h" 10 | 11 | namespace syncspirit::model::diff::modify { 12 | 13 | struct SYNCSPIRIT_API finish_file_t final : cluster_diff_t { 14 | finish_file_t(const model::file_info_t &file) noexcept; 15 | 16 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 17 | 18 | std::string folder_id; 19 | std::string peer_id; 20 | std::string file_name; 21 | model::advance_action_t action; 22 | }; 23 | 24 | } // namespace syncspirit::model::diff::modify 25 | -------------------------------------------------------------------------------- /src/model/diff/modify/generic_remove.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "generic_remove.h" 5 | 6 | #include 7 | 8 | using namespace syncspirit::model::diff::modify; 9 | 10 | generic_remove_t::generic_remove_t(keys_t keys_) noexcept : keys{std::move(keys_)} {} 11 | 12 | generic_remove_t::generic_remove_t(unique_keys_t keys_) noexcept { 13 | keys.reserve(keys_.size()); 14 | std::copy(keys_.begin(), keys_.end(), std::back_insert_iterator(keys)); 15 | } 16 | -------------------------------------------------------------------------------- /src/model/diff/modify/generic_remove.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/diff/cluster_diff.h" 7 | #include "utils/string_comparator.hpp" 8 | #include 9 | #include 10 | 11 | namespace syncspirit::model::diff::modify { 12 | 13 | struct SYNCSPIRIT_API generic_remove_t : cluster_diff_t { 14 | using unique_keys_t = std::set; 15 | using keys_t = std::vector; 16 | 17 | generic_remove_t() = default; 18 | generic_remove_t(keys_t keys) noexcept; 19 | generic_remove_t(unique_keys_t keys) noexcept; 20 | 21 | keys_t keys; 22 | }; 23 | 24 | } // namespace syncspirit::model::diff::modify 25 | -------------------------------------------------------------------------------- /src/model/diff/modify/lock_file.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "utils/platform.h" 7 | #include "../cluster_diff.h" 8 | #include "model/file_info.h" 9 | 10 | namespace syncspirit::model::diff::modify { 11 | 12 | struct SYNCSPIRIT_API lock_file_t final : cluster_diff_t { 13 | 14 | lock_file_t(const model::file_info_t &file, bool locked) noexcept; 15 | 16 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 17 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 18 | 19 | std::string folder_id; 20 | std::string device_id; 21 | std::string file_name; 22 | bool locked; 23 | }; 24 | 25 | } // namespace syncspirit::model::diff::modify 26 | -------------------------------------------------------------------------------- /src/model/diff/modify/mark_reachable.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2023 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/file_info.h" 8 | 9 | namespace syncspirit::model::diff::modify { 10 | 11 | struct SYNCSPIRIT_API mark_reachable_t final : cluster_diff_t { 12 | 13 | mark_reachable_t(const model::file_info_t &file, bool reachable) noexcept; 14 | 15 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 16 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 17 | 18 | std::string folder_id; 19 | std::string device_id; 20 | std::string file_name; 21 | bool reachable; 22 | }; 23 | 24 | } // namespace syncspirit::model::diff::modify 25 | -------------------------------------------------------------------------------- /src/model/diff/modify/remove_blocks.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "remove_blocks.h" 5 | 6 | #include "model/cluster.h" 7 | #include "model/diff/cluster_visitor.h" 8 | 9 | using namespace syncspirit::model::diff::modify; 10 | 11 | auto remove_blocks_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 12 | -> outcome::result { 13 | if (!keys.empty()) { 14 | LOG_TRACE(log, "applying remove_blocks_t, blocks = {}", keys.size()); 15 | auto &blocks = cluster.get_blocks(); 16 | for (auto &block_key : keys) { 17 | auto block_hash = block_key.substr(1); 18 | auto b = blocks.get(block_hash); 19 | blocks.remove(b); 20 | } 21 | } 22 | return applicator_t::apply_sibling(cluster, controller); 23 | } 24 | 25 | auto remove_blocks_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 26 | LOG_TRACE(log, "visiting remove_blocks_t"); 27 | return visitor(*this, custom); 28 | } 29 | -------------------------------------------------------------------------------- /src/model/diff/modify/remove_blocks.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "generic_remove.h" 7 | 8 | namespace syncspirit::model::diff::modify { 9 | 10 | struct SYNCSPIRIT_API remove_blocks_t final : generic_remove_t { 11 | using generic_remove_t::generic_remove_t; 12 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 13 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 14 | }; 15 | 16 | } // namespace syncspirit::model::diff::modify 17 | -------------------------------------------------------------------------------- /src/model/diff/modify/remove_files.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/device.h" 7 | #include "model/file_info.h" 8 | #include "model/misc/orphaned_blocks.h" 9 | #include "generic_remove.h" 10 | 11 | namespace syncspirit::model::diff::modify { 12 | 13 | struct SYNCSPIRIT_API remove_files_t final : generic_remove_t { 14 | using generic_remove_t::generic_remove_t; 15 | 16 | remove_files_t(const device_t &device, const file_infos_map_t &files, 17 | orphaned_blocks_t *orphaned_blocks = nullptr) noexcept; 18 | 19 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 20 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 21 | 22 | std::string device_id; 23 | keys_t folder_ids; 24 | }; 25 | 26 | } // namespace syncspirit::model::diff::modify 27 | -------------------------------------------------------------------------------- /src/model/diff/modify/remove_folder.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/folder.h" 7 | #include "model/diff/cluster_diff.h" 8 | #include "model/misc/sequencer.h" 9 | 10 | namespace syncspirit::model::diff::modify { 11 | 12 | struct SYNCSPIRIT_API remove_folder_t final : cluster_diff_t { 13 | using parent_t = cluster_diff_t; 14 | 15 | remove_folder_t(const model::cluster_t &cluster, model::sequencer_t &sequencer, 16 | const model::folder_t &folder) noexcept; 17 | 18 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 19 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 20 | 21 | std::string folder_id; 22 | std::string folder_key; 23 | }; 24 | 25 | } // namespace syncspirit::model::diff::modify 26 | -------------------------------------------------------------------------------- /src/model/diff/modify/remove_folder_infos.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "generic_remove.h" 7 | #include "model/folder_info.h" 8 | #include "model/misc/orphaned_blocks.h" 9 | 10 | namespace syncspirit::model::diff::modify { 11 | 12 | struct SYNCSPIRIT_API remove_folder_infos_t final : generic_remove_t { 13 | remove_folder_infos_t(const folder_infos_map_t &map, orphaned_blocks_t *orphaned_blocks = nullptr); 14 | 15 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 16 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 17 | }; 18 | 19 | } // namespace syncspirit::model::diff::modify 20 | -------------------------------------------------------------------------------- /src/model/diff/modify/remove_ignored_device.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/ignored_device.h" 8 | 9 | namespace syncspirit::model::diff::modify { 10 | 11 | struct SYNCSPIRIT_API remove_ignored_device_t final : cluster_diff_t { 12 | remove_ignored_device_t(const ignored_device_t &device) noexcept; 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 15 | 16 | std::string_view get_device_sha256() const noexcept; 17 | 18 | std::string device_key; 19 | }; 20 | 21 | } // namespace syncspirit::model::diff::modify 22 | -------------------------------------------------------------------------------- /src/model/diff/modify/remove_peer.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/device.h" 8 | #include "model/misc/orphaned_blocks.h" 9 | 10 | namespace syncspirit::model::diff::modify { 11 | 12 | struct SYNCSPIRIT_API remove_peer_t final : cluster_diff_t { 13 | using parent_t = cluster_diff_t; 14 | 15 | remove_peer_t(const cluster_t &cluster, const device_t &peer) noexcept; 16 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 17 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 18 | std::string_view get_peer_sha256() const noexcept; 19 | 20 | std::string peer_key; 21 | }; 22 | 23 | } // namespace syncspirit::model::diff::modify 24 | -------------------------------------------------------------------------------- /src/model/diff/modify/remove_pending_device.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/pending_device.h" 8 | 9 | namespace syncspirit::model::diff::modify { 10 | 11 | struct SYNCSPIRIT_API remove_pending_device_t final : cluster_diff_t { 12 | remove_pending_device_t(const pending_device_t &device) noexcept; 13 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 14 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 15 | 16 | std::string_view get_device_sha256() const noexcept; 17 | 18 | std::string device_key; 19 | }; 20 | 21 | } // namespace syncspirit::model::diff::modify 22 | -------------------------------------------------------------------------------- /src/model/diff/modify/remove_pending_folders.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "remove_pending_folders.h" 5 | 6 | #include "model/cluster.h" 7 | #include "model/diff/cluster_visitor.h" 8 | 9 | using namespace syncspirit::model::diff::modify; 10 | 11 | auto remove_pending_folders_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 12 | -> outcome::result { 13 | if (!keys.empty()) { 14 | LOG_TRACE(log, "applying remove_pending_folders_t, folders = {}", keys.size()); 15 | auto &map = cluster.get_pending_folders(); 16 | for (auto &key : keys) { 17 | auto folder = map.by_key(key); 18 | map.remove(folder); 19 | } 20 | } 21 | return applicator_t::apply_sibling(cluster, controller); 22 | } 23 | 24 | auto remove_pending_folders_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 25 | LOG_TRACE(log, "visiting remove_pending_folders_t"); 26 | return visitor(*this, custom); 27 | } 28 | -------------------------------------------------------------------------------- /src/model/diff/modify/remove_pending_folders.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "generic_remove.h" 7 | 8 | namespace syncspirit::model::diff::modify { 9 | 10 | struct SYNCSPIRIT_API remove_pending_folders_t final : generic_remove_t { 11 | using generic_remove_t::generic_remove_t; 12 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 13 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 14 | }; 15 | 16 | } // namespace syncspirit::model::diff::modify 17 | -------------------------------------------------------------------------------- /src/model/diff/modify/reset_folder_infos.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/diff/cluster_diff.h" 7 | #include "model/folder_info.h" 8 | #include "model/misc/orphaned_blocks.h" 9 | 10 | namespace syncspirit::model::diff::modify { 11 | 12 | struct SYNCSPIRIT_API reset_folder_infos_t final : cluster_diff_t { 13 | reset_folder_infos_t(const folder_infos_map_t &map, orphaned_blocks_t *orphaned_blocks = nullptr); 14 | 15 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 16 | }; 17 | 18 | } // namespace syncspirit::model::diff::modify 19 | -------------------------------------------------------------------------------- /src/model/diff/modify/share_folder.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2023 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/misc/sequencer.h" 8 | #include "model/device.h" 9 | #include "model/folder.h" 10 | #include "model/pending_folder.h" 11 | 12 | namespace syncspirit::model::diff::modify { 13 | 14 | struct SYNCSPIRIT_API share_folder_t final : cluster_diff_t { 15 | 16 | static outcome::result create(cluster_t &, sequencer_t &sequencer, const model::device_t &, 17 | const model::folder_t &folder) noexcept; 18 | 19 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 20 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 21 | 22 | std::string peer_id; 23 | std::string folder_id; 24 | 25 | private: 26 | share_folder_t(const bu::uuid &uuid, const model::device_t &peer, std::string_view folder_id, 27 | std::uint64_t index_id, model::pending_folder_ptr_t pf) noexcept; 28 | }; 29 | 30 | } // namespace syncspirit::model::diff::modify 31 | -------------------------------------------------------------------------------- /src/model/diff/modify/suspend_folder.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2025 Ivan Baidakou 3 | 4 | #include "suspend_folder.h" 5 | #include "model/cluster.h" 6 | #include "model/diff/cluster_visitor.h" 7 | 8 | using namespace syncspirit::model::diff::modify; 9 | 10 | suspend_folder_t::suspend_folder_t(const model::folder_t &folder) noexcept : folder_id{folder.get_id()} { 11 | LOG_DEBUG(log, "suspend_folder_t, folder_id = {}", folder_id); 12 | } 13 | 14 | auto suspend_folder_t::apply_impl(cluster_t &cluster, apply_controller_t &controller) const noexcept 15 | -> outcome::result { 16 | LOG_TRACE(log, "applying suspend_folder_t"); 17 | auto folder = cluster.get_folders().by_id(folder_id); 18 | folder->mark_suspended(true); 19 | return applicator_t::apply_impl(cluster, controller); 20 | } 21 | 22 | auto suspend_folder_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { 23 | LOG_TRACE(log, "visiting suspend_folder_t"); 24 | return visitor(*this, custom); 25 | } 26 | -------------------------------------------------------------------------------- /src/model/diff/modify/suspend_folder.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/folder.h" 8 | 9 | namespace syncspirit::model::diff::modify { 10 | 11 | struct SYNCSPIRIT_API suspend_folder_t final : cluster_diff_t { 12 | 13 | suspend_folder_t(const model::folder_t &folder) noexcept; 14 | 15 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 16 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 17 | 18 | std::string folder_id; 19 | 20 | private: 21 | }; 22 | 23 | } // namespace syncspirit::model::diff::modify 24 | -------------------------------------------------------------------------------- /src/model/diff/modify/unshare_folder.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/diff/cluster_diff.h" 7 | #include "model/folder_info.h" 8 | #include "model/misc/orphaned_blocks.h" 9 | 10 | namespace syncspirit::model::diff::modify { 11 | 12 | struct SYNCSPIRIT_API unshare_folder_t final : cluster_diff_t { 13 | using parent_t = cluster_diff_t; 14 | 15 | unshare_folder_t(const model::cluster_t &cluster, model::folder_info_t &folder, 16 | orphaned_blocks_t *orphaned_blocks = nullptr) noexcept; 17 | 18 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 19 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 20 | 21 | std::string peer_id; 22 | }; 23 | 24 | } // namespace syncspirit::model::diff::modify 25 | -------------------------------------------------------------------------------- /src/model/diff/modify/update_peer.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "structs.pb.h" 8 | #include "model/device_id.h" 9 | 10 | namespace syncspirit::model::diff::modify { 11 | 12 | struct SYNCSPIRIT_API update_peer_t final : cluster_diff_t { 13 | using parent_t = cluster_diff_t; 14 | 15 | update_peer_t(db::Device db, const model::device_id_t &device_id, const model::cluster_t &) noexcept; 16 | 17 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 18 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 19 | 20 | db::Device item; 21 | std::string peer_id; 22 | }; 23 | 24 | } // namespace syncspirit::model::diff::modify 25 | -------------------------------------------------------------------------------- /src/model/diff/modify/upsert_folder.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "model/device.h" 8 | #include "model/misc/sequencer.h" 9 | #include "structs.pb.h" 10 | 11 | namespace syncspirit::model::diff::modify { 12 | 13 | struct SYNCSPIRIT_API upsert_folder_t final : cluster_diff_t { 14 | 15 | static outcome::result create(const cluster_t &cluster, sequencer_t &sequencer, db::Folder db, 16 | std::uint64_t index_id) noexcept; 17 | 18 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 19 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 20 | 21 | bu::uuid uuid; 22 | db::Folder db; 23 | 24 | private: 25 | upsert_folder_t(sequencer_t &sequencer, bu::uuid uuid, db::Folder db, model::folder_info_ptr_t folder_info, 26 | const model::device_t &device, std::uint64_t index_id) noexcept; 27 | }; 28 | 29 | } // namespace syncspirit::model::diff::modify 30 | -------------------------------------------------------------------------------- /src/model/diff/modify/upsert_folder_info.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../cluster_diff.h" 7 | #include "structs.pb.h" 8 | #include "model/misc/uuid.h" 9 | 10 | namespace syncspirit::model::diff::modify { 11 | 12 | struct SYNCSPIRIT_API upsert_folder_info_t final : cluster_diff_t { 13 | using parent_t = cluster_diff_t; 14 | 15 | upsert_folder_info_t(const bu::uuid &uuid, std::string_view device_id, std::string_view folder_id, 16 | std::uint64_t index_id) noexcept; 17 | 18 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 19 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 20 | 21 | bu::uuid uuid; 22 | std::string device_id; 23 | std::string folder_id; 24 | std::uint64_t index_id; 25 | }; 26 | 27 | } // namespace syncspirit::model::diff::modify 28 | -------------------------------------------------------------------------------- /src/model/diff/peer/cluster_update.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "proto/bep_support.h" 7 | #include "model/device.h" 8 | #include "model/misc/sequencer.h" 9 | #include "model/diff/cluster_diff.h" 10 | 11 | namespace syncspirit::model::diff::peer { 12 | 13 | struct SYNCSPIRIT_API cluster_update_t final : cluster_diff_t { 14 | using message_t = proto::ClusterConfig; 15 | using parent_t = cluster_diff_t; 16 | 17 | static outcome::result create(const cluster_t &cluster, sequencer_t &sequencer, 18 | const model::device_t &source, const message_t &message) noexcept; 19 | 20 | outcome::result apply_impl(cluster_t &, apply_controller_t &) const noexcept override; 21 | outcome::result visit(cluster_visitor_t &, void *) const noexcept override; 22 | 23 | cluster_update_t(const cluster_t &cluster, sequencer_t &sequencer, const model::device_t &source, 24 | const message_t &message) noexcept; 25 | 26 | std::string peer_id; 27 | }; 28 | 29 | } // namespace syncspirit::model::diff::peer 30 | -------------------------------------------------------------------------------- /src/model/ignored_device.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "ignored_device.h" 5 | 6 | namespace syncspirit::model { 7 | 8 | template <> SYNCSPIRIT_API std::string_view get_index<0>(const ignored_device_ptr_t &item) noexcept { 9 | return item->get_device_id().get_sha256(); 10 | } 11 | 12 | } // namespace syncspirit::model 13 | -------------------------------------------------------------------------------- /src/model/ignored_device.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "some_device.h" 7 | #include "db/prefix.h" 8 | 9 | namespace syncspirit::model { 10 | 11 | using ignored_device_t = some_device_t<(char)db::prefix::ignored_device>; 12 | using ignored_devices_map_t = typename ignored_device_t::map_t; 13 | using ignored_device_ptr_t = typename ignored_device_t::ptr_t; 14 | 15 | }; // namespace syncspirit::model 16 | -------------------------------------------------------------------------------- /src/model/messages.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include "cluster.h" 9 | #include "diff/cluster_diff.h" 10 | 11 | namespace syncspirit::model { 12 | 13 | namespace r = rotor; 14 | 15 | namespace payload { 16 | 17 | struct model_response_t { 18 | model::cluster_ptr_t cluster; 19 | }; 20 | 21 | struct model_request_t { 22 | using response_t = model_response_t; 23 | }; 24 | 25 | struct model_update_t { 26 | model::diff::cluster_diff_ptr_t diff; 27 | const void *custom; 28 | }; 29 | 30 | struct ui_ready_t {}; 31 | 32 | } // namespace payload 33 | 34 | namespace message { 35 | 36 | using model_update_t = r::message_t; 37 | using ui_ready_t = r::message_t; 38 | 39 | using model_request_t = r::request_traits_t::request::message_t; 40 | using model_response_t = r::request_traits_t::response::message_t; 41 | 42 | } // namespace message 43 | 44 | } // namespace syncspirit::model 45 | -------------------------------------------------------------------------------- /src/model/misc/arc.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace syncspirit::model { 10 | 11 | template struct arc_base_t : boost::intrusive_ref_counter { 12 | using parent_t = boost::intrusive_ref_counter; 13 | using parent_t::parent_t; 14 | arc_base_t(const arc_base_t &) = delete; 15 | }; 16 | 17 | template using intrusive_ptr_t = boost::intrusive_ptr; 18 | 19 | } // namespace syncspirit::model 20 | -------------------------------------------------------------------------------- /src/model/misc/augmentation.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "arc.hpp" 7 | 8 | namespace syncspirit::model { 9 | 10 | struct augmentation_t : arc_base_t { 11 | augmentation_t() = default; 12 | inline virtual void on_update() noexcept {}; 13 | inline virtual void on_delete() noexcept {}; 14 | virtual ~augmentation_t() = default; 15 | }; 16 | 17 | using augmentation_ptr_t = intrusive_ptr_t; 18 | 19 | template struct augmentable_t : arc_base_t { 20 | 21 | ~augmentable_t() { 22 | if (extension) { 23 | extension->on_delete(); 24 | } 25 | } 26 | 27 | void set_augmentation(augmentation_t &value) noexcept { extension = &value; } 28 | void set_augmentation(augmentation_ptr_t value) noexcept { extension = std::move(value); } 29 | 30 | augmentation_ptr_t get_augmentation() noexcept { return extension; } 31 | 32 | void notify_update() noexcept { 33 | if (extension) { 34 | extension->on_update(); 35 | } 36 | } 37 | 38 | augmentation_ptr_t extension; 39 | }; 40 | 41 | } // namespace syncspirit::model 42 | -------------------------------------------------------------------------------- /src/model/misc/block_iterator.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "arc.hpp" 8 | #include "model/block_info.h" 9 | #include "syncspirit-export.h" 10 | 11 | namespace syncspirit::model { 12 | 13 | struct folder_info_t; 14 | struct file_info_t; 15 | 16 | struct SYNCSPIRIT_API blocks_iterator_t : arc_base_t { 17 | using blocks_t = std::vector; 18 | 19 | blocks_iterator_t(file_info_t &source) noexcept; 20 | operator bool() const noexcept; 21 | 22 | file_block_t next() noexcept; 23 | file_info_t *get_source() noexcept; 24 | 25 | private: 26 | void prepare() noexcept; 27 | void advance() noexcept; 28 | size_t i = 0; 29 | std::int64_t sequence; 30 | file_info_ptr_t source; 31 | }; 32 | 33 | using block_iterator_ptr_t = intrusive_ptr_t; 34 | 35 | } // namespace syncspirit::model 36 | -------------------------------------------------------------------------------- /src/model/misc/file_block.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #include "file_block.h" 5 | #include "../block_info.h" 6 | #include "../file_info.h" 7 | 8 | namespace syncspirit::model { 9 | 10 | file_block_t::file_block_t(block_info_t *block, file_info_t *file_info_, std::size_t block_index_) noexcept 11 | : block_info{block}, file_info{file_info_}, block_idx{block_index_}, local{block->local_file()} {} 12 | 13 | bool file_block_t::matches(const block_info_t *block, const file_info_t *file) noexcept { 14 | return block_info == block && file_info == file; 15 | } 16 | 17 | file_block_t &file_block_t::operator=(const file_block_t &other) noexcept { 18 | block_info = other.block_info; 19 | file_info = other.file_info; 20 | block_idx = other.block_idx; 21 | local = other.local; 22 | return *this; 23 | } 24 | 25 | file_block_t::operator bool() const noexcept { return (bool)file_info; } 26 | 27 | size_t file_block_t::get_offset() const noexcept { 28 | assert(file_info); 29 | return file_info->get_block_offset(block_idx); 30 | } 31 | 32 | } // namespace syncspirit::model 33 | -------------------------------------------------------------------------------- /src/model/misc/orphaned_blocks.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "orphaned_blocks.h" 5 | #include "model/file_info.h" 6 | 7 | using namespace syncspirit::model; 8 | 9 | void orphaned_blocks_t::record(file_info_t &file) { file_for_removal.emplace(&file); } 10 | 11 | auto orphaned_blocks_t::deduce() const -> set_t { 12 | set_t processed; 13 | set_t r; 14 | for (auto &file : file_for_removal) { 15 | auto &blocks = file->get_blocks(); 16 | for (auto &b : blocks) { 17 | auto key = b->get_key(); 18 | if (processed.contains(b->get_key())) { 19 | continue; 20 | } 21 | auto &file_blocks = b->get_file_blocks(); 22 | auto usages = file_blocks.size(); 23 | for (auto &fb : file_blocks) { 24 | auto target_file = file_info_ptr_t(fb.file()); 25 | auto it = file_for_removal.find(target_file); 26 | if (it != file_for_removal.end()) { 27 | --usages; 28 | } 29 | } 30 | if (!usages) { 31 | r.emplace(std::string{key}); 32 | } 33 | processed.emplace(std::string{key}); 34 | } 35 | } 36 | return r; 37 | } 38 | -------------------------------------------------------------------------------- /src/model/misc/orphaned_blocks.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/file_info.h" 7 | #include "utils/string_comparator.hpp" 8 | #include 9 | 10 | namespace syncspirit::model { 11 | 12 | struct SYNCSPIRIT_API orphaned_blocks_t { 13 | using set_t = std::set; 14 | 15 | void record(file_info_t &); 16 | set_t deduce() const; 17 | 18 | file_infos_set_t file_for_removal; 19 | }; 20 | 21 | } // namespace syncspirit::model 22 | -------------------------------------------------------------------------------- /src/model/misc/resolver.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/file_info.h" 7 | #include "syncspirit-export.h" 8 | 9 | namespace syncspirit::model { 10 | 11 | enum class advance_action_t { 12 | ignore = 0, 13 | remote_copy, 14 | local_update, 15 | resolve_remote_win, 16 | }; 17 | 18 | advance_action_t SYNCSPIRIT_API resolve(const file_info_t &remote) noexcept; 19 | 20 | } // namespace syncspirit::model 21 | -------------------------------------------------------------------------------- /src/model/misc/sequencer.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "sequencer.h" 5 | 6 | namespace syncspirit::model { 7 | 8 | sequencer_t::sequencer_t(size_t seed) noexcept : uuid_generator(rng_engine) { rng_engine.seed(seed); } 9 | 10 | bu::uuid sequencer_t::next_uuid() noexcept { 11 | auto lock = lock_t(mutex); 12 | return uuid_generator(); 13 | } 14 | 15 | uint64_t sequencer_t::next_uint64() noexcept { 16 | auto lock = lock_t(mutex); 17 | return uint64_generator(rng_engine); 18 | } 19 | 20 | auto make_sequencer(size_t seed) -> sequencer_ptr_t { return new sequencer_t(seed); } 21 | 22 | } // namespace syncspirit::model 23 | -------------------------------------------------------------------------------- /src/model/misc/sequencer.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "arc.hpp" 7 | #include "uuid.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace syncspirit::model { 14 | 15 | using rng_engine_t = std::mt19937; 16 | using uuid_generator_t = boost::uuids::basic_random_generator; 17 | using uint64_generator_t = std::uniform_int_distribution; 18 | 19 | struct SYNCSPIRIT_API sequencer_t : arc_base_t { 20 | sequencer_t(size_t seed) noexcept; 21 | sequencer_t(sequencer_t &&) = delete; 22 | sequencer_t(const sequencer_t &) = delete; 23 | 24 | bu::uuid next_uuid() noexcept; 25 | uint64_t next_uint64() noexcept; 26 | 27 | private: 28 | using mutex_t = std::mutex; 29 | using lock_t = std::unique_lock; 30 | mutex_t mutex; 31 | rng_engine_t rng_engine; 32 | uuid_generator_t uuid_generator; 33 | uint64_generator_t uint64_generator; 34 | }; 35 | 36 | using sequencer_ptr_t = intrusive_ptr_t; 37 | 38 | auto SYNCSPIRIT_API make_sequencer(size_t seed) -> sequencer_ptr_t; 39 | 40 | } // namespace syncspirit::model 41 | -------------------------------------------------------------------------------- /src/model/misc/string_map.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "map.hpp" 7 | 8 | namespace syncspirit::model { 9 | 10 | using string_map = syncspirit::model::generic_map_t; 11 | 12 | template <> inline std::string_view get_index<0>(const std::string &item) noexcept { return item; } 13 | 14 | } // namespace syncspirit::model 15 | -------------------------------------------------------------------------------- /src/model/misc/upnp.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "../../utils/uri.h" 8 | 9 | namespace syncspirit::model { 10 | 11 | struct discovery_result { 12 | utils::uri_ptr_t location; 13 | std::string search_target; 14 | std::string usn; 15 | }; 16 | 17 | struct igd_result { 18 | std::string control_path; 19 | std::string description_path; 20 | }; 21 | 22 | } // namespace syncspirit::model 23 | -------------------------------------------------------------------------------- /src/model/misc/uuid.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #include "uuid.h" 5 | #include 6 | 7 | namespace syncspirit::model { 8 | 9 | void assign(bu::uuid &uuid, std::string_view source) noexcept { 10 | assert(source.size() == uuid.size()); 11 | auto data = (const uint8_t *)source.data(); 12 | std::copy(data, data + source.size(), &uuid.data[0]); 13 | } 14 | 15 | } // namespace syncspirit::model 16 | -------------------------------------------------------------------------------- /src/model/misc/uuid.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include "syncspirit-export.h" 9 | 10 | namespace syncspirit::model { 11 | 12 | namespace bu = boost::uuids; 13 | 14 | static const constexpr size_t uuid_length = 16; 15 | 16 | SYNCSPIRIT_API void assign(bu::uuid &, std::string_view source) noexcept; 17 | 18 | } // namespace syncspirit::model 19 | -------------------------------------------------------------------------------- /src/model/pending_device.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "pending_device.h" 5 | 6 | namespace syncspirit::model { 7 | 8 | template <> SYNCSPIRIT_API std::string_view get_index<0>(const pending_device_ptr_t &item) noexcept { 9 | return item->get_device_id().get_sha256(); 10 | } 11 | 12 | } // namespace syncspirit::model 13 | -------------------------------------------------------------------------------- /src/model/pending_device.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "some_device.h" 7 | #include "db/prefix.h" 8 | 9 | namespace syncspirit::model { 10 | 11 | using pending_device_t = some_device_t<(char)db::prefix::pending_device>; 12 | using pending_devices_map_t = typename pending_device_t::map_t; 13 | using pending_device_ptr_t = typename pending_device_t::ptr_t; 14 | 15 | }; // namespace syncspirit::model 16 | -------------------------------------------------------------------------------- /src/model/version.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "misc/arc.hpp" 7 | #include "syncspirit-export.h" 8 | #include "bep.pb.h" 9 | #include 10 | 11 | namespace syncspirit::model { 12 | 13 | struct device_t; 14 | 15 | struct SYNCSPIRIT_API version_t final : arc_base_t { 16 | version_t(const proto::Vector &) noexcept; 17 | version_t(const device_t &) noexcept; 18 | 19 | proto::Vector as_proto() const noexcept; 20 | void to_proto(proto::Vector &) const noexcept; 21 | 22 | proto::Counter &get_best() noexcept; 23 | const proto::Counter &get_best() const noexcept; 24 | void update(const device_t &) noexcept; 25 | const proto::Counter &get_counter(size_t) noexcept; 26 | bool contains(const version_t &other) noexcept; 27 | bool identical_to(const version_t &) noexcept; 28 | size_t counters_size() const; 29 | 30 | private: 31 | using counters_t = std::vector; 32 | counters_t counters; 33 | size_t best_index; 34 | }; 35 | 36 | using version_ptr_t = intrusive_ptr_t; 37 | 38 | } // namespace syncspirit::model 39 | -------------------------------------------------------------------------------- /src/net/names.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #include "names.h" 5 | 6 | using namespace syncspirit::net; 7 | 8 | const char *names::peer_supervisor = "net.peer_supervisor"; 9 | const char *names::coordinator = "net.coordinator"; 10 | const char *names::sink = "net.sink"; 11 | const char *names::resolver = "net.resolver"; 12 | const char *names::http10 = "net.http10"; 13 | const char *names::http11_gda = "net.http11_gda"; 14 | const char *names::http11_relay = "net.http11_relay"; 15 | const char *names::hasher_proxy = "net.hasher_proxy"; 16 | const char *names::fs_actor = "fs.actor"; 17 | const char *names::fs_scanner = "fs.scanner"; 18 | const char *names::fs_scheduler = "fs.scheduler"; 19 | -------------------------------------------------------------------------------- /src/net/names.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "syncspirit-export.h" 7 | 8 | namespace syncspirit { 9 | namespace net { 10 | 11 | struct SYNCSPIRIT_API names { 12 | static const char *peer_supervisor; 13 | static const char *coordinator; 14 | static const char *sink; 15 | static const char *resolver; 16 | static const char *http10; 17 | static const char *http11_gda; 18 | static const char *http11_relay; 19 | static const char *hasher_proxy; 20 | static const char *fs_actor; 21 | static const char *fs_scanner; 22 | static const char *fs_scheduler; 23 | }; 24 | 25 | } // namespace net 26 | }; // namespace syncspirit 27 | -------------------------------------------------------------------------------- /src/net/sink_actor.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "model/messages.h" 8 | 9 | namespace syncspirit { 10 | namespace net { 11 | 12 | namespace r = rotor; 13 | 14 | struct SYNCSPIRIT_API sink_actor_t : public r::actor_base_t { 15 | using r::actor_base_t::actor_base_t; 16 | void configure(r::plugin::plugin_base_t &plugin) noexcept override; 17 | void on_start() noexcept override; 18 | 19 | private: 20 | void on_model_sink(model::message::model_update_t &message) noexcept; 21 | 22 | utils::logger_t log; 23 | r::address_ptr_t coordinator; 24 | }; 25 | 26 | } // namespace net 27 | } // namespace syncspirit 28 | -------------------------------------------------------------------------------- /src/proto/discovery_support.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | #include "utils/uri.h" 6 | #include "model/device_id.h" 7 | #include "syncspirit-export.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace syncspirit::proto { 14 | 15 | namespace outcome = boost::outcome_v2; 16 | namespace asio = boost::asio; 17 | namespace http = boost::beast::http; 18 | 19 | SYNCSPIRIT_API outcome::result 20 | make_announce_request(fmt::memory_buffer &buff, const utils::uri_ptr_t &announce_uri, 21 | const utils::uri_container_t &listening_uris) noexcept; 22 | SYNCSPIRIT_API outcome::result make_discovery_request(fmt::memory_buffer &buff, 23 | const utils::uri_ptr_t &announce_uri, 24 | const model::device_id_t device_id) noexcept; 25 | 26 | SYNCSPIRIT_API outcome::result parse_announce(http::response &res) noexcept; 27 | 28 | SYNCSPIRIT_API outcome::result parse_contact(http::response &res) noexcept; 29 | 30 | } // namespace syncspirit::proto 31 | -------------------------------------------------------------------------------- /src/proto/luhn32.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "syncspirit-export.h" 8 | 9 | namespace syncspirit::proto { 10 | 11 | struct SYNCSPIRIT_API luhn32 { 12 | static char calculate(std::string_view in) noexcept; 13 | static bool validate(std::string_view in) noexcept; 14 | }; 15 | 16 | } // namespace syncspirit::proto 17 | -------------------------------------------------------------------------------- /src/transport/http.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | #include "base.h" 6 | #include "stream.h" 7 | #include 8 | 9 | namespace syncspirit::transport { 10 | 11 | namespace http = boost::beast::http; 12 | 13 | struct http_interface_t { 14 | using rx_buff_t = boost::beast::flat_buffer; 15 | using response_t = http::response; 16 | virtual void async_read(rx_buff_t &rx_buff, response_t &response, io_fn_t &on_read, 17 | error_fn_t &on_error) noexcept = 0; 18 | }; 19 | 20 | struct SYNCSPIRIT_API http_base_t : model::arc_base_t, http_interface_t, stream_interface_t { 21 | virtual ~http_base_t() = default; 22 | }; 23 | 24 | using http_sp_t = model::intrusive_ptr_t; 25 | 26 | http_sp_t initiate_http(transport_config_t &config) noexcept; 27 | 28 | } // namespace syncspirit::transport 29 | -------------------------------------------------------------------------------- /src/ui-daemon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.19) 2 | 3 | add_executable(syncspirit-daemon 4 | command/add_folder.cpp 5 | command/add_peer.cpp 6 | command/inactivate.cpp 7 | command/pair_iterator.cpp 8 | command/share_folder.cpp 9 | command.cpp 10 | error_code.cpp 11 | governor_actor.cpp 12 | main.cpp 13 | ) 14 | 15 | target_link_libraries(syncspirit-daemon 16 | syncspirit_core 17 | $<$:ws2_32> 18 | $<$:wsock32> 19 | ) 20 | target_include_directories(syncspirit-daemon PUBLIC ${syncspirit_SOURCE_DIR}/src) 21 | install_executable("syncspirit-daemon") 22 | 23 | if (("${CMAKE_BUILD_TYPE}" STREQUAL "Release") AND (NOT WIN32)) 24 | include(CheckIPOSupported) 25 | check_ipo_supported(RESULT supported OUTPUT error) 26 | if( supported ) 27 | message(STATUS "IPO / LTO enabled for the syncspirit-daemon") 28 | set_property(TARGET syncspirit-daemon PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) 29 | else() 30 | message(STATUS "IPO / LTO not supported") 31 | endif() 32 | endif() 33 | 34 | if (CMAKE_BUILD_TYPE MATCHES "^([Rr]elease)|(MinSizeRel)") 35 | set_target_properties(syncspirit-daemon PROPERTIES LINK_FLAGS -s) 36 | endif() 37 | -------------------------------------------------------------------------------- /src/ui-daemon/command.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #include "command.h" 5 | #include "error_code.h" 6 | #include "command/add_peer.h" 7 | #include "command/add_folder.h" 8 | #include "command/inactivate.h" 9 | #include "command/share_folder.h" 10 | 11 | namespace syncspirit::daemon { 12 | 13 | outcome::result command_t::parse(std::string_view in) noexcept { 14 | auto colon = in.find(":"); 15 | if (colon == in.npos) { 16 | return make_error_code(error_code_t::command_is_missing); 17 | } 18 | auto cmd = in.substr(0, colon); 19 | if (cmd == "add_peer") { 20 | return command::add_peer_t::construct(in.substr(colon + 1)); 21 | } else if (cmd == "add_folder") { 22 | return command::add_folder_t::construct(in.substr(colon + 1)); 23 | } else if (cmd == "share") { 24 | return command::share_folder_t::construct(in.substr(colon + 1)); 25 | } else if (cmd == "inactivate") { 26 | return command::inactivate_t::construct(in.substr(colon + 1)); 27 | } 28 | return make_error_code(error_code_t::unknown_command); 29 | } 30 | 31 | void command_t::finish() noexcept {} 32 | 33 | } // namespace syncspirit::daemon 34 | -------------------------------------------------------------------------------- /src/ui-daemon/command.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include "../utils/log.h" 10 | #include "utils/format.hpp" 11 | 12 | namespace syncspirit::daemon { 13 | 14 | namespace outcome = boost::outcome_v2; 15 | 16 | struct governor_actor_t; 17 | 18 | struct command_t; 19 | using command_ptr_t = std::unique_ptr; 20 | 21 | struct command_t { 22 | virtual ~command_t() = default; 23 | virtual bool execute(governor_actor_t &) noexcept = 0; 24 | virtual void finish() noexcept; 25 | 26 | static outcome::result parse(std::string_view) noexcept; 27 | utils::logger_t log; 28 | }; 29 | 30 | using Commands = std::list; 31 | 32 | } // namespace syncspirit::daemon 33 | -------------------------------------------------------------------------------- /src/ui-daemon/command/add_folder.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../command.h" 7 | #include "model/folder.h" 8 | 9 | namespace syncspirit::daemon::command { 10 | 11 | struct add_folder_t final : command_t { 12 | bool execute(governor_actor_t &) noexcept override; 13 | static outcome::result construct(std::string_view in) noexcept; 14 | 15 | inline add_folder_t() noexcept = default; 16 | inline add_folder_t(db::Folder &&f) noexcept : folder{std::move(f)} {} 17 | 18 | private: 19 | db::Folder folder; 20 | }; 21 | 22 | } // namespace syncspirit::daemon::command 23 | -------------------------------------------------------------------------------- /src/ui-daemon/command/add_peer.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../command.h" 7 | #include "model/device_id.h" 8 | 9 | namespace syncspirit::daemon::command { 10 | 11 | struct add_peer_t final : command_t { 12 | static outcome::result construct(std::string_view in) noexcept; 13 | bool execute(governor_actor_t &) noexcept override; 14 | 15 | inline add_peer_t() noexcept = default; 16 | inline add_peer_t(model::device_id_t peer_, std::string_view label_) noexcept : peer{peer_}, label(label_) {} 17 | 18 | private: 19 | model::device_id_t peer; 20 | std::string label; 21 | }; 22 | 23 | } // namespace syncspirit::daemon::command 24 | -------------------------------------------------------------------------------- /src/ui-daemon/command/inactivate.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #include "inactivate.h" 5 | #include "../governor_actor.h" 6 | #include "../error_code.h" 7 | #include "utils/error_code.h" 8 | #include 9 | 10 | namespace syncspirit::daemon::command { 11 | 12 | outcome::result inactivate_t::construct(std::string_view in) noexcept { 13 | std::uint32_t seconds; 14 | auto pair = std::from_chars(in.data(), in.data() + in.size(), seconds); 15 | if (pair.ec != std::errc()) { 16 | auto ec = std::make_error_code(pair.ec); 17 | return utils::adapt(ec); 18 | } 19 | return std::make_unique(seconds); 20 | } 21 | 22 | bool inactivate_t::execute(governor_actor_t &actor) noexcept { 23 | if (seconds) { 24 | actor.inactivity_seconds = seconds; 25 | actor.track_inactivity(); 26 | } 27 | return true; 28 | } 29 | 30 | } // namespace syncspirit::daemon::command 31 | -------------------------------------------------------------------------------- /src/ui-daemon/command/inactivate.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../command.h" 7 | #include "model/device_id.h" 8 | 9 | namespace syncspirit::daemon::command { 10 | 11 | struct inactivate_t final : command_t { 12 | static outcome::result construct(std::string_view in) noexcept; 13 | bool execute(governor_actor_t &) noexcept override; 14 | 15 | inline inactivate_t() noexcept = default; 16 | inline inactivate_t(std::uint32_t seconds_) noexcept : seconds{seconds_} {} 17 | 18 | private: 19 | std::uint32_t seconds; 20 | }; 21 | 22 | } // namespace syncspirit::daemon::command 23 | -------------------------------------------------------------------------------- /src/ui-daemon/command/pair_iterator.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #include "pair_iterator.h" 5 | 6 | using namespace syncspirit::daemon::command; 7 | 8 | std::optional pair_iterator_t::next(bool skip_colon) noexcept { 9 | auto colon = in.size(); 10 | if (!skip_colon) { 11 | auto colon_pos = in.find(":"); 12 | if (colon_pos != in.npos) { 13 | colon = colon_pos; 14 | } 15 | } 16 | 17 | auto it = in.substr(0, colon); 18 | auto eq = it.find("="); 19 | if (eq == it.npos) { 20 | return {}; 21 | } 22 | 23 | auto f = in.substr(0, eq); 24 | auto s = in.substr(eq + 1, colon - (eq + 1)); 25 | if (colon < in.size()) { 26 | in = in.substr(colon + 1); 27 | } else { 28 | in = ""; 29 | } 30 | return pair_t{f, s}; 31 | } 32 | -------------------------------------------------------------------------------- /src/ui-daemon/command/pair_iterator.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace syncspirit::daemon::command { 11 | 12 | struct pair_iterator_t { 13 | using pair_t = std::pair; 14 | 15 | inline pair_iterator_t(std::string_view in_) noexcept : in(in_) {} 16 | 17 | std::optional next(bool skip_colon = false) noexcept; 18 | std::string_view in; 19 | }; 20 | 21 | } // namespace syncspirit::daemon::command 22 | -------------------------------------------------------------------------------- /src/ui-daemon/command/share_folder.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../command.h" 7 | #include "../../model/folder.h" 8 | 9 | namespace syncspirit::daemon::command { 10 | 11 | struct share_folder_t final : command_t { 12 | bool execute(governor_actor_t &) noexcept override; 13 | static outcome::result construct(std::string_view in) noexcept; 14 | 15 | inline share_folder_t() noexcept = default; 16 | template 17 | inline share_folder_t(Folder &&f, Peer &&p) noexcept 18 | : folder{std::forward(f)}, peer{std::forward(p)} {} 19 | 20 | private: 21 | std::string folder; 22 | std::string peer; 23 | }; 24 | 25 | } // namespace syncspirit::daemon::command 26 | -------------------------------------------------------------------------------- /src/ui-daemon/error_code.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace syncspirit::daemon { 9 | 10 | enum class error_code_t { 11 | success = 0, 12 | command_is_missing, 13 | unknown_command, 14 | invalid_device_id, 15 | missing_device_label, 16 | missing_folder_label, 17 | missing_folder, 18 | missing_device, 19 | missing_folder_path, 20 | incorrect_number, 21 | }; 22 | 23 | namespace detail { 24 | 25 | class error_code_category : public boost::system::error_category { 26 | virtual const char *name() const noexcept override; 27 | virtual std::string message(int c) const override; 28 | }; 29 | } // namespace detail 30 | 31 | const detail::error_code_category &error_code_category(); 32 | 33 | inline boost::system::error_code make_error_code(error_code_t e) { 34 | return {static_cast(e), error_code_category()}; 35 | } 36 | 37 | } // namespace syncspirit::daemon 38 | 39 | namespace boost { 40 | namespace system { 41 | 42 | template <> struct is_error_code_enum : std::true_type { 43 | static const bool value = true; 44 | }; 45 | } // namespace system 46 | } // namespace boost 47 | -------------------------------------------------------------------------------- /src/ui-fltk/app-manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | UTF-8 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/ui-fltk/app.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #define ID_SYNCSPIRIT_ICON 1000 7 | -------------------------------------------------------------------------------- /src/ui-fltk/app.rc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2025 Ivan Baidakou 3 | 4 | #include // RT_MANIFEST 5 | #include "app.h" 6 | // CREATEPROCESS_MANIFEST_RESOURCE_ID is defined as 1 cast to `char*`; not directly usable here. 7 | 8 | 1 RT_MANIFEST "app-manifest.xml" 9 | ID_SYNCSPIRIT_ICON ICON "syncspirit-fltk.ico" 10 | -------------------------------------------------------------------------------- /src/ui-fltk/config/category.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "property.h" 7 | #include 8 | 9 | namespace syncspirit::fltk::config { 10 | 11 | using properties_t = std::vector; 12 | 13 | struct category_t : boost::intrusive_ref_counter { 14 | using parent_t = boost::intrusive_ref_counter; 15 | 16 | category_t(std::string label, std::string explanation, properties_t properties); 17 | virtual ~category_t() = default; 18 | const std::string &get_label() const; 19 | const std::string &get_explanation() const; 20 | const properties_t &get_properties() const; 21 | 22 | private: 23 | std::string label; 24 | std::string explanation; 25 | properties_t properties; 26 | }; 27 | 28 | using category_ptr_t = boost::intrusive_ptr; 29 | using categories_t = std::vector; 30 | 31 | auto reflect(const main_cfg_t &config, const main_cfg_t &default_config) -> categories_t; 32 | auto reflect(const categories_t &, const main_cfg_t &default_config) -> main_cfg_t; 33 | bool is_valid(const categories_t &); 34 | 35 | } // namespace syncspirit::fltk::config 36 | -------------------------------------------------------------------------------- /src/ui-fltk/config/control.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../tree_item.h" 7 | #include "category.h" 8 | #include 9 | 10 | namespace syncspirit::fltk::config { 11 | 12 | struct control_t : contentable_t { 13 | using parent_t = contentable_t; 14 | 15 | control_t(tree_item_t &tree_item, int x, int y, int w, int h); 16 | 17 | void on_reset(); 18 | void on_save(); 19 | void on_setting_modify(); 20 | 21 | tree_item_t &tree_item; 22 | categories_t categories; 23 | main_cfg_t default_cfg; 24 | }; 25 | 26 | } // namespace syncspirit::fltk::config 27 | -------------------------------------------------------------------------------- /src/ui-fltk/content.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "content.h" 5 | 6 | using namespace syncspirit::fltk; 7 | 8 | void content_t::refresh() {} 9 | void content_t::reset() {} 10 | bool content_t::store(void *) { return true; } 11 | -------------------------------------------------------------------------------- /src/ui-fltk/content.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace syncspirit::fltk { 11 | 12 | struct content_t { 13 | virtual Fl_Widget *get_widget() = 0; 14 | 15 | virtual void refresh(); 16 | virtual void reset(); 17 | virtual bool store(void *); 18 | 19 | virtual ~content_t() = default; 20 | }; 21 | 22 | template struct contentable_t : T, content_t { 23 | using T::T; 24 | 25 | Fl_Widget *get_widget() override { return this; } 26 | }; 27 | 28 | template struct contentable_t> : T, content_t { 29 | using T::T; 30 | 31 | Fl_Widget *get_widget() override { return this; } 32 | 33 | void refresh() override { 34 | for (int i = 0; i < this->children(); ++i) { 35 | auto child = this->child(i); 36 | if (auto content = dynamic_cast(child)) { 37 | content->refresh(); 38 | } 39 | } 40 | } 41 | }; 42 | 43 | } // namespace syncspirit::fltk 44 | -------------------------------------------------------------------------------- /src/ui-fltk/content/remote_file_table.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../static_table.h" 7 | #include "../tree_item.h" 8 | 9 | namespace syncspirit::fltk::content { 10 | 11 | struct remote_file_table_t : static_table_t { 12 | using parent_t = static_table_t; 13 | 14 | remote_file_table_t(tree_item_t &container_, int x, int y, int w, int h); 15 | 16 | void refresh() override; 17 | 18 | private: 19 | tree_item_t &container; 20 | static_string_provider_ptr_t name_cell; 21 | static_string_provider_ptr_t modified_cell; 22 | static_string_provider_ptr_t sequence_cell; 23 | static_string_provider_ptr_t size_cell; 24 | static_string_provider_ptr_t block_size_cell; 25 | static_string_provider_ptr_t blocks_cell; 26 | static_string_provider_ptr_t permissions_cell; 27 | static_string_provider_ptr_t modified_s_cell; 28 | static_string_provider_ptr_t modified_ns_cell; 29 | static_string_provider_ptr_t modified_by_cell; 30 | static_string_provider_ptr_t symlink_target_cell; 31 | static_string_provider_ptr_t entries_cell; 32 | static_string_provider_ptr_t entries_size_cell; 33 | static_string_provider_ptr_t local_entries_cell; 34 | size_t displayed_versions; 35 | }; 36 | 37 | } // namespace syncspirit::fltk::content 38 | -------------------------------------------------------------------------------- /src/ui-fltk/entry_stats.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace syncspirit::fltk { 9 | 10 | struct entry_stats_t { 11 | inline entry_stats_t() : sequence{0}, entries{0}, scanned_entries{0}, entries_size{0}, local_mark{false} {} 12 | std::int64_t sequence; 13 | std::int64_t entries; 14 | std::int64_t scanned_entries; 15 | std::int64_t entries_size; 16 | bool local_mark; 17 | }; 18 | 19 | } // namespace syncspirit::fltk 20 | -------------------------------------------------------------------------------- /src/ui-fltk/log_colors.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "log_colors.h" 5 | 6 | namespace syncspirit::fltk { 7 | 8 | color_array_t log_colors = { 9 | fl_rgb_color(220, 255, 220), fl_rgb_color(240, 255, 240), // trace 10 | fl_rgb_color(210, 245, 255), fl_rgb_color(230, 250, 255), // debug 11 | fl_rgb_color(245, 245, 245), fl_rgb_color(255, 255, 255), // info 12 | fl_rgb_color(255, 250, 200), fl_rgb_color(255, 250, 220), // warn 13 | fl_rgb_color(255, 220, 220), fl_rgb_color(255, 240, 240), // error 14 | fl_rgb_color(255, 220, 255), fl_rgb_color(255, 240, 255) // critical 15 | }; 16 | 17 | Fl_Color table_selection_color = FL_GREEN; 18 | 19 | } // namespace syncspirit::fltk 20 | -------------------------------------------------------------------------------- /src/ui-fltk/log_colors.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace syncspirit::fltk { 10 | 11 | using color_array_t = std::array; 12 | 13 | extern color_array_t log_colors; 14 | extern Fl_Color table_selection_color; 15 | 16 | } // namespace syncspirit::fltk 17 | -------------------------------------------------------------------------------- /src/ui-fltk/log_sink.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "utils/log.h" 7 | #include "log_utils.h" 8 | #include 9 | #include 10 | 11 | namespace syncspirit::fltk { 12 | 13 | struct base_sink_t : spdlog::sinks::sink { 14 | base_sink_t(); 15 | 16 | void log(const spdlog::details::log_msg &msg) override; 17 | 18 | void flush() override; 19 | void set_pattern(const std::string &) override; 20 | void set_formatter(std::unique_ptr) override; 21 | virtual void forward(log_record_ptr_t) = 0; 22 | 23 | private: 24 | spdlog::pattern_formatter date_formatter; 25 | }; 26 | 27 | struct im_memory_sink_t final : base_sink_t { 28 | using base_sink_t::base_sink_t; 29 | using mutex_t = std::mutex; 30 | 31 | void forward(log_record_ptr_t) override; 32 | 33 | mutex_t mutex; 34 | log_queue_t records; 35 | }; 36 | 37 | } // namespace syncspirit::fltk 38 | -------------------------------------------------------------------------------- /src/ui-fltk/log_table.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "log_utils.h" 7 | #include 8 | #include 9 | 10 | namespace syncspirit::fltk { 11 | 12 | struct fltk_sink_t; 13 | 14 | struct log_table_t : Fl_Table_Row { 15 | using parent_t = Fl_Table_Row; 16 | 17 | log_table_t(log_buffer_ptr_t &displayed_records, int x, int y, int w, int h); 18 | 19 | void draw_cell(TableContext context, int row, int col, int x, int y, int w, int h) override; 20 | void autoscroll(bool value); 21 | void update(); 22 | int handle(int event) override; 23 | log_iterator_ptr_t get_selected(); 24 | 25 | private: 26 | using selected_indices_t = std::vector; 27 | std::string gather_selected(); 28 | void draw_header(int col, int x, int y, int w, int h); 29 | void draw_data(int row, int col, int x, int y, int w, int h); 30 | 31 | selected_indices_t selected_records; 32 | log_buffer_ptr_t &displayed_records; 33 | bool auto_scrolling; 34 | }; 35 | 36 | } // namespace syncspirit::fltk 37 | -------------------------------------------------------------------------------- /src/ui-fltk/log_utils.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "log_utils.h" 5 | 6 | namespace syncspirit::fltk { 7 | 8 | const char *eol = 9 | #ifdef _WIN32 10 | "\r\n" 11 | #else 12 | "\n" 13 | #endif 14 | ; 15 | 16 | } // namespace syncspirit::fltk 17 | -------------------------------------------------------------------------------- /src/ui-fltk/main_window.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "app_supervisor.h" 7 | #include 8 | #include 9 | 10 | namespace syncspirit::fltk { 11 | 12 | struct log_panel_t; 13 | struct tree_view_t; 14 | 15 | struct main_window_t : Fl_Double_Window { 16 | using parent_t = Fl_Double_Window; 17 | 18 | main_window_t(app_supervisor_t &supervisor, int w, int h); 19 | 20 | void on_shutdown(); 21 | void set_splash_text(std::string text); 22 | void on_loading_done(); 23 | 24 | private: 25 | app_supervisor_t &supervisor; 26 | Fl_Group *content_left; 27 | tree_view_t *tree; 28 | log_panel_t *log_panel; 29 | }; 30 | 31 | } // namespace syncspirit::fltk 32 | -------------------------------------------------------------------------------- /src/ui-fltk/qr_button.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "app_supervisor.h" 7 | 8 | #include 9 | 10 | namespace syncspirit::fltk { 11 | 12 | struct qr_button_t : Fl_Group { 13 | using parent_t = Fl_Group; 14 | 15 | qr_button_t(const model::device_id_t &device, app_supervisor_t &supervisor, int x, int y, int w, int h); 16 | 17 | model::device_id_t device_id; 18 | app_supervisor_t &supervisor; 19 | }; 20 | 21 | } // namespace syncspirit::fltk 22 | -------------------------------------------------------------------------------- /src/ui-fltk/symbols.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace syncspirit::fltk::symbols { 9 | 10 | extern const std::string_view online; 11 | extern const std::string_view offline; 12 | extern const std::string_view connecting; 13 | extern const std::string_view discovering; 14 | extern const std::string_view scanning; 15 | extern const std::string_view synchronizing; 16 | extern const std::string_view deleted; 17 | extern const std::string_view colorize; 18 | 19 | std::string_view get_description(std::string_view symbol); 20 | 21 | } // namespace syncspirit::fltk::symbols 22 | -------------------------------------------------------------------------------- /src/ui-fltk/table_widget/checkbox.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "checkbox.h" 5 | 6 | static constexpr int padding = 2; 7 | 8 | using namespace syncspirit::fltk::table_widget; 9 | 10 | Fl_Widget *checkbox_t::create_widget(int x, int y, int w, int h) { 11 | auto group = new Fl_Group(x, y, w, h); 12 | group->begin(); 13 | group->box(FL_FLAT_BOX); 14 | auto yy = y + padding, ww = 25, hh = h - padding * 2; 15 | input = new Fl_Check_Button(x + padding, yy, ww, hh); 16 | // auto xx = input->x() + ww + padding; 17 | 18 | group->end(); 19 | widget = group; 20 | reset(); 21 | return widget; 22 | } 23 | -------------------------------------------------------------------------------- /src/ui-fltk/table_widget/checkbox.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "../static_table.h" 5 | 6 | #include 7 | 8 | namespace syncspirit::fltk::table_widget { 9 | 10 | struct checkbox_t : widgetable_t { 11 | using parent_t = widgetable_t; 12 | using parent_t::parent_t; 13 | 14 | Fl_Widget *create_widget(int x, int y, int w, int h) override; 15 | Fl_Check_Button *input = nullptr; 16 | }; 17 | 18 | } // namespace syncspirit::fltk::table_widget 19 | -------------------------------------------------------------------------------- /src/ui-fltk/table_widget/choice.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "choice.h" 5 | 6 | static constexpr int padding = 2; 7 | 8 | using namespace syncspirit::fltk::table_widget; 9 | 10 | Fl_Widget *choice_t::create_widget(int x, int y, int w, int h) { 11 | auto group = new Fl_Group(x, y, w, h); 12 | group->begin(); 13 | group->box(FL_FLAT_BOX); 14 | auto yy = y + padding, ww = w - padding * 2, hh = h - padding * 2; 15 | ww = std::min(150, ww); 16 | 17 | input = new Fl_Choice(x + padding, yy, ww, hh); 18 | group->end(); 19 | group->resizable(nullptr); 20 | widget = group; 21 | 22 | reset(); 23 | return widget; 24 | } 25 | -------------------------------------------------------------------------------- /src/ui-fltk/table_widget/choice.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "../static_table.h" 5 | 6 | #include 7 | 8 | namespace syncspirit::fltk::table_widget { 9 | 10 | struct choice_t : widgetable_t { 11 | using parent_t = widgetable_t; 12 | using parent_t::parent_t; 13 | 14 | Fl_Widget *create_widget(int x, int y, int w, int h) override; 15 | Fl_Choice *input = nullptr; 16 | }; 17 | 18 | } // namespace syncspirit::fltk::table_widget 19 | -------------------------------------------------------------------------------- /src/ui-fltk/table_widget/input.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "input.h" 5 | 6 | static constexpr int padding = 2; 7 | 8 | using namespace syncspirit::fltk::table_widget; 9 | 10 | Fl_Widget *input_t::create_widget(int x, int y, int w, int h) { 11 | auto group = new Fl_Group(x, y, w, h); 12 | group->begin(); 13 | group->box(FL_FLAT_BOX); 14 | auto yy = y + padding, ww = w - padding * 2, hh = h - padding * 2; 15 | 16 | input = new Fl_Input(x + padding, yy, ww, hh); 17 | group->end(); 18 | widget = group; 19 | reset(); 20 | return widget; 21 | } 22 | -------------------------------------------------------------------------------- /src/ui-fltk/table_widget/input.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "../static_table.h" 5 | 6 | #include 7 | 8 | namespace syncspirit::fltk::table_widget { 9 | 10 | struct input_t : widgetable_t { 11 | using parent_t = widgetable_t; 12 | using parent_t::parent_t; 13 | 14 | Fl_Widget *create_widget(int x, int y, int w, int h) override; 15 | Fl_Input *input = nullptr; 16 | }; 17 | 18 | } // namespace syncspirit::fltk::table_widget 19 | -------------------------------------------------------------------------------- /src/ui-fltk/table_widget/int_input.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "int_input.h" 5 | 6 | static constexpr int padding = 2; 7 | 8 | using namespace syncspirit::fltk::table_widget; 9 | 10 | Fl_Widget *int_input_t::create_widget(int x, int y, int w, int h) { 11 | auto group = new Fl_Group(x, y, w, h); 12 | group->begin(); 13 | group->box(FL_FLAT_BOX); 14 | auto yy = y + padding, ww = w - padding * 2, hh = h - padding * 2; 15 | 16 | input = new Fl_Int_Input(x + padding, yy, ww, hh); 17 | group->end(); 18 | widget = group; 19 | reset(); 20 | return widget; 21 | } 22 | -------------------------------------------------------------------------------- /src/ui-fltk/table_widget/int_input.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "../static_table.h" 5 | 6 | #include 7 | 8 | namespace syncspirit::fltk::table_widget { 9 | 10 | struct int_input_t : widgetable_t { 11 | using parent_t = widgetable_t; 12 | using parent_t::parent_t; 13 | 14 | Fl_Widget *create_widget(int x, int y, int w, int h) override; 15 | Fl_Int_Input *input = nullptr; 16 | }; 17 | 18 | } // namespace syncspirit::fltk::table_widget 19 | -------------------------------------------------------------------------------- /src/ui-fltk/table_widget/label.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "label.h" 5 | 6 | static constexpr int padding = 2; 7 | 8 | using namespace syncspirit::fltk::table_widget; 9 | 10 | Fl_Widget *label_t::create_widget(int x, int y, int w, int h) { 11 | input = new Fl_Box(x, y, w, h, ""); 12 | input->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); 13 | widget = input; 14 | reset(); 15 | return widget; 16 | } 17 | -------------------------------------------------------------------------------- /src/ui-fltk/table_widget/label.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "../static_table.h" 5 | 6 | #include 7 | 8 | namespace syncspirit::fltk::table_widget { 9 | 10 | struct label_t : widgetable_t { 11 | using parent_t = widgetable_t; 12 | using parent_t::parent_t; 13 | 14 | Fl_Widget *create_widget(int x, int y, int w, int h) override; 15 | Fl_Box *input = nullptr; 16 | }; 17 | 18 | } // namespace syncspirit::fltk::table_widget 19 | -------------------------------------------------------------------------------- /src/ui-fltk/table_widget/path.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "../static_table.h" 5 | 6 | #include 7 | #include 8 | 9 | namespace syncspirit::fltk::table_widget { 10 | 11 | struct path_t : widgetable_t { 12 | using parent_t = widgetable_t; 13 | 14 | path_t(Fl_Widget &container, std::string title); 15 | 16 | Fl_Widget *create_widget(int x, int y, int w, int h) override; 17 | void on_click(); 18 | 19 | Fl_Input *input = nullptr; 20 | std::string title; 21 | }; 22 | 23 | } // namespace syncspirit::fltk::table_widget 24 | -------------------------------------------------------------------------------- /src/ui-fltk/toolbar.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "app_supervisor.h" 7 | #include 8 | 9 | namespace syncspirit::fltk { 10 | 11 | struct toolbar_t : Fl_Group { 12 | using parent_t = Fl_Group; 13 | toolbar_t(app_supervisor_t &supervisor, int x, int y, int w, int h); 14 | 15 | app_supervisor_t &supervisor; 16 | }; 17 | 18 | } // namespace syncspirit::fltk 19 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/devices.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/device.h" 7 | #include "../tree_item.h" 8 | #include "peer_device.h" 9 | 10 | namespace syncspirit::fltk::tree_item { 11 | 12 | struct devices_t : tree_item_t { 13 | using parent_t = tree_item_t; 14 | devices_t(app_supervisor_t &supervisor, Fl_Tree *tree); 15 | 16 | augmentation_ptr_t set_self(model::device_t &self); 17 | augmentation_ptr_t add_peer(model::device_t &peer); 18 | peer_device_t *get_peer(const model::device_t &peer); 19 | 20 | bool on_select() override; 21 | void update_label() override; 22 | void remove_child(tree_item_t *child) override; 23 | }; 24 | 25 | } // namespace syncspirit::fltk::tree_item 26 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/entry.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../tree_item.h" 7 | 8 | namespace syncspirit::fltk::tree_item { 9 | 10 | struct entry_t : dynamic_item_t { 11 | using parent_t = dynamic_item_t; 12 | entry_t(app_supervisor_t &supervisor, Fl_Tree *tree, augmentation_entry_t *augmentation, 13 | tree_item_t *parent = nullptr); 14 | 15 | void update_label() override; 16 | void on_update() override; 17 | void on_open() override; 18 | void show_deleted(bool value) override; 19 | 20 | void hide(); 21 | void show(); 22 | 23 | dynamic_item_t *create(augmentation_entry_t &) override; 24 | virtual entry_t *create_child(augmentation_entry_t &entry) = 0; 25 | virtual void refresh_children() override; 26 | 27 | tree_item_t *parent; 28 | bool expanded; 29 | }; 30 | 31 | } // namespace syncspirit::fltk::tree_item 32 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/file_entry.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "file_entry.h" 5 | 6 | #include "../content/remote_file_table.h" 7 | 8 | using namespace syncspirit::fltk; 9 | using namespace syncspirit::fltk::tree_item; 10 | 11 | bool file_entry_t::on_select() { 12 | content = supervisor.replace_content([&](content_t *content) -> content_t * { 13 | auto prev = content->get_widget(); 14 | int x = prev->x(), y = prev->y(), w = prev->w(), h = prev->h(); 15 | return new content::remote_file_table_t(*this, x, y, w, h); 16 | }); 17 | return true; 18 | } 19 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/file_entry.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "entry.h" 7 | 8 | namespace syncspirit::fltk::tree_item { 9 | 10 | struct file_entry_t : entry_t { 11 | using parent_t = entry_t; 12 | using parent_t::parent_t; 13 | bool on_select() override; 14 | }; 15 | 16 | }; // namespace syncspirit::fltk::tree_item 17 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/folder.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "local_entry.h" 7 | 8 | namespace syncspirit::fltk::tree_item { 9 | 10 | struct folder_t final : local_entry_t { 11 | using parent_t = local_entry_t; 12 | 13 | folder_t(model::folder_t &folder, app_supervisor_t &supervisor, Fl_Tree *tree); 14 | void update_label() override; 15 | bool on_select() override; 16 | 17 | void reset_stats(); 18 | }; 19 | 20 | } // namespace syncspirit::fltk::tree_item 21 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/folders.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../tree_item.h" 7 | 8 | namespace syncspirit::fltk::tree_item { 9 | 10 | struct folders_t final : tree_item_t { 11 | using parent_t = tree_item_t; 12 | folders_t(app_supervisor_t &supervisor, Fl_Tree *tree); 13 | 14 | void select_folder(std::string_view folder_id); 15 | augmentation_ptr_t add_folder(model::folder_t &folder); 16 | void update_label() override; 17 | 18 | bool on_select() override; 19 | void remove_child(tree_item_t *child) override; 20 | }; 21 | 22 | } // namespace syncspirit::fltk::tree_item 23 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/ignored_device.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/ignored_device.h" 7 | #include "../tree_item.h" 8 | 9 | namespace syncspirit::fltk::tree_item { 10 | 11 | struct ignored_device_t : tree_item_t { 12 | using parent_t = tree_item_t; 13 | 14 | ignored_device_t(model::ignored_device_t &device, app_supervisor_t &supervisor, Fl_Tree *tree); 15 | void update_label() override; 16 | 17 | bool on_select() override; 18 | 19 | model::ignored_device_t &device; 20 | }; 21 | 22 | }; // namespace syncspirit::fltk::tree_item 23 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/ignored_devices.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "ignored_devices.h" 5 | #include "ignored_device.h" 6 | 7 | using namespace syncspirit; 8 | using namespace syncspirit::model::diff; 9 | using namespace syncspirit::fltk; 10 | using namespace syncspirit::fltk::tree_item; 11 | 12 | ignored_devices_t::ignored_devices_t(app_supervisor_t &supervisor, Fl_Tree *tree) : parent_t(supervisor, tree, false) { 13 | supervisor.set_ignored_devices(this); 14 | update_label(); 15 | tree->close(this, 0); 16 | } 17 | 18 | void ignored_devices_t::update_label() { 19 | auto cluster = supervisor.get_cluster(); 20 | auto count = cluster ? cluster->get_ignored_devices().size() : 0; 21 | auto l = fmt::format("ignored devices ({})", count); 22 | label(l.data()); 23 | tree()->redraw(); 24 | } 25 | 26 | augmentation_ptr_t ignored_devices_t::add_device(model::ignored_device_t &device) { 27 | return within_tree([&]() { 28 | auto node = insert_by_label(new ignored_device_t(device, supervisor, tree())); 29 | update_label(); 30 | return node->get_proxy(); 31 | }); 32 | } 33 | 34 | void ignored_devices_t::remove_device(tree_item_t *item) { 35 | remove_child(item); 36 | update_label(); 37 | tree()->redraw(); 38 | } 39 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/ignored_devices.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../tree_item.h" 7 | 8 | namespace syncspirit::fltk::tree_item { 9 | 10 | struct ignored_devices_t : tree_item_t { 11 | using parent_t = tree_item_t; 12 | ignored_devices_t(app_supervisor_t &supervisor, Fl_Tree *tree); 13 | 14 | void update_label() override; 15 | 16 | augmentation_ptr_t add_device(model::ignored_device_t &device); 17 | void remove_device(tree_item_t *item); 18 | }; 19 | 20 | } // namespace syncspirit::fltk::tree_item 21 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/local_entry.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "local_entry.h" 5 | 6 | using namespace syncspirit::fltk; 7 | using namespace syncspirit::fltk::tree_item; 8 | 9 | auto local_entry_t::create_child(augmentation_entry_t &entry) -> entry_t * { 10 | return new local_entry_t(supervisor, tree(), &entry, this); 11 | } 12 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/local_entry.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "file_entry.h" 7 | 8 | namespace syncspirit::fltk::tree_item { 9 | 10 | struct local_entry_t : file_entry_t { 11 | using parent_t = file_entry_t; 12 | using parent_t::parent_t; 13 | 14 | entry_t *create_child(augmentation_entry_t &entry) override; 15 | }; 16 | 17 | }; // namespace syncspirit::fltk::tree_item 18 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/peer_device.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/device.h" 7 | #include "../tree_item.h" 8 | 9 | namespace syncspirit::fltk::tree_item { 10 | 11 | struct peer_device_t : tree_item_t { 12 | using parent_t = tree_item_t; 13 | 14 | peer_device_t(model::device_t &peer, app_supervisor_t &supervisor, Fl_Tree *tree); 15 | 16 | const model::device_t &get_device() const; 17 | std::string_view get_state(); 18 | 19 | void update_label() override; 20 | bool on_select() override; 21 | void remove_child(tree_item_t *child) override; 22 | 23 | tree_item_t *get_folders(); 24 | tree_item_t *get_pending_folders(); 25 | 26 | model::device_t &peer; 27 | tree_item_t *folders; 28 | tree_item_t *pending_folders; 29 | }; 30 | 31 | } // namespace syncspirit::fltk::tree_item 32 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/peer_entry.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "peer_entry.h" 5 | #include "../content/remote_file_table.h" 6 | 7 | using namespace syncspirit::fltk; 8 | using namespace syncspirit::fltk::tree_item; 9 | 10 | entry_t *peer_entry_t::create_child(augmentation_entry_t &entry) { 11 | return new peer_entry_t(supervisor, tree(), &entry, this); 12 | } 13 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/peer_entry.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "file_entry.h" 7 | 8 | namespace syncspirit::fltk::tree_item { 9 | 10 | struct peer_entry_t : file_entry_t { 11 | using parent_t = file_entry_t; 12 | using parent_t::parent_t; 13 | 14 | entry_t *create_child(augmentation_entry_t &entry) override; 15 | }; 16 | 17 | }; // namespace syncspirit::fltk::tree_item 18 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/peer_folder.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "peer_entry.h" 7 | 8 | namespace syncspirit::fltk::tree_item { 9 | 10 | struct peer_folder_t final : peer_entry_t { 11 | using parent_t = peer_entry_t; 12 | peer_folder_t(model::folder_info_t &folder_info, app_supervisor_t &supervisor, Fl_Tree *tree); 13 | 14 | void update_label() override; 15 | bool on_select() override; 16 | }; 17 | 18 | } // namespace syncspirit::fltk::tree_item 19 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/peer_folders.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../tree_item.h" 7 | 8 | namespace syncspirit::fltk::tree_item { 9 | 10 | struct peer_folders_t : tree_item_t { 11 | using parent_t = tree_item_t; 12 | peer_folders_t(model::device_t &peer, app_supervisor_t &supervisor, Fl_Tree *tree); 13 | 14 | void update_label() override; 15 | 16 | augmentation_ptr_t add_folder(model::folder_info_t &folder); 17 | void remove_child(tree_item_t *child) override; 18 | model::device_t &peer; 19 | }; 20 | 21 | } // namespace syncspirit::fltk::tree_item 22 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/pending_device.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/pending_device.h" 7 | #include "../tree_item.h" 8 | 9 | namespace syncspirit::fltk::tree_item { 10 | 11 | struct pending_device_t : tree_item_t { 12 | using parent_t = tree_item_t; 13 | 14 | pending_device_t(model::pending_device_t &device, app_supervisor_t &supervisor, Fl_Tree *tree); 15 | void update_label() override; 16 | 17 | bool on_select() override; 18 | 19 | model::pending_device_t &device; 20 | }; 21 | 22 | }; // namespace syncspirit::fltk::tree_item 23 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/pending_devices.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "pending_devices.h" 5 | #include "pending_device.h" 6 | 7 | using namespace syncspirit; 8 | using namespace syncspirit::model::diff; 9 | using namespace syncspirit::fltk; 10 | using namespace syncspirit::fltk::tree_item; 11 | 12 | pending_devices_t::pending_devices_t(app_supervisor_t &supervisor, Fl_Tree *tree) : parent_t(supervisor, tree, false) { 13 | supervisor.set_pending_devices(this); 14 | update_label(); 15 | } 16 | 17 | void pending_devices_t::update_label() { 18 | auto cluster = supervisor.get_cluster(); 19 | auto count = cluster ? cluster->get_pending_devices().size() : 0; 20 | auto l = fmt::format("pending devices ({})", count); 21 | label(l.data()); 22 | } 23 | 24 | auto pending_devices_t::add_device(model::pending_device_t &device) -> augmentation_ptr_t { 25 | return within_tree([&]() { 26 | auto node = insert_by_label(new pending_device_t(device, supervisor, tree())); 27 | update_label(); 28 | return node->get_proxy(); 29 | }); 30 | } 31 | 32 | void pending_devices_t::remove_device(tree_item_t *item) { 33 | remove_child(item); 34 | update_label(); 35 | tree()->redraw(); 36 | } 37 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/pending_devices.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../tree_item.h" 7 | 8 | namespace syncspirit::fltk::tree_item { 9 | 10 | struct pending_devices_t : tree_item_t { 11 | using parent_t = tree_item_t; 12 | pending_devices_t(app_supervisor_t &supervisor, Fl_Tree *tree); 13 | 14 | void update_label() override; 15 | 16 | augmentation_ptr_t add_device(model::pending_device_t &device); 17 | void remove_device(tree_item_t *item); 18 | }; 19 | 20 | } // namespace syncspirit::fltk::tree_item 21 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/pending_folder.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/pending_folder.h" 7 | #include "../tree_item.h" 8 | 9 | namespace syncspirit::fltk::tree_item { 10 | 11 | struct pending_folder_t : tree_item_t { 12 | using parent_t = tree_item_t; 13 | 14 | pending_folder_t(model::pending_folder_t &folder, app_supervisor_t &supervisor, Fl_Tree *tree); 15 | 16 | bool on_select() override; 17 | 18 | model::pending_folder_t &folder; 19 | }; 20 | 21 | }; // namespace syncspirit::fltk::tree_item 22 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/pending_folders.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../tree_item.h" 7 | #include "model/device.h" 8 | 9 | namespace syncspirit::fltk::tree_item { 10 | 11 | struct pending_folders_t : tree_item_t { 12 | using parent_t = tree_item_t; 13 | 14 | pending_folders_t(model::device_t &peer, app_supervisor_t &supervisor, Fl_Tree *tree); 15 | 16 | augmentation_ptr_t add_pending_folder(model::pending_folder_t &uf); 17 | 18 | void remove_folder(tree_item_t *item); 19 | void remove_child(tree_item_t *child) override; 20 | 21 | model::device_t &peer; 22 | }; 23 | 24 | }; // namespace syncspirit::fltk::tree_item 25 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/self_device.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../tree_item.h" 7 | #include "FL/Fl_Widget.H" 8 | 9 | namespace syncspirit::fltk::tree_item { 10 | 11 | struct self_device_t final : tree_item_t { 12 | using parent_t = tree_item_t; 13 | self_device_t(model::device_t &self, app_supervisor_t &supervisor, Fl_Tree *tree); 14 | 15 | bool on_select() override; 16 | void update_label() override; 17 | }; 18 | 19 | } // namespace syncspirit::fltk::tree_item 20 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/settings.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #include "settings.h" 5 | #include "../config/control.h" 6 | #include 7 | 8 | using namespace syncspirit::fltk::tree_item; 9 | 10 | settings_t::settings_t(app_supervisor_t &supervisor, Fl_Tree *tree) : parent_t(supervisor, tree, false) { 11 | update_label(false); 12 | } 13 | 14 | bool settings_t::on_select() { 15 | content = supervisor.replace_content([&](content_t *content) -> content_t * { 16 | auto prev = content->get_widget(); 17 | content = new config::control_t(*this, prev->x(), prev->y(), prev->w(), prev->h()); 18 | return content; 19 | }); 20 | return true; 21 | } 22 | 23 | void settings_t::update_label(bool modified) { 24 | auto l = std::string("settings"); 25 | if (modified) { 26 | l = fmt::format("({}) {}", "*", l); 27 | } 28 | label(l.data()); 29 | tree()->redraw(); 30 | } 31 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_item/settings.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "../tree_item.h" 7 | 8 | namespace syncspirit::fltk::tree_item { 9 | 10 | struct settings_t : tree_item_t { 11 | using parent_t = tree_item_t; 12 | settings_t(app_supervisor_t &supervisor, Fl_Tree *tree); 13 | 14 | void update_label(bool modified); 15 | bool on_select() override; 16 | }; 17 | 18 | } // namespace syncspirit::fltk::tree_item 19 | -------------------------------------------------------------------------------- /src/ui-fltk/tree_view.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "app_supervisor.h" 7 | #include 8 | 9 | namespace syncspirit::fltk { 10 | 11 | struct tree_view_t : Fl_Tree { 12 | using parent_t = Fl_Tree; 13 | tree_view_t(app_supervisor_t &supervisor, int x, int y, int w, int h); 14 | 15 | app_supervisor_t &supervisor; 16 | Fl_Tree_Item *current; 17 | }; 18 | 19 | } // namespace syncspirit::fltk 20 | -------------------------------------------------------------------------------- /src/ui-fltk/utils.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2025 Ivan Baidakou 3 | 4 | #include "utils.hpp" 5 | #include 6 | #include 7 | #include 8 | 9 | namespace syncspirit::fltk { 10 | 11 | static std::array suffix = { 12 | "b", "Kb", "Mb", "Gb", "Tb", 13 | }; 14 | 15 | std::string get_file_size(std::int64_t value) { 16 | auto v = double(value); 17 | size_t i = 0; 18 | for (; i < suffix.size() && v > 1024; ++i) { 19 | v /= 1024.0; 20 | } 21 | if (i) { 22 | return fmt::format("{:.2f}{} ({}b)", v, suffix[i], value); 23 | } 24 | return fmt::format("{}b", value); 25 | } 26 | 27 | } // namespace syncspirit::fltk 28 | -------------------------------------------------------------------------------- /src/utils/base32.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include "syncspirit-export.h" 9 | 10 | namespace syncspirit::utils { 11 | 12 | namespace outcome = boost::outcome_v2; 13 | 14 | struct SYNCSPIRIT_API base32 { 15 | 16 | static const char in_alphabet[]; 17 | static const std::int32_t out_alphabet[]; 18 | 19 | static inline std::size_t encoded_size(std::size_t dec_len) noexcept { return (dec_len + 4) / 5 * 8; } 20 | static inline std::size_t decoded_size(std::size_t dec_len) noexcept { return dec_len * 5 / 8; } 21 | 22 | static std::string encode(std::string_view input) noexcept; 23 | static outcome::result decode(std::string_view input) noexcept; 24 | }; 25 | 26 | } // namespace syncspirit::utils 27 | -------------------------------------------------------------------------------- /src/utils/beast_support.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include "syncspirit-export.h" 10 | 11 | namespace syncspirit::utils { 12 | namespace sys = boost::system; 13 | namespace outcome = boost::outcome_v2; 14 | namespace http = boost::beast::http; 15 | 16 | SYNCSPIRIT_API outcome::result serialize(http::request &req, fmt::memory_buffer &buff); 17 | 18 | SYNCSPIRIT_API outcome::result serialize(http::request &req, fmt::memory_buffer &buff); 19 | 20 | } // namespace syncspirit::utils 21 | -------------------------------------------------------------------------------- /src/utils/io.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace syncspirit::utils { 9 | 10 | using fstream_t = boost::nowide::fstream; 11 | using ifstream_t = boost::nowide::ifstream; 12 | using ofstream_t = boost::nowide::ofstream; 13 | 14 | } // namespace syncspirit::utils 15 | -------------------------------------------------------------------------------- /src/utils/location.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include "syncspirit-export.h" 10 | 11 | namespace syncspirit { 12 | namespace utils { 13 | 14 | namespace outcome = boost::outcome_v2; 15 | namespace bfs = std::filesystem; 16 | 17 | using home_option_t = outcome::result; 18 | 19 | SYNCSPIRIT_API outcome::result get_home_dir() noexcept; 20 | 21 | SYNCSPIRIT_API outcome::result get_default_config_dir() noexcept; 22 | 23 | SYNCSPIRIT_API std::string expand_home(const std::string &path, const home_option_t &home) noexcept; 24 | 25 | } // namespace utils 26 | } // namespace syncspirit 27 | -------------------------------------------------------------------------------- /src/utils/log-setup.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "log.h" 7 | #include "config/log.h" 8 | #include 9 | #include 10 | #include 11 | #include "syncspirit-export.h" 12 | 13 | namespace syncspirit::utils { 14 | 15 | namespace outcome = boost::outcome_v2; 16 | namespace bfs = std::filesystem; 17 | 18 | using dist_sink_t = std::shared_ptr; 19 | using sink_t = spdlog::sink_ptr; 20 | 21 | struct SYNCSPIRIT_API bootstrap_guard_t { 22 | bootstrap_guard_t(dist_sink_t dist_sink, spdlog::sinks::sink *); 23 | ~bootstrap_guard_t(); 24 | dist_sink_t get_dist_sink(); 25 | 26 | private: 27 | dist_sink_t dist_sink; 28 | spdlog::sinks::sink *sink; 29 | }; 30 | using bootstrap_guard_ptr_t = std::unique_ptr; 31 | 32 | SYNCSPIRIT_API outcome::result init_loggers(const config::log_configs_t &configs) noexcept; 33 | 34 | SYNCSPIRIT_API dist_sink_t create_root_logger() noexcept; 35 | SYNCSPIRIT_API bootstrap_guard_ptr_t bootstrap(dist_sink_t &, const bfs::path &dir) noexcept; 36 | 37 | } // namespace syncspirit::utils 38 | -------------------------------------------------------------------------------- /src/utils/network_interface.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "uri.h" 8 | #include "log.h" 9 | #include "syncspirit-export.h" 10 | 11 | namespace syncspirit::utils { 12 | using tcp = boost::asio::ip::tcp; 13 | 14 | SYNCSPIRIT_API uri_container_t local_interfaces(const tcp::endpoint &fallback, logger_t &log) noexcept; 15 | } // namespace syncspirit::utils 16 | -------------------------------------------------------------------------------- /src/utils/platform.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #include "platform.h" 5 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) 6 | #include 7 | #endif 8 | using namespace syncspirit::utils; 9 | 10 | void platform_t::startup() { 11 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) 12 | auto wVersionRequested = MAKEWORD(2, 2); 13 | WSADATA wsaData; 14 | 15 | auto err = WSAStartup(wVersionRequested, &wsaData); 16 | if (err != 0) { 17 | std::string msg = "WSAStartup failed with error: "; 18 | msg += std::to_string(err); 19 | throw std::runtime_error(msg); 20 | } 21 | #endif 22 | } 23 | 24 | void platform_t::shutdown() noexcept {} 25 | 26 | bool platform_t::symlinks_supported() noexcept { 27 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) 28 | return false; 29 | #else 30 | return true; 31 | #endif 32 | } 33 | -------------------------------------------------------------------------------- /src/utils/platform.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "syncspirit-export.h" 7 | 8 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) 9 | 10 | #define WIN32_LEAN_AND_MEAN 11 | 12 | #include 13 | #include 14 | #include 15 | #endif 16 | 17 | namespace syncspirit::utils { 18 | 19 | struct SYNCSPIRIT_API platform_t { 20 | static void startup(); 21 | static void shutdown() noexcept; 22 | static bool symlinks_supported() noexcept; 23 | }; 24 | 25 | } // namespace syncspirit::utils 26 | -------------------------------------------------------------------------------- /src/utils/string_comparator.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | namespace syncspirit::utils { 7 | 8 | struct string_comparator_t { 9 | using is_transparent = void; 10 | 11 | template bool operator()(const T1 &k1, const T2 &k2) const { return k1 < k2; } 12 | }; 13 | 14 | } // namespace syncspirit::utils 15 | -------------------------------------------------------------------------------- /src/utils/time.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "time.h" 5 | 6 | namespace syncspirit::utils { 7 | 8 | std::int64_t as_seconds(const pt::ptime &t) noexcept { 9 | pt::ptime epoch(boost::gregorian::date(1970, 1, 1)); 10 | auto time_diff = t - epoch; 11 | auto value = time_diff.ticks() / time_diff.ticks_per_second(); 12 | return value; 13 | } 14 | 15 | } // namespace syncspirit::utils 16 | -------------------------------------------------------------------------------- /src/utils/time.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include "syncspirit-export.h" 9 | 10 | namespace syncspirit::utils { 11 | 12 | namespace pt = boost::posix_time; 13 | 14 | SYNCSPIRIT_API std::int64_t as_seconds(const pt::ptime &t) noexcept; 15 | 16 | } // namespace syncspirit::utils 17 | -------------------------------------------------------------------------------- /src/utils/uri.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "uri.h" 5 | 6 | namespace syncspirit::utils { 7 | 8 | uri_t::uri_t(boost::urls::url_view view) : parent_t(view) { 9 | if (!has_port()) { 10 | if (scheme() == "http") { 11 | set_port_number(80); 12 | } else if (scheme() == "https") { 13 | set_port_number(443); 14 | } 15 | } 16 | } 17 | 18 | uri_ptr_t uri_t::clone() const { return new uri_t(*this); } 19 | 20 | uri_ptr_t parse(std::string_view str) { 21 | auto result = boost::urls::parse_uri(str); 22 | if (result) { 23 | return new uri_t(result.value()); 24 | } 25 | return {}; 26 | } 27 | 28 | } // namespace syncspirit::utils 29 | -------------------------------------------------------------------------------- /src/utils/uri.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "syncspirit-export.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace syncspirit::utils { 13 | 14 | struct uri_t; 15 | using uri_ptr_t = boost::intrusive_ptr; 16 | 17 | struct SYNCSPIRIT_API uri_t : boost::intrusive_ref_counter, boost::urls::url { 18 | using parent_t = boost::urls::url; 19 | uri_t(boost::urls::url_view view); 20 | 21 | uri_ptr_t clone() const; 22 | }; 23 | 24 | using uri_container_t = std::vector; 25 | 26 | SYNCSPIRIT_API uri_ptr_t parse(std::string_view string); 27 | 28 | } // namespace syncspirit::utils 29 | -------------------------------------------------------------------------------- /syncspirit.toml: -------------------------------------------------------------------------------- 1 | [bep] 2 | blocks_max_requested = 16 3 | blocks_simultaneous_write = 16 4 | connect_timeout = 5000 5 | request_timeout = 60000 6 | rx_buff_size = 16777216 7 | rx_timeout = 300000 8 | tx_buff_limit = 8388608 9 | tx_timeout = 90000 10 | 11 | [db] 12 | uncommitted_threshold = 150 13 | upper_limit = 17179869184 14 | 15 | [dialer] 16 | enabled = true 17 | redial_timeout = 30000 18 | 19 | [fs] 20 | mru_size = 5 21 | temporally_timeout = 86400000 22 | 23 | [global_discovery] 24 | announce_url = 'https://discovery.syncthing.net/' 25 | cert_file = '/home/b/.config/syncspirit/cert.pem' 26 | device_id = 'LYXKCHX-VI3NYZR-ALCJBHF-WMZYSPK-QG6QJA3-MPFYMSO-U56GTUK-NA2MIAW' 27 | enabled = true 28 | key_file = '/home/b/.config/syncspirit/key.pem' 29 | rx_buff_size = 32768 30 | timeout = 3000 31 | 32 | [local_discovery] 33 | enabled = true 34 | frequency = 30000 35 | port = 21026 36 | 37 | [main] 38 | default_location = '/tmp/syncspirit' 39 | device_name = 'hp-note' 40 | hasher_threads = 7 41 | timeout = 5000 42 | 43 | [relay] 44 | discovery_url = 'https://relays.syncthing.net/endpoint' 45 | enabled = false 46 | rx_buff_size = 1048576 47 | 48 | [upnp] 49 | debug = false 50 | enabled = true 51 | external_port = 22001 52 | max_wait = 1 53 | rx_buff_size = 65536 54 | 55 | [[log]] 56 | level = 'trace' 57 | name = 'default' 58 | sinks = [ 'stdout', 'file:/tmp/syncspirit-log.txt' ] 59 | -------------------------------------------------------------------------------- /tests/009-uri.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "test-utils.h" 5 | #include "utils/uri.h" 6 | 7 | using namespace syncspirit::utils; 8 | 9 | TEST_CASE("parse IGD control url", "[support]") { 10 | auto uri = parse("http://192.168.100.1:49652/upnp/control/WANIPConn1"); 11 | REQUIRE((bool)uri); 12 | CHECK(uri->port_number() == 49652); 13 | CHECK(uri->port() == "49652"); 14 | CHECK(uri->host() == "192.168.100.1"); 15 | CHECK(uri->scheme() == "http"); 16 | CHECK(uri->encoded_path() == "/upnp/control/WANIPConn1"); 17 | 18 | std::string relay = "relay://188.68.32.45:22067/" 19 | "?id=O4LHPKG-O6BQ36W-MUOVKTI-MKAVHSC-Y7EC3U4-DHNLEDE-MZBJWQN-UIX6QAL\u0026pingInterval=" 20 | "1m0s\u0026networkTimeout=2m0s\u0026sessionLimitBps=0\u0026globalLimitBps=0\u0026statusAddr=:" 21 | "22070\u0026providedBy=🐾 TilCreator (tils.pw)"; 22 | REQUIRE((bool)parse(relay) == false); 23 | 24 | std::string relay2 = "relay://188.68.32.45:22067/" 25 | "?id=O4LHPKG-O6BQ36W-MUOVKTI-MKAVHSC-Y7EC3U4-DHNLEDE-MZBJWQN-UIX6QAL&pingInterval=1m0s&" 26 | "networkTimeout=2m0s&sessionLimitBps=0&globalLimitBps=0&statusAddr=22070"; 27 | REQUIRE((bool)parse(relay2) == true); 28 | } 29 | -------------------------------------------------------------------------------- /tests/018-dns.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2024 Ivan Baidakou 3 | 4 | #include "test-utils.h" 5 | #include "utils/dns.h" 6 | 7 | using namespace syncspirit::utils; 8 | namespace ip = boost::asio::ip; 9 | 10 | TEST_CASE("get_block_size", "[support]") { 11 | auto str = "192.168.1.100,192.168.1.101:53,[1:2:3::4]:53,[fe80::1]:53%eth0"; 12 | auto endpoints = parse_dns_servers(str); 13 | #if !defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0600 14 | CHECK(endpoints.size() == 4u); 15 | #else 16 | CHECK(endpoints.size() == 2u); 17 | #endif 18 | 19 | auto &e0 = endpoints[0]; 20 | CHECK(e0.ip == ip::make_address_v4("192.168.1.100")); 21 | CHECK(e0.port == 53); 22 | 23 | auto &e1 = endpoints[1]; 24 | CHECK(e1.ip == ip::make_address_v4("192.168.1.101")); 25 | CHECK(e1.port == 53); 26 | 27 | #if !defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0600 28 | auto &e2 = endpoints[2]; 29 | CHECK(e2.ip == ip::make_address_v6("1:2:3::4")); 30 | CHECK(e2.port == 53); 31 | 32 | auto &e3 = endpoints[3]; 33 | CHECK(e3.ip == ip::make_address_v6("fe80::1")); 34 | CHECK(e3.port == 53); 35 | #endif 36 | } 37 | -------------------------------------------------------------------------------- /tests/022-version.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2024 Ivan Baidakou 3 | 4 | #include "test-utils.h" 5 | #include "model/version.h" 6 | 7 | using namespace syncspirit; 8 | using namespace syncspirit::model; 9 | 10 | TEST_CASE("version ", "[model]") { 11 | auto my_id = device_id_t::from_string("KHQNO2S-5QSILRK-YX4JZZ4-7L77APM-QNVGZJT-EKU7IFI-PNEPBMY-4MXFMQD").value(); 12 | auto my_device = device_t::create(my_id, "my-device").value(); 13 | 14 | auto proto_v = proto::Vector(); 15 | auto c0 = proto_v.mutable_counters()->Add(); 16 | c0->set_id(1); 17 | c0->set_value(2); 18 | 19 | auto c1 = proto_v.mutable_counters()->Add(); 20 | c1->set_id(my_device->device_id().get_uint()); 21 | c1->set_value(10); 22 | 23 | auto v1 = version_ptr_t(new version_t(proto_v)); 24 | auto v1_copy = version_ptr_t(new version_t(proto_v)); 25 | v1->update(*my_device); 26 | 27 | CHECK(v1->contains(*v1_copy)); 28 | CHECK(v1->contains(*v1)); 29 | CHECK(!v1_copy->contains(*v1)); 30 | CHECK(v1_copy->contains(*v1_copy)); 31 | } 32 | -------------------------------------------------------------------------------- /tests/029-diff-generic.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2023 Ivan Baidakou 3 | 4 | #include "test-utils.h" 5 | #include "access.h" 6 | #include "model/cluster.h" 7 | #include "model/misc/error_code.h" 8 | #include "model/diff/cluster_diff.h" 9 | 10 | using namespace syncspirit; 11 | using namespace syncspirit::model; 12 | using namespace syncspirit::proto; 13 | using namespace syncspirit::test; 14 | 15 | struct fail_diff_t : diff::cluster_diff_t { 16 | outcome::result apply_impl(cluster_t &, diff::apply_controller_t &) const noexcept override { 17 | auto ec = make_error_code(error_code_t::source_device_not_exists); 18 | return outcome::failure(ec); 19 | } 20 | }; 21 | 22 | TEST_CASE("generic cluster diff", "[model]") { 23 | auto my_id = device_id_t::from_string("KHQNO2S-5QSILRK-YX4JZZ4-7L77APM-QNVGZJT-EKU7IFI-PNEPBMY-4MXFMQD").value(); 24 | auto my_device = device_t::create(my_id, "my-device").value(); 25 | auto cluster = cluster_ptr_t(new cluster_t(my_device, 1)); 26 | auto diff = diff::cluster_diff_ptr_t(new fail_diff_t()); 27 | CHECK(!cluster->is_tainted()); 28 | CHECK(!diff->apply(*cluster, get_apply_controller())); 29 | CHECK(cluster->is_tainted()); 30 | } 31 | -------------------------------------------------------------------------------- /tests/access.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "model/folder.h" 8 | 9 | namespace syncspirit::test { 10 | namespace { 11 | namespace to { 12 | struct device {}; 13 | struct state {}; 14 | } // namespace to 15 | } // namespace 16 | } // namespace syncspirit::test 17 | 18 | namespace syncspirit::model { 19 | 20 | template <> inline auto &folder_t::access() noexcept { return device; } 21 | 22 | } // namespace syncspirit::model 23 | 24 | namespace rotor { 25 | 26 | template <> inline auto &actor_base_t::access() noexcept { return state; } 27 | 28 | } // namespace rotor 29 | -------------------------------------------------------------------------------- /tests/data/cert.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/tests/data/cert.der -------------------------------------------------------------------------------- /tests/data/external-ip.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 81.31.113.9 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/data/mykey.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basiliscos/syncspirit/f47379af5fd60f5769249ab5c14b1d3f240adeae/tests/data/mykey.der -------------------------------------------------------------------------------- /tests/data/port-mapping-success.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /tests/data/port-unmapping-failure.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | s:Client 6 | UPnPError 7 | 8 | 9 | 714 10 | NoSuchEntryInArray 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /tests/data/sample-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBmjCCASCgAwIBAgIIGXTPd8iLU/0wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ 3 | c3luY3RoaW5nMB4XDTE5MDgxODIwNDcxMVoXDTQ5MTIzMTIzNTk1OVowFDESMBAG 4 | A1UEAxMJc3luY3RoaW5nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEvYXFP+QY1a8W 5 | HEbR3NO7TQmd5GlYDe4Ypt+Q32Th8yvV7NOCqJRLbUhZuP4KHNZv8rxSKg+3eaTY 6 | AXWDzo8+g0kwT61OjvuTxeS96pxaL8KIfwgvtY5hHJ1xcEQ2Jw7hoz8wPTAOBgNV 7 | HQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1Ud 8 | EwEB/wQCMAAwCgYIKoZIzj0EAwIDaAAwZQIxAIkcES0jMYD0jcjjxzjAs8UssiFE 9 | dzvMiMCRKSE7YmUiRP92Vbts5fFHYz9lA+c58AIwU0K87K3Sm1/w+OrbQ9H7aYcK 10 | yfPYj4HhLsW1v77Fzr3sFCeEywEqHtQZhd/+hpQn 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /tests/data/sample-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MIGkAgEBBDCnfh5zKDvOQeJNZY6NA4B3zPPq7qsFimWZImxIy4qBJwevk7LXFgT4 3 | P0AsLwHmloSgBwYFK4EEACKhZANiAAS9hcU/5BjVrxYcRtHc07tNCZ3kaVgN7him 4 | 35DfZOHzK9Xs04KolEttSFm4/goc1m/yvFIqD7d5pNgBdYPOjz6DSTBPrU6O+5PF 5 | 5L3qnFovwoh/CC+1jmEcnXFwRDYnDuE= 6 | -----END EC PRIVATE KEY----- 7 | -------------------------------------------------------------------------------- /tests/data/soap-failure.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | s:Client 5 | UPnPError 6 | 7 | 8 | 402 9 | Invalid Args 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/fixture.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "model/device.h" 7 | #include "model/cluster.h" 8 | #include "net/controller_actor.h" 9 | #include "fs/file_actor.h" 10 | #include "sample_peer.h" 11 | #include "test_supervisor.h" 12 | 13 | namespace syncspirit::test { 14 | 15 | namespace bfs = std::filesystem; 16 | namespace payload = syncspirit::net::payload; 17 | 18 | struct Fixture { 19 | model::device_ptr_t device_my; 20 | model::device_ptr_t device_peer; 21 | model::cluster_ptr_t cluster; 22 | model::ignored_folders_map_t ignored_folders; 23 | r::intrusive_ptr_t peer; 24 | r::intrusive_ptr_t sup; 25 | r::intrusive_ptr_t controller; 26 | payload::cluster_config_ptr_t peer_cluster_config; 27 | bfs::path root_path; 28 | 29 | Fixture(); 30 | virtual void setup(); 31 | virtual void pre_run(); 32 | virtual void main(); 33 | void create_controller(); 34 | 35 | void run(); 36 | uint64_t seq = 1; 37 | }; 38 | 39 | }; // namespace syncspirit::test 40 | -------------------------------------------------------------------------------- /tests/test-db.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou 3 | 4 | #include "test-db.h" 5 | #include "test-utils.h" 6 | 7 | namespace syncspirit::test { 8 | 9 | env_t::~env_t() { 10 | if (env) { 11 | mdbx_env_close(env); 12 | } 13 | // std::cout << path.c_str() << "\n"; 14 | bfs::remove_all(path); 15 | } 16 | 17 | env_t mk_env() { 18 | auto path = unique_path(); 19 | MDBX_env *env; 20 | auto r = mdbx_env_create(&env); 21 | assert(r == MDBX_SUCCESS); 22 | (void)r; 23 | MDBX_env_flags_t flags = 24 | MDBX_EXCLUSIVE | MDBX_SAFE_NOSYNC | MDBX_WRITEMAP | MDBX_NOSTICKYTHREADS | MDBX_LIFORECLAIM; 25 | r = mdbx_env_open(env, path.string().c_str(), flags, 0664); 26 | assert(r == MDBX_SUCCESS); 27 | // std::cout << path.c_str() << "\n"; 28 | return env_t{env, std::move(path)}; 29 | } 30 | 31 | db::transaction_t mk_txn(env_t &env, db::transaction_type_t type) { 32 | auto r = db::make_transaction(type, env.env); 33 | assert((bool)r); 34 | return std::move(r.value()); 35 | } 36 | 37 | } // namespace syncspirit::test 38 | -------------------------------------------------------------------------------- /tests/test-db.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // SPDX-FileCopyrightText: 2019-2022 Ivan Baidakou 3 | 4 | #pragma once 5 | 6 | #include "db/utils.h" 7 | #include 8 | 9 | namespace syncspirit::test { 10 | 11 | namespace bfs = std::filesystem; 12 | namespace db = syncspirit::db; 13 | 14 | struct env_t { 15 | MDBX_env *env; 16 | bfs::path path; 17 | ~env_t(); 18 | }; 19 | 20 | env_t mk_env(); 21 | 22 | db::transaction_t mk_txn(env_t &env, db::transaction_type_t type); 23 | 24 | } // namespace syncspirit::test 25 | --------------------------------------------------------------------------------